From 0fc8913c542d6ba129ca8bede1505e7d2e8b4b4b Mon Sep 17 00:00:00 2001 From: shawns-valve Date: Tue, 20 Aug 2024 19:58:27 -0700 Subject: [PATCH] HL25 SDK Update --- README.md | 20 +- cl_dll/ammo.cpp | 65 +- cl_dll/ammo_secondary.cpp | 2 +- cl_dll/ammohistory.cpp | 8 +- cl_dll/battery.cpp | 9 +- cl_dll/cl_util.h | 3 +- cl_dll/death.cpp | 19 +- cl_dll/ev_hldm.cpp | 43 +- cl_dll/geiger.cpp | 8 +- cl_dll/health.cpp | 17 +- cl_dll/hl/hl_baseentity.cpp | 7 +- cl_dll/hl/hl_weapons.cpp | 4 +- cl_dll/hud.cpp | 24 +- cl_dll/hud.h | 1 + cl_dll/hud_bench.cpp | 12 +- cl_dll/hud_msg.cpp | 7 + cl_dll/hud_redraw.cpp | 6 +- cl_dll/hud_spectator.cpp | 7 +- cl_dll/inputw32.cpp | 141 +- cl_dll/menu.cpp | 10 +- cl_dll/meson.build | 175 + cl_dll/message.cpp | 21 +- cl_dll/text_message.cpp | 5 +- cl_dll/util.cpp | 14 +- cl_dll/vgui_TeamFortressViewport.cpp | 10 +- cl_dll/view.cpp | 20 +- common/const.h | 1 + common/cvardef.h | 4 + common/mathlib.h | 2 +- common/netadr.h | 11 +- common/qfont.h | 4 +- create_vs_projects.bat | 75 + devtools/image_to_background.py | 86 + devtools/meson/COPYING | 202 + devtools/meson/MANIFEST.in | 19 + devtools/meson/PKG-INFO | 33 + devtools/meson/README.md | 104 + devtools/meson/contributing.md | 8 + devtools/meson/cross/arm64cl.txt | 18 + devtools/meson/cross/armcc.txt | 20 + devtools/meson/cross/armclang-linux.txt | 31 + devtools/meson/cross/armclang.txt | 20 + devtools/meson/cross/c2000.txt | 28 + devtools/meson/cross/ccomp-armv7a.txt | 13 + devtools/meson/cross/ccrx.txt | 22 + devtools/meson/cross/iphone.txt | 32 + .../meson/cross/linux-mingw-w64-32bit.json | 7 + .../meson/cross/linux-mingw-w64-32bit.txt | 31 + .../meson/cross/linux-mingw-w64-64bit.json | 7 + .../meson/cross/linux-mingw-w64-64bit.txt | 30 + devtools/meson/cross/metrowerks-arm.txt | 28 + devtools/meson/cross/metrowerks-eppc.txt | 28 + devtools/meson/cross/metrowerks.lcf | 18 + devtools/meson/cross/msp430.txt | 25 + devtools/meson/cross/none.txt | 19 + devtools/meson/cross/ownstdlib.txt | 13 + devtools/meson/cross/tvos.txt | 29 + devtools/meson/cross/ubuntu-armhf.json | 5 + devtools/meson/cross/ubuntu-armhf.txt | 29 + devtools/meson/cross/ubuntu-faketarget.txt | 13 + devtools/meson/cross/wasm.txt | 17 + devtools/meson/cross/xc16.txt | 26 + devtools/meson/data/.coveragerc.in | 25 + .../meson/data/com.mesonbuild.install.policy | 22 + devtools/meson/data/macros.meson | 45 + devtools/meson/data/schema.xsd | 96 + .../meson/data/shell-completions/bash/meson | 492 + .../meson/data/shell-completions/zsh/_meson | 425 + .../meson/data/syntax-highlighting/vim/README | 4 + .../vim/ftdetect/meson.vim | 4 + .../vim/ftplugin/meson.vim | 39 + .../syntax-highlighting/vim/indent/meson.vim | 183 + .../syntax-highlighting/vim/syntax/meson.vim | 162 + devtools/meson/data/test.schema.json | 180 + devtools/meson/graphics/meson_logo.svg | 340 + devtools/meson/graphics/meson_logo_big.png | Bin 0 -> 21889 bytes devtools/meson/graphics/wrap_logo.svg | 70 + devtools/meson/man/meson.1 | 238 + devtools/meson/manual tests/1 wrap/main.c | 12 + .../meson/manual tests/1 wrap/meson.build | 13 + .../1 wrap/subprojects/sqlite.wrap | 10 + .../manual tests/10 svn wrap/meson.build | 10 + .../meson/manual tests/10 svn wrap/prog.c | 6 + .../subprojects/samplesubproject.wrap | 4 + .../manual tests/11 wrap imposter/meson.build | 8 + .../11 wrap imposter/subprojects/zlib.wrap | 10 + .../manual tests/12 wrap mirror/meson.build | 4 + .../12 wrap mirror/subprojects/zlib.wrap | 10 + .../13 builddir upgrade/data/foo.dat | 0 .../manual tests/13 builddir upgrade/foo.1 | 0 .../manual tests/13 builddir upgrade/foo.c | 6 + .../manual tests/13 builddir upgrade/lib.c | 9 + .../13 builddir upgrade/meson.build | 21 + .../manual tests/13 builddir upgrade/mod.py | 1 + .../manual tests/2 multiwrap/meson.build | 12 + .../meson/manual tests/2 multiwrap/prog.c | 66 + .../2 multiwrap/subprojects/libpng.wrap | 10 + .../2 multiwrap/subprojects/lua.wrap | 11 + .../2 multiwrap/subprojects/zlib.wrap | 10 + .../meson/manual tests/3 git wrap/meson.build | 10 + devtools/meson/manual tests/3 git wrap/prog.c | 6 + .../subprojects/samplesubproject.wrap | 4 + .../4 standalone binaries/Info.plist | 26 + .../build_linux_package.sh | 12 + .../build_osx_package.sh | 20 + .../build_windows_package.py | 32 + .../4 standalone binaries/linux_bundler.sh | 7 + .../4 standalone binaries/meson.build | 38 + .../4 standalone binaries/myapp.cpp | 39 + .../4 standalone binaries/myapp.icns | Bin 0 -> 1831 bytes .../4 standalone binaries/myapp.iss | 18 + .../4 standalone binaries/myapp.sh | 10 + .../4 standalone binaries/osx_bundler.sh | 6 + .../4 standalone binaries/readme.txt | 11 + .../4 standalone binaries/template.dmg.gz | Bin 0 -> 37311 bytes devtools/meson/manual tests/5 rpm/lib.c | 6 + devtools/meson/manual tests/5 rpm/lib.h | 1 + devtools/meson/manual tests/5 rpm/main.c | 8 + devtools/meson/manual tests/5 rpm/meson.build | 14 + .../meson/manual tests/6 hg wrap/meson.build | 10 + devtools/meson/manual tests/6 hg wrap/prog.c | 6 + .../subprojects/samplesubproject.wrap | 4 + .../7 vala composite widgets/meson.build | 21 + .../7 vala composite widgets/my-resources.xml | 6 + .../7 vala composite widgets/mywidget.ui | 70 + .../7 vala composite widgets/mywidget.vala | 41 + .../meson/manual tests/8 timeout/meson.build | 8 + .../meson/manual tests/8 timeout/sleepprog.c | 6 + devtools/meson/meson.egg-info/PKG-INFO | 33 + devtools/meson/meson.egg-info/SOURCES.txt | 4226 +++++ .../meson/meson.egg-info/dependency_links.txt | 1 + .../meson/meson.egg-info/entry_points.txt | 2 + devtools/meson/meson.egg-info/requires.txt | 12 + devtools/meson/meson.egg-info/top_level.txt | 1 + devtools/meson/meson.py | 40 + devtools/meson/mesonbuild/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 151 bytes .../__pycache__/_pathlib.cpython-37.pyc | Bin 0 -> 1792 bytes .../__pycache__/arglist.cpython-37.pyc | Bin 0 -> 10223 bytes .../__pycache__/build.cpython-37.pyc | Bin 0 -> 108170 bytes .../__pycache__/coredata.cpython-37.pyc | Bin 0 -> 48191 bytes .../__pycache__/depfile.cpython-37.pyc | Bin 0 -> 1955 bytes .../__pycache__/envconfig.cpython-37.pyc | Bin 0 -> 13903 bytes .../__pycache__/environment.cpython-37.pyc | Bin 0 -> 26132 bytes .../__pycache__/mcompile.cpython-37.pyc | Bin 0 -> 9919 bytes .../__pycache__/mconf.cpython-37.pyc | Bin 0 -> 12265 bytes .../__pycache__/mdevenv.cpython-37.pyc | Bin 0 -> 8196 bytes .../__pycache__/mdist.cpython-37.pyc | Bin 0 -> 13136 bytes .../__pycache__/mesonlib.cpython-37.pyc | Bin 0 -> 410 bytes .../__pycache__/mesonmain.cpython-37.pyc | Bin 0 -> 8997 bytes .../__pycache__/minit.cpython-37.pyc | Bin 0 -> 6595 bytes .../__pycache__/minstall.cpython-37.pyc | Bin 0 -> 28758 bytes .../__pycache__/mintro.cpython-37.pyc | Bin 0 -> 26560 bytes .../__pycache__/mlog.cpython-37.pyc | Bin 0 -> 17577 bytes .../__pycache__/mparser.cpython-37.pyc | Bin 0 -> 30887 bytes .../__pycache__/msetup.cpython-37.pyc | Bin 0 -> 11995 bytes .../__pycache__/msubprojects.cpython-37.pyc | Bin 0 -> 23708 bytes .../__pycache__/mtest.cpython-37.pyc | Bin 0 -> 67875 bytes .../munstable_coredata.cpython-37.pyc | Bin 0 -> 3561 bytes .../__pycache__/optinterpreter.cpython-37.pyc | Bin 0 -> 9918 bytes .../__pycache__/programs.cpython-37.pyc | Bin 0 -> 10494 bytes .../__pycache__/rewriter.cpython-37.pyc | Bin 0 -> 34123 bytes devtools/meson/mesonbuild/_pathlib.py | 73 + devtools/meson/mesonbuild/_typing.py | 81 + devtools/meson/mesonbuild/arglist.py | 331 + devtools/meson/mesonbuild/ast/__init__.py | 34 + .../ast/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 615 bytes .../__pycache__/interpreter.cpython-37.pyc | Bin 0 -> 13767 bytes .../__pycache__/introspection.cpython-37.pyc | Bin 0 -> 12747 bytes .../__pycache__/postprocess.cpython-37.pyc | Bin 0 -> 4683 bytes .../ast/__pycache__/printer.cpython-37.pyc | Bin 0 -> 16493 bytes .../ast/__pycache__/visitor.cpython-37.pyc | Bin 0 -> 6486 bytes devtools/meson/mesonbuild/ast/interpreter.py | 452 + .../meson/mesonbuild/ast/introspection.py | 383 + devtools/meson/mesonbuild/ast/postprocess.py | 120 + devtools/meson/mesonbuild/ast/printer.py | 399 + devtools/meson/mesonbuild/ast/visitor.py | 146 + devtools/meson/mesonbuild/backend/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 159 bytes .../__pycache__/backends.cpython-37.pyc | Bin 0 -> 60988 bytes .../__pycache__/vs2010backend.cpython-37.pyc | Bin 0 -> 55325 bytes .../__pycache__/vs2019backend.cpython-37.pyc | Bin 0 -> 2658 bytes devtools/meson/mesonbuild/backend/backends.py | 2030 +++ .../meson/mesonbuild/backend/ninjabackend.py | 3854 +++++ .../meson/mesonbuild/backend/nonebackend.py | 39 + .../meson/mesonbuild/backend/vs2010backend.py | 2121 +++ .../meson/mesonbuild/backend/vs2012backend.py | 45 + .../meson/mesonbuild/backend/vs2013backend.py | 44 + .../meson/mesonbuild/backend/vs2015backend.py | 45 + .../meson/mesonbuild/backend/vs2017backend.py | 69 + .../meson/mesonbuild/backend/vs2019backend.py | 64 + .../meson/mesonbuild/backend/vs2022backend.py | 64 + .../meson/mesonbuild/backend/xcodebackend.py | 1718 ++ devtools/meson/mesonbuild/build.py | 3129 ++++ devtools/meson/mesonbuild/cargo/__init__.py | 0 devtools/meson/mesonbuild/cargo/builder.py | 284 + devtools/meson/mesonbuild/cargo/cfg.py | 276 + .../meson/mesonbuild/cargo/interpreter.py | 451 + devtools/meson/mesonbuild/cargo/manifest.py | 227 + devtools/meson/mesonbuild/cargo/version.py | 96 + devtools/meson/mesonbuild/cmake/__init__.py | 39 + devtools/meson/mesonbuild/cmake/common.py | 344 + .../meson/mesonbuild/cmake/data/__init__.py | 0 .../meson/mesonbuild/cmake/data/preload.cmake | 82 + devtools/meson/mesonbuild/cmake/executor.py | 254 + devtools/meson/mesonbuild/cmake/fileapi.py | 321 + devtools/meson/mesonbuild/cmake/generator.py | 196 + .../meson/mesonbuild/cmake/interpreter.py | 1266 ++ devtools/meson/mesonbuild/cmake/toolchain.py | 258 + .../meson/mesonbuild/cmake/traceparser.py | 825 + .../meson/mesonbuild/cmake/tracetargets.py | 119 + .../meson/mesonbuild/compilers/__init__.py | 97 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 1492 bytes .../compilers/__pycache__/c.cpython-37.pyc | Bin 0 -> 33888 bytes .../c_function_attributes.cpython-37.pyc | Bin 0 -> 4288 bytes .../__pycache__/compilers.cpython-37.pyc | Bin 0 -> 50605 bytes .../compilers/__pycache__/cpp.cpython-37.pyc | Bin 0 -> 36088 bytes .../compilers/__pycache__/d.cpython-37.pyc | Bin 0 -> 30152 bytes .../__pycache__/detect.cpython-37.pyc | Bin 0 -> 33630 bytes devtools/meson/mesonbuild/compilers/asm.py | 330 + devtools/meson/mesonbuild/compilers/c.py | 799 + .../compilers/c_function_attributes.py | 143 + .../meson/mesonbuild/compilers/compilers.py | 1390 ++ devtools/meson/mesonbuild/compilers/cpp.py | 964 ++ devtools/meson/mesonbuild/compilers/cs.py | 154 + devtools/meson/mesonbuild/compilers/cuda.py | 791 + devtools/meson/mesonbuild/compilers/cython.py | 96 + devtools/meson/mesonbuild/compilers/d.py | 1028 ++ devtools/meson/mesonbuild/compilers/detect.py | 1381 ++ .../meson/mesonbuild/compilers/fortran.py | 546 + devtools/meson/mesonbuild/compilers/java.py | 125 + .../mesonbuild/compilers/mixins/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 168 bytes .../mixins/__pycache__/arm.cpython-37.pyc | Bin 0 -> 6400 bytes .../mixins/__pycache__/ccrx.cpython-37.pyc | Bin 0 -> 3890 bytes .../mixins/__pycache__/clang.cpython-37.pyc | Bin 0 -> 6017 bytes .../mixins/__pycache__/clike.cpython-37.pyc | Bin 0 -> 41868 bytes .../__pycache__/compcert.cpython-37.pyc | Bin 0 -> 4273 bytes .../mixins/__pycache__/elbrus.cpython-37.pyc | Bin 0 -> 4297 bytes .../__pycache__/emscripten.cpython-37.pyc | Bin 0 -> 3213 bytes .../mixins/__pycache__/gnu.cpython-37.pyc | Bin 0 -> 17804 bytes .../mixins/__pycache__/intel.cpython-37.pyc | Bin 0 -> 5719 bytes .../__pycache__/metrowerks.cpython-37.pyc | Bin 0 -> 8650 bytes .../mixins/__pycache__/pgi.cpython-37.pyc | Bin 0 -> 3641 bytes .../mixins/__pycache__/ti.cpython-37.pyc | Bin 0 -> 4899 bytes .../__pycache__/visualstudio.cpython-37.pyc | Bin 0 -> 16344 bytes .../mixins/__pycache__/xc16.cpython-37.pyc | Bin 0 -> 3896 bytes .../meson/mesonbuild/compilers/mixins/arm.py | 201 + .../meson/mesonbuild/compilers/mixins/ccrx.py | 134 + .../mesonbuild/compilers/mixins/clang.py | 180 + .../mesonbuild/compilers/mixins/clike.py | 1356 ++ .../mesonbuild/compilers/mixins/compcert.py | 138 + .../mesonbuild/compilers/mixins/elbrus.py | 101 + .../mesonbuild/compilers/mixins/emscripten.py | 101 + .../meson/mesonbuild/compilers/mixins/gnu.py | 653 + .../mesonbuild/compilers/mixins/intel.py | 185 + .../mesonbuild/compilers/mixins/islinker.py | 130 + .../mesonbuild/compilers/mixins/metrowerks.py | 300 + .../meson/mesonbuild/compilers/mixins/pgi.py | 113 + .../meson/mesonbuild/compilers/mixins/ti.py | 151 + .../compilers/mixins/visualstudio.py | 503 + .../meson/mesonbuild/compilers/mixins/xc16.py | 133 + devtools/meson/mesonbuild/compilers/objc.py | 114 + devtools/meson/mesonbuild/compilers/objcpp.py | 115 + devtools/meson/mesonbuild/compilers/rust.py | 230 + devtools/meson/mesonbuild/compilers/swift.py | 130 + devtools/meson/mesonbuild/compilers/vala.py | 140 + devtools/meson/mesonbuild/coredata.py | 1343 ++ .../meson/mesonbuild/dependencies/__init__.py | 261 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 1401 bytes .../__pycache__/base.cpython-37.pyc | Bin 0 -> 26036 bytes .../__pycache__/detect.cpython-37.pyc | Bin 0 -> 6074 bytes .../meson/mesonbuild/dependencies/base.py | 656 + .../meson/mesonbuild/dependencies/boost.py | 1092 ++ .../meson/mesonbuild/dependencies/cmake.py | 670 + .../meson/mesonbuild/dependencies/coarrays.py | 89 + .../mesonbuild/dependencies/configtool.py | 187 + .../meson/mesonbuild/dependencies/cuda.py | 305 + .../dependencies/data/CMakeLists.txt | 102 + .../dependencies/data/CMakeListsLLVM.txt | 204 + .../dependencies/data/CMakePathInfo.txt | 31 + .../mesonbuild/dependencies/data/__init__.py | 0 .../meson/mesonbuild/dependencies/detect.py | 235 + devtools/meson/mesonbuild/dependencies/dev.py | 720 + devtools/meson/mesonbuild/dependencies/dub.py | 434 + .../meson/mesonbuild/dependencies/factory.py | 156 + .../mesonbuild/dependencies/framework.py | 121 + .../meson/mesonbuild/dependencies/hdf5.py | 183 + .../meson/mesonbuild/dependencies/misc.py | 619 + devtools/meson/mesonbuild/dependencies/mpi.py | 240 + .../mesonbuild/dependencies/pkgconfig.py | 500 + .../meson/mesonbuild/dependencies/platform.py | 63 + .../meson/mesonbuild/dependencies/python.py | 417 + devtools/meson/mesonbuild/dependencies/qt.py | 490 + .../mesonbuild/dependencies/scalapack.py | 159 + devtools/meson/mesonbuild/dependencies/ui.py | 268 + devtools/meson/mesonbuild/depfile.py | 91 + devtools/meson/mesonbuild/envconfig.py | 475 + devtools/meson/mesonbuild/environment.py | 923 ++ .../meson/mesonbuild/interpreter/__init__.py | 59 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 1033 bytes .../__pycache__/compiler.cpython-37.pyc | Bin 0 -> 29729 bytes .../dependencyfallbacks.cpython-37.pyc | Bin 0 -> 11883 bytes .../__pycache__/interpreter.cpython-37.pyc | Bin 0 -> 109747 bytes .../interpreterobjects.cpython-37.pyc | Bin 0 -> 44455 bytes .../__pycache__/mesonmain.cpython-37.pyc | Bin 0 -> 18000 bytes .../__pycache__/type_checking.cpython-37.pyc | Bin 0 -> 15728 bytes .../meson/mesonbuild/interpreter/compiler.py | 805 + .../interpreter/dependencyfallbacks.py | 374 + .../mesonbuild/interpreter/interpreter.py | 3408 ++++ .../interpreter/interpreterobjects.py | 1054 ++ .../meson/mesonbuild/interpreter/kwargs.py | 310 + .../meson/mesonbuild/interpreter/mesonmain.py | 477 + .../interpreter/primitives/__init__.py | 29 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 741 bytes .../__pycache__/array.cpython-37.pyc | Bin 0 -> 4245 bytes .../__pycache__/boolean.cpython-37.pyc | Bin 0 -> 2645 bytes .../__pycache__/dict.cpython-37.pyc | Bin 0 -> 3530 bytes .../__pycache__/integer.cpython-37.pyc | Bin 0 -> 3984 bytes .../__pycache__/range.cpython-37.pyc | Bin 0 -> 1640 bytes .../__pycache__/string.cpython-37.pyc | Bin 0 -> 10008 bytes .../interpreter/primitives/array.py | 108 + .../interpreter/primitives/boolean.py | 52 + .../mesonbuild/interpreter/primitives/dict.py | 88 + .../interpreter/primitives/integer.py | 83 + .../interpreter/primitives/range.py | 38 + .../interpreter/primitives/string.py | 244 + .../mesonbuild/interpreter/type_checking.py | 481 + .../mesonbuild/interpreterbase/__init__.py | 139 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 2133 bytes .../__pycache__/_unholder.cpython-37.pyc | Bin 0 -> 1089 bytes .../__pycache__/baseobjects.cpython-37.pyc | Bin 0 -> 7658 bytes .../__pycache__/decorators.cpython-37.pyc | Bin 0 -> 34205 bytes .../__pycache__/disabler.cpython-37.pyc | Bin 0 -> 1265 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 0 -> 1087 bytes .../__pycache__/helpers.cpython-37.pyc | Bin 0 -> 2424 bytes .../interpreterbase.cpython-37.pyc | Bin 0 -> 22747 bytes .../__pycache__/operator.cpython-37.pyc | Bin 0 -> 664 bytes .../mesonbuild/interpreterbase/_unholder.py | 35 + .../mesonbuild/interpreterbase/baseobjects.py | 187 + .../mesonbuild/interpreterbase/decorators.py | 833 + .../mesonbuild/interpreterbase/disabler.py | 45 + .../mesonbuild/interpreterbase/exceptions.py | 33 + .../mesonbuild/interpreterbase/helpers.py | 56 + .../interpreterbase/interpreterbase.py | 666 + .../mesonbuild/interpreterbase/operator.py | 32 + devtools/meson/mesonbuild/linkers/__init__.py | 32 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 375 bytes .../linkers/__pycache__/base.cpython-37.pyc | Bin 0 -> 1452 bytes .../linkers/__pycache__/detect.cpython-37.pyc | Bin 0 -> 6015 bytes .../__pycache__/linkers.cpython-37.pyc | Bin 0 -> 68271 bytes devtools/meson/mesonbuild/linkers/base.py | 50 + devtools/meson/mesonbuild/linkers/detect.py | 234 + devtools/meson/mesonbuild/linkers/linkers.py | 1621 ++ devtools/meson/mesonbuild/mcompile.py | 359 + devtools/meson/mesonbuild/mconf.py | 336 + devtools/meson/mesonbuild/mdevenv.py | 231 + devtools/meson/mesonbuild/mdist.py | 383 + devtools/meson/mesonbuild/mesondata.py | 48 + devtools/meson/mesonbuild/mesonlib.py | 35 + devtools/meson/mesonbuild/mesonmain.py | 297 + devtools/meson/mesonbuild/minit.py | 199 + devtools/meson/mesonbuild/minstall.py | 864 + devtools/meson/mesonbuild/mintro.py | 672 + devtools/meson/mesonbuild/mlog.py | 547 + devtools/meson/mesonbuild/modules/__init__.py | 279 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 10701 bytes devtools/meson/mesonbuild/modules/cmake.py | 450 + devtools/meson/mesonbuild/modules/cuda.py | 390 + devtools/meson/mesonbuild/modules/dlang.py | 137 + .../mesonbuild/modules/external_project.py | 313 + devtools/meson/mesonbuild/modules/fs.py | 317 + devtools/meson/mesonbuild/modules/gnome.py | 2187 +++ devtools/meson/mesonbuild/modules/hotdoc.py | 471 + devtools/meson/mesonbuild/modules/i18n.py | 399 + devtools/meson/mesonbuild/modules/icestorm.py | 131 + devtools/meson/mesonbuild/modules/java.py | 117 + devtools/meson/mesonbuild/modules/keyval.py | 75 + devtools/meson/mesonbuild/modules/modtest.py | 44 + .../meson/mesonbuild/modules/pkgconfig.py | 748 + devtools/meson/mesonbuild/modules/python.py | 487 + devtools/meson/mesonbuild/modules/python3.py | 85 + devtools/meson/mesonbuild/modules/qt.py | 611 + devtools/meson/mesonbuild/modules/qt4.py | 34 + devtools/meson/mesonbuild/modules/qt5.py | 34 + devtools/meson/mesonbuild/modules/qt6.py | 33 + devtools/meson/mesonbuild/modules/rust.py | 278 + devtools/meson/mesonbuild/modules/simd.py | 88 + .../meson/mesonbuild/modules/sourceset.py | 307 + devtools/meson/mesonbuild/modules/wayland.py | 160 + devtools/meson/mesonbuild/modules/windows.py | 214 + devtools/meson/mesonbuild/mparser.py | 954 ++ devtools/meson/mesonbuild/msetup.py | 360 + devtools/meson/mesonbuild/msubprojects.py | 736 + devtools/meson/mesonbuild/mtest.py | 2195 +++ .../meson/mesonbuild/munstable_coredata.py | 115 + devtools/meson/mesonbuild/optinterpreter.py | 279 + devtools/meson/mesonbuild/programs.py | 378 + devtools/meson/mesonbuild/rewriter.py | 1070 ++ devtools/meson/mesonbuild/scripts/__init__.py | 21 + .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 401 bytes .../__pycache__/depfixer.cpython-37.pyc | Bin 0 -> 13672 bytes .../__pycache__/env2mfile.cpython-37.pyc | Bin 0 -> 11603 bytes .../__pycache__/meson_exe.cpython-37.pyc | Bin 0 -> 3402 bytes .../__pycache__/regen_checker.cpython-37.pyc | Bin 0 -> 1873 bytes .../meson/mesonbuild/scripts/clangformat.py | 65 + .../meson/mesonbuild/scripts/clangtidy.py | 35 + .../meson/mesonbuild/scripts/cleantrees.py | 45 + .../mesonbuild/scripts/cmake_run_ctgt.py | 103 + .../meson/mesonbuild/scripts/cmd_or_ps.ps1 | 17 + devtools/meson/mesonbuild/scripts/copy.py | 19 + devtools/meson/mesonbuild/scripts/coverage.py | 202 + .../meson/mesonbuild/scripts/delwithsuffix.py | 37 + devtools/meson/mesonbuild/scripts/depfixer.py | 505 + devtools/meson/mesonbuild/scripts/depscan.py | 208 + .../meson/mesonbuild/scripts/dirchanger.py | 30 + .../meson/mesonbuild/scripts/env2mfile.py | 402 + .../mesonbuild/scripts/externalproject.py | 116 + devtools/meson/mesonbuild/scripts/gettext.py | 96 + .../meson/mesonbuild/scripts/gtkdochelper.py | 296 + .../meson/mesonbuild/scripts/hotdochelper.py | 40 + devtools/meson/mesonbuild/scripts/itstool.py | 86 + .../meson/mesonbuild/scripts/meson_exe.py | 125 + .../meson/mesonbuild/scripts/msgfmthelper.py | 39 + .../meson/mesonbuild/scripts/pycompile.py | 65 + .../meson/mesonbuild/scripts/python_info.py | 79 + .../meson/mesonbuild/scripts/regen_checker.py | 65 + devtools/meson/mesonbuild/scripts/run_tool.py | 68 + .../meson/mesonbuild/scripts/scanbuild.py | 66 + .../mesonbuild/scripts/symbolextractor.py | 333 + devtools/meson/mesonbuild/scripts/tags.py | 54 + .../mesonbuild/scripts/test_loaded_modules.py | 11 + .../meson/mesonbuild/scripts/uninstall.py | 51 + .../meson/mesonbuild/scripts/vcstagger.py | 45 + devtools/meson/mesonbuild/scripts/yasm.py | 22 + .../meson/mesonbuild/templates/__init__.py | 0 .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 161 bytes .../__pycache__/cpptemplates.cpython-37.pyc | Bin 0 -> 4525 bytes .../__pycache__/cstemplates.cpython-37.pyc | Bin 0 -> 3614 bytes .../__pycache__/ctemplates.cpython-37.pyc | Bin 0 -> 4301 bytes .../__pycache__/cudatemplates.cpython-37.pyc | Bin 0 -> 4531 bytes .../__pycache__/dlangtemplates.cpython-37.pyc | Bin 0 -> 3797 bytes .../fortrantemplates.cpython-37.pyc | Bin 0 -> 3645 bytes .../__pycache__/javatemplates.cpython-37.pyc | Bin 0 -> 3654 bytes .../__pycache__/mesontemplates.cpython-37.pyc | Bin 0 -> 2260 bytes .../objcpptemplates.cpython-37.pyc | Bin 0 -> 4431 bytes .../__pycache__/objctemplates.cpython-37.pyc | Bin 0 -> 4342 bytes .../__pycache__/rusttemplates.cpython-37.pyc | Bin 0 -> 3105 bytes .../__pycache__/samplefactory.cpython-37.pyc | Bin 0 -> 1416 bytes .../__pycache__/sampleimpl.cpython-37.pyc | Bin 0 -> 800 bytes .../__pycache__/valatemplates.cpython-37.pyc | Bin 0 -> 3392 bytes .../mesonbuild/templates/cpptemplates.py | 187 + .../meson/mesonbuild/templates/cstemplates.py | 136 + .../meson/mesonbuild/templates/ctemplates.py | 168 + .../mesonbuild/templates/cudatemplates.py | 187 + .../mesonbuild/templates/dlangtemplates.py | 145 + .../mesonbuild/templates/fortrantemplates.py | 142 + .../mesonbuild/templates/javatemplates.py | 138 + .../mesonbuild/templates/mesontemplates.py | 77 + .../mesonbuild/templates/objcpptemplates.py | 168 + .../mesonbuild/templates/objctemplates.py | 168 + .../mesonbuild/templates/rusttemplates.py | 115 + .../mesonbuild/templates/samplefactory.py | 44 + .../meson/mesonbuild/templates/sampleimpl.py | 22 + .../mesonbuild/templates/valatemplates.py | 125 + devtools/meson/mesonbuild/utils/__init__.py | 0 .../utils/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 157 bytes .../utils/__pycache__/core.cpython-37.pyc | Bin 0 -> 6929 bytes .../utils/__pycache__/platform.cpython-37.pyc | Bin 0 -> 1024 bytes .../__pycache__/universal.cpython-37.pyc | Bin 0 -> 72554 bytes .../utils/__pycache__/vsenv.cpython-37.pyc | Bin 0 -> 2799 bytes .../utils/__pycache__/win32.cpython-37.pyc | Bin 0 -> 1184 bytes devtools/meson/mesonbuild/utils/core.py | 161 + devtools/meson/mesonbuild/utils/platform.py | 38 + devtools/meson/mesonbuild/utils/posix.py | 43 + devtools/meson/mesonbuild/utils/universal.py | 2430 +++ devtools/meson/mesonbuild/utils/vsenv.py | 125 + devtools/meson/mesonbuild/utils/win32.py | 40 + devtools/meson/mesonbuild/wrap/__init__.py | 59 + .../wrap/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 880 bytes .../wrap/__pycache__/wrap.cpython-37.pyc | Bin 0 -> 26773 bytes .../wrap/__pycache__/wraptool.cpython-37.pyc | Bin 0 -> 7601 bytes devtools/meson/mesonbuild/wrap/wrap.py | 836 + devtools/meson/mesonbuild/wrap/wraptool.py | 231 + devtools/meson/packaging/License.rtf | 73 + devtools/meson/packaging/create_zipapp.py | 23 + devtools/meson/packaging/createmsi.py | 344 + devtools/meson/packaging/createpkg.py | 123 + devtools/meson/packaging/hook-mesonbuild.py | 60 + .../macpages/English.lproj/conclusion.html | 24 + .../macpages/English.lproj/license.html | 209 + .../macpages/English.lproj/welcome.html | 12 + devtools/meson/pyproject.toml | 3 + devtools/meson/run_cross_test.py | 63 + devtools/meson/run_meson_command_tests.py | 230 + devtools/meson/run_project_tests.py | 1656 ++ devtools/meson/run_tests.py | 423 + devtools/meson/run_unittests.py | 161 + devtools/meson/setup.cfg | 69 + devtools/meson/setup.py | 31 + devtools/meson/tools/ac_converter.py | 453 + devtools/meson/tools/boost_names.py | 300 + devtools/meson/tools/build_website.py | 51 + devtools/meson/tools/cmake2meson.py | 330 + devtools/meson/tools/copy_files.py | 55 + devtools/meson/tools/dircondenser.py | 91 + devtools/meson/tools/regenerate_docs.py | 184 + devtools/meson/tools/run_with_cov.py | 53 + devtools/meson/unittests/__init__.py | 0 devtools/meson/unittests/allplatformstests.py | 4782 ++++++ devtools/meson/unittests/baseplatformtests.py | 497 + devtools/meson/unittests/cargotests.py | 186 + devtools/meson/unittests/darwintests.py | 155 + devtools/meson/unittests/datatests.py | 248 + devtools/meson/unittests/failuretests.py | 394 + devtools/meson/unittests/helpers.py | 214 + devtools/meson/unittests/internaltests.py | 1713 ++ devtools/meson/unittests/linuxcrosstests.py | 192 + devtools/meson/unittests/linuxliketests.py | 1852 +++ devtools/meson/unittests/machinefiletests.py | 978 ++ .../meson/unittests/platformagnostictests.py | 263 + devtools/meson/unittests/pythontests.py | 99 + devtools/meson/unittests/rewritetests.py | 398 + .../unittests/subprojectscommandtests.py | 311 + devtools/meson/unittests/taptests.py | 294 + devtools/meson/unittests/windowstests.py | 490 + devtools/meson_set_outdir.bat | 11 + devtools/vs_add_build_steps.py | 149 + devtools/vs_add_launch_config.py | 46 + dlls/aflock.cpp | 1 + dlls/agrunt.cpp | 2 +- dlls/airtank.cpp | 2 +- dlls/apache.cpp | 2 +- dlls/barnacle.cpp | 2 +- dlls/barney.cpp | 2 +- dlls/basemonster.h | 9 +- dlls/bigmomma.cpp | 2 +- dlls/bloater.cpp | 2 +- dlls/bullsquid.cpp | 2 +- dlls/cbase.h | 19 +- dlls/client.cpp | 30 +- dlls/controller.cpp | 2 +- dlls/crowbar.cpp | 15 +- dlls/effects.cpp | 2 +- dlls/egon.cpp | 31 +- dlls/explode.cpp | 2 +- dlls/extdll.h | 7 +- dlls/flyingmonster.cpp | 22 +- dlls/flyingmonster.h | 3 +- dlls/func_break.cpp | 36 +- dlls/game.cpp | 10 + dlls/game.h | 1 + dlls/gamerules.cpp | 9 +- dlls/gamerules.h | 29 + dlls/gargantua.cpp | 2 +- dlls/gauss.cpp | 17 +- dlls/genericmonster.cpp | 2 +- dlls/ggrenade.cpp | 4 +- dlls/glock.cpp | 8 +- dlls/gman.cpp | 2 +- dlls/h_cine.cpp | 2 +- dlls/h_cycler.cpp | 3 +- dlls/handgrenade.cpp | 9 +- dlls/hassassin.cpp | 6 +- dlls/headcrab.cpp | 2 +- dlls/hgrunt.cpp | 2 +- dlls/hornet.cpp | 2 +- dlls/hornetgun.cpp | 25 +- dlls/houndeye.cpp | 2 +- dlls/ichthyosaur.cpp | 48 +- dlls/islave.cpp | 2 +- dlls/items.cpp | 2 +- dlls/leech.cpp | 2 +- dlls/maprules.cpp | 2 +- dlls/meson.build | 183 + dlls/monstermaker.cpp | 2 +- dlls/monsters.cpp | 42 +- dlls/mortar.cpp | 2 +- dlls/mp5.cpp | 6 +- dlls/multiplay_gamerules.cpp | 419 +- dlls/nihilanth.cpp | 6 +- dlls/nodes.cpp | 2 +- dlls/observer.cpp | 2 +- dlls/osprey.cpp | 2 +- dlls/plats.cpp | 2 +- dlls/player.cpp | 288 +- dlls/player.h | 6 +- dlls/python.cpp | 4 +- dlls/rat.cpp | 2 +- dlls/roach.cpp | 2 +- dlls/rpg.cpp | 89 +- dlls/satchel.cpp | 61 +- dlls/scientist.cpp | 41 +- dlls/scripted.cpp | 61 +- dlls/shotgun.cpp | 25 +- dlls/singleplay_gamerules.cpp | 80 + dlls/squadmonster.cpp | 2 +- dlls/squeakgrenade.cpp | 57 +- dlls/subs.cpp | 25 + dlls/talkmonster.cpp | 8 +- dlls/talkmonster.h | 2 +- dlls/tempmonster.cpp | 2 +- dlls/tentacle.cpp | 2 +- dlls/trains.h | 78 + dlls/triggers.cpp | 16 +- dlls/tripmine.cpp | 4 +- dlls/turret.cpp | 2 +- dlls/util.cpp | 12 +- dlls/util.h | 4 +- dlls/vector.h | 16 + dlls/vehicle.cpp | 1100 ++ dlls/weapons.cpp | 28 +- dlls/weapons.h | 15 +- dlls/world.cpp | 4 +- dlls/wpn_shared/hl_wpn_glock.cpp | 8 +- dlls/zombie.cpp | 10 +- dmc/cl_dll/ammo.cpp | 29 +- dmc/cl_dll/ammo_secondary.cpp | 2 +- dmc/cl_dll/ammohistory.cpp | 6 +- dmc/cl_dll/cl_util.h | 3 +- dmc/cl_dll/death.cpp | 2 +- dmc/cl_dll/ev_hldm.cpp | 22 +- dmc/cl_dll/geiger.cpp | 8 +- dmc/cl_dll/health.cpp | 16 +- dmc/cl_dll/hud.cpp | 4 +- dmc/cl_dll/hud_redraw.cpp | 2 +- dmc/cl_dll/hud_spectator.cpp | 7 +- dmc/cl_dll/inputw32.cpp | 21 +- dmc/cl_dll/menu.cpp | 10 +- dmc/cl_dll/meson.build | 165 + dmc/cl_dll/message.cpp | 6 +- dmc/cl_dll/text_message.cpp | 5 +- dmc/cl_dll/vgui_viewport.cpp | 8 + dmc/cl_dll/view.cpp | 20 +- dmc/dlls/basemonster.h | 2 + dmc/dlls/cbase.h | 3 + dmc/dlls/client.cpp | 34 +- dmc/dlls/effects.cpp | 2 +- dmc/dlls/extdll.h | 10 +- dmc/dlls/func_break.cpp | 37 +- dmc/dlls/game.cpp | 4 + dmc/dlls/items.cpp | 2 +- dmc/dlls/maprules.cpp | 2 +- dmc/dlls/meson.build | 133 + dmc/dlls/multiplay_gamerules.cpp | 14 +- dmc/dlls/player.cpp | 12 +- dmc/dlls/threewave_gamerules.cpp | 40 +- dmc/dlls/triggers.cpp | 7 +- dmc/dlls/util.cpp | 12 +- dmc/dlls/util.h | 2 +- dmc/dlls/weapons.cpp | 2 +- dmc/dlls/world.cpp | 2 - dmc/meson.build | 2 + dmc/pm_shared/pm_shared.c | 13 +- engine/APIProxy.h | 4 + engine/cdll_int.h | 12 +- engine/eiface.h | 5 + external/SDL2/SDL.h | 201 +- external/SDL2/SDL_assert.h | 205 +- external/SDL2/SDL_atomic.h | 359 +- external/SDL2/SDL_audio.h | 1395 +- external/SDL2/SDL_bits.h | 58 +- external/SDL2/SDL_blendmode.h | 166 +- external/SDL2/SDL_clipboard.h | 47 +- external/SDL2/SDL_config.h.cmake | 445 + external/SDL2/SDL_config.h.in | 389 + external/SDL2/SDL_config_android.h | 185 +- external/SDL2/SDL_config_iphoneos.h | 193 +- external/SDL2/SDL_config_macosx.h | 190 +- external/SDL2/SDL_config_macosx.h.orig | 197 + external/SDL2/SDL_config_minimal.h | 312 +- external/SDL2/SDL_config_pandora.h | 18 +- external/SDL2/SDL_config_psp.h | 144 + external/SDL2/SDL_config_windows.h | 101 +- external/SDL2/SDL_config_winrt.h | 215 + external/SDL2/SDL_config_wiz.h | 18 +- external/SDL2/SDL_copying.h | 2 +- external/SDL2/SDL_cpuinfo.h | 473 +- external/SDL2/SDL_egl.h | 2302 +++ external/SDL2/SDL_endian.h | 209 +- external/SDL2/SDL_error.h | 119 +- external/SDL2/SDL_events.h | 823 +- external/SDL2/SDL_filesystem.h | 145 + external/SDL2/SDL_gamecontroller.h | 921 +- external/SDL2/SDL_gesture.h | 58 +- external/SDL2/SDL_haptic.h | 979 +- external/SDL2/SDL_hidapi.h | 451 + external/SDL2/SDL_hints.h | 1839 ++- external/SDL2/SDL_joystick.h | 909 +- external/SDL2/SDL_keyboard.h | 287 +- external/SDL2/SDL_keycode.h | 50 +- external/SDL2/SDL_loadso.h | 62 +- external/SDL2/SDL_locale.h | 103 + external/SDL2/SDL_log.h | 267 +- external/SDL2/SDL_main.h | 193 +- external/SDL2/SDL_messagebox.h | 112 +- external/SDL2/SDL_metal.h | 112 + external/SDL2/SDL_misc.h | 79 + external/SDL2/SDL_mouse.h | 441 +- external/SDL2/SDL_mutex.h | 412 +- external/SDL2/SDL_name.h | 30 +- external/SDL2/SDL_opengl.h | 13079 +++------------- external/SDL2/SDL_opengl_glext.h | 11180 +++++++++++++ external/SDL2/SDL_opengles.h | 5 +- external/SDL2/SDL_opengles2.h | 22 +- external/SDL2/SDL_opengles2_gl2.h | 621 + external/SDL2/SDL_opengles2_gl2ext.h | 2050 +++ external/SDL2/SDL_opengles2_gl2platform.h | 30 + external/SDL2/SDL_opengles2_khrplatform.h | 282 + external/SDL2/SDL_pixels.h | 381 +- external/SDL2/SDL_platform.h | 166 +- external/SDL2/SDL_power.h | 51 +- external/SDL2/SDL_quit.h | 16 +- external/SDL2/SDL_rect.h | 167 +- external/SDL2/SDL_render.h | 1868 ++- external/SDL2/SDL_revision.h | 2 +- external/SDL2/SDL_rwops.h | 768 +- external/SDL2/SDL_scancode.h | 148 +- external/SDL2/SDL_sensor.h | 301 + external/SDL2/SDL_shape.h | 112 +- external/SDL2/SDL_stdinc.h | 1080 +- external/SDL2/SDL_surface.h | 931 +- external/SDL2/SDL_system.h | 533 +- external/SDL2/SDL_syswm.h | 225 +- external/SDL2/SDL_test.h | 39 +- external/SDL2/SDL_test_assert.h | 36 +- external/SDL2/SDL_test_common.h | 77 +- external/SDL2/SDL_test_compare.h | 24 +- external/SDL2/SDL_test_crc32.h | 58 +- external/SDL2/SDL_test_font.h | 37 +- external/SDL2/SDL_test_fuzzer.h | 104 +- external/SDL2/SDL_test_harness.h | 94 +- external/SDL2/SDL_test_images.h | 42 +- external/SDL2/SDL_test_log.h | 20 +- external/SDL2/SDL_test_md5.h | 50 +- external/SDL2/SDL_test_memory.h | 63 + external/SDL2/SDL_test_random.h | 34 +- external/SDL2/SDL_thread.h | 410 +- external/SDL2/SDL_timer.h | 166 +- external/SDL2/SDL_touch.h | 82 +- external/SDL2/SDL_types.h | 4 +- external/SDL2/SDL_version.h | 172 +- external/SDL2/SDL_video.h | 1958 ++- external/SDL2/SDL_vulkan.h | 215 + external/SDL2/begin_code.h | 119 +- external/SDL2/close_code.h | 9 +- game_shared/bot/bot_manager.h | 13 +- game_shared/bot/bot_profile.cpp | 5 +- game_shared/bot/nav_area.h | 2 + game_shared/bot/nav_file.cpp | 17 +- game_shared/shared_util.cpp | 25 +- lib/public/SDL2.lib | Bin 108368 -> 178186 bytes lib/public/game_controls.lib | Bin 507268 -> 1465566 bytes lib/public/steam_api.lib | Bin 0 -> 370310 bytes lib/public/vgui_controls.lib | Bin 0 -> 8284166 bytes linux/Makefile | 100 +- linux/Makefile.dmc_cdll | 8 +- linux/Makefile.dmcdll | 14 +- linux/Makefile.hl_cdll | 9 +- linux/Makefile.hldll | 17 +- linux/Makefile.ricochet_cdll | 8 +- linux/Makefile.ricochetdll | 16 +- linux/gendbg.sh | 49 +- linux/libSDL2-2.0.0.dylib | Bin 1408108 -> 3395092 bytes .../Resources/DWARF/libsdl2-2.0.0.dylib | Bin 1149526 -> 3050108 bytes linux/libSDL2.dylib | Bin 19 -> 3395092 bytes linux/libSDL2.so | Bin 16 -> 923556 bytes linux/release/vgui.dylib | Bin 431988 -> 415392 bytes linux/release/vgui.so | Bin 975981 -> 1349075 bytes meson.build | 72 + pm_shared/pm_shared.c | 61 +- projects/readme.txt | 4 +- projects/vs2010/makefont.vcxproj | 4 +- projects/vs2010/readme.txt | 4 - projects/vs2010/utils.opensdf | Bin 0 -> 26 bytes public/FileSystem.h | 6 + public/archtypes.h | 2 + public/basetypes.h | 153 + public/commonmacros.h | 25 + public/interface.cpp | 14 +- public/interface.h | 23 +- public/minmax.h | 67 + public/pman_particlemem.h | 2 + public/steam/steamtypes.h | 226 +- public/tier1/interface.h | 218 + ricochet/cl_dll/GameStudioModelRenderer.cpp | 12 +- ricochet/cl_dll/ammo.cpp | 25 +- ricochet/cl_dll/ammo_secondary.cpp | 2 +- ricochet/cl_dll/ammohistory.cpp | 6 +- ricochet/cl_dll/cl_util.h | 2 - ricochet/cl_dll/death.cpp | 2 +- ricochet/cl_dll/geiger.cpp | 8 +- ricochet/cl_dll/health.cpp | 16 +- ricochet/cl_dll/hud.cpp | 4 +- ricochet/cl_dll/hud_iface.h | 4 + ricochet/cl_dll/hud_redraw.cpp | 2 +- ricochet/cl_dll/inputw32.cpp | 22 +- ricochet/cl_dll/menu.cpp | 10 +- ricochet/cl_dll/meson.build | 157 + ricochet/cl_dll/message.cpp | 6 +- ricochet/cl_dll/text_message.cpp | 5 +- ricochet/cl_dll/vgui_TeamFortressViewport.cpp | 8 + ricochet/cl_dll/view.cpp | 22 +- ricochet/dlls/cbase.h | 4 + ricochet/dlls/client.cpp | 18 +- ricochet/dlls/effects.cpp | 2 +- ricochet/dlls/extdll.h | 10 +- ricochet/dlls/func_break.cpp | 36 +- ricochet/dlls/func_tank.cpp | 1 + ricochet/dlls/game.cpp | 4 + ricochet/dlls/items.cpp | 2 +- ricochet/dlls/maprules.cpp | 2 +- ricochet/dlls/meson.build | 135 + ricochet/dlls/multiplay_gamerules.cpp | 6 +- ricochet/dlls/player.cpp | 12 +- ricochet/dlls/triggers.cpp | 7 +- ricochet/dlls/util.cpp | 12 +- ricochet/dlls/util.h | 2 +- ricochet/dlls/weapons.cpp | 2 +- ricochet/dlls/world.cpp | 2 - ricochet/meson.build | 2 + ricochet/pm_shared/pm_shared.c | 23 +- utils/bspinfo/bspinfo.dsp | 248 +- utils/light/light.dsp | 264 +- utils/makefont/makefont.dsp | 276 +- utils/makels/makels.dsp | 200 +- utils/mdlviewer/mdlviewer.dsp | 244 +- utils/mkmovie/mkmovie.dsp | 206 +- utils/procinfo/lib/win32_vc6/procinfo.lib | Bin 2440 -> 28134 bytes utils/procinfo/procinfo.dsp | 236 +- utils/qbsp2/qbsp2.dsp | 352 +- utils/qcsg/qcsg.dsp | 344 +- utils/qlumpy/qlumpy.dsp | 280 +- utils/qrad/qrad.dsp | 328 +- utils/serverctrl/serverctrl.dsp | 288 +- utils/smdlexp/smdlexp.dsp | 238 +- utils/sprgen/sprgen.dsp | 256 +- utils/vgui/lib/win32_vc16/vgui.lib | Bin 0 -> 478872 bytes utils/vgui2/lib/win32_vc16/vgui2.lib | Bin 0 -> 1710 bytes utils/visx2/vis.dsp | 322 +- utils/xwad/xwad.dsp | 200 +- 841 files changed, 155253 insertions(+), 19375 deletions(-) create mode 100644 cl_dll/meson.build create mode 100644 create_vs_projects.bat create mode 100644 devtools/image_to_background.py create mode 100644 devtools/meson/COPYING create mode 100644 devtools/meson/MANIFEST.in create mode 100644 devtools/meson/PKG-INFO create mode 100644 devtools/meson/README.md create mode 100644 devtools/meson/contributing.md create mode 100644 devtools/meson/cross/arm64cl.txt create mode 100644 devtools/meson/cross/armcc.txt create mode 100644 devtools/meson/cross/armclang-linux.txt create mode 100644 devtools/meson/cross/armclang.txt create mode 100644 devtools/meson/cross/c2000.txt create mode 100644 devtools/meson/cross/ccomp-armv7a.txt create mode 100644 devtools/meson/cross/ccrx.txt create mode 100644 devtools/meson/cross/iphone.txt create mode 100644 devtools/meson/cross/linux-mingw-w64-32bit.json create mode 100644 devtools/meson/cross/linux-mingw-w64-32bit.txt create mode 100644 devtools/meson/cross/linux-mingw-w64-64bit.json create mode 100644 devtools/meson/cross/linux-mingw-w64-64bit.txt create mode 100644 devtools/meson/cross/metrowerks-arm.txt create mode 100644 devtools/meson/cross/metrowerks-eppc.txt create mode 100644 devtools/meson/cross/metrowerks.lcf create mode 100644 devtools/meson/cross/msp430.txt create mode 100644 devtools/meson/cross/none.txt create mode 100644 devtools/meson/cross/ownstdlib.txt create mode 100644 devtools/meson/cross/tvos.txt create mode 100644 devtools/meson/cross/ubuntu-armhf.json create mode 100644 devtools/meson/cross/ubuntu-armhf.txt create mode 100644 devtools/meson/cross/ubuntu-faketarget.txt create mode 100644 devtools/meson/cross/wasm.txt create mode 100644 devtools/meson/cross/xc16.txt create mode 100644 devtools/meson/data/.coveragerc.in create mode 100644 devtools/meson/data/com.mesonbuild.install.policy create mode 100644 devtools/meson/data/macros.meson create mode 100644 devtools/meson/data/schema.xsd create mode 100644 devtools/meson/data/shell-completions/bash/meson create mode 100644 devtools/meson/data/shell-completions/zsh/_meson create mode 100644 devtools/meson/data/syntax-highlighting/vim/README create mode 100644 devtools/meson/data/syntax-highlighting/vim/ftdetect/meson.vim create mode 100644 devtools/meson/data/syntax-highlighting/vim/ftplugin/meson.vim create mode 100644 devtools/meson/data/syntax-highlighting/vim/indent/meson.vim create mode 100644 devtools/meson/data/syntax-highlighting/vim/syntax/meson.vim create mode 100644 devtools/meson/data/test.schema.json create mode 100644 devtools/meson/graphics/meson_logo.svg create mode 100644 devtools/meson/graphics/meson_logo_big.png create mode 100644 devtools/meson/graphics/wrap_logo.svg create mode 100644 devtools/meson/man/meson.1 create mode 100644 devtools/meson/manual tests/1 wrap/main.c create mode 100644 devtools/meson/manual tests/1 wrap/meson.build create mode 100644 devtools/meson/manual tests/1 wrap/subprojects/sqlite.wrap create mode 100644 devtools/meson/manual tests/10 svn wrap/meson.build create mode 100644 devtools/meson/manual tests/10 svn wrap/prog.c create mode 100644 devtools/meson/manual tests/10 svn wrap/subprojects/samplesubproject.wrap create mode 100644 devtools/meson/manual tests/11 wrap imposter/meson.build create mode 100644 devtools/meson/manual tests/11 wrap imposter/subprojects/zlib.wrap create mode 100644 devtools/meson/manual tests/12 wrap mirror/meson.build create mode 100644 devtools/meson/manual tests/12 wrap mirror/subprojects/zlib.wrap create mode 100644 devtools/meson/manual tests/13 builddir upgrade/data/foo.dat create mode 100644 devtools/meson/manual tests/13 builddir upgrade/foo.1 create mode 100644 devtools/meson/manual tests/13 builddir upgrade/foo.c create mode 100644 devtools/meson/manual tests/13 builddir upgrade/lib.c create mode 100644 devtools/meson/manual tests/13 builddir upgrade/meson.build create mode 100644 devtools/meson/manual tests/13 builddir upgrade/mod.py create mode 100644 devtools/meson/manual tests/2 multiwrap/meson.build create mode 100644 devtools/meson/manual tests/2 multiwrap/prog.c create mode 100644 devtools/meson/manual tests/2 multiwrap/subprojects/libpng.wrap create mode 100644 devtools/meson/manual tests/2 multiwrap/subprojects/lua.wrap create mode 100644 devtools/meson/manual tests/2 multiwrap/subprojects/zlib.wrap create mode 100644 devtools/meson/manual tests/3 git wrap/meson.build create mode 100644 devtools/meson/manual tests/3 git wrap/prog.c create mode 100644 devtools/meson/manual tests/3 git wrap/subprojects/samplesubproject.wrap create mode 100644 devtools/meson/manual tests/4 standalone binaries/Info.plist create mode 100644 devtools/meson/manual tests/4 standalone binaries/build_linux_package.sh create mode 100644 devtools/meson/manual tests/4 standalone binaries/build_osx_package.sh create mode 100644 devtools/meson/manual tests/4 standalone binaries/build_windows_package.py create mode 100644 devtools/meson/manual tests/4 standalone binaries/linux_bundler.sh create mode 100644 devtools/meson/manual tests/4 standalone binaries/meson.build create mode 100644 devtools/meson/manual tests/4 standalone binaries/myapp.cpp create mode 100644 devtools/meson/manual tests/4 standalone binaries/myapp.icns create mode 100644 devtools/meson/manual tests/4 standalone binaries/myapp.iss create mode 100644 devtools/meson/manual tests/4 standalone binaries/myapp.sh create mode 100644 devtools/meson/manual tests/4 standalone binaries/osx_bundler.sh create mode 100644 devtools/meson/manual tests/4 standalone binaries/readme.txt create mode 100644 devtools/meson/manual tests/4 standalone binaries/template.dmg.gz create mode 100644 devtools/meson/manual tests/5 rpm/lib.c create mode 100644 devtools/meson/manual tests/5 rpm/lib.h create mode 100644 devtools/meson/manual tests/5 rpm/main.c create mode 100644 devtools/meson/manual tests/5 rpm/meson.build create mode 100644 devtools/meson/manual tests/6 hg wrap/meson.build create mode 100644 devtools/meson/manual tests/6 hg wrap/prog.c create mode 100644 devtools/meson/manual tests/6 hg wrap/subprojects/samplesubproject.wrap create mode 100644 devtools/meson/manual tests/7 vala composite widgets/meson.build create mode 100644 devtools/meson/manual tests/7 vala composite widgets/my-resources.xml create mode 100644 devtools/meson/manual tests/7 vala composite widgets/mywidget.ui create mode 100644 devtools/meson/manual tests/7 vala composite widgets/mywidget.vala create mode 100644 devtools/meson/manual tests/8 timeout/meson.build create mode 100644 devtools/meson/manual tests/8 timeout/sleepprog.c create mode 100644 devtools/meson/meson.egg-info/PKG-INFO create mode 100644 devtools/meson/meson.egg-info/SOURCES.txt create mode 100644 devtools/meson/meson.egg-info/dependency_links.txt create mode 100644 devtools/meson/meson.egg-info/entry_points.txt create mode 100644 devtools/meson/meson.egg-info/requires.txt create mode 100644 devtools/meson/meson.egg-info/top_level.txt create mode 100644 devtools/meson/meson.py create mode 100644 devtools/meson/mesonbuild/__init__.py create mode 100644 devtools/meson/mesonbuild/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/_pathlib.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/arglist.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/build.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/coredata.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/depfile.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/envconfig.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/environment.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mcompile.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mconf.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mdevenv.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mdist.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mesonlib.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mesonmain.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/minit.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/minstall.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mintro.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mlog.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mparser.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/msetup.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/msubprojects.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/mtest.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/munstable_coredata.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/optinterpreter.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/programs.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/__pycache__/rewriter.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/_pathlib.py create mode 100644 devtools/meson/mesonbuild/_typing.py create mode 100644 devtools/meson/mesonbuild/arglist.py create mode 100644 devtools/meson/mesonbuild/ast/__init__.py create mode 100644 devtools/meson/mesonbuild/ast/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/ast/__pycache__/interpreter.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/ast/__pycache__/introspection.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/ast/__pycache__/postprocess.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/ast/__pycache__/printer.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/ast/__pycache__/visitor.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/ast/interpreter.py create mode 100644 devtools/meson/mesonbuild/ast/introspection.py create mode 100644 devtools/meson/mesonbuild/ast/postprocess.py create mode 100644 devtools/meson/mesonbuild/ast/printer.py create mode 100644 devtools/meson/mesonbuild/ast/visitor.py create mode 100644 devtools/meson/mesonbuild/backend/__init__.py create mode 100644 devtools/meson/mesonbuild/backend/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/backend/__pycache__/backends.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/backend/__pycache__/vs2010backend.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/backend/__pycache__/vs2019backend.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/backend/backends.py create mode 100644 devtools/meson/mesonbuild/backend/ninjabackend.py create mode 100644 devtools/meson/mesonbuild/backend/nonebackend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2010backend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2012backend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2013backend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2015backend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2017backend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2019backend.py create mode 100644 devtools/meson/mesonbuild/backend/vs2022backend.py create mode 100644 devtools/meson/mesonbuild/backend/xcodebackend.py create mode 100644 devtools/meson/mesonbuild/build.py create mode 100644 devtools/meson/mesonbuild/cargo/__init__.py create mode 100644 devtools/meson/mesonbuild/cargo/builder.py create mode 100644 devtools/meson/mesonbuild/cargo/cfg.py create mode 100644 devtools/meson/mesonbuild/cargo/interpreter.py create mode 100644 devtools/meson/mesonbuild/cargo/manifest.py create mode 100644 devtools/meson/mesonbuild/cargo/version.py create mode 100644 devtools/meson/mesonbuild/cmake/__init__.py create mode 100644 devtools/meson/mesonbuild/cmake/common.py create mode 100644 devtools/meson/mesonbuild/cmake/data/__init__.py create mode 100644 devtools/meson/mesonbuild/cmake/data/preload.cmake create mode 100644 devtools/meson/mesonbuild/cmake/executor.py create mode 100644 devtools/meson/mesonbuild/cmake/fileapi.py create mode 100644 devtools/meson/mesonbuild/cmake/generator.py create mode 100644 devtools/meson/mesonbuild/cmake/interpreter.py create mode 100644 devtools/meson/mesonbuild/cmake/toolchain.py create mode 100644 devtools/meson/mesonbuild/cmake/traceparser.py create mode 100644 devtools/meson/mesonbuild/cmake/tracetargets.py create mode 100644 devtools/meson/mesonbuild/compilers/__init__.py create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/c.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/c_function_attributes.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/compilers.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/cpp.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/d.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/__pycache__/detect.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/asm.py create mode 100644 devtools/meson/mesonbuild/compilers/c.py create mode 100644 devtools/meson/mesonbuild/compilers/c_function_attributes.py create mode 100644 devtools/meson/mesonbuild/compilers/compilers.py create mode 100644 devtools/meson/mesonbuild/compilers/cpp.py create mode 100644 devtools/meson/mesonbuild/compilers/cs.py create mode 100644 devtools/meson/mesonbuild/compilers/cuda.py create mode 100644 devtools/meson/mesonbuild/compilers/cython.py create mode 100644 devtools/meson/mesonbuild/compilers/d.py create mode 100644 devtools/meson/mesonbuild/compilers/detect.py create mode 100644 devtools/meson/mesonbuild/compilers/fortran.py create mode 100644 devtools/meson/mesonbuild/compilers/java.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__init__.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/arm.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/ccrx.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/clang.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/clike.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/compcert.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/elbrus.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/emscripten.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/gnu.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/intel.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/metrowerks.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/pgi.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/ti.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/visualstudio.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/__pycache__/xc16.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/compilers/mixins/arm.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/ccrx.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/clang.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/clike.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/compcert.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/elbrus.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/emscripten.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/gnu.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/intel.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/islinker.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/metrowerks.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/pgi.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/ti.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/visualstudio.py create mode 100644 devtools/meson/mesonbuild/compilers/mixins/xc16.py create mode 100644 devtools/meson/mesonbuild/compilers/objc.py create mode 100644 devtools/meson/mesonbuild/compilers/objcpp.py create mode 100644 devtools/meson/mesonbuild/compilers/rust.py create mode 100644 devtools/meson/mesonbuild/compilers/swift.py create mode 100644 devtools/meson/mesonbuild/compilers/vala.py create mode 100644 devtools/meson/mesonbuild/coredata.py create mode 100644 devtools/meson/mesonbuild/dependencies/__init__.py create mode 100644 devtools/meson/mesonbuild/dependencies/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/dependencies/__pycache__/base.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/dependencies/__pycache__/detect.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/dependencies/base.py create mode 100644 devtools/meson/mesonbuild/dependencies/boost.py create mode 100644 devtools/meson/mesonbuild/dependencies/cmake.py create mode 100644 devtools/meson/mesonbuild/dependencies/coarrays.py create mode 100644 devtools/meson/mesonbuild/dependencies/configtool.py create mode 100644 devtools/meson/mesonbuild/dependencies/cuda.py create mode 100644 devtools/meson/mesonbuild/dependencies/data/CMakeLists.txt create mode 100644 devtools/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt create mode 100644 devtools/meson/mesonbuild/dependencies/data/CMakePathInfo.txt create mode 100644 devtools/meson/mesonbuild/dependencies/data/__init__.py create mode 100644 devtools/meson/mesonbuild/dependencies/detect.py create mode 100644 devtools/meson/mesonbuild/dependencies/dev.py create mode 100644 devtools/meson/mesonbuild/dependencies/dub.py create mode 100644 devtools/meson/mesonbuild/dependencies/factory.py create mode 100644 devtools/meson/mesonbuild/dependencies/framework.py create mode 100644 devtools/meson/mesonbuild/dependencies/hdf5.py create mode 100644 devtools/meson/mesonbuild/dependencies/misc.py create mode 100644 devtools/meson/mesonbuild/dependencies/mpi.py create mode 100644 devtools/meson/mesonbuild/dependencies/pkgconfig.py create mode 100644 devtools/meson/mesonbuild/dependencies/platform.py create mode 100644 devtools/meson/mesonbuild/dependencies/python.py create mode 100644 devtools/meson/mesonbuild/dependencies/qt.py create mode 100644 devtools/meson/mesonbuild/dependencies/scalapack.py create mode 100644 devtools/meson/mesonbuild/dependencies/ui.py create mode 100644 devtools/meson/mesonbuild/depfile.py create mode 100644 devtools/meson/mesonbuild/envconfig.py create mode 100644 devtools/meson/mesonbuild/environment.py create mode 100644 devtools/meson/mesonbuild/interpreter/__init__.py create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/compiler.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/dependencyfallbacks.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/interpreter.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/interpreterobjects.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/mesonmain.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/__pycache__/type_checking.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/compiler.py create mode 100644 devtools/meson/mesonbuild/interpreter/dependencyfallbacks.py create mode 100644 devtools/meson/mesonbuild/interpreter/interpreter.py create mode 100644 devtools/meson/mesonbuild/interpreter/interpreterobjects.py create mode 100644 devtools/meson/mesonbuild/interpreter/kwargs.py create mode 100644 devtools/meson/mesonbuild/interpreter/mesonmain.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__init__.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/array.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/boolean.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/dict.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/integer.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/range.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/__pycache__/string.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/array.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/boolean.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/dict.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/integer.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/range.py create mode 100644 devtools/meson/mesonbuild/interpreter/primitives/string.py create mode 100644 devtools/meson/mesonbuild/interpreter/type_checking.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/__init__.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/_unholder.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/baseobjects.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/decorators.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/disabler.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/exceptions.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/helpers.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/interpreterbase.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/__pycache__/operator.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/interpreterbase/_unholder.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/baseobjects.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/decorators.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/disabler.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/exceptions.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/helpers.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/interpreterbase.py create mode 100644 devtools/meson/mesonbuild/interpreterbase/operator.py create mode 100644 devtools/meson/mesonbuild/linkers/__init__.py create mode 100644 devtools/meson/mesonbuild/linkers/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/linkers/__pycache__/base.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/linkers/__pycache__/detect.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/linkers/__pycache__/linkers.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/linkers/base.py create mode 100644 devtools/meson/mesonbuild/linkers/detect.py create mode 100644 devtools/meson/mesonbuild/linkers/linkers.py create mode 100644 devtools/meson/mesonbuild/mcompile.py create mode 100644 devtools/meson/mesonbuild/mconf.py create mode 100644 devtools/meson/mesonbuild/mdevenv.py create mode 100644 devtools/meson/mesonbuild/mdist.py create mode 100644 devtools/meson/mesonbuild/mesondata.py create mode 100644 devtools/meson/mesonbuild/mesonlib.py create mode 100644 devtools/meson/mesonbuild/mesonmain.py create mode 100644 devtools/meson/mesonbuild/minit.py create mode 100644 devtools/meson/mesonbuild/minstall.py create mode 100644 devtools/meson/mesonbuild/mintro.py create mode 100644 devtools/meson/mesonbuild/mlog.py create mode 100644 devtools/meson/mesonbuild/modules/__init__.py create mode 100644 devtools/meson/mesonbuild/modules/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/modules/cmake.py create mode 100644 devtools/meson/mesonbuild/modules/cuda.py create mode 100644 devtools/meson/mesonbuild/modules/dlang.py create mode 100644 devtools/meson/mesonbuild/modules/external_project.py create mode 100644 devtools/meson/mesonbuild/modules/fs.py create mode 100644 devtools/meson/mesonbuild/modules/gnome.py create mode 100644 devtools/meson/mesonbuild/modules/hotdoc.py create mode 100644 devtools/meson/mesonbuild/modules/i18n.py create mode 100644 devtools/meson/mesonbuild/modules/icestorm.py create mode 100644 devtools/meson/mesonbuild/modules/java.py create mode 100644 devtools/meson/mesonbuild/modules/keyval.py create mode 100644 devtools/meson/mesonbuild/modules/modtest.py create mode 100644 devtools/meson/mesonbuild/modules/pkgconfig.py create mode 100644 devtools/meson/mesonbuild/modules/python.py create mode 100644 devtools/meson/mesonbuild/modules/python3.py create mode 100644 devtools/meson/mesonbuild/modules/qt.py create mode 100644 devtools/meson/mesonbuild/modules/qt4.py create mode 100644 devtools/meson/mesonbuild/modules/qt5.py create mode 100644 devtools/meson/mesonbuild/modules/qt6.py create mode 100644 devtools/meson/mesonbuild/modules/rust.py create mode 100644 devtools/meson/mesonbuild/modules/simd.py create mode 100644 devtools/meson/mesonbuild/modules/sourceset.py create mode 100644 devtools/meson/mesonbuild/modules/wayland.py create mode 100644 devtools/meson/mesonbuild/modules/windows.py create mode 100644 devtools/meson/mesonbuild/mparser.py create mode 100644 devtools/meson/mesonbuild/msetup.py create mode 100644 devtools/meson/mesonbuild/msubprojects.py create mode 100644 devtools/meson/mesonbuild/mtest.py create mode 100644 devtools/meson/mesonbuild/munstable_coredata.py create mode 100644 devtools/meson/mesonbuild/optinterpreter.py create mode 100644 devtools/meson/mesonbuild/programs.py create mode 100644 devtools/meson/mesonbuild/rewriter.py create mode 100644 devtools/meson/mesonbuild/scripts/__init__.py create mode 100644 devtools/meson/mesonbuild/scripts/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/scripts/__pycache__/depfixer.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/scripts/__pycache__/env2mfile.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/scripts/__pycache__/meson_exe.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/scripts/__pycache__/regen_checker.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/scripts/clangformat.py create mode 100644 devtools/meson/mesonbuild/scripts/clangtidy.py create mode 100644 devtools/meson/mesonbuild/scripts/cleantrees.py create mode 100644 devtools/meson/mesonbuild/scripts/cmake_run_ctgt.py create mode 100644 devtools/meson/mesonbuild/scripts/cmd_or_ps.ps1 create mode 100644 devtools/meson/mesonbuild/scripts/copy.py create mode 100644 devtools/meson/mesonbuild/scripts/coverage.py create mode 100644 devtools/meson/mesonbuild/scripts/delwithsuffix.py create mode 100644 devtools/meson/mesonbuild/scripts/depfixer.py create mode 100644 devtools/meson/mesonbuild/scripts/depscan.py create mode 100644 devtools/meson/mesonbuild/scripts/dirchanger.py create mode 100644 devtools/meson/mesonbuild/scripts/env2mfile.py create mode 100644 devtools/meson/mesonbuild/scripts/externalproject.py create mode 100644 devtools/meson/mesonbuild/scripts/gettext.py create mode 100644 devtools/meson/mesonbuild/scripts/gtkdochelper.py create mode 100644 devtools/meson/mesonbuild/scripts/hotdochelper.py create mode 100644 devtools/meson/mesonbuild/scripts/itstool.py create mode 100644 devtools/meson/mesonbuild/scripts/meson_exe.py create mode 100644 devtools/meson/mesonbuild/scripts/msgfmthelper.py create mode 100644 devtools/meson/mesonbuild/scripts/pycompile.py create mode 100644 devtools/meson/mesonbuild/scripts/python_info.py create mode 100644 devtools/meson/mesonbuild/scripts/regen_checker.py create mode 100644 devtools/meson/mesonbuild/scripts/run_tool.py create mode 100644 devtools/meson/mesonbuild/scripts/scanbuild.py create mode 100644 devtools/meson/mesonbuild/scripts/symbolextractor.py create mode 100644 devtools/meson/mesonbuild/scripts/tags.py create mode 100644 devtools/meson/mesonbuild/scripts/test_loaded_modules.py create mode 100644 devtools/meson/mesonbuild/scripts/uninstall.py create mode 100644 devtools/meson/mesonbuild/scripts/vcstagger.py create mode 100644 devtools/meson/mesonbuild/scripts/yasm.py create mode 100644 devtools/meson/mesonbuild/templates/__init__.py create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/cpptemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/cstemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/ctemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/cudatemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/dlangtemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/fortrantemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/javatemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/mesontemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/objcpptemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/objctemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/rusttemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/samplefactory.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/sampleimpl.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/__pycache__/valatemplates.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/templates/cpptemplates.py create mode 100644 devtools/meson/mesonbuild/templates/cstemplates.py create mode 100644 devtools/meson/mesonbuild/templates/ctemplates.py create mode 100644 devtools/meson/mesonbuild/templates/cudatemplates.py create mode 100644 devtools/meson/mesonbuild/templates/dlangtemplates.py create mode 100644 devtools/meson/mesonbuild/templates/fortrantemplates.py create mode 100644 devtools/meson/mesonbuild/templates/javatemplates.py create mode 100644 devtools/meson/mesonbuild/templates/mesontemplates.py create mode 100644 devtools/meson/mesonbuild/templates/objcpptemplates.py create mode 100644 devtools/meson/mesonbuild/templates/objctemplates.py create mode 100644 devtools/meson/mesonbuild/templates/rusttemplates.py create mode 100644 devtools/meson/mesonbuild/templates/samplefactory.py create mode 100644 devtools/meson/mesonbuild/templates/sampleimpl.py create mode 100644 devtools/meson/mesonbuild/templates/valatemplates.py create mode 100644 devtools/meson/mesonbuild/utils/__init__.py create mode 100644 devtools/meson/mesonbuild/utils/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/utils/__pycache__/core.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/utils/__pycache__/platform.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/utils/__pycache__/universal.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/utils/__pycache__/vsenv.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/utils/__pycache__/win32.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/utils/core.py create mode 100644 devtools/meson/mesonbuild/utils/platform.py create mode 100644 devtools/meson/mesonbuild/utils/posix.py create mode 100644 devtools/meson/mesonbuild/utils/universal.py create mode 100644 devtools/meson/mesonbuild/utils/vsenv.py create mode 100644 devtools/meson/mesonbuild/utils/win32.py create mode 100644 devtools/meson/mesonbuild/wrap/__init__.py create mode 100644 devtools/meson/mesonbuild/wrap/__pycache__/__init__.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/wrap/__pycache__/wrap.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/wrap/__pycache__/wraptool.cpython-37.pyc create mode 100644 devtools/meson/mesonbuild/wrap/wrap.py create mode 100644 devtools/meson/mesonbuild/wrap/wraptool.py create mode 100644 devtools/meson/packaging/License.rtf create mode 100644 devtools/meson/packaging/create_zipapp.py create mode 100644 devtools/meson/packaging/createmsi.py create mode 100644 devtools/meson/packaging/createpkg.py create mode 100644 devtools/meson/packaging/hook-mesonbuild.py create mode 100644 devtools/meson/packaging/macpages/English.lproj/conclusion.html create mode 100644 devtools/meson/packaging/macpages/English.lproj/license.html create mode 100644 devtools/meson/packaging/macpages/English.lproj/welcome.html create mode 100644 devtools/meson/pyproject.toml create mode 100644 devtools/meson/run_cross_test.py create mode 100644 devtools/meson/run_meson_command_tests.py create mode 100644 devtools/meson/run_project_tests.py create mode 100644 devtools/meson/run_tests.py create mode 100644 devtools/meson/run_unittests.py create mode 100644 devtools/meson/setup.cfg create mode 100644 devtools/meson/setup.py create mode 100644 devtools/meson/tools/ac_converter.py create mode 100644 devtools/meson/tools/boost_names.py create mode 100644 devtools/meson/tools/build_website.py create mode 100644 devtools/meson/tools/cmake2meson.py create mode 100644 devtools/meson/tools/copy_files.py create mode 100644 devtools/meson/tools/dircondenser.py create mode 100644 devtools/meson/tools/regenerate_docs.py create mode 100644 devtools/meson/tools/run_with_cov.py create mode 100644 devtools/meson/unittests/__init__.py create mode 100644 devtools/meson/unittests/allplatformstests.py create mode 100644 devtools/meson/unittests/baseplatformtests.py create mode 100644 devtools/meson/unittests/cargotests.py create mode 100644 devtools/meson/unittests/darwintests.py create mode 100644 devtools/meson/unittests/datatests.py create mode 100644 devtools/meson/unittests/failuretests.py create mode 100644 devtools/meson/unittests/helpers.py create mode 100644 devtools/meson/unittests/internaltests.py create mode 100644 devtools/meson/unittests/linuxcrosstests.py create mode 100644 devtools/meson/unittests/linuxliketests.py create mode 100644 devtools/meson/unittests/machinefiletests.py create mode 100644 devtools/meson/unittests/platformagnostictests.py create mode 100644 devtools/meson/unittests/pythontests.py create mode 100644 devtools/meson/unittests/rewritetests.py create mode 100644 devtools/meson/unittests/subprojectscommandtests.py create mode 100644 devtools/meson/unittests/taptests.py create mode 100644 devtools/meson/unittests/windowstests.py create mode 100644 devtools/meson_set_outdir.bat create mode 100644 devtools/vs_add_build_steps.py create mode 100644 devtools/vs_add_launch_config.py create mode 100644 dlls/meson.build create mode 100644 dlls/vehicle.cpp create mode 100644 dmc/cl_dll/meson.build create mode 100644 dmc/dlls/meson.build create mode 100644 dmc/meson.build create mode 100644 external/SDL2/SDL_config.h.cmake create mode 100644 external/SDL2/SDL_config.h.in create mode 100644 external/SDL2/SDL_config_macosx.h.orig create mode 100644 external/SDL2/SDL_config_psp.h create mode 100644 external/SDL2/SDL_config_winrt.h create mode 100644 external/SDL2/SDL_egl.h create mode 100644 external/SDL2/SDL_filesystem.h create mode 100644 external/SDL2/SDL_hidapi.h create mode 100644 external/SDL2/SDL_locale.h create mode 100644 external/SDL2/SDL_metal.h create mode 100644 external/SDL2/SDL_misc.h create mode 100644 external/SDL2/SDL_opengl_glext.h create mode 100644 external/SDL2/SDL_opengles2_gl2.h create mode 100644 external/SDL2/SDL_opengles2_gl2ext.h create mode 100644 external/SDL2/SDL_opengles2_gl2platform.h create mode 100644 external/SDL2/SDL_opengles2_khrplatform.h create mode 100644 external/SDL2/SDL_sensor.h create mode 100644 external/SDL2/SDL_test_memory.h create mode 100644 external/SDL2/SDL_vulkan.h create mode 100644 lib/public/steam_api.lib create mode 100644 lib/public/vgui_controls.lib create mode 100644 meson.build create mode 100644 projects/vs2010/utils.opensdf create mode 100644 public/basetypes.h create mode 100644 public/commonmacros.h create mode 100644 public/minmax.h create mode 100644 public/tier1/interface.h create mode 100644 ricochet/cl_dll/meson.build create mode 100644 ricochet/dlls/meson.build create mode 100644 ricochet/meson.build create mode 100644 utils/vgui/lib/win32_vc16/vgui.lib create mode 100644 utils/vgui2/lib/win32_vc16/vgui2.lib diff --git a/README.md b/README.md index aef5edf..1a692e8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Half Life 1 SDK LICENSE ====================== -Half Life 1 SDK Copyright© Valve Corp. +Half Life 1 SDK Copyright © Valve Corp. THIS DOCUMENT DESCRIBES A CONTRACT BETWEEN YOU AND VALVE CORPORATION (“Valveâ€). PLEASE READ IT BEFORE DOWNLOADING OR USING THE HALF LIFE 1 SDK (“SDKâ€). BY DOWNLOADING AND/OR USING THE SOURCE ENGINE SDK YOU ACCEPT THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE PLEASE DON’T DOWNLOAD OR USE THE SDK. @@ -37,7 +37,7 @@ If it has not been reported, create a new issue with at least the following info - a detailed description of the issue, including any output from the command line; - steps for reproducing the issue; - your system information.\*; and -- the `version` output from the inâ€game console. +- the `version` output from the in-game console. Please place logs either in a code block (press `M` in your browser for a GFM cheat sheet) or a [gist](https://gist.github.com). @@ -55,3 +55,19 @@ There are basic rules of conduct that should be followed at all times by everyon - Do not repeatedly update an open issue remarking that the issue persists. Remember: Just because the issue you reported was reported here does not mean that it is an issue with Half-Life. As well, should your issue not be resolved immediately, it does not mean that a resolution is not being researched or tested. Patience is always appreciated. + + +Building the SDK code +------- + +Visual Studio 2019 is required to build mod DLLs on Windows. In the Visual Studio installer, install "Desktop development with C++" under "Workloads" and "C++ MFC for latest v142 build tools (x86 & x64)" under "Individual components". Python must also be installed to run scripts used as part of the build process (Python 3.9 has been tested). + +To generate a Visual Studio solution with projects for each mod, run `create_vs_projects.bat` from a command line. This will create a solution file called `goldsrc.sln` in a folder called `build-debugoptimized-sln`. You can add `release` to the command line to generate a solution that builds the Release configuration instead, e.g. `create_vs_projects.bat release`. + +create_vs_projects uses [Meson](https://mesonbuild.com/) to generate the projects and solution. Each mod DLL must have a corresponding `meson.build` file that specifies the included files and dependencies. + +By default, as a post-build step, built mod DLLs are copied to a folder called `game` one level up from the root SDK folder. This behavior can be customized by modifying `vs_add_build_steps.py` under `devtools`. + +Tools have not yet been updated for Meson / VS2019, but can be built using the VS2010 projects in the projects\vs2010 folder. See the `readme.txt` file there. + +Linux binaries are built using Makefiles found in the `linux` folder, and are expected to be built / run in the Steam Runtime "scout" environment. You will need to set the environment variables VALVE_NO_AUTO_P4=1 and USE_STEAM_RUNTIME=1 while building. diff --git a/cl_dll/ammo.cpp b/cl_dll/ammo.cpp index 6121b68..dbbf9a2 100644 --- a/cl_dll/ammo.cpp +++ b/cl_dll/ammo.cpp @@ -74,10 +74,15 @@ void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon ) { int i, iRes; - if (ScreenWidth < 640) - iRes = 320; - else + + if (ScreenWidth > 2560 && ScreenHeight > 1600) + iRes = 2560; + else if (ScreenWidth >= 1280 && ScreenHeight > 720) + iRes = 1280; + else if (ScreenWidth >= 640) iRes = 640; + else + iRes = 320; char sz[128]; @@ -325,16 +330,17 @@ int CHudAmmo::VidInit(void) // If we've already loaded weapons, let's get new sprites gWR.LoadAllWeaponSprites(); - if (ScreenWidth >= 640) - { - giABWidth = 20; - giABHeight = 4; - } - else - { - giABWidth = 10; - giABHeight = 2; - } + int nScale = 1; + + if (ScreenWidth > 2560 && ScreenHeight > 1600) + nScale = 4; + else if (ScreenWidth >= 1280 && ScreenHeight > 720) + nScale = 3; + else if (ScreenWidth >= 640) + nScale = 2; + + giABWidth = 10 * nScale; + giABHeight = 2 * nScale; return 1; } @@ -641,7 +647,9 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf ) WEAPON Weapon; - strcpy( Weapon.szName, READ_STRING() ); + strncpy( Weapon.szName, READ_STRING(), MAX_WEAPON_NAME ); + Weapon.szName[ sizeof(Weapon.szName) - 1 ] = '\0'; + Weapon.iAmmoType = (int)READ_CHAR(); Weapon.iMax1 = READ_BYTE(); @@ -659,6 +667,27 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf ) Weapon.iFlags = READ_BYTE(); Weapon.iClip = 0; + if (Weapon.iId < 0 || Weapon.iId >= MAX_WEAPONS) + return 0; + + if (Weapon.iSlot < 0 || Weapon.iSlot >= MAX_WEAPON_SLOTS+1) + return 0; + + if (Weapon.iSlotPos < 0 || Weapon.iSlotPos >= MAX_WEAPON_POSITIONS+1) + return 0; + + if (Weapon.iAmmoType < -1 || Weapon.iAmmoType >= MAX_AMMO_TYPES) + return 0; + + if (Weapon.iAmmo2Type < -1 || Weapon.iAmmo2Type >= MAX_AMMO_TYPES) + return 0; + + if (Weapon.iAmmoType >= 0 && Weapon.iMax1 == 0) + return 0; + + if (Weapon.iAmmo2Type >= 0 && Weapon.iMax2 == 0) + return 0; + gWR.AddWeapon( &Weapon ); return 1; @@ -862,7 +891,7 @@ int CHudAmmo::Draw(float flTime) AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; - a = (int) max( MIN_ALPHA, m_fFade ); + a = max( MIN_ALPHA, m_fFade ); if (m_fFade > 0) m_fFade -= (gHUD.m_flTimeDelta * 20); @@ -871,8 +900,8 @@ int CHudAmmo::Draw(float flTime) ScaleColors(r, g, b, a ); - // Does this weapon have a clip? y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2; + y += (int)(gHUD.m_iFontHeight * 0.2f); // Does weapon have any ammo at all? if (m_pWeapon->iAmmoType > 0) @@ -1188,10 +1217,10 @@ client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes int i = iCount; client_sprite_t *p = pList; - + while(i--) { - if ((!strcmp(psz, p->szName)) && (p->iRes == iRes)) + if ((p->iRes == iRes) && (!strcmp(psz, p->szName))) return p; p++; } diff --git a/cl_dll/ammo_secondary.cpp b/cl_dll/ammo_secondary.cpp index e2a2f59..f4cc316 100644 --- a/cl_dll/ammo_secondary.cpp +++ b/cl_dll/ammo_secondary.cpp @@ -61,7 +61,7 @@ int CHudAmmoSecondary :: Draw(float flTime) // draw secondary ammo icons above normal ammo readout int a, x, y, r, g, b, AmmoWidth; UnpackRGB( r, g, b, RGB_YELLOWISH ); - a = (int) max( MIN_ALPHA, m_fFade ); + a = max( MIN_ALPHA, m_fFade ); if (m_fFade > 0) m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons ScaleColors( r, g, b, a ); diff --git a/cl_dll/ammohistory.cpp b/cl_dll/ammohistory.cpp index bc78dad..4825f32 100644 --- a/cl_dll/ammohistory.cpp +++ b/cl_dll/ammohistory.cpp @@ -126,11 +126,11 @@ int HistoryResource :: DrawAmmoHistory( float flTime ) int r, g, b; UnpackRGB(r,g,b, RGB_YELLOWISH); float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - ScaleColors(r, g, b, min(scale, 255) ); + ScaleColors(r, g, b, min(scale, 255) ); // Draw the pic int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - 24; + int xpos = ScreenWidth - (rcPic.right - rcPic.left) - 4; if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic { // the dll has to make sure it has sent info the weapons you need SPR_Set( *spr, r, g, b ); @@ -154,7 +154,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime ) UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - ScaleColors(r, g, b, min(scale, 255) ); + ScaleColors(r, g, b, min(scale, 255) ); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); @@ -172,7 +172,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime ) UnpackRGB(r,g,b, RGB_YELLOWISH); float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - ScaleColors(r, g, b, min(scale, 255) ); + ScaleColors(r, g, b, min(scale, 255) ); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int xpos = ScreenWidth - (rect.right - rect.left) - 10; diff --git a/cl_dll/battery.cpp b/cl_dll/battery.cpp index 2befb90..efeb3c5 100644 --- a/cl_dll/battery.cpp +++ b/cl_dll/battery.cpp @@ -134,7 +134,11 @@ int CHudBattery::Draw(float flTime) int iOffset = (m_prc1->bottom - m_prc1->top)/6; y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; - x = ScreenWidth/5; + + int width = (m_prc1->right - m_prc1->left); + + // this used to just be ScreenWidth/5 but that caused real issues at higher resolutions. Instead, base it on the width of this sprite. + x = 3 * width; // make sure we have the right sprite handles if ( !m_hSprite1 ) @@ -151,7 +155,8 @@ int CHudBattery::Draw(float flTime) SPR_DrawAdditive( 0, x, y - iOffset + (rc.top - m_prc2->top), &rc); } - x += (m_prc1->right - m_prc1->left); + x += width; + y += (int)(gHUD.m_iFontHeight * 0.2f); x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b); return 1; diff --git a/cl_dll/cl_util.h b/cl_dll/cl_util.h index d9034d9..431eda7 100644 --- a/cl_dll/cl_util.h +++ b/cl_dll/cl_util.h @@ -83,6 +83,7 @@ inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int fl #define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) #define ServerCmd (*gEngfuncs.pfnServerCmd) #define EngineClientCmd (*gEngfuncs.pfnClientCmd) +#define EngineFilteredClientCmd (*gEngfuncs.pfnFilteredClientCmd) #define SetCrosshair (*gEngfuncs.pfnSetCrosshair) #define AngleVectors (*gEngfuncs.pfnAngleVectors) @@ -162,8 +163,6 @@ inline int safe_sprintf( char *dst, int len_dst, const char *format, ...) inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); } inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); } -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) #define fabs(x) ((x) > 0 ? (x) : 0 - (x)) void ScaleColors( int &r, int &g, int &b, int a ); diff --git a/cl_dll/death.cpp b/cl_dll/death.cpp index 836ac47..7a10521 100644 --- a/cl_dll/death.cpp +++ b/cl_dll/death.cpp @@ -73,7 +73,7 @@ int CHudDeathNotice :: Init( void ) HOOK_MESSAGE( DeathMsg ); - CVAR_CREATE( "hud_deathnotice_time", "6", 0 ); + CVAR_CREATE( "hud_deathnotice_time", "6", FCVAR_ARCHIVE ); return 1; } @@ -94,7 +94,12 @@ int CHudDeathNotice :: VidInit( void ) int CHudDeathNotice :: Draw( float flTime ) { - int x, y, r, g, b; + int x, y, r, g, b, texty; + + int gap = 20; + + wrect_t& sprite = gHUD.GetSpriteRect(m_HUD_d_skull); + gap = sprite.bottom - sprite.top; for ( int i = 0; i < MAX_DEATHNOTICES; i++ ) { @@ -115,10 +120,12 @@ int CHudDeathNotice :: Draw( float flTime ) if ( gViewPort && gViewPort->AllowedToPrintText() ) { // Draw the death notice - y = DEATHNOTICE_TOP + 2 + (20 * i); //!!! + y = DEATHNOTICE_TOP + 2 + (gap * i); + + texty = y + 4; int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId; - x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left); + x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left) - 4; if ( !rgDeathNoticeList[i].iSuicide ) { @@ -127,7 +134,7 @@ int CHudDeathNotice :: Draw( float flTime ) // Draw killers name if ( rgDeathNoticeList[i].KillerColor ) gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] ); - x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller ); + x = 5 + DrawConsoleString( x, texty, rgDeathNoticeList[i].szKiller ); } r = 255; g = 80; b = 0; @@ -147,7 +154,7 @@ int CHudDeathNotice :: Draw( float flTime ) { if ( rgDeathNoticeList[i].VictimColor ) gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] ); - x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim ); + x = DrawConsoleString( x, texty, rgDeathNoticeList[i].szVictim ); } } } diff --git a/cl_dll/ev_hldm.cpp b/cl_dll/ev_hldm.cpp index 892f2ab..91aed0c 100644 --- a/cl_dll/ev_hldm.cpp +++ b/cl_dll/ev_hldm.cpp @@ -97,6 +97,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v { // hit the world, try to play sound based on texture material type char chTextureType = CHAR_TEX_CONCRETE; + cl_entity_t *cl_entity = NULL; float fvol; float fvolbar; char *rgsz[4]; @@ -115,12 +116,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v chTextureType = 0; // Player - if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) - { - // hit body - chTextureType = CHAR_TEX_FLESH; - } - else if ( entity == 0 ) + if ( entity == 0 ) { // get texture from entity or world (world is ent(0)) pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); @@ -149,6 +145,20 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v chTextureType = PM_FindTextureType( szbuffer ); } } + else + { + // JoshA: Look up the entity and find the EFLAG_FLESH_SOUND flag. + // This broke at some point then TF:C added prediction. + // + // It used to use Classify of pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE + // to determine what sound to play, but that's server side and isn't available on the client + // and got lost in the translation to that. + // Now the server will replicate that state via an eflag. + cl_entity = gEngfuncs.GetEntityByIndex( entity ); + + if ( cl_entity && !!( cl_entity->curstate.eflags & EFLAG_FLESH_SOUND ) ) + chTextureType = CHAR_TEX_FLESH; + } switch (chTextureType) { @@ -400,7 +410,16 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + // JoshA: Changed from PM_STUDIO_BOX to PM_NORMAL in prediction code as otherwise if you hit an NPC or player's + // bounding box but not one of their hitboxes, the shot won't hit on the server but it will + // play a hit sound on the client and not make a decal (as if it hit the NPC/player). + // We should mirror the way the server does the test here as close as possible. + // + // I initially thought I was just fixing some stupid Half-Life bug but no, + // this is *the* root cause of all the ghost shot bad prediction bugs in Half-Life Deathmatch! + // + // Also... CStrike was always using PM_NORMAL for all of these so it didn't have the problem. + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr ); tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); @@ -912,7 +931,7 @@ void EV_FireGauss( event_args_t *args ) gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_NORMAL, -1, &tr ); gEngfuncs.pEventAPI->EV_PopPMStates(); @@ -1034,7 +1053,7 @@ void EV_FireGauss( event_args_t *args ) gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr ); + gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_NORMAL, -1, &beam_tr ); if ( !beam_tr.allsolid ) { @@ -1043,7 +1062,7 @@ void EV_FireGauss( event_args_t *args ) // trace backwards to find exit point - gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr ); + gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_NORMAL, -1, &beam_tr ); VectorSubtract( beam_tr.endpos, tr.endpos, delta ); @@ -1239,7 +1258,7 @@ void EV_FireCrossbow2( event_args_t *args ) // Now add in all of the players. gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr ); //We hit something if ( tr.fraction < 1.0 ) @@ -1444,7 +1463,7 @@ void EV_EgonFire( event_args_t *args ) gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_NORMAL, -1, &tr ); gEngfuncs.pEventAPI->EV_PopPMStates(); diff --git a/cl_dll/geiger.cpp b/cl_dll/geiger.cpp index 9944267..8fa1407 100644 --- a/cl_dll/geiger.cpp +++ b/cl_dll/geiger.cpp @@ -68,10 +68,14 @@ int CHudGeiger::Draw (float flTime) int rg[3]; int i; - if (m_iGeigerRange <= 800 && m_iGeigerRange > 0) + if (m_iGeigerRange < 1000 && m_iGeigerRange > 0) { // peicewise linear is better than continuous formula for this - if (m_iGeigerRange > 600) + if (m_iGeigerRange > 800) + { + pct = 0; //Con_Printf ( "range > 800\n"); + } + else if (m_iGeigerRange > 600) { pct = 2; flvol = 0.4; //Con_Printf ( "range > 600\n"); diff --git a/cl_dll/health.cpp b/cl_dll/health.cpp index 67b3a76..bb425d4 100644 --- a/cl_dll/health.cpp +++ b/cl_dll/health.cpp @@ -217,6 +217,7 @@ int CHudHealth::Draw(float flTime) SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross)); x = CrossWidth + HealthWidth / 2; + y += (int)(gHUD.m_iFontHeight * 0.2f); x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b); @@ -307,49 +308,49 @@ int CHudHealth::DrawPain(float flTime) if (m_fAttackFront > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackFront, 0.5 ); + shade = a * max( m_fAttackFront, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2; y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3; SPR_DrawAdditive(0, x, y, NULL); - m_fAttackFront = max( 0, m_fAttackFront - fFade ); + m_fAttackFront = max( 0.0f, m_fAttackFront - fFade ); } else m_fAttackFront = 0; if (m_fAttackRight > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackRight, 0.5 ); + shade = a * max( m_fAttackRight, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2; y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2; SPR_DrawAdditive(1, x, y, NULL); - m_fAttackRight = max( 0, m_fAttackRight - fFade ); + m_fAttackRight = max( 0.0f, m_fAttackRight - fFade ); } else m_fAttackRight = 0; if (m_fAttackRear > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackRear, 0.5 ); + shade = a * max( m_fAttackRear, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2; y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2; SPR_DrawAdditive(2, x, y, NULL); - m_fAttackRear = max( 0, m_fAttackRear - fFade ); + m_fAttackRear = max( 0.0f, m_fAttackRear - fFade ); } else m_fAttackRear = 0; if (m_fAttackLeft > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackLeft, 0.5 ); + shade = a * max( m_fAttackLeft, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); @@ -357,7 +358,7 @@ int CHudHealth::DrawPain(float flTime) y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2; SPR_DrawAdditive(3, x, y, NULL); - m_fAttackLeft = max( 0, m_fAttackLeft - fFade ); + m_fAttackLeft = max( 0.0f, m_fAttackLeft - fFade ); } else m_fAttackLeft = 0; diff --git a/cl_dll/hl/hl_baseentity.cpp b/cl_dll/hl/hl_baseentity.cpp index 7b4a0b9..0c2d539 100644 --- a/cl_dll/hl/hl_baseentity.cpp +++ b/cl_dll/hl/hl_baseentity.cpp @@ -86,7 +86,9 @@ void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const c int CBaseToggle::Restore( class CRestore & ) { return 1; } int CBaseToggle::Save( class CSave & ) { return 1; } void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { } - +void CBaseToggle::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { } +void CBaseToggle::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { } +void CBaseToggle::SentenceStop( void ) { } // CGrenade Stubs void CGrenade::BounceSound( void ) { } void CGrenade::Explode( Vector, Vector ) { } @@ -206,9 +208,6 @@ BOOL CBaseMonster :: FindLateralCover ( const Vector &vecThreat, const Vector &v Vector CBaseMonster :: ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; } BOOL CBaseMonster :: FacingIdeal( void ) { return FALSE; } BOOL CBaseMonster :: FCanActiveIdle ( void ) { return FALSE; } -void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { } -void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { } -void CBaseMonster::SentenceStop( void ) { } void CBaseMonster::CorpseFallThink( void ) { } void CBaseMonster :: MonsterInitDead( void ) { } BOOL CBaseMonster :: BBoxFlat ( void ) { return TRUE; } diff --git a/cl_dll/hl/hl_weapons.cpp b/cl_dll/hl/hl_weapons.cpp index f6a5044..d8215cb 100644 --- a/cl_dll/hl/hl_weapons.cpp +++ b/cl_dll/hl/hl_weapons.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2002, Valve LLC. All rights reserved. * @@ -811,6 +811,8 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm player.m_afButtonPressed = buttonsChanged & cmd->buttons; // The ones not down are "released" player.m_afButtonReleased = buttonsChanged & (~cmd->buttons); + player.pev->v_angle = cmd->viewangles; + player.pev->origin = from->client.origin; // Set player variables that weapons code might check/alter player.pev->button = cmd->buttons; diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index d376e0e..4923f7b 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -81,7 +81,8 @@ static CHLVoiceStatusHelper g_VoiceStatusHelper; extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount); -extern cvar_t *sensitivity; +extern float IN_GetMouseSensitivity(); + cvar_t *cl_lw = NULL; void ShutdownInput (void); @@ -326,8 +327,9 @@ void CHud :: Init( void ) m_iLogo = 0; m_iFOV = 0; - CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 ); - default_fov = CVAR_CREATE( "default_fov", "90", 0 ); + CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", FCVAR_ARCHIVE ); + CVAR_CREATE( "cl_autowepswitch", "1", FCVAR_USERINFO|FCVAR_ARCHIVE ); + default_fov = CVAR_CREATE( "default_fov", "90", FCVAR_ARCHIVE ); m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); @@ -371,6 +373,9 @@ void CHud :: Init( void ) ServersInit(); MsgFunc_ResetHUD(0, 0, NULL ); + + gEngfuncs.pfnClientCmd("richpresence_gamemode\n"); // reset + gEngfuncs.pfnClientCmd("richpresence_update\n"); } // CHud destructor @@ -425,10 +430,15 @@ void CHud :: VidInit( void ) m_hsprLogo = 0; m_hsprCursor = 0; - if (ScreenWidth < 640) - m_iRes = 320; - else + if (ScreenWidth > 2560 && ScreenHeight > 1600) + m_iRes = 2560; + else if (ScreenWidth >= 1280 && ScreenHeight > 720) + m_iRes = 1280; + else if (ScreenWidth >= 640) m_iRes = 640; + else + m_iRes = 320; + // Only load this once if ( !m_pSpriteList ) @@ -653,7 +663,7 @@ int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf) else { // set a new sensitivity that is proportional to the change from the FOV default - m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); + m_flMouseSensitivity = IN_GetMouseSensitivity() * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); } return 1; diff --git a/cl_dll/hud.h b/cl_dll/hud.h index 96e0df2..3519999 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -438,6 +438,7 @@ private: int m_HUD_title_life; int m_HUD_title_half; + bool m_bEndAfterMessage; }; // diff --git a/cl_dll/hud_bench.cpp b/cl_dll/hud_bench.cpp index 71dd87e..8f69e66 100644 --- a/cl_dll/hud_bench.cpp +++ b/cl_dll/hud_bench.cpp @@ -146,8 +146,8 @@ int CHudBenchmark::MsgFunc_Bench(const char *pszName, int iSize, void *pbuf) m_fReceiveTime = gHUD.m_flTime; m_StoredLatency = ( m_fReceiveTime - m_fSendTime ); - m_StoredLatency = min( 1.0, m_StoredLatency ); - m_StoredLatency = max( 0.0, m_StoredLatency ); + m_StoredLatency = min( 1.0f, m_StoredLatency ); + m_StoredLatency = max( 0.0f, m_StoredLatency ); m_StoredPacketLoss = 0.0; @@ -286,8 +286,8 @@ void CHudBenchmark::Think( void ) float switch_time; float total_time; - latency = max( 0.0, latency ); - latency = min( 1.0, latency ); + latency = max( 0.0f, latency ); + latency = min( 1.0f, latency ); total_time = Bench_GetSwitchTime(); total_time -= 2.0; @@ -341,8 +341,8 @@ void CHudBenchmark::Think( void ) // Only takes 1/2 time to get up to maximum speed frac *= 2.0; - frac = max( 0.0, frac ); - frac = min( 1.0, frac ); + frac = max( 0.0f, frac ); + frac = min( 1.0f, frac ); m_nObjects = (int)(NUM_BENCH_OBJ * frac); } diff --git a/cl_dll/hud_msg.cpp b/cl_dll/hud_msg.cpp index ce72cc3..e478d59 100644 --- a/cl_dll/hud_msg.cpp +++ b/cl_dll/hud_msg.cpp @@ -101,6 +101,13 @@ int CHud :: MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf ) BEGIN_READ( pbuf, iSize ); m_Teamplay = READ_BYTE(); + if ( m_Teamplay ) + gEngfuncs.pfnClientCmd("richpresence_gamemode Teamplay\n"); + else + gEngfuncs.pfnClientCmd("richpresence_gamemode\n"); // reset + + gEngfuncs.pfnClientCmd("richpresence_update\n"); + return 1; } diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index ecba3a1..6b3593f 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -36,7 +36,7 @@ extern int g_iVisibleMouse; float HUD_GetFOV( void ); -extern cvar_t *sensitivity; +extern float IN_GetMouseSensitivity(); // Think void CHud::Think(void) @@ -75,13 +75,13 @@ void CHud::Think(void) else { // set a new sensitivity that is proportional to the change from the FOV default - m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)default_fov->value) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); + m_flMouseSensitivity = IN_GetMouseSensitivity() * ( (float)newfov / (float) max( default_fov->value, 90 ) ) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); } // think about default fov if ( m_iFOV == 0 ) { // only let players adjust up in fov, and only if they are not overriden by something else - m_iFOV = max( default_fov->value, 90 ); + m_iFOV = max( default_fov->value, 90 ); } if ( gEngfuncs.IsSpectateOnly() ) diff --git a/cl_dll/hud_spectator.cpp b/cl_dll/hud_spectator.cpp index e70f194..5b819e2 100644 --- a/cl_dll/hud_spectator.cpp +++ b/cl_dll/hud_spectator.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============ // // Purpose: // @@ -210,7 +210,8 @@ void UTIL_StringToVector( float * pVector, const char *pString ) char *pstr, *pfront, tempString[128]; int j; - strcpy( tempString, pString ); + strncpy( tempString, pString, sizeof( tempString ) ); + tempString[ sizeof( tempString ) - 1 ] = '\0'; pstr = pfront = tempString; for ( j = 0; j < 3; j++ ) @@ -812,7 +813,7 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf ) break; case DRC_CMD_STUFFTEXT: - EngineClientCmd( READ_STRING() ); + EngineFilteredClientCmd( READ_STRING() ); break; case DRC_CMD_CAMPATH: diff --git a/cl_dll/inputw32.cpp b/cl_dll/inputw32.cpp index 3c9e886..94f5a75 100644 --- a/cl_dll/inputw32.cpp +++ b/cl_dll/inputw32.cpp @@ -23,6 +23,7 @@ #include "view.h" #include "Exports.h" +#include #include #include @@ -55,8 +56,6 @@ extern cvar_t *cl_pitchspeed; extern cvar_t *cl_movespeedkey; -static double s_flRawInputUpdateTime = 0.0f; -static bool m_bRawInput = false; static bool m_bMouseThread = false; extern globalvars_t *gpGlobals; @@ -78,6 +77,13 @@ static cvar_t *m_customaccel_exponent; // if threaded mouse is enabled then the time to sleep between polls static cvar_t *m_mousethread_sleep; +static cvar_t* m_rawinput = nullptr; + +static bool IN_UseRawInput() +{ + return m_rawinput ? ( m_rawinput->value != 0 ) : false; +} + int mouse_buttons; int mouse_oldbuttonstate; POINT current_pos; @@ -138,6 +144,7 @@ cvar_t *joy_advaxisz; cvar_t *joy_advaxisr; cvar_t *joy_advaxisu; cvar_t *joy_advaxisv; +cvar_t *joy_supported; cvar_t *joy_forwardthreshold; cvar_t *joy_sidethreshold; cvar_t *joy_pitchthreshold; @@ -149,7 +156,7 @@ cvar_t *joy_yawsensitivity; cvar_t *joy_wwhack1; cvar_t *joy_wwhack2; -int joy_avail, joy_advancedinit, joy_haspov; +int joy_avail = 0, joy_advancedinit, joy_haspov; #ifdef _WIN32 DWORD s_hMouseThreadId = 0; @@ -158,6 +165,7 @@ HANDLE s_hMouseQuitEvent = 0; HANDLE s_hMouseDoneQuitEvent = 0; #endif + /* =========== Force_CenterView_f @@ -344,6 +352,28 @@ void IN_GetMousePos( int *mx, int *my ) gEngfuncs.GetMousePosition( mx, my ); } +/* +=========== +IN_GetMouseSensitivity + +Get mouse sensitivity with sanitization +=========== +*/ +float IN_GetMouseSensitivity() +{ + // Absurdly high sensitivity values can cause the game to hang, so clamp + if ( sensitivity->value > 10000.0 ) + { + gEngfuncs.Cvar_SetValue( "sensitivity", 10000.0 ); + } + else if ( sensitivity->value < 0.01 ) + { + gEngfuncs.Cvar_SetValue( "sensitivity", 0.01 ); + } + + return sensitivity->value; +} + /* =========== IN_ResetMouse @@ -355,22 +385,33 @@ void IN_ResetMouse( void ) { // no work to do in SDL #ifdef _WIN32 - if ( !m_bRawInput && mouseactive && gEngfuncs.GetWindowCenterX && gEngfuncs.GetWindowCenterY ) + if ( !IN_UseRawInput() && mouseactive && gEngfuncs.GetWindowCenterX && gEngfuncs.GetWindowCenterY ) { SetCursorPos ( gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY() ); ThreadInterlockedExchange( &old_mouse_pos.x, gEngfuncs.GetWindowCenterX() ); ThreadInterlockedExchange( &old_mouse_pos.y, gEngfuncs.GetWindowCenterY() ); } - - if ( gpGlobals && gpGlobals->time - s_flRawInputUpdateTime > 1.0f ) - { - s_flRawInputUpdateTime = gpGlobals->time; - m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) != 0; - } #endif } + +/* +=========== +IN_ResetRelativeMouseState +=========== +*/ +void IN_ResetRelativeMouseState(void) +{ + if ( IN_UseRawInput() ) + { + SDL_PumpEvents(); + int deltaX, deltaY; + SDL_GetRelativeMouseState(&deltaX, &deltaY); + } +} + + /* =========== IN_MouseEvent @@ -414,7 +455,7 @@ void IN_ScaleMouse( float *x, float *y ) float my = *y; // This is the default sensitivity - float mouse_senstivity = ( gHUD.GetSensitivity() != 0 ) ? gHUD.GetSensitivity() : sensitivity->value; + float mouse_senstivity = ( gHUD.GetSensitivity() != 0 ) ? gHUD.GetSensitivity() : IN_GetMouseSensitivity(); // Using special accleration values if ( m_customaccel->value != 0 ) @@ -474,7 +515,7 @@ void IN_MouseMove ( float frametime, usercmd_t *cmd) { int deltaX, deltaY; #ifdef _WIN32 - if ( !m_bRawInput ) + if ( !IN_UseRawInput() ) { if ( m_bMouseThread ) { @@ -497,7 +538,7 @@ void IN_MouseMove ( float frametime, usercmd_t *cmd) } #ifdef _WIN32 - if ( !m_bRawInput ) + if ( !IN_UseRawInput() ) { if ( m_bMouseThread ) { @@ -598,7 +639,7 @@ void CL_DLLEXPORT IN_Accumulate (void) if (mouseactive) { #ifdef _WIN32 - if ( !m_bRawInput ) + if ( !IN_UseRawInput() ) { if ( !m_bMouseThread ) { @@ -649,41 +690,56 @@ void IN_StartupJoystick (void) // abort startup if user requests no joystick if ( gEngfuncs.CheckParm ("-nojoy", NULL ) ) return; - - // assume no joystick - joy_avail = 0; + + static float flLastCheck = 0.0f; + if ( flLastCheck > 0.0f && (gEngfuncs.GetAbsoluteTime()-flLastCheck) < 1.0f ) + return; + + //gEngfuncs.Con_Printf("IN_StartupJoystick, %f\n", flLastCheck); + + flLastCheck = gEngfuncs.GetAbsoluteTime(); int nJoysticks = SDL_NumJoysticks(); if ( nJoysticks > 0 ) { - for ( int i = 0; i < nJoysticks; i++ ) + if ( s_pJoystick == NULL ) { - if ( SDL_IsGameController( i ) ) + for ( int i = 0; i < nJoysticks; i++ ) { - s_pJoystick = SDL_GameControllerOpen( i ); - if ( s_pJoystick ) + if ( SDL_IsGameController( i ) ) { - //save the joystick's number of buttons and POV status - joy_numbuttons = SDL_CONTROLLER_BUTTON_MAX; - joy_haspov = 0; - - // old button and POV states default to no buttons pressed - joy_oldbuttonstate = joy_oldpovstate = 0; - - // mark the joystick as available and advanced initialization not completed - // this is needed as cvars are not available during initialization - gEngfuncs.Con_Printf ("joystick found\n\n", SDL_GameControllerName(s_pJoystick)); - joy_avail = 1; - joy_advancedinit = 0; - break; - } + s_pJoystick = SDL_GameControllerOpen( i ); + if ( s_pJoystick ) + { + //save the joystick's number of buttons and POV status + joy_numbuttons = SDL_CONTROLLER_BUTTON_MAX; + joy_haspov = 0; + + // old button and POV states default to no buttons pressed + joy_oldbuttonstate = joy_oldpovstate = 0; + + // mark the joystick as available and advanced initialization not completed + // this is needed as cvars are not available during initialization + gEngfuncs.Con_Printf ("joystick found %s\n\n", SDL_GameControllerName(s_pJoystick)); + joy_avail = 1; + joy_advancedinit = 0; + break; + } + } } } } else { - gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n"); + if ( s_pJoystick ) + SDL_GameControllerClose( s_pJoystick ); + s_pJoystick = NULL; + if ( joy_avail ) + { + joy_avail = 0; + gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n"); + } } } @@ -806,12 +862,14 @@ void IN_Commands (void) { key_index = (i < 4) ? K_JOY1 : K_AUX1; gEngfuncs.Key_Event (key_index + i, 1); + //gEngfuncs.Con_Printf ("Button %d pressed\n", i); } if ( !(buttonstate & (1<value) { @@ -1062,7 +1123,7 @@ IN_Init void IN_Init (void) { m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE ); - sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE ); // user mouse sensitivity setting. + sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE | FCVAR_FILTERSTUFFTEXT ); // user mouse sensitivity setting. in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE ); joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 ); @@ -1073,6 +1134,7 @@ void IN_Init (void) joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 ); joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 ); joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 ); + joy_supported = gEngfuncs.pfnRegisterVariable ( "joysupported", "1", 0 ); joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 ); joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 ); joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 ); @@ -1089,12 +1151,13 @@ void IN_Init (void) m_customaccel_max = gEngfuncs.pfnRegisterVariable ( "m_customaccel_max", "0", FCVAR_ARCHIVE ); m_customaccel_exponent = gEngfuncs.pfnRegisterVariable ( "m_customaccel_exponent", "1", FCVAR_ARCHIVE ); + m_rawinput = gEngfuncs.pfnGetCvarPointer("m_rawinput"); + #ifdef _WIN32 - m_bRawInput = CVAR_GET_FLOAT( "m_rawinput" ) > 0; m_bMouseThread = gEngfuncs.CheckParm ("-mousethread", NULL ) != NULL; m_mousethread_sleep = gEngfuncs.pfnRegisterVariable ( "m_mousethread_sleep", "10", FCVAR_ARCHIVE ); - if ( !m_bRawInput && m_bMouseThread && m_mousethread_sleep ) + if ( !IN_UseRawInput() && m_bMouseThread && m_mousethread_sleep ) { s_mouseDeltaX = s_mouseDeltaY = 0; diff --git a/cl_dll/menu.cpp b/cl_dll/menu.cpp index 82f991a..994abeb 100644 --- a/cl_dll/menu.cpp +++ b/cl_dll/menu.cpp @@ -143,6 +143,10 @@ int CHudMenu :: Draw( float flTime ) if ( gViewPort && gViewPort->IsScoreBoardVisible() ) return 1; + SCREENINFO screenInfo; + screenInfo.iSize = sizeof( SCREENINFO ); + gEngfuncs.pfnGetScreenInfo( &screenInfo ); + // draw the menu, along the left-hand side of the screen // count the number of newlines @@ -154,8 +158,10 @@ int CHudMenu :: Draw( float flTime ) nlc++; } + int nFontHeight = max(12, screenInfo.iCharHeight); + // center it - int y = (ScreenHeight/2) - ((nlc/2)*12) - 40; // make sure it is above the say text + int y = (ScreenHeight/2) - ((nlc/2)* nFontHeight) - (3 * nFontHeight + nFontHeight / 3); // make sure it is above the say text menu_r = 255; menu_g = 255; @@ -175,7 +181,7 @@ int CHudMenu :: Draw( float flTime ) { menu_ralign = FALSE; menu_x = 20; - y += (12); + y += nFontHeight; sptr++; } diff --git a/cl_dll/meson.build b/cl_dll/meson.build new file mode 100644 index 0000000..25990fb --- /dev/null +++ b/cl_dll/meson.build @@ -0,0 +1,175 @@ +hl_client_src = [ + 'hud_spectator.cpp', + '../game_shared/vgui_scrollbar2.cpp', + '../game_shared/vgui_slider2.cpp', + 'vgui_SpectatorPanel.cpp', + '../dlls/crossbow.cpp', + '../dlls/crowbar.cpp', + '../dlls/egon.cpp', + 'ev_hldm.cpp', + '../dlls/gauss.cpp', + '../dlls/handgrenade.cpp', + 'hl/hl_baseentity.cpp', + 'hl/hl_events.cpp', + 'hl/hl_objects.cpp', + 'hl/hl_weapons.cpp', + '../dlls/wpn_shared/hl_wpn_glock.cpp', + '../dlls/hornetgun.cpp', + '../dlls/mp5.cpp', + '../dlls/python.cpp', + '../dlls/rpg.cpp', + '../dlls/satchel.cpp', + '../dlls/shotgun.cpp', + '../dlls/squeakgrenade.cpp', + '../dlls/tripmine.cpp', + 'ammo.cpp', + 'ammo_secondary.cpp', + 'ammohistory.cpp', + 'battery.cpp', + 'cdll_int.cpp', + 'com_weapons.cpp', + 'death.cpp', + 'demo.cpp', + 'entity.cpp', + 'ev_common.cpp', + 'events.cpp', + 'flashlight.cpp', + 'GameStudioModelRenderer.cpp', + 'geiger.cpp', + 'health.cpp', + 'hud.cpp', + 'hud_bench.cpp', + 'hud_benchtrace.cpp', + 'hud_msg.cpp', + 'hud_redraw.cpp', + 'hud_servers.cpp', + 'hud_update.cpp', + 'in_camera.cpp', + 'input.cpp', + 'inputw32.cpp', + '../public/interface.cpp', + 'interpolation.cpp', + 'menu.cpp', + 'message.cpp', + '../common/parsemsg.cpp', + '../pm_shared/pm_debug.c', + '../pm_shared/pm_math.c', + '../pm_shared/pm_shared.c', + 'saytext.cpp', + 'status_icons.cpp', + 'statusbar.cpp', + 'studio_util.cpp', + 'StudioModelRenderer.cpp', + 'text_message.cpp', + 'train.cpp', + 'tri.cpp', + 'util.cpp', + '../game_shared/vgui_checkbutton2.cpp', + 'vgui_ClassMenu.cpp', + 'vgui_ControlConfigPanel.cpp', + 'vgui_CustomObjects.cpp', + '../game_shared/vgui_grid.cpp', + '../game_shared/vgui_helpers.cpp', + 'vgui_int.cpp', + '../game_shared/vgui_listbox.cpp', + '../game_shared/vgui_loadtga.cpp', + 'vgui_MOTDWindow.cpp', + 'vgui_SchemeManager.cpp', + 'vgui_ScorePanel.cpp', + 'vgui_ServerBrowser.cpp', + 'vgui_TeamFortressViewport.cpp', + 'vgui_TeamMenu.cpp', + 'view.cpp', + '../game_shared/voice_banmgr.cpp', + 'voice_status.cpp', + 'ammo.h', + 'ammohistory.h', + 'camera.h', + 'cl_dll.h', + 'cl_util.h', + 'com_weapons.h', + 'demo.h', + 'ev_hldm.h', + 'eventscripts.h', + 'GameStudioModelRenderer.h', + 'health.h', + 'hud.h', + 'hud_servers.h', + 'hud_servers_priv.h', + 'hud_spectator.h', + '../public/cl_dll/IGameClientExports.h', + 'in_defs.h', + 'interpolation.h', + 'kbutton.h', + '../common/parsemsg.h', + '../pm_shared/pm_debug.h', + '../pm_shared/pm_defs.h', + '../pm_shared/pm_info.h', + '../pm_shared/pm_materials.h', + '../pm_shared/pm_movevars.h', + '../pm_shared/pm_shared.h', + 'StudioModelRenderer.h', + 'tri.h', + 'util_vector.h', + 'vgui_ControlConfigPanel.h', + 'vgui_int.h', + 'vgui_SchemeManager.h', + 'vgui_ScorePanel.h', + '../game_shared/vgui_scrollbar2.h', + 'vgui_ServerBrowser.h', + '../game_shared/vgui_slider2.h', + 'vgui_SpectatorPanel.h', + 'view.h', + '../game_shared/voice_banmgr.h', + '../game_shared/voice_status.h', + 'wrect.h', +] + +hl_client_defines = [ + '-DVOXEL', + '-DQUAKE2', + '-DVALVE_DLL', + '-DCLIENT_DLL', + '-DCLIENT_WEAPONS', + '-DHL_DLL', +] + +hl_client_includes = include_directories([ + '.', + '../dlls', + '../pm_shared', + '../game_shared', + '../engine', + '../utils/vgui/include', +]) + +hl_client_deps = [ + vgui2_dep, + vgui_dep, + SDL2_dep, + ws2_32_dep, +] + +install_dir = '/valve/cl_dlls' +target_name = 'client' +hl_client_lib = shared_library(target_name, hl_client_src, + dependencies : hl_client_deps, + cpp_args : hl_client_defines, + c_args : hl_client_defines, + include_directories : [ hl_client_includes, goldsrc_includes ], + install : true, + install_dir : output_dir + install_dir, +) + +hl_client_dep = declare_dependency( + link_with : [ hl_client_lib ], +) + +# this doesn't run when we need it to; the vcxproj won't be generated yet........ thought REGEN might run it but nah +# cmd = join_paths(meson.current_build_dir(), '..\..\devtools\inject_post_build.bat') +# cs = run_command(cmd, [target_name, meson.current_build_dir(), install_dir], check: false) +# #message(cs.stdout()) + +cmd = join_paths(meson.current_build_dir(), '..\..\devtools\meson_set_outdir.bat') +cs = run_command(cmd, [target_name, meson.current_build_dir(), install_dir], check: false) +#message(cs.stdout()) \ No newline at end of file diff --git a/cl_dll/message.cpp b/cl_dll/message.cpp index deb40e3..199fb2c 100644 --- a/cl_dll/message.cpp +++ b/cl_dll/message.cpp @@ -20,6 +20,7 @@ #include "hud.h" #include "cl_util.h" +#include "commonmacros.h" #include #include #include "parsemsg.h" @@ -58,6 +59,7 @@ void CHudMessage::Reset( void ) memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages ); memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages ); + m_bEndAfterMessage = false; m_gameTitleTime = 0; m_pGameTitle = NULL; } @@ -147,13 +149,13 @@ void CHudMessage::MessageScanNextChar( void ) srcGreen = m_parms.pMessage->g1; srcBlue = m_parms.pMessage->b1; blend = 0; // Pure source - destRed = destGreen = destBlue = 0; switch( m_parms.pMessage->effect ) { // Fade-in / Fade-out case 0: case 1: + destRed = destGreen = destBlue = 0; blend = m_parms.fadeBlend; break; @@ -168,6 +170,7 @@ void CHudMessage::MessageScanNextChar( void ) { float deltaTime = m_parms.time - m_parms.charTime; + destRed = destGreen = destBlue = 0; if ( m_parms.time > m_parms.fadeTime ) { blend = m_parms.fadeBlend; @@ -285,7 +288,7 @@ void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time ) { m_parms.lineLength = 0; m_parms.width = 0; - while ( *pText && *pText != '\n' ) + while ( *pText && *pText != '\n' && m_parms.lineLength < ARRAYSIZE( line ) - 1 ) { unsigned char c = *pText; line[m_parms.lineLength] = c; @@ -402,6 +405,12 @@ int CHudMessage::Draw( float fTime ) { // The message is over m_pMessages[i] = NULL; + + if (m_bEndAfterMessage) + { + // leave game + gEngfuncs.pfnClientCmd("wait\nwait\nwait\nwait\nwait\nwait\nwait\ndisconnect\n"); + } } } } @@ -487,6 +496,14 @@ int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf ) char *pString = READ_STRING(); + bool bIsEnding = false; + const char *HL1_ENDING_STR = "END3"; + + if (strlen(pString) == strlen(HL1_ENDING_STR) && strcmp(HL1_ENDING_STR, pString) == 0) + { + m_bEndAfterMessage = true; + } + MessageAdd( pString, gHUD.m_flTime ); // Remember the time -- to fix up level transitions m_parms.time = gHUD.m_flTime; diff --git a/cl_dll/text_message.cpp b/cl_dll/text_message.cpp index 646c43e..680ba25 100644 --- a/cl_dll/text_message.cpp +++ b/cl_dll/text_message.cpp @@ -46,6 +46,7 @@ int CHudTextMessage::Init(void) // the new value is pushed into dst_buffer char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ) { + int len = buffer_size; char *dst = dst_buffer; for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- ) { @@ -85,7 +86,7 @@ char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, in } } - dst_buffer[buffer_size-1] = 0; // ensure null termination + dst_buffer[len-1] = 0; // ensure null termination return dst_buffer; } @@ -195,7 +196,7 @@ int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf case HUD_PRINTNOTIFY: psz[0] = 1; // mark this message to go into the notify buffer - safe_sprintf( psz+1, MSG_BUF_SIZE, msg_text, sstr1, sstr2, sstr3, sstr4 ); + safe_sprintf( psz+1, MSG_BUF_SIZE - 1, msg_text, sstr1, sstr2, sstr3, sstr4 ); ConsolePrint( ConvertCRtoNL( psz ) ); break; diff --git a/cl_dll/util.cpp b/cl_dll/util.cpp index 68566eb..3420ab9 100644 --- a/cl_dll/util.cpp +++ b/cl_dll/util.cpp @@ -118,15 +118,19 @@ void VectorMA (const float *veca, float scale, const float *vecb, float *vecc) HSPRITE LoadSprite(const char *pszName) { - int i; + int iRes; char sz[256]; - if (ScreenWidth < 640) - i = 320; + if (ScreenWidth > 2560 && ScreenHeight > 1600) + iRes = 2560; + else if (ScreenWidth >= 1280 && ScreenHeight > 720) + iRes = 1280; + else if (ScreenWidth >= 640) + iRes = 640; else - i = 640; + iRes = 320; - sprintf(sz, pszName, i); + sprintf(sz, pszName, iRes); return SPR_Load(sz); } diff --git a/cl_dll/vgui_TeamFortressViewport.cpp b/cl_dll/vgui_TeamFortressViewport.cpp index b0cdd28..3f716c3 100644 --- a/cl_dll/vgui_TeamFortressViewport.cpp +++ b/cl_dll/vgui_TeamFortressViewport.cpp @@ -78,6 +78,7 @@ int g_iUser3 = 0; #define SBOARD_INDENT_Y_400 20 void IN_ResetMouse( void ); +void IN_ResetRelativeMouseState( void ); extern CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ); extern float * GetClientColor( int clientIndex ); @@ -817,8 +818,7 @@ try // Get the button text pfile = gEngfuncs.COM_ParseFile(pfile, token); - strncpy( cText, token, 32 ); - cText[31] = '\0'; + CHudTextMessage::LocaliseTextString( token, cText, sizeof( cText ) ); // save off the last button text we've come across (for error reporting) strcpy( szLastButtonText, cText ); @@ -2081,6 +2081,12 @@ void TeamFortressViewport::UpdateCursorState() IN_ResetMouse(); } + if ( g_iVisibleMouse ) + { + //Clear any residual input so our camera doesn't jerk when dismissing the UI + IN_ResetRelativeMouseState(); + } + g_iVisibleMouse = false; App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_none) ); } diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index 796be73..edfaed6 100644 --- a/cl_dll/view.cpp +++ b/cl_dll/view.cpp @@ -199,8 +199,8 @@ float V_CalcBob ( struct ref_params_s *pparams ) bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value; bob = bob * 0.3 + bob * 0.7 * sin(cycle); - bob = min( bob, 4 ); - bob = max( bob, -7 ); + bob = min( bob, 4.0f ); + bob = max( bob, -7.0f ); return bob; } @@ -374,9 +374,6 @@ void V_CalcGunAngle ( struct ref_params_s *pparams ) // don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view. viewent->angles[PITCH] -= v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * (v_ipitch_level.value * 0.5); viewent->angles[YAW] -= v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; - - VectorCopy( viewent->angles, viewent->curstate.angles ); - VectorCopy( viewent->angles, viewent->latched.prevangles ); } /* @@ -827,6 +824,15 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams ) } } + // Update the latched view origin/angles here, this was + // previously done in V_CalcGunAngle but that happens + // before a bunch of other stuff happens, which nukes + // a bunch of the viewbob fx. + VectorCopy( view->origin, view->curstate.origin ); + VectorCopy( view->origin, view->latched.prevorigin ); + VectorCopy( view->angles, view->curstate.angles ); + VectorCopy( view->angles, view->latched.prevangles ); + lasttime = pparams->time; v_origin = pparams->vieworg; @@ -1679,7 +1685,7 @@ void V_DropPunchAngle ( float frametime, float *ev_punchangle ) len = VectorNormalize ( ev_punchangle ); len -= (10.0 + len * 0.5) * frametime; - len = max( len, 0.0 ); + len = max( len, 0.0f ); VectorScale ( ev_punchangle, len, ev_punchangle ); } @@ -1712,7 +1718,7 @@ void V_Init (void) v_centerspeed = gEngfuncs.pfnRegisterVariable( "v_centerspeed","500", 0 ); cl_bobcycle = gEngfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0 );// best default for my experimental gun wag (sjb) - cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", 0 );// best default for my experimental gun wag (sjb) + cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", FCVAR_ARCHIVE );// best default for my experimental gun wag (sjb) cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 ); cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 ); cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 ); diff --git a/common/const.h b/common/const.h index 6c5f35b..ef92e0e 100644 --- a/common/const.h +++ b/common/const.h @@ -116,6 +116,7 @@ // entity flags #define EFLAG_SLERP 1 // do studio interpolation of this entity +#define EFLAG_FLESH_SOUND 2 // JoshA: Whether this entity should sound like flesh. (ie. pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) // // temp entity events diff --git a/common/cvardef.h b/common/cvardef.h index 16044ab..ef6dccc 100644 --- a/common/cvardef.h +++ b/common/cvardef.h @@ -25,6 +25,10 @@ #define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). #define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log #define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar +#define FCVAR_PRIVILEGED (1<<10) // Not queryable/settable by unprivileged sources +#define FCVAR_FILTERSTUFFTEXT (1<<11) // Not queryable/settable if unprivileged and filterstufftext is enabled +#define FCVAR_FILTERCHARS (1<<12) // This cvar's string will be filtered for 'bad' characters (e.g. ';', '\n') +#define FCVAR_NOBADPATHS (1<<13) // This cvar's string cannot contain file paths that are above the current directory typedef struct cvar_s { diff --git a/common/mathlib.h b/common/mathlib.h index f5a0c37..c765eb5 100644 --- a/common/mathlib.h +++ b/common/mathlib.h @@ -108,8 +108,8 @@ void __inline restore_fpu_cw(void) _asm fldcw old_cw } #else +#define quick_ftol(f) ((int)(f)) #define set_fpu_cw() /* */ -#define quick_ftol(f) ftol(f) #define restore_fpu_cw() /* */ #endif diff --git a/common/netadr.h b/common/netadr.h index 304073c..31da390 100644 --- a/common/netadr.h +++ b/common/netadr.h @@ -19,21 +19,26 @@ #pragma once #endif +// JoshA: Unfortunately netadr_s is passed to clients for connectionless packets. +// No Valve mod uses them, but custom mods *might*, so not changing the start of this struct layout. +// It's very unlikely they touch this, but I'd like to play as safe as possible with all ABI etc for mod compat. +// If we want to add IPv6 someday, bung it at the end of netadr_s and leave ip + ipx alone. + typedef enum { NA_UNUSED, NA_LOOPBACK, NA_BROADCAST, NA_IP, - NA_IPX, - NA_BROADCAST_IPX, + NA_IPX, // deprecated + NA_BROADCAST_IPX, // deprecated } netadrtype_t; typedef struct netadr_s { netadrtype_t type; unsigned char ip[4]; - unsigned char ipx[10]; + unsigned char ipx[10]; // deprecated unsigned short port; } netadr_t; diff --git a/common/qfont.h b/common/qfont.h index 2fc8129..d6bbb87 100644 --- a/common/qfont.h +++ b/common/qfont.h @@ -21,7 +21,7 @@ // Font stuff #define NUM_GLYPHS 256 -// does not exist: // #include "basetypes.h" +#include "basetypes.h" typedef struct { @@ -35,7 +35,7 @@ typedef struct qfont_s int rowcount; int rowheight; charinfo fontinfo[ NUM_GLYPHS ]; - unsigned char data[4]; + byte data[4]; } qfont_t; #endif // qfont.h diff --git a/create_vs_projects.bat b/create_vs_projects.bat new file mode 100644 index 0000000..6df9754 --- /dev/null +++ b/create_vs_projects.bat @@ -0,0 +1,75 @@ +@if "%overbose%" == "" echo off + +REM ---------------------------------- +REM create_vs_projects.bat +REM create a usable sln and vcxproj for the goldsrc dlls +REM ---------------------------------- + +setlocal enabledelayedexpansion +goto Setup + +:Setup +set _PYTHON_=vpython + +set _VSVER_=2019 +set _BUILD_=DEBUG +set _BUILDTYPE_=debugoptimized + +REM TODO: better arg support here +if "%1" == "release" ( + set _BUILD_=RELEASE + set _BUILDTYPE_=release +) + +if "%_BUILD_%" == "DEBUG" ( + set _BUILDTYPE_=debugoptimized +) + +set "_PGM_FILES_=%ProgramFiles%" +if not exist "!_PGM_FILES_!\Microsoft Visual Studio\%_VSVER_%\" ( + set "_PGM_FILES_=%ProgramFiles(x86)%" +) + +set "VSINSTALLDIR=!_PGM_FILES_!\Microsoft Visual Studio\%_VSVER_%\BuildTools\" +set "_VC_VARS_=!VSINSTALLDIR!VC\Auxiliary\Build\vcvars32.bat" +if not exist "!_VC_VARS_!" ( + set "VSINSTALLDIR=!_PGM_FILES_!\Microsoft Visual Studio\%_VSVER_%\Professional\" + set "_VC_VARS_=!VSINSTALLDIR!VC\Auxiliary\Build\vcvars32.bat" +) +if not exist "!_VC_VARS_!" ( + set "VSINSTALLDIR=!_PGM_FILES_!\Microsoft Visual Studio\%_VSVER_%\Community\" + set "_VC_VARS_=!VSINSTALLDIR!VC\Auxiliary\Build\vcvars32.bat" +) +call "%_VC_VARS_%" + +call %_PYTHON_% --version 2>NUL +if errorlevel 1 ( + echo %_PYTHON_% not installed, using system python3. + set _PYTHON_=python3 + + call !_PYTHON_! --version 2>NUL + if errorlevel 1 ( + echo !_PYTHON_! ALSO not installed, using system python. + set _PYTHON_=python + ) +) +goto GenerateSLN + +:GenerateSLN +echo: +echo ------------------------------------------------------------------ +echo cleaning previous sln artifacts. +RD /S /Q "build-%_BUILDTYPE_%-sln" +echo ------------------------------------------------------------------ +call %_PYTHON_% devtools\meson\meson.py setup --buildtype %_BUILDTYPE_% --backend vs%_VSVER_% build-%_BUILDTYPE_%-sln + +REM now we post-process the meson output +call %_PYTHON_% devtools\vs_add_build_steps.py %_BUILDTYPE_% +call %_PYTHON_% devtools\vs_add_launch_config.py cl_dll\client.vcxproj hl %_BUILDTYPE_% + +goto End + +:End +echo: +echo ------------------------------------------------------------------ +echo Work Complete. \ No newline at end of file diff --git a/devtools/image_to_background.py b/devtools/image_to_background.py new file mode 100644 index 0000000..ba8f611 --- /dev/null +++ b/devtools/image_to_background.py @@ -0,0 +1,86 @@ +from PIL import Image +import sys +import os + +def convert_to_tiles(input_file, output_folder, tile_size=(256, 256)): + # Open the image + img = Image.open(input_file) + width, height = img.size + + # Create the output folder if it doesn't exist + if not os.path.exists(output_folder): + os.makedirs(output_folder) + + output_img_folder = os.path.join(output_folder, "background") + if not os.path.exists(output_img_folder): + os.makedirs(output_img_folder) + + row = 0 + col = 0 + + prefix = "21_9" + + # background txt file should look like: + # + # resolution 800 600 + # + # resource/background/800_1_a_loading.tga fit 0 0 + # resource/background/800_1_b_loading.tga fit 256 0 + # etc + + layout_file = f"resolution\t{width}\t{height}\n\n" + + # Loop through the image and extract tiles + for j in range(0, height, tile_size[1]): + row = row + 1 + col = 0 + + for i in range(0, width, tile_size[0]): + # Calculate the boundaries for the tile, making sure it doesn't exceed the image dimensions + right_bound = min(i + tile_size[0], width) + bottom_bound = min(j + tile_size[1], height) + + box = (i, j, right_bound, bottom_bound) + tile = img.crop(box) + + tile_char = chr(ord('a')+col) + target_file = f"{prefix}_{row}_{tile_char}_loading.tga" + tile_filename = os.path.join(output_img_folder, target_file) + tile.save(tile_filename) + print(f"Saved {tile_filename}") + + line = f"resource/background/{target_file}\tfit\t{i}\t{j}\n" + layout_file += line + + col = col + 1 + + print("------------------------------------------") + print(layout_file) + print("------------------------------------------") + + out_txt = os.path.join(output_folder, "BackgroundLayout.txt") + with open(out_txt, 'w') as f: + f.write(layout_file) + + out_txt = os.path.join(output_folder, "BackgroundLoadingLayout.txt") + with open(out_txt, 'w') as f: + f.write(layout_file) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python image_to_background.py path_to_image (psd/png/tga)") + sys.exit(1) + + img_path = sys.argv[1] + img_dir = os.path.dirname(img_path) + img_dir = os.path.join(img_dir, "Background") + + print(f"out dir: {img_dir}") + + convert_to_tiles(img_path, img_dir) + + #width, height, palette, data = read_spr(spr_path) + #save_as_png(spr_path + "__.png", width, height, palette, data) + + print(f"Converted {img_path}") + \ No newline at end of file diff --git a/devtools/meson/COPYING b/devtools/meson/COPYING new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/devtools/meson/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/devtools/meson/MANIFEST.in b/devtools/meson/MANIFEST.in new file mode 100644 index 0000000..9b72e82 --- /dev/null +++ b/devtools/meson/MANIFEST.in @@ -0,0 +1,19 @@ +graft test?cases +graft manual?tests +graft cross +graft data +graft graphics +graft man +graft tools +graft packaging +graft unittests + +include contributing.md +include COPYING +include README.md +include run_cross_test.py +include run_tests.py +include run_unittests.py +include run_meson_command_tests.py +include run_project_tests.py +include meson.py diff --git a/devtools/meson/PKG-INFO b/devtools/meson/PKG-INFO new file mode 100644 index 0000000..ff92e6c --- /dev/null +++ b/devtools/meson/PKG-INFO @@ -0,0 +1,33 @@ +Metadata-Version: 2.1 +Name: meson +Version: 1.2.2 +Summary: A high performance build system +Home-page: https://mesonbuild.com +Author: Jussi Pakkanen +Author-email: jpakkane@gmail.com +License: Apache License, Version 2.0 +Project-URL: Source, https://github.com/mesonbuild/meson +Keywords: meson,mesonbuild,build system,cmake +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Natural Language :: English +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: POSIX :: Linux +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Topic :: Software Development :: Build Tools +Requires-Python: >=3.7 +Provides-Extra: ninja +Provides-Extra: progress +Provides-Extra: typing +License-File: COPYING + +Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. diff --git a/devtools/meson/README.md b/devtools/meson/README.md new file mode 100644 index 0000000..f3a2657 --- /dev/null +++ b/devtools/meson/README.md @@ -0,0 +1,104 @@ +

+ +

+Meson® is a project to create the best possible next-generation +build system. + +#### Status + +[![PyPI](https://img.shields.io/pypi/v/meson.svg)](https://pypi.python.org/pypi/meson) +[![Build Status](https://dev.azure.com/jussi0947/jussi/_apis/build/status/mesonbuild.meson)](https://dev.azure.com/jussi0947/jussi/_build/latest?definitionId=1) +[![Codecov](https://codecov.io/gh/mesonbuild/meson/coverage.svg?branch=master)](https://codecov.io/gh/mesonbuild/meson/branch/master) + +#### Dependencies + + - [Python](https://python.org) (version 3.7 or newer) + - [Ninja](https://ninja-build.org) (version 1.8.2 or newer) + +Latest Meson version supporting previous Python versions: +- Python 3.6: **0.61.5** +- Python 3.5: **0.56.2** +- Python 3.4: **0.45.1** + +#### Installing from source + +Meson is available on [PyPi](https://pypi.python.org/pypi/meson), so +it can be installed with `pip3 install meson`. The exact command to +type to install with `pip` can vary between systems, be sure to use +the Python 3 version of `pip`. + +If you wish you can install it locally with the standard Python command: + +```console +python3 -m pip install meson +``` + +For builds using Ninja, Ninja can be downloaded directly from Ninja +[GitHub release page](https://github.com/ninja-build/ninja/releases) +or via [PyPi](https://pypi.python.org/pypi/ninja) + +```console +python3 -m pip install ninja +``` + +More on Installing Meson build can be found at the +[getting meson page](https://mesonbuild.com/Getting-meson.html). + +#### Creating a standalone script + +Meson can be run as a [Python zip +app](https://docs.python.org/3/library/zipapp.html). To generate the +executable run the following command: + + ./packaging/create_zipapp.py --outfile meson.pyz --interpreter '/usr/bin/env python3' + +#### Running + +Meson requires that you have a source directory and a build directory +and that these two are different. In your source root must exist a +file called `meson.build`. To generate the build system run this +command: + +`meson setup ` + +Depending on how you obtained Meson the command might also be called +`meson.py` instead of plain `meson`. In the rest of this document we +are going to use the latter form. + +You can omit either of the two directories, and Meson will substitute +the current directory and autodetect what you mean. This allows you to +do things like this: + +```console +cd +meson setup builddir +``` + +To compile, cd into your build directory and type `ninja`. To run unit +tests, type `ninja test`. + +More on running Meson build system commands can be found at the +[running meson page](https://mesonbuild.com/Running-Meson.html) +or by typing `meson --help`. + +#### Contributing + +We love code contributions. See the [contribution +page](https://mesonbuild.com/Contributing.html) on the website for +details. + + +#### IRC + +The channel to use is `#mesonbuild` either via Matrix ([web +interface][matrix_web]) or [OFTC IRC][oftc_irc]. + +[matrix_web]: https://app.element.io/#/room/#mesonbuild:matrix.org +[oftc_irc]: https://www.oftc.net/ + +#### Further info + +More information about the Meson build system can be found at the +[project's home page](https://mesonbuild.com). + +Meson is a registered trademark of ***Jussi Pakkanen***. diff --git a/devtools/meson/contributing.md b/devtools/meson/contributing.md new file mode 100644 index 0000000..3d1f4bc --- /dev/null +++ b/devtools/meson/contributing.md @@ -0,0 +1,8 @@ +## Contributing to the Meson build system + +Thank you for your interest in participating to the development! +A large fraction of Meson is contributed by people outside +the core team and we are *excited* to see what you do. + +**Contribution instructions can be found on the website** + @ https://mesonbuild.com/Contributing.html diff --git a/devtools/meson/cross/arm64cl.txt b/devtools/meson/cross/arm64cl.txt new file mode 100644 index 0000000..aa7398d --- /dev/null +++ b/devtools/meson/cross/arm64cl.txt @@ -0,0 +1,18 @@ +[binaries] +c = 'cl' +cpp = 'cl' +fc = 'false' +ar = 'lib' +windres = 'rc' + +[built-in options] +c_args = ['-DWINAPI_FAMILY=WINAPI_FAMILY_APP'] +c_link_args = ['-APPCONTAINER', 'WindowsApp.lib'] +cpp_args = ['-DWINAPI_FAMILY=WINAPI_FAMILY_APP'] +cpp_link_args = ['-APPCONTAINER', 'WindowsApp.lib'] + +[host_machine] +system = 'windows' +cpu_family = 'aarch64' +cpu = 'armv8' +endian = 'little' diff --git a/devtools/meson/cross/armcc.txt b/devtools/meson/cross/armcc.txt new file mode 100644 index 0000000..ae65c9e --- /dev/null +++ b/devtools/meson/cross/armcc.txt @@ -0,0 +1,20 @@ +# This file assumes that path to the arm compiler toolchain is added +# to the environment(PATH) variable, so that Meson can find +# the armcc, armlink and armar while building. +[binaries] +c = 'armcc' +cpp = 'armcc' +ar = 'armar' +strip = 'armar' + +[built-in options] +# The '--cpu' option with the appropriate target type should be mentioned +# to cross compile c/c++ code with armcc,. +c_args = ['--cpu=Cortex-M0plus'] +cpp_args = ['--cpu=Cortex-M0plus'] + +[host_machine] +system = 'bare metal' # Update with your system name - bare metal/OS. +cpu_family = 'arm' +cpu = 'Cortex-M0+' +endian = 'little' diff --git a/devtools/meson/cross/armclang-linux.txt b/devtools/meson/cross/armclang-linux.txt new file mode 100644 index 0000000..36927b8 --- /dev/null +++ b/devtools/meson/cross/armclang-linux.txt @@ -0,0 +1,31 @@ +# Using ARM compilers from Linux command line is tricky and +# not really well documented because they want you to use +# their IDE instead. +# +# First you need to do the full install with the IDE and set +# up license files et al. This may be possible from the command +# line. +# +# Then you need to do the following: +# +# Select toolchain by running /opt/arm/developmentstudio-2019.0/bin/select_default_toolchain +# Armcc is only available in toolchain version 5. +# Armclang is only available in toolchain version 6. +# Start shell with /opt/arm/developmentstudio-2019.0/bin/suite_exec zsh +# Now the compilers will work. + +[binaries] +# we could set exe_wrapper = qemu-arm-static but to test the case +# when cross compiled binaries can't be run we don't do that +c = ['/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armclang', '--target=aarch64-arm-none-eabi'] +#c = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler5.06u6/bin/armcc' +#cpp = '/usr/bin/arm-linux-gnueabihf-g++' +ar = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armar' +#strip = '/usr/arm-linux-gnueabihf/bin/strip' +#pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' + +[host_machine] +system = 'baremetal' +cpu_family = 'arm' +cpu = 'armv7' # Not sure if correct. +endian = 'little' diff --git a/devtools/meson/cross/armclang.txt b/devtools/meson/cross/armclang.txt new file mode 100644 index 0000000..aad7efc --- /dev/null +++ b/devtools/meson/cross/armclang.txt @@ -0,0 +1,20 @@ +# This file assumes that path to the arm compiler toolchain is added +# to the environment(PATH) variable, so that Meson can find +# the armclang, armlink and armar while building. +[binaries] +c = ['armclang', '--target=arm-arm-none-eabi'] +cpp = ['armclang', '--target=arm-arm-none-eabi'] +ar = 'armar' +strip = 'armar' + +[built-in options] +# The '--target', '-mcpu' options with the appropriate values should be mentioned +# to cross compile c/c++ code with armclang. +c_args = ['-mcpu=cortex-m0plus'] +cpp_args = ['-mcpu=cortex-m0plus'] + +[host_machine] +system = 'bare metal' # Update with your system name - bare metal/OS. +cpu_family = 'arm' +cpu = 'Cortex-M0+' +endian = 'little' diff --git a/devtools/meson/cross/c2000.txt b/devtools/meson/cross/c2000.txt new file mode 100644 index 0000000..61c0310 --- /dev/null +++ b/devtools/meson/cross/c2000.txt @@ -0,0 +1,28 @@ +# This file assumes that path to the Texas Instruments C20000 toolchain is added +# to the environment(PATH) variable, so that Meson can find +# cl2000 and ar2000 while building. +[binaries] +c = 'cl2000' +ar = 'ar2000' +strip = 'cl2000' + +[host_machine] +system = 'bare metal' +cpu_family = 'c2000' +cpu = 'c28x' +endian = 'little' + +[built-in options] +c_args = [ + '-v28', + '-ml', + '-mt'] +c_link_args = [ + '-z', + '--rom_model', + '\f28004x_flash.cmd'] +cpp_args = [] +cpp_link_args = [] + +[properties] +needs_exe_wrapper = true diff --git a/devtools/meson/cross/ccomp-armv7a.txt b/devtools/meson/cross/ccomp-armv7a.txt new file mode 100644 index 0000000..b90b96f --- /dev/null +++ b/devtools/meson/cross/ccomp-armv7a.txt @@ -0,0 +1,13 @@ +[binaries] +c = ['ccomp', '-target', 'armv7a-eabi'] +ar = 'ccomp' +strip = 'strip' + +[built-in options] +c_args = ['-fall'] + +[host_machine] +system = 'bare metal' # Update with your system name - bare metal/OS. +cpu_family = 'arm' +cpu = 'Cortex-A9' +endian = 'little' diff --git a/devtools/meson/cross/ccrx.txt b/devtools/meson/cross/ccrx.txt new file mode 100644 index 0000000..f1b536c --- /dev/null +++ b/devtools/meson/cross/ccrx.txt @@ -0,0 +1,22 @@ +# This file assumes that path to the Renesas CC-RX toolchain is added +# to the environment(PATH) variable, so that Meson can find +# ccrx and rlink while building. +[binaries] +c = 'ccrx' +cpp = 'ccrx' +ar = 'rlink' +strip = 'rlink' + +[built-in options] +# The '--cpu' option with the appropriate target type should be mentioned +# to cross compile c/c++ code with ccrx,. +c_args = ['-cpu=rx600'] +cpp_args = ['-cpu=rx600'] +c_link_args = [] +cpp_link_args = [] + +[host_machine] +system = 'bare metal' +cpu_family = 'rx' +cpu = 'rx600' +endian = 'little' diff --git a/devtools/meson/cross/iphone.txt b/devtools/meson/cross/iphone.txt new file mode 100644 index 0000000..b7149c1 --- /dev/null +++ b/devtools/meson/cross/iphone.txt @@ -0,0 +1,32 @@ +# This is a cross compilation file from OSX Yosemite to iPhone +# Apple keeps changing the location and names of files so +# these might not work for you. Use the googles and xcrun. + +[binaries] +c = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +cpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +objc = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +objcpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk'] +ar = 'ar' +strip = 'strip' + +[built-in options] +c_args = ['-miphoneos-version-min=11.0'] +cpp_args = ['-miphoneos-version-min=11.0'] +c_link_args = ['-miphoneos-version-min=11.0'] +cpp_link_args = ['-miphoneos-version-min=11.0'] +objc_args = ['-miphoneos-version-min=11.0'] +objcpp_args = ['-miphoneos-version-min=11.0'] + +[properties] +root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer' +has_function_printf = true +has_function_hfkerhisadf = false + +[host_machine] +system = 'darwin' +subsystem = 'ios' +kernel = 'xnu' +cpu_family = 'aarch64' +cpu = 'aarch64' +endian = 'little' diff --git a/devtools/meson/cross/linux-mingw-w64-32bit.json b/devtools/meson/cross/linux-mingw-w64-32bit.json new file mode 100644 index 0000000..4761111 --- /dev/null +++ b/devtools/meson/cross/linux-mingw-w64-32bit.json @@ -0,0 +1,7 @@ +{ + "file": "linux-mingw-w64-32bit.txt", + "tests": ["common", "cmake"], + "env": { + "WINEPATH": "/usr/lib/gcc/i686-w64-mingw32/9.2-posix;/usr/i686-w64-mingw32/bin;/usr/i686-w64-mingw32/lib" + } +} diff --git a/devtools/meson/cross/linux-mingw-w64-32bit.txt b/devtools/meson/cross/linux-mingw-w64-32bit.txt new file mode 100644 index 0000000..91ad9c5 --- /dev/null +++ b/devtools/meson/cross/linux-mingw-w64-32bit.txt @@ -0,0 +1,31 @@ +[binaries] +c = '/usr/bin/i686-w64-mingw32-gcc' +cpp = '/usr/bin/i686-w64-mingw32-g++' +objc = '/usr/bin/i686-w64-mingw32-gcc' +ar = '/usr/bin/i686-w64-mingw32-ar' +strip = '/usr/bin/i686-w64-mingw32-strip' +pkg-config = '/usr/bin/i686-w64-mingw32-pkg-config' +windres = '/usr/bin/i686-w64-mingw32-windres' +exe_wrapper = 'wine' +ld = '/usr/bin/i686-w64-mingw32-ld' +cmake = '/usr/bin/cmake' + +[properties] +# Directory that contains 'bin', 'lib', etc +root = '/usr/i686-w64-mingw32' +# Directory that contains 'bin', 'lib', etc for the toolchain and system libraries +sys_root = '/usr/i686-w64-mingw32/sys-root/mingw' + +[host_machine] +system = 'windows' +cpu_family = 'x86' +cpu = 'i686' +endian = 'little' + +[cmake] + +CMAKE_BUILD_WITH_INSTALL_RPATH = 'ON' +CMAKE_FIND_ROOT_PATH_MODE_PROGRAM = 'NEVER' +CMAKE_FIND_ROOT_PATH_MODE_LIBRARY = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_INCLUDE = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_PACKAGE = 'ONLY' diff --git a/devtools/meson/cross/linux-mingw-w64-64bit.json b/devtools/meson/cross/linux-mingw-w64-64bit.json new file mode 100644 index 0000000..df344da --- /dev/null +++ b/devtools/meson/cross/linux-mingw-w64-64bit.json @@ -0,0 +1,7 @@ +{ + "file": "linux-mingw-w64-64bit.txt", + "tests": ["common", "cmake"], + "env": { + "WINEPATH": "/usr/lib/gcc/x86_64-w64-mingw32/9.2-posix;/usr/x86_64-w64-mingw32/bin;/usr/x86_64-w64-mingw32/lib" + } +} diff --git a/devtools/meson/cross/linux-mingw-w64-64bit.txt b/devtools/meson/cross/linux-mingw-w64-64bit.txt new file mode 100644 index 0000000..08fa704 --- /dev/null +++ b/devtools/meson/cross/linux-mingw-w64-64bit.txt @@ -0,0 +1,30 @@ +[binaries] +c = '/usr/bin/x86_64-w64-mingw32-gcc' +cpp = '/usr/bin/x86_64-w64-mingw32-g++' +objc = '/usr/bin/x86_64-w64-mingw32-gcc' +ar = '/usr/bin/x86_64-w64-mingw32-ar' +strip = '/usr/bin/x86_64-w64-mingw32-strip' +pkg-config = '/usr/bin/x86_64-w64-mingw32-pkg-config' +windres = '/usr/bin/x86_64-w64-mingw32-windres' +exe_wrapper = 'wine' +cmake = '/usr/bin/cmake' + +[properties] +# Directory that contains 'bin', 'lib', etc +root = '/usr/x86_64-w64-mingw32' +# Directory that contains 'bin', 'lib', etc for the toolchain and system libraries +sys_root = '/usr/x86_64-w64-mingw32/sys-root/mingw' + +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[cmake] + +CMAKE_BUILD_WITH_INSTALL_RPATH = 'ON' +CMAKE_FIND_ROOT_PATH_MODE_PROGRAM = 'NEVER' +CMAKE_FIND_ROOT_PATH_MODE_LIBRARY = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_INCLUDE = 'ONLY' +CMAKE_FIND_ROOT_PATH_MODE_PACKAGE = 'ONLY' diff --git a/devtools/meson/cross/metrowerks-arm.txt b/devtools/meson/cross/metrowerks-arm.txt new file mode 100644 index 0000000..a13175b --- /dev/null +++ b/devtools/meson/cross/metrowerks-arm.txt @@ -0,0 +1,28 @@ +# This file assumes that the path to your Metrowerks Embedded ARM +# toolchain is added to the environment(PATH) variable, so that +# Meson can find the binaries while building. + +# You should also do one of the following to ensure Meson can +# locate the .lcf linker script: +# - Add the cross directory to PATH as well +# - Edit c_link_args and cpp_link_args with the full +# path to the .lcf file on your machine + +[binaries] +c = 'mwccarm' +c_ld = 'mwldarm' +cpp = 'mwccarm' +cpp_ld = 'mwldarm' +ar = 'mwldarm' +as = 'mwasmarm' + +[built-in options] +c_args = ['-lang', 'c99', '-D_NITRO', '-nosyspath'] +c_link_args = 'metrowerks.lcf' +cpp_args = ['-lang', 'c++', '-D_NITRO', '-nosyspath'] +cpp_link_args = 'metrowerks.lcf' + +[host_machine] +system = 'bare metal' +cpu_family = 'arm' +endian = 'little' \ No newline at end of file diff --git a/devtools/meson/cross/metrowerks-eppc.txt b/devtools/meson/cross/metrowerks-eppc.txt new file mode 100644 index 0000000..e5e0e42 --- /dev/null +++ b/devtools/meson/cross/metrowerks-eppc.txt @@ -0,0 +1,28 @@ +# This file assumes that the path to your Metrowerks toolchain +# of choice is added to the environment(PATH) variable, so that +# Meson can find the binaries while building. + +# You should also do one of the following to ensure Meson can +# locate the .lcf linker script: +# - Add the cross directory to PATH as well +# - Edit c_link_args and cpp_link_args with the full +# path to the lcf file on your machine + +[binaries] +c = 'mwcceppc' +c_ld = 'mwldeppc' +cpp = 'mwcceppc' +cpp_ld = 'mwldeppc' +ar = 'mwldeppc' +as = 'mwasmeppc' + +[built-in options] +c_args = ['-lang', 'c99', '-nosyspath'] +c_link_args = 'metrowerks.lcf' +cpp_args = ['-lang', 'c++', '-nosyspath'] +cpp_link_args = 'metrowerks.lcf' + +[host_machine] +system = 'bare metal' +cpu_family = 'ppc' +endian = 'little' \ No newline at end of file diff --git a/devtools/meson/cross/metrowerks.lcf b/devtools/meson/cross/metrowerks.lcf new file mode 100644 index 0000000..96d13af --- /dev/null +++ b/devtools/meson/cross/metrowerks.lcf @@ -0,0 +1,18 @@ +# General-purpose linker script for Metrowerks toolchains. +# This script will link a blank application. Its only purpose +# is to allow the toolchains to run Meson tests. To link an +# actual application, you need to write your own fine-tuned lcf. + +MEMORY { + TEST (RWX) : ORIGIN=0, LENGTH=0 +} + +SECTIONS { + .TEST:{ + * (.text) + * (.data) + * (.rodata) + * (.bss) + __startup=.; + } > TEST +} \ No newline at end of file diff --git a/devtools/meson/cross/msp430.txt b/devtools/meson/cross/msp430.txt new file mode 100644 index 0000000..839c90b --- /dev/null +++ b/devtools/meson/cross/msp430.txt @@ -0,0 +1,25 @@ +# This file assumes that path to the Texas Instruments MSP430 toolchain is added +# to the environment(PATH) variable, so that Meson can find +# cl430 and ar430 while building. +[binaries] +c = cl430 +ar = ar430 +strip = strip430 + +[host_machine] +system = 'baremetal' +cpu_family = 'msp430' +endian = 'little' + +[built-in options] +c_args = [ + '-vmsp', + '--printf_support=minimal'] +c_link_args = [ + '--rom_model', + '-llibc.a',] +cpp_args = [] +cpp_link_args = [] + +[properties] +needs_exe_wrapper = true diff --git a/devtools/meson/cross/none.txt b/devtools/meson/cross/none.txt new file mode 100644 index 0000000..9eadf97 --- /dev/null +++ b/devtools/meson/cross/none.txt @@ -0,0 +1,19 @@ +# native file used to make the build machine compiler unusable + +[host_machine] +system = 'none' +cpu_family = 'none' +cpu = 'none' +endian = 'little' + +[properties] + +[binaries] +c = ['false'] +cpp = ['false'] +fc = ['false'] +objc = ['false'] +objcpp = ['false'] +ar = ['false'] +pkg-config = ['false'] +cmake = ['false'] diff --git a/devtools/meson/cross/ownstdlib.txt b/devtools/meson/cross/ownstdlib.txt new file mode 100644 index 0000000..bdff6f4 --- /dev/null +++ b/devtools/meson/cross/ownstdlib.txt @@ -0,0 +1,13 @@ +# This is a setup for compiling a program that runs natively +# but uses a custom std lib. This test will only work on +# x86_64. + +[target_machine] +system = 'linux' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' + +[properties] + +c_stdlib = 'mylibc' # Subproject name diff --git a/devtools/meson/cross/tvos.txt b/devtools/meson/cross/tvos.txt new file mode 100644 index 0000000..6f6bfb5 --- /dev/null +++ b/devtools/meson/cross/tvos.txt @@ -0,0 +1,29 @@ +# This is a cross compilation file from OSX Yosemite to Apple tvOS +# Apple keeps changing the location and names of files so +# these might not work for you. Use the googles and xcrun. + +[binaries] +c = ['clang', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] +cpp = ['clang++', '-arch', 'arm64', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] +ar = 'ar' +strip = 'strip' + +[built-in options] +c_args = ['-mtvos-version-min=12.0'] +cpp_args = ['-mtvos-version-min=12.0'] +c_link_args = ['-mtvos-version-min=12.0'] +cpp_link_args = ['-mtvos-version-min=12.0'] + +[properties] +root = '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer' + +has_function_printf = true +has_function_hfkerhisadf = false + +[host_machine] +system = 'darwin' +subsystem = 'tvos' +kernel = 'xnu' +cpu_family = 'arm' +cpu = 'arm64' +endian = 'little' diff --git a/devtools/meson/cross/ubuntu-armhf.json b/devtools/meson/cross/ubuntu-armhf.json new file mode 100644 index 0000000..40f5619 --- /dev/null +++ b/devtools/meson/cross/ubuntu-armhf.json @@ -0,0 +1,5 @@ +{ + "file": "ubuntu-armhf.txt", + "tests": ["common"], + "env": {} +} diff --git a/devtools/meson/cross/ubuntu-armhf.txt b/devtools/meson/cross/ubuntu-armhf.txt new file mode 100644 index 0000000..6409e39 --- /dev/null +++ b/devtools/meson/cross/ubuntu-armhf.txt @@ -0,0 +1,29 @@ +[binaries] +# we could set exe_wrapper = qemu-arm-static but to test the case +# when cross compiled binaries can't be run we don't do that +c = ['/usr/bin/arm-linux-gnueabihf-gcc'] +cpp = ['/usr/bin/arm-linux-gnueabihf-g++'] +rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7'] +ar = '/usr/arm-linux-gnueabihf/bin/ar' +strip = '/usr/arm-linux-gnueabihf/bin/strip' +pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' +ld = '/usr/bin/arm-linux/gnueabihf-ld' + +[built-in options] +# Used in unit test '140 get define' +c_args = ['-DMESON_TEST_ISSUE_1665=1'] +cpp_args = '-DMESON_TEST_ISSUE_1665=1' + +[properties] +root = '/usr/arm-linux-gnueabihf' + +has_function_printf = true +has_function_hfkerhisadf = false + +skip_sanity_check = true + +[host_machine] +system = 'linux' +cpu_family = 'arm' +cpu = 'armv7' # Not sure if correct. +endian = 'little' diff --git a/devtools/meson/cross/ubuntu-faketarget.txt b/devtools/meson/cross/ubuntu-faketarget.txt new file mode 100644 index 0000000..cc43998 --- /dev/null +++ b/devtools/meson/cross/ubuntu-faketarget.txt @@ -0,0 +1,13 @@ +# This is a setup for compiling a program that runs natively +# but produces output that runs on a different platform. +# That is either a cross compiler or something like binutils. + +# We don't need to specify any properties or compilers, +# for we use the native ones and can run the resulting +# binaries directly. + +[target_machine] +system = 'linux' +cpu_family = 'mips' +cpu = 'mips' +endian = 'little' diff --git a/devtools/meson/cross/wasm.txt b/devtools/meson/cross/wasm.txt new file mode 100644 index 0000000..269c77a --- /dev/null +++ b/devtools/meson/cross/wasm.txt @@ -0,0 +1,17 @@ +[binaries] +c = '/home/jpakkane/src/emsdk/upstream/emscripten/emcc' +cpp = '/home/jpakkane/src/emsdk/upstream/emscripten/em++' +ar = '/home/jpakkane/src/emsdk/upstream/emscripten/emar' + +[built-in options] +c_args = [] +c_link_args = ['-sEXPORT_ALL=1'] +cpp_args = [] +cpp_link_args = ['-sEXPORT_ALL=1'] + +[host_machine] + +system = 'emscripten' +cpu_family = 'wasm32' +cpu = 'wasm32' +endian = 'little' diff --git a/devtools/meson/cross/xc16.txt b/devtools/meson/cross/xc16.txt new file mode 100644 index 0000000..c66889d --- /dev/null +++ b/devtools/meson/cross/xc16.txt @@ -0,0 +1,26 @@ +# This file assumes that path to the Microchip xc16 toolchain is added +# to the environment(PATH) variable, so that Meson can find +# xc16-gcc and xc16-ar while building. +[binaries] +c = 'xc16-gcc' +ar = 'xc16-ar' +strip = 'xc16-gcc' + +[host_machine] +system = 'bare metal' +cpu_family = 'dspic' +cpu = '33ep64mc203' +endian = 'little' + +[properties] +needs_exe_wrapper = true + +[built-in options] +c_args = [ + '-c', + '-mcpu=33EP64MC203', + '-omf=elf'] +c_link_args = [ + '-mcpu=33EP64MC203', + '-omf=elf', + '-Wl,--script=p33EP64MC203.gld,'] diff --git a/devtools/meson/data/.coveragerc.in b/devtools/meson/data/.coveragerc.in new file mode 100644 index 0000000..328e13c --- /dev/null +++ b/devtools/meson/data/.coveragerc.in @@ -0,0 +1,25 @@ +[run] +branch = True +parallel = True +concurrency = multiprocessing +data_file = @ROOT@/.coverage/coverage +source = @ROOT@/mesonbuild/ + +[report] +exclude_lines = + if T.TYPE_CHECKING: + +[paths] +mesonbuild = + mesonbuild/ + __w/meson/meson/mesonbuild/ + @ROOT@/mesonbuild/ + +[html] +directory = @ROOT@/.coverage/html + +[xml] +output = @ROOT@/.coverage/coverage.xml + +[json] +output = @ROOT@/.coverage/coverage.json diff --git a/devtools/meson/data/com.mesonbuild.install.policy b/devtools/meson/data/com.mesonbuild.install.policy new file mode 100644 index 0000000..65bf3ef --- /dev/null +++ b/devtools/meson/data/com.mesonbuild.install.policy @@ -0,0 +1,22 @@ + + + + + The Meson Build System + https://github.com/mesonbuild/meson + + + Install the given project via Meson + Authentication is required to install this project + preferences-system + + no + no + auth_admin_keep + + /usr/bin/python3 + /usr/bin/meson + + + diff --git a/devtools/meson/data/macros.meson b/devtools/meson/data/macros.meson new file mode 100644 index 0000000..f5e3a15 --- /dev/null +++ b/devtools/meson/data/macros.meson @@ -0,0 +1,45 @@ +%__meson %{_bindir}/meson +%__meson_wrap_mode nodownload +%__meson_auto_features enabled + +%meson \ + %set_build_flags \ + %{shrink:%{__meson} setup \ + --buildtype=plain \ + --prefix=%{_prefix} \ + --libdir=%{_libdir} \ + --libexecdir=%{_libexecdir} \ + --bindir=%{_bindir} \ + --sbindir=%{_sbindir} \ + --includedir=%{_includedir} \ + --datadir=%{_datadir} \ + --mandir=%{_mandir} \ + --infodir=%{_infodir} \ + --localedir=%{_datadir}/locale \ + --sysconfdir=%{_sysconfdir} \ + --localstatedir=%{_localstatedir} \ + --sharedstatedir=%{_sharedstatedir} \ + --wrap-mode=%{__meson_wrap_mode} \ + --auto-features=%{__meson_auto_features} \ + %{_vpath_srcdir} %{_vpath_builddir} \ + %{nil}} + +%meson_build \ + %{shrink:%{__meson} compile \ + -C %{_vpath_builddir} \ + -j %{_smp_build_ncpus} \ + --verbose \ + %{nil}} + +%meson_install \ + %{shrink:DESTDIR=%{buildroot} %{__meson} install \ + -C %{_vpath_builddir} \ + --no-rebuild \ + %{nil}} + +%meson_test \ + %{shrink:%{__meson} test \ + -C %{_vpath_builddir} \ + --num-processes %{_smp_build_ncpus} \ + --print-errorlogs \ + %{nil}} diff --git a/devtools/meson/data/schema.xsd b/devtools/meson/data/schema.xsd new file mode 100644 index 0000000..58c6bfd --- /dev/null +++ b/devtools/meson/data/schema.xsd @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devtools/meson/data/shell-completions/bash/meson b/devtools/meson/data/shell-completions/bash/meson new file mode 100644 index 0000000..4357a3f --- /dev/null +++ b/devtools/meson/data/shell-completions/bash/meson @@ -0,0 +1,492 @@ +_meson() { + command="${COMP_WORDS[1]}" + meson_subcommands=( + setup + configure + dist + install + introspect + init + test + wrap + subprojects + help + rewrite + compile + devenv + env2mfile + ) + + if [[ " ${meson_subcommands[*]} " =~ " ${command} " ]]; then + _meson-$command "${COMP_WORDS[@]:1}" + else + _meson-setup "${COMP_WORDS[@]}" + fi +} && +complete -F _meson meson + +_meson_complete_option() { + option_string=$1 + + if [[ $# -eq 2 ]] && ! [[ "$option_string" == *=* ]]; then + option_string="$option_string=$2" + fi + + if [[ "$option_string" == *=* ]]; then + _meson_complete_option_value "$option_string" + else + _meson_complete_option_name "$option_string" + fi +} + +_meson_complete_option_name() { + option=$1 + options=($(python3 -c 'import sys, json +for option in json.load(sys.stdin): + print(option["name"]) +' <<< "$(_meson_get_options)")) + compopt -o nospace + COMPREPLY=($(compgen -W '${options[@]}' -S= -- "$option")) +} + +_meson_complete_option_value() { + cur=$1 + option_name=${cur%%=*} + option_value=${cur#*=} + + if _meson_complete_filedir "$option_name" "$option_value"; then + return + fi + +# TODO: support all the option types + options=($(python3 -c 'import sys, json +for option in json.load(sys.stdin): + if option["name"] != "'$option_name'": + continue + choices = [] + if option["type"] == "boolean": + choices.append("true") + choices.append("false") + elif option["type"] == "combo": + for choice in option["choices"]: + choices.append(choice) + for choice in choices: + if choice.startswith("'$cur'"): + print(choice) +' <<< "$(_meson_get_options)")) + COMPREPLY=("${options[@]}") +} + +_meson_get_options() { + local options + for builddir in "${COMP_WORDS[@]}"; do + if [ -d "$builddir" ]; then + break + fi + builddir=. + done + options=$(meson introspect "$builddir" --buildoptions 2>/dev/null) && + echo "$options" || + echo '[]' +} + +_meson_complete_filedir() { + _filedir_in() { + pushd "$1" &>/dev/null + local COMPREPLY=() + _filedir + echo "${COMPREPLY[@]}" + popd &>/dev/null + } + + option=$1 + cur=$2 + case $option in + prefix |\ + libdir |\ + libexecdir |\ + bindir |\ + sbindir |\ + includedir |\ + datadir |\ + mandir |\ + infodir |\ + localedir |\ + sysconfdir |\ + localstatedir |\ + sharedstatedir) + _filedir -d + ;; + cross-file) + _filedir + COMPREPLY+=($(_filedir_in "$XDG_DATA_DIRS"/meson/cross)) + COMPREPLY+=($(_filedir_in /usr/local/share/meson/cross)) + COMPREPLY+=($(_filedir_in /usr/share/meson/cross)) + COMPREPLY+=($(_filedir_in "$XDG_DATA_HOME"/meson/cross)) + COMPREPLY+=($(_filedir_in ~/.local/share/meson/cross)) + ;; + *) + return 1;; + esac + return 0 +} + +_meson-setup() { + + shortopts=( + h + D + v + ) + + longopts=( + help + prefix + libdir + libexecdir + bindir + sbindir + includedir + datadir + mandir + infodir + localedir + sysconfdir + localstatedir + sharedstatedir + backend + buildtype + strip + unity + werror + layout + default-library + warnlevel + stdsplit + errorlogs + cross-file + version + wrap-mode + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null && + [ "${prev:0:2}" = '--' ] && _meson_complete_option "${prev:2}" "$cur"; then + return + elif _get_comp_words_by_ref cur prev &>/dev/null && + [ "${prev:0:1}" = '-' ] && [ "${prev:1:2}" != '-' ] && _meson_complete_option "${prev:1}"; then + return + elif _get_comp_words_by_ref -n '=' cur prev &>/dev/null; then + if [ $prev == -D ]; then + _meson_complete_option "$cur" + return + fi + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if [[ "$cur" == "--"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ "$cur" == "-"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + _filedir -d + if [ -z "$cur" ]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + + if [ $COMP_CWORD -eq 1 ]; then + COMPREPLY+=($(compgen -W "${meson_subcommands[*]}" -- "$cur")) + fi + fi +} + +_meson-configure() { + + shortopts=( + h + D + ) + + longopts=( + help + clearcache + ) + + local cur prev + if _get_comp_words_by_ref -n '=' cur prev &>/dev/null; then + if [ $prev == -D ]; then + _meson_complete_option "$cur" + return + fi + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if [[ "$cur" == "--"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ "$cur" == "-"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + for dir in "${COMP_WORDS[@]}"; do + if [ -d "$dir" ]; then + break + fi + dir=. + done + if [ ! -d "$dir/meson-private" ]; then + _filedir -d + fi + + if [ -z "$cur" ]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-dist() { + : TODO +} + +_meson-install() { + : TODO +} + +_meson-introspect() { + shortopts=( + h + ) + + longopts=( + targets + installed + buildsystem-files + buildoptions + tests + benchmarks + dependencies + projectinfo + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if [[ "$cur" == "--"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ "$cur" == "-"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + for dir in "${COMP_WORDS[@]}"; do + if [ -d "$dir" ]; then + break + fi + dir=. + done + if [ ! -d "$dir/meson-private" ]; then + _filedir -d + fi + + if [ -z "$cur" ]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-init() { + shortopts=( + h + C + n + e + e + d + l + b + f + ) + + longopts=( + help + name + executable + deps + language + builddir + force + type + version + ) + + if [[ "$cur" == "--"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ "$cur" == "-"* && ${#cur} -gt 1 ]]; then + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + if [ -z "$cur" ]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + +} + +_meson-test() { + shortopts=( + q + v + t + C + ) + + longopts=( + quiet + verbose + timeout-multiplier + repeat + no-rebuild + gdb + list + wrapper --wrap + no-suite + suite + no-stdsplit + print-errorlogs + benchmark + logbase + num-processes + setup + test-args + ) + + local cur prev + if _get_comp_words_by_ref -n ':' cur prev &>/dev/null; then + case $prev in + --repeat) + # number, can't be completed + return + ;; + --wrapper) + _command_offset $COMP_CWORD + return + ;; + -C) + _filedir -d + return + ;; + --suite | --no-suite) + for i in "${!COMP_WORDS[@]}"; do + opt="${COMP_WORDS[i]}" + dir="${COMP_WORDS[i+1]}" + case "$opt" in + -C) + break + ;; + esac + dir=. + done + suites=($(python3 -c 'import sys, json; +for test in json.load(sys.stdin): + for suite in test["suite"]: + print(suite) + ' <<< "$(meson introspect "$dir" --tests)")) +# TODO + COMPREPLY+=($(compgen -W "${suites[*]}" -- "$cur")) + return + ;; + --logbase) + # free string, can't be completed + return + ;; + --num-processes) + # number, can't be completed + return + ;; + -t | --timeout-multiplier) + # number, can't be completed + return + ;; + --setup) + # TODO + return + ;; + --test-args) + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if [[ "$cur" == "--"* ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ "$cur" == "-"* && ${#cur} -gt 1 ]]; then + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + for dir in "${COMP_WORDS[@]}"; do + if [ -d "$dir" ]; then + break + fi + dir=. + done + if [ ! -d "$dir/meson-private" ]; then + _filedir -d + fi + + for i in "${!COMP_WORDS[@]}"; do + opt="${COMP_WORDS[i]}" + dir="${COMP_WORDS[i+1]}" + case "$opt" in + -C) + break + ;; + esac + dir=. + done + tests=($(python3 -c 'import sys, json; +for test in json.load(sys.stdin): + print(test["name"]) +' <<< "$(meson introspect "$dir" --tests)")) + COMPREPLY+=($(compgen -W "${tests[*]}" -- "$cur")) + + if [ -z "$cur" ]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + fi + fi +} + +_meson-wrap() { + : TODO +} + +_meson-subprojects() { + : TODO +} + +_meson-help() { + : # Nothing to do +} + +_meson-rewrite() { + : TODO +} + +_meson-compile() { + : TODO +} + +_meson-devenv() { + : TODO +} + +_meson-env2mfile() { + : TODO +} diff --git a/devtools/meson/data/shell-completions/zsh/_meson b/devtools/meson/data/shell-completions/zsh/_meson new file mode 100644 index 0000000..bd71a31 --- /dev/null +++ b/devtools/meson/data/shell-completions/zsh/_meson @@ -0,0 +1,425 @@ +#compdef meson + +# vim:ts=2 sw=2 + +# Copyright (c) 2017 Arseny Maslennikov +# All rights reserved. Individual authors, whether or not +# specifically named, retain copyright in all changes; in what follows, they +# are referred to as `the Meson development team'. This is for convenience +# only and this body has no legal status. This file is distributed under +# the following licence. +# +# Permission is hereby granted, without written agreement and without +# licence or royalty fees, to use, copy, modify, and distribute this +# software and to distribute modified versions of this software for any +# purpose, provided that the above copyright notice and the following +# two paragraphs appear in all copies of this software. +# +# In no event shall the Meson development team be liable to any party for +# direct, indirect, special, incidental, or consequential damages arising out +# of the use of this software and its documentation, even if the Meson +# development team have been advised of the possibility of such damage. +# +# The Meson development team specifically disclaim any warranties, including, +# but not limited to, the implied warranties of merchantability and fitness +# for a particular purpose. The software provided hereunder is on an "as is" +# basis, and the Meson development team have no obligation to provide +# maintenance, support, updates, enhancements, or modifications. + +local curcontext="$curcontext" state line +local -i ret + +local __meson_backends="(ninja xcode ${(j. .)${:-vs{,2010,2015,2017}}})" +local __meson_build_types="(plain debug debugoptimized minsize release)" +local __meson_wrap_modes="(WrapMode.{default,nofallback,nodownload,forcefallback})" +local __meson_dist_formats=("xztar" "gztar" "zip") +local __meson_cd='-C[change into this directory before running]:target dir:_directories' +local -a __meson_common=( + '--prefix=[installation prefix]: :_directories' + '--bindir=[executable directory]: :_directories' + '--datadir=[data file directory]: :_directories' + '--includedir=[header file directory]: :_directories' + '--infodir=[info page directory]: :_directories' + '--libdir=[library directory]: :_directories' + '--libexecdir=[library executable directory]: :_directories' + '--localedir=[locale data directory]: :_directories' + '--localstatedir=[local state data directory]: :_directories' + '--mandir=[manual page directory]: :_directories' + '--sbindir=[system executable directory]: :_directories' + '--sharedstatedir=[arch-independent data directory]: :_directories' + '--sysconfdir=[system configuration directory]: :_directories' + '--auto-features=[default value for auto features]:auto features types:(auto disabled enabled)' + '--backend=[backend to use]:Meson backend:'"$__meson_backends" + '--buildtype=[build type to use]:Meson build type:'"$__meson_build_types" + '--debug[turn on building with debug]' + '--default-library=[default library type]:default library type:(shared static both)' + '--errorlogs[prints the logs from failing tests]' + '--install-umask=[default umask for permissions of all installed files]' + '--layout=[build directory layout]:build directory layout:(flat mirror)' + '--optimization=[optimization level for compiled targets]:optimization:(0 g 1 2 3 s)' + '--stdsplit=[split stdout and stderr in test logs]' + '--strip[strip targets on install]' + '--unity=[unity builds on/off]:whether to do unity builds:(on off subprojects)' + '--warnlevel=[compiler warning level]:compiler warning level:warning level:(1 2 3)' + '--werror[treat warnings as errors]' + '--wrap-mode=[special wrap mode]:wrap mode:'"$__meson_wrap_modes" + '--force-fallback-for=[force fallback for listed subprojects]' + '--pkg-config-path=[extra paths for HOST pkg-config to search]:paths:_dir_list -s ,' + '--build.pkg-config-path=[extra paths for BUILD pkg-config to search]:paths:_dir_list -s ,' + '--cmake-prefix-path=[extra prefixes for HOST cmake to search]:paths:_dir_list -s ,' + '--build.cmake-prefix-path=[extra prefix for BUILD cmake to search]:paths:_dir_list -s ,' +) + +local -a meson_commands=( +'configure:configure a project' +'dist:generate release archive' +'init:create a new project' +'install:install one or more targets' +'introspect:query project properties' +'setup:set up a build directory' +'test:run tests' +'wrap:manage source dependencies' +'subprojects:manage subprojects' +'compile:Build the project' +) + +(( $+functions[__meson_is_build_dir] )) || __meson_is_build_dir() { + local mpd="${1:-$PWD}/meson-private" + [[ -f "$mpd/build.dat" && -f "$mpd/coredata.dat" ]] + return $? +} + +# TODO: implement build option completion +(( $+functions[__meson_build_options] )) || __meson_build_options() {} + +# `meson introspect` currently can provide that information in JSON. +# We can: +# 1) pipe its output to python3 -m json.tool | grep "$alovelyregex" | cut <...> +# 2) teach mintro.py to use a different output format +# (or perhaps just to select the fields printed) + +(( $+functions[__meson_test_names] )) || __meson_test_names() { + local rtests + if rtests="$(_call_program meson meson test ${opt_args[-C]:+-C "$opt_args[-C]"} --list)"; + then + local -a tests=(${(@f)rtests}) + _describe -t "tests" "Meson tests" tests + else + _message -r "current working directory is not a build directory" + _message -r 'use -C $build_dir or cd $build_dir' + fi +} + +(( $+functions[__meson_wrap_names] )) || __meson_wrap_names() { + local rwraps + rwraps="$(_call_program meson meson wrap list)" + local -a wraps=(${(@f)rwraps}) + _describe -t wraps "Meson wraps" wraps +} + +(( $+functions[__meson_installed_wraps] )) || __meson_installed_wraps() { + local rwraps + if rwraps="$(ls subprojects/ | grep '\.wrap$' | cut -d . -f 1)"; then + local -a wraps=(${(@f)rwraps}) + _describe -t wraps "Meson wraps" wraps + fi +} + +(( $+functions[_meson_commands] )) || _meson_commands() { + _describe -t commands "Meson subcommands" meson_commands +} + +(( $+functions[_meson-setup] )) || _meson-setup() { + local firstd secondd + if [[ -f "meson.build" ]]; then + # if there's no second argument on the command line + # cwd will implicitly be substituted: + # - as the source directory if it has a file with the name "meson.build"; + # - as the build directory otherwise + # more info in mesonbuild/mesonmain.py + firstd="build" + secondd="source" + else + firstd="source" + secondd="build" + fi + + _arguments \ + '*-D-[set the value of a build option]:build option:__meson_build_options' \ + '--cross-file=[cross-compilation environment description]:cross file:_files' \ + '--native-file=[build machine compilation environment description]:native file:_files' \ + '--clearcache[clear cached state]' \ + '--fatal-meson-warnings=[exit when any meson warnings are encountered]' \ + '(-v --version)'{'-v','--version'}'[print the meson version and exit]' \ + '--reconfigure=[re-run build configuration]' \ + '--wipe=[delete saved state and restart using saved command line options]' \ + ":$firstd directory:_directories" \ + "::$secondd directory:_directories" \ + "${(@)__meson_common}" +} + +(( $+functions[_meson-configure] )) || _meson-configure() { + local curcontext="$curcontext" + # TODO: implement 'mesonconf @file' + local -a specs=( + '*-D-[set the value of a build option]:build option:__meson_build_options' + '::build directory:_directories' + ) + + _arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" \ + "${(@)__meson_common}" +} + +(( $+functions[_meson-test] )) || _meson-test() { + local curcontext="$curcontext" + + # TODO: complete test suites + local -a specs=( + '--repeat[number of times to run the tests]:number of times to repeat: ' + '--no-rebuild[do not rebuild before running tests]' + '--gdb[run tests under gdb]' + '--gdb-path=[program to run for gdb (can be wrapper or compatible program)]:program:_path_commands' + '--list[list available tests]' + '(--wrapper --wrap)'{'--wrapper=','--wrap='}'[wrapper to run tests with]:wrapper program:_path_commands' + "$__meson_cd" + '(--suite)--no-suite[do not run tests from this suite]:test suite: ' + '(--no-suite)--suite[only run tests from this suite]:test suite: ' + '--no-stdsplit[do not split stderr and stdout in logs]' + '--print-errorlogs[print logs for failing tests]' + '--benchmark[run benchmarks instead of tests]' + '--logbase[base name for log file]:filename: ' + '--num-processes[how many threads to use]:number of processes: ' + '(--verbose -v)'{'--verbose','-v'}'[do not redirect stdout and stderr]' + '(--quiet -q)'{'--quiet','-q'}'[produce less output to the terminal]' + '(--timeout-multiplier -t)'{'--timeout-multiplier','-t'}'[a multiplier for test timeouts]:Python floating-point number: ' + '--setup[which test setup to use]:test setup: ' + '--test-args[arguments to pass to the tests]: : ' + '*:Meson tests:__meson_test_names' + ) + + _arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-install] )) || _meson-install() { + local curcontext="$curcontext" + local -a specs=( + "$__meson_cd" + '--no-rebuild[Do not rebuild before installing]' + '--only-changed[Do not overwrite files that are older than the copied file]' + '--quiet[Do not print every file that was installed]' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-introspect] )) || _meson-introspect() { + local curcontext="$curcontext" + local -a specs=( + '--ast[dump the ASK of the meson file]' + '--benchmarks[list all benchmarks]' + '--buildoptions[list all build options]' + '--buildsystem-files[list files that belong to the build system]' + '--dependencies[list external dependencies]' + '--installed[list all installed files and directories]' + '--projectinfo[show project information]' + '--targets[list top level targets]' + '--tests[list all unit tests]' + '--backend=[backend to use]:Meson backend:'"$__meson_backends" + '::build directory:_directories' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-init] )) || _meson-init() { + local curcontext="$curcontext" + local -a specs=( + "$__meson_cd" + '(-n --name)'{'-n','--name'}'=[the name of the project (defaults to directory name)]' + '(-e --executable)'{'-e','--executable'}'=[the name of the executable target to create (defaults to project name)]' + '(-d --deps)'{'-d','--deps'}'=[comma separated list of dependencies]' + '(-l --language)'{'-l','--language'}'=[comma separated list of languages (autodetected based on sources if unset)]:languages:_values , (c cpp cs cuda d fortran java objc objcpp rust)' + '(-b --build)'{'-b','--build'}'[build the project immediately after generation]' + '--builddir=[directory for building]:directory:_directories' + '(-f --force)'{'-f','--force'}'[overwrite any existing files and directories]' + '(-t --type)'{'-t','--type'}'=[project type, defaults to executable]:type:(executable library)' + '(-v --version)'{'-v','--version'}'[print the meson version and exit]' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-wrap] )) || _meson-wrap() { + local -a commands=( + 'list:list all available wraps' + 'search:search the db by name' + 'install:install the specified project' + 'update:Update a project to its newest available version' + 'info:Show info about a wrap' + 'status:Show the status of your subprojects' + ) + + if (( CURRENT == 2 )); then + _describe -t commands "Meson wrap subcommands" commands + else + local curcontext="$curcontext" + cmd="${${commands[(r)$words[2]:*]%%:*}}" + if (( $#cmd )); then + if [[ $cmd == status ]]; then + _message "no options" + elif [[ $cmd == "list" ]]; then + _arguments '*:meson wraps' + elif [[ $cmd == "search" ]]; then + _arguments '*:meson wraps' + elif [[ $cmd == "install" ]]; then + _arguments '*:meson wraps:__meson_wrap_names' + elif [[ $cmd == "update" ]]; then + _arguments '*:meson wraps:__meson_installed_wraps' + elif [[ $cmd == "info" ]]; then + _arguments '*:meson wraps:__meson_wrap_name' + elif [[ $cmd == "status" ]]; then + _arguments '*:' + elif [[ $cmd == "promote" ]]; then + # TODO: how do you figure out what wraps are provided by subprojects if + # they haven't been fetched yet? + _arguments '*:' + fi + else + _message "unknown meson wrap command: $words[2]" + fi + fi + +} + +(( $+functions[_meson-dist] )) || _meson-dist() { + local curcontext="$curcontext" + local -a specs=( + '--allow-dirty[Allow even when repository contains uncommitted changes]' + '--formats=[comma separated list of archive types to create]:archive formats:_values -s , format '"$__meson_dist_formats" + '--include-subprojects[Include source code of subprojects that have been used for the build]' + '--no-tests[Do not build and test generated packages]' + "$__meson_cd" + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-update] )) || _meson-subprojects-update() { + local curcontext="$curcontext" + local -a specs=( + "--rebase[rebase your branch on top of wrap's revision (git only)]" + '--sourcedir=[path to source directory]:_directories' + '*:subprojects:__meson_installed_wraps' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-checkout] )) || _meson-subprojects-checkout() { + local curcontext="$curcontext" + local -a specs=( + '-b[create a new branch]' + '--sourcedir=[path to source directory]:_directories' + # FIXME: this doesn't work exactly right, but I can't figure it out + ':branch name' + '*:subprojects:__meson_installed_wraps' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-download] )) || _meson-subprojects-download() { + local curcontext="$curcontext" + local -a specs=( + '--sourcedir=[path to source directory]:_directories' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects-foreach] )) || _meson-subprojects-foreach() { + local curcontext="$curcontext" + local -a specs=( + '--sourcedir=[path to source directory]:_directories' + '*:command:_command_names -e' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +(( $+functions[_meson-subprojects] )) || _meson-subprojects() { + local -a commands=( + 'update:update all subprojects from wrap files' + 'checkout:checkout a branch (git only)' + 'download:ensure subprojects are fetched, even if not in use. Already downloaded subprojects are not modified.' + 'foreach:execute a command in each subproject directory' + ) + + if (( CURRENT == 2 )); then + _describe -t commands "Meson subproject subcommands" commands + else + local curcontext="$curcontext" + cmd="${${commands[(r)$words[2]:*]%%:*}}" + if (( $#cmd )); then + if [[ $cmd == status ]]; then + _message "no options" + else + _meson-subprojects-$cmd + fi + else + _message "unknown meson subproject command: $words[2]" + fi + fi + +} + +(( $+functions[_meson-compile] )) || _meson-compile() { + local curcontext="$curcontext" + local -a specs=( + "$__meson_cd" + '--clean[Clean the build directory]' + '(-j --jobs)'{'-j','--jobs'}'=[the number fo work jobs to run (if supported)]:_guard "[0-9]#" "number of jobs"' + '(-l --load-average)'{'-l','--load-average'}'=[the system load average to try to maintain (if supported)]:_guard "[0-9]#" "load average"' + '(-v --verbose)'{'-v','--verbose'}'[Show more output]' + '--ninja-args=[Arguments to pass to ninja (only when using ninja)]' + '--vs-args=[Arguments to pass to vs (only when using msbuild)]' + ) +_arguments \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + "${(@)specs}" +} + +if [[ $service != meson ]]; then + _call_function ret _$service + return ret +fi + +_arguments -C -R \ + '(: -)'{'--help','-h'}'[show a help message and quit]' \ + '(: -)'{'--version','-v'}'[show version information and quit]' \ + '(-): :_meson_commands' \ + '*:: :->post-command' \ +# +ret=$? + +[[ $ret = 300 ]] && case "$state" in + post-command) + service="meson-$words[1]" + curcontext=${curcontext%:*:*}:$service: + _call_function ret _$service + ;; +esac + +return ret diff --git a/devtools/meson/data/syntax-highlighting/vim/README b/devtools/meson/data/syntax-highlighting/vim/README new file mode 100644 index 0000000..95188fc --- /dev/null +++ b/devtools/meson/data/syntax-highlighting/vim/README @@ -0,0 +1,4 @@ +ftdetect sets the filetype +ftplugin sets Meson indentation rules +indent does Meson indentation +syntax does Meson syntax highlighting diff --git a/devtools/meson/data/syntax-highlighting/vim/ftdetect/meson.vim b/devtools/meson/data/syntax-highlighting/vim/ftdetect/meson.vim new file mode 100644 index 0000000..28e3a29 --- /dev/null +++ b/devtools/meson/data/syntax-highlighting/vim/ftdetect/meson.vim @@ -0,0 +1,4 @@ +au BufNewFile,BufRead meson.build set filetype=meson +au BufNewFile,BufRead meson.options set filetype=meson +au BufNewFile,BufRead meson_options.txt set filetype=meson +au BufNewFile,BufRead *.wrap set filetype=dosini diff --git a/devtools/meson/data/syntax-highlighting/vim/ftplugin/meson.vim b/devtools/meson/data/syntax-highlighting/vim/ftplugin/meson.vim new file mode 100644 index 0000000..1ce9a03 --- /dev/null +++ b/devtools/meson/data/syntax-highlighting/vim/ftplugin/meson.vim @@ -0,0 +1,39 @@ +" Vim filetype plugin file +" Language: meson +" License: VIM License +" Maintainer: Liam Beguin +" Original Author: Laurent Pinchart +" Last Change: 2018 Nov 27 + +if exists("b:did_ftplugin") | finish | endif +let b:did_ftplugin = 1 +let s:keepcpo= &cpo +set cpo&vim + +setlocal commentstring=#\ %s +setlocal comments=:# +setlocal formatoptions+=croql formatoptions-=t + +let b:undo_ftplugin = "setl com< cms< fo<" + +if get(g:, "meson_recommended_style", 1) + setlocal expandtab + setlocal shiftwidth=2 + setlocal softtabstop=2 + let b:undo_ftplugin .= " | setl et< sts< sw<" +endif + +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_words = '\:\:\:\,' . + \ '\:\:\:\' + let b:undo_ftplugin .= " | unlet! b:match_words" +endif + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Meson Build Files (meson.build)\tmeson.build\n" . + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin .= " | unlet! b:browsefilter" +endif + +let &cpo = s:keepcpo +unlet s:keepcpo diff --git a/devtools/meson/data/syntax-highlighting/vim/indent/meson.vim b/devtools/meson/data/syntax-highlighting/vim/indent/meson.vim new file mode 100644 index 0000000..57bea13 --- /dev/null +++ b/devtools/meson/data/syntax-highlighting/vim/indent/meson.vim @@ -0,0 +1,183 @@ +" Vim indent file +" Language: Meson +" License: VIM License +" Maintainer: Nirbheek Chauhan +" Liam Beguin +" Original Authors: David Bustos +" Bram Moolenaar +" Last Change: 2015 Feb 23 + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +" Some preliminary settings +setlocal nolisp " Make sure lisp indenting doesn't supersede us +setlocal autoindent " indentexpr isn't much help otherwise + +setlocal indentexpr=GetMesonIndent(v:lnum) +setlocal indentkeys+==elif,=else,=endforeach,=endif,0) + +let b:undo_indent = "setl ai< inde< indk< lisp<" + +" Only define the function once. +if exists("*GetMesonIndent") + finish +endif +let s:keepcpo= &cpo +set cpo&vim + +" Come here when loading the script the first time. + +let s:maxoff = 50 " maximum number of lines to look backwards for () + +function GetMesonIndent(lnum) + echom getline(line(".")) + + " If this line is explicitly joined: If the previous line was also joined, + " line it up with that one, otherwise add two 'shiftwidth' + if getline(a:lnum - 1) =~ '\\$' + if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$' + return indent(a:lnum - 1) + endif + return indent(a:lnum - 1) + (exists("g:mesonindent_continue") ? eval(g:mesonindent_continue) : (shiftwidth() * 2)) + endif + + " If the start of the line is in a string don't change the indent. + if has('syntax_items') + \ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$" + return -1 + endif + + " Search backwards for the previous non-empty line. + let plnum = prevnonblank(v:lnum - 1) + + if plnum == 0 + " This is the first non-empty line, use zero indent. + return 0 + endif + + " If the previous line is inside parenthesis, use the indent of the starting + " line. + " Trick: use the non-existing "dummy" variable to break out of the loop when + " going too far back. + call cursor(plnum, 1) + let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW', + \ "line('.') < " . (plnum - s:maxoff) . " ? dummy :" + \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + \ . " =~ '\\(Comment\\|Todo\\|String\\)$'") + if parlnum > 0 + let plindent = indent(parlnum) + let plnumstart = parlnum + else + let plindent = indent(plnum) + let plnumstart = plnum + endif + + + " When inside parenthesis: If at the first line below the parenthesis add + " a 'shiftwidth', otherwise same as previous line. + " i = (a + " + b + " + c) + call cursor(a:lnum, 1) + let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', + \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" + \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + \ . " =~ '\\(Comment\\|Todo\\|String\\)$'") + if p > 0 + if p == plnum + " When the start is inside parenthesis, only indent one 'shiftwidth'. + let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW', + \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" + \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" + \ . " =~ '\\(Comment\\|Todo\\|String\\)$'") + if pp > 0 + return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth()) + endif + return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : shiftwidth()) + endif + if plnumstart == p + return indent(plnum) + endif + return plindent + endif + + + " Get the line and remove a trailing comment. + " Use syntax highlighting attributes when possible. + let pline = getline(plnum) + let pline_len = strlen(pline) + if has('syntax_items') + " If the last character in the line is a comment, do a binary search for + " the start of the comment. synID() is slow, a linear search would take + " too long on a long line. + if synIDattr(synID(plnum, pline_len, 1), "name") =~ "\\(Comment\\|Todo\\)$" + let min = 1 + let max = pline_len + while min < max + let col = (min + max) / 2 + if synIDattr(synID(plnum, col, 1), "name") =~ "\\(Comment\\|Todo\\)$" + let max = col + else + let min = col + 1 + endif + endwhile + let pline = strpart(pline, 0, min - 1) + endif + else + let col = 0 + while col < pline_len + if pline[col] == '#' + let pline = strpart(pline, 0, col) + break + endif + let col = col + 1 + endwhile + endif + + " If the previous line ended the conditional/loop + if getline(plnum) =~ '^\s*\(endif\|endforeach\)\>\s*' + " Maintain indent + return -1 + endif + + " If the previous line ended with a builtin, indent this line + if pline =~ '^\s*\(foreach\|if\|else\|elif\)\>\s*' + return plindent + shiftwidth() + endif + + " If the current line begins with a header keyword, deindent + if getline(a:lnum) =~ '^\s*\(else\|elif\|endif\|endforeach\)' + + " Unless the previous line was a one-liner + if getline(plnumstart) =~ '^\s*\(foreach\|if\)\>\s*' + return plindent + endif + + " Or the user has already dedented + if indent(a:lnum) <= plindent - shiftwidth() + return -1 + endif + + return plindent - shiftwidth() + endif + + " When after a () construct we probably want to go back to the start line. + " a = (b + " + c) + " here + if parlnum > 0 + return plindent + endif + + return -1 + +endfunction + +let &cpo = s:keepcpo +unlet s:keepcpo + +" vim:sw=2 diff --git a/devtools/meson/data/syntax-highlighting/vim/syntax/meson.vim b/devtools/meson/data/syntax-highlighting/vim/syntax/meson.vim new file mode 100644 index 0000000..1b576d9 --- /dev/null +++ b/devtools/meson/data/syntax-highlighting/vim/syntax/meson.vim @@ -0,0 +1,162 @@ +" Vim syntax file +" Language: Meson +" License: VIM License +" Maintainer: Nirbheek Chauhan +" Liam Beguin +" Last Change: 2021 Aug 16 +" Credits: Zvezdan Petkovic +" Neil Schemenauer +" Dmitry Vasiliev +" +" This version is copied and edited from python.vim +" It's very basic, and doesn't do many things I'd like it to +" For instance, it should show errors for syntax that is valid in +" Python but not in Meson. +" +" Optional highlighting can be controlled using these variables. +" +" let meson_space_error_highlight = 1 +" + +if exists("b:current_syntax") + finish +endif + +" We need nocompatible mode in order to continue lines with backslashes. +" Original setting will be restored. +let s:cpo_save = &cpo +set cpo&vim + +" http://mesonbuild.com/Syntax.html +syn keyword mesonConditional elif else if endif +syn keyword mesonRepeat foreach endforeach +syn keyword mesonOperator and not or in +syn keyword mesonStatement continue break + +syn match mesonComment "#.*$" contains=mesonTodo,@Spell +syn keyword mesonTodo FIXME NOTE NOTES TODO XXX contained + +" Strings can either be single quoted or triple counted across multiple lines, +" but always with a ' +syn region mesonString + \ start="\z('\)" end="\z1" skip="\\\\\|\\\z1" + \ contains=mesonEscape,@Spell +syn region mesonString + \ start="\z('''\)" end="\z1" keepend + \ contains=mesonEscape,mesonSpaceError,@Spell + +syn match mesonEscape "\\[abfnrtv'\\]" contained +syn match mesonEscape "\\\o\{1,3}" contained +syn match mesonEscape "\\x\x\{2}" contained +syn match mesonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained +" Meson allows case-insensitive Unicode IDs: http://www.unicode.org/charts/ +syn match mesonEscape "\\N{\a\+\%(\s\a\+\)*}" contained +syn match mesonEscape "\\$" + +" Meson only supports integer numbers +" http://mesonbuild.com/Syntax.html#numbers +syn match mesonNumber "\<\d\+\>" +syn match mesonNumber "\<0x\x\+\>" +syn match mesonNumber "\<0o\o\+\>" + +" booleans +syn keyword mesonBoolean false true + +" Built-in functions +syn keyword mesonBuiltin + \ add_global_arguments + \ add_global_link_arguments + \ add_languages + \ add_project_arguments + \ add_project_dependencies + \ add_project_link_arguments + \ add_test_setup + \ alias_target + \ assert + \ benchmark + \ both_libraries + \ build_machine + \ build_target + \ configuration_data + \ configure_file + \ custom_target + \ declare_dependency + \ dependency + \ disabler + \ environment + \ error + \ executable + \ files + \ find_library + \ find_program + \ generator + \ get_option + \ get_variable + \ gettext + \ host_machine + \ import + \ include_directories + \ install_data + \ install_headers + \ install_man + \ install_subdir + \ install_symlink + \ install_emptydir + \ is_disabler + \ is_variable + \ jar + \ join_paths + \ library + \ meson + \ message + \ option + \ project + \ run_command + \ run_target + \ set_variable + \ shared_library + \ shared_module + \ static_library + \ structured_sources + \ subdir + \ subdir_done + \ subproject + \ summary + \ target_machine + \ test + \ unset_variable + \ vcs_tag + \ warning + \ range + \ debug + +if exists("meson_space_error_highlight") + " trailing whitespace + syn match mesonSpaceError display excludenl "\s\+$" + " mixed tabs and spaces + syn match mesonSpaceError display " \+\t" + syn match mesonSpaceError display "\t\+ " +endif + +" The default highlight links. Can be overridden later. +hi def link mesonStatement Statement +hi def link mesonConditional Conditional +hi def link mesonRepeat Repeat +hi def link mesonOperator Operator +hi def link mesonComment Comment +hi def link mesonTodo Todo +hi def link mesonString String +hi def link mesonEscape Special +hi def link mesonNumber Number +hi def link mesonBuiltin Function +hi def link mesonBoolean Boolean +if exists("meson_space_error_highlight") + hi def link mesonSpaceError Error +endif + +let b:current_syntax = "meson" + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:set sw=2 sts=2 ts=8 noet: diff --git a/devtools/meson/data/test.schema.json b/devtools/meson/data/test.schema.json new file mode 100644 index 0000000..fa5a53e --- /dev/null +++ b/devtools/meson/data/test.schema.json @@ -0,0 +1,180 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "installed": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "file": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "file", + "python_file", + "dir", + "exe", + "shared_lib", + "python_lib", + "python_bytecode", + "pdb", + "implib", + "py_implib", + "implibempty", + "expr" + ] + }, + "platform": { + "type": "string", + "enum": [ + "msvc", + "gcc", + "cygwin", + "!cygwin" + ] + }, + "version": { + "type": "string" + }, + "language": { + "type": "string" + } + }, + "required": [ + "file", + "type" + ] + } + }, + "matrix": { + "type": "object", + "properties": { + "options": { + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "val": { + "type": ["string", "boolean", "null", "array"], + "items": { + "type": "string" + } + }, + "compilers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "skip_on_env": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_jobname": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_os": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "val" + ] + } + }, + "exclude": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": ["string", "boolean", "array"], + "items": { + "type": "string" + } + } + } + } + } + } + }, + "do_not_set_opts": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "libdir", + "prefix" + ] + } + }, + "tools": { + "type": "object" + }, + "stdout": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "line": { + "type": "string" + }, + "match": { + "type": "string", + "enum": [ + "literal", + "re" + ] + }, + "count": { + "type": "integer" + }, + "comment": { + "type": "string" + } + }, + "required": [ + "line" + ] + } + }, + "skip_on_env": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_jobname": { + "type": "array", + "items": { + "type": "string" + } + }, + "skip_on_os": { + "type": "array", + "items": { + "type": "string" + } + } + } +} diff --git a/devtools/meson/graphics/meson_logo.svg b/devtools/meson/graphics/meson_logo.svg new file mode 100644 index 0000000..d5b47bc --- /dev/null +++ b/devtools/meson/graphics/meson_logo.svg @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/devtools/meson/graphics/meson_logo_big.png b/devtools/meson/graphics/meson_logo_big.png new file mode 100644 index 0000000000000000000000000000000000000000..e2abe1b24b1028424d072aface4b8467189b920d GIT binary patch literal 21889 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 + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/devtools/meson/man/meson.1 b/devtools/meson/man/meson.1 new file mode 100644 index 0000000..5fcc96c --- /dev/null +++ b/devtools/meson/man/meson.1 @@ -0,0 +1,238 @@ +.TH MESON "1" "September 2023" "meson 1.2.2" "User Commands" +.SH NAME +meson - a high productivity build system +.SH DESCRIPTION + +Meson is a build system designed to optimize programmer +productivity. It aims to do this by providing simple, out-of-the-box +support for modern software development tools and practices, such as +unit tests, coverage reports, Valgrind, Ccache and the like. + +The main Meson executable provides many subcommands to access all +the functionality. + +.SH The setup command + +Using Meson is simple and follows the common two-phase +process of most build systems. First you run Meson to +configure your build: + +.B meson setup [ +.I options +.B ] [ +.I build directory +.B ] [ +.I source directory +.B ] + +Note that the build directory must be different from the source +directory. Meson does not support building inside the source directory +and attempting to do that leads to an error. + +After a successful configuration step you can build the source by +running the actual build command in the build directory. The default +backend of Meson is Ninja, which can be invoked like this. + +\fBninja [\fR \fItarget\fR \fB]\fR + +You only need to run the Meson command once: when you first configure +your build dir. After that you just run the build command. Meson will +autodetect changes in your source tree and regenerate all files +needed to build the project. + +The setup command is the default operation. If no actual command is +specified, Meson will assume you meant to do a setup. That means +that you can set up a build directory without the setup command +like this: + +.B meson [ +.I options +.B ] [ +.I build directory +.B ] [ +.I source directory +.B ] + +.SS "options:" +.TP +\fB\-\-version\fR +print version number +.TP +\fB\-\-help\fR +print command line help + +.SH The configure command + +.B meson configure +provides a way to configure a Meson project from the command line. +Its usage is simple: + +.B meson configure [ +.I build directory +.B ] [ +.I options to set +.B ] + +If build directory is omitted, the current directory is used instead. + +If no parameters are set, +.B meson configure +will print the value of all build options to the console. + +To set values, use the \-D command line argument like this. + +.B meson configure \-Dopt1=value1 \-Dopt2=value2 + +.SH The introspect command + +Meson introspect is a command designed to make it simple to integrate with +other tools, such as IDEs. The output of this command is in JSON. + +.B meson introspect [ +.I build directory +.B ] [ +.I option +.B ] + +If build directory is omitted, the current directory is used instead. + +.SS "options:" +.TP +\fB\-\-targets\fR +print all top level targets (executables, libraries, etc) +.TP +\fB\-\-target\-files\fR +print the source files of the given target +.TP +\fB\-\-buildsystem\-files\fR +print all files that make up the build system (meson.build, meson.options, meson_options.txt etc) +.TP +\fB\-\-tests\fR +print all unit tests +.TP +\fB\-\-help\fR +print command line help + +.SH The test command + +.B meson test +is a helper tool for running test suites of projects using Meson. +The default way of running tests is to invoke the default build command: + +\fBninja [\fR \fItest\fR \fB]\fR + +.B meson test +provides a richer set of tools for invoking tests. + +.B meson test +automatically rebuilds the necessary targets to run tests when used with the Ninja backend. +Upon build failure, +.B meson test +will return an exit code of 125. +This return code tells +.B git bisect run +to skip the current commit. +Thus bisecting using git can be done conveniently like this. + +.B git bisect run meson test -C build_dir + +.SS "options:" +.TP +\fB\-\-repeat\fR +run tests as many times as specified +.TP +\fB\-\-gdb\fR +run tests under gdb +.TP +\fB\-\-list\fR +list all available tests +.TP +\fB\-\-wrapper\fR +invoke all tests via the given wrapper (e.g. valgrind) +.TP +\fB\-C\fR +Change into the given directory before running tests (must be root of build directory). +.TP +\fB\-\-suite\fR +run tests in this suite +.TP +\fB\-\-no\-suite\fR +do not run tests in this suite +.TP +\fB\-\-no\-stdsplit\fR +do not split stderr and stdout in test logs +.TP +\fB\-\-benchmark\fR +run benchmarks instead of tests +.TP +\fB\-\-logbase\fR +base of file name to use for writing test logs +.TP +\fB\-\-num-processes\fR +how many parallel processes to use to run tests +.TP +\fB\-\-verbose\fR +do not redirect stdout and stderr +.TP +\fB\-t\fR +a multiplier to use for test timeout values (usually something like 100 for Valgrind) +.TP +\fB\-\-setup\fR +use the specified test setup + +.SH The wrap command + +Wraptool is a helper utility to manage source dependencies +using the online wrapdb service. + +.B meson wrap < +.I command +.B > [ +.I options +.B ] + +You should run this command in the top level source directory +of your project. + +.SS "Commands:" +.TP +\fBlist\fR +list all available projects +.TP +\fBsearch\fR +search projects by name +.TP +\fBinstall\fR +install a project with the given name +.TP +\fBupdate\fR +update the specified project to latest available version +.TP +\fBinfo\fR +show available versions of the specified project +.TP +\fBstatus\fR +show installed and available versions of currently used subprojects + +.SH EXIT STATUS + +.TP +.B 0 +Successful. +.TP +.B 1 +Usage error, or an error parsing or executing meson.build. +.TP +.B 2 +Internal error. +.TP +.B 125 +.B meson test +could not rebuild the required targets. +.TP + +.SH SEE ALSO + +http://mesonbuild.com/ + +https://wrapdb.mesonbuild.com/ diff --git a/devtools/meson/manual tests/1 wrap/main.c b/devtools/meson/manual tests/1 wrap/main.c new file mode 100644 index 0000000..df6abe4 --- /dev/null +++ b/devtools/meson/manual tests/1 wrap/main.c @@ -0,0 +1,12 @@ +#include +#include + +int main(void) { + sqlite3 *db; + if(sqlite3_open(":memory:", &db) != SQLITE_OK) { + printf("Sqlite failed.\n"); + return 1; + } + sqlite3_close(db); + return 0; +} diff --git a/devtools/meson/manual tests/1 wrap/meson.build b/devtools/meson/manual tests/1 wrap/meson.build new file mode 100644 index 0000000..aee358d --- /dev/null +++ b/devtools/meson/manual tests/1 wrap/meson.build @@ -0,0 +1,13 @@ +project('downloader', 'c') + +cc = meson.get_compiler('c') + +s = subproject('sqlite').get_variable('sqlite_dep') +th = dependency('threads') + +libdl = cc.find_library('dl', required : false) + +e = executable('dtest', 'main.c', + dependencies : [th, libdl, s]) + +test('dltest', e) diff --git a/devtools/meson/manual tests/1 wrap/subprojects/sqlite.wrap b/devtools/meson/manual tests/1 wrap/subprojects/sqlite.wrap new file mode 100644 index 0000000..6d14949 --- /dev/null +++ b/devtools/meson/manual tests/1 wrap/subprojects/sqlite.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = sqlite-amalgamation-3080802 + +source_url = http://sqlite.com/2015/sqlite-amalgamation-3080802.zip +source_filename = sqlite-amalgamation-3080802.zip +source_hash = 5ebeea0dfb75d090ea0e7ff84799b2a7a1550db3fe61eb5f6f61c2e971e57663 + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/sqlite/3080802/5/get_zip +patch_filename = sqlite-3080802-5-wrap.zip +patch_hash = d66469a73fa1344562d56a1d7627d5d0ee4044a77b32d16cf4bbb85741d4c9fd diff --git a/devtools/meson/manual tests/10 svn wrap/meson.build b/devtools/meson/manual tests/10 svn wrap/meson.build new file mode 100644 index 0000000..23ef1f1 --- /dev/null +++ b/devtools/meson/manual tests/10 svn wrap/meson.build @@ -0,0 +1,10 @@ +project('Subversion outchecker', 'c') + +sp = subproject('samplesubproject') + +exe = executable('gitprog', 'prog.c', +include_directories : sp.get_variable('subproj_inc'), +link_with : sp.get_variable('subproj_lib'), +) + +test('maintest', exe) diff --git a/devtools/meson/manual tests/10 svn wrap/prog.c b/devtools/meson/manual tests/10 svn wrap/prog.c new file mode 100644 index 0000000..6e2c4d8 --- /dev/null +++ b/devtools/meson/manual tests/10 svn wrap/prog.c @@ -0,0 +1,6 @@ +#include"subproj.h" + +int main(void) { + subproj_function(); + return 0; +} diff --git a/devtools/meson/manual tests/10 svn wrap/subprojects/samplesubproject.wrap b/devtools/meson/manual tests/10 svn wrap/subprojects/samplesubproject.wrap new file mode 100644 index 0000000..c8a687e --- /dev/null +++ b/devtools/meson/manual tests/10 svn wrap/subprojects/samplesubproject.wrap @@ -0,0 +1,4 @@ +[wrap-svn] +directory=samplesubproject +url=https://svn.code.sf.net/p/mesonsubproject/code/trunk +revision=head diff --git a/devtools/meson/manual tests/11 wrap imposter/meson.build b/devtools/meson/manual tests/11 wrap imposter/meson.build new file mode 100644 index 0000000..d0575ac --- /dev/null +++ b/devtools/meson/manual tests/11 wrap imposter/meson.build @@ -0,0 +1,8 @@ +project('evil URL') +# showing that new Meson wrap.py code tries to stop imposter WrapDB URLs +# a WrapException is raised. +# +# ERROR: https://wrapdb.mesonbuild.com.invalid/v1/projects/zlib/1.2.11/4/get_zip may be a WrapDB-impersonating URL +# + +subproject('zlib') \ No newline at end of file diff --git a/devtools/meson/manual tests/11 wrap imposter/subprojects/zlib.wrap b/devtools/meson/manual tests/11 wrap imposter/subprojects/zlib.wrap new file mode 100644 index 0000000..b88f8f2 --- /dev/null +++ b/devtools/meson/manual tests/11 wrap imposter/subprojects/zlib.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = zlib-1.2.8 + +source_url = https://zlib.net/zlib-1.2.11.tar.gz +source_filename = zlib-1.2.11.tar.gz +source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 + +patch_url = https://wrapdb.mesonbuild.com.invalid/v1/projects/zlib/1.2.11/4/get_zip +patch_filename = zlib-1.2.11-4-wrap.zip +patch_hash = 886b67480dbe73b406ad83a1dd6d9596f93089d90c220ccfc91944c95f1c68c4 \ No newline at end of file diff --git a/devtools/meson/manual tests/12 wrap mirror/meson.build b/devtools/meson/manual tests/12 wrap mirror/meson.build new file mode 100644 index 0000000..d299577 --- /dev/null +++ b/devtools/meson/manual tests/12 wrap mirror/meson.build @@ -0,0 +1,4 @@ +project('downloader') +# this test will timeout, showing that a subdomain isn't caught as masquerading url + +subproject('zlib') diff --git a/devtools/meson/manual tests/12 wrap mirror/subprojects/zlib.wrap b/devtools/meson/manual tests/12 wrap mirror/subprojects/zlib.wrap new file mode 100644 index 0000000..de0b9ad --- /dev/null +++ b/devtools/meson/manual tests/12 wrap mirror/subprojects/zlib.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = zlib-1.2.8 + +source_url = https://zlib.net/zlib-1.2.11.tar.gz +source_filename = zlib-1.2.11.tar.gz +source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 + +patch_url = https://mirror1.wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/4/get_zip +patch_filename = zlib-1.2.11-4-wrap.zip +patch_hash = 886b67480dbe73b406ad83a1dd6d9596f93089d90c220ccfc91944c95f1c68c4 \ No newline at end of file diff --git a/devtools/meson/manual tests/13 builddir upgrade/data/foo.dat b/devtools/meson/manual tests/13 builddir upgrade/data/foo.dat new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/manual tests/13 builddir upgrade/foo.1 b/devtools/meson/manual tests/13 builddir upgrade/foo.1 new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/manual tests/13 builddir upgrade/foo.c b/devtools/meson/manual tests/13 builddir upgrade/foo.c new file mode 100644 index 0000000..f8edd23 --- /dev/null +++ b/devtools/meson/manual tests/13 builddir upgrade/foo.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello world!\n"); + return 0; +} diff --git a/devtools/meson/manual tests/13 builddir upgrade/lib.c b/devtools/meson/manual tests/13 builddir upgrade/lib.c new file mode 100644 index 0000000..2ea9c7d --- /dev/null +++ b/devtools/meson/manual tests/13 builddir upgrade/lib.c @@ -0,0 +1,9 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define DLL_PUBLIC __declspec(dllexport) +#else +#define DLL_PUBLIC +#endif + +int DLL_PUBLIC foo(void) { + return 0; +} diff --git a/devtools/meson/manual tests/13 builddir upgrade/meson.build b/devtools/meson/manual tests/13 builddir upgrade/meson.build new file mode 100644 index 0000000..34ae39c --- /dev/null +++ b/devtools/meson/manual tests/13 builddir upgrade/meson.build @@ -0,0 +1,21 @@ +project('check old builddirs in a stable release', 'c') + +lib = both_libraries('lib', 'lib.c') +exe = executable('foo', 'foo.c', link_with: lib, install: true) +test('exe', exe) + +install_data('data/foo.dat', install_dir: get_option('datadir') / 'foo') +install_man('foo.1') + +py = import('python').find_installation() +py.install_sources('mod.py', subdir: 'foo') +install_subdir('data', install_dir: py.get_install_dir()) + +custom_target( + input: 'mod.py', + output: 'hello.dat', + command: [py, '@INPUT@'], + capture: true, + install: true, + install_dir: get_option('localstatedir') / 'foo', +) diff --git a/devtools/meson/manual tests/13 builddir upgrade/mod.py b/devtools/meson/manual tests/13 builddir upgrade/mod.py new file mode 100644 index 0000000..60f08aa --- /dev/null +++ b/devtools/meson/manual tests/13 builddir upgrade/mod.py @@ -0,0 +1 @@ +print('Hello world!') diff --git a/devtools/meson/manual tests/2 multiwrap/meson.build b/devtools/meson/manual tests/2 multiwrap/meson.build new file mode 100644 index 0000000..a4c42f4 --- /dev/null +++ b/devtools/meson/manual tests/2 multiwrap/meson.build @@ -0,0 +1,12 @@ +project('multiwrap', 'c', + default_options : 'c_std=c99') + +# Using multiple downloaded projects for great justice. + +cc = meson.get_compiler('c') + +luadep = dependency('lua', fallback : ['lua', 'lua_dep']) +pngdep = dependency('libpng', fallback : ['libpng', 'png_dep']) + +executable('prog', 'prog.c', + dependencies : [pngdep, luadep]) diff --git a/devtools/meson/manual tests/2 multiwrap/prog.c b/devtools/meson/manual tests/2 multiwrap/prog.c new file mode 100644 index 0000000..dd0349e --- /dev/null +++ b/devtools/meson/manual tests/2 multiwrap/prog.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#if !defined(_MSC_VER) +#include +#endif + +static void *l_alloc (void *ud, void *ptr, size_t osize, + size_t nsize) { + (void)ud; + (void)osize; + if (nsize == 0) { + free(ptr); + return NULL; + } else { + return realloc(ptr, nsize); + } +} + +void open_image(const char *fname) { + png_image image; + + memset(&image, 0, (sizeof image)); + image.version = PNG_IMAGE_VERSION; + + if(png_image_begin_read_from_file(&image, fname) != 0) { + png_bytep buffer; + + image.format = PNG_FORMAT_RGBA; + buffer = malloc(PNG_IMAGE_SIZE(image)); + + if(png_image_finish_read(&image, NULL, buffer, 0, NULL) != 0) { + printf("Image %s read failed: %s\n", fname, image.message); + } +// png_free_image(&image); + free(buffer); + } else { + printf("Image %s open failed: %s", fname, image.message); + } +} + +int printer(lua_State *l) { + if(!lua_isstring(l, 1)) { + fprintf(stderr, "Incorrect call.\n"); + return 0; + } + open_image(lua_tostring(l, 1)); + return 0; +} + + +int main(int argc, char **argv) { + lua_State *l = lua_newstate(l_alloc, NULL); + if(!l) { + printf("Lua state allocation failed.\n"); + return 1; + } + lua_register(l, "printer", printer); + lua_getglobal(l, "printer"); + lua_pushliteral(l, "foobar.png"); + lua_call(l, 1, 0); + lua_close(l); + return 0; +} diff --git a/devtools/meson/manual tests/2 multiwrap/subprojects/libpng.wrap b/devtools/meson/manual tests/2 multiwrap/subprojects/libpng.wrap new file mode 100644 index 0000000..283775c --- /dev/null +++ b/devtools/meson/manual tests/2 multiwrap/subprojects/libpng.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = libpng-1.6.34 + +source_url = ftp://ftp-osl.osuosl.org/pub/libpng/src/libpng16/libpng-1.6.34.tar.xz +source_filename = libpng-1.6.34.tar.xz +source_hash = 2f1e960d92ce3b3abd03d06dfec9637dfbd22febf107a536b44f7a47c60659f6 + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/libpng/1.6.34/1/get_zip +patch_filename = libpng-1.6.34-1-wrap.zip +patch_hash = 2123806eba8180c164e33a210f2892bbeb2473b69e56aecc786574e9221e6f20 diff --git a/devtools/meson/manual tests/2 multiwrap/subprojects/lua.wrap b/devtools/meson/manual tests/2 multiwrap/subprojects/lua.wrap new file mode 100644 index 0000000..c1a179a --- /dev/null +++ b/devtools/meson/manual tests/2 multiwrap/subprojects/lua.wrap @@ -0,0 +1,11 @@ +[wrap-file] +directory = lua-5.3.0 + +source_url = http://www.lua.org/ftp/lua-5.3.0.tar.gz +source_filename = lua-5.3.0.tar.gz +source_hash = ae4a5eb2d660515eb191bfe3e061f2b8ffe94dce73d32cfd0de090ddcc0ddb01 + + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/lua/5.3.0/5/get_zip +patch_filename = lua-5.3.0-5-wrap.zip +patch_hash = 439038309a0700adfb67d764b3fe935ed8601b31f819fc369e1438c6e79334dd diff --git a/devtools/meson/manual tests/2 multiwrap/subprojects/zlib.wrap b/devtools/meson/manual tests/2 multiwrap/subprojects/zlib.wrap new file mode 100644 index 0000000..6d5896f --- /dev/null +++ b/devtools/meson/manual tests/2 multiwrap/subprojects/zlib.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = zlib-1.2.8 + +source_url = http://zlib.net/fossils/zlib-1.2.8.tar.gz +source_filename = zlib-1.2.8.tar.gz +source_hash = 36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d + +patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.8/8/get_zip +patch_filename = zlib-1.2.8-8-wrap.zip +patch_hash = 17c52a0e0c59ce926d3959005d5cd8178c6c7e2c9a4a1304279a8320c955ac60 diff --git a/devtools/meson/manual tests/3 git wrap/meson.build b/devtools/meson/manual tests/3 git wrap/meson.build new file mode 100644 index 0000000..14b0671 --- /dev/null +++ b/devtools/meson/manual tests/3 git wrap/meson.build @@ -0,0 +1,10 @@ +project('git outchecker', 'c') + +sp = subproject('samplesubproject') + +exe = executable('gitprog', 'prog.c', +include_directories : sp.get_variable('subproj_inc'), +link_with : sp.get_variable('subproj_lib'), +) + +test('maintest', exe) diff --git a/devtools/meson/manual tests/3 git wrap/prog.c b/devtools/meson/manual tests/3 git wrap/prog.c new file mode 100644 index 0000000..6e2c4d8 --- /dev/null +++ b/devtools/meson/manual tests/3 git wrap/prog.c @@ -0,0 +1,6 @@ +#include"subproj.h" + +int main(void) { + subproj_function(); + return 0; +} diff --git a/devtools/meson/manual tests/3 git wrap/subprojects/samplesubproject.wrap b/devtools/meson/manual tests/3 git wrap/subprojects/samplesubproject.wrap new file mode 100644 index 0000000..f52190b --- /dev/null +++ b/devtools/meson/manual tests/3 git wrap/subprojects/samplesubproject.wrap @@ -0,0 +1,4 @@ +[wrap-git] +directory=samplesubproject +url=https://github.com/jpakkane/samplesubproject.git +revision=head diff --git a/devtools/meson/manual tests/4 standalone binaries/Info.plist b/devtools/meson/manual tests/4 standalone binaries/Info.plist new file mode 100644 index 0000000..0f0c90e --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleGetInfoString + MyApp + CFBundleExecutable + myapp.sh + CFBundleIdentifier + com.example.me + CFBundleName + myapp + CFBundleIconFile + myapp.icns + CFBundleShortVersionString + 1.0 + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + IFMajorVersion + 0 + IFMinorVersion + 1 + + diff --git a/devtools/meson/manual tests/4 standalone binaries/build_linux_package.sh b/devtools/meson/manual tests/4 standalone binaries/build_linux_package.sh new file mode 100644 index 0000000..783981e --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/build_linux_package.sh @@ -0,0 +1,12 @@ +#!/bin/sh -eu + +curdir=`pwd` +rm -rf buildtmp +mkdir buildtmp +LDFLAGS=-static-libstdc++ ~/meson/meson.py buildtmp --buildtype=release --prefix=/tmp/myapp --libdir=lib --strip +ninja -C buildtmp install +rm -rf buildtmp +cd /tmp/ +tar czf myapp.tar.gz myapp +mv myapp.tar.gz "$curdir" +rm -rf myapp diff --git a/devtools/meson/manual tests/4 standalone binaries/build_osx_package.sh b/devtools/meson/manual tests/4 standalone binaries/build_osx_package.sh new file mode 100644 index 0000000..8a94ca5 --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/build_osx_package.sh @@ -0,0 +1,20 @@ +#!/bin/sh -eu + +rm -rf buildtmp +mkdir buildtmp +~/meson/meson.py buildtmp --buildtype=release --prefix=/tmp/myapp.app --bindir=Contents/MacOS +ninja -C buildtmp install +rm -rf buildtmp +mkdir -p mnttmp +rm -f working.dmg +gunzip < template.dmg.gz > working.dmg +hdiutil attach working.dmg -noautoopen -quiet -mountpoint mnttmp +rm -rf mnttmp/myapp.app +mv /tmp/myapp.app mnttmp +# NOTE: output of hdiutil changes every now and then. +# Verify that this is still working. +hdiutil detach $(hdiutil info|grep "mnttmp"|awk '{print $1}') +rm -rf mnttmp +rm -f myapp.dmg +hdiutil convert working.dmg -quiet -format UDZO -imagekey zlib-level=9 -o myapp.dmg +rm -f working.dmg diff --git a/devtools/meson/manual tests/4 standalone binaries/build_windows_package.py b/devtools/meson/manual tests/4 standalone binaries/build_windows_package.py new file mode 100644 index 0000000..0932eac --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/build_windows_package.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import os, urllib.request, shutil, subprocess +from glob import glob + +sdl_url = 'http://libsdl.org/release/SDL2-devel-2.0.3-VC.zip' +sdl_filename = 'SDL2-devel-2.0.3-VC.zip' +sdl_dir = 'SDL2-2.0.3' + +shutil.rmtree('build', ignore_errors=True) +os.mkdir('build') + +if not os.path.exists(sdl_filename): + response = urllib.request.urlopen(sdl_url, timeout=600.0) + data = response.read() + open(sdl_filename, 'wb').write(data) + +shutil.unpack_archive(sdl_filename, 'build') + +libs = glob(os.path.join('build', sdl_dir, 'lib/x86/*')) +[shutil.copy(x, 'build') for x in libs] + +# Sorry for this hack but this needs to work during development +# when Meson is not in path. +subprocess.check_call(['python3', r'..\..\meson.py', 'build', + '--backend=ninja', '--buildtype=release']) +subprocess.check_call(['ninja'], cwd='build') +shutil.copy('myapp.iss', 'build') +subprocess.check_call([r'\Program Files\Inno Setup 5\ISCC.exe', 'myapp.iss'], + cwd='build') +shutil.copy('build/setup.exe', 'myapp 1.0.exe') +shutil.rmtree('build') diff --git a/devtools/meson/manual tests/4 standalone binaries/linux_bundler.sh b/devtools/meson/manual tests/4 standalone binaries/linux_bundler.sh new file mode 100644 index 0000000..2a8e907 --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/linux_bundler.sh @@ -0,0 +1,7 @@ +#!/bin/sh -eu + +libdir="${MESON_INSTALL_PREFIX}/lib" +mkdir -p $libdir +sdlfile=`ldd ${MESON_INSTALL_PREFIX}/bin/myapp | grep libSDL | cut -d ' ' -f 3` +cp $sdlfile "${libdir}" +strip "${libdir}/libSDL"* diff --git a/devtools/meson/manual tests/4 standalone binaries/meson.build b/devtools/meson/manual tests/4 standalone binaries/meson.build new file mode 100644 index 0000000..ad6645f --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/meson.build @@ -0,0 +1,38 @@ +project('myapp', 'cpp') + +sdl = dependency('sdl2', required : host_machine.system() != 'windows') + +if meson.get_compiler('cpp').get_id() != 'msvc' + add_global_arguments('-std=c++11', language : 'cpp') +endif + +if host_machine.system() == 'darwin' + install_data('myapp.sh', + install_dir : 'Contents/MacOS') + + install_data('myapp.icns', + install_dir : 'Contents/Resources') + + install_data('Info.plist', + install_dir : 'Contents') + + meson.add_install_script('osx_bundler.sh') +endif + +if host_machine.system() == 'linux' + install_data('myapp.sh', install_dir : '.') + meson.add_install_script('linux_bundler.sh') +endif + +extra_link_args = [] + +if host_machine.system() == 'windows' + str = '-I@0@/@1@'.format(meson.current_build_dir(), 'SDL2-2.0.3/include') + add_global_arguments(str, language : 'cpp') + extra_link_args = ['/SUBSYSTEM:CONSOLE', 'SDL2main.lib', 'SDL2.lib'] +endif + +prog = executable('myapp', 'myapp.cpp', +dependencies : sdl, +link_args : extra_link_args, +install : true) diff --git a/devtools/meson/manual tests/4 standalone binaries/myapp.cpp b/devtools/meson/manual tests/4 standalone binaries/myapp.cpp new file mode 100644 index 0000000..8ddff27 --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/myapp.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +int main(void) { + SDL_Surface *screenSurface; + SDL_Event e; + int keepGoing = 1; + std::string message; + + if(SDL_Init( SDL_INIT_VIDEO ) < 0) { + printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); + } + atexit(SDL_Quit); + + std::unique_ptr window(SDL_CreateWindow( "My application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN), SDL_DestroyWindow); + screenSurface = SDL_GetWindowSurface(window.get()); + + // Use iostream to make sure we have not screwed + // up libstdc++ linking. + message = "Window created."; + message += " Starting main loop."; + std::cout << message << std::endl; + + while(keepGoing) { + while(SDL_PollEvent(&e) != 0) { + if(e.type == SDL_QUIT) { + keepGoing = 0; + break; + } + } + SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0x00, 0x00)); + SDL_UpdateWindowSurface(window.get()); + SDL_Delay(100); + } + + return 0; +} diff --git a/devtools/meson/manual tests/4 standalone binaries/myapp.icns b/devtools/meson/manual tests/4 standalone binaries/myapp.icns new file mode 100644 index 0000000000000000000000000000000000000000..633195454d7dd4b045637131696c2d0b66fabebf GIT binary patch literal 1831 zcmai#`8(SQ9>>2qCL<;52*xpv)^1g+(*~)dRHAhbb#)wJQ5td#p^iaoWUOPHwPoE( z$59p4@7{@CgWw#?R*cmK7&+EmgWRIR};1 zQ36$?4P__>__Gr~f?mP}eq4Gx8&0oUr#Ma|_H0JPl~9TP>AVJy$Gr<`-ta4Hk^3nEdyVi1L`V>vU&B4UfM~ss+xxCuv_t`!{J<1+ ztLIhUdQj!1D=v2%Yj;3JH?o8{AwjpjWhV0KzEbb~Dnqs66kJpA?0AAiA%Mqsx{)R) z%{B^nGuvNhfC*V?Of2$HO|*w?yVYz50@%aanXz-*egg!+it|kCaIXDBXg&c5v(Y>2 z?2+3fuh?@*o{{~u<+5mr!XQX*YYHknJCKKr=axO`^C=`yMG3EJ!>8hR zDqh;Qg@L^_-EBY6WQTKV-asZCr5n+D;jI9+Qg1)7my%y)pzh-Ub^-OT-=AY=`!@jW z785&lDoEw_)Ww$cEtnb4sp`PgH~QxT*rz?|IOp)@npFO85Ar&GJvTaNi~r0YI|J`!4WBOM(BYH6!S2Us$uN*<24DpJ82C$s|m9#*}>W2M#%->=# z_D*&@#2zF@lEkt+ABdZ{^FUx}ZrEa%`a5E$c~37DLYo^V75|dpU9{UIc3y3{P9Y>Q zC#+yASaYnbz{YlgpW(;%T$^&`dRSUQCTU*etf@+jcF(c6Axs@VT_7xVPb?f%hm@+F z<>HcHjX0@pw@|SviGmp)$Cb9Ml=-03y;slJ5*>}u81F@;Z8NTk*R?zrLl~aiwM&jO zLtro=+=1i%A|bP);$}UI5wK-@$be7ZMl5EfZs(4rHT#m--H!78DdrDz*J&%`kpeAg zx2Y7~f%6ftU+O=v3spIv9-R=$>y_W;FO~{@nj|A!{~GU}S`HM4ZqPTW=2|qA7ovNH zD@y89@g)J@vN^R+x1l<4{9r{>GTTC=^5SNAaJa1_l3Db6KiCQr3@seRsYtqX`r_Jg zX7|1^FZ^UPyb%Ii77y7!UJgm@KUn^)^Q-Zo0M9&FhsPi4rY4?V^>azJI>sTsH7*mh zM~vroBG0osxDN)6qK(#aAdYU z*s6F`^!`-FjjXm%!51)=2LP1|s)Y(ul%yx&Vq zqQ;MnBJaWjipAgPsfe9Z)U3fsfg$B$5V1$v)Vx?IFm{=|AkA$>{3Ui zKdghLk47Zp45Dn>aNen)VzKAfm?7naKUc~B eb4^4pmvSnc{f{oj2hAh10q)LMuP~es8tpK literal 0 HcmV?d00001 diff --git a/devtools/meson/manual tests/4 standalone binaries/myapp.iss b/devtools/meson/manual tests/4 standalone binaries/myapp.iss new file mode 100644 index 0000000..2bd441d --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/myapp.iss @@ -0,0 +1,18 @@ +; Innosetup file for My app. + +[Setup] +AppName=My App +AppVersion=1.0 +DefaultDirName={pf}\My App +DefaultGroupName=My App +UninstallDisplayIcon={app}\myapp.exe +Compression=lzma2 +SolidCompression=yes +OutputDir=. + +[Files] +Source: "myapp.exe"; DestDir: "{app}" +Source: "SDL2.dll"; DestDir: "{app}" + +;[Icons] +;Name: "{group}\My App"; Filename: "{app}\myapp.exe" diff --git a/devtools/meson/manual tests/4 standalone binaries/myapp.sh b/devtools/meson/manual tests/4 standalone binaries/myapp.sh new file mode 100644 index 0000000..3191483 --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/myapp.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd "${0%/*}" + +if [ `uname` == 'Darwin' ]; then + ./myapp +else + export LD_LIBRARY_PATH="`pwd`/lib" + bin/myapp +fi diff --git a/devtools/meson/manual tests/4 standalone binaries/osx_bundler.sh b/devtools/meson/manual tests/4 standalone binaries/osx_bundler.sh new file mode 100644 index 0000000..3bad65f --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/osx_bundler.sh @@ -0,0 +1,6 @@ +#!/bin/sh -eu + +mkdir -p ${MESON_INSTALL_PREFIX}/Contents/Frameworks +cp -R /Library/Frameworks/SDL2.framework ${MESON_INSTALL_PREFIX}/Contents/Frameworks + +install_name_tool -change @rpath/SDL2.framework/Versions/A/SDL2 @executable_path/../Frameworks/SDL2.framework/Versions/A/SDL2 ${MESON_INSTALL_PREFIX}/Contents/MacOS/myapp diff --git a/devtools/meson/manual tests/4 standalone binaries/readme.txt b/devtools/meson/manual tests/4 standalone binaries/readme.txt new file mode 100644 index 0000000..39d21f3 --- /dev/null +++ b/devtools/meson/manual tests/4 standalone binaries/readme.txt @@ -0,0 +1,11 @@ +This directory shows how you can build redistributable binaries. On +OSX this means building an app bundle and a .dmg installer. On Linux +it means building an archive that bundles its dependencies. On Windows +it means building an .exe installer. + +To build each package you run the corresponding build_ARCH.sh build +script. + +On Linux you must build the package on the oldest distribution you +plan to support (Debian stable/oldstable and old CentOS are the common +choice here). diff --git a/devtools/meson/manual tests/4 standalone binaries/template.dmg.gz b/devtools/meson/manual tests/4 standalone binaries/template.dmg.gz new file mode 100644 index 0000000000000000000000000000000000000000..fcb6d6115080784c39eee3bfdcb771955a11f5d5 GIT binary patch literal 37311 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 Oz+d)G=$!pU=l=jiVxCX{ literal 0 HcmV?d00001 diff --git a/devtools/meson/manual tests/5 rpm/lib.c b/devtools/meson/manual tests/5 rpm/lib.c new file mode 100644 index 0000000..efc230a --- /dev/null +++ b/devtools/meson/manual tests/5 rpm/lib.c @@ -0,0 +1,6 @@ +#include"lib.h" + +char *meson_print(void) +{ + return "Hello, world!"; +} diff --git a/devtools/meson/manual tests/5 rpm/lib.h b/devtools/meson/manual tests/5 rpm/lib.h new file mode 100644 index 0000000..08fc961 --- /dev/null +++ b/devtools/meson/manual tests/5 rpm/lib.h @@ -0,0 +1 @@ +char *meson_print(void); diff --git a/devtools/meson/manual tests/5 rpm/main.c b/devtools/meson/manual tests/5 rpm/main.c new file mode 100644 index 0000000..8b1d193 --- /dev/null +++ b/devtools/meson/manual tests/5 rpm/main.c @@ -0,0 +1,8 @@ +#include +#include +int main(void) +{ + char *t = meson_print(); + printf("%s", t); + return 0; +} diff --git a/devtools/meson/manual tests/5 rpm/meson.build b/devtools/meson/manual tests/5 rpm/meson.build new file mode 100644 index 0000000..131da39 --- /dev/null +++ b/devtools/meson/manual tests/5 rpm/meson.build @@ -0,0 +1,14 @@ +project('test spec', 'c') + +rpm = import('rpm') +dependency('zlib') +find_program('nonexistprog', required : false) + +lib = shared_library('mesontest_shared', ['lib.c', 'lib.h'], + version : '0.1', soversion : '0', + install : true) +executable('mesontest-bin', 'main.c', + link_with : lib, + install : true) + +rpm.generate_spec_template() diff --git a/devtools/meson/manual tests/6 hg wrap/meson.build b/devtools/meson/manual tests/6 hg wrap/meson.build new file mode 100644 index 0000000..d0e7550 --- /dev/null +++ b/devtools/meson/manual tests/6 hg wrap/meson.build @@ -0,0 +1,10 @@ +project('Mercurial outchecker', 'c') + +sp = subproject('samplesubproject') + +exe = executable('gitprog', 'prog.c', +include_directories : sp.get_variable('subproj_inc'), +link_with : sp.get_variable('subproj_lib'), +) + +test('maintest', exe) diff --git a/devtools/meson/manual tests/6 hg wrap/prog.c b/devtools/meson/manual tests/6 hg wrap/prog.c new file mode 100644 index 0000000..6e2c4d8 --- /dev/null +++ b/devtools/meson/manual tests/6 hg wrap/prog.c @@ -0,0 +1,6 @@ +#include"subproj.h" + +int main(void) { + subproj_function(); + return 0; +} diff --git a/devtools/meson/manual tests/6 hg wrap/subprojects/samplesubproject.wrap b/devtools/meson/manual tests/6 hg wrap/subprojects/samplesubproject.wrap new file mode 100644 index 0000000..6d3b3f2 --- /dev/null +++ b/devtools/meson/manual tests/6 hg wrap/subprojects/samplesubproject.wrap @@ -0,0 +1,4 @@ +[wrap-hg] +directory=samplesubproject +url=https://bitbucket.org/jpakkane/samplesubproject +revision=tip diff --git a/devtools/meson/manual tests/7 vala composite widgets/meson.build b/devtools/meson/manual tests/7 vala composite widgets/meson.build new file mode 100644 index 0000000..579ca51 --- /dev/null +++ b/devtools/meson/manual tests/7 vala composite widgets/meson.build @@ -0,0 +1,21 @@ +project('composite', 'vala', 'c') +gnome = import('gnome') +deps = [ + dependency('glib-2.0', version : '>=2.38'), + dependency('gobject-2.0'), + dependency('gtk+-3.0'), +] +res = files('my-resources.xml') +gres = gnome.compile_resources( + 'my', res, + source_dir : '.', +) +executable( + 'demo', + sources : [ + 'mywidget.vala', + gres, + ], + dependencies : deps, + vala_args : ['--gresources', res], +) diff --git a/devtools/meson/manual tests/7 vala composite widgets/my-resources.xml b/devtools/meson/manual tests/7 vala composite widgets/my-resources.xml new file mode 100644 index 0000000..b5743c1 --- /dev/null +++ b/devtools/meson/manual tests/7 vala composite widgets/my-resources.xml @@ -0,0 +1,6 @@ + + + + mywidget.ui + + diff --git a/devtools/meson/manual tests/7 vala composite widgets/mywidget.ui b/devtools/meson/manual tests/7 vala composite widgets/mywidget.ui new file mode 100644 index 0000000..2d6286c --- /dev/null +++ b/devtools/meson/manual tests/7 vala composite widgets/mywidget.ui @@ -0,0 +1,70 @@ + + + + + diff --git a/devtools/meson/manual tests/7 vala composite widgets/mywidget.vala b/devtools/meson/manual tests/7 vala composite widgets/mywidget.vala new file mode 100644 index 0000000..68eaecc --- /dev/null +++ b/devtools/meson/manual tests/7 vala composite widgets/mywidget.vala @@ -0,0 +1,41 @@ +using Gtk; + +[GtkTemplate (ui = "/org/foo/my/mywidget.ui")] +public class MyWidget : Box { + public string text { + get { return entry.text; } + set { entry.text = value; } + } + + [GtkChild] + private Entry entry; + + public MyWidget (string text) { + this.text = text; + } + + [GtkCallback] + private void on_button_clicked (Button button) { + print ("The button was clicked with entry text: %s\n", entry.text); + } + + [GtkCallback] + private void on_entry_changed (Editable editable) { + print ("The entry text changed: %s\n", entry.text); + + notify_property ("text"); + } +} + +void main(string[] args) { + Gtk.init (ref args); + var win = new Window(); + win.destroy.connect (Gtk.main_quit); + + var widget = new MyWidget ("The entry text!"); + + win.add (widget); + win.show_all (); + + Gtk.main (); +} diff --git a/devtools/meson/manual tests/8 timeout/meson.build b/devtools/meson/manual tests/8 timeout/meson.build new file mode 100644 index 0000000..8ba7d4b --- /dev/null +++ b/devtools/meson/manual tests/8 timeout/meson.build @@ -0,0 +1,8 @@ +project('timeout', 'c') + +# This creates a test that times out. It is a manual test +# because currently there is no test suite for test that are expected +# to fail during unit test phase. + +exe = executable('sleepprog', 'sleepprog.c') +test('timeout', exe, timeout : 1) diff --git a/devtools/meson/manual tests/8 timeout/sleepprog.c b/devtools/meson/manual tests/8 timeout/sleepprog.c new file mode 100644 index 0000000..8875e12 --- /dev/null +++ b/devtools/meson/manual tests/8 timeout/sleepprog.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + sleep(1000); + return 0; +} diff --git a/devtools/meson/meson.egg-info/PKG-INFO b/devtools/meson/meson.egg-info/PKG-INFO new file mode 100644 index 0000000..ff92e6c --- /dev/null +++ b/devtools/meson/meson.egg-info/PKG-INFO @@ -0,0 +1,33 @@ +Metadata-Version: 2.1 +Name: meson +Version: 1.2.2 +Summary: A high performance build system +Home-page: https://mesonbuild.com +Author: Jussi Pakkanen +Author-email: jpakkane@gmail.com +License: Apache License, Version 2.0 +Project-URL: Source, https://github.com/mesonbuild/meson +Keywords: meson,mesonbuild,build system,cmake +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Natural Language :: English +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: POSIX :: Linux +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Topic :: Software Development :: Build Tools +Requires-Python: >=3.7 +Provides-Extra: ninja +Provides-Extra: progress +Provides-Extra: typing +License-File: COPYING + +Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. diff --git a/devtools/meson/meson.egg-info/SOURCES.txt b/devtools/meson/meson.egg-info/SOURCES.txt new file mode 100644 index 0000000..c24b711 --- /dev/null +++ b/devtools/meson/meson.egg-info/SOURCES.txt @@ -0,0 +1,4226 @@ +COPYING +MANIFEST.in +README.md +contributing.md +meson.py +pyproject.toml +run_cross_test.py +run_meson_command_tests.py +run_project_tests.py +run_tests.py +run_unittests.py +setup.cfg +setup.py +cross/arm64cl.txt +cross/armcc.txt +cross/armclang-linux.txt +cross/armclang.txt +cross/c2000.txt +cross/ccomp-armv7a.txt +cross/ccrx.txt +cross/iphone.txt +cross/linux-mingw-w64-32bit.json +cross/linux-mingw-w64-32bit.txt +cross/linux-mingw-w64-64bit.json +cross/linux-mingw-w64-64bit.txt +cross/metrowerks-arm.txt +cross/metrowerks-eppc.txt +cross/metrowerks.lcf +cross/msp430.txt +cross/none.txt +cross/ownstdlib.txt +cross/tvos.txt +cross/ubuntu-armhf.json +cross/ubuntu-armhf.txt +cross/ubuntu-faketarget.txt +cross/wasm.txt +cross/xc16.txt +data/.coveragerc.in +data/com.mesonbuild.install.policy +data/macros.meson +data/schema.xsd +data/test.schema.json +data/shell-completions/bash/meson +data/shell-completions/zsh/_meson +data/syntax-highlighting/vim/README +data/syntax-highlighting/vim/ftdetect/meson.vim +data/syntax-highlighting/vim/ftplugin/meson.vim +data/syntax-highlighting/vim/indent/meson.vim +data/syntax-highlighting/vim/syntax/meson.vim +graphics/meson_logo.svg +graphics/meson_logo_big.png +graphics/wrap_logo.svg +man/meson.1 +manual tests/1 wrap/main.c +manual tests/1 wrap/meson.build +manual tests/1 wrap/subprojects/sqlite.wrap +manual tests/10 svn wrap/meson.build +manual tests/10 svn wrap/prog.c +manual tests/10 svn wrap/subprojects/samplesubproject.wrap +manual tests/11 wrap imposter/meson.build +manual tests/11 wrap imposter/subprojects/zlib.wrap +manual tests/12 wrap mirror/meson.build +manual tests/12 wrap mirror/subprojects/zlib.wrap +manual tests/13 builddir upgrade/foo.1 +manual tests/13 builddir upgrade/foo.c +manual tests/13 builddir upgrade/lib.c +manual tests/13 builddir upgrade/meson.build +manual tests/13 builddir upgrade/mod.py +manual tests/13 builddir upgrade/data/foo.dat +manual tests/2 multiwrap/meson.build +manual tests/2 multiwrap/prog.c +manual tests/2 multiwrap/subprojects/libpng.wrap +manual tests/2 multiwrap/subprojects/lua.wrap +manual tests/2 multiwrap/subprojects/zlib.wrap +manual tests/3 git wrap/meson.build +manual tests/3 git wrap/prog.c +manual tests/3 git wrap/subprojects/samplesubproject.wrap +manual tests/4 standalone binaries/Info.plist +manual tests/4 standalone binaries/build_linux_package.sh +manual tests/4 standalone binaries/build_osx_package.sh +manual tests/4 standalone binaries/build_windows_package.py +manual tests/4 standalone binaries/linux_bundler.sh +manual tests/4 standalone binaries/meson.build +manual tests/4 standalone binaries/myapp.cpp +manual tests/4 standalone binaries/myapp.icns +manual tests/4 standalone binaries/myapp.iss +manual tests/4 standalone binaries/myapp.sh +manual tests/4 standalone binaries/osx_bundler.sh +manual tests/4 standalone binaries/readme.txt +manual tests/4 standalone binaries/template.dmg.gz +manual tests/5 rpm/lib.c +manual tests/5 rpm/lib.h +manual tests/5 rpm/main.c +manual tests/5 rpm/meson.build +manual tests/6 hg wrap/meson.build +manual tests/6 hg wrap/prog.c +manual tests/6 hg wrap/subprojects/samplesubproject.wrap +manual tests/7 vala composite widgets/meson.build +manual tests/7 vala composite widgets/my-resources.xml +manual tests/7 vala composite widgets/mywidget.ui +manual tests/7 vala composite widgets/mywidget.vala +manual tests/8 timeout/meson.build +manual tests/8 timeout/sleepprog.c +meson.egg-info/PKG-INFO +meson.egg-info/SOURCES.txt +meson.egg-info/dependency_links.txt +meson.egg-info/entry_points.txt +meson.egg-info/requires.txt +meson.egg-info/top_level.txt +mesonbuild/__init__.py +mesonbuild/_pathlib.py +mesonbuild/_typing.py +mesonbuild/arglist.py +mesonbuild/build.py +mesonbuild/coredata.py +mesonbuild/depfile.py +mesonbuild/envconfig.py +mesonbuild/environment.py +mesonbuild/mcompile.py +mesonbuild/mconf.py +mesonbuild/mdevenv.py +mesonbuild/mdist.py +mesonbuild/mesondata.py +mesonbuild/mesonlib.py +mesonbuild/mesonmain.py +mesonbuild/minit.py +mesonbuild/minstall.py +mesonbuild/mintro.py +mesonbuild/mlog.py +mesonbuild/mparser.py +mesonbuild/msetup.py +mesonbuild/msubprojects.py +mesonbuild/mtest.py +mesonbuild/munstable_coredata.py +mesonbuild/optinterpreter.py +mesonbuild/programs.py +mesonbuild/rewriter.py +mesonbuild/ast/__init__.py +mesonbuild/ast/interpreter.py +mesonbuild/ast/introspection.py +mesonbuild/ast/postprocess.py +mesonbuild/ast/printer.py +mesonbuild/ast/visitor.py +mesonbuild/backend/__init__.py +mesonbuild/backend/backends.py +mesonbuild/backend/ninjabackend.py +mesonbuild/backend/nonebackend.py +mesonbuild/backend/vs2010backend.py +mesonbuild/backend/vs2012backend.py +mesonbuild/backend/vs2013backend.py +mesonbuild/backend/vs2015backend.py +mesonbuild/backend/vs2017backend.py +mesonbuild/backend/vs2019backend.py +mesonbuild/backend/vs2022backend.py +mesonbuild/backend/xcodebackend.py +mesonbuild/cargo/__init__.py +mesonbuild/cargo/builder.py +mesonbuild/cargo/cfg.py +mesonbuild/cargo/interpreter.py +mesonbuild/cargo/manifest.py +mesonbuild/cargo/version.py +mesonbuild/cmake/__init__.py +mesonbuild/cmake/common.py +mesonbuild/cmake/executor.py +mesonbuild/cmake/fileapi.py +mesonbuild/cmake/generator.py +mesonbuild/cmake/interpreter.py +mesonbuild/cmake/toolchain.py +mesonbuild/cmake/traceparser.py +mesonbuild/cmake/tracetargets.py +mesonbuild/cmake/data/__init__.py +mesonbuild/cmake/data/preload.cmake +mesonbuild/compilers/__init__.py +mesonbuild/compilers/asm.py +mesonbuild/compilers/c.py +mesonbuild/compilers/c_function_attributes.py +mesonbuild/compilers/compilers.py +mesonbuild/compilers/cpp.py +mesonbuild/compilers/cs.py +mesonbuild/compilers/cuda.py +mesonbuild/compilers/cython.py +mesonbuild/compilers/d.py +mesonbuild/compilers/detect.py +mesonbuild/compilers/fortran.py +mesonbuild/compilers/java.py +mesonbuild/compilers/objc.py +mesonbuild/compilers/objcpp.py +mesonbuild/compilers/rust.py +mesonbuild/compilers/swift.py +mesonbuild/compilers/vala.py +mesonbuild/compilers/mixins/__init__.py +mesonbuild/compilers/mixins/arm.py +mesonbuild/compilers/mixins/ccrx.py +mesonbuild/compilers/mixins/clang.py +mesonbuild/compilers/mixins/clike.py +mesonbuild/compilers/mixins/compcert.py +mesonbuild/compilers/mixins/elbrus.py +mesonbuild/compilers/mixins/emscripten.py +mesonbuild/compilers/mixins/gnu.py +mesonbuild/compilers/mixins/intel.py +mesonbuild/compilers/mixins/islinker.py +mesonbuild/compilers/mixins/metrowerks.py +mesonbuild/compilers/mixins/pgi.py +mesonbuild/compilers/mixins/ti.py +mesonbuild/compilers/mixins/visualstudio.py +mesonbuild/compilers/mixins/xc16.py +mesonbuild/dependencies/__init__.py +mesonbuild/dependencies/base.py +mesonbuild/dependencies/boost.py +mesonbuild/dependencies/cmake.py +mesonbuild/dependencies/coarrays.py +mesonbuild/dependencies/configtool.py +mesonbuild/dependencies/cuda.py +mesonbuild/dependencies/detect.py +mesonbuild/dependencies/dev.py +mesonbuild/dependencies/dub.py +mesonbuild/dependencies/factory.py +mesonbuild/dependencies/framework.py +mesonbuild/dependencies/hdf5.py +mesonbuild/dependencies/misc.py +mesonbuild/dependencies/mpi.py +mesonbuild/dependencies/pkgconfig.py +mesonbuild/dependencies/platform.py +mesonbuild/dependencies/python.py +mesonbuild/dependencies/qt.py +mesonbuild/dependencies/scalapack.py +mesonbuild/dependencies/ui.py +mesonbuild/dependencies/data/CMakeLists.txt +mesonbuild/dependencies/data/CMakeListsLLVM.txt +mesonbuild/dependencies/data/CMakePathInfo.txt +mesonbuild/dependencies/data/__init__.py +mesonbuild/interpreter/__init__.py +mesonbuild/interpreter/compiler.py +mesonbuild/interpreter/dependencyfallbacks.py +mesonbuild/interpreter/interpreter.py +mesonbuild/interpreter/interpreterobjects.py +mesonbuild/interpreter/kwargs.py +mesonbuild/interpreter/mesonmain.py +mesonbuild/interpreter/type_checking.py +mesonbuild/interpreter/primitives/__init__.py +mesonbuild/interpreter/primitives/array.py +mesonbuild/interpreter/primitives/boolean.py +mesonbuild/interpreter/primitives/dict.py +mesonbuild/interpreter/primitives/integer.py +mesonbuild/interpreter/primitives/range.py +mesonbuild/interpreter/primitives/string.py +mesonbuild/interpreterbase/__init__.py +mesonbuild/interpreterbase/_unholder.py +mesonbuild/interpreterbase/baseobjects.py +mesonbuild/interpreterbase/decorators.py +mesonbuild/interpreterbase/disabler.py +mesonbuild/interpreterbase/exceptions.py +mesonbuild/interpreterbase/helpers.py +mesonbuild/interpreterbase/interpreterbase.py +mesonbuild/interpreterbase/operator.py +mesonbuild/linkers/__init__.py +mesonbuild/linkers/base.py +mesonbuild/linkers/detect.py +mesonbuild/linkers/linkers.py +mesonbuild/modules/__init__.py +mesonbuild/modules/cmake.py +mesonbuild/modules/cuda.py +mesonbuild/modules/dlang.py +mesonbuild/modules/external_project.py +mesonbuild/modules/fs.py +mesonbuild/modules/gnome.py +mesonbuild/modules/hotdoc.py +mesonbuild/modules/i18n.py +mesonbuild/modules/icestorm.py +mesonbuild/modules/java.py +mesonbuild/modules/keyval.py +mesonbuild/modules/modtest.py +mesonbuild/modules/pkgconfig.py +mesonbuild/modules/python.py +mesonbuild/modules/python3.py +mesonbuild/modules/qt.py +mesonbuild/modules/qt4.py +mesonbuild/modules/qt5.py +mesonbuild/modules/qt6.py +mesonbuild/modules/rust.py +mesonbuild/modules/simd.py +mesonbuild/modules/sourceset.py +mesonbuild/modules/wayland.py +mesonbuild/modules/windows.py +mesonbuild/scripts/__init__.py +mesonbuild/scripts/clangformat.py +mesonbuild/scripts/clangtidy.py +mesonbuild/scripts/cleantrees.py +mesonbuild/scripts/cmake_run_ctgt.py +mesonbuild/scripts/cmd_or_ps.ps1 +mesonbuild/scripts/copy.py +mesonbuild/scripts/coverage.py +mesonbuild/scripts/delwithsuffix.py +mesonbuild/scripts/depfixer.py +mesonbuild/scripts/depscan.py +mesonbuild/scripts/dirchanger.py +mesonbuild/scripts/env2mfile.py +mesonbuild/scripts/externalproject.py +mesonbuild/scripts/gettext.py +mesonbuild/scripts/gtkdochelper.py +mesonbuild/scripts/hotdochelper.py +mesonbuild/scripts/itstool.py +mesonbuild/scripts/meson_exe.py +mesonbuild/scripts/msgfmthelper.py +mesonbuild/scripts/pycompile.py +mesonbuild/scripts/python_info.py +mesonbuild/scripts/regen_checker.py +mesonbuild/scripts/run_tool.py +mesonbuild/scripts/scanbuild.py +mesonbuild/scripts/symbolextractor.py +mesonbuild/scripts/tags.py +mesonbuild/scripts/test_loaded_modules.py +mesonbuild/scripts/uninstall.py +mesonbuild/scripts/vcstagger.py +mesonbuild/scripts/yasm.py +mesonbuild/templates/__init__.py +mesonbuild/templates/cpptemplates.py +mesonbuild/templates/cstemplates.py +mesonbuild/templates/ctemplates.py +mesonbuild/templates/cudatemplates.py +mesonbuild/templates/dlangtemplates.py +mesonbuild/templates/fortrantemplates.py +mesonbuild/templates/javatemplates.py +mesonbuild/templates/mesontemplates.py +mesonbuild/templates/objcpptemplates.py +mesonbuild/templates/objctemplates.py +mesonbuild/templates/rusttemplates.py +mesonbuild/templates/samplefactory.py +mesonbuild/templates/sampleimpl.py +mesonbuild/templates/valatemplates.py +mesonbuild/utils/__init__.py +mesonbuild/utils/core.py +mesonbuild/utils/platform.py +mesonbuild/utils/posix.py +mesonbuild/utils/universal.py +mesonbuild/utils/vsenv.py +mesonbuild/utils/win32.py +mesonbuild/wrap/__init__.py +mesonbuild/wrap/wrap.py +mesonbuild/wrap/wraptool.py +packaging/License.rtf +packaging/create_zipapp.py +packaging/createmsi.py +packaging/createpkg.py +packaging/hook-mesonbuild.py +packaging/macpages/English.lproj/conclusion.html +packaging/macpages/English.lproj/license.html +packaging/macpages/English.lproj/welcome.html +test cases/cmake/1 basic/main.cpp +test cases/cmake/1 basic/meson.build +test cases/cmake/1 basic/subprojects/cmMod/CMakeLists.txt +test cases/cmake/1 basic/subprojects/cmMod/cmMod.cpp +test cases/cmake/1 basic/subprojects/cmMod/cmMod.hpp +test cases/cmake/1 basic/subprojects/cmMod/cpp_pch.hpp +test cases/cmake/10 header only/main.cpp +test cases/cmake/10 header only/meson.build +test cases/cmake/10 header only/subprojects/cmMod/CMakeLists.txt +test cases/cmake/10 header only/subprojects/cmMod/include/cmMod.hpp +test cases/cmake/11 cmake_module_path/meson.build +test cases/cmake/11 cmake_module_path/cmake/FindSomethingLikePython.cmake +test cases/cmake/11 cmake_module_path/subprojects/cmMod/CMakeLists.txt +test cases/cmake/11 cmake_module_path/subprojects/cmMod/gen.py +test cases/cmake/12 generator expressions/main.cpp +test cases/cmake/12 generator expressions/meson.build +test cases/cmake/12 generator expressions/test.json +test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt +test cases/cmake/12 generator expressions/subprojects/cmMod/include/cmMod.hpp +test cases/cmake/13 system includes/main.cpp +test cases/cmake/13 system includes/meson.build +test cases/cmake/13 system includes/subprojects/cmMod/CMakeLists.txt +test cases/cmake/13 system includes/subprojects/cmMod/cmMod.cpp +test cases/cmake/13 system includes/subprojects/cmMod/cmMod.hpp +test cases/cmake/13 system includes/subprojects/cmMod/sysInc/triggerWarn.hpp +test cases/cmake/14 fortran threads/meson.build +test cases/cmake/15 object library advanced/main.cpp +test cases/cmake/15 object library advanced/meson.build +test cases/cmake/15 object library advanced/subprojects/cmObjLib/CMakeLists.txt +test cases/cmake/15 object library advanced/subprojects/cmObjLib/genC.cpp +test cases/cmake/15 object library advanced/subprojects/cmObjLib/libA.cpp +test cases/cmake/15 object library advanced/subprojects/cmObjLib/libA.hpp +test cases/cmake/15 object library advanced/subprojects/cmObjLib/libB.cpp +test cases/cmake/15 object library advanced/subprojects/cmObjLib/libB.hpp +test cases/cmake/16 threads/main.cpp +test cases/cmake/16 threads/meson.build +test cases/cmake/16 threads/meson_options.txt +test cases/cmake/16 threads/test.json +test cases/cmake/16 threads/subprojects/cmMod/CMakeLists.txt +test cases/cmake/16 threads/subprojects/cmMod/cmMod.cpp +test cases/cmake/16 threads/subprojects/cmMod/cmMod.hpp +test cases/cmake/16 threads/subprojects/cmMod/main.cpp +test cases/cmake/17 include path order/main.cpp +test cases/cmake/17 include path order/meson.build +test cases/cmake/17 include path order/subprojects/cmMod/CMakeLists.txt +test cases/cmake/17 include path order/subprojects/cmMod/cmMod.cpp +test cases/cmake/17 include path order/subprojects/cmMod/incA/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incB/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incC/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incD/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incE/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incF/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incG/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incH/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incI/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incJ/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incL/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incM/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incN/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incO/cmMod.hpp +test cases/cmake/17 include path order/subprojects/cmMod/incP/cmMod.hpp +test cases/cmake/18 skip include files/main.cpp +test cases/cmake/18 skip include files/meson.build +test cases/cmake/18 skip include files/subprojects/cmMod/CMakeLists.txt +test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.cpp +test cases/cmake/18 skip include files/subprojects/cmMod/cmMod.hpp +test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/CMakeLists.txt +test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc1.cpp +test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc2.cpp +test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc3.cpp +test cases/cmake/18 skip include files/subprojects/cmMod/fakeInc/cmModInc4.cpp +test cases/cmake/19 advanced options/main.cpp +test cases/cmake/19 advanced options/meson.build +test cases/cmake/19 advanced options/test.json +test cases/cmake/19 advanced options/subprojects/cmOpts/CMakeLists.txt +test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.cpp +test cases/cmake/19 advanced options/subprojects/cmOpts/cmMod.hpp +test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.cpp +test cases/cmake/19 advanced options/subprojects/cmOpts/cmTest.hpp +test cases/cmake/19 advanced options/subprojects/cmOpts/main.cpp +test cases/cmake/2 advanced/main.cpp +test cases/cmake/2 advanced/meson.build +test cases/cmake/2 advanced/test.json +test cases/cmake/2 advanced/subprojects/cmMod/CMakeLists.txt +test cases/cmake/2 advanced/subprojects/cmMod/config.h.in +test cases/cmake/2 advanced/subprojects/cmMod/main.cpp +test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.cpp +test cases/cmake/2 advanced/subprojects/cmMod/lib/cmMod.hpp +test cases/cmake/20 cmake file/foolib.cmake.in +test cases/cmake/20 cmake file/meson.build +test cases/cmake/20 cmake file/test.json +test cases/cmake/21 shared module/meson.build +test cases/cmake/21 shared module/prog.c +test cases/cmake/21 shared module/runtime.c +test cases/cmake/21 shared module/subprojects/cmMod/CMakeLists.txt +test cases/cmake/21 shared module/subprojects/cmMod/module/module.c +test cases/cmake/21 shared module/subprojects/cmMod/module/module.h +test cases/cmake/22 cmake module/meson.build +test cases/cmake/22 cmake module/projectConfig.cmake.in +test cases/cmake/22 cmake module/test.json +test cases/cmake/22 cmake module/cmake_project/CMakeLists.txt +test cases/cmake/23 cmake toolchain/CMakeToolchain.cmake +test cases/cmake/23 cmake toolchain/meson.build +test cases/cmake/23 cmake toolchain/nativefile.ini.in +test cases/cmake/23 cmake toolchain/subprojects/cmMod/CMakeLists.txt +test cases/cmake/23 cmake toolchain/subprojects/cmModFortran/CMakeLists.txt +test cases/cmake/24 mixing languages/main.c +test cases/cmake/24 mixing languages/meson.build +test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt +test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.c +test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.h +test cases/cmake/24 mixing languages/subprojects/cmTest/cmTest.m +test cases/cmake/25 assembler/main.c +test cases/cmake/25 assembler/meson.build +test cases/cmake/25 assembler/subprojects/cmTest/CMakeLists.txt +test cases/cmake/25 assembler/subprojects/cmTest/cmTest.c +test cases/cmake/25 assembler/subprojects/cmTest/cmTestAsm.s +test cases/cmake/26 cmake package prefix dir/cmakePackagePrefixDirConfig.cmake.in +test cases/cmake/26 cmake package prefix dir/meson.build +test cases/cmake/26 cmake package prefix dir/test.json +test cases/cmake/3 advanced no dep/main.cpp +test cases/cmake/3 advanced no dep/meson.build +test cases/cmake/3 advanced no dep/test.json +test cases/cmake/3 advanced no dep/subprojects/cmMod/CMakeLists.txt +test cases/cmake/3 advanced no dep/subprojects/cmMod/config.h.in +test cases/cmake/3 advanced no dep/subprojects/cmMod/main.cpp +test cases/cmake/3 advanced no dep/subprojects/cmMod/lib/cmMod.cpp +test cases/cmake/3 advanced no dep/subprojects/cmMod/lib/cmMod.hpp +test cases/cmake/4 code gen/main.cpp +test cases/cmake/4 code gen/meson.build +test cases/cmake/4 code gen/test.hpp +test cases/cmake/4 code gen/subprojects/cmCodeGen/CMakeLists.txt +test cases/cmake/4 code gen/subprojects/cmCodeGen/main.cpp +test cases/cmake/5 object library/main.cpp +test cases/cmake/5 object library/meson.build +test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt +test cases/cmake/5 object library/subprojects/cmObjLib/libA.cpp +test cases/cmake/5 object library/subprojects/cmObjLib/libA.hpp +test cases/cmake/5 object library/subprojects/cmObjLib/libB.cpp +test cases/cmake/5 object library/subprojects/cmObjLib/libB.hpp +test cases/cmake/6 object library no dep/main.cpp +test cases/cmake/6 object library no dep/meson.build +test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt +test cases/cmake/6 object library no dep/subprojects/cmObjLib/libA.cpp +test cases/cmake/6 object library no dep/subprojects/cmObjLib/libA.hpp +test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.cpp +test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.hpp +test cases/cmake/7 cmake options/meson.build +test cases/cmake/7 cmake options/test.json +test cases/cmake/7 cmake options/subprojects/cmOpts/CMakeLists.txt +test cases/cmake/8 custom command/main.cpp +test cases/cmake/8 custom command/meson.build +test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt +test cases/cmake/8 custom command/subprojects/cmMod/args_test.cpp +test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp +test cases/cmake/8 custom command/subprojects/cmMod/cmMod.hpp +test cases/cmake/8 custom command/subprojects/cmMod/cp.cpp +test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.cpp.am +test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.hpp.am +test cases/cmake/8 custom command/subprojects/cmMod/cpyInc.hpp.am +test cases/cmake/8 custom command/subprojects/cmMod/cpyNext.cpp.am +test cases/cmake/8 custom command/subprojects/cmMod/cpyNext.hpp.am +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp +test cases/cmake/8 custom command/subprojects/cmMod/genMain.cpp +test cases/cmake/8 custom command/subprojects/cmMod/macro_name.cpp +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/CMakeLists.txt +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest.hpp +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest2.hpp +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest3.hpp +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest4.hpp +test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest5.hpp +test cases/cmake/8 custom command/subprojects/cmMod/mycpy/.gitkeep +test cases/cmake/9 disabled subproject/meson.build +test cases/common/1 trivial/meson.build +test cases/common/1 trivial/trivial.c +test cases/common/10 man install/bar.2 +test cases/common/10 man install/baz.1.in +test cases/common/10 man install/foo.1 +test cases/common/10 man install/foo.fr.1 +test cases/common/10 man install/meson.build +test cases/common/10 man install/test.json +test cases/common/10 man install/vanishing/meson.build +test cases/common/10 man install/vanishing/vanishing.1 +test cases/common/10 man install/vanishing/vanishing.2 +test cases/common/100 postconf with args/meson.build +test cases/common/100 postconf with args/postconf.py +test cases/common/100 postconf with args/prog.c +test cases/common/100 postconf with args/raw.dat +test cases/common/101 testframework options/meson.build +test cases/common/101 testframework options/meson_options.txt +test cases/common/101 testframework options/test.json +test cases/common/102 extract same name/lib.c +test cases/common/102 extract same name/main.c +test cases/common/102 extract same name/meson.build +test cases/common/102 extract same name/src/lib.c +test cases/common/103 has header symbol/meson.build +test cases/common/104 has arg/meson.build +test cases/common/105 generatorcustom/catter.py +test cases/common/105 generatorcustom/gen-resx.py +test cases/common/105 generatorcustom/gen.c +test cases/common/105 generatorcustom/gen.py +test cases/common/105 generatorcustom/host.c +test cases/common/105 generatorcustom/main.c +test cases/common/105 generatorcustom/meson.build +test cases/common/105 generatorcustom/res1.txt +test cases/common/105 generatorcustom/res2.txt +test cases/common/106 multiple dir configure file/meson.build +test cases/common/106 multiple dir configure file/subdir/foo.txt +test cases/common/106 multiple dir configure file/subdir/meson.build +test cases/common/106 multiple dir configure file/subdir/someinput.in +test cases/common/107 spaces backslash/comparer-end-notstring.c +test cases/common/107 spaces backslash/comparer-end.c +test cases/common/107 spaces backslash/comparer.c +test cases/common/107 spaces backslash/meson.build +test cases/common/107 spaces backslash/asm output/meson.build +test cases/common/107 spaces backslash/include/comparer.h +test cases/common/108 ternary/meson.build +test cases/common/109 custom target capture/data_source.txt +test cases/common/109 custom target capture/meson.build +test cases/common/109 custom target capture/my_compiler.py +test cases/common/109 custom target capture/test.json +test cases/common/11 subdir/meson.build +test cases/common/11 subdir/subdir/meson.build +test cases/common/11 subdir/subdir/prog.c +test cases/common/110 allgenerate/converter.py +test cases/common/110 allgenerate/foobar.cpp.in +test cases/common/110 allgenerate/meson.build +test cases/common/111 pathjoin/meson.build +test cases/common/112 subdir subproject/meson.build +test cases/common/112 subdir subproject/prog/meson.build +test cases/common/112 subdir subproject/prog/prog.c +test cases/common/112 subdir subproject/subprojects/sub/meson.build +test cases/common/112 subdir subproject/subprojects/sub/sub.c +test cases/common/112 subdir subproject/subprojects/sub/sub.h +test cases/common/113 interpreter copy mutable var on assignment/meson.build +test cases/common/114 skip/meson.build +test cases/common/115 subproject project arguments/exe.c +test cases/common/115 subproject project arguments/exe.cpp +test cases/common/115 subproject project arguments/meson.build +test cases/common/115 subproject project arguments/subprojects/subexe/meson.build +test cases/common/115 subproject project arguments/subprojects/subexe/subexe.c +test cases/common/116 test skip/meson.build +test cases/common/116 test skip/test_skip.c +test cases/common/117 shared module/meson.build +test cases/common/117 shared module/module.c +test cases/common/117 shared module/nosyms.c +test cases/common/117 shared module/prog.c +test cases/common/117 shared module/runtime.c +test cases/common/117 shared module/test.json +test cases/common/118 llvm ir and assembly/main.c +test cases/common/118 llvm ir and assembly/main.cpp +test cases/common/118 llvm ir and assembly/meson.build +test cases/common/118 llvm ir and assembly/square-aarch64.S +test cases/common/118 llvm ir and assembly/square-arm.S +test cases/common/118 llvm ir and assembly/square-x86.S +test cases/common/118 llvm ir and assembly/square-x86_64.S +test cases/common/118 llvm ir and assembly/square.ll +test cases/common/118 llvm ir and assembly/symbol-underscore.h +test cases/common/119 cpp and asm/meson.build +test cases/common/119 cpp and asm/retval-arm.S +test cases/common/119 cpp and asm/retval-x86.S +test cases/common/119 cpp and asm/retval-x86_64.S +test cases/common/119 cpp and asm/symbol-underscore.h +test cases/common/119 cpp and asm/trivial.cc +test cases/common/12 data/datafile.dat +test cases/common/12 data/etcfile.dat +test cases/common/12 data/fileobject_datafile.dat +test cases/common/12 data/meson.build +test cases/common/12 data/runscript.sh +test cases/common/12 data/somefile.txt +test cases/common/12 data/test.json +test cases/common/12 data/to_be_renamed_1.txt +test cases/common/12 data/to_be_renamed_3.txt +test cases/common/12 data/to_be_renamed_4.txt +test cases/common/12 data/vanishing/meson.build +test cases/common/12 data/vanishing/to_be_renamed_2.txt +test cases/common/12 data/vanishing/vanishing.dat +test cases/common/12 data/vanishing/vanishing2.dat +test cases/common/120 extract all shared library/extractor.h +test cases/common/120 extract all shared library/four.c +test cases/common/120 extract all shared library/func1234.def +test cases/common/120 extract all shared library/meson.build +test cases/common/120 extract all shared library/one.c +test cases/common/120 extract all shared library/prog.c +test cases/common/120 extract all shared library/three.c +test cases/common/120 extract all shared library/two.c +test cases/common/121 object only target/meson.build +test cases/common/121 object only target/obj_generator.py +test cases/common/121 object only target/prog.c +test cases/common/121 object only target/source.c +test cases/common/121 object only target/source2.c +test cases/common/121 object only target/source2.def +test cases/common/121 object only target/source3.c +test cases/common/121 object only target/test.json +test cases/common/121 object only target/objdir/meson.build +test cases/common/121 object only target/objdir/source4.c +test cases/common/121 object only target/objdir/source5.c +test cases/common/121 object only target/objdir/source6.c +test cases/common/122 no buildincdir/meson.build +test cases/common/122 no buildincdir/prog.c +test cases/common/122 no buildincdir/include/header.h +test cases/common/123 custom target directory install/docgen.py +test cases/common/123 custom target directory install/meson.build +test cases/common/123 custom target directory install/test.json +test cases/common/124 dependency file generation/main .c +test cases/common/124 dependency file generation/meson.build +test cases/common/125 configure file in generator/meson.build +test cases/common/125 configure file in generator/inc/confdata.in +test cases/common/125 configure file in generator/inc/meson.build +test cases/common/125 configure file in generator/src/gen.py +test cases/common/125 configure file in generator/src/main.c +test cases/common/125 configure file in generator/src/meson.build +test cases/common/125 configure file in generator/src/source +test cases/common/126 generated llvm ir/copyfile.py +test cases/common/126 generated llvm ir/main.c +test cases/common/126 generated llvm ir/meson.build +test cases/common/126 generated llvm ir/square.ll.in +test cases/common/127 generated assembly/copyfile.py +test cases/common/127 generated assembly/empty.c +test cases/common/127 generated assembly/main.c +test cases/common/127 generated assembly/meson.build +test cases/common/127 generated assembly/square-arm.S.in +test cases/common/127 generated assembly/square-x86.S.in +test cases/common/127 generated assembly/square-x86_64.S.in +test cases/common/127 generated assembly/square.def +test cases/common/127 generated assembly/symbol-underscore.h +test cases/common/128 build by default targets in tests/main.c +test cases/common/128 build by default targets in tests/meson.build +test cases/common/128 build by default targets in tests/write_file.py +test cases/common/129 build by default/checkexists.py +test cases/common/129 build by default/foo.c +test cases/common/129 build by default/meson.build +test cases/common/129 build by default/mygen.py +test cases/common/129 build by default/source.txt +test cases/common/13 pch/meson.build +test cases/common/13 pch/c/meson.build +test cases/common/13 pch/c/prog.c +test cases/common/13 pch/c/pch/prog.h +test cases/common/13 pch/cpp/meson.build +test cases/common/13 pch/cpp/prog.cc +test cases/common/13 pch/cpp/pch/prog.hh +test cases/common/13 pch/generated/gen_custom.py +test cases/common/13 pch/generated/gen_generator.py +test cases/common/13 pch/generated/generated_generator.in +test cases/common/13 pch/generated/meson.build +test cases/common/13 pch/generated/prog.c +test cases/common/13 pch/generated/pch/prog.h +test cases/common/13 pch/linkwhole/lib1.c +test cases/common/13 pch/linkwhole/lib2.c +test cases/common/13 pch/linkwhole/main.c +test cases/common/13 pch/linkwhole/meson.build +test cases/common/13 pch/linkwhole/pch1/pch_one.h +test cases/common/13 pch/linkwhole/pch2/pch_two.h +test cases/common/13 pch/mixed/func.c +test cases/common/13 pch/mixed/main.cc +test cases/common/13 pch/mixed/meson.build +test cases/common/13 pch/mixed/pch/func.h +test cases/common/13 pch/mixed/pch/main.h +test cases/common/13 pch/userDefined/meson.build +test cases/common/13 pch/userDefined/prog.c +test cases/common/13 pch/userDefined/pch/pch.c +test cases/common/13 pch/userDefined/pch/pch.h +test cases/common/13 pch/withIncludeDirectories/meson.build +test cases/common/13 pch/withIncludeDirectories/prog.c +test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h +test cases/common/13 pch/withIncludeDirectories/pch/prog.h +test cases/common/13 pch/withIncludeFile/meson.build +test cases/common/13 pch/withIncludeFile/prog.c +test cases/common/13 pch/withIncludeFile/pch/prog.h +test cases/common/130 include order/meson.build +test cases/common/130 include order/ordertest.c +test cases/common/130 include order/ctsub/copyfile.py +test cases/common/130 include order/ctsub/emptyfile.c +test cases/common/130 include order/ctsub/main.h +test cases/common/130 include order/ctsub/meson.build +test cases/common/130 include order/inc1/hdr.h +test cases/common/130 include order/inc2/hdr.h +test cases/common/130 include order/inc3/meson.build +test cases/common/130 include order/inc3/prefer-build-dir-over-src-dir.h +test cases/common/130 include order/sub1/main.h +test cases/common/130 include order/sub1/meson.build +test cases/common/130 include order/sub1/some.c +test cases/common/130 include order/sub1/some.h +test cases/common/130 include order/sub2/main.h +test cases/common/130 include order/sub2/meson.build +test cases/common/130 include order/sub3/main.h +test cases/common/130 include order/sub3/meson.build +test cases/common/130 include order/sub4/main.c +test cases/common/130 include order/sub4/main.h +test cases/common/130 include order/sub4/meson.build +test cases/common/131 override options/four.c +test cases/common/131 override options/meson.build +test cases/common/131 override options/one.c +test cases/common/131 override options/three.c +test cases/common/131 override options/two.c +test cases/common/132 get define/concat.h +test cases/common/132 get define/meson.build +test cases/common/132 get define/meson_options.txt +test cases/common/132 get define/test.json +test cases/common/133 c cpp and asm/main.c +test cases/common/133 c cpp and asm/main.cpp +test cases/common/133 c cpp and asm/meson.build +test cases/common/133 c cpp and asm/retval-arm.S +test cases/common/133 c cpp and asm/retval-x86.S +test cases/common/133 c cpp and asm/retval-x86_64.S +test cases/common/133 c cpp and asm/somelib.c +test cases/common/133 c cpp and asm/symbol-underscore.h +test cases/common/134 compute int/config.h.in +test cases/common/134 compute int/foobar.h +test cases/common/134 compute int/meson.build +test cases/common/134 compute int/prog.c.in +test cases/common/135 custom target object output/meson.build +test cases/common/135 custom target object output/obj_generator.py +test cases/common/135 custom target object output/objdir/meson.build +test cases/common/135 custom target object output/objdir/source.c +test cases/common/135 custom target object output/progdir/meson.build +test cases/common/135 custom target object output/progdir/prog.c +test cases/common/136 empty build file/meson.build +test cases/common/136 empty build file/subdir/meson.build +test cases/common/137 whole archive/func1.c +test cases/common/137 whole archive/func2.c +test cases/common/137 whole archive/meson.build +test cases/common/137 whole archive/mylib.h +test cases/common/137 whole archive/prog.c +test cases/common/137 whole archive/exe/meson.build +test cases/common/137 whole archive/exe2/meson.build +test cases/common/137 whole archive/exe3/meson.build +test cases/common/137 whole archive/exe4/meson.build +test cases/common/137 whole archive/sh_func2_dep_func1/meson.build +test cases/common/137 whole archive/sh_func2_linked_func1/meson.build +test cases/common/137 whole archive/sh_func2_transdep_func1/meson.build +test cases/common/137 whole archive/sh_only_link_whole/meson.build +test cases/common/137 whole archive/st_func1/meson.build +test cases/common/137 whole archive/st_func2/meson.build +test cases/common/138 C and CPP link/dummy.c +test cases/common/138 C and CPP link/foo.c +test cases/common/138 C and CPP link/foo.cpp +test cases/common/138 C and CPP link/foo.h +test cases/common/138 C and CPP link/foo.hpp +test cases/common/138 C and CPP link/foobar.c +test cases/common/138 C and CPP link/foobar.h +test cases/common/138 C and CPP link/meson.build +test cases/common/138 C and CPP link/sub.c +test cases/common/138 C and CPP link/sub.h +test cases/common/139 mesonintrospect from scripts/check_env.py +test cases/common/139 mesonintrospect from scripts/check_introspection.py +test cases/common/139 mesonintrospect from scripts/meson.build +test cases/common/14 configure file/basename.py +test cases/common/14 configure file/check_file.py +test cases/common/14 configure file/check_inputs.py +test cases/common/14 configure file/config.h +test cases/common/14 configure file/config.h.in +test cases/common/14 configure file/config4a.h.in +test cases/common/14 configure file/config4b.h.in +test cases/common/14 configure file/config5.h.in +test cases/common/14 configure file/config6.h.in +test cases/common/14 configure file/config7.h.in +test cases/common/14 configure file/config8.h.in +test cases/common/14 configure file/depfile +test cases/common/14 configure file/differentafterbasename1.in +test cases/common/14 configure file/differentafterbasename2.in +test cases/common/14 configure file/dummy.dat +test cases/common/14 configure file/dumpprog.c +test cases/common/14 configure file/file_contains.py +test cases/common/14 configure file/generator-deps.py +test cases/common/14 configure file/generator-without-input-file.py +test cases/common/14 configure file/generator.py +test cases/common/14 configure file/invalid-utf8.bin.in +test cases/common/14 configure file/meson.build +test cases/common/14 configure file/nosubst-nocopy1.txt.in +test cases/common/14 configure file/nosubst-nocopy2.txt.in +test cases/common/14 configure file/prog.c +test cases/common/14 configure file/prog2.c +test cases/common/14 configure file/prog4.c +test cases/common/14 configure file/prog5.c +test cases/common/14 configure file/prog6.c +test cases/common/14 configure file/prog7.c +test cases/common/14 configure file/prog9.c +test cases/common/14 configure file/sameafterbasename.in +test cases/common/14 configure file/sameafterbasename.in2 +test cases/common/14 configure file/test.json +test cases/common/14 configure file/test.py.in +test cases/common/14 configure file/touch.py +test cases/common/14 configure file/subdir/meson.build +test cases/common/140 custom target multiple outputs/generator.py +test cases/common/140 custom target multiple outputs/meson.build +test cases/common/140 custom target multiple outputs/test.json +test cases/common/141 special characters/.editorconfig +test cases/common/141 special characters/arg-char-test.c +test cases/common/141 special characters/arg-string-test.c +test cases/common/141 special characters/arg-unquoted-test.c +test cases/common/141 special characters/check_quoting.py +test cases/common/141 special characters/meson.build +test cases/common/141 special characters/test.json +test cases/common/142 nested links/meson.build +test cases/common/142 nested links/xephyr.c +test cases/common/143 list of file sources/foo +test cases/common/143 list of file sources/gen.py +test cases/common/143 list of file sources/meson.build +test cases/common/144 link depends custom target/foo.c +test cases/common/144 link depends custom target/make_file.py +test cases/common/144 link depends custom target/meson.build +test cases/common/145 recursive linking/lib.h +test cases/common/145 recursive linking/main.c +test cases/common/145 recursive linking/meson.build +test cases/common/145 recursive linking/3rdorderdeps/lib.c.in +test cases/common/145 recursive linking/3rdorderdeps/main.c.in +test cases/common/145 recursive linking/3rdorderdeps/meson.build +test cases/common/145 recursive linking/circular/lib1.c +test cases/common/145 recursive linking/circular/lib2.c +test cases/common/145 recursive linking/circular/lib3.c +test cases/common/145 recursive linking/circular/main.c +test cases/common/145 recursive linking/circular/meson.build +test cases/common/145 recursive linking/circular/prop1.c +test cases/common/145 recursive linking/circular/prop2.c +test cases/common/145 recursive linking/circular/prop3.c +test cases/common/145 recursive linking/edge-cases/libsto.c +test cases/common/145 recursive linking/edge-cases/meson.build +test cases/common/145 recursive linking/edge-cases/shstmain.c +test cases/common/145 recursive linking/edge-cases/stobuilt.c +test cases/common/145 recursive linking/edge-cases/stomain.c +test cases/common/145 recursive linking/shnodep/lib.c +test cases/common/145 recursive linking/shnodep/meson.build +test cases/common/145 recursive linking/shshdep/lib.c +test cases/common/145 recursive linking/shshdep/meson.build +test cases/common/145 recursive linking/shstdep/lib.c +test cases/common/145 recursive linking/shstdep/meson.build +test cases/common/145 recursive linking/stnodep/lib.c +test cases/common/145 recursive linking/stnodep/meson.build +test cases/common/145 recursive linking/stshdep/lib.c +test cases/common/145 recursive linking/stshdep/meson.build +test cases/common/145 recursive linking/ststdep/lib.c +test cases/common/145 recursive linking/ststdep/meson.build +test cases/common/146 library at root/lib.c +test cases/common/146 library at root/meson.build +test cases/common/146 library at root/main/main.c +test cases/common/146 library at root/main/meson.build +test cases/common/147 simd/fallback.c +test cases/common/147 simd/meson.build +test cases/common/147 simd/simd_avx.c +test cases/common/147 simd/simd_avx2.c +test cases/common/147 simd/simd_mmx.c +test cases/common/147 simd/simd_neon.c +test cases/common/147 simd/simd_sse.c +test cases/common/147 simd/simd_sse2.c +test cases/common/147 simd/simd_sse3.c +test cases/common/147 simd/simd_sse41.c +test cases/common/147 simd/simd_sse42.c +test cases/common/147 simd/simd_ssse3.c +test cases/common/147 simd/simdchecker.c +test cases/common/147 simd/simdfuncs.h +test cases/common/147 simd/include/simdheader.h +test cases/common/148 shared module resolving symbol in executable/meson.build +test cases/common/148 shared module resolving symbol in executable/module.c +test cases/common/148 shared module resolving symbol in executable/prog.c +test cases/common/149 dotinclude/dotproc.c +test cases/common/149 dotinclude/meson.build +test cases/common/149 dotinclude/stdio.h +test cases/common/15 if/meson.build +test cases/common/15 if/prog.c +test cases/common/150 reserved targets/meson.build +test cases/common/150 reserved targets/test.c +test cases/common/150 reserved targets/all/meson.build +test cases/common/150 reserved targets/benchmark/meson.build +test cases/common/150 reserved targets/clean/meson.build +test cases/common/150 reserved targets/clean-ctlist/meson.build +test cases/common/150 reserved targets/clean-gcda/meson.build +test cases/common/150 reserved targets/clean-gcno/meson.build +test cases/common/150 reserved targets/coverage/meson.build +test cases/common/150 reserved targets/coverage-html/meson.build +test cases/common/150 reserved targets/coverage-sonarqube/meson.build +test cases/common/150 reserved targets/coverage-text/meson.build +test cases/common/150 reserved targets/coverage-xml/meson.build +test cases/common/150 reserved targets/dist/meson.build +test cases/common/150 reserved targets/distcheck/meson.build +test cases/common/150 reserved targets/install/meson.build +test cases/common/150 reserved targets/phony/meson.build +test cases/common/150 reserved targets/reconfigure/meson.build +test cases/common/150 reserved targets/runtarget/echo.py +test cases/common/150 reserved targets/runtarget/meson.build +test cases/common/150 reserved targets/scan-build/meson.build +test cases/common/150 reserved targets/test/meson.build +test cases/common/150 reserved targets/uninstall/meson.build +test cases/common/151 duplicate source names/meson.build +test cases/common/151 duplicate source names/dir1/file.c +test cases/common/151 duplicate source names/dir1/meson.build +test cases/common/151 duplicate source names/dir2/file.c +test cases/common/151 duplicate source names/dir2/meson.build +test cases/common/151 duplicate source names/dir2/dir1/file.c +test cases/common/151 duplicate source names/dir3/file.c +test cases/common/151 duplicate source names/dir3/meson.build +test cases/common/151 duplicate source names/dir3/dir1/file.c +test cases/common/152 index customtarget/check_args.py +test cases/common/152 index customtarget/gen_sources.py +test cases/common/152 index customtarget/lib.c +test cases/common/152 index customtarget/meson.build +test cases/common/152 index customtarget/subdir/foo.c +test cases/common/152 index customtarget/subdir/meson.build +test cases/common/153 wrap file should not failed/meson.build +test cases/common/153 wrap file should not failed/src/meson.build +test cases/common/153 wrap file should not failed/src/test.c +test cases/common/153 wrap file should not failed/src/subprojects/prog.c +test cases/common/153 wrap file should not failed/src/subprojects/foo/prog2.c +test cases/common/153 wrap file should not failed/subprojects/.gitignore +test cases/common/153 wrap file should not failed/subprojects/bar.wrap +test cases/common/153 wrap file should not failed/subprojects/foo.wrap +test cases/common/153 wrap file should not failed/subprojects/patchdir.wrap +test cases/common/153 wrap file should not failed/subprojects/patchfile.wrap +test cases/common/153 wrap file should not failed/subprojects/zlib.wrap +test cases/common/153 wrap file should not failed/subprojects/bar-1.0/bar.c +test cases/common/153 wrap file should not failed/subprojects/bar-1.0/meson.build +test cases/common/153 wrap file should not failed/subprojects/foo-1.0/foo.c +test cases/common/153 wrap file should not failed/subprojects/foo-1.0/meson.build +test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/foo.c +test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchdir/meson.build +test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchfile/.meson-subproject-wrap-hash.txt +test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchfile/foo.c +test cases/common/153 wrap file should not failed/subprojects/foo-1.0-patchfile/meson.build +test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0-patch.tar.xz +test cases/common/153 wrap file should not failed/subprojects/packagecache/foo-1.0.tar.xz +test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8-8-wrap.zip +test cases/common/153 wrap file should not failed/subprojects/packagecache/zlib-1.2.8.tar.gz +test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0-patch.tar.xz +test cases/common/153 wrap file should not failed/subprojects/packagefiles/bar-1.0.tar.xz +test cases/common/153 wrap file should not failed/subprojects/packagefiles/foo-1.0/meson.build +test cases/common/153 wrap file should not failed/subprojects/packagefiles/patchfile/0001-Change-foo-to-executable.patch +test cases/common/153 wrap file should not failed/subprojects/packagefiles/patchfile/0001-Change-return-value-to-43.patch +test cases/common/153 wrap file should not failed/subprojects/packagefiles/patchfile/0002-Change-return-value-to-44.patch +test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/foo.c +test cases/common/153 wrap file should not failed/subprojects/zlib-1.2.8/meson.build +test cases/common/154 includedir subproj/meson.build +test cases/common/154 includedir subproj/prog.c +test cases/common/154 includedir subproj/subprojects/inctest/meson.build +test cases/common/154 includedir subproj/subprojects/inctest/include/incfile.h +test cases/common/155 subproject dir name collision/a.c +test cases/common/155 subproject dir name collision/meson.build +test cases/common/155 subproject dir name collision/custom_subproject_dir/B/b.c +test cases/common/155 subproject dir name collision/custom_subproject_dir/B/meson.build +test cases/common/155 subproject dir name collision/custom_subproject_dir/C/c.c +test cases/common/155 subproject dir name collision/custom_subproject_dir/C/meson.build +test cases/common/155 subproject dir name collision/other_subdir/meson.build +test cases/common/155 subproject dir name collision/other_subdir/custom_subproject_dir/other.c +test cases/common/156 config tool variable/meson.build +test cases/common/157 custom target subdir depend files/copyfile.py +test cases/common/157 custom target subdir depend files/meson.build +test cases/common/157 custom target subdir depend files/subdir/dep.dat +test cases/common/157 custom target subdir depend files/subdir/foo.c.in +test cases/common/157 custom target subdir depend files/subdir/meson.build +test cases/common/158 disabler/meson.build +test cases/common/159 array option/meson.build +test cases/common/159 array option/meson_options.txt +test cases/common/16 comparison/meson.build +test cases/common/16 comparison/prog.c +test cases/common/160 custom target template substitution/checkcopy.py +test cases/common/160 custom target template substitution/foo.c.in +test cases/common/160 custom target template substitution/meson.build +test cases/common/161 not-found dependency/meson.build +test cases/common/161 not-found dependency/testlib.c +test cases/common/161 not-found dependency/sub/meson.build +test cases/common/161 not-found dependency/subprojects/trivial/meson.build +test cases/common/161 not-found dependency/subprojects/trivial/trivial.c +test cases/common/162 subdir if_found/meson.build +test cases/common/162 subdir if_found/subdir/meson.build +test cases/common/163 default options prefix dependent defaults/meson.build +test cases/common/164 dependency factory/meson.build +test cases/common/165 get project license/bar.c +test cases/common/165 get project license/meson.build +test cases/common/166 yield/meson.build +test cases/common/166 yield/meson_options.txt +test cases/common/166 yield/subprojects/sub/meson.build +test cases/common/166 yield/subprojects/sub/meson_options.txt +test cases/common/167 subproject nested subproject dirs/meson.build +test cases/common/167 subproject nested subproject dirs/prog.c +test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/a.c +test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/meson.build +test cases/common/167 subproject nested subproject dirs/contrib/subprojects/alpha/var/subprojects/wrap_files_might_be_here +test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/b.c +test cases/common/167 subproject nested subproject dirs/contrib/subprojects/beta/meson.build +test cases/common/168 preserve gendir/base.inp +test cases/common/168 preserve gendir/genprog.py +test cases/common/168 preserve gendir/meson.build +test cases/common/168 preserve gendir/testprog.c +test cases/common/168 preserve gendir/com/mesonbuild/subbie.inp +test cases/common/169 source in dep/bar.cpp +test cases/common/169 source in dep/foo.c +test cases/common/169 source in dep/meson.build +test cases/common/169 source in dep/generated/funname +test cases/common/169 source in dep/generated/genheader.py +test cases/common/169 source in dep/generated/main.c +test cases/common/169 source in dep/generated/meson.build +test cases/common/17 array/func.c +test cases/common/17 array/meson.build +test cases/common/17 array/prog.c +test cases/common/170 generator link whole/export.h +test cases/common/170 generator link whole/generator.py +test cases/common/170 generator link whole/main.c +test cases/common/170 generator link whole/meson.build +test cases/common/170 generator link whole/meson_test_function.tmpl +test cases/common/170 generator link whole/pull_meson_test_function.c +test cases/common/171 initial c_args/meson.build +test cases/common/171 initial c_args/test.json +test cases/common/172 identical target name in subproject flat layout/foo.c +test cases/common/172 identical target name in subproject flat layout/main.c +test cases/common/172 identical target name in subproject flat layout/meson.build +test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/foo.c +test cases/common/172 identical target name in subproject flat layout/subprojects/subproj/meson.build +test cases/common/173 as-needed/config.h +test cases/common/173 as-needed/libA.cpp +test cases/common/173 as-needed/libA.h +test cases/common/173 as-needed/libB.cpp +test cases/common/173 as-needed/main.cpp +test cases/common/173 as-needed/meson.build +test cases/common/174 ndebug if-release enabled/main.c +test cases/common/174 ndebug if-release enabled/meson.build +test cases/common/175 ndebug if-release disabled/main.c +test cases/common/175 ndebug if-release disabled/meson.build +test cases/common/176 subproject version/meson.build +test cases/common/176 subproject version/subprojects/a/meson.build +test cases/common/177 subdir_done/meson.build +test cases/common/178 bothlibraries/dummy.py +test cases/common/178 bothlibraries/foo.cpp +test cases/common/178 bothlibraries/libfile.c +test cases/common/178 bothlibraries/main.c +test cases/common/178 bothlibraries/main2.c +test cases/common/178 bothlibraries/meson.build +test cases/common/178 bothlibraries/mylib.h +test cases/common/179 escape and unicode/file.c.in +test cases/common/179 escape and unicode/file.py +test cases/common/179 escape and unicode/find.py +test cases/common/179 escape and unicode/fun.c +test cases/common/179 escape and unicode/main.c +test cases/common/179 escape and unicode/meson.build +test cases/common/18 includedir/meson.build +test cases/common/18 includedir/include/func.h +test cases/common/18 includedir/src/func.c +test cases/common/18 includedir/src/meson.build +test cases/common/18 includedir/src/prog.c +test cases/common/180 has link arg/meson.build +test cases/common/181 same target name flat layout/foo.c +test cases/common/181 same target name flat layout/main.c +test cases/common/181 same target name flat layout/meson.build +test cases/common/181 same target name flat layout/subdir/foo.c +test cases/common/181 same target name flat layout/subdir/meson.build +test cases/common/182 find override/meson.build +test cases/common/182 find override/otherdir/main.c +test cases/common/182 find override/otherdir/main2.c +test cases/common/182 find override/otherdir/meson.build +test cases/common/182 find override/otherdir/source.desc +test cases/common/182 find override/otherdir/source2.desc +test cases/common/182 find override/subdir/converter.py +test cases/common/182 find override/subdir/gencodegen.py.in +test cases/common/182 find override/subdir/meson.build +test cases/common/182 find override/subprojects/sub.wrap +test cases/common/182 find override/subprojects/sub/meson.build +test cases/common/183 partial dependency/meson.build +test cases/common/183 partial dependency/declare_dependency/main.c +test cases/common/183 partial dependency/declare_dependency/meson.build +test cases/common/183 partial dependency/declare_dependency/other.c +test cases/common/183 partial dependency/declare_dependency/headers/foo.c +test cases/common/183 partial dependency/declare_dependency/headers/foo.h +test cases/common/184 openmp/main.c +test cases/common/184 openmp/main.cpp +test cases/common/184 openmp/main.f90 +test cases/common/184 openmp/meson.build +test cases/common/185 same target name/file.c +test cases/common/185 same target name/meson.build +test cases/common/185 same target name/sub/file2.c +test cases/common/185 same target name/sub/meson.build +test cases/common/186 test depends/gen.py +test cases/common/186 test depends/main.c +test cases/common/186 test depends/meson.build +test cases/common/186 test depends/test.py +test cases/common/187 args flattening/meson.build +test cases/common/188 dict/meson.build +test cases/common/188 dict/prog.c +test cases/common/189 check header/meson.build +test cases/common/189 check header/ouagadougou.h +test cases/common/19 header in file list/header.h +test cases/common/19 header in file list/meson.build +test cases/common/19 header in file list/prog.c +test cases/common/190 install_mode/config.h.in +test cases/common/190 install_mode/data_source.txt +test cases/common/190 install_mode/foo.1 +test cases/common/190 install_mode/meson.build +test cases/common/190 install_mode/rootdir.h +test cases/common/190 install_mode/runscript.sh +test cases/common/190 install_mode/stat.c +test cases/common/190 install_mode/test.json +test cases/common/190 install_mode/trivial.c +test cases/common/190 install_mode/sub1/second.dat +test cases/common/190 install_mode/sub2/stub +test cases/common/191 subproject array version/meson.build +test cases/common/191 subproject array version/subprojects/foo/meson.build +test cases/common/192 feature option/meson.build +test cases/common/192 feature option/meson_options.txt +test cases/common/193 feature option disabled/meson.build +test cases/common/193 feature option disabled/meson_options.txt +test cases/common/194 static threads/lib1.c +test cases/common/194 static threads/lib2.c +test cases/common/194 static threads/meson.build +test cases/common/194 static threads/prog.c +test cases/common/195 generator in subdir/meson.build +test cases/common/195 generator in subdir/com/mesonbuild/meson.build +test cases/common/195 generator in subdir/com/mesonbuild/subbie.inp +test cases/common/195 generator in subdir/com/mesonbuild/testprog.c +test cases/common/195 generator in subdir/com/mesonbuild/tooldir/genprog.py +test cases/common/196 subproject with features/meson.build +test cases/common/196 subproject with features/meson_options.txt +test cases/common/196 subproject with features/nothing.c +test cases/common/196 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build +test cases/common/196 subproject with features/subprojects/disabled_sub/meson.build +test cases/common/196 subproject with features/subprojects/disabled_sub/lib/meson.build +test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.c +test cases/common/196 subproject with features/subprojects/disabled_sub/lib/sub.h +test cases/common/196 subproject with features/subprojects/sub/meson.build +test cases/common/196 subproject with features/subprojects/sub/lib/meson.build +test cases/common/196 subproject with features/subprojects/sub/lib/sub.c +test cases/common/196 subproject with features/subprojects/sub/lib/sub.h +test cases/common/197 function attributes/meson.build +test cases/common/197 function attributes/meson_options.txt +test cases/common/197 function attributes/test.json +test cases/common/198 broken subproject/meson.build +test cases/common/198 broken subproject/subprojects/broken/broken.c +test cases/common/198 broken subproject/subprojects/broken/meson.build +test cases/common/199 argument syntax/meson.build +test cases/common/2 cpp/VERSIONFILE +test cases/common/2 cpp/cpp.C +test cases/common/2 cpp/meson.build +test cases/common/2 cpp/something.txt +test cases/common/2 cpp/trivial.cc +test cases/common/20 global arg/meson.build +test cases/common/20 global arg/prog.c +test cases/common/20 global arg/prog.cc +test cases/common/200 install name_prefix name_suffix/libfile.c +test cases/common/200 install name_prefix name_suffix/meson.build +test cases/common/200 install name_prefix name_suffix/test.json +test cases/common/201 kwarg entry/meson.build +test cases/common/201 kwarg entry/prog.c +test cases/common/201 kwarg entry/test.json +test cases/common/201 kwarg entry/inc/prog.h +test cases/common/202 custom target build by default/docgen.py +test cases/common/202 custom target build by default/meson.build +test cases/common/202 custom target build by default/test.json +test cases/common/203 find_library and headers/foo.h +test cases/common/203 find_library and headers/meson.build +test cases/common/204 line continuation/meson.build +test cases/common/205 native file path override/main.cpp +test cases/common/205 native file path override/meson.build +test cases/common/205 native file path override/nativefile.ini +test cases/common/205 native file path override/test.json +test cases/common/206 tap tests/cat.c +test cases/common/206 tap tests/issue7515.txt +test cases/common/206 tap tests/meson.build +test cases/common/206 tap tests/tester.c +test cases/common/207 warning level 0/main.cpp +test cases/common/207 warning level 0/meson.build +test cases/common/208 link custom/custom_stlib.py +test cases/common/208 link custom/custom_target.c +test cases/common/208 link custom/custom_target.py +test cases/common/208 link custom/dummy.c +test cases/common/208 link custom/lib.c +test cases/common/208 link custom/meson.build +test cases/common/208 link custom/outerlib.c +test cases/common/208 link custom/prog.c +test cases/common/209 link custom_i single from multiple/generate_conflicting_stlibs.py +test cases/common/209 link custom_i single from multiple/meson.build +test cases/common/209 link custom_i single from multiple/prog.c +test cases/common/21 target arg/func.c +test cases/common/21 target arg/func2.c +test cases/common/21 target arg/meson.build +test cases/common/21 target arg/prog.cc +test cases/common/21 target arg/prog2.cc +test cases/common/210 link custom_i multiple from multiple/generate_stlibs.py +test cases/common/210 link custom_i multiple from multiple/meson.build +test cases/common/210 link custom_i multiple from multiple/prog.c +test cases/common/211 dependency get_variable method/meson.build +test cases/common/211 dependency get_variable method/test.json +test cases/common/212 source set configuration_data/a.c +test cases/common/212 source set configuration_data/all.h +test cases/common/212 source set configuration_data/f.c +test cases/common/212 source set configuration_data/g.c +test cases/common/212 source set configuration_data/meson.build +test cases/common/212 source set configuration_data/nope.c +test cases/common/212 source set configuration_data/subdir/b.c +test cases/common/212 source set configuration_data/subdir/meson.build +test cases/common/213 source set dictionary/a.c +test cases/common/213 source set dictionary/all.h +test cases/common/213 source set dictionary/f.c +test cases/common/213 source set dictionary/g.c +test cases/common/213 source set dictionary/meson.build +test cases/common/213 source set dictionary/nope.c +test cases/common/213 source set dictionary/subdir/b.c +test cases/common/213 source set dictionary/subdir/meson.build +test cases/common/214 source set custom target/a.c +test cases/common/214 source set custom target/all.h +test cases/common/214 source set custom target/cp.py +test cases/common/214 source set custom target/f.c +test cases/common/214 source set custom target/g.c +test cases/common/214 source set custom target/meson.build +test cases/common/215 source set realistic example/common.h +test cases/common/215 source set realistic example/dummy.cpp +test cases/common/215 source set realistic example/main.cc +test cases/common/215 source set realistic example/meson.build +test cases/common/215 source set realistic example/not-found.cc +test cases/common/215 source set realistic example/was-found.cc +test cases/common/215 source set realistic example/zlib.cc +test cases/common/215 source set realistic example/boards/meson.build +test cases/common/215 source set realistic example/boards/arm/aarch64.cc +test cases/common/215 source set realistic example/boards/arm/arm.cc +test cases/common/215 source set realistic example/boards/arm/arm.h +test cases/common/215 source set realistic example/boards/arm/arm32.cc +test cases/common/215 source set realistic example/boards/arm/versatilepb.cc +test cases/common/215 source set realistic example/boards/arm/virt.cc +test cases/common/215 source set realistic example/boards/arm/xlnx_zcu102.cc +test cases/common/215 source set realistic example/boards/x86/pc.cc +test cases/common/215 source set realistic example/config/aarch64 +test cases/common/215 source set realistic example/config/arm +test cases/common/215 source set realistic example/config/x86 +test cases/common/215 source set realistic example/devices/meson.build +test cases/common/215 source set realistic example/devices/virtio-mmio.cc +test cases/common/215 source set realistic example/devices/virtio-pci.cc +test cases/common/215 source set realistic example/devices/virtio.cc +test cases/common/215 source set realistic example/devices/virtio.h +test cases/common/216 custom target input extracted objects/check_object.py +test cases/common/216 custom target input extracted objects/meson.build +test cases/common/216 custom target input extracted objects/libdir/gen.py +test cases/common/216 custom target input extracted objects/libdir/meson.build +test cases/common/216 custom target input extracted objects/libdir/source.c +test cases/common/217 test priorities/meson.build +test cases/common/217 test priorities/testprog.py +test cases/common/218 include_dir dot/meson.build +test cases/common/218 include_dir dot/rone.h +test cases/common/218 include_dir dot/src/main.c +test cases/common/218 include_dir dot/src/meson.build +test cases/common/218 include_dir dot/src/rone.c +test cases/common/219 include_type dependency/main.cpp +test cases/common/219 include_type dependency/meson.build +test cases/common/219 include_type dependency/pch/test.hpp +test cases/common/219 include_type dependency/subprojects/subDep/meson.build +test cases/common/22 object extraction/check-obj.py +test cases/common/22 object extraction/create-source.py +test cases/common/22 object extraction/header.h +test cases/common/22 object extraction/lib.c +test cases/common/22 object extraction/lib2.c +test cases/common/22 object extraction/main.c +test cases/common/22 object extraction/meson.build +test cases/common/22 object extraction/src/lib.c +test cases/common/220 fs module/meson.build +test cases/common/220 fs module/subdir/meson.build +test cases/common/220 fs module/subdir/subdirfile.txt +test cases/common/220 fs module/subprojects/subbie/meson.build +test cases/common/220 fs module/subprojects/subbie/subprojectfile.txt +test cases/common/220 fs module/subprojects/subbie/subsub/meson.build +test cases/common/220 fs module/subprojects/subbie/subsub/subsubfile.txt +test cases/common/221 zlib/meson.build +test cases/common/222 native prop/crossfile.ini +test cases/common/222 native prop/meson.build +test cases/common/222 native prop/nativefile.ini +test cases/common/223 persubproject options/foo.c +test cases/common/223 persubproject options/main.cpp +test cases/common/223 persubproject options/meson.build +test cases/common/223 persubproject options/test.json +test cases/common/223 persubproject options/subprojects/sub1/foo.c +test cases/common/223 persubproject options/subprojects/sub1/meson.build +test cases/common/223 persubproject options/subprojects/sub2/foo.c +test cases/common/223 persubproject options/subprojects/sub2/foo.cpp +test cases/common/223 persubproject options/subprojects/sub2/meson.build +test cases/common/224 arithmetic operators/meson.build +test cases/common/225 link language/c_linkage.cpp +test cases/common/225 link language/c_linkage.h +test cases/common/225 link language/lib.cpp +test cases/common/225 link language/main.c +test cases/common/225 link language/meson.build +test cases/common/226 link depends indexed custom target/check_arch.py +test cases/common/226 link depends indexed custom target/foo.c +test cases/common/226 link depends indexed custom target/make_file.py +test cases/common/226 link depends indexed custom target/meson.build +test cases/common/227 very long command line/codegen.py +test cases/common/227 very long command line/main.c +test cases/common/227 very long command line/meson.build +test cases/common/227 very long command line/name_gen.py +test cases/common/228 custom_target source/a +test cases/common/228 custom_target source/meson.build +test cases/common/228 custom_target source/x.py +test cases/common/229 disabler array addition/meson.build +test cases/common/229 disabler array addition/test.c +test cases/common/23 endian/meson.build +test cases/common/23 endian/prog.c +test cases/common/230 external project/app.c +test cases/common/230 external project/func.c +test cases/common/230 external project/func.h +test cases/common/230 external project/meson.build +test cases/common/230 external project/test.json +test cases/common/230 external project/libfoo/configure +test cases/common/230 external project/libfoo/libfoo.c +test cases/common/230 external project/libfoo/libfoo.h +test cases/common/230 external project/libfoo/meson.build +test cases/common/231 subdir files/meson.build +test cases/common/231 subdir files/subdir/meson.build +test cases/common/231 subdir files/subdir/prog.c +test cases/common/232 dependency allow_fallback/meson.build +test cases/common/232 dependency allow_fallback/subprojects/foob/meson.build +test cases/common/232 dependency allow_fallback/subprojects/foob3/meson.build +test cases/common/233 wrap case/meson.build +test cases/common/233 wrap case/prog.c +test cases/common/233 wrap case/subprojects/up_down.wrap +test cases/common/233 wrap case/subprojects/up_down/meson.build +test cases/common/233 wrap case/subprojects/up_down/up_down.h +test cases/common/234 get_file_contents/.gitattributes +test cases/common/234 get_file_contents/VERSION +test cases/common/234 get_file_contents/meson.build +test cases/common/234 get_file_contents/utf-16-text +test cases/common/234 get_file_contents/other/meson.build +test cases/common/235 invalid standard overridden to valid/main.c +test cases/common/235 invalid standard overridden to valid/meson.build +test cases/common/235 invalid standard overridden to valid/test.json +test cases/common/236 proper args splitting/main.c +test cases/common/236 proper args splitting/meson.build +test cases/common/236 proper args splitting/test.json +test cases/common/237 fstrings/meson.build +test cases/common/238 dependency include_type inconsistency/meson.build +test cases/common/238 dependency include_type inconsistency/bar/meson.build +test cases/common/238 dependency include_type inconsistency/subprojects/baz.wrap +test cases/common/238 dependency include_type inconsistency/subprojects/foo.wrap +test cases/common/238 dependency include_type inconsistency/subprojects/baz/meson.build +test cases/common/238 dependency include_type inconsistency/subprojects/foo/meson.build +test cases/common/239 includedir violation/meson.build +test cases/common/239 includedir violation/test.json +test cases/common/239 includedir violation/subprojects/sub/meson.build +test cases/common/239 includedir violation/subprojects/sub/include/placeholder.h +test cases/common/24 library versions/lib.c +test cases/common/24 library versions/meson.build +test cases/common/24 library versions/test.json +test cases/common/24 library versions/subdir/meson.build +test cases/common/240 dependency native host == build/meson.build +test cases/common/240 dependency native host == build/test.json +test cases/common/241 set and get variable/meson.build +test cases/common/241 set and get variable/test1.txt +test cases/common/241 set and get variable/test2.txt +test cases/common/242 custom target feed/data_source.txt +test cases/common/242 custom target feed/meson.build +test cases/common/242 custom target feed/my_compiler.py +test cases/common/242 custom target feed/test.json +test cases/common/243 escape++/meson.build +test cases/common/243 escape++/test.c +test cases/common/244 variable scope/meson.build +test cases/common/245 custom target index source/code_source.c +test cases/common/245 custom target index source/copyfile.py +test cases/common/245 custom target index source/copyfile2.py +test cases/common/245 custom target index source/header_source.h +test cases/common/245 custom target index source/main.c +test cases/common/245 custom target index source/meson.build +test cases/common/246 dependency fallbacks/meson.build +test cases/common/246 dependency fallbacks/subprojects/png/meson.build +test cases/common/247 deprecated option/meson.build +test cases/common/247 deprecated option/meson_options.txt +test cases/common/247 deprecated option/test.json +test cases/common/248 install_emptydir/meson.build +test cases/common/248 install_emptydir/test.json +test cases/common/249 install_symlink/datafile.dat +test cases/common/249 install_symlink/meson.build +test cases/common/249 install_symlink/test.json +test cases/common/25 config subdir/meson.build +test cases/common/25 config subdir/include/config.h.in +test cases/common/25 config subdir/include/meson.build +test cases/common/25 config subdir/src/meson.build +test cases/common/25 config subdir/src/prog.c +test cases/common/250 system include dir/main.cpp +test cases/common/250 system include dir/meson.build +test cases/common/250 system include dir/lib/lib.hpp +test cases/common/251 add_project_dependencies/lib.c +test cases/common/251 add_project_dependencies/main.c +test cases/common/251 add_project_dependencies/meson.build +test cases/common/251 add_project_dependencies/inc/lib.h +test cases/common/252 install data structured/meson.build +test cases/common/252 install data structured/test.json +test cases/common/252 install data structured/dir1/bad +test cases/common/252 install data structured/dir1/file1 +test cases/common/252 install data structured/dir1/file2 +test cases/common/252 install data structured/dir1/file3 +test cases/common/252 install data structured/dir2/bad +test cases/common/252 install data structured/dir2/file1 +test cases/common/252 install data structured/dir2/file2 +test cases/common/252 install data structured/dir2/file3 +test cases/common/252 install data structured/dir3/bad +test cases/common/252 install data structured/dir3/file1 +test cases/common/252 install data structured/dir3/file2 +test cases/common/252 install data structured/dir3/file3 +test cases/common/252 install data structured/pysrc/__init__.py +test cases/common/252 install data structured/pysrc/bad.py +test cases/common/252 install data structured/pysrc/bar.py +test cases/common/252 install data structured/pysrc/foo.py +test cases/common/252 install data structured/pysrc/meson.build +test cases/common/252 install data structured/pysrc/submod/__init__.py +test cases/common/252 install data structured/pysrc/submod/bad.py +test cases/common/252 install data structured/pysrc/submod/baz.py +test cases/common/253 subproject dependency variables/meson.build +test cases/common/253 subproject dependency variables/test.json +test cases/common/253 subproject dependency variables/subprojects/subfiles/foo.c +test cases/common/253 subproject dependency variables/subprojects/subfiles/meson.build +test cases/common/253 subproject dependency variables/subprojects/subfiles/subdir/foo.c +test cases/common/253 subproject dependency variables/subprojects/subfiles/subdir2/foo.c +test cases/common/254 long output/dumper.c +test cases/common/254 long output/meson.build +test cases/common/255 module warnings/meson.build +test cases/common/255 module warnings/test.json +test cases/common/256 subproject extracted objects/foo.c +test cases/common/256 subproject extracted objects/meson.build +test cases/common/256 subproject extracted objects/test.json +test cases/common/256 subproject extracted objects/subprojects/myobjects/cpplib.cpp +test cases/common/256 subproject extracted objects/subprojects/myobjects/cpplib.h +test cases/common/256 subproject extracted objects/subprojects/myobjects/meson.build +test cases/common/257 generated header dep/foo.c +test cases/common/257 generated header dep/meson.build +test cases/common/258 subsubproject inplace/meson.build +test cases/common/258 subsubproject inplace/subprojects/subsub.wrap +test cases/common/258 subsubproject inplace/subprojects/sub/meson.build +test cases/common/258 subsubproject inplace/subprojects/sub/subprojects/subsub.wrap +test cases/common/258 subsubproject inplace/subprojects/sub/subprojects/subsub-1.0/meson.build +test cases/common/259 preprocess/bar.c +test cases/common/259 preprocess/foo.c +test cases/common/259 preprocess/foo.h +test cases/common/259 preprocess/math.c +test cases/common/259 preprocess/meson.build +test cases/common/259 preprocess/src/file.map.in +test cases/common/259 preprocess/src/meson.build +test cases/common/26 find program/meson.build +test cases/common/26 find program/print-version-with-prefix.py +test cases/common/26 find program/print-version.py +test cases/common/26 find program/source.in +test cases/common/26 find program/scripts/test_subdir.py +test cases/common/260 declare_dependency objects/bar.c +test cases/common/260 declare_dependency objects/foo.c +test cases/common/260 declare_dependency objects/meson.build +test cases/common/260 declare_dependency objects/prog.c +test cases/common/261 testcase clause/meson.build +test cases/common/261 testcase clause/test.json +test cases/common/262 generator chain/data.txt +test cases/common/262 generator chain/meson.build +test cases/common/262 generator chain/stage1.py +test cases/common/262 generator chain/stage2.py +test cases/common/263 default_options dict/lib.c +test cases/common/263 default_options dict/meson.build +test cases/common/263 default_options dict/meson_options.txt +test cases/common/27 multiline string/meson.build +test cases/common/28 try compile/invalid.c +test cases/common/28 try compile/meson.build +test cases/common/28 try compile/valid.c +test cases/common/29 compiler id/meson.build +test cases/common/3 static/libfile.c +test cases/common/3 static/libfile2.c +test cases/common/3 static/meson.build +test cases/common/3 static/meson_options.txt +test cases/common/30 sizeof/config.h.in +test cases/common/30 sizeof/meson.build +test cases/common/30 sizeof/prog.c.in +test cases/common/31 define10/config.h.in +test cases/common/31 define10/meson.build +test cases/common/31 define10/prog.c +test cases/common/32 has header/meson.build +test cases/common/32 has header/ouagadougou.h +test cases/common/33 run program/check-env.py +test cases/common/33 run program/get-version.py +test cases/common/33 run program/meson.build +test cases/common/33 run program/test.json +test cases/common/33 run program/scripts/hello.bat +test cases/common/33 run program/scripts/hello.sh +test cases/common/34 logic ops/meson.build +test cases/common/35 string operations/meson.build +test cases/common/36 has function/meson.build +test cases/common/37 has member/meson.build +test cases/common/38 alignment/meson.build +test cases/common/39 library chain/main.c +test cases/common/39 library chain/meson.build +test cases/common/39 library chain/test.json +test cases/common/39 library chain/subdir/lib1.c +test cases/common/39 library chain/subdir/meson.build +test cases/common/39 library chain/subdir/subdir2/lib2.c +test cases/common/39 library chain/subdir/subdir2/meson.build +test cases/common/39 library chain/subdir/subdir3/lib3.c +test cases/common/39 library chain/subdir/subdir3/meson.build +test cases/common/4 shared/libfile.c +test cases/common/4 shared/meson.build +test cases/common/40 options/meson.build +test cases/common/40 options/meson_options.txt +test cases/common/40 options/test.json +test cases/common/41 test args/cmd_args.c +test cases/common/41 test args/copyfile.py +test cases/common/41 test args/env2vars.c +test cases/common/41 test args/envvars.c +test cases/common/41 test args/meson.build +test cases/common/41 test args/tester.c +test cases/common/41 test args/tester.py +test cases/common/41 test args/testfile.txt +test cases/common/42 subproject/meson.build +test cases/common/42 subproject/mylicense.txt +test cases/common/42 subproject/test.json +test cases/common/42 subproject/user.c +test cases/common/42 subproject/subprojects/sublib/meson.build +test cases/common/42 subproject/subprojects/sublib/simpletest.c +test cases/common/42 subproject/subprojects/sublib/sublib.c +test cases/common/42 subproject/subprojects/sublib/sublicense1.txt +test cases/common/42 subproject/subprojects/sublib/sublicense2.txt +test cases/common/42 subproject/subprojects/sublib/include/subdefs.h +test cases/common/43 subproject options/meson.build +test cases/common/43 subproject options/meson_options.txt +test cases/common/43 subproject options/subprojects/subproject/meson.build +test cases/common/43 subproject options/subprojects/subproject/meson_options.txt +test cases/common/44 pkgconfig-gen/answer.c +test cases/common/44 pkgconfig-gen/foo.c +test cases/common/44 pkgconfig-gen/meson.build +test cases/common/44 pkgconfig-gen/simple.c +test cases/common/44 pkgconfig-gen/simple.h +test cases/common/44 pkgconfig-gen/simple5.c +test cases/common/44 pkgconfig-gen/test.json +test cases/common/44 pkgconfig-gen/dependencies/custom.c +test cases/common/44 pkgconfig-gen/dependencies/dummy.c +test cases/common/44 pkgconfig-gen/dependencies/exposed.c +test cases/common/44 pkgconfig-gen/dependencies/internal.c +test cases/common/44 pkgconfig-gen/dependencies/main.c +test cases/common/44 pkgconfig-gen/dependencies/meson.build +test cases/common/44 pkgconfig-gen/dependencies/test2.c +test cases/common/44 pkgconfig-gen/inc1/inc1.h +test cases/common/44 pkgconfig-gen/inc2/inc2.h +test cases/common/45 custom install dirs/datafile.cat +test cases/common/45 custom install dirs/meson.build +test cases/common/45 custom install dirs/prog.1 +test cases/common/45 custom install dirs/prog.c +test cases/common/45 custom install dirs/sample.h +test cases/common/45 custom install dirs/test.json +test cases/common/45 custom install dirs/subdir/datafile.dog +test cases/common/46 subproject subproject/meson.build +test cases/common/46 subproject subproject/prog.c +test cases/common/46 subproject subproject/subprojects/a/a.c +test cases/common/46 subproject subproject/subprojects/a/meson.build +test cases/common/46 subproject subproject/subprojects/b/b.c +test cases/common/46 subproject subproject/subprojects/b/meson.build +test cases/common/46 subproject subproject/subprojects/c/meson.build +test cases/common/47 same file name/meson.build +test cases/common/47 same file name/prog.c +test cases/common/47 same file name/d1/file.c +test cases/common/47 same file name/d2/file.c +test cases/common/48 file grabber/a.c +test cases/common/48 file grabber/b.c +test cases/common/48 file grabber/c.c +test cases/common/48 file grabber/grabber.bat +test cases/common/48 file grabber/grabber.sh +test cases/common/48 file grabber/grabber2.bat +test cases/common/48 file grabber/meson.build +test cases/common/48 file grabber/prog.c +test cases/common/48 file grabber/subdir/meson.build +test cases/common/48 file grabber/subdir/suba.c +test cases/common/48 file grabber/subdir/subb.c +test cases/common/48 file grabber/subdir/subc.c +test cases/common/48 file grabber/subdir/subprog.c +test cases/common/49 custom target/data_source.txt +test cases/common/49 custom target/meson.build +test cases/common/49 custom target/my_compiler.py +test cases/common/49 custom target/test.json +test cases/common/49 custom target/depfile/dep.py +test cases/common/49 custom target/depfile/meson.build +test cases/common/5 linkstatic/libfile.c +test cases/common/5 linkstatic/libfile2.c +test cases/common/5 linkstatic/libfile3.c +test cases/common/5 linkstatic/libfile4.c +test cases/common/5 linkstatic/main.c +test cases/common/5 linkstatic/meson.build +test cases/common/50 custom target chain/data_source.txt +test cases/common/50 custom target chain/meson.build +test cases/common/50 custom target chain/my_compiler.py +test cases/common/50 custom target chain/my_compiler2.py +test cases/common/50 custom target chain/test.json +test cases/common/50 custom target chain/usetarget/meson.build +test cases/common/50 custom target chain/usetarget/myexe.c +test cases/common/50 custom target chain/usetarget/subcomp.py +test cases/common/51 run target/.clang-format +test cases/common/51 run target/.clang-tidy +test cases/common/51 run target/check-env.py +test cases/common/51 run target/check_exists.py +test cases/common/51 run target/configure.in +test cases/common/51 run target/converter.py +test cases/common/51 run target/fakeburner.py +test cases/common/51 run target/helloprinter.c +test cases/common/51 run target/meson.build +test cases/common/51 run target/subdir/textprinter.py +test cases/common/52 object generator/meson.build +test cases/common/52 object generator/obj_generator.py +test cases/common/52 object generator/prog.c +test cases/common/52 object generator/source.c +test cases/common/52 object generator/source2.c +test cases/common/52 object generator/source3.c +test cases/common/53 install script/customtarget.py +test cases/common/53 install script/meson.build +test cases/common/53 install script/myinstall.py +test cases/common/53 install script/prog.c +test cases/common/53 install script/test.json +test cases/common/53 install script/src/a file.txt +test cases/common/53 install script/src/foo.c +test cases/common/53 install script/src/meson.build +test cases/common/53 install script/src/myinstall.py +test cases/common/54 custom target source output/generator.py +test cases/common/54 custom target source output/main.c +test cases/common/54 custom target source output/meson.build +test cases/common/55 exe static shared/meson.build +test cases/common/55 exe static shared/prog.c +test cases/common/55 exe static shared/shlib2.c +test cases/common/55 exe static shared/stat.c +test cases/common/55 exe static shared/stat2.c +test cases/common/55 exe static shared/subdir/exports.h +test cases/common/55 exe static shared/subdir/meson.build +test cases/common/55 exe static shared/subdir/shlib.c +test cases/common/56 array methods/a.txt +test cases/common/56 array methods/b.txt +test cases/common/56 array methods/c.txt +test cases/common/56 array methods/meson.build +test cases/common/57 custom header generator/input.def +test cases/common/57 custom header generator/makeheader.py +test cases/common/57 custom header generator/meson.build +test cases/common/57 custom header generator/prog.c +test cases/common/57 custom header generator/somefile.txt +test cases/common/58 multiple generators/data2.dat +test cases/common/58 multiple generators/main.cpp +test cases/common/58 multiple generators/meson.build +test cases/common/58 multiple generators/mygen.py +test cases/common/58 multiple generators/subdir/data.dat +test cases/common/58 multiple generators/subdir/meson.build +test cases/common/59 install subdir/meson.build +test cases/common/59 install subdir/test.json +test cases/common/59 install subdir/nested_elided/sub/eighth.dat +test cases/common/59 install subdir/nested_elided/sub/dircheck/ninth.dat +test cases/common/59 install subdir/sub/sub1/third.dat +test cases/common/59 install subdir/sub1/second.dat +test cases/common/59 install subdir/sub2/excluded-three.dat +test cases/common/59 install subdir/sub2/one.dat +test cases/common/59 install subdir/sub2/dircheck/excluded-three.dat +test cases/common/59 install subdir/sub2/excluded/two.dat +test cases/common/59 install subdir/sub3/data/data.txt +test cases/common/59 install subdir/sub3/data/excluded.txt +test cases/common/59 install subdir/sub3/data/excluded/excluded.txt +test cases/common/59 install subdir/sub_elided/fourth.dat +test cases/common/59 install subdir/sub_elided/dircheck/fifth.dat +test cases/common/59 install subdir/subdir/meson.build +test cases/common/59 install subdir/subdir/sub1/data1.dat +test cases/common/59 install subdir/subdir/sub1/sub2/data2.dat +test cases/common/59 install subdir/subdir/sub_elided/sixth.dat +test cases/common/59 install subdir/subdir/sub_elided/dircheck/seventh.dat +test cases/common/6 linkshared/cpplib.cpp +test cases/common/6 linkshared/cpplib.h +test cases/common/6 linkshared/cppmain.cpp +test cases/common/6 linkshared/libfile.c +test cases/common/6 linkshared/main.c +test cases/common/6 linkshared/meson.build +test cases/common/6 linkshared/test.json +test cases/common/60 foreach/meson.build +test cases/common/60 foreach/prog1.c +test cases/common/60 foreach/prog2.c +test cases/common/60 foreach/prog3.c +test cases/common/60 foreach/test.json +test cases/common/61 number arithmetic/meson.build +test cases/common/62 string arithmetic/meson.build +test cases/common/62 string arithmetic/test.json +test cases/common/63 array arithmetic/meson.build +test cases/common/64 arithmetic bidmas/meson.build +test cases/common/65 build always/main.c +test cases/common/65 build always/meson.build +test cases/common/65 build always/version.c.in +test cases/common/65 build always/version.h +test cases/common/65 build always/version_gen.py +test cases/common/66 vcstag/meson.build +test cases/common/66 vcstag/tagprog.c +test cases/common/66 vcstag/vcstag.c.in +test cases/common/66 vcstag/version.py +test cases/common/67 modules/meson.build +test cases/common/67 modules/meson_options.txt +test cases/common/68 should fail/failing.c +test cases/common/68 should fail/meson.build +test cases/common/69 configure file in custom target/meson.build +test cases/common/69 configure file in custom target/inc/confdata.in +test cases/common/69 configure file in custom target/inc/meson.build +test cases/common/69 configure file in custom target/src/meson.build +test cases/common/69 configure file in custom target/src/mycompiler.py +test cases/common/7 mixed/func.c +test cases/common/7 mixed/main.cc +test cases/common/7 mixed/meson.build +test cases/common/70 external test program/meson.build +test cases/common/70 external test program/mytest.py +test cases/common/71 ctarget dependency/gen1.py +test cases/common/71 ctarget dependency/gen2.py +test cases/common/71 ctarget dependency/input.dat +test cases/common/71 ctarget dependency/meson.build +test cases/common/72 shared subproject/a.c +test cases/common/72 shared subproject/meson.build +test cases/common/72 shared subproject/subprojects/B/b.c +test cases/common/72 shared subproject/subprojects/B/meson.build +test cases/common/72 shared subproject/subprojects/C/c.c +test cases/common/72 shared subproject/subprojects/C/meson.build +test cases/common/73 shared subproject 2/a.c +test cases/common/73 shared subproject 2/meson.build +test cases/common/73 shared subproject 2/subprojects/B/b.c +test cases/common/73 shared subproject 2/subprojects/B/meson.build +test cases/common/73 shared subproject 2/subprojects/C/c.c +test cases/common/73 shared subproject 2/subprojects/C/meson.build +test cases/common/74 file object/lib.c +test cases/common/74 file object/meson.build +test cases/common/74 file object/prog.c +test cases/common/74 file object/subdir1/lib.c +test cases/common/74 file object/subdir1/meson.build +test cases/common/74 file object/subdir1/prog.c +test cases/common/74 file object/subdir2/lib.c +test cases/common/74 file object/subdir2/meson.build +test cases/common/74 file object/subdir2/prog.c +test cases/common/75 custom subproject dir/a.c +test cases/common/75 custom subproject dir/meson.build +test cases/common/75 custom subproject dir/custom_subproject_dir/B/b.c +test cases/common/75 custom subproject dir/custom_subproject_dir/B/meson.build +test cases/common/75 custom subproject dir/custom_subproject_dir/C/c.c +test cases/common/75 custom subproject dir/custom_subproject_dir/C/meson.build +test cases/common/76 has type/meson.build +test cases/common/77 extract from nested subdir/meson.build +test cases/common/77 extract from nested subdir/src/meson.build +test cases/common/77 extract from nested subdir/src/first/lib_first.c +test cases/common/77 extract from nested subdir/src/first/meson.build +test cases/common/77 extract from nested subdir/tst/meson.build +test cases/common/77 extract from nested subdir/tst/first/exe_first.c +test cases/common/77 extract from nested subdir/tst/first/meson.build +test cases/common/78 internal dependency/meson.build +test cases/common/78 internal dependency/proj1/meson.build +test cases/common/78 internal dependency/proj1/proj1f1.c +test cases/common/78 internal dependency/proj1/proj1f2.c +test cases/common/78 internal dependency/proj1/proj1f3.c +test cases/common/78 internal dependency/proj1/include/proj1.h +test cases/common/78 internal dependency/src/main.c +test cases/common/78 internal dependency/src/meson.build +test cases/common/79 same basename/exe1.c +test cases/common/79 same basename/exe2.c +test cases/common/79 same basename/lib.c +test cases/common/79 same basename/meson.build +test cases/common/79 same basename/sharedsub/meson.build +test cases/common/79 same basename/staticsub/meson.build +test cases/common/8 install/gendir.py +test cases/common/8 install/meson.build +test cases/common/8 install/prog.c +test cases/common/8 install/stat.c +test cases/common/8 install/test.json +test cases/common/80 declare dep/main.c +test cases/common/80 declare dep/meson.build +test cases/common/80 declare dep/entity/entity.h +test cases/common/80 declare dep/entity/entity1.c +test cases/common/80 declare dep/entity/entity2.c +test cases/common/80 declare dep/entity/meson.build +test cases/common/81 extract all/extractor.h +test cases/common/81 extract all/four.c +test cases/common/81 extract all/meson.build +test cases/common/81 extract all/one.c +test cases/common/81 extract all/prog.c +test cases/common/81 extract all/three.c +test cases/common/81 extract all/two.c +test cases/common/82 add language/meson.build +test cases/common/82 add language/prog.c +test cases/common/82 add language/prog.cc +test cases/common/83 identical target name in subproject/bar.c +test cases/common/83 identical target name in subproject/meson.build +test cases/common/83 identical target name in subproject/true.py +test cases/common/83 identical target name in subproject/subprojects/foo/bar.c +test cases/common/83 identical target name in subproject/subprojects/foo/meson.build +test cases/common/83 identical target name in subproject/subprojects/foo/true.py +test cases/common/84 plusassign/meson.build +test cases/common/85 skip subdir/meson.build +test cases/common/85 skip subdir/subdir1/meson.build +test cases/common/85 skip subdir/subdir1/subdir2/meson.build +test cases/common/86 private include/meson.build +test cases/common/86 private include/stlib/compiler.py +test cases/common/86 private include/stlib/foo1.def +test cases/common/86 private include/stlib/foo2.def +test cases/common/86 private include/stlib/meson.build +test cases/common/86 private include/user/libuser.c +test cases/common/86 private include/user/meson.build +test cases/common/87 default options/meson.build +test cases/common/87 default options/subprojects/sub1/meson.build +test cases/common/87 default options/subprojects/sub1/meson_options.txt +test cases/common/88 dep fallback/gensrc.py +test cases/common/88 dep fallback/meson.build +test cases/common/88 dep fallback/tester.c +test cases/common/88 dep fallback/subprojects/boblib/bob.c +test cases/common/88 dep fallback/subprojects/boblib/bob.h +test cases/common/88 dep fallback/subprojects/boblib/genbob.py +test cases/common/88 dep fallback/subprojects/boblib/meson.build +test cases/common/88 dep fallback/subprojects/dummylib/meson.build +test cases/common/89 default library/ef.cpp +test cases/common/89 default library/ef.h +test cases/common/89 default library/eftest.cpp +test cases/common/89 default library/meson.build +test cases/common/9 header install/meson.build +test cases/common/9 header install/rootdir.h +test cases/common/9 header install/subdir.h +test cases/common/9 header install/test.json +test cases/common/9 header install/child/childdir.h +test cases/common/9 header install/sub/fileheader.h +test cases/common/9 header install/sub/meson.build +test cases/common/9 header install/vanishing_subdir/meson.build +test cases/common/9 header install/vanishing_subdir/vanished.h +test cases/common/90 gen extra/meson.build +test cases/common/90 gen extra/name.dat +test cases/common/90 gen extra/name.l +test cases/common/90 gen extra/plain.c +test cases/common/90 gen extra/srcgen.py +test cases/common/90 gen extra/srcgen2.py +test cases/common/90 gen extra/srcgen3.py +test cases/common/90 gen extra/upper.c +test cases/common/91 benchmark/delayer.c +test cases/common/91 benchmark/meson.build +test cases/common/92 test workdir/meson.build +test cases/common/92 test workdir/opener.c +test cases/common/92 test workdir/subdir/checker.py +test cases/common/92 test workdir/subdir/meson.build +test cases/common/93 suites/exe1.c +test cases/common/93 suites/exe2.c +test cases/common/93 suites/meson.build +test cases/common/93 suites/subprojects/sub/meson.build +test cases/common/93 suites/subprojects/sub/sub1.c +test cases/common/93 suites/subprojects/sub/sub2.c +test cases/common/94 threads/meson.build +test cases/common/94 threads/threadprog.c +test cases/common/94 threads/threadprog.cpp +test cases/common/95 manygen/depuser.c +test cases/common/95 manygen/meson.build +test cases/common/95 manygen/subdir/funcinfo.def +test cases/common/95 manygen/subdir/manygen.py +test cases/common/95 manygen/subdir/meson.build +test cases/common/96 stringdef/meson.build +test cases/common/96 stringdef/stringdef.c +test cases/common/97 find program path/meson.build +test cases/common/97 find program path/program.py +test cases/common/98 subproject subdir/meson.build +test cases/common/98 subproject subdir/prog.c +test cases/common/98 subproject subdir/test.json +test cases/common/98 subproject subdir/subprojects/sub_implicit.wrap +test cases/common/98 subproject subdir/subprojects/subsubsub.wrap +test cases/common/98 subproject subdir/subprojects/sub/meson.build +test cases/common/98 subproject subdir/subprojects/sub/lib/meson.build +test cases/common/98 subproject subdir/subprojects/sub/lib/sub.c +test cases/common/98 subproject subdir/subprojects/sub/lib/sub.h +test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build +test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt +test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h +test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build +test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/subsubsub.wrap +test cases/common/98 subproject subdir/subprojects/sub_implicit/subprojects/subsub/subprojects/packagefiles/subsubsub-1.0.zip +test cases/common/98 subproject subdir/subprojects/sub_novar/meson.build +test cases/common/98 subproject subdir/subprojects/sub_static/meson.build +test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/.meson-subproject-wrap-hash.txt +test cases/common/98 subproject subdir/subprojects/subsubsub-1.0/meson.build +test cases/common/99 postconf/meson.build +test cases/common/99 postconf/postconf.py +test cases/common/99 postconf/prog.c +test cases/common/99 postconf/raw.dat +test cases/csharp/1 basic/meson.build +test cases/csharp/1 basic/prog.cs +test cases/csharp/1 basic/test.json +test cases/csharp/1 basic/text.cs +test cases/csharp/2 library/helper.cs +test cases/csharp/2 library/meson.build +test cases/csharp/2 library/prog.cs +test cases/csharp/2 library/test.json +test cases/csharp/3 resource/TestRes.resx +test cases/csharp/3 resource/meson.build +test cases/csharp/3 resource/resprog.cs +test cases/csharp/4 external dep/hello.txt +test cases/csharp/4 external dep/meson.build +test cases/csharp/4 external dep/prog.cs +test cases/csharp/4 external dep/test.json +test cases/cuda/1 simple/meson.build +test cases/cuda/1 simple/prog.cu +test cases/cuda/10 cuda dependency/meson.build +test cases/cuda/10 cuda dependency/c/meson.build +test cases/cuda/10 cuda dependency/c/prog.c +test cases/cuda/10 cuda dependency/cpp/meson.build +test cases/cuda/10 cuda dependency/cpp/prog.cc +test cases/cuda/10 cuda dependency/modules/meson.build +test cases/cuda/10 cuda dependency/modules/prog.cc +test cases/cuda/10 cuda dependency/version_reqs/meson.build +test cases/cuda/10 cuda dependency/version_reqs/prog.cc +test cases/cuda/11 cuda dependency (nvcc)/meson.build +test cases/cuda/11 cuda dependency (nvcc)/modules/meson.build +test cases/cuda/11 cuda dependency (nvcc)/modules/prog.cu +test cases/cuda/11 cuda dependency (nvcc)/version_reqs/meson.build +test cases/cuda/11 cuda dependency (nvcc)/version_reqs/prog.cu +test cases/cuda/12 cuda dependency (mixed)/kernel.cu +test cases/cuda/12 cuda dependency (mixed)/meson.build +test cases/cuda/12 cuda dependency (mixed)/prog.cpp +test cases/cuda/13 cuda compiler setting/meson.build +test cases/cuda/13 cuda compiler setting/nativefile.ini +test cases/cuda/13 cuda compiler setting/prog.cu +test cases/cuda/14 cuda has header symbol/meson.build +test cases/cuda/15 sanitizer/meson.build +test cases/cuda/15 sanitizer/prog.cu +test cases/cuda/16 multistd/lib.cu +test cases/cuda/16 multistd/main.cu +test cases/cuda/16 multistd/meson.build +test cases/cuda/2 split/lib.cu +test cases/cuda/2 split/main.cpp +test cases/cuda/2 split/meson.build +test cases/cuda/2 split/static/lib.cu +test cases/cuda/2 split/static/libsta.cu +test cases/cuda/2 split/static/main_static.cpp +test cases/cuda/2 split/static/meson.build +test cases/cuda/3 cudamodule/meson.build +test cases/cuda/3 cudamodule/prog.cu +test cases/cuda/4 shared/main.cu +test cases/cuda/4 shared/meson.build +test cases/cuda/4 shared/shared/kernels.cu +test cases/cuda/4 shared/shared/kernels.h +test cases/cuda/4 shared/shared/meson.build +test cases/cuda/5 threads/main.cu +test cases/cuda/5 threads/meson.build +test cases/cuda/5 threads/shared/kernels.cu +test cases/cuda/5 threads/shared/kernels.h +test cases/cuda/5 threads/shared/meson.build +test cases/cuda/6 std/main.cu +test cases/cuda/6 std/meson.build +test cases/cuda/7 static vs runtime/main.cu +test cases/cuda/7 static vs runtime/meson.build +test cases/cuda/8 release/main.cu +test cases/cuda/8 release/meson.build +test cases/cuda/9 optimize for space/main.cu +test cases/cuda/9 optimize for space/meson.build +test cases/cython/1 basic/cytest.py +test cases/cython/1 basic/meson.build +test cases/cython/1 basic/test.json +test cases/cython/1 basic/libdir/cstorer.pxd +test cases/cython/1 basic/libdir/meson.build +test cases/cython/1 basic/libdir/storer.c +test cases/cython/1 basic/libdir/storer.h +test cases/cython/1 basic/libdir/storer.pyx +test cases/cython/2 generated sources/configure.pyx.in +test cases/cython/2 generated sources/g.in +test cases/cython/2 generated sources/gen.py +test cases/cython/2 generated sources/generator.py +test cases/cython/2 generated sources/includestuff.pyx +test cases/cython/2 generated sources/meson.build +test cases/cython/2 generated sources/simpleinclude.pyx +test cases/cython/2 generated sources/simplestuff.pxi +test cases/cython/2 generated sources/stuff.pxi.in +test cases/cython/2 generated sources/test.py +test cases/cython/2 generated sources/libdir/gen.py +test cases/cython/2 generated sources/libdir/meson.build +test cases/cython/3 cython_args/cythonargs.pyx +test cases/cython/3 cython_args/meson.build +test cases/cython/3 cython_args/test.py +test cases/d/1 simple/app.d +test cases/d/1 simple/meson.build +test cases/d/1 simple/test.json +test cases/d/1 simple/utils.d +test cases/d/10 d cpp/cppmain.cpp +test cases/d/10 d cpp/dmain.d +test cases/d/10 d cpp/libfile.cpp +test cases/d/10 d cpp/libfile.d +test cases/d/10 d cpp/meson.build +test cases/d/11 dub/.gitignore +test cases/d/11 dub/meson.build +test cases/d/11 dub/test.d +test cases/d/12 root include directory/meson.build +test cases/d/12 root include directory/some/meson.build +test cases/d/12 root include directory/some/dlang/code.d +test cases/d/12 root include directory/some/dlang/meson.build +test cases/d/13 declare dep/meson.build +test cases/d/13 declare dep/test.d +test cases/d/13 declare dep/views/test.txt +test cases/d/14 dub with deps/meson.build +test cases/d/14 dub with deps/test.d +test cases/d/15 compiler run checks/meson.build +test cases/d/15 compiler run checks/test_sizeof.d +test cases/d/16 code generation/exe.d +test cases/d/16 code generation/generator.d +test cases/d/16 code generation/input.txt +test cases/d/16 code generation/meson.build +test cases/d/2 static library/app.d +test cases/d/2 static library/libstuff.d +test cases/d/2 static library/meson.build +test cases/d/2 static library/test.json +test cases/d/3 shared library/app.d +test cases/d/3 shared library/libstuff.d +test cases/d/3 shared library/libstuff.di +test cases/d/3 shared library/lld-test.py +test cases/d/3 shared library/meson.build +test cases/d/3 shared library/test.json +test cases/d/3 shared library/sub/libstuff.d +test cases/d/3 shared library/sub/meson.build +test cases/d/4 library versions/lib.d +test cases/d/4 library versions/meson.build +test cases/d/4 library versions/test.json +test cases/d/5 mixed/app.d +test cases/d/5 mixed/libstuff.c +test cases/d/5 mixed/meson.build +test cases/d/5 mixed/test.json +test cases/d/6 unittest/app.d +test cases/d/6 unittest/meson.build +test cases/d/6 unittest/second_unit.d +test cases/d/6 unittest/test.json +test cases/d/7 multilib/app.d +test cases/d/7 multilib/meson.build +test cases/d/7 multilib/say1.d +test cases/d/7 multilib/say1.di +test cases/d/7 multilib/say2.d +test cases/d/7 multilib/say2.di +test cases/d/7 multilib/test.json +test cases/d/8 has multi arguments/meson.build +test cases/d/9 features/app.d +test cases/d/9 features/extra.d +test cases/d/9 features/meson.build +test cases/d/9 features/data/food.txt +test cases/d/9 features/data/people.txt +test cases/failing build/1 vala c werror/meson.build +test cases/failing build/1 vala c werror/prog.vala +test cases/failing build/1 vala c werror/unused-var.c +test cases/failing build/2 hidden symbol/bob.c +test cases/failing build/2 hidden symbol/bob.h +test cases/failing build/2 hidden symbol/bobuser.c +test cases/failing build/2 hidden symbol/meson.build +test cases/failing build/3 pch disabled/meson.build +test cases/failing build/3 pch disabled/c/meson.build +test cases/failing build/3 pch disabled/c/prog.c +test cases/failing build/3 pch disabled/c/pch/prog.h +test cases/failing build/3 pch disabled/c/pch/prog_pch.c +test cases/failing build/4 cmake subproject isolation/main.cpp +test cases/failing build/4 cmake subproject isolation/meson.build +test cases/failing build/4 cmake subproject isolation/test.json +test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp +test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt +test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp +test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp +test cases/failing build/5 failed pickled/false.py +test cases/failing build/5 failed pickled/meson.build +test cases/failing test/1 trivial/main.c +test cases/failing test/1 trivial/meson.build +test cases/failing test/2 signal/main.c +test cases/failing test/2 signal/meson.build +test cases/failing test/3 ambiguous/main.c +test cases/failing test/3 ambiguous/meson.build +test cases/failing test/3 ambiguous/test_runner.sh +test cases/failing test/4 hard error/main.c +test cases/failing test/4 hard error/meson.build +test cases/failing test/5 tap tests/meson.build +test cases/failing test/5 tap tests/tester.c +test cases/failing test/5 tap tests/tester_with_status.c +test cases/failing test/6 xpass/meson.build +test cases/failing test/6 xpass/xpass.c +test cases/failing/1 project not first/meson.build +test cases/failing/1 project not first/prog.c +test cases/failing/1 project not first/test.json +test cases/failing/10 out of bounds/meson.build +test cases/failing/10 out of bounds/test.json +test cases/failing/100 no glib-compile-resources/meson.build +test cases/failing/100 no glib-compile-resources/test.json +test cases/failing/100 no glib-compile-resources/trivial.gresource.xml +test cases/failing/101 number in combo/meson.build +test cases/failing/101 number in combo/nativefile.ini +test cases/failing/101 number in combo/test.json +test cases/failing/102 bool in combo/meson.build +test cases/failing/102 bool in combo/meson_options.txt +test cases/failing/102 bool in combo/nativefile.ini +test cases/failing/102 bool in combo/test.json +test cases/failing/103 compiler no lang/meson.build +test cases/failing/103 compiler no lang/test.json +test cases/failing/104 no fallback/meson.build +test cases/failing/104 no fallback/test.json +test cases/failing/104 no fallback/subprojects/foob/meson.build +test cases/failing/105 feature require/meson.build +test cases/failing/105 feature require/meson_options.txt +test cases/failing/105 feature require/test.json +test cases/failing/106 feature require.bis/meson.build +test cases/failing/106 feature require.bis/meson_options.txt +test cases/failing/106 feature require.bis/test.json +test cases/failing/107 no build get_external_property/meson.build +test cases/failing/107 no build get_external_property/test.json +test cases/failing/108 enter subdir twice/meson.build +test cases/failing/108 enter subdir twice/test.json +test cases/failing/108 enter subdir twice/sub/meson.build +test cases/failing/109 invalid fstring/meson.build +test cases/failing/109 invalid fstring/test.json +test cases/failing/109 invalid fstring/109 invalid fstring/meson.build +test cases/failing/109 invalid fstring/109 invalid fstring/test.json +test cases/failing/11 object arithmetic/meson.build +test cases/failing/11 object arithmetic/test.json +test cases/failing/110 compiler argument checking/meson.build +test cases/failing/110 compiler argument checking/test.json +test cases/failing/111 empty fallback/meson.build +test cases/failing/111 empty fallback/test.json +test cases/failing/111 empty fallback/subprojects/foo/meson.build +test cases/failing/112 cmake executable dependency/meson.build +test cases/failing/112 cmake executable dependency/test.json +test cases/failing/112 cmake executable dependency/subprojects/cmlib/CMakeLists.txt +test cases/failing/112 cmake executable dependency/subprojects/cmlib/main.c +test cases/failing/113 allow_fallback with fallback/meson.build +test cases/failing/113 allow_fallback with fallback/test.json +test cases/failing/114 nonsensical bindgen/meson.build +test cases/failing/114 nonsensical bindgen/test.json +test cases/failing/114 nonsensical bindgen/src/header.h +test cases/failing/114 nonsensical bindgen/src/source.c +test cases/failing/115 run_target in test/meson.build +test cases/failing/115 run_target in test/test.json +test cases/failing/115 run_target in test/trivial.c +test cases/failing/116 run_target in add_install_script/meson.build +test cases/failing/116 run_target in add_install_script/test.json +test cases/failing/116 run_target in add_install_script/trivial.c +test cases/failing/117 pathsep in install_symlink/meson.build +test cases/failing/117 pathsep in install_symlink/test.json +test cases/failing/118 subproject version conflict/meson.build +test cases/failing/118 subproject version conflict/test.json +test cases/failing/118 subproject version conflict/subprojects/A/meson.build +test cases/failing/118 subproject version conflict/subprojects/B/meson.build +test cases/failing/119 structured source empty string/main.rs +test cases/failing/119 structured source empty string/meson.build +test cases/failing/119 structured source empty string/test.json +test cases/failing/12 string arithmetic/meson.build +test cases/failing/12 string arithmetic/test.json +test cases/failing/120 structured_sources conflicts/main.rs +test cases/failing/120 structured_sources conflicts/meson.build +test cases/failing/120 structured_sources conflicts/test.json +test cases/failing/121 missing compiler/meson.build +test cases/failing/121 missing compiler/test.json +test cases/failing/121 missing compiler/subprojects/sub/main.c +test cases/failing/121 missing compiler/subprojects/sub/meson.build +test cases/failing/122 cmake subproject error/meson.build +test cases/failing/122 cmake subproject error/test.json +test cases/failing/122 cmake subproject error/subprojects/cmlib/CMakeLists.txt +test cases/failing/123 pkgconfig not relocatable outside prefix/meson.build +test cases/failing/123 pkgconfig not relocatable outside prefix/test.json +test cases/failing/124 subproject sandbox violation/meson.build +test cases/failing/124 subproject sandbox violation/meson_options.txt +test cases/failing/124 subproject sandbox violation/test.json +test cases/failing/124 subproject sandbox violation/subprojects/subproj1/file.txt +test cases/failing/124 subproject sandbox violation/subprojects/subproj1/meson.build +test cases/failing/124 subproject sandbox violation/subprojects/subproj1/nested/meson.build +test cases/failing/124 subproject sandbox violation/subprojects/subproj2/file.txt +test cases/failing/124 subproject sandbox violation/subprojects/subproj2/meson.build +test cases/failing/124 subproject sandbox violation/subprojects/subproj2/nested/meson.build +test cases/failing/124 subproject sandbox violation/subprojects/subproj3/file.txt +test cases/failing/124 subproject sandbox violation/subprojects/subproj3/meson.build +test cases/failing/125 override and add_project_dependency/lib.c +test cases/failing/125 override and add_project_dependency/meson.build +test cases/failing/125 override and add_project_dependency/test.json +test cases/failing/125 override and add_project_dependency/inc/lib.h +test cases/failing/125 override and add_project_dependency/subprojects/a/meson.build +test cases/failing/125 override and add_project_dependency/subprojects/a/prog.c +test cases/failing/126 targets before add_project_dependency/lib.c +test cases/failing/126 targets before add_project_dependency/meson.build +test cases/failing/126 targets before add_project_dependency/test.json +test cases/failing/126 targets before add_project_dependency/inc/lib.h +test cases/failing/127 extract from unity/meson.build +test cases/failing/127 extract from unity/src1.c +test cases/failing/127 extract from unity/src2.c +test cases/failing/127 extract from unity/test.json +test cases/failing/128 subproject object as a dependency/main.c +test cases/failing/128 subproject object as a dependency/meson.build +test cases/failing/128 subproject object as a dependency/test.json +test cases/failing/128 subproject object as a dependency/subprojects/sub/meson.build +test cases/failing/129 generator host binary/exe.c +test cases/failing/129 generator host binary/lib.in +test cases/failing/129 generator host binary/meson.build +test cases/failing/129 generator host binary/test.json +test cases/failing/13 array arithmetic/meson.build +test cases/failing/13 array arithmetic/test.json +test cases/failing/130 invalid ast/meson.build +test cases/failing/130 invalid ast/test.json +test cases/failing/131 invalid project function/meson.build +test cases/failing/131 invalid project function/test.json +test cases/failing/14 invalid option name/meson.build +test cases/failing/14 invalid option name/meson_options.txt +test cases/failing/14 invalid option name/test.json +test cases/failing/15 kwarg before arg/meson.build +test cases/failing/15 kwarg before arg/prog.c +test cases/failing/15 kwarg before arg/test.json +test cases/failing/16 extract from subproject/main.c +test cases/failing/16 extract from subproject/meson.build +test cases/failing/16 extract from subproject/test.json +test cases/failing/16 extract from subproject/subprojects/sub_project/meson.build +test cases/failing/16 extract from subproject/subprojects/sub_project/sub_lib.c +test cases/failing/17 same target/file.c +test cases/failing/17 same target/meson.build +test cases/failing/17 same target/test.json +test cases/failing/18 wrong plusassign/meson.build +test cases/failing/18 wrong plusassign/test.json +test cases/failing/19 target clash/clash.c +test cases/failing/19 target clash/meson.build +test cases/failing/19 target clash/test.json +test cases/failing/2 missing file/meson.build +test cases/failing/2 missing file/test.json +test cases/failing/20 version/meson.build +test cases/failing/20 version/test.json +test cases/failing/21 subver/meson.build +test cases/failing/21 subver/test.json +test cases/failing/21 subver/subprojects/foo/meson.build +test cases/failing/22 assert/meson.build +test cases/failing/22 assert/test.json +test cases/failing/23 rel testdir/meson.build +test cases/failing/23 rel testdir/simple.c +test cases/failing/23 rel testdir/test.json +test cases/failing/24 int conversion/meson.build +test cases/failing/24 int conversion/test.json +test cases/failing/25 badlang/meson.build +test cases/failing/25 badlang/test.json +test cases/failing/26 output subdir/foo.in +test cases/failing/26 output subdir/meson.build +test cases/failing/26 output subdir/test.json +test cases/failing/26 output subdir/subdir/dummy.txt +test cases/failing/27 noprog use/meson.build +test cases/failing/27 noprog use/test.json +test cases/failing/28 no crossprop/meson.build +test cases/failing/28 no crossprop/test.json +test cases/failing/29 nested ternary/meson.build +test cases/failing/29 nested ternary/test.json +test cases/failing/3 missing subdir/meson.build +test cases/failing/3 missing subdir/test.json +test cases/failing/30 invalid man extension/foo.a1 +test cases/failing/30 invalid man extension/meson.build +test cases/failing/30 invalid man extension/test.json +test cases/failing/31 no man extension/foo +test cases/failing/31 no man extension/meson.build +test cases/failing/31 no man extension/test.json +test cases/failing/32 exe static shared/meson.build +test cases/failing/32 exe static shared/prog.c +test cases/failing/32 exe static shared/shlib2.c +test cases/failing/32 exe static shared/stat.c +test cases/failing/32 exe static shared/test.json +test cases/failing/33 non-root subproject/meson.build +test cases/failing/33 non-root subproject/test.json +test cases/failing/33 non-root subproject/some/meson.build +test cases/failing/34 dependency not-required then required/meson.build +test cases/failing/34 dependency not-required then required/test.json +test cases/failing/35 project argument after target/exe.c +test cases/failing/35 project argument after target/meson.build +test cases/failing/35 project argument after target/test.json +test cases/failing/36 pkgconfig dependency impossible conditions/meson.build +test cases/failing/36 pkgconfig dependency impossible conditions/test.json +test cases/failing/37 has function external dependency/meson.build +test cases/failing/37 has function external dependency/mylib.c +test cases/failing/37 has function external dependency/test.json +test cases/failing/38 prefix absolute/meson.build +test cases/failing/38 prefix absolute/test.json +test cases/failing/39 kwarg assign/dummy.c +test cases/failing/39 kwarg assign/meson.build +test cases/failing/39 kwarg assign/prog.c +test cases/failing/39 kwarg assign/test.json +test cases/failing/4 missing meson.build/meson.build +test cases/failing/4 missing meson.build/test.json +test cases/failing/4 missing meson.build/subdir/dummy.txt +test cases/failing/40 custom target plainname many inputs/1.txt +test cases/failing/40 custom target plainname many inputs/2.txt +test cases/failing/40 custom target plainname many inputs/catfiles.py +test cases/failing/40 custom target plainname many inputs/meson.build +test cases/failing/40 custom target plainname many inputs/test.json +test cases/failing/41 custom target outputs not matching install_dirs/generator.py +test cases/failing/41 custom target outputs not matching install_dirs/meson.build +test cases/failing/41 custom target outputs not matching install_dirs/test.json +test cases/failing/42 project name colon/meson.build +test cases/failing/42 project name colon/test.json +test cases/failing/43 abs subdir/meson.build +test cases/failing/43 abs subdir/test.json +test cases/failing/43 abs subdir/bob/meson.build +test cases/failing/44 abspath to srcdir/meson.build +test cases/failing/44 abspath to srcdir/test.json +test cases/failing/45 pkgconfig variables reserved/meson.build +test cases/failing/45 pkgconfig variables reserved/simple.c +test cases/failing/45 pkgconfig variables reserved/simple.h +test cases/failing/45 pkgconfig variables reserved/test.json +test cases/failing/46 pkgconfig variables zero length/meson.build +test cases/failing/46 pkgconfig variables zero length/simple.c +test cases/failing/46 pkgconfig variables zero length/simple.h +test cases/failing/46 pkgconfig variables zero length/test.json +test cases/failing/47 pkgconfig variables zero length value/meson.build +test cases/failing/47 pkgconfig variables zero length value/simple.c +test cases/failing/47 pkgconfig variables zero length value/simple.h +test cases/failing/47 pkgconfig variables zero length value/test.json +test cases/failing/48 pkgconfig variables not key value/meson.build +test cases/failing/48 pkgconfig variables not key value/simple.c +test cases/failing/48 pkgconfig variables not key value/simple.h +test cases/failing/48 pkgconfig variables not key value/test.json +test cases/failing/49 executable comparison/meson.build +test cases/failing/49 executable comparison/prog.c +test cases/failing/49 executable comparison/test.json +test cases/failing/5 misplaced option/meson.build +test cases/failing/5 misplaced option/test.json +test cases/failing/50 inconsistent comparison/meson.build +test cases/failing/50 inconsistent comparison/test.json +test cases/failing/51 slashname/meson.build +test cases/failing/51 slashname/test.json +test cases/failing/51 slashname/sub/meson.build +test cases/failing/51 slashname/sub/prog.c +test cases/failing/52 reserved meson prefix/meson.build +test cases/failing/52 reserved meson prefix/test.json +test cases/failing/52 reserved meson prefix/meson-foo/meson.build +test cases/failing/53 wrong shared crate type/foo.rs +test cases/failing/53 wrong shared crate type/meson.build +test cases/failing/53 wrong shared crate type/test.json +test cases/failing/54 wrong static crate type/foo.rs +test cases/failing/54 wrong static crate type/meson.build +test cases/failing/54 wrong static crate type/test.json +test cases/failing/55 or on new line/meson.build +test cases/failing/55 or on new line/meson_options.txt +test cases/failing/55 or on new line/test.json +test cases/failing/56 link with executable/meson.build +test cases/failing/56 link with executable/module.c +test cases/failing/56 link with executable/prog.c +test cases/failing/56 link with executable/test.json +test cases/failing/57 assign custom target index/meson.build +test cases/failing/57 assign custom target index/test.json +test cases/failing/58 getoption prefix/meson.build +test cases/failing/58 getoption prefix/test.json +test cases/failing/58 getoption prefix/subprojects/abc/meson.build +test cases/failing/58 getoption prefix/subprojects/abc/meson_options.txt +test cases/failing/59 bad option argument/meson.build +test cases/failing/59 bad option argument/meson_options.txt +test cases/failing/59 bad option argument/test.json +test cases/failing/6 missing incdir/meson.build +test cases/failing/6 missing incdir/test.json +test cases/failing/60 subproj filegrab/meson.build +test cases/failing/60 subproj filegrab/prog.c +test cases/failing/60 subproj filegrab/test.json +test cases/failing/60 subproj filegrab/subprojects/a/meson.build +test cases/failing/61 grab subproj/meson.build +test cases/failing/61 grab subproj/test.json +test cases/failing/61 grab subproj/subprojects/foo/meson.build +test cases/failing/61 grab subproj/subprojects/foo/sub.c +test cases/failing/62 grab sibling/meson.build +test cases/failing/62 grab sibling/test.json +test cases/failing/62 grab sibling/subprojects/a/meson.build +test cases/failing/62 grab sibling/subprojects/b/meson.build +test cases/failing/62 grab sibling/subprojects/b/sneaky.c +test cases/failing/63 string as link target/meson.build +test cases/failing/63 string as link target/prog.c +test cases/failing/63 string as link target/test.json +test cases/failing/64 dependency not-found and required/meson.build +test cases/failing/64 dependency not-found and required/test.json +test cases/failing/65 subproj different versions/main.c +test cases/failing/65 subproj different versions/meson.build +test cases/failing/65 subproj different versions/test.json +test cases/failing/65 subproj different versions/subprojects/a/a.c +test cases/failing/65 subproj different versions/subprojects/a/a.h +test cases/failing/65 subproj different versions/subprojects/a/meson.build +test cases/failing/65 subproj different versions/subprojects/b/b.c +test cases/failing/65 subproj different versions/subprojects/b/b.h +test cases/failing/65 subproj different versions/subprojects/b/meson.build +test cases/failing/65 subproj different versions/subprojects/c/c.h +test cases/failing/65 subproj different versions/subprojects/c/meson.build +test cases/failing/66 wrong boost module/meson.build +test cases/failing/66 wrong boost module/test.json +test cases/failing/67 install_data rename bad size/file1.txt +test cases/failing/67 install_data rename bad size/file2.txt +test cases/failing/67 install_data rename bad size/meson.build +test cases/failing/67 install_data rename bad size/test.json +test cases/failing/68 skip only subdir/meson.build +test cases/failing/68 skip only subdir/test.json +test cases/failing/68 skip only subdir/subdir/meson.build +test cases/failing/69 dual override/meson.build +test cases/failing/69 dual override/overrides.py +test cases/failing/69 dual override/test.json +test cases/failing/7 go to subproject/meson.build +test cases/failing/7 go to subproject/test.json +test cases/failing/7 go to subproject/subprojects/meson.build +test cases/failing/70 override used/meson.build +test cases/failing/70 override used/other.py +test cases/failing/70 override used/something.py +test cases/failing/70 override used/test.json +test cases/failing/71 run_command unclean exit/meson.build +test cases/failing/71 run_command unclean exit/returncode.py +test cases/failing/71 run_command unclean exit/test.json +test cases/failing/72 int literal leading zero/meson.build +test cases/failing/72 int literal leading zero/test.json +test cases/failing/73 configuration immutable/input +test cases/failing/73 configuration immutable/meson.build +test cases/failing/73 configuration immutable/test.json +test cases/failing/74 link with shared module on osx/meson.build +test cases/failing/74 link with shared module on osx/module.c +test cases/failing/74 link with shared module on osx/prog.c +test cases/failing/74 link with shared module on osx/test.json +test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in +test cases/failing/75 non-ascii in ascii encoded configure file/meson.build +test cases/failing/75 non-ascii in ascii encoded configure file/test.json +test cases/failing/76 subproj dependency not-found and required/meson.build +test cases/failing/76 subproj dependency not-found and required/test.json +test cases/failing/77 unfound run/meson.build +test cases/failing/77 unfound run/test.json +test cases/failing/78 framework dependency with version/meson.build +test cases/failing/78 framework dependency with version/test.json +test cases/failing/79 override exe config/foo.c +test cases/failing/79 override exe config/meson.build +test cases/failing/79 override exe config/test.json +test cases/failing/8 recursive/meson.build +test cases/failing/8 recursive/test.json +test cases/failing/8 recursive/subprojects/a/meson.build +test cases/failing/8 recursive/subprojects/b/meson.build +test cases/failing/80 gl dependency with version/meson.build +test cases/failing/80 gl dependency with version/test.json +test cases/failing/81 threads dependency with version/meson.build +test cases/failing/81 threads dependency with version/test.json +test cases/failing/82 gtest dependency with version/meson.build +test cases/failing/82 gtest dependency with version/test.json +test cases/failing/83 dub library/meson.build +test cases/failing/83 dub library/test.json +test cases/failing/84 dub executable/meson.build +test cases/failing/84 dub executable/test.json +test cases/failing/85 dub compiler/meson.build +test cases/failing/85 dub compiler/test.json +test cases/failing/86 subproj not-found dep/meson.build +test cases/failing/86 subproj not-found dep/test.json +test cases/failing/86 subproj not-found dep/subprojects/somesubproj/meson.build +test cases/failing/87 invalid configure file/input +test cases/failing/87 invalid configure file/meson.build +test cases/failing/87 invalid configure file/test.json +test cases/failing/88 kwarg dupe/meson.build +test cases/failing/88 kwarg dupe/prog.c +test cases/failing/88 kwarg dupe/test.json +test cases/failing/89 missing pch file/meson.build +test cases/failing/89 missing pch file/prog.c +test cases/failing/89 missing pch file/test.json +test cases/failing/9 missing extra file/meson.build +test cases/failing/9 missing extra file/prog.c +test cases/failing/9 missing extra file/test.json +test cases/failing/90 pch source different folder/meson.build +test cases/failing/90 pch source different folder/prog.c +test cases/failing/90 pch source different folder/test.json +test cases/failing/90 pch source different folder/include/pch.h +test cases/failing/90 pch source different folder/src/pch.c +test cases/failing/91 unknown config tool/meson.build +test cases/failing/91 unknown config tool/test.json +test cases/failing/92 custom target install data/Info.plist.cpp +test cases/failing/92 custom target install data/meson.build +test cases/failing/92 custom target install data/preproc.py +test cases/failing/92 custom target install data/test.json +test cases/failing/93 add dict non string key/meson.build +test cases/failing/93 add dict non string key/test.json +test cases/failing/94 add dict duplicate keys/meson.build +test cases/failing/94 add dict duplicate keys/test.json +test cases/failing/95 no host get_external_property/meson.build +test cases/failing/95 no host get_external_property/test.json +test cases/failing/96 no native compiler/main.c +test cases/failing/96 no native compiler/meson.build +test cases/failing/96 no native compiler/test.json +test cases/failing/97 subdir parse error/meson.build +test cases/failing/97 subdir parse error/test.json +test cases/failing/97 subdir parse error/subdir/meson.build +test cases/failing/98 invalid option file/meson.build +test cases/failing/98 invalid option file/meson_options.txt +test cases/failing/98 invalid option file/test.json +test cases/failing/99 no lang/main.c +test cases/failing/99 no lang/meson.build +test cases/failing/99 no lang/test.json +test cases/fortran/1 basic/meson.build +test cases/fortran/1 basic/simple.f90 +test cases/fortran/10 find library/gzip.f90 +test cases/fortran/10 find library/main.f90 +test cases/fortran/10 find library/meson.build +test cases/fortran/11 compiles links runs/meson.build +test cases/fortran/12 submodule/a1.f90 +test cases/fortran/12 submodule/a2.f90 +test cases/fortran/12 submodule/a3.f90 +test cases/fortran/12 submodule/child.f90 +test cases/fortran/12 submodule/meson.build +test cases/fortran/12 submodule/parent.f90 +test cases/fortran/13 coarray/main.f90 +test cases/fortran/13 coarray/meson.build +test cases/fortran/14 fortran links c/clib.c +test cases/fortran/14 fortran links c/clib.def +test cases/fortran/14 fortran links c/f_call_c.f90 +test cases/fortran/14 fortran links c/meson.build +test cases/fortran/15 include/inc1.f90 +test cases/fortran/15 include/inc2.f90 +test cases/fortran/15 include/include_hierarchy.f90 +test cases/fortran/15 include/include_syntax.f90 +test cases/fortran/15 include/meson.build +test cases/fortran/15 include/timestwo.f90 +test cases/fortran/15 include/subprojects/cmake_inc/CMakeLists.txt +test cases/fortran/15 include/subprojects/cmake_inc/main.f90 +test cases/fortran/15 include/subprojects/cmake_inc/thousand.f90 +test cases/fortran/16 openmp/main.f90 +test cases/fortran/16 openmp/meson.build +test cases/fortran/17 add_languages/meson.build +test cases/fortran/18 first_arg/main.f90 +test cases/fortran/18 first_arg/meson.build +test cases/fortran/19 fortran_std/legacy.f +test cases/fortran/19 fortran_std/meson.build +test cases/fortran/19 fortran_std/std2003.f90 +test cases/fortran/19 fortran_std/std2008.f90 +test cases/fortran/19 fortran_std/std2018.f90 +test cases/fortran/19 fortran_std/std95.f90 +test cases/fortran/2 modules/comment_mod.f90 +test cases/fortran/2 modules/meson.build +test cases/fortran/2 modules/mymod.F90 +test cases/fortran/2 modules/prog.f90 +test cases/fortran/20 buildtype/main.f90 +test cases/fortran/20 buildtype/meson.build +test cases/fortran/21 install static/main.f90 +test cases/fortran/21 install static/main_lib.f90 +test cases/fortran/21 install static/meson.build +test cases/fortran/21 install static/test.json +test cases/fortran/21 install static/subprojects/static_hello/meson.build +test cases/fortran/21 install static/subprojects/static_hello/static_hello.f90 +test cases/fortran/22 extract_objects/bar.f90 +test cases/fortran/22 extract_objects/foo1.f90 +test cases/fortran/22 extract_objects/foo2.f90 +test cases/fortran/22 extract_objects/meson.build +test cases/fortran/23 preprocess/main.f90 +test cases/fortran/23 preprocess/meson.build +test cases/fortran/3 module procedure/meson.build +test cases/fortran/3 module procedure/use_syntax.f90 +test cases/fortran/4 self dependency/meson.build +test cases/fortran/4 self dependency/selfdep.f90 +test cases/fortran/4 self dependency/src/selfdep_mod.f90 +test cases/fortran/4 self dependency/subprojects/sub1/main.f90 +test cases/fortran/4 self dependency/subprojects/sub1/meson.build +test cases/fortran/5 static/main.f90 +test cases/fortran/5 static/meson.build +test cases/fortran/5 static/static_hello.f90 +test cases/fortran/6 dynamic/dynamic.f90 +test cases/fortran/6 dynamic/main.f90 +test cases/fortran/6 dynamic/meson.build +test cases/fortran/7 generated/meson.build +test cases/fortran/7 generated/mod1.fpp +test cases/fortran/7 generated/mod2.fpp +test cases/fortran/7 generated/mod3.f90 +test cases/fortran/7 generated/prog.f90 +test cases/fortran/8 module names/meson.build +test cases/fortran/8 module names/mod1.f90 +test cases/fortran/8 module names/mod2.f90 +test cases/fortran/8 module names/test.f90 +test cases/fortran/9 cpp/fortran.f +test cases/fortran/9 cpp/main.c +test cases/fortran/9 cpp/main.cpp +test cases/fortran/9 cpp/meson.build +test cases/fpga/1 simple/meson.build +test cases/fpga/1 simple/spin.pcf +test cases/fpga/1 simple/spin.v +test cases/frameworks/1 boost/extralib.cpp +test cases/frameworks/1 boost/linkexe.cc +test cases/frameworks/1 boost/meson.build +test cases/frameworks/1 boost/meson_options.txt +test cases/frameworks/1 boost/nomod.cpp +test cases/frameworks/1 boost/python_module.cpp +test cases/frameworks/1 boost/test.json +test cases/frameworks/1 boost/test_python_module.py +test cases/frameworks/1 boost/unit_test.cpp +test cases/frameworks/1 boost/partial_dep/foo.cpp +test cases/frameworks/1 boost/partial_dep/foo.hpp +test cases/frameworks/1 boost/partial_dep/main.cpp +test cases/frameworks/1 boost/partial_dep/meson.build +test cases/frameworks/10 gtk-doc/foo.c +test cases/frameworks/10 gtk-doc/meson.build +test cases/frameworks/10 gtk-doc/test.json +test cases/frameworks/10 gtk-doc/doc/foobar-docs.sgml +test cases/frameworks/10 gtk-doc/doc/meson.build +test cases/frameworks/10 gtk-doc/doc/version.xml.in +test cases/frameworks/10 gtk-doc/doc/foobar1/baz.jpg +test cases/frameworks/10 gtk-doc/doc/foobar1/baz.png.in +test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml +test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-sections.txt +test cases/frameworks/10 gtk-doc/doc/foobar1/foobar.types +test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build +test cases/frameworks/10 gtk-doc/doc/foobar2/foobar-docs.sgml +test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build +test cases/frameworks/10 gtk-doc/doc/foobar3/foobar-docs.sgml +test cases/frameworks/10 gtk-doc/doc/foobar3/meson.build +test cases/frameworks/10 gtk-doc/doc/foobar4/foobar-docs.sgml +test cases/frameworks/10 gtk-doc/doc/foobar4/meson.build +test cases/frameworks/10 gtk-doc/include/foo-version.h.in +test cases/frameworks/10 gtk-doc/include/foo.h +test cases/frameworks/10 gtk-doc/include/generate-enums-docbook.py +test cases/frameworks/10 gtk-doc/include/meson.build +test cases/frameworks/11 gir subproject/meson.build +test cases/frameworks/11 gir subproject/test.json +test cases/frameworks/11 gir subproject/gir/meson-subsample.c +test cases/frameworks/11 gir subproject/gir/meson-subsample.h +test cases/frameworks/11 gir subproject/gir/meson.build +test cases/frameworks/11 gir subproject/gir/prog.c +test cases/frameworks/11 gir subproject/gir/prog.py +test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.c +test cases/frameworks/11 gir subproject/subprojects/mesongir/meson-sample.h +test cases/frameworks/11 gir subproject/subprojects/mesongir/meson.build +test cases/frameworks/12 multiple gir/meson.build +test cases/frameworks/12 multiple gir/test.json +test cases/frameworks/12 multiple gir/gir/meson-subsample.c +test cases/frameworks/12 multiple gir/gir/meson-subsample.h +test cases/frameworks/12 multiple gir/gir/meson.build +test cases/frameworks/12 multiple gir/gir/prog.c +test cases/frameworks/12 multiple gir/mesongir/meson-sample.c +test cases/frameworks/12 multiple gir/mesongir/meson-sample.h.in +test cases/frameworks/12 multiple gir/mesongir/meson.build +test cases/frameworks/13 yelp/meson.build +test cases/frameworks/13 yelp/test.json +test cases/frameworks/13 yelp/help/LINGUAS +test cases/frameworks/13 yelp/help/meson.build +test cases/frameworks/13 yelp/help/C/index.page +test cases/frameworks/13 yelp/help/C/index2.page +test cases/frameworks/13 yelp/help/C/index3.page +test cases/frameworks/13 yelp/help/C/media/test.txt +test cases/frameworks/13 yelp/help/de/de.po +test cases/frameworks/13 yelp/help/es/es.po +test cases/frameworks/13 yelp/help/es/media/test.txt +test cases/frameworks/14 doxygen/meson.build +test cases/frameworks/14 doxygen/test.json +test cases/frameworks/14 doxygen/doc/Doxyfile.in +test cases/frameworks/14 doxygen/doc/meson.build +test cases/frameworks/14 doxygen/include/comedian.h +test cases/frameworks/14 doxygen/include/spede.h +test cases/frameworks/14 doxygen/src/spede.cpp +test cases/frameworks/15 llvm/meson.build +test cases/frameworks/15 llvm/meson_options.txt +test cases/frameworks/15 llvm/sum.c +test cases/frameworks/15 llvm/test.json +test cases/frameworks/16 sdl2/meson.build +test cases/frameworks/16 sdl2/meson_options.txt +test cases/frameworks/16 sdl2/sdl2prog.c +test cases/frameworks/16 sdl2/test.json +test cases/frameworks/17 mpi/main.c +test cases/frameworks/17 mpi/main.cpp +test cases/frameworks/17 mpi/main.f90 +test cases/frameworks/17 mpi/meson.build +test cases/frameworks/17 mpi/meson_options.txt +test cases/frameworks/17 mpi/test.json +test cases/frameworks/18 vulkan/meson.build +test cases/frameworks/18 vulkan/test.json +test cases/frameworks/18 vulkan/vulkanprog.c +test cases/frameworks/19 pcap/meson.build +test cases/frameworks/19 pcap/pcap_prog.c +test cases/frameworks/19 pcap/test.json +test cases/frameworks/2 gtest/meson.build +test cases/frameworks/2 gtest/test.cc +test cases/frameworks/2 gtest/test.json +test cases/frameworks/2 gtest/test_nomain.cc +test cases/frameworks/20 cups/cups_prog.c +test cases/frameworks/20 cups/meson.build +test cases/frameworks/20 cups/test.json +test cases/frameworks/21 libwmf/libwmf_prog.c +test cases/frameworks/21 libwmf/meson.build +test cases/frameworks/21 libwmf/test.json +test cases/frameworks/22 gir link order/meson-sample.c +test cases/frameworks/22 gir link order/meson-sample.h +test cases/frameworks/22 gir link order/meson.build +test cases/frameworks/22 gir link order/test.json +test cases/frameworks/22 gir link order/fake-gthread/fake-gthread.c +test cases/frameworks/22 gir link order/fake-gthread/fake-gthread.h +test cases/frameworks/22 gir link order/fake-gthread/meson.build +test cases/frameworks/22 gir link order/get-prgname/get-prgname.c +test cases/frameworks/22 gir link order/get-prgname/get-prgname.h +test cases/frameworks/22 gir link order/get-prgname/meson.build +test cases/frameworks/23 hotdoc/meson.build +test cases/frameworks/23 hotdoc/test.json +test cases/frameworks/23 hotdoc/doc/index.md +test cases/frameworks/23 hotdoc/doc/meson.build +test cases/frameworks/23 hotdoc/doc/sitemap.txt +test cases/frameworks/24 libgcrypt/libgcrypt_prog.c +test cases/frameworks/24 libgcrypt/meson.build +test cases/frameworks/24 libgcrypt/test.json +test cases/frameworks/25 hdf5/main.c +test cases/frameworks/25 hdf5/main.cpp +test cases/frameworks/25 hdf5/main.f90 +test cases/frameworks/25 hdf5/meson.build +test cases/frameworks/25 hdf5/meson_options.txt +test cases/frameworks/25 hdf5/test.json +test cases/frameworks/26 netcdf/main.c +test cases/frameworks/26 netcdf/main.cpp +test cases/frameworks/26 netcdf/main.f90 +test cases/frameworks/26 netcdf/meson.build +test cases/frameworks/26 netcdf/test.json +test cases/frameworks/27 gpgme/gpgme_prog.c +test cases/frameworks/27 gpgme/meson.build +test cases/frameworks/27 gpgme/test.json +test cases/frameworks/28 gir link order 2/meson-sample.c +test cases/frameworks/28 gir link order 2/meson-sample.h +test cases/frameworks/28 gir link order 2/meson.build +test cases/frameworks/28 gir link order 2/test.json +test cases/frameworks/28 gir link order 2/samelibname/dummy.c +test cases/frameworks/28 gir link order 2/samelibname/meson.build +test cases/frameworks/29 blocks/main.c +test cases/frameworks/29 blocks/meson.build +test cases/frameworks/29 blocks/test.json +test cases/frameworks/3 gmock/gmocktest.cc +test cases/frameworks/3 gmock/meson.build +test cases/frameworks/3 gmock/test.json +test cases/frameworks/30 scalapack/main.c +test cases/frameworks/30 scalapack/main.f90 +test cases/frameworks/30 scalapack/meson.build +test cases/frameworks/30 scalapack/test.json +test cases/frameworks/30 scalapack/cmake/FindSCALAPACK.cmake +test cases/frameworks/31 curses/main.c +test cases/frameworks/31 curses/meson.build +test cases/frameworks/31 curses/meson_options.txt +test cases/frameworks/31 curses/test.json +test cases/frameworks/32 boost root/meson.build +test cases/frameworks/32 boost root/nativefile.ini.in +test cases/frameworks/32 boost root/boost/include/boost/version.hpp +test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x32-0_1.lib +test cases/frameworks/32 boost root/boost/lib/boost_regex-vc142-mt-gd-x64-0_1.lib +test cases/frameworks/32 boost root/boost/lib/libboost_regex.so.0.1.0 +test cases/frameworks/33 boost split root/meson.build +test cases/frameworks/33 boost split root/nativefile.ini.in +test cases/frameworks/33 boost split root/boost/extra-dir/include/boost/version.hpp +test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x32-0_2.lib +test cases/frameworks/33 boost split root/boost/lib/boost_regex-vc142-mt-gd-x64-0_2.lib +test cases/frameworks/33 boost split root/boost/lib/libboost_regex.so.0.2.0 +test cases/frameworks/34 gir static lib/meson.build +test cases/frameworks/34 gir static lib/test.json +test cases/frameworks/34 gir static lib/statichelper/meson-sample.c +test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in +test cases/frameworks/34 gir static lib/statichelper/meson.build +test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c +test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h +test cases/frameworks/34 gir static lib/subdir/gir/meson.build +test cases/frameworks/34 gir static lib/subdir/gir/prog.c +test cases/frameworks/35 boost symlinks/meson.build +test cases/frameworks/35 boost symlinks/nativefile.ini.in +test cases/frameworks/35 boost symlinks/boost/Cellar/boost-python/0.3.0/lib/boost_python-vc142-mt-gd-x32-0_3.lib +test cases/frameworks/35 boost symlinks/boost/Cellar/boost-python/0.3.0/lib/boost_python-vc142-mt-gd-x64-0_3.lib +test cases/frameworks/35 boost symlinks/boost/Cellar/boost-python/0.3.0/lib/libboost_python.so.0.3.0 +test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/include/boost/version.hpp +test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/lib/boost_regex-vc142-mt-gd-x32-0_3.lib +test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/lib/boost_regex-vc142-mt-gd-x64-0_3.lib +test cases/frameworks/35 boost symlinks/boost/Cellar/boost/0.3.0/lib/libboost_regex.so.0.3.0 +test cases/frameworks/35 boost symlinks/boost/include/boost/version.hpp +test cases/frameworks/35 boost symlinks/boost/lib/boost_python-vc142-mt-gd-x32-0_3.lib +test cases/frameworks/35 boost symlinks/boost/lib/boost_python-vc142-mt-gd-x64-0_3.lib +test cases/frameworks/35 boost symlinks/boost/lib/boost_regex-vc142-mt-gd-x32-0_3.lib +test cases/frameworks/35 boost symlinks/boost/lib/boost_regex-vc142-mt-gd-x64-0_3.lib +test cases/frameworks/35 boost symlinks/boost/lib/libboost_python.so.0.3.0 +test cases/frameworks/35 boost symlinks/boost/lib/libboost_regex.so.0.3.0 +test cases/frameworks/36 gtkdoc cpp/foo-docs.xml +test cases/frameworks/36 gtkdoc cpp/foo.cpp +test cases/frameworks/36 gtkdoc cpp/foo.h +test cases/frameworks/36 gtkdoc cpp/meson.build +test cases/frameworks/36 gtkdoc cpp/test.json +test cases/frameworks/37 gir cpp/foo.cpp +test cases/frameworks/37 gir cpp/foo.h +test cases/frameworks/37 gir cpp/meson.build +test cases/frameworks/37 gir cpp/test.json +test cases/frameworks/4 qt/main.cpp +test cases/frameworks/4 qt/mainWindow.cpp +test cases/frameworks/4 qt/mainWindow.h +test cases/frameworks/4 qt/mainWindow.ui +test cases/frameworks/4 qt/manualinclude.cpp +test cases/frameworks/4 qt/manualinclude.h +test cases/frameworks/4 qt/meson.build +test cases/frameworks/4 qt/meson_options.txt +test cases/frameworks/4 qt/q5core.cpp +test cases/frameworks/4 qt/qt4_lang.qrc +test cases/frameworks/4 qt/qt4core_fr.ts +test cases/frameworks/4 qt/qt4embedded_fr.ts +test cases/frameworks/4 qt/qt5_lang.qrc +test cases/frameworks/4 qt/qt5core_fr.ts +test cases/frameworks/4 qt/qt5embedded_fr.ts +test cases/frameworks/4 qt/qt6_lang.qrc +test cases/frameworks/4 qt/qt6core_fr.ts +test cases/frameworks/4 qt/qt6embedded_fr.ts +test cases/frameworks/4 qt/qtinterface.cpp +test cases/frameworks/4 qt/stuff.qrc +test cases/frameworks/4 qt/stuff2.qrc +test cases/frameworks/4 qt/test.json +test cases/frameworks/4 qt/thing.png +test cases/frameworks/4 qt/thing2.png +test cases/frameworks/4 qt/mocdep/meson.build +test cases/frameworks/4 qt/mocdep/mocdep.h +test cases/frameworks/4 qt/plugin/plugin.cpp +test cases/frameworks/4 qt/plugin/plugin.h +test cases/frameworks/4 qt/plugin/plugin.json +test cases/frameworks/4 qt/pluginInterface/plugin_if.h +test cases/frameworks/4 qt/subfolder/generator.py +test cases/frameworks/4 qt/subfolder/main.cpp +test cases/frameworks/4 qt/subfolder/meson.build +test cases/frameworks/4 qt/subfolder/resources/stuff3.qrc +test cases/frameworks/4 qt/subfolder/resources/stuff4.qrc.in +test cases/frameworks/4 qt/subfolder/resources/thing.png +test cases/frameworks/5 protocol buffers/defs.proto +test cases/frameworks/5 protocol buffers/main.cpp +test cases/frameworks/5 protocol buffers/meson.build +test cases/frameworks/5 protocol buffers/test.json +test cases/frameworks/5 protocol buffers/asubdir/defs.proto +test cases/frameworks/5 protocol buffers/asubdir/main.cpp +test cases/frameworks/5 protocol buffers/asubdir/meson.build +test cases/frameworks/5 protocol buffers/sidedir/meson.build +test cases/frameworks/5 protocol buffers/sidedir/sideprog.cpp +test cases/frameworks/5 protocol buffers/withpath/meson.build +test cases/frameworks/5 protocol buffers/withpath/pathprog.cpp +test cases/frameworks/5 protocol buffers/withpath/com/mesonbuild/simple.proto +test cases/frameworks/5 protocol buffers/withpath/com/mesonbuild/subsite/complex.proto +test cases/frameworks/6 gettext/meson.build +test cases/frameworks/6 gettext/meson_options.txt +test cases/frameworks/6 gettext/test.json +test cases/frameworks/6 gettext/data/meson.build +test cases/frameworks/6 gettext/data/test.desktop.in +test cases/frameworks/6 gettext/data/test2.desktop.in +test cases/frameworks/6 gettext/data/test5.desktop.in.in +test cases/frameworks/6 gettext/data/test6.desktop.in.in +test cases/frameworks/6 gettext/data/data3/meson.build +test cases/frameworks/6 gettext/data/data3/test.desktop.in +test cases/frameworks/6 gettext/data2/meson.build +test cases/frameworks/6 gettext/data2/test.desktop.in +test cases/frameworks/6 gettext/data3/com.mesonbuild.test.intlprog.metainfo.xml +test cases/frameworks/6 gettext/data3/meson.build +test cases/frameworks/6 gettext/data3/metainfo.its +test cases/frameworks/6 gettext/data3/verify.py +test cases/frameworks/6 gettext/generated/desktopgenerator.py +test cases/frameworks/6 gettext/generated/meson.build +test cases/frameworks/6 gettext/generated/something.desktop.in.in +test cases/frameworks/6 gettext/po/LINGUAS +test cases/frameworks/6 gettext/po/POTFILES +test cases/frameworks/6 gettext/po/de.po +test cases/frameworks/6 gettext/po/fi.po +test cases/frameworks/6 gettext/po/intltest.pot +test cases/frameworks/6 gettext/po/meson.build +test cases/frameworks/6 gettext/po/ru.po +test cases/frameworks/6 gettext/src/intlmain.c +test cases/frameworks/6 gettext/src/meson.build +test cases/frameworks/7 gnome/copyfile.py +test cases/frameworks/7 gnome/meson.build +test cases/frameworks/7 gnome/test.json +test cases/frameworks/7 gnome/gdbus/gdbusprog.c +test cases/frameworks/7 gnome/gdbus/meson.build +test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml +test cases/frameworks/7 gnome/genmarshal/main.c.in +test cases/frameworks/7 gnome/genmarshal/marshaller.list +test cases/frameworks/7 gnome/genmarshal/meson.build +test cases/frameworks/7 gnome/gir/copy.py +test cases/frameworks/7 gnome/gir/meson-sample.c +test cases/frameworks/7 gnome/gir/meson-sample.h +test cases/frameworks/7 gnome/gir/meson-sample2.c +test cases/frameworks/7 gnome/gir/meson-sample2.h +test cases/frameworks/7 gnome/gir/meson.build +test cases/frameworks/7 gnome/gir/prog.c +test cases/frameworks/7 gnome/gir/prog.py +test cases/frameworks/7 gnome/gir/dep1/dep1.c +test cases/frameworks/7 gnome/gir/dep1/dep1.h +test cases/frameworks/7 gnome/gir/dep1/meson.build +test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.c +test cases/frameworks/7 gnome/gir/dep1/dep2/dep2.h +test cases/frameworks/7 gnome/gir/dep1/dep2/meson.build +test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c +test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h +test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build +test cases/frameworks/7 gnome/mkenums/enums.c.in +test cases/frameworks/7 gnome/mkenums/enums.h.in +test cases/frameworks/7 gnome/mkenums/enums2.c.in +test cases/frameworks/7 gnome/mkenums/enums2.h.in +test cases/frameworks/7 gnome/mkenums/main.c +test cases/frameworks/7 gnome/mkenums/main4.c +test cases/frameworks/7 gnome/mkenums/main5.c +test cases/frameworks/7 gnome/mkenums/meson-decls.h +test cases/frameworks/7 gnome/mkenums/meson-sample.h +test cases/frameworks/7 gnome/mkenums/meson.build +test cases/frameworks/7 gnome/resources/generated-main.c +test cases/frameworks/7 gnome/resources/generated.gresource.xml +test cases/frameworks/7 gnome/resources/meson.build +test cases/frameworks/7 gnome/resources/myresource.gresource.xml +test cases/frameworks/7 gnome/resources/res3.txt +test cases/frameworks/7 gnome/resources/resources.py +test cases/frameworks/7 gnome/resources/simple-main.c +test cases/frameworks/7 gnome/resources/simple.gresource.xml +test cases/frameworks/7 gnome/resources-data/meson.build +test cases/frameworks/7 gnome/resources-data/res1.txt +test cases/frameworks/7 gnome/resources-data/res3.txt.in +test cases/frameworks/7 gnome/resources-data/subdir/meson.build +test cases/frameworks/7 gnome/resources-data/subdir/res2.txt +test cases/frameworks/7 gnome/resources-data/subdir/res4.txt.in +test cases/frameworks/7 gnome/resources/generated/meson.build +test cases/frameworks/7 gnome/schemas/com.github.meson.gschema.xml +test cases/frameworks/7 gnome/schemas/meson.build +test cases/frameworks/7 gnome/schemas/schemaprog.c +test cases/frameworks/8 flex/lexer.l +test cases/frameworks/8 flex/meson.build +test cases/frameworks/8 flex/parser.y +test cases/frameworks/8 flex/prog.c +test cases/frameworks/8 flex/test.json +test cases/frameworks/8 flex/test.txt +test cases/frameworks/8 flex/testfile +test cases/frameworks/9 wxwidgets/mainwin.h +test cases/frameworks/9 wxwidgets/meson.build +test cases/frameworks/9 wxwidgets/wxprog.cpp +test cases/frameworks/9 wxwidgets/wxstc.cpp +test cases/java/1 basic/meson.build +test cases/java/1 basic/test.json +test cases/java/1 basic/com/mesonbuild/Simple.java +test cases/java/10 resources/meson.build +test cases/java/10 resources/src/meson.build +test cases/java/10 resources/src/com/mesonbuild/Resources.java +test cases/java/10 resources/src/resources/resource1.txt +test cases/java/10 resources/src/resources/subdir/resource2.txt +test cases/java/2 subdir/meson.build +test cases/java/2 subdir/sub/meson.build +test cases/java/2 subdir/sub/com/mesonbuild/Simple.java +test cases/java/2 subdir/sub/com/mesonbuild/TextPrinter.java +test cases/java/3 args/meson.build +test cases/java/3 args/com/mesonbuild/Simple.java +test cases/java/4 inner class/meson.build +test cases/java/4 inner class/com/mesonbuild/Simple.java +test cases/java/5 includedirs/meson.build +test cases/java/5 includedirs/com/mesonbuild/Simple.java +test cases/java/5 includedirs/com/mesonbuild/TextPrinter.java +test cases/java/6 codegen/meson.build +test cases/java/6 codegen/com/mesonbuild/Config.java.in +test cases/java/6 codegen/com/mesonbuild/Simple.java +test cases/java/6 codegen/com/mesonbuild/TextPrinter.java +test cases/java/6 codegen/com/mesonbuild/meson.build +test cases/java/7 linking/meson.build +test cases/java/7 linking/com/mesonbuild/Linking.java +test cases/java/7 linking/sub/meson.build +test cases/java/7 linking/sub/com/mesonbuild/SimpleLib.java +test cases/java/8 codegen custom target/meson.build +test cases/java/8 codegen custom target/com/mesonbuild/Config.java.in +test cases/java/8 codegen custom target/com/mesonbuild/Simple.java +test cases/java/8 codegen custom target/com/mesonbuild/TextPrinter.java +test cases/java/8 codegen custom target/com/mesonbuild/meson.build +test cases/java/9 jni/meson.build +test cases/java/9 jni/lib/com_mesonbuild_JniTest.c +test cases/java/9 jni/lib/meson.build +test cases/java/9 jni/lib/native.c +test cases/java/9 jni/src/meson.build +test cases/java/9 jni/src/com/mesonbuild/Configured.java.in +test cases/java/9 jni/src/com/mesonbuild/JniTest.java +test cases/java/9 jni/src/com/mesonbuild/meson.build +test cases/keyval/1 basic/.config +test cases/keyval/1 basic/meson.build +test cases/keyval/1 basic/test.json +test cases/keyval/2 subdir/.config +test cases/keyval/2 subdir/meson.build +test cases/keyval/2 subdir/dir/meson.build +test cases/keyval/3 load_config files/meson.build +test cases/keyval/3 load_config files/dir/config +test cases/keyval/3 load_config files/dir/meson.build +test cases/keyval/4 load_config builddir/config +test cases/keyval/4 load_config builddir/meson.build +test cases/linuxlike/1 pkg-config/meson.build +test cases/linuxlike/1 pkg-config/prog-checkver.c +test cases/linuxlike/1 pkg-config/prog.c +test cases/linuxlike/1 pkg-config/incdir/myinc.h +test cases/linuxlike/10 large file support/meson.build +test cases/linuxlike/11 runpath rpath ldlibrarypath/lib.c +test cases/linuxlike/11 runpath rpath ldlibrarypath/main.c +test cases/linuxlike/11 runpath rpath ldlibrarypath/meson.build +test cases/linuxlike/11 runpath rpath ldlibrarypath/lib1/meson.build +test cases/linuxlike/11 runpath rpath ldlibrarypath/lib2/meson.build +test cases/linuxlike/12 subprojects in subprojects/main.c +test cases/linuxlike/12 subprojects in subprojects/meson.build +test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.c +test cases/linuxlike/12 subprojects in subprojects/subprojects/a/a.h +test cases/linuxlike/12 subprojects in subprojects/subprojects/a/meson.build +test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.c +test cases/linuxlike/12 subprojects in subprojects/subprojects/b/b.h +test cases/linuxlike/12 subprojects in subprojects/subprojects/b/meson.build +test cases/linuxlike/12 subprojects in subprojects/subprojects/c/c.h +test cases/linuxlike/12 subprojects in subprojects/subprojects/c/meson.build +test cases/linuxlike/13 cmake dependency/meson.build +test cases/linuxlike/13 cmake dependency/prog-checkver.c +test cases/linuxlike/13 cmake dependency/prog.c +test cases/linuxlike/13 cmake dependency/test.json +test cases/linuxlike/13 cmake dependency/testFlagSet.c +test cases/linuxlike/13 cmake dependency/cmake/FindImportedOldStyle.cmake +test cases/linuxlike/13 cmake dependency/cmake/FindImportedTarget.cmake +test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake +test cases/linuxlike/13 cmake dependency/cmake_fake1/cmMesonTestF1Config.cmake +test cases/linuxlike/13 cmake dependency/cmake_fake2/cmMesonTestF2Config.cmake +test cases/linuxlike/13 cmake dependency/cmake_fake3/bin/.gitkeep +test cases/linuxlike/13 cmake dependency/cmake_fake3/lib/cmake/cmMesonTestF3/cmMesonTestF3Config.cmake +test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonTestDep/cmMesonTestDepConfig.cmake +test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfig.cmake +test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonVersionedTestDep/cmMesonVersionedTestDepConfigVersion.cmake +test cases/linuxlike/13 cmake dependency/incdir/myinc.h +test cases/linuxlike/14 static dynamic linkage/main.c +test cases/linuxlike/14 static dynamic linkage/meson.build +test cases/linuxlike/14 static dynamic linkage/verify_static.py +test cases/linuxlike/15 ld binary/meson.build +test cases/linuxlike/2 external library/meson.build +test cases/linuxlike/2 external library/prog.c +test cases/linuxlike/3 linker script/bob.c +test cases/linuxlike/3 linker script/bob.h +test cases/linuxlike/3 linker script/bob.map +test cases/linuxlike/3 linker script/bob.map.in +test cases/linuxlike/3 linker script/copy.py +test cases/linuxlike/3 linker script/meson.build +test cases/linuxlike/3 linker script/prog.c +test cases/linuxlike/3 linker script/sub/foo.map +test cases/linuxlike/3 linker script/sub/meson.build +test cases/linuxlike/4 extdep static lib/lib.c +test cases/linuxlike/4 extdep static lib/meson.build +test cases/linuxlike/4 extdep static lib/prog.c +test cases/linuxlike/5 dependency versions/meson.build +test cases/linuxlike/5 dependency versions/subprojects/fakezlib/meson.build +test cases/linuxlike/5 dependency versions/subprojects/somelib/lib.c +test cases/linuxlike/5 dependency versions/subprojects/somelib/meson.build +test cases/linuxlike/5 dependency versions/subprojects/somelibnover/lib.c +test cases/linuxlike/5 dependency versions/subprojects/somelibnover/meson.build +test cases/linuxlike/5 dependency versions/subprojects/somelibver/lib.c +test cases/linuxlike/5 dependency versions/subprojects/somelibver/meson.build +test cases/linuxlike/6 subdir include order/meson.build +test cases/linuxlike/6 subdir include order/prog.c +test cases/linuxlike/6 subdir include order/subdir/glib.h +test cases/linuxlike/7 library versions/exe.orig.c +test cases/linuxlike/7 library versions/lib.c +test cases/linuxlike/7 library versions/meson.build +test cases/linuxlike/7 library versions/test.json +test cases/linuxlike/8 subproject library install/meson.build +test cases/linuxlike/8 subproject library install/test.json +test cases/linuxlike/8 subproject library install/subprojects/sublib/meson.build +test cases/linuxlike/8 subproject library install/subprojects/sublib/sublib.c +test cases/linuxlike/8 subproject library install/subprojects/sublib/include/subdefs.h +test cases/linuxlike/9 compiler checks with dependencies/meson.build +test cases/nasm/1 configure file/hello.asm +test cases/nasm/1 configure file/meson.build +test cases/nasm/2 asm language/hello.asm +test cases/nasm/2 asm language/meson.build +test cases/nasm/3 nasm only/dummy.asm +test cases/nasm/3 nasm only/dummy.def +test cases/nasm/3 nasm only/meson.build +test cases/native/1 trivial/meson.build +test cases/native/1 trivial/trivial.c +test cases/native/2 global arg/meson.build +test cases/native/2 global arg/prog.c +test cases/native/2 global arg/prog.cc +test cases/native/3 pipeline/input_src.dat +test cases/native/3 pipeline/meson.build +test cases/native/3 pipeline/prog.c +test cases/native/3 pipeline/srcgen.c +test cases/native/3 pipeline/depends/copyrunner.py +test cases/native/3 pipeline/depends/filecopier.c +test cases/native/3 pipeline/depends/libsrc.c.in +test cases/native/3 pipeline/depends/meson.build +test cases/native/3 pipeline/depends/prog.c +test cases/native/3 pipeline/src/input_src.dat +test cases/native/3 pipeline/src/meson.build +test cases/native/3 pipeline/src/prog.c +test cases/native/3 pipeline/src/srcgen.c +test cases/native/4 tryrun/error.c +test cases/native/4 tryrun/meson.build +test cases/native/4 tryrun/no_compile.c +test cases/native/4 tryrun/ok.c +test cases/native/5 install script/file.txt +test cases/native/5 install script/meson.build +test cases/native/5 install script/test.json +test cases/native/5 install script/wrap.py +test cases/native/5 install script/src/exe.c +test cases/native/5 install script/src/meson.build +test cases/native/6 add language/meson.build +test cases/native/6 add language/prog.cc +test cases/native/7 selfbuilt custom/checkarg.cpp +test cases/native/7 selfbuilt custom/data.dat +test cases/native/7 selfbuilt custom/mainprog.cpp +test cases/native/7 selfbuilt custom/meson.build +test cases/native/7 selfbuilt custom/tool.cpp +test cases/native/8 external program shebang parsing/input.txt +test cases/native/8 external program shebang parsing/main.c +test cases/native/8 external program shebang parsing/meson.build +test cases/native/8 external program shebang parsing/script.int.in +test cases/native/9 override with exe/main2.input +test cases/native/9 override with exe/meson.build +test cases/native/9 override with exe/subprojects/sub/foobar.c +test cases/native/9 override with exe/subprojects/sub/meson.build +test cases/objc/1 simple/meson.build +test cases/objc/1 simple/prog.m +test cases/objc/2 nsstring/meson.build +test cases/objc/2 nsstring/stringprog.m +test cases/objc/3 objc args/meson.build +test cases/objc/3 objc args/prog.m +test cases/objc/4 c++ project objc subproject/master.cpp +test cases/objc/4 c++ project objc subproject/meson.build +test cases/objc/4 c++ project objc subproject/subprojects/foo/foo.m +test cases/objc/4 c++ project objc subproject/subprojects/foo/meson.build +test cases/objcpp/1 simple/meson.build +test cases/objcpp/1 simple/prog.mm +test cases/objcpp/2 objc++ args/meson.build +test cases/objcpp/2 objc++ args/prog.mm +test cases/osx/1 basic/main.c +test cases/osx/1 basic/meson.build +test cases/osx/2 library versions/CMakeLists.txt +test cases/osx/2 library versions/exe.orig.c +test cases/osx/2 library versions/lib.c +test cases/osx/2 library versions/meson.build +test cases/osx/2 library versions/require_pkgconfig.py +test cases/osx/2 library versions/test.json +test cases/osx/3 has function xcode8/meson.build +test cases/osx/4 framework/meson.build +test cases/osx/4 framework/prog.c +test cases/osx/4 framework/stat.c +test cases/osx/4 framework/test.json +test cases/osx/4 framework/xcode-frameworks.png +test cases/osx/5 extra frameworks/meson.build +test cases/osx/5 extra frameworks/prog.c +test cases/osx/5 extra frameworks/stat.c +test cases/osx/5 extra frameworks/test.json +test cases/osx/6 multiframework/main.m +test cases/osx/6 multiframework/meson.build +test cases/osx/7 bitcode/libbar.mm +test cases/osx/7 bitcode/libfile.c +test cases/osx/7 bitcode/libfoo.m +test cases/osx/7 bitcode/meson.build +test cases/osx/7 bitcode/vis.h +test cases/osx/8 pie/main.c +test cases/osx/8 pie/meson.build +test cases/osx/9 global variable ar/libfile.c +test cases/osx/9 global variable ar/libfile2.c +test cases/osx/9 global variable ar/meson.build +test cases/osx/9 global variable ar/nativefile.ini +test cases/osx/9 global variable ar/prog.c +test cases/python/1 basic/meson.build +test cases/python/1 basic/prog.py +test cases/python/1 basic/gluon/__init__.py +test cases/python/1 basic/gluon/gluonator.py +test cases/python/1 basic/subdir/meson.build +test cases/python/1 basic/subdir/subprog.py +test cases/python/2 extmodule/blaster.py.in +test cases/python/2 extmodule/meson.build +test cases/python/2 extmodule/meson_options.txt +test cases/python/2 extmodule/test.json +test cases/python/2 extmodule/ext/meson.build +test cases/python/2 extmodule/ext/tachyon_module.c +test cases/python/2 extmodule/ext/nested/meson.build +test cases/python/2 extmodule/ext/wrongdir/meson.build +test cases/python/2 extmodule/subinst/printer.py +test cases/python/2 extmodule/subinst/submod/printer.py +test cases/python/3 cython/cytest.py +test cases/python/3 cython/meson.build +test cases/python/3 cython/libdir/cstorer.pxd +test cases/python/3 cython/libdir/meson.build +test cases/python/3 cython/libdir/storer.c +test cases/python/3 cython/libdir/storer.h +test cases/python/3 cython/libdir/storer.pyx +test cases/python/4 custom target depends extmodule/blaster.py +test cases/python/4 custom target depends extmodule/meson.build +test cases/python/4 custom target depends extmodule/ext/meson.build +test cases/python/4 custom target depends extmodule/ext/tachyon_module.c +test cases/python/4 custom target depends extmodule/ext/lib/meson-tachyonlib.c +test cases/python/4 custom target depends extmodule/ext/lib/meson-tachyonlib.h +test cases/python/4 custom target depends extmodule/ext/lib/meson.build +test cases/python/5 modules kwarg/meson.build +test cases/python/6 failing subproject/meson.build +test cases/python/6 failing subproject/subprojects/bar/meson.build +test cases/python/7 install path/meson.build +test cases/python/7 install path/test.json +test cases/python/7 install path/test.py +test cases/python/7 install path/structured/meson.build +test cases/python/7 install path/structured/one.py +test cases/python/7 install path/structured/two.py +test cases/python/7 install path/structured/alpha/one.py +test cases/python/7 install path/structured/alpha/three.py +test cases/python/7 install path/structured/alpha/two.py +test cases/python/7 install path/structured/beta/one.py +test cases/python/7 install path/target/meson.build +test cases/python/8 different python versions/blaster.py +test cases/python/8 different python versions/meson.build +test cases/python/8 different python versions/meson_options.txt +test cases/python/8 different python versions/test.json +test cases/python/8 different python versions/ext/meson.build +test cases/python/8 different python versions/ext/tachyon_module.c +test cases/python3/1 basic/meson.build +test cases/python3/1 basic/prog.py +test cases/python3/1 basic/gluon/__init__.py +test cases/python3/1 basic/gluon/gluonator.py +test cases/python3/1 basic/subdir/meson.build +test cases/python3/1 basic/subdir/subprog.py +test cases/python3/2 extmodule/blaster.py +test cases/python3/2 extmodule/meson.build +test cases/python3/2 extmodule/ext/meson.build +test cases/python3/2 extmodule/ext/tachyon_module.c +test cases/python3/3 cython/cytest.py +test cases/python3/3 cython/meson.build +test cases/python3/3 cython/libdir/cstorer.pxd +test cases/python3/3 cython/libdir/meson.build +test cases/python3/3 cython/libdir/storer.c +test cases/python3/3 cython/libdir/storer.h +test cases/python3/3 cython/libdir/storer.pyx +test cases/python3/4 custom target depends extmodule/blaster.py +test cases/python3/4 custom target depends extmodule/meson.build +test cases/python3/4 custom target depends extmodule/ext/meson.build +test cases/python3/4 custom target depends extmodule/ext/tachyon_module.c +test cases/python3/4 custom target depends extmodule/ext/lib/meson-tachyonlib.c +test cases/python3/4 custom target depends extmodule/ext/lib/meson-tachyonlib.h +test cases/python3/4 custom target depends extmodule/ext/lib/meson.build +test cases/rewrite/1 basic/addSrc.json +test cases/rewrite/1 basic/addTgt.json +test cases/rewrite/1 basic/info.json +test cases/rewrite/1 basic/meson.build +test cases/rewrite/1 basic/rmSrc.json +test cases/rewrite/1 basic/rmTgt.json +test cases/rewrite/2 subdirs/addSrc.json +test cases/rewrite/2 subdirs/addTgt.json +test cases/rewrite/2 subdirs/info.json +test cases/rewrite/2 subdirs/meson.build +test cases/rewrite/2 subdirs/rmTgt.json +test cases/rewrite/2 subdirs/sub1/meson.build +test cases/rewrite/2 subdirs/sub2/meson.build +test cases/rewrite/3 kwargs/add.json +test cases/rewrite/3 kwargs/defopts_delete.json +test cases/rewrite/3 kwargs/defopts_set.json +test cases/rewrite/3 kwargs/delete.json +test cases/rewrite/3 kwargs/info.json +test cases/rewrite/3 kwargs/meson.build +test cases/rewrite/3 kwargs/remove.json +test cases/rewrite/3 kwargs/remove_regex.json +test cases/rewrite/3 kwargs/set.json +test cases/rewrite/4 same name targets/addSrc.json +test cases/rewrite/4 same name targets/info.json +test cases/rewrite/4 same name targets/meson.build +test cases/rewrite/4 same name targets/sub1/meson.build +test cases/rewrite/5 sorting/meson.build +test cases/rewrite/6 extra_files/addExtraFiles.json +test cases/rewrite/6 extra_files/info.json +test cases/rewrite/6 extra_files/meson.build +test cases/rewrite/6 extra_files/rmExtraFiles.json +test cases/rust/1 basic/clippy.toml +test cases/rust/1 basic/meson.build +test cases/rust/1 basic/prog.rs +test cases/rust/1 basic/test.json +test cases/rust/1 basic/subdir/meson.build +test cases/rust/1 basic/subdir/prog.rs +test cases/rust/10 language stds/2015.rs +test cases/rust/10 language stds/2018.rs +test cases/rust/10 language stds/meson.build +test cases/rust/11 generated main/gen.py +test cases/rust/11 generated main/generated_lib_main.rs +test cases/rust/11 generated main/meson.build +test cases/rust/11 generated main/sub/meson.build +test cases/rust/12 bindgen/meson.build +test cases/rust/12 bindgen/test.json +test cases/rust/12 bindgen/dependencies/clib2.c +test cases/rust/12 bindgen/dependencies/external_dep.h +test cases/rust/12 bindgen/dependencies/internal_dep.h +test cases/rust/12 bindgen/dependencies/internal_main.rs +test cases/rust/12 bindgen/dependencies/meson.build +test cases/rust/12 bindgen/include/other.h +test cases/rust/12 bindgen/src/gen_header.py +test cases/rust/12 bindgen/src/global-project.h +test cases/rust/12 bindgen/src/global.c +test cases/rust/12 bindgen/src/global.rs +test cases/rust/12 bindgen/src/header.h +test cases/rust/12 bindgen/src/main.rs +test cases/rust/12 bindgen/src/main2.rs +test cases/rust/12 bindgen/src/source.c +test cases/rust/12 bindgen/sub/meson.build +test cases/rust/13 external c dependencies/c_accessing_zlib.c +test cases/rust/13 external c dependencies/meson.build +test cases/rust/13 external c dependencies/meson_options.txt +test cases/rust/13 external c dependencies/prog.rs +test cases/rust/13 external c dependencies/test.json +test cases/rust/14 external libm/meson.build +test cases/rust/14 external libm/meson_options.txt +test cases/rust/14 external libm/prog.rs +test cases/rust/14 external libm/rs_math.rs +test cases/rust/14 external libm/test.json +test cases/rust/15 polyglot sharedlib/adder.c +test cases/rust/15 polyglot sharedlib/adder.h +test cases/rust/15 polyglot sharedlib/adder.rs +test cases/rust/15 polyglot sharedlib/addertest.c +test cases/rust/15 polyglot sharedlib/meson.build +test cases/rust/16 internal c dependencies/lib.c +test cases/rust/16 internal c dependencies/lib.h +test cases/rust/16 internal c dependencies/main.rs +test cases/rust/16 internal c dependencies/meson.build +test cases/rust/16 internal c dependencies/test.py +test cases/rust/17 staticlib link staticlib/branch.rs +test cases/rust/17 staticlib link staticlib/leaf.rs +test cases/rust/17 staticlib link staticlib/meson.build +test cases/rust/17 staticlib link staticlib/prog.c +test cases/rust/17 staticlib link staticlib/test.json +test cases/rust/18 proc-macro/meson.build +test cases/rust/18 proc-macro/proc.rs +test cases/rust/18 proc-macro/use.rs +test cases/rust/19 structured sources/gen.py +test cases/rust/19 structured sources/main-gen-copy.rs +test cases/rust/19 structured sources/meson.build +test cases/rust/19 structured sources/no_copy_test.py +test cases/rust/19 structured sources/priv.rs +test cases/rust/19 structured sources/src/foo.rs.in +test cases/rust/19 structured sources/src/main.rs +test cases/rust/19 structured sources/src2/main-unique.rs +test cases/rust/19 structured sources/src2/meson.build +test cases/rust/19 structured sources/src2/foo/mod.rs +test cases/rust/2 sharedlib/meson.build +test cases/rust/2 sharedlib/prog.rs +test cases/rust/2 sharedlib/stuff.rs +test cases/rust/2 sharedlib/test.json +test cases/rust/2 sharedlib/value.c +test cases/rust/20 rust and cpp/lib.cpp +test cases/rust/20 rust and cpp/lib.hpp +test cases/rust/20 rust and cpp/main.rs +test cases/rust/20 rust and cpp/meson.build +test cases/rust/20 rust and cpp/test.json +test cases/rust/3 staticlib/meson.build +test cases/rust/3 staticlib/other.rs +test cases/rust/3 staticlib/prog.rs +test cases/rust/3 staticlib/stuff.rs +test cases/rust/3 staticlib/test.json +test cases/rust/3 staticlib/value.c +test cases/rust/4 polyglot/meson.build +test cases/rust/4 polyglot/prog.c +test cases/rust/4 polyglot/stuff.rs +test cases/rust/4 polyglot/test.json +test cases/rust/5 polyglot static/clib.c +test cases/rust/5 polyglot static/meson.build +test cases/rust/5 polyglot static/overflow_size_checks.py +test cases/rust/5 polyglot static/prog.c +test cases/rust/5 polyglot static/stuff.rs +test cases/rust/5 polyglot static/test.json +test cases/rust/6 named staticlib/meson.build +test cases/rust/6 named staticlib/prog.rs +test cases/rust/6 named staticlib/stuff.rs +test cases/rust/6 named staticlib/test.json +test cases/rust/7 private crate collision/meson.build +test cases/rust/7 private crate collision/prog.rs +test cases/rust/7 private crate collision/rand.rs +test cases/rust/7 private crate collision/test.json +test cases/rust/8 many files/foo.rs +test cases/rust/8 many files/main.rs +test cases/rust/8 many files/meson.build +test cases/rust/9 unit tests/helper.rs +test cases/rust/9 unit tests/meson.build +test cases/rust/9 unit tests/test.rs +test cases/rust/9 unit tests/test2.rs +test cases/rust/9 unit tests/test3.rs +test cases/swift/1 exe/main.swift +test cases/swift/1 exe/meson.build +test cases/swift/2 multifile/libfile.swift +test cases/swift/2 multifile/main.swift +test cases/swift/2 multifile/meson.build +test cases/swift/3 library/meson.build +test cases/swift/3 library/exe/main.swift +test cases/swift/3 library/exe/meson.build +test cases/swift/3 library/lib/datasource.swift +test cases/swift/3 library/lib/meson.build +test cases/swift/3 library/lib/othersource.swift +test cases/swift/4 generate/meson.build +test cases/swift/4 generate/gen/main.swift +test cases/swift/4 generate/gen/meson.build +test cases/swift/4 generate/user/main.swift +test cases/swift/4 generate/user/meson.build +test cases/swift/5 mixed/main.swift +test cases/swift/5 mixed/meson.build +test cases/swift/5 mixed/mylib.c +test cases/swift/5 mixed/mylib.h +test cases/swift/6 modulemap/main.swift +test cases/swift/6 modulemap/meson.build +test cases/swift/6 modulemap/module.modulemap +test cases/swift/6 modulemap/mylib.c +test cases/swift/6 modulemap/mylib.h +test cases/swift/7 modulemap subdir/main.swift +test cases/swift/7 modulemap subdir/meson.build +test cases/swift/7 modulemap subdir/mylib/meson.build +test cases/swift/7 modulemap subdir/mylib/module.modulemap +test cases/swift/7 modulemap subdir/mylib/mylib.c +test cases/swift/7 modulemap subdir/mylib/mylib.h +test cases/unit/1 soname/CMakeLists.txt +test cases/unit/1 soname/main.c +test cases/unit/1 soname/meson.build +test cases/unit/1 soname/versioned.c +test cases/unit/10 build_rpath/meson.build +test cases/unit/10 build_rpath/prog.c +test cases/unit/10 build_rpath/prog.cc +test cases/unit/10 build_rpath/sub/meson.build +test cases/unit/10 build_rpath/sub/stuff.c +test cases/unit/100 custom target name/file.txt.in +test cases/unit/100 custom target name/meson.build +test cases/unit/100 custom target name/subdir/meson.build +test cases/unit/101 relative find program/foo.py +test cases/unit/101 relative find program/meson.build +test cases/unit/101 relative find program/subdir/meson.build +test cases/unit/102 rlib linkage/lib2.rs +test cases/unit/102 rlib linkage/main.rs +test cases/unit/102 rlib linkage/meson.build +test cases/unit/103 python without pkgconfig/meson.build +test cases/unit/104 strip/lib.c +test cases/unit/104 strip/meson.build +test cases/unit/105 debug function/meson.build +test cases/unit/106 pkgconfig relocatable with absolute path/meson.build +test cases/unit/107 subproject symlink/cp.py +test cases/unit/107 subproject symlink/main.c +test cases/unit/107 subproject symlink/meson.build +test cases/unit/107 subproject symlink/symlinked_subproject/meson.build +test cases/unit/107 subproject symlink/symlinked_subproject/src.c +test cases/unit/107 subproject symlink/symlinked_subproject/datadir/datafile +test cases/unit/107 subproject symlink/symlinked_subproject/datadir/meson.build +test cases/unit/108 new subproject on reconfigure/meson.build +test cases/unit/108 new subproject on reconfigure/meson_options.txt +test cases/unit/108 new subproject on reconfigure/subprojects/foo/foo.c +test cases/unit/108 new subproject on reconfigure/subprojects/foo/meson.build +test cases/unit/109 configure same noop/meson.build +test cases/unit/109 configure same noop/meson_options.txt +test cases/unit/11 cross prog/meson.build +test cases/unit/11 cross prog/some_cross_tool.py +test cases/unit/11 cross prog/sometool.py +test cases/unit/110 freeze/freeze.c +test cases/unit/110 freeze/meson.build +test cases/unit/110 replace unencodable xml chars/meson.build +test cases/unit/110 replace unencodable xml chars/script.py +test cases/unit/111 classpath/meson.build +test cases/unit/111 classpath/com/mesonbuild/Simple.java +test cases/unit/112 list build options/meson.build +test cases/unit/112 list build options/meson_options.txt +test cases/unit/113 complex link cases/main.c +test cases/unit/113 complex link cases/meson.build +test cases/unit/113 complex link cases/s1.c +test cases/unit/113 complex link cases/s2.c +test cases/unit/113 complex link cases/s3.c +test cases/unit/114 empty project/expected_mods.json +test cases/unit/114 empty project/meson.build +test cases/unit/115 genvslite/main.cpp +test cases/unit/115 genvslite/meson.build +test cases/unit/117 openssl cmake bug/meson.build +test cases/unit/117 openssl cmake bug/nativefile.ini +test cases/unit/12 promote/meson.build +test cases/unit/12 promote/subprojects/s1/meson.build +test cases/unit/12 promote/subprojects/s1/s1.c +test cases/unit/12 promote/subprojects/s1/subprojects/s3/meson.build +test cases/unit/12 promote/subprojects/s1/subprojects/s3/s3.c +test cases/unit/12 promote/subprojects/s1/subprojects/scommon/meson.build +test cases/unit/12 promote/subprojects/s1/subprojects/scommon/scommon_broken.c +test cases/unit/12 promote/subprojects/s2/meson.build +test cases/unit/12 promote/subprojects/s2/s2.c +test cases/unit/12 promote/subprojects/s2/subprojects/athing.wrap +test cases/unit/12 promote/subprojects/s2/subprojects/scommon/meson.build +test cases/unit/12 promote/subprojects/s2/subprojects/scommon/scommon_ok.c +test cases/unit/13 reconfigure/meson.build +test cases/unit/14 testsetup selection/main.c +test cases/unit/14 testsetup selection/meson.build +test cases/unit/14 testsetup selection/subprojects/bar/bar.c +test cases/unit/14 testsetup selection/subprojects/bar/meson.build +test cases/unit/14 testsetup selection/subprojects/foo/foo.c +test cases/unit/14 testsetup selection/subprojects/foo/meson.build +test cases/unit/15 prebuilt object/cp.py +test cases/unit/15 prebuilt object/main.c +test cases/unit/15 prebuilt object/meson.build +test cases/unit/15 prebuilt object/source.c +test cases/unit/16 prebuilt static/main.c +test cases/unit/16 prebuilt static/meson.build +test cases/unit/16 prebuilt static/libdir/best.c +test cases/unit/16 prebuilt static/libdir/best.h +test cases/unit/16 prebuilt static/libdir/meson.build +test cases/unit/17 prebuilt shared/alexandria.c +test cases/unit/17 prebuilt shared/alexandria.h +test cases/unit/17 prebuilt shared/another_visitor.c +test cases/unit/17 prebuilt shared/meson.build +test cases/unit/17 prebuilt shared/meson_options.txt +test cases/unit/17 prebuilt shared/patron.c +test cases/unit/17 prebuilt shared/rejected.c +test cases/unit/17 prebuilt shared/rejected.h +test cases/unit/17 prebuilt shared/rejected_main.c +test cases/unit/18 pkgconfig static/foo.c +test cases/unit/18 pkgconfig static/foo.pc.in +test cases/unit/18 pkgconfig static/main.c +test cases/unit/18 pkgconfig static/meson.build +test cases/unit/18 pkgconfig static/include/foo.h +test cases/unit/19 array option/meson.build +test cases/unit/19 array option/meson_options.txt +test cases/unit/2 testsetups/buggy.c +test cases/unit/2 testsetups/envcheck.py +test cases/unit/2 testsetups/impl.c +test cases/unit/2 testsetups/impl.h +test cases/unit/2 testsetups/meson.build +test cases/unit/20 subproj dep variables/meson.build +test cases/unit/20 subproj dep variables/subprojects/failingsubproj/meson.build +test cases/unit/20 subproj dep variables/subprojects/nestedsubproj/meson.build +test cases/unit/20 subproj dep variables/subprojects/nestedsubproj/subprojects/subsubproject.wrap +test cases/unit/20 subproj dep variables/subprojects/somesubproj/meson.build +test cases/unit/21 exit status/meson.build +test cases/unit/22 warning location/a.c +test cases/unit/22 warning location/b.c +test cases/unit/22 warning location/conf.in +test cases/unit/22 warning location/main.c +test cases/unit/22 warning location/meson.build +test cases/unit/22 warning location/sub/c.c +test cases/unit/22 warning location/sub/d.c +test cases/unit/22 warning location/sub/meson.build +test cases/unit/22 warning location/sub/sub.c +test cases/unit/23 unfound pkgconfig/meson.build +test cases/unit/23 unfound pkgconfig/some.c +test cases/unit/24 compiler run_command/meson.build +test cases/unit/25 non-permitted kwargs/meson.build +test cases/unit/26 install umask/datafile.cat +test cases/unit/26 install umask/meson.build +test cases/unit/26 install umask/myinstall.py +test cases/unit/26 install umask/prog.1 +test cases/unit/26 install umask/prog.c +test cases/unit/26 install umask/sample.h +test cases/unit/26 install umask/subdir/datafile.dog +test cases/unit/26 install umask/subdir/sayhello +test cases/unit/27 pkgconfig usage/dependee/meson.build +test cases/unit/27 pkgconfig usage/dependee/pkguser.c +test cases/unit/27 pkgconfig usage/dependency/meson.build +test cases/unit/27 pkgconfig usage/dependency/pkgdep.c +test cases/unit/27 pkgconfig usage/dependency/pkgdep.h +test cases/unit/27 pkgconfig usage/dependency/privatelib.c +test cases/unit/28 ndebug if-release/main.c +test cases/unit/28 ndebug if-release/meson.build +test cases/unit/29 guessed linker dependencies/exe/app.c +test cases/unit/29 guessed linker dependencies/exe/meson.build +test cases/unit/29 guessed linker dependencies/lib/lib.c +test cases/unit/29 guessed linker dependencies/lib/meson.build +test cases/unit/29 guessed linker dependencies/lib/meson_options.txt +test cases/unit/3 subproject defaults/meson.build +test cases/unit/3 subproject defaults/meson_options.txt +test cases/unit/3 subproject defaults/subprojects/foob/meson.build +test cases/unit/3 subproject defaults/subprojects/foob/meson_options.txt +test cases/unit/30 shared_mod linking/libfile.c +test cases/unit/30 shared_mod linking/main.c +test cases/unit/30 shared_mod linking/meson.build +test cases/unit/31 forcefallback/meson.build +test cases/unit/31 forcefallback/test_not_zlib.c +test cases/unit/31 forcefallback/subprojects/notzlib/meson.build +test cases/unit/31 forcefallback/subprojects/notzlib/notzlib.c +test cases/unit/31 forcefallback/subprojects/notzlib/notzlib.h +test cases/unit/32 pkgconfig use libraries/app/app.c +test cases/unit/32 pkgconfig use libraries/app/meson.build +test cases/unit/32 pkgconfig use libraries/lib/liba.c +test cases/unit/32 pkgconfig use libraries/lib/libb.c +test cases/unit/32 pkgconfig use libraries/lib/meson.build +test cases/unit/33 cross file overrides always args/meson.build +test cases/unit/33 cross file overrides always args/test.c +test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt +test cases/unit/34 command line/meson.build +test cases/unit/34 command line/meson_options.txt +test cases/unit/34 command line/subprojects/subp/meson.build +test cases/unit/34 command line/subprojects/subp/meson_options.txt +test cases/unit/35 dist script/meson.build +test cases/unit/35 dist script/prog.c +test cases/unit/35 dist script/replacer.py +test cases/unit/35 dist script/subprojects/sub/dist-script.py +test cases/unit/35 dist script/subprojects/sub/meson.build +test cases/unit/35 dist script/subprojects/sub/meson_options.txt +test cases/unit/35 dist script/subprojects/sub/prog.c +test cases/unit/36 exe_wrapper behaviour/broken-cross.txt +test cases/unit/36 exe_wrapper behaviour/meson.build +test cases/unit/36 exe_wrapper behaviour/meson_options.txt +test cases/unit/36 exe_wrapper behaviour/prog.c +test cases/unit/37 mixed command line args/meson.build +test cases/unit/37 mixed command line args/meson_options.txt +test cases/unit/38 pkgconfig format/meson.build +test cases/unit/38 pkgconfig format/somelib.c +test cases/unit/38 pkgconfig format/someret.c +test cases/unit/39 external, internal library rpath/built library/bar.c +test cases/unit/39 external, internal library rpath/built library/foo.py +test cases/unit/39 external, internal library rpath/built library/meson.build +test cases/unit/39 external, internal library rpath/built library/meson_options.txt +test cases/unit/39 external, internal library rpath/built library/prog.c +test cases/unit/39 external, internal library rpath/external library/bar.c +test cases/unit/39 external, internal library rpath/external library/faa.c +test cases/unit/39 external, internal library rpath/external library/foo.c +test cases/unit/39 external, internal library rpath/external library/meson.build +test cases/unit/4 suite selection/failing_test.c +test cases/unit/4 suite selection/meson.build +test cases/unit/4 suite selection/successful_test.c +test cases/unit/4 suite selection/subprojects/subprjfail/failing_test.c +test cases/unit/4 suite selection/subprojects/subprjfail/meson.build +test cases/unit/4 suite selection/subprojects/subprjmix/failing_test.c +test cases/unit/4 suite selection/subprojects/subprjmix/meson.build +test cases/unit/4 suite selection/subprojects/subprjmix/successful_test.c +test cases/unit/4 suite selection/subprojects/subprjsucc/meson.build +test cases/unit/4 suite selection/subprojects/subprjsucc/successful_test.c +test cases/unit/40 featurenew subprojects/meson.build +test cases/unit/40 featurenew subprojects/subprojects/bar/meson.build +test cases/unit/40 featurenew subprojects/subprojects/baz/meson.build +test cases/unit/40 featurenew subprojects/subprojects/foo/meson.build +test cases/unit/41 rpath order/meson.build +test cases/unit/41 rpath order/myexe.c +test cases/unit/41 rpath order/subprojects/sub1/lib.c +test cases/unit/41 rpath order/subprojects/sub1/meson.build +test cases/unit/41 rpath order/subprojects/sub2/lib.c +test cases/unit/41 rpath order/subprojects/sub2/meson.build +test cases/unit/42 dep order/lib1.c +test cases/unit/42 dep order/lib2.c +test cases/unit/42 dep order/meson.build +test cases/unit/42 dep order/myexe.c +test cases/unit/43 promote wrap/meson.build +test cases/unit/43 promote wrap/subprojects/s1/meson.build +test cases/unit/43 promote wrap/subprojects/s1/subprojects/ambiguous/meson.build +test cases/unit/43 promote wrap/subprojects/s2/meson.build +test cases/unit/43 promote wrap/subprojects/s2/subprojects/ambiguous.wrap +test cases/unit/44 vscpp17/main.cpp +test cases/unit/44 vscpp17/meson.build +test cases/unit/45 native dep pkgconfig var/cross_pkgconfig.py +test cases/unit/45 native dep pkgconfig var/meson.build +test cases/unit/45 native dep pkgconfig var/meson_options.txt +test cases/unit/45 native dep pkgconfig var/cross_pkgconfig/dep_tester.pc +test cases/unit/45 native dep pkgconfig var/native_pkgconfig/dep_tester.pc +test cases/unit/46 native file binary/meson.build +test cases/unit/46 native file binary/meson_options.txt +test cases/unit/47 reconfigure/main.c +test cases/unit/47 reconfigure/meson.build +test cases/unit/47 reconfigure/meson_options.txt +test cases/unit/47 reconfigure/subprojects/sub1/meson.build +test cases/unit/48 testsetup default/envcheck.py +test cases/unit/48 testsetup default/meson.build +test cases/unit/49 pkgconfig csharp library/meson.build +test cases/unit/49 pkgconfig csharp library/somelib.cs +test cases/unit/5 compiler detection/compiler wrapper.py +test cases/unit/5 compiler detection/meson.build +test cases/unit/5 compiler detection/trivial.c +test cases/unit/5 compiler detection/trivial.cc +test cases/unit/5 compiler detection/trivial.m +test cases/unit/5 compiler detection/trivial.mm +test cases/unit/50 noncross options/meson.build +test cases/unit/50 noncross options/prog.c +test cases/unit/50 noncross options/ylib.pc +test cases/unit/51 ldflagdedup/bob.c +test cases/unit/51 ldflagdedup/meson.build +test cases/unit/51 ldflagdedup/prog.c +test cases/unit/52 pkgconfig static link order/dummy.c +test cases/unit/52 pkgconfig static link order/meson.build +test cases/unit/53 clang-format/.clang-format +test cases/unit/53 clang-format/header_expected_h +test cases/unit/53 clang-format/header_orig_h +test cases/unit/53 clang-format/meson.build +test cases/unit/53 clang-format/prog_expected_c +test cases/unit/53 clang-format/prog_orig_c +test cases/unit/53 clang-format/dummydir.h/dummy.dat +test cases/unit/54 introspect buildoptions/subprojects/projectBad/meson.build +test cases/unit/54 introspect buildoptions/subprojects/projectBad/meson_options.txt +test cases/unit/55 dedup compiler libs/meson.build +test cases/unit/55 dedup compiler libs/app/app.c +test cases/unit/55 dedup compiler libs/app/meson.build +test cases/unit/55 dedup compiler libs/liba/liba.c +test cases/unit/55 dedup compiler libs/liba/liba.h +test cases/unit/55 dedup compiler libs/liba/meson.build +test cases/unit/55 dedup compiler libs/libb/libb.c +test cases/unit/55 dedup compiler libs/libb/libb.h +test cases/unit/55 dedup compiler libs/libb/meson.build +test cases/unit/56 introspection/cp.py +test cases/unit/56 introspection/meson.build +test cases/unit/56 introspection/meson_options.txt +test cases/unit/56 introspection/t1.cpp +test cases/unit/56 introspection/t2.cpp +test cases/unit/56 introspection/t3.cpp +test cases/unit/56 introspection/sharedlib/meson.build +test cases/unit/56 introspection/sharedlib/shared.cpp +test cases/unit/56 introspection/sharedlib/shared.hpp +test cases/unit/56 introspection/staticlib/meson.build +test cases/unit/56 introspection/staticlib/static.c +test cases/unit/56 introspection/staticlib/static.h +test cases/unit/57 pkg_config_path option/meson.build +test cases/unit/57 pkg_config_path option/build_extra_path/totally_made_up_dep.pc +test cases/unit/57 pkg_config_path option/host_extra_path/totally_made_up_dep.pc +test cases/unit/58 introspect buildoptions/c_compiler.py +test cases/unit/58 introspect buildoptions/main.c +test cases/unit/58 introspect buildoptions/meson.build +test cases/unit/58 introspect buildoptions/meson_options.txt +test cases/unit/58 introspect buildoptions/subprojects/evilFile.txt +test cases/unit/58 introspect buildoptions/subprojects/projectA/meson.build +test cases/unit/58 introspect buildoptions/subprojects/projectA/meson_options.txt +test cases/unit/58 introspect buildoptions/subprojects/projectBad/meson.build +test cases/unit/58 introspect buildoptions/subprojects/projectBad/meson_options.txt +test cases/unit/59 native file override/crossfile +test cases/unit/59 native file override/crossfile2 +test cases/unit/59 native file override/meson.build +test cases/unit/59 native file override/meson_options.txt +test cases/unit/59 native file override/nativefile +test cases/unit/6 std override/meson.build +test cases/unit/6 std override/prog11.cpp +test cases/unit/6 std override/prog98.cpp +test cases/unit/6 std override/progp.cpp +test cases/unit/60 identity cross/build_wrapper.py +test cases/unit/60 identity cross/host_wrapper.py +test cases/unit/60 identity cross/meson.build +test cases/unit/60 identity cross/stuff.h +test cases/unit/61 pkgconfig relative paths/pkgconfig/librelativepath.pc +test cases/unit/62 cmake_prefix_path/meson.build +test cases/unit/62 cmake_prefix_path/prefix/lib/cmake/mesontest/mesontest-config.cmake +test cases/unit/63 cmake parser/meson.build +test cases/unit/63 cmake parser/prefix/lib/cmake/mesontest/mesontest-config.cmake +test cases/unit/64 alias target/main.c +test cases/unit/64 alias target/meson.build +test cases/unit/64 alias target/subdir/meson.build +test cases/unit/65 static archive stripping/app/appA.c +test cases/unit/65 static archive stripping/app/appB.c +test cases/unit/65 static archive stripping/app/meson.build +test cases/unit/65 static archive stripping/lib/libA.c +test cases/unit/65 static archive stripping/lib/libA.h +test cases/unit/65 static archive stripping/lib/libB.c +test cases/unit/65 static archive stripping/lib/libB.h +test cases/unit/65 static archive stripping/lib/meson.build +test cases/unit/66 static link/meson.build +test cases/unit/66 static link/test1.c +test cases/unit/66 static link/test2.c +test cases/unit/66 static link/test3.c +test cases/unit/66 static link/test4.c +test cases/unit/66 static link/test5.c +test cases/unit/66 static link/lib/func1.c +test cases/unit/66 static link/lib/func10.c +test cases/unit/66 static link/lib/func11.c +test cases/unit/66 static link/lib/func12.c +test cases/unit/66 static link/lib/func14.c +test cases/unit/66 static link/lib/func15.c +test cases/unit/66 static link/lib/func16.c +test cases/unit/66 static link/lib/func17.c +test cases/unit/66 static link/lib/func18.c +test cases/unit/66 static link/lib/func19.c +test cases/unit/66 static link/lib/func2.c +test cases/unit/66 static link/lib/func3.c +test cases/unit/66 static link/lib/func4.c +test cases/unit/66 static link/lib/func5.c +test cases/unit/66 static link/lib/func6.c +test cases/unit/66 static link/lib/func7.c +test cases/unit/66 static link/lib/func8.c +test cases/unit/66 static link/lib/func9.c +test cases/unit/66 static link/lib/meson.build +test cases/unit/67 test env value/meson.build +test cases/unit/67 test env value/test.py +test cases/unit/68 clang-tidy/.clang-tidy +test cases/unit/68 clang-tidy/cttest.cpp +test cases/unit/68 clang-tidy/meson.build +test cases/unit/68 clang-tidy/dummydir.h/dummy.dat +test cases/unit/69 cross/crossfile.in +test cases/unit/69 cross/meson.build +test cases/unit/69 cross/meson_options.txt +test cases/unit/7 run installed/meson.build +test cases/unit/7 run installed/prog.c +test cases/unit/7 run installed/foo/foo.c +test cases/unit/7 run installed/foo/meson.build +test cases/unit/70 cross test passed/exewrapper.py +test cases/unit/70 cross test passed/meson.build +test cases/unit/70 cross test passed/meson_options.txt +test cases/unit/70 cross test passed/script.py +test cases/unit/70 cross test passed/src/main.c +test cases/unit/71 summary/meson.build +test cases/unit/71 summary/meson_options.txt +test cases/unit/71 summary/subprojects/sub/meson.build +test cases/unit/71 summary/subprojects/sub2/meson.build +test cases/unit/71 summary/subprojects/sub2/subprojects/subsub/meson.build +test cases/unit/72 wrap file url/meson.build +test cases/unit/72 wrap file url/subprojects/foo-patch.tar.xz +test cases/unit/72 wrap file url/subprojects/foo.tar.xz +test cases/unit/73 dep files/foo.c +test cases/unit/73 dep files/meson.build +test cases/unit/74 pkgconfig prefixes/client/client.c +test cases/unit/74 pkgconfig prefixes/client/meson.build +test cases/unit/74 pkgconfig prefixes/val1/meson.build +test cases/unit/74 pkgconfig prefixes/val1/val1.c +test cases/unit/74 pkgconfig prefixes/val1/val1.h +test cases/unit/74 pkgconfig prefixes/val2/meson.build +test cases/unit/74 pkgconfig prefixes/val2/val2.c +test cases/unit/74 pkgconfig prefixes/val2/val2.h +test cases/unit/75 subdir libdir/meson.build +test cases/unit/75 subdir libdir/subprojects/flub/meson.build +test cases/unit/76 as link whole/bar.c +test cases/unit/76 as link whole/foo.c +test cases/unit/76 as link whole/meson.build +test cases/unit/77 nostdlib/meson.build +test cases/unit/77 nostdlib/prog.c +test cases/unit/77 nostdlib/subprojects/mylibc/libc.c +test cases/unit/77 nostdlib/subprojects/mylibc/meson.build +test cases/unit/77 nostdlib/subprojects/mylibc/stdio.h +test cases/unit/77 nostdlib/subprojects/mylibc/stubstart.s +test cases/unit/78 user options for subproject/.gitignore +test cases/unit/78 user options for subproject/75 user options for subproject/.gitignore +test cases/unit/78 user options for subproject/75 user options for subproject/meson.build +test cases/unit/78 user options for subproject/subprojects/sub/meson.build +test cases/unit/78 user options for subproject/subprojects/sub/meson_options.txt +test cases/unit/79 global-rpath/meson.build +test cases/unit/79 global-rpath/rpathified.cpp +test cases/unit/79 global-rpath/yonder/meson.build +test cases/unit/79 global-rpath/yonder/yonder.cpp +test cases/unit/79 global-rpath/yonder/yonder.h +test cases/unit/8 -L -l order/first.pc +test cases/unit/8 -L -l order/meson.build +test cases/unit/8 -L -l order/prog.c +test cases/unit/8 -L -l order/second.pc +test cases/unit/80 wrap-git/meson.build +test cases/unit/80 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build +test cases/unit/80 wrap-git/subprojects/wrap_git_upstream/main.c +test cases/unit/81 meson version compare/meson.build +test cases/unit/81 meson version compare/subprojects/foo/meson.build +test cases/unit/82 cross only introspect/meson.build +test cases/unit/83 change option choices/meson.build +test cases/unit/83 change option choices/meson_options.1.txt +test cases/unit/83 change option choices/meson_options.2.txt +test cases/unit/84 nested subproject regenerate depends/main.c +test cases/unit/84 nested subproject regenerate depends/meson.build +test cases/unit/84 nested subproject regenerate depends/subprojects/sub1/meson.build +test cases/unit/84 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt +test cases/unit/85 cpp modules/meson.build +test cases/unit/85 cpp modules/gcc/main.cpp +test cases/unit/85 cpp modules/gcc/meson.build +test cases/unit/85 cpp modules/gcc/src0.cxx +test cases/unit/85 cpp modules/gcc/src1.cxx +test cases/unit/85 cpp modules/gcc/src2.cxx +test cases/unit/85 cpp modules/gcc/src3.cxx +test cases/unit/85 cpp modules/gcc/src4.cxx +test cases/unit/85 cpp modules/gcc/src5.cxx +test cases/unit/85 cpp modules/gcc/src6.cxx +test cases/unit/85 cpp modules/gcc/src7.cxx +test cases/unit/85 cpp modules/gcc/src8.cxx +test cases/unit/85 cpp modules/gcc/src9.cxx +test cases/unit/85 cpp modules/vs/main.cpp +test cases/unit/85 cpp modules/vs/meson.build +test cases/unit/85 cpp modules/vs/src0.ixx +test cases/unit/85 cpp modules/vs/src1.ixx +test cases/unit/85 cpp modules/vs/src2.ixx +test cases/unit/85 cpp modules/vs/src3.ixx +test cases/unit/85 cpp modules/vs/src4.ixx +test cases/unit/85 cpp modules/vs/src5.ixx +test cases/unit/85 cpp modules/vs/src6.ixx +test cases/unit/85 cpp modules/vs/src7.ixx +test cases/unit/85 cpp modules/vs/src8.ixx +test cases/unit/85 cpp modules/vs/src9.ixx +test cases/unit/86 prelinking/file1.c +test cases/unit/86 prelinking/file2.c +test cases/unit/86 prelinking/file3.c +test cases/unit/86 prelinking/file4.c +test cases/unit/86 prelinking/main.c +test cases/unit/86 prelinking/meson.build +test cases/unit/86 prelinking/private_header.h +test cases/unit/86 prelinking/public_header.h +test cases/unit/87 run native test/main.c +test cases/unit/87 run native test/meson.build +test cases/unit/88 multiple envvars/meson.build +test cases/unit/88 multiple envvars/prog.c +test cases/unit/88 multiple envvars/prog.cpp +test cases/unit/89 pkgconfig build rpath order/dummy.pc +test cases/unit/89 pkgconfig build rpath order/meson.build +test cases/unit/89 pkgconfig build rpath order/prog.c +test cases/unit/89 pkgconfig build rpath order/prog.cc +test cases/unit/89 pkgconfig build rpath order/sub/meson.build +test cases/unit/89 pkgconfig build rpath order/sub/stuff.c +test cases/unit/9 d dedup/meson.build +test cases/unit/9 d dedup/prog.c +test cases/unit/90 devenv/main.c +test cases/unit/90 devenv/meson.build +test cases/unit/90 devenv/test-devenv.py +test cases/unit/90 devenv/subprojects/sub/foo.c +test cases/unit/90 devenv/subprojects/sub/meson.build +test cases/unit/92 install skip subprojects/foo.c +test cases/unit/92 install skip subprojects/foo.dat +test cases/unit/92 install skip subprojects/foo.h +test cases/unit/92 install skip subprojects/meson.build +test cases/unit/92 install skip subprojects/foo/foofile +test cases/unit/92 install skip subprojects/subprojects/bar/bar.c +test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat +test cases/unit/92 install skip subprojects/subprojects/bar/bar.h +test cases/unit/92 install skip subprojects/subprojects/bar/meson.build +test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile +test cases/unit/93 new subproject in configured project/meson.build +test cases/unit/93 new subproject in configured project/meson_options.txt +test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c +test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build +test cases/unit/94 clangformat/.clang-format +test cases/unit/94 clangformat/.clang-format-ignore +test cases/unit/94 clangformat/.clang-format-include +test cases/unit/94 clangformat/meson.build +test cases/unit/94 clangformat/not-included/badformat.cpp +test cases/unit/94 clangformat/src/badformat.c +test cases/unit/94 clangformat/src/badformat.cpp +test cases/unit/95 custominc/helper.c +test cases/unit/95 custominc/meson.build +test cases/unit/95 custominc/prog.c +test cases/unit/95 custominc/prog2.c +test cases/unit/95 custominc/easytogrepfor/genh.py +test cases/unit/95 custominc/easytogrepfor/meson.build +test cases/unit/96 implicit force fallback/meson.build +test cases/unit/96 implicit force fallback/subprojects/something/meson.build +test cases/unit/97 compiler.links file arg/meson.build +test cases/unit/97 compiler.links file arg/test.c +test cases/unit/98 link full name/.gitignore +test cases/unit/98 link full name/libtestprovider/meson.build +test cases/unit/98 link full name/libtestprovider/provider.c +test cases/unit/98 link full name/proguser/meson.build +test cases/unit/98 link full name/proguser/receiver.c +test cases/unit/99 install all targets/bar-custom.txt +test cases/unit/99 install all targets/bar-devel.h +test cases/unit/99 install all targets/bar-notag.txt +test cases/unit/99 install all targets/foo.in +test cases/unit/99 install all targets/foo1-devel.h +test cases/unit/99 install all targets/lib.c +test cases/unit/99 install all targets/main.c +test cases/unit/99 install all targets/meson.build +test cases/unit/99 install all targets/script.py +test cases/unit/99 install all targets/custom_files/data.txt +test cases/unit/99 install all targets/excludes/excluded.txt +test cases/unit/99 install all targets/excludes/installed.txt +test cases/unit/99 install all targets/excludes/excluded/placeholder.txt +test cases/unit/99 install all targets/subdir/bar2-devel.h +test cases/unit/99 install all targets/subdir/foo2.in +test cases/unit/99 install all targets/subdir/foo3-devel.h +test cases/unit/99 install all targets/subdir/lib.c +test cases/unit/99 install all targets/subdir/main.c +test cases/unit/99 install all targets/subdir/meson.build +test cases/unit/99 install all targets/subdir/script.py +test cases/unit/99 install all targets/subprojects/subproject/aaa.txt +test cases/unit/99 install all targets/subprojects/subproject/bbb.txt +test cases/unit/99 install all targets/subprojects/subproject/meson.build +test cases/vala/1 basic/meson.build +test cases/vala/1 basic/prog.vala +test cases/vala/10 mixed sources/meson.build +test cases/vala/10 mixed sources/c/foo.c +test cases/vala/10 mixed sources/c/meson.build +test cases/vala/10 mixed sources/c/writec.py +test cases/vala/10 mixed sources/vala/bar.vala +test cases/vala/11 generated vapi/main.vala +test cases/vala/11 generated vapi/meson.build +test cases/vala/11 generated vapi/test.json +test cases/vala/11 generated vapi/libbar/bar.c +test cases/vala/11 generated vapi/libbar/bar.h +test cases/vala/11 generated vapi/libbar/meson.build +test cases/vala/11 generated vapi/libfoo/foo.c +test cases/vala/11 generated vapi/libfoo/foo.h +test cases/vala/11 generated vapi/libfoo/foo.metadata +test cases/vala/11 generated vapi/libfoo/meson.build +test cases/vala/12 custom output/bar.vala +test cases/vala/12 custom output/foo.vala +test cases/vala/12 custom output/meson.build +test cases/vala/13 find library/meson.build +test cases/vala/13 find library/test.vala +test cases/vala/14 target glib version and gresources/meson.build +test cases/vala/14 target glib version and gresources/test.vala +test cases/vala/14 target glib version and gresources/gres/meson.build +test cases/vala/14 target glib version and gresources/gres/test-resources.xml +test cases/vala/14 target glib version and gresources/gres/test.ui +test cases/vala/15 static vapi in source tree/meson.build +test cases/vala/15 static vapi in source tree/test.vala +test cases/vala/15 static vapi in source tree/vapi/config.vapi +test cases/vala/16 mixed dependence/app.vala +test cases/vala/16 mixed dependence/meson.build +test cases/vala/16 mixed dependence/mixer-glue.c +test cases/vala/16 mixed dependence/mixer.vala +test cases/vala/17 plain consumer/app.c +test cases/vala/17 plain consumer/badger.vala +test cases/vala/17 plain consumer/meson.build +test cases/vala/18 vapi consumed twice/app.vala +test cases/vala/18 vapi consumed twice/beer.vala +test cases/vala/18 vapi consumed twice/meson.build +test cases/vala/18 vapi consumed twice/person.vala +test cases/vala/19 genie/meson.build +test cases/vala/19 genie/prog.gs +test cases/vala/2 multiple files/class1.vala +test cases/vala/2 multiple files/class2.vala +test cases/vala/2 multiple files/main.vala +test cases/vala/2 multiple files/meson.build +test cases/vala/20 genie multiple mixed sources/c_test_one.c +test cases/vala/20 genie multiple mixed sources/c_test_two.c +test cases/vala/20 genie multiple mixed sources/init.gs +test cases/vala/20 genie multiple mixed sources/meson.build +test cases/vala/20 genie multiple mixed sources/test_one.gs +test cases/vala/20 genie multiple mixed sources/test_two.gs +test cases/vala/20 genie multiple mixed sources/vala_test_one.vala +test cases/vala/20 genie multiple mixed sources/vala_test_two.vala +test cases/vala/21 type module/foo.vala +test cases/vala/21 type module/meson.build +test cases/vala/21 type module/plugin-bar.vala +test cases/vala/21 type module/plugin-module.vala +test cases/vala/21 type module/plugin.vala +test cases/vala/22 same target in directories/Test.vala +test cases/vala/22 same target in directories/meson.build +test cases/vala/22 same target in directories/prog.vala +test cases/vala/22 same target in directories/Subdir/Test.vala +test cases/vala/22 same target in directories/Subdir/Subdir2/Test.vala +test cases/vala/22 same target in directories/Subdir2/Test.vala +test cases/vala/23 thread flags/meson.build +test cases/vala/23 thread flags/prog.vala +test cases/vala/24 export dynamic shared module/app.vala +test cases/vala/24 export dynamic shared module/meson.build +test cases/vala/24 export dynamic shared module/module.vala +test cases/vala/25 extract_all_objects/meson.build +test cases/vala/25 extract_all_objects/prog.vala +test cases/vala/26 vala and asm/meson.build +test cases/vala/26 vala and asm/prog.vala +test cases/vala/26 vala and asm/retval-arm.S +test cases/vala/26 vala and asm/retval-x86.S +test cases/vala/26 vala and asm/retval-x86_64.S +test cases/vala/26 vala and asm/symbol-underscore.h +test cases/vala/3 dep/gioprog.vala +test cases/vala/3 dep/meson.build +test cases/vala/4 config/config.vapi +test cases/vala/4 config/meson-something-else.vapi +test cases/vala/4 config/meson.build +test cases/vala/4 config/prog.vala +test cases/vala/5 target glib/GLib.Thread.vala +test cases/vala/5 target glib/meson.build +test cases/vala/5 target glib/retcode.c +test cases/vala/6 static library/meson.build +test cases/vala/6 static library/mylib.vala +test cases/vala/6 static library/prog.vala +test cases/vala/6 static library/test.json +test cases/vala/7 shared library/meson.build +test cases/vala/7 shared library/test.json +test cases/vala/7 shared library/lib/meson.build +test cases/vala/7 shared library/lib/mylib.vala +test cases/vala/7 shared library/lib/source.py +test cases/vala/7 shared library/prog/meson.build +test cases/vala/7 shared library/prog/prog.vala +test cases/vala/8 generated sources/meson.build +test cases/vala/8 generated sources/test.json +test cases/vala/8 generated sources/dependency-generated/enum-types.c.template +test cases/vala/8 generated sources/dependency-generated/enum-types.h.template +test cases/vala/8 generated sources/dependency-generated/enums.h +test cases/vala/8 generated sources/dependency-generated/lib.vala +test cases/vala/8 generated sources/dependency-generated/main.vala +test cases/vala/8 generated sources/dependency-generated/meson.build +test cases/vala/8 generated sources/dependency-generated/null.c +test cases/vala/8 generated sources/onlygen/maingen.in +test cases/vala/8 generated sources/onlygen/meson.build +test cases/vala/8 generated sources/src/config.vala.in +test cases/vala/8 generated sources/src/copy_file.py +test cases/vala/8 generated sources/src/meson.build +test cases/vala/8 generated sources/src/returncode.in +test cases/vala/8 generated sources/src/test.vala +test cases/vala/8 generated sources/src/write_wrapper.py +test cases/vala/8 generated sources/tools/meson.build +test cases/vala/9 gir/foo.vala +test cases/vala/9 gir/meson.build +test cases/vala/9 gir/test.json +test cases/warning/1 version for string div/meson.build +test cases/warning/1 version for string div/test.json +test cases/warning/1 version for string div/a/b.c +test cases/warning/2 languages missing native/meson.build +test cases/warning/2 languages missing native/test.json +test cases/warning/3 fallback consistency/meson.build +test cases/warning/3 fallback consistency/test.json +test cases/warning/3 fallback consistency/subprojects/sub/meson.build +test cases/warning/4 fallback consistency/meson.build +test cases/warning/4 fallback consistency/test.json +test cases/warning/4 fallback consistency/subprojects/sub/meson.build +test cases/warning/5 fallback consistency/meson.build +test cases/warning/5 fallback consistency/test.json +test cases/warning/5 fallback consistency/subprojects/foo.wrap +test cases/warning/5 fallback consistency/subprojects/foo/meson.build +test cases/warning/6 list add/meson.build +test cases/warning/6 list add/test.json +test cases/warning/7 module without unstable/meson.build +test cases/warning/7 module without unstable/test.json +test cases/warning/8 target with no sources/meson.build +test cases/warning/8 target with no sources/test.json +test cases/warning/9 meson.options/meson.build +test cases/warning/9 meson.options/meson.options +test cases/warning/9 meson.options/test.json +test cases/warning/9 meson.options/subprojects/no-warn/meson.build +test cases/warning/9 meson.options/subprojects/no-warn/meson.options +test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt +test cases/wasm/1 basic/hello.c +test cases/wasm/1 basic/hello.cpp +test cases/wasm/1 basic/hello.html +test cases/wasm/1 basic/meson.build +test cases/wasm/2 threads/meson.build +test cases/wasm/2 threads/threads.c +test cases/wasm/2 threads/threads.cpp +test cases/wasm/3 jslib/meson.build +test cases/wasm/3 jslib/prog.c +test cases/wasm/3 jslib/somefuncs.js +test cases/wayland/1 client/both.c +test cases/wayland/1 client/client.c +test cases/wayland/1 client/local.c +test cases/wayland/1 client/meson.build +test cases/wayland/1 client/server.c +test cases/wayland/1 client/test.xml +test cases/wayland/2 core only/core.c +test cases/wayland/2 core only/meson.build +test cases/windows/1 basic/meson.build +test cases/windows/1 basic/prog.c +test cases/windows/1 basic/test.json +test cases/windows/10 vs module defs generated custom target/meson.build +test cases/windows/10 vs module defs generated custom target/prog.c +test cases/windows/10 vs module defs generated custom target/subdir/make_def.py +test cases/windows/10 vs module defs generated custom target/subdir/meson.build +test cases/windows/10 vs module defs generated custom target/subdir/somedll.c +test cases/windows/11 exe implib/meson.build +test cases/windows/11 exe implib/prog.c +test cases/windows/11 exe implib/test.json +test cases/windows/12 resources with custom targets/meson.build +test cases/windows/12 resources with custom targets/prog.c +test cases/windows/12 resources with custom targets/res/gen-res.py +test cases/windows/12 resources with custom targets/res/meson.build +test cases/windows/12 resources with custom targets/res/myres.rc.in +test cases/windows/12 resources with custom targets/res/myres_static.rc +test cases/windows/12 resources with custom targets/res/resource.h +test cases/windows/12 resources with custom targets/res/sample.ico +test cases/windows/13 test argument extra paths/meson.build +test cases/windows/13 test argument extra paths/exe/main.c +test cases/windows/13 test argument extra paths/exe/meson.build +test cases/windows/13 test argument extra paths/lib/foo.c +test cases/windows/13 test argument extra paths/lib/foo.h +test cases/windows/13 test argument extra paths/lib/meson.build +test cases/windows/13 test argument extra paths/test/meson.build +test cases/windows/13 test argument extra paths/test/test_run_exe.py +test cases/windows/14 resources with custom target depend_files/meson.build +test cases/windows/14 resources with custom target depend_files/prog.c +test cases/windows/14 resources with custom target depend_files/ico/gen-ico.py +test cases/windows/14 resources with custom target depend_files/ico/meson.build +test cases/windows/14 resources with custom target depend_files/ico/sample.ico.in +test cases/windows/14 resources with custom target depend_files/res/meson.build +test cases/windows/14 resources with custom target depend_files/res/myres.rc +test cases/windows/15 resource scripts with duplicate filenames/meson.build +test cases/windows/15 resource scripts with duplicate filenames/rsrc.rc +test cases/windows/15 resource scripts with duplicate filenames/verify.c +test cases/windows/15 resource scripts with duplicate filenames/a/meson.build +test cases/windows/15 resource scripts with duplicate filenames/a/rsrc.rc +test cases/windows/15 resource scripts with duplicate filenames/b/meson.build +test cases/windows/15 resource scripts with duplicate filenames/b/rsrc.rc +test cases/windows/15 resource scripts with duplicate filenames/c/meson.build +test cases/windows/15 resource scripts with duplicate filenames/c/rsrc.rc +test cases/windows/15 resource scripts with duplicate filenames/exe3/meson.build +test cases/windows/15 resource scripts with duplicate filenames/exe3/src_dll/main.c +test cases/windows/15 resource scripts with duplicate filenames/exe3/src_dll/version.rc +test cases/windows/15 resource scripts with duplicate filenames/exe3/src_exe/main.c +test cases/windows/15 resource scripts with duplicate filenames/exe3/src_exe/version.rc +test cases/windows/15 resource scripts with duplicate filenames/exe4/meson.build +test cases/windows/15 resource scripts with duplicate filenames/exe4/src_dll/main.c +test cases/windows/15 resource scripts with duplicate filenames/exe4/src_dll/version.rc +test cases/windows/15 resource scripts with duplicate filenames/exe4/src_exe/main.c +test cases/windows/15 resource scripts with duplicate filenames/exe4/src_exe/version.rc +test cases/windows/16 gui app/console_prog.c +test cases/windows/16 gui app/dummy.c +test cases/windows/16 gui app/gui_app_tester.py +test cases/windows/16 gui app/gui_prog.c +test cases/windows/16 gui app/meson.build +test cases/windows/17 msvc ndebug/main.cpp +test cases/windows/17 msvc ndebug/meson.build +test cases/windows/18 msvc charset/iso-8859-1.c +test cases/windows/18 msvc charset/meson.build +test cases/windows/18 msvc charset/meson_options.txt +test cases/windows/18 msvc charset/utf8.c +test cases/windows/19 msvc cplusplus define/main.cpp +test cases/windows/19 msvc cplusplus define/meson.build +test cases/windows/2 winmain/meson.build +test cases/windows/2 winmain/prog.c +test cases/windows/20 vs install static lib with generated obj deps/both_lib_source.c +test cases/windows/20 vs install static lib with generated obj deps/copyfile.py +test cases/windows/20 vs install static lib with generated obj deps/generated_source.c +test cases/windows/20 vs install static lib with generated obj deps/meson.build +test cases/windows/20 vs install static lib with generated obj deps/static_lib_source.c +test cases/windows/20 vs install static lib with generated obj deps/test.json +test cases/windows/21 masm/hello.masm +test cases/windows/21 masm/meson.build +test cases/windows/3 cpp/meson.build +test cases/windows/3 cpp/prog.cpp +test cases/windows/4 winmaincpp/meson.build +test cases/windows/4 winmaincpp/prog.cpp +test cases/windows/5 resources/meson.build +test cases/windows/5 resources/prog.c +test cases/windows/5 resources/inc/meson.build +test cases/windows/5 resources/inc/resource/resource.h +test cases/windows/5 resources/res/dummy.c +test cases/windows/5 resources/res/meson.build +test cases/windows/5 resources/res/myres.rc +test cases/windows/5 resources/res/sample.ico +test cases/windows/6 vs module defs/meson.build +test cases/windows/6 vs module defs/prog.c +test cases/windows/6 vs module defs/subdir/meson.build +test cases/windows/6 vs module defs/subdir/somedll.c +test cases/windows/6 vs module defs/subdir/somedll.def +test cases/windows/7 dll versioning/copyfile.py +test cases/windows/7 dll versioning/exe.orig.c +test cases/windows/7 dll versioning/lib.c +test cases/windows/7 dll versioning/meson.build +test cases/windows/7 dll versioning/test.json +test cases/windows/8 find program/meson.build +test cases/windows/8 find program/test-script +test cases/windows/8 find program/test-script-ext.py +test cases/windows/9 vs module defs generated/meson.build +test cases/windows/9 vs module defs generated/prog.c +test cases/windows/9 vs module defs generated/subdir/meson.build +test cases/windows/9 vs module defs generated/subdir/somedll.c +test cases/windows/9 vs module defs generated/subdir/somedll.def.in +tools/ac_converter.py +tools/boost_names.py +tools/build_website.py +tools/cmake2meson.py +tools/copy_files.py +tools/dircondenser.py +tools/regenerate_docs.py +tools/run_with_cov.py +unittests/__init__.py +unittests/allplatformstests.py +unittests/baseplatformtests.py +unittests/cargotests.py +unittests/darwintests.py +unittests/datatests.py +unittests/failuretests.py +unittests/helpers.py +unittests/internaltests.py +unittests/linuxcrosstests.py +unittests/linuxliketests.py +unittests/machinefiletests.py +unittests/platformagnostictests.py +unittests/pythontests.py +unittests/rewritetests.py +unittests/subprojectscommandtests.py +unittests/taptests.py +unittests/windowstests.py \ No newline at end of file diff --git a/devtools/meson/meson.egg-info/dependency_links.txt b/devtools/meson/meson.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/devtools/meson/meson.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/devtools/meson/meson.egg-info/entry_points.txt b/devtools/meson/meson.egg-info/entry_points.txt new file mode 100644 index 0000000..4778de1 --- /dev/null +++ b/devtools/meson/meson.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +meson = mesonbuild.mesonmain:main diff --git a/devtools/meson/meson.egg-info/requires.txt b/devtools/meson/meson.egg-info/requires.txt new file mode 100644 index 0000000..655740e --- /dev/null +++ b/devtools/meson/meson.egg-info/requires.txt @@ -0,0 +1,12 @@ + +[ninja] +ninja>=1.8.2 + +[progress] +tqdm + +[typing] +mypy + +[typing:python_version < "3.8"] +typing_extensions diff --git a/devtools/meson/meson.egg-info/top_level.txt b/devtools/meson/meson.egg-info/top_level.txt new file mode 100644 index 0000000..08fc0a0 --- /dev/null +++ b/devtools/meson/meson.egg-info/top_level.txt @@ -0,0 +1 @@ +mesonbuild diff --git a/devtools/meson/meson.py b/devtools/meson/meson.py new file mode 100644 index 0000000..6f3ba2a --- /dev/null +++ b/devtools/meson/meson.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is an entry point for all commands, including scripts. Include the +# strict minimum python modules for performance reasons. +import sys + +# Check python version before importing anything else, we might have an older +# Python that would error on f-string syntax for example. +if sys.version_info < (3, 7): + print('Meson works correctly only with python 3.7+.') + print('You have python {}.'.format(sys.version)) + print('Please update your environment') + sys.exit(1) + +from pathlib import Path + +# If we're run uninstalled, add the script directory to sys.path to ensure that +# we always import the correct mesonbuild modules even if PYTHONPATH is mangled +meson_exe = Path(sys.argv[0]).resolve() +if (meson_exe.parent / 'mesonbuild').is_dir(): + sys.path.insert(0, str(meson_exe.parent)) + +from mesonbuild import mesonmain + +if __name__ == '__main__': + sys.exit(mesonmain.main()) diff --git a/devtools/meson/mesonbuild/__init__.py b/devtools/meson/mesonbuild/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24ea0de3cd10737727732515f4be26e5d91f053e GIT binary patch literal 151 zcmZ?b<>g`kf;}G&r-A6lAOZ#$feZ&AE@lA|DGb33nv8xc8Hzx{2;!H6i&acYYFSKr zeojhpQF2U1j$ur3N_ISm4HPfQ&(A52$xSWJ&x4RjrI|S?G4b)4d6^~g@p=W7w>WHa Q^HWN5Qtdz{e+FU(0GOL6oB#j- literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/_pathlib.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/_pathlib.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fe7cff38f95723b53af0ce34200835e441c2de9 GIT binary patch literal 1792 zcmbVMPj4JG6!-ku+0AY?l%9YCSQVn$sG3zvtCk2=1wl}S)J6(Y(XePTJNE84nHdkZ zC!4K$OGQt703;5{vEP9k2fo8xIdS96iT6Cap{Y<0*qS%b_WS$ud;WYl>=PKj{`K4J z=M6&sz{Pq5z&wCY{|JPUh%kq_xf40|??$fudy&UH=Cck9=6>XJ=dcrXfCfSD~ zch);6XB+2)b&mqYz9Ov0g6D(D$xHm`d-A$8%w_dK#v(7#CopoYo>|Ejt!k z*IbY9-umRuB^_|0!)j?VS%y;0Te**K-n)IPwf)dgoyj_9bbGtx$6Rf1(ChW`UqmR=&UYN^am-xg{FC;H3%e%TRRYi zTtHSCS3IP<;vy_?JQG+PEzW?h;)O&2WSMdbdbF;zQ9LPL3&@{T6(KAMfe!7DsH(^>}ir6EAlleRKD%P2m6kbmD*Mzo9E%6(2dO3n)Aqb(@Z^ zE3TUED)grNc>hbKq_UVcuGEcR;l=h!sS4x(W?%DsW-W}IW+RSm#m4bV^7n%;b|#D; zPv$abTBVaLzd6zDC`KOkjg+~b*mi5FeQ72!+Qk>FS}J_5@8C7zeUYB)Y{7iGiDk2X z;6~2wC}?_dTqXsNj{_J4oI|auHn1VQ5Y7(>BNZAHYg~2*h`L4ouH=a0XuB!1S(o?`>Jm H#od1ZC5HqP literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/arglist.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/arglist.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc85a801c94b07bc439696f083c5598a2b4600de GIT binary patch literal 10223 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/build.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/build.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e41d26c80cc62e96fe6138d5fe64e54337acae80 GIT binary patch literal 108170 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/depfile.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/depfile.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91b8f5b8cb390f2438d7c8b6efea4b66d53836ef GIT binary patch literal 1955 zcmZuyy>A>v6rY*>^!n_aqF_Q~fk8oV3OWG|(kTR#SOKJPAmvb`%UP?<&DvRKy|Hh4(p!->qtL#CU-`9=Wnso-< zJB4oU54wYC4dbawzIQgxDO+0|VS}=$a&1GEH&a!OIcq^a>;dd0>>hphdnPb3c_;?7ScZ>6^^J*1t7_;G^k1=FAkGiQSKk|N!A)?43|EN} zXEL4fG-}UqScUPn1opr$@43uE$xOTR#4dsY?|4qs`t(=8s1^lTvCm9z87I8)^9{B^mZ+ zGAZ?FFV~amgg=-TrG%&6F3P-HKe0ibDV<+LEd3=I8LF-r#B zyLscPT3x_`K74VSR@q*jrZ!2_y@^EjAh*(Vf0~u2o(pMu4kBslvUQHVgjnijun$3+ z9xoA2f9|XS?Cz{x2xn)NT#9F$@C)2}vPB3c>^}1xUV|ZUjXSK^Xfv;GBhCNAXNS9o zAJeup2x?S14r&rYgAzOBb5Q_l2X~ABgf>TF?gMZ=<3oENfTMyB8_{@&NZz;nNC0k^ zO#pA3;I`{8Q2JEr`!`Uw8=#9QUC*!-(8K{nALpQ)b|UvmHqm(_^X+U}HZB#`gTc+P zUM8iDPRpjVWPP2N+wKx-1rgK+u~lLe(1s_aYdzXXwvi+ChImBbEUM3 z!np*x%xCS>+;z{U_Hmj<&DI9pFKTLgS&6Q8RvKHg<#S!F<5{1|z($V?T{O8=)Q!hf zcr*x-gi)968bZSkk!K@x+eyNpO`yH3?;uOA9dOE`VY_1C8OU?r_`2u3-U9NjYdZ%U zBq952XgOqOix6#09JzM0-@nJ2$asg;I(WYmt5>nJdX3lynDqdC8%}GPp_98LUVeD@fKg>v-PvQzi4whc%UvLfO>@(#Zqq)qwwdpbep?<*WtJc()0vq5{V*9Cno4_ zPw|HX=qkbiYUW8@R6CXrPOGtxCzS60%T=RW_@X^*eEp;e+@Mm_1f-UTz4o<>!Qb-f B#I*nb literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/envconfig.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/envconfig.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e8da13b6781477ebcaa5ccaa51000052a387646 GIT binary patch literal 13903 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 Y`RS?2D>Ij7tn$T~iSjqgSEgV2UtNkGSO5S3 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/mconf.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/mconf.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef8806169f10cebfc5ce57da69569f00aaa960e7 GIT binary patch literal 12265 zcmcIqTZ|jmd7c}|;bloKm)eW8lE=66}yBItv9{r-Q3 zmt8Ba3#7}PGv_}4`Okkp=hECH7e*)B&DC=ltBVx!`Ffu7Y2*v_0_QWx z&(-HRZz5l;7df9rzEm%9KG!LC=j-#F&v)j!m3pPSP+w3LC)2LVpYj)v)sLaH=qx#< z_VSjtqSRMJLClHbJx!EE`3<9fT+EA#SU|Zdj-hjV>pEUYOQFhrMh}&?CRCx(2EMH)<&;Q^j4(y^Z6m44iF}M; zsu2oMQ`(43UcYeV1NGC9S_1$n4=@H%MmSrIekU9h&Yf#^oQ7;-QBIT#utvuYW#4&j zaP~4aSllA40JwFmGfu5lv$p)cCoJLg98Wl2({+NiH9bl;Zt&>3Z(-Lg?2Rj(W@!2Su-6Z*(6<^EcUjZrBF`tBAe2kU zq9%n`{kU{mZV)=srbULXXJciI^dKrUgqRf9R9VD;A1ZPcuLqx6f9kq$?p$yA9TCXp z_3h5%*8_3OrabCH-|qz1nI__tQFy)E^u4WGZ#SBoojUj^W(*2Q6g8)o@tAnzDU=7P z&Dt~GZlnWj;9bAd=*SZ4CtI$eK-|q+{u(kNwmMYzHMtmSLuFqb=?BYgf$q56GAq~6u9p;jojOnFtLF^Xrn7862dW1yY24t-e1_X46dLhewx zQQTAUA$4DU6{L6@LIw1rZh-!?0N?dm?$$0Aq1Dbus>^7Mlam3&eZ*=088F+}oBwwc26Z%hlGQa7HO2g=qMQ?E5PKCe~_anr;^s9D4~>2N@X#RQidce z_l;$%3CSA&Qex>|ilwSi&qA!IkgCTq_5^BI#Yv3Kp)Ms(;X98A3*|hQA4T~w@gbB8 zC|A(q!}oOY5%E#f%mJ>HIE@}>#2U&)lnCyRiC;shB+df0=OTkp%bQDN#av~B>zhO` z^hYF_#l!q?5t|e$ZFQt^st-Z!2M~z1Awa08PeCjiRMR$E+O4#_$hGNlE&741?Ti2) z*k+6JSx$4D<~c2dbNkd%2+vjN8ZS;#KgeoTgz<7RRkY_PgV_e_A z0Nf7dxaM3>x_2PXpOdFiSx=$je*=I( zT{QxScnbQ-m6VYrA?r)s#*W=&eH+*v=w7?ycr8q1G6OdKPLzdw?K?JQ^W&ae553Wp zT(1XC7?m2Gjve%GCV&P}$_?->d6vF!bo_>p#F+JB%L(mx6-1@bjJzVsv-*h^5)Eqe zhXWfX#BP*!gDtn?)Qd5BQ=V5rbRFe9--c1qf;g2XePj6w85=vp_bA!KT}&) zi};arT-9=DUsfx~o7#YdUu`^#oWlgrorjbb$xdQeW>V6sAXr!`M4n@vp~d*gvsq!Y z^?+HPN8cj=%PXjR9S@60MIDq$Leyr)4Hh?R>uxiAePUysg&iVq$Tf_Dw9fb}rh^#9 zu^^#02@{5qWPA)GiI7;UjUfa**vSk~E)3yk(fufxpF`aj@f-$oX7EI_5_Tpkos0nb zvdj@?LWnYyNMJ#@OtEFib@Yo-W(18p4sY-;LD*GvZQu!rL=`Qq8tNd+NTZPxF!E?5 z0@K-;Oe86!w)QqO%ZdV3uMJ^29EaVouR*@3B0bcq%CaKT%gUZUgv7y57nxgze0r#R zC~XJpXnI@Sgdm`VHk9>Xt@Y@(nYb6V-i{EULX+m~H2V zxo?A<-%)QDKaW*F>SjSU#~Kk333C-f(1M{0|Cz6=9=;&foK#3CE}rc<*vxBY%= z8v_71{=5C=Hhqle0Hm~Bvd%<9ipgwG&VoQd0Tg&nu<_1fb;1G&G%^|PIk4oc$DcS4 z8`SS&#Q`k7)?_lQ8lZ&RKH!hVI-qFWa$*D~4gnS{s2lW!m_hfm@LDiwr{DErBy58Z zfHRV*?v~q((G~;6NViu@xP{=r z>9{Y!ZZSpb8_E_qTV&n<|FOTI?WMdz+%_~0Py!FA;0o#izSt-6nB9;c0Td5Zi){m- zVjkKuaBlbE%|gGx-wOw&%^EH2^j#cB_GhX1XJ8;s;$&QSsFW@c9$1sEZ5E974P0CNq>j$|DUHleWST?7X z!EdoNWCpYoCY!n+wCOhO#I$NU%b_)7FeUHEhmqkmtd1Qd!FVQDX<4Z%OG>;N0Qf4p z0%rDJbP)0p_+LTu6n=^PX zNoY|XaR@f;!2XfiIfC7L_{f+nKKg#(Pif#jDetvnln%E0q1%b($p{?FHalIRvr^?U~#OF3E@d|)UMLGv4IOp@ZC}gtvF@ z5I?k0&v6SSUxpo6R+qI^4qIpjS%#WcsZ_A_^g9mQa8P+K?gpn$kK<`I1il;*+h=5| zZSMA*(}O1xyA8(LS!>$&g?>mv@nJ)5O#DEi5|SZozL9a{LjLVMHB?8+0pcDvYS*uXp=TMmeUx`~>a9riV+xxHp=dSebzpEOHl*D{ENVLWA7bt#G-LpmY2bEI9X!g| ze7|w>WefxiA;FenE{ZaVOB1EoorzTlA&UO!O&W<2b`u$jz4Mvz@PP#PTk8L~KQcnAW<8#kpQAXNXY{ z9E860#1V!Wqng$#ze>s1DET@ijOHn>vo;0Zh!y@6t%-~(s8x+z8Tt*1jM_=JBmkFS zGM@9RG%4Sqz|!bOSPoqcu{)S=^&(q5EtCkL(AsHewF$&U`LjnqgBTQ_Gjo5TmIy(se=-) zciIkzC>6S4$9b=XLEZo_?st)ibuprch(U}H0YVN7rEqf_DmS(-PzQ?wtym!Jab-lY zDE`r6sSFRnfW@tk%ZOQk`}Wl;ya?ogwj`IDMp7)j>94&0t3UJ>=^q%+MG+ z?~m{-A(T7*1%@Sbmg9gTMR?0&I-7JOKQxG4_``_TFn%J)C=^J1XA|-$n$N!kc?oR^ zeF+i&X$yyyVtz|)upyeP`YGvPx-~=Y<26HTa|pt88y!2QH7EjJ{q5wgk?_zBd1 zjrM>jM1hbhL+B@t_)HhrX@o@iSxT67NZ`;PjhnE}k5CwDfk`4_sLDkw6>kz6FCuI9JWV=EB-^e^r;Pn}!EZ*?-+Bw-98tpt%io@w` z12MlI?BH}*7^XtKJqLUFTNqb7Q1I51@ye(amWP>r6*J7k4@|Wyg!0=LD3%7TU~CMI zPc+#pIH`HgY2aMOiS-#`{r%9lx8k~BaPordAp{0hE37T)cj2bMol7D~7uOc#+gQJ} zDftp5DM}b+1>|5=zy)(etc6M}CrKN|0VKr40$cii7@51S(-9OT+NJSlkksej16w`g z1~!2wze&B=>ddoph}nsS$(lK300ty7c*q_NA!kGW0g}j|?;fR)#Arx#+ux#JKnA^{ z8vLWc(IU&CWt6KVk7f;pWEe_iHXKC){ohLh;Bb3LB%Oy? zfkTcS5JF5$luJ)?L=bRiSYv6yb?%42Xgfu9VLHsTO_t?Zk=<8A1kv}^ZIBtviWHtS zo=lh<<--C*ow>7vk(u@!5mG{s*}dE_JJdmNe?H7XQ8^Nr-qxSAG?A6gRFdqWqqeU@K*hX$iREBwxBIZT8 zjKKEab8Tu^nAB3Q1sv+qN)AKDdxX|wIE?t^txLnX(XznaAaovoMUzh^Un$PE?3@{z z$v&+@aLn&jsMl~F2V%?bYQqYRen-1~iE+CmR)$OwJk#-En&&21PYg?kX8mcn0=SQ} zK>G3C!f-*PZfWmm@<*8KdlP6Ts=NmXhK`Qr}?&VT)H;G9AS#?s;uEFB>$ zmCoqxgaJPgCjNW+=|S~{86(L`?1Djo*=1ZRT|%T4-r>0U;k){OgO`H0nDPU`n^vck zU$}%b$X^v8WTerV<_CfzGXn+0Nlb`iNCqVu+~n-f)iJA5MH$TqD|~O`PeymnG!mXm7k`B%-H$@vFGNM4SW5{%l3;e zZC-hCC-#4W2qq}sD`>ifv4Hk`1U~uu@u(2NsBv^=ts2|H zY>(c!j?H&Q$=kK-zXv_ubN8ZH|Eu8=Cqc?IHvF&k_;0k;!A)R<_^0M2xzH6 zg=`ZF*d#U!<=AG~`S_6h%(IAnP&fxCDJzOFz7JJO=Br3^4kwJ1dzV9Bx6dZNqPa1+ znj=$Z3-s>aoif{*V9iR-orJr!<#5y@Ib$22f$=6zY{0O-ICx{Z)7FSa7JdsMUj7=2EY z2#Ul1v^fSgfqsM2Gv>fUznD<{##&kaI_8n*DS4cd&rouO5;{khS1BQ$jd}e|%CQH_ zzVn33dy| z@vY1a+$h1tlcpoDVKB_cX*>f9=RXoYIXoOKyM$V@eB+ClWI2osPWk-%fFfrUHOmwf zA7*;nEFe-XaDu*jFT{Nuayk*2&dHY%6L~qzk8pG90Jn3fF1S9_WCw8yxN7YpThoYA zBc4I0>lyiNw2(8FN#bzjA;G}zQ`?jyw9c~$Z=k;c7fdI261MrmsEXMUylfw9FSeIx z1nQQl+~V<{SGN3P@C{(_X_JWkgxh8-q`7_+-($;ysQ4-zCM#Fkjy# z9fzxiV=Y!=4tQ>Ja3;QUL=wtv_4$y{!o^cuL&X6LqA@sWW{dhMXg21JMc#0`*^NWS z6Y=*6Y^|gSul!9)o}{FVq+UMSHOlctlqTJaWjcx#B*~np$ly$_3C6_AiiK#rUhVgA z)fktN#$Tsxx>5buT?#qbAYI?X2`p-Pz8ZBU z|A(18DqWI344#+Vp7Sg@7YKebb@S>H3D0+w)Fv}wq&hRKMO=l$!@hT(B)|of$Rk>W zNH$cB#XQM@0`5~95aSeXPotJ3gvmm^lJtgH$F&ssml%&5U$`;3)u(uxZA*%V${rH5FSfI?l)VmJ~Y=u^}?I`GuFBwJ(3> z*~_21vhjRmj@dp+z2ecmEY-HNr0sJt*xD(L_#x~l}HXrOB#%1xQS}wL!cX~ zZt&CF*w{5^BPP}%?_6vjMw$RG4m*6^!ybHb*e9QTaCG?KuzlH^&pP>KHArd{VKPu% zm6ctetgOtJ*|&4Kw1mHZ{NI1x{GUsb^xxDt{7a(psZ@}>d$J@kiOF55C)Z?|>PlCs zDdMTtRPoemns_E^3Gvixx_BmQNj%lA(M#1*cvoYIZn~GLWqR3KR)G%K*l=Q1m@DYVY8Y4n~z?+iPM_8V*#{d4TpbCsQDXFxd%${Xw~dlM9s zy#>mfY@WT1UzVMFuCep%0%#`MZwT5&&@QnOXm7FiF#2VTcLlsxpC?$ERlZ5o=GirN zo!!8k@342l_cl}3q|*C;AQ_kBC}TN}>sx-?b-X3CwH3>6{Q=^ZN=lU27__@AGJ0*t z^Q~^Tq(}Mtw&yz4-G<$#ccOILtM9ZO=I(e=#x@#dgsJN^o_c%&`4j*YeJqL)WH$D+8?pe@lKJxQ+?NUu7mgi;5Z#S~v= zD(S|vgdEd!mIO^=21^~$(((DS{4;ILH9;qgU$LpODK>pXKjAAKmCl*X5{*fa`rJ~W zloujHh?TW@Bv*oyByiJrO+hq4wHv<6_exr%G28Pa&EMdX~oB4a{K836EYJA-R7=C;x{kFV_mO&@D2tu z*R3tvGcCt-g&tU4bFvp}zJ-Uu@DHP~&kCyFhSNeNV?$v2MI$MvIm{_mG_txru zjiY#iB~60fpx5XxfgjmxaeEw8e94#h<&HAMoni86*yYpGP~Khj)kW#a7ei(5a;U`j zis`-=0^1L8X zCWcaGdgw9()qD5q)koE}NQD@pv^Utm*bUqBqHLpOH@52T z!0!*Bn9L?+j1pjL_oLzh%%sg$V%{p}E{~GSYobz0L}_tcu~pUMec(+pYWz(IlZ=&z zOD@hoF3uBqa%@1!%EE?%{cVuFX%v#2#^I%9MV=NlD)|SX2Zi;@V!PqfF^5&>WI7(xHk2T}367MmR_ujU38ek<6Aaj})dH$o+GoM#rXvidPYRYN#~9IntPR zAnz-r1RvrUM>m0Rnd*K~3OAG{Z7^n5A*G?zM2r-6*lsYByRugAG8S{chXmIjXDV zR8;;G)N2OKD4b7{YS5n7^d?1mu zaRP8rP5D59+o6^Ux22BTQb+3~e7%#L6BlWyhARI;aB1NokIYxwl4JO(PI{EVn7E28 zv8D4C(;dL5VZvATrJ=ri-OrA47&{*-EzE{Xd}f#olcR}H3lj$l-qX=497xOHe)`Qr z$)60heVjD<^-Y2n$)#HMesyhmslHf!P+fWu$v0}nn6R?C{6%$Py}oqoezlhWvU>kd z>h~7wE34HzcOQLBQsAelID;b4&i(xQuvFwEkZ8Jk>}VcXylriCZ4Xxy8j!`k>_Bts zj@7fH%qt!#N}~(r+i%+*&(bj3=gVvBQI>9#x98Ql>%ybBUX&ca6=@9@b~Dw6VHf5V zE~#a;9pNs(6D8?Ys-&nwGkQW5N(R48D_@{lQueOTEn=%BF%8Wk6fnw+T?d_fWWYa& z0V28mnjUhxhkuNpN0N|Wp7U}+DMI)1C=0SK&*07%6hjf5LGI!!nCW7WS+Cq{d$Gbn z_i15Kc8uWa46y3QT1R*02oU`z8l-6iw1?2OrUY$@wM`*#!~lw(tNW@j-0FeE{{y~!lY&RF}zU?sEY3v0P8~K9$-pUaJ{|f8opQDHpo9@5?Hit>HX__caDj9<A=)>WLy|rnP<2zdy8a7`NzIGf`RoDp-N_XWQ4dF zrzNO9c$_o7K1%(6y$>bl6mU@5S34PjgSHQGkfS_`F_5~nUQ&1$%ZLnn7dO4`Zk4jU zM1(|-VggQ{gnvlI5*2j%;lyNv3z^C+U zWls7*`Ac{?roqSk680hid$CQPt)q{UgjKxOxURoaPaeqpQ;Y>JSQKNFLNKTvC@eK6 z4UOIRFisldTpp&tlj>w(jnc3-Mrdp){9B)_8Qu)j`ziv!H2mea52dG{!V2l%$^73~ zCe*%{SoVcF%!De-L7lQ#UvBSan1%I20)Z8tDZiZ`=EF>wALS3Ett8&lQJ)BfMZ=gm z0>)oTtI{J0s&fgdQ`ky_>t?Jr7-=%h#3P9{hRy!kQik)fLnt*-}xPqJB1wIh60E7eI*YgrLlTo5Ewz!-*}GW)l1- zsh7s`36f<{5#0oas1RRV^BTRE za+wpbT@OsC;qj~GamY}Hip9~j8OiCusNn6k)Aj>}UkMTef3y5Ya0&*zfJ-nlsJsSE zKU=(Q#%6*dTSk)ru*PN_5o2&=-8E^cX4^Mu-H2S<4Fm*x=AJt+d+lb+Hys zH_PTN#)8?`mTGOj z(g3TRD8+4y!Fm9RC3ZM4Q#45iW6AaJkZX$VNLuvNePE&}iRi}dZUd!py9?25+jV3* z2&eN;P(<1WBHh?TPjWJ|!W{5n+=sKP6^`sSnJ_XKWR_}$mW8o!m}4XEMKVJBZhJ#) zME1o7YuWK>*J;hiEs}LDz1ik4q<$Nw-=!h5W68!20$#r>YOkBSLcBeiI@U2V%ib3# z;*ddyW15vUIHGgvEXp+g^LXm`8K5h0PkGP?*3pyr4LoPWk2ql`{|ci8>EkFOn0_Tn zN7w<`-d%oDO7Jhi$RD5p)D#iMIC&DssxFXI^Hd+l=sL1oAI-m%=P9d4;k7{ZK{8I^ zn4l&^8tK&q^S{Ol_}@_RYbsvzDjIEv#Nd%+tc|uhc_KF;a2)Yg=@4AnjQ~&qa`3sfctPi+L z6c|eC(ffC(1-Ze~Ln>-V1X+HT!D$@8Z~_wN!h{Ht5LoeTa8HP!OZN+*8tVJXV?f@a z0eYVQ7s^Tg9J40J&^gbHErb6Kz!ne~+;Aq&Wxq(=lyzpAXX_PD!2>LlO{`nV3k;u~S z1^)_8H@8ng^z3k2a9jwdvEGX@$9Kxp4S<2E(bWTFy5QE!?2_0iYT;C;LUre=f30&p zUJU|ola-hR0CE{2(TVWHcS`?X#(h}thtgirztMRIlq=8`ja_}FiLBa<&bt5wDu-SS zXJq7c!mqz9ylF>nwLy0R4HaMfI=Jce#T zDo%v};s@!)BPSb_P39sCj4uqxh2sRwOzl31nt<@Rn{YU=g5)sU*Vz)JP=&G<(P3skTM764yV9{UK?~7t>`eQ zdnucNa?=bl<8Zlx4ZW1VeknhxB}7gz_~4EOi$)$?WUM$ojo9YH_yb6s1-@!-Vu>48 zV~d!OWfI>jlI11$p4)VRUzS_|Z9h1@IdG6Xb{(_XbvLZ;O=K&2ec$}KY0d}J=E|Bm zZ(cFatvp=BWBy}veh8qm5IglKxv+eHZKb*poL;#37zwh)<%esJk!${Xer^TGwQa!g3qPK}c~ zch_#+zE`cUtlg+DKd7#*-d(H)*|BX0@uT@5iJ8`J%%=mjf~_d1809i=kSoCVB_sin zRi;4X4&v!lqw9KheG?gOO43DYV}}J(<82DX5pnKKv-Ck6!4-)siLXw=vryt9P7!GW zBMPh_uOpFTA>~PKjW?)ZRFKi<6ha8c5xX2pweYi4e2XF~5In0xRqA6Mi6%tK=a|4- z#FruJSnG}v3@3*gP0~v0KT5cW0F3+>|BMO>yg3E1{HIiqEa(ddMPG5~MhRSmLC6pR zhVskQ0tB(TB0@HB$bBKqB6&Qvj;6~kzITUw?QdvA3V0F8b_Y1i9ub676#=1ufmf*? zGD6<@I#tu-k7UpU{udyWPVyJ@8iBAVzS~0FBFq;uP76Van<}zi$Jj%7@ks6=7k4Z* zoGa3;BD&Myuf19>R?B*vGpVISR-1BW{5_fzxfHq#wS?d6^F|EG3?vT5IRg82fS}@= z4WR+=mnbAaDS}Z&z^ANo3N->(x&T*zU&x^Wk|~rmAi$L;;00P%Ar3$;Wm>#VErM&5 zU(YKAc}AJVlOP;r7YZ1IfLdNXB^MP1b^1+<9{x{QLrGpLor}`=z%an~M|@)73aIhX zllVF1E;wa*V|c!dT9l*%25yZZdaT*8QW?VDQkPJ9fzFe&a(JkwMq~m@t+{+si^?@uwvNGAqcYlEtScz+Pl63;BGukS3*hrCI&| E0P;7;$^ZZW literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/mdist.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/mdist.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59713b8dc76d0a1790a260bf22cb59adcdccf381 GIT binary patch literal 13136 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/mesonlib.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/mesonlib.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9067a9fbd4eacf6958e9a8d93337b194a214158e GIT binary patch literal 410 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 K%^#X&Q~qCJQ7a1o literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/minit.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/minit.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7eb6b1280240915c1d203d66847d9de7da51e82a GIT binary patch literal 6595 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 tfeLJKq(F<^a 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 bk(zt>XJxl%2gd9%MAtU^H)@Y=85#V)&3;0` literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/mparser.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/mparser.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65546839f836ee0e59379abfb08fd21118a5cc43 GIT binary patch literal 30887 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/msubprojects.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/msubprojects.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d25fa27b8abb0801793ee720dfd5e61bb43a0318 GIT binary patch literal 23708 zcmb_^ZEzgNncmLq>?anB1qgy5MNvzN6bXu0O0q4#PGlcY+cVwM)BSe$``vHPePrtYP+7}avKW3)) z=iuh!iBiI|?LAz1_0clhx$9Q*|VtY^ACxlqXy1YFe(DYDTWvYF4hf zYEG{CYF@4*)e&5sR$+a#Ix20XTE+FT>R8lXsX8w8CaM#1-B;bG(kj!MT;E^ak2-0U zZB4Bos2-5}Tx)v$VD;eoq3WUayQ+7sAFdu=zq@+3Jj=I^tlv|;XT4l4uOF=*T|ZVm zwtjE*-u2_vLBt5CI65*wDSS?=&n`$pt=kHht=J0C)E*k&udQgL#SI;M^X3aO}qNAn^ecty>D13 zJ+4lm^u$g3rd54J-KS2fQ*Ya9MxDl6kH-1?)fwbJtY%SC!Sl1~0p!og^9PZCNPPhL zkEjo-52=Tde?&cs{CSnUnwa_UyTptcD;%k}+a15|H#%)^#tw6;?$?)EbG-?dCb&U&k}g2L&i+P?018}1U@M8?${ z+C@5(3Ue=SHeA29((uE=CmQ|}uPnJ6tQF=jcQ)L1&8siFVeuK)>$LmNCT}#_s&m7u zZRk#Cxu(~B?Yc9WFna~{TGw42jy|XB8~qn@7oL8)w(z;jPh1VhFV~mW>MQOgce#Pl zu&c3+y7t`KM%`apt!?U7SlZmcpxxRHG*Vk`wA`?;0wA^9a_gS!VMy7_y5o12I;|y6 zTJJB38zHI3aN{PbmP%CZXF*z6Nc%j<2UiEz6s~DpS)Rc)i)#+oJgy_S7O)(nVeW!n z*<5$qz85AvUxzubv#FO{)zD$G(e}g9_U1ZgV9E6WR4}qodAi~GFQDqRaKzhO#G@vr z+zV6w)&?p}E>teoTdn$H%YEU6YiG)fSh{OrX`p6pd9%F~I(!foQMGfU)@XZJT@f+2VbnR(pA~-in@#)oKIiQ>*=ILZ857Nb=sLOXprx?)4W} zIxXetr59IQ55DNBwHohH?xSDt#dWT=Nf$R8E%oC10ECr|Eqws(-G!f5K$5qz@xMH| z{em1p)!Qrx7a)lVcQE0paO_!G_ITR$J$NfjYj+W=9;USGxjyDWA4Rb~#^hcm$C<=~ zG?9J_@W^TjsFb`f0Aq{+fa!3*0g$+T>G3^arj|QEj$mS;a;dQ-Sa7DiP`S|F zx)x@8i2HtkKMj~UfIjdn`2~O+cK5hXK+fLqM`5u+Nlrnm1sIS6%-FN~LQv$C)%fcXD8K7>{?%+-gcyRN@_cMYj!Do)ANB-2^t%rrI#o@`A3+@Irb5jDcr0A znrp>v>-9v}YJvrR!+sfzOBfDC66ck~1DS1C9tf?*jHS=vwLV9BFLxd+40ycp*vIj} zV-M*>aDsxoR@Y0bjq9$+JFjxS)mf^yyvHi>8$T~xj)6&2ChCtNxdkl!ag<)fF9Hah zF70hDFE?HZGnf+*z?o`eV~&zI+h{L$S`c($#;8Fq%B8FI>uHs2g)+kHaDhW-? zQ7LFzPye9fi((r_CiF@u9P|YJS~Y^YljuTo0#ttwX@k$HCL1RS`C5P@!Zz3G-9w+#HcI;lnv@mfs?>?axPLp}yda#r>mHf)C^1`2}3K%M#btWnTV(rqjK4C>F= zdI6U(wV|PEq4{T#+Y4f9xwYx7&f|$kW|IJHMJp&ou*t)iXb24}2}EDQ4JW;s_!bxn zuGY5_?>O6*FRY}ArRZ8Wt?9%zaAzlt=b2qF7nCM%TFN<)=-O+J{%kj?aHmq!i7(p+ zVKE&@Y$vOE^lrbR!8QXm`FcSAofHST)hQ!{z}8QdFONPDZBexntR zQ)7mXzussAExktIh7d}v&Gk0aSum>5X?7ZIeU&eMjtS=*$`vOXxCQhGGwbzNYOI=x zFlp}s6lHa&1IrlLmRCZOuqLeut6-IIE#WTMAFau7ebGB;;fS73HgzlEP#DOXQTySF zef^NdD}{lz3v0QXAp5rxebz5?Yf&e-jCW*&VY052UO^U!C8)H@M}4JHP(I~>HTl=@ zB*LdG#t`F^JPgi6TK+<1VG|_x0!^&S!e?t7AT@iM06oPI5>KM%&{5!qi>TlgktD=4C;|rxq|6aclB+AMGY=q+qQ-z8|5;`QCibhFOgc>Z%M`OG z{YgBS!%sL<)+%L+sbapAGUebTw)^ssbl_BrY54o#O+D%GGfcw_ER!rOlN_#jTu11m zfNY>=f|3Is36xAgHtbWAB0cu2DM*$BYMQdc&8UNTeh6>C!|<8|uR&Is8h5KBsF90u z_oy;*d36*r=@@F?tBxZ-f_y>pC)9n&7m#D?@H!wj8s&`lp@=v4tNZcp88wTiV{yKs z&LUq@m!)LCdJxdk1CfI7r}qv#5vVf}=O0#&Aipny?ost&~lq+~evZatEW_CG`Yyhoan^`UG-!MY$){Q^+00?0ph_a`rx@ zo|f6WJF4-Fnn#Tz>eJw#p9#}fAmSj2i49>INDTA}#v?Du3q5bdHGLk>^#m(9 zG|*-m;zNW?jlzK9#3F?@bIttD2sKo^QCI;r*G7A+s~9>1UZ=>t+u^d3?a(nC+u0{#z2G=%S&jsAj@~0UC8<867BO&!cVQ`_45|=1}hO9 z!LziV*~uy(g`exfbGS>b$7XGX|84tK`}xG@5^bc?a^AFzbc8j#mZ*S1`U$N&`rO=1 zK@$kW7`fj10uzo%k22x-B7Ux2B}i@o%GMb>(w5bceBkSsec&VK> zQ@dC#ka2n^LztVu!EL*1dvo%hBN&;wn%FAy=}tzasV8=mSaVnyyEeqOvz-ENG=UpA z;KskTAk=|3hokyA)KB~QZu+Jb*L^gq`+ZXvy^namBmL$5!p^7~*)@0sC#3?xum^)f z5hlTYfi_w^nApyAGdq+H29oS{uAA*TYst4P&+g{BDc6r#MbtNz&JiwrZ6`%6Z65n;(CH9Qf|Sm z>-lBlK`TSg@ZbP0!*vGr7rL%Kjl~J>E|+H?lR9NM!tr#ot;&sdnaofvE`&vMQ;S}I z&zcprCd|biRfP-JiXAOF}qc+`@L~TO`V&W zG{hQHacC`o<=5dm7PKb`gh_DgFy(Eu8onmo=zUD?XF{b-|9K=JXQ>coSL>em%Qekq zJ;|iZ3eI9{)14VHtdWg}4lQ{77kHaCK0kUWuQ#|9`gIl;%`){SxSDUfH)>JU0`KGM z(%Bv&9UUUjH_@Q?D3S#DNHJNm9Ec4kN!~Jvyx}oLm~InzG6}IlqoK??P#!1k2|E@r zL(Rq{J;bEHiEe0Ji*W}}kq~cE2fhOoPTeHSCaD^7&Ng%OCJ8d#Z?CxOOc`|JuexO{N!e^poD~v4fvY?s^P*dh z+bx6ASlff4Ri=B1n=h5%e3^fjvA+Z=fN*gAveAI}zQUG^@0Me|0%W1e5H1m}S7ydE zIk5gqOaygjct_=5Q(4eAkidS7G?*CQ4f+dK$GB|F!AOWpTQ}Ll9_$*4(14z&e}v~A zy)X%w7ilLCi8UdZQ=-gD<#8WOL_%TUwIL5Ot?8w8b*tr>LbD<#NK24e^cMiJ;Jd({ z#X;k>Sb(LGf?pSo7%{ADokwLEc~7bO>nzwahCH_0YVgEwZ2EtI$31;yJOZ`g1Ken_EV!v#5c7t0ct$L#!96NXP zY(*$zw!hmnOHMlrq+hN0AP)9jrH$^b!jTNmPmr3O#V%QBRbcDK6AzZ@>&AwD2i5Q3 zILdK&($F8Gk~r8C&Y?_D8dv~%9FKj7%e;t}IRD1ExB||x4Y!a=y#^!!?|~8^K4$3r zJGRPDndsUodk~sF?o+tW@gCRw!30XuxEo=~E(EKrV`0APz*~1C$jr{l{%mj*lLc3~ zzx7eD?)AEV?!@Ye_6dcbccT5miF*553@UXk>d{xJM-z8xT3joT749T<6TdX*wAQz;3@po_YO`Iz#MQ^$Mr)iZ`hbfO~zSU;|fzf6zu*IZnmcSYpk3Vhd2yXZW;2yf_&&k^5IEY<&>;46-KPT z+>Y^=1a82@L|36`2v(vrEB#vjbYGW0U_X(f^}R6I^`? zK!*9bCl)R~S$pz{3zvfZA}{(nk9n=?blQGrZeb>8CY^&Em~`wmx0K=4Mxii#X^0ui zY~79-3nMe#{20wfmV*uMTe6OT7t;+G46-#-H)d-?lTMV_dVrHo*A=e9ZOLBDv^B*$ z%O|*VSSMNzT3z29SdO%EXm_C=^lON2-uIV-Hd(%F!^Y|@hm`n*f#nzy?y?+MpqcEv zrgRI^vtUYE>A%g)5hxnW{~5_3v+0k?S|@A|vNjr)O73WE5saNCUNl z>Dk%FN*g=OvmGcydiF*~uQ7bZ1F0?IHya$-v!cCML%Y!i8I9;KVBiBQ`~SOYkt0=B z?bq3as0Ozqs{%P$uiO8Ps*#eDwWvH7WGRQ1ao+%k>%BKbWL!YuY=?0}65}M(l-1N) zMT=k#NDjxjt$&l?{R1R}s1|0t%_RoA>{Vx`2Ej%6iGqCqA}Cq_oQyq@q&5#-?C#ru z*{}Z#1N?XQ0IaDW?gjS1ZGh!|^wcfT9=S8Ld?6ONT>qFTeu|kMwm|$Oz4Vd_Leu8h zwY=}Zl+Nn6;1~jui)8|bk?{yN3(ZjwlCeyRWOR{TG6sVA+JIeB0>O;$O!)imXqS8^ zvP(*;XP1=V4xqjW7Ki={&B>kpif#z%a3+^Wj`ottflY2><4cEK$NLlDN=X&ueOO9c z#GNT_m#Q%`>74_+iS0Cq`z6T8>9stZ3NJ;_J|=IL0PR7v9JvfwM)<*u55+_+CGm(N zNc)zSILk0|X!|`87VLjqjdddl-A&=iHzT;PZHp%L{E_ z#DOE~ST~Db4)dK{5nKcOs}UX~^+p6g*?dXeEAXRVb$nnXMqB#%Fap~xYxY}7{Whrz z*SFBm-5l9=z76-)&XMT;$u72MrRMKPHU9~oVq9^}a&&(rdLHg+DSF<`qnH1IXF{Ld zJUHhGW8ou^1T04X6>x>vl8>x?IJ4?yJcI=eUwMO$`bzM~&uMxaF`Y!bWRRsbG|RhV zBD>~0=)pL2=puOb%F|^J(VvawhN~)Oi_dq1%!=#tr7+#mjTIPS6?u8C4$E2@6M__ZG0MxjvtEX=0Cz)>1KhI`4jL3- z+$}CLuifR)p@u7a;KAwtCz!@n1(#uvot=f1+gRQTaxZ<}SP|PMrXsbBNSsx@gJlZt zy&qk8XIJ5^^Uj_=CmHU8!dH3LK!5ghFl{RN^_94exo0PMWgT8Y;L=CD7WyBe zvzeoNJtnW9RJL`(wEGI|Ekt9o#Anj?rci&>f0c>H96r!vAuSAC#uV@@s7%6xWC~s5*T5qtyV3vxf;rt*1yGC-(^C*K#Qy$ z@G9z?EEV16ALA|*lw>e(HE(8+_xc-nR4vFnLr370F&t>ci!!$r*!lh-k5EScGTNZO zXWB~J#^Xb^NIX8sQ`0EQe-=3h9--;T4xufQ6%SE*pllLvOtGFliL0?#ShHvyb|!2) zBAeV2!OjEePZHadhUasX$e*$TCz9* zQuBy5-dr>>zG2$5802SXd&(WXC)n!Sg#Y|HqL0jy{wjL8y~jiUQ#`uK*`sG5f$;=W zk#^IER!}Ggx#va@t?@cug0v8m44jg#1o(NBjkvrDH5+(&pzfnaN~IXu)4mjyLYWs? zBIPQxmed+g(tGPiWka>0qZk`FVst*D^X%1?DqKIU7Gs5$ZYcd508Hq40X_vG3}Seg zf*S!*=y~HyqRvY1daETw73O6Y5s`^@OgIRGi?72dIKk#5ksYyIG&!p)U*X)*tC@iM zU2vxCL$Gb9tk`1|SB&S6rcxR|nLpC<;QaYE0?ROG;-^loz%%_~a+@(8Fp!{oVdoe# z`!KgpFw-z~RT}x{{S;;n9wnJ+_|;^lr%{?=slw*W3iY<=iEO^)=cC#4uDA6s0SY1x zT}!hK-(AO^18GtJ9v%R3{so`gvl^ip@l@&p3Jov%m%RHvlOHho10)FgdzSbA3Q1_y z!XzxL>S(mX!d-$}=d?%80O*%FsS|jWlX?h*MndM~PTxXIs2$HNF_W_^GfM*(qys|~ zBOlttQ%QthiSCUj@X2}9L7_=g4?{_&nJr-Bw*57EFQ-zN;RV#l@3QoIRLXg8qI5(` z|6Ej>LFpG!T9DFDMx|MlQu7>@(ho+ZiM6c$E=mzfvZrUWVFv94aObeCmjqmv{>dQB z`X_w4Q$&gp@HzC1!hDc>mXY$@P?K%5xu6)yeV@BoknxTLW+thK{Bz8ZrjIu`E0r$F z`GDRwSKr%OzR~bkvArPMY-PS5Ox*fHkEVFC0nYyx8y94`z`MREOEo-f8W_Y8Up@`b z(BVl4{nuFadrbZ{lYh@A<2?$3d&|U1N2GZ>nIH)Jw}?ITfpKGrOg|5{492|oXBX@V zVd%l=5X+14DTyXxzxM0M4BKy*dvZ8?E$N*i1RXMCQsCO3d=>Ldh zK?pg>U5ujmsWCyTlJy7e(xEUnQ`)Or$kP0fZNy8X{}Z#KU7Y0|8KzlBSwb=WD=ZUn zGPoTh)lcw|BxI4ofPb4SF@+q&G8m%+@#@$Vn*#FuSUh&M6lIgb>N~XhC=;Rhk z9-@ecqz?3T$Oqb>Wz3>+_JR5pHtb2=pf;fw*dV>_^sic=YdD&?pNAFj5qkrdAHooJ z&3+za4XjM-RV#KKp>^!q1-VPnW|x`k$UW5C+wJXyVcSkr{vanbLv1YD#+w!M|rV$T+If);arX=l8PRWvJ#$VW#)XtBOLpM@3&OSo2}^ZEfmAM7{h z;m94S!*a)xgks!!^RU5sGXN`R%k>wq1Bg8-g)lOafTB(Wm5b4DDWHD4 z)1D1n-NCLZ%sA{3VJEBn`R&SkRyjz?%8QKxf_xsJ%*{;fB}ieILVSA&@*mjd>(|o7m3J3y+aBv zMlM}5r7!!2A;S5!lZD76Bh2ZK<2VOIu!T+dodRNTz&H)k$y<(cAY{K9y*WDcX3%>R z=rjB#7%ZGZugY6v%~JGMa_by|Y00w3!8WYB;D_!yI}_Nx3xAQTr~(c( z$A~A1`ZESg8XggZEE%IekEXn>b#@=7agQd#%%`tP^)LlO$3ft1pBq$1djk^y!or3* ze=G1+_xJTbqjgE8q2m7B4i!ghzyaJ&ETuMhD()xbDNT$IJOu``1LL_Q#&QX|TJMf! zHhx)of}kK6_RO23r9459c5IPjxJ%~k5&}JV=rjr?LS4q`lSe_$*+C)VPy#?uIyrni z?_|ue02+>&MaqY<$(z_{;W0BtY=Q&vP6VFVx-`sna|)1%D4Ts1?57Za`gj9LAv}AJRL@H+tqkEIFjKReZKp9Ov74b^ zBOVeZN36+y0|VT{gso;$-v<(Q^nHFxVfPsXXmr@5Zh?%kaSDbA%Lqi8ib5fyDCH)+ z{@zPc2h0ucVM7#kM~(kea%dOqX#J6kzDPfER~wShIjTNA5CB?9#Ii<16qEcPifNI&HA><^hCO zPD8&=qdemu1Uo;ZMt8xowgDl=N~_9@6?+6SV$sU|yLJwDY)g#G6|$zaX(YZ01@x zg=71w-(_vR;dvNB;G8}UziQ@c{W=F^Jit)KGKSlEVOHFswa(hDKGR1?M2|9&vrEE( zg_mDo*&fwO)Gbl4{~n+IE)&t5{yXo;?Dd~8VGOuo*K(Fq4A}q5vZt6_K@vJEtfYed(|xb!{+cTBw|bMaJB>?`qJPqAJP8@O*~2lGKU)~b_K9t2aL97 zB2dXA`{dQ6jP{046v`fA1?knEeeV zA(KC1@;{mUFD9Ig0rgkr>OPjejD#S141}VKH~P0rxrt;kKj{=t6{kwcQnEN&OqKGb zvB~jLwv;WpMF%Bg#e?{b7AJ~NPNt=;-~bLs$u>r%ce3O%zj2{^=ShBqeuj@fP#h5z z#TLGd8*nEHub`jsjU?49?{c~k{VuP{SS$t6gac;dYYCQC0=SCU! z+ZMQxMisYJjvo?a25z6aiUam;`GLxZK3sWVhVm7xH=%!sv1v?NA}C3WARV63mo(23e!LbVrIfH>{KC@BA8iAX_aKyPH`CN+EYZHe}q(GX*S@r^s6yhAS`9w%q ziobADySi}YsrgUH>0n6r9}$vasthOjDs9tFJ8r>SB$?9qH>c)EY$Un7rL!1EEaQnM zDf|RaCULVDPofP3O;awkP6x-HzGY#&JyVahPPH)<&y3B|Y4maj*ry45e~rC(04>6A zwiocFjSr_MM!b*?)Wvp{AD}@1xVh9{@UG3IvCM z`LK7F+&PV|6Tt@u+CY@`D&qT92XdH)6+G8nm&j`@uRGXu4>J+tX)qIwQ|rV|MwSOw z_~{oM^Uia6f$roLTm@NtnN4s`oZgB^#uGMUIOmtyimeN*{UhA(#kMInNpajeIb)jN z=;Iq1yy1A+eK`@3+^H5`s+0>6wv5$USDJYOujqV?~;<#EULs${FB(T|$ ziy0J4$e?myQF1C80s5kj;*7Oi@eZQ$nprg#ttZamBg~`U-h{lp&%7-?;2TiVaXiFJ#=v4H#*!mN3fDmW$Dq32JATQ z|0upJC2iiO|0GU<<}f~dbBeewqq|Q^PR1piow2Ar(|Sprid)CY(4W!z{nFN%xUD3< zSH=D+aS2;TPz~D?c5-$;%tj6|Pt#LHj^Q_ad=J7=IMB0Ti0i(HFux6Qnu7&avkv2YJAVFem2Bl+5}JSVW#If*eh>qu{$wv^{)UYG|owdq~s*r`5d< z>$b5hj16r;-d4)DI=*jtpL`Ho*CyPgys(O;p^<^JDBPUlD$oRH3)Fe!bJc zXV@aQyH{45_y`1@x%i~c3IMK%UKgA-eqPv1gMMDRG6x{)D>Rj0gv-Sa_*I3o5k3~r%ErkUQ%F)YQ>PWH1q~S>!UWOZpiwE9{=n(Zrq*5;SF9i2r>^U0ng1Efutv$L} z+&2VHPJ9QHIHD2<_dHW?Bd%WXY*4H3S(YRbu~LKM7xNJL&td@J;RiOmrCR&!apL} zY4SbW0mc);Ld2FR;tA_8JcY(qFK_lG2Xh+VRKyx1a`t*_*}_V6oc37^l2d&o);aQFHp9HqiX6#(J5 zC?l&>`LQ;-bv-nTQkYrg7~Y8QRPP@-gtPVns%Y9D~72_78OO)$4Jt;TjO zp1NtjMtEYSV;d-PiyY>D(XuXU+^RJ_>_P=5+TZkzogef`Wlk$(gjt^0)1ZD{yAo{<$Bd-Gv z%-=Ep-Yz0L@OI&qE3AL*liQ>IacmNdHt`|Jo%_&N(LdQOAl_rNTf|$b?J@Y3PT|1q zSaSwDVI>^kJ>4zQOV-WeZnSwn?*a7=zW$NhIpZI0&UQ0z;_T4&c(<@q;Tj1a(BW&1O*B6<)4LDYy74y@bByHLyga>sqM+`q&k3*`+d9khRF6L*6o4rBzwas z_T6OM!8GhgIigjO?*dkHmwKLwV0K9VB})afua}?Urvz`YEGu#vNUX@v!G@YEJTy3V zOB;~hL&B*NMfxP8?;?Pg;9HjXVo(`WfIU38TH5{+2uS{@snQ&g&v#MNmUB>3IA_i6 zd3?mHnOI9}=$*qSqG&dOE6@=j{&tCO0H5DvLEmHWZDfCk+yFl)#K8ghes6aUDh7x3 z2+sRImgVnJ=r#NPXZ^n4v(5z5&$ic~{$R3WE-c12wmr|F>^AoIEr7{99YWJGPZM%< z7Q`iUWDU;|t!tdpOA>+z*obm=uq!~Ax{6Qi6;45 zUxdC3NyvEOy6>B>vFJsX(^53<%`A?mGv@gf5!~Sz$OYdNsTs|yqxEa7`2{8ykl-_L zc)r=jhpgx)k#C!Y=@m>S?9nPKB>Azv48B3cFPzQn7xILEL7ZE%C5BV(_-1Rdzn(Hd z=h?#yk?|-;nUc@7Rr9>ahc6K)D5Hey*?d#iV6NtC#B}|6cAf@wU|R@h!h3SM8D26^ z@Ee~21VTYc^+IdiU~MG3Wva#7$g%!?qUlSxVe}GRuI6MTB<1<_M*Z`AxX0J1;A*mh&;ztpF71O3yG2f;WT%h~jUu`uO%`R#hEuZT^5D3 zn(x<;kKD>pe)(913D9EPiR@U*-j1Pcl9Aat_#~f-zDiG?ICI3uBFdh@d=V`DglH0G z&ztz)$M90Zdm2f>=4wa2X<6-p$w}nfVe7aFO19yfcKZK$dm>l7Z~6-f{%^s1?cn$D F{{>~4w)X%4 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/mtest.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/mtest.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2921e75881e45351b08a265fc7ed7c390c67cdfc GIT binary patch literal 67875 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 BgslJo literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/munstable_coredata.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/munstable_coredata.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d56312a5d3b161ff7dfc255e50e5afa2021244ad GIT binary patch literal 3561 zcmZ`+O^h5z74Ght?&1oKbFEIUtTDZb*pSIQzu+s(Z$E2(6u}S6{t)_3FK< z_ul@v-ELU;zWC2y4t{mfvi?bf#pi&yZFMZgL2!%Pu{E;$wrz2TS7K*W=~oS1jop#g z_eQmT4P%SDvEQ$ozR_=(zS(bbkJmo6`YrDBI{G$m@Fw~d-r{ZatK5BHbyvQmy}Pz< z21$};K^CQn`qC~iKTM_IK^Al!-M$xuM^PfSkJ2a)r&PK2%ixHG-+;3z#| zqz8kFY@!5b`)4eiNGXzx?FZpdB)r$HYA*;$D_!M6WxB@2K`@CkT|E-;xx&vxpi*sSdaJjoS8jyGMn4Ey^ia%Zau>_ z!nl$&Ct%##gZHDF$WJ#9QH9Ov&&9mZbRThj(J--mpQ zO;-zgI~|RJ1i%ZMP1g$S&Loc6v5*Rm0_R47?uZN?fMb_4-I{izOpKIv$1+MX?L=Hx zpQKTuYvNSI5j@;FfUrTiMAu3JPOOLNXdK1ZMOWh>In=ny1z=oOG;6S#Ug49`7%nK; z-vp*QXe|4p-LY5fHQPh$+44HD*KA(}U~Jz5ar*Ys_E-Pc_IYXXrPV6NYEx&6bsb4w zmYZmxxQ#O=!ANNLIEW|WtJ*ea+cVodMr&A? z*E0Kw1Fz$8=Jq-6i5XWx+v*3I%N@E0yz+pas)sw|@~XKzE_ch`GktCDlZ>># zde-2zXOJ~h+2Ef7zw#QsZt%}@uh4>T ze2vUa!}HfA&o{n?=MC^U(mVZI*1=nUYgWTfSLYY<+Wg`<{9(LvDfjZ)rg_uP?Wg~E zWEqXWX;%K4U*m6nYR&x9-(+i9hdlK7V@PQhYYMN;>UkZzT!(B{NdBG0zxDeHNk4rj zuhY)(X=Bzr-N>65b!M&H&l`E`nPbD_Px&Kie{S0AwEt^%ceBg$E7|&dgKWyLpPO6v z^pi5Ge0z7=HWBkC-u`iriRs7NWw>9)Y8EMz4}zCLyvII@MW6&zV-ZFNXDrHCDp`1h z5Fl8Fcz=@0VU!%cjQA`|!PS!#O{WhY9ziJn0!9ywr3YpaqK}YC5VJ+dW+9THplPFI zk1f_6U^g!ICx?f$Nt(oGz3JVZlAD8U~E zCM0E~33d{kDQ)RmneT47&{(&S4doy;$yn*ta&8H97J+SvwDw`2<;dj3EK1ZZI=^m# z%8+vh6k&8jibIhUbUi~xElB5BQQ*?83@K3*ppsW;eS>1H;X>3t4O1?3;YJFulnJKq z-lIIo%3+bqanK?SA0T2gv#F4#64_#M9di3CgbB7}567vjJd5M9edTz-*$f=n*j9%gQ4d%YYOp#SLSw~Wx zR@`^Eagmlw)fp8(Krb-!#ZfX`KxIx>=|qNtcuHVt&aP*&n664OmbycCqm)X;lhSQM zNMbQ;(y)}K&0vwg9V*?%gP}On6%b!df^}053^22glPD_EEPDf)dd>Fnn_iKVr1xH& zhC!@u^_I-jjnZLQh>c%MH=9(&|!*aD5)sZo=PR^8SM`SJPNbHz@&MqZUdRAlL%rdXG`;nJ!mlsGJVNd zC_TZG4(XXvC145_i4*?L~Bg45g?!U%xgkM0DG_wulBb(hoZKTlA#M z(4ZvM4DxN#(H?61SU0h9P~Kp98+gBA>MpoSW%3qr|B#yZsiA`RmFlSiQ@;yHC1@oLuV`}4^el1l!uuB5q~LOD~(a5?Q|+qp`vov-BELzSWSaAmkXQW@dC zj8|xnRz}-nl`&m&t=55Wbh!w)SJya-lr@p}4z(vMlkKU>6wf*A z9&wLi?sLeGHjF8PbId(Dr8TT6t#aI*6hqX5QC6#%^kLNVT%YFgMVG$E#qiVgx>0%I zJxz>=!V^st+{tybasu^HF^2jW*H5B;K#Ze4&h-~jKPVW9Q6>XTeQh5D2@ zjQU}&mry?dNa~&c?31f#kt)Zf2q+NA-s~=ZB0DX&9%5LA0EjEidZk@dcPM+c>3Tw?>i0X%x*I4Pi+5dRwwpe(+KS2wcUiji zTIh;8(JuKjQD8owK*7~2y3i`dE%3W*3gbLD8q~IcWhk5eJz8IxK`7-EM$e%mU9I}H zwp*>LY_;0%h^|NFe6{+ZTl3C+>EzYaisnmXMd1SLJhnIExe*$g(=ue~XRgE@45p z#*|jpA}YyN<#EEfNZIq0O;a}5M^rjNZ6}evjFezP_5Cq9hMxUM4$@m7y$#YkDs#Eh zUhEL%C5>lvdb#=Xjb;#jj-yzRlW4|S{Mrc4VEijcfrTuqr*%m!`=j_GdcFrm6R6ri z)d8w0mAj5Jx#!A=O>jUFvLo~5h<$6`=V)AzhXGU`LH3(qeG22>KnfgWgf;M{w*B$` zwMaXXaJ8(h63)GoJ20Iu-|}(gh{UtS9pqkE_yLaKG!TD>HZwQ^YWW?ul8faSZ{t)f zIzB%&#$^e&#MoIUea^~}O99ELD} zakvKgu#JN-g!$AEmav~#6;n8*5XZBk|@_OS~oCrjeC#jC+U20gr|O$mhk6pJMA6s9d-3e|#dV&22(v%n z+1LTCiuFEh>M%=g@NPeHCkIgHlJdI6us)7qeIkC!u%-a(Q-&2&5A>X9m^(3AH|}Xf z?--k#F@$+>iy<5agr7xw5w~$_x5XXt*?kk|RoSrO{eK?MxhocU&JpnixVNfCBkm=! z7ptOPer8*t&nSzG0ky-|l ziDV(!NDfj;=uh#jriDh=XbyV9fuMqlRw+_i&|u20lj2Y*h+GoN%C1SsIhATe7EdXo zQlv&2 z=Ccq`t7k({TwL98v%`aP8Xt$iD zto%aP)+`<32PbA#Q+?~PP9p_czq0OVpJ~2vM+?(^Gt^s|btCvX%nGpAn%y@ybAWGG zbC_vkru|r7`L=Ji@>jHlzg%-x$NO}~Lw#*?xbJMi_qeS+_-3%~e_>r4>mKVntsFyf zS|j+5Y(tCju)nei51w0C%EF_VPUg}c!qL9Ht}_&ZpbKkbdk=%TcQBvef#2-8p4|-_ zXWk_H+V$%l0mkc1MF&zOY8RV9v0d{T9ocq8xnwHGgXQdZh$%gMEE-fAQ&wl$^(AR^ z<$S`nxw52N6UvUb(59Z@kH~}{s0ewL8nexy=?7uWue)mKa!0tAyiR>-4h2>Q@-hvw zX;m2V^{$kzA69*It1*{sV;I6!Ob^{QIwa{5mDyf`%!g7+l46q=sZVbxvlfKPXuC>> zT}=?T6%*+smBIyw=^flbC4f5#mNoQYeOey_>rUu-7%W+oER+m){-@L2zv7~9&?`v#caIj=ov-PZbW@8UH_0P#O~ z3^3Wkg+aR=7Q#`|IKj^W1v>1p9*%7u5Vml>)>`9Rrj9W=Flh|q;JN{JfAJY86Vx6Q z03$Vkk=_X-zYXIM!}unKF$qkt7BJUaQz)nKJuEUyw9YbCb%?HUITe+I6|9pTtOJ{3 zfUDC_9io+n#1QrK^%|b5lgUJXq#Nkq4$#4ohjtITVPSZUNJo-M|8wJkbu%)La2bc- z_IB%FY}`lOFGCsSvlR!t3XUl05j!*262ty7d)|W&0kOV(VFh)zr5vsI>a&7%7ufQ7 z+_ah(TtFe2-#bMV)*8^6#pyHC zBr4#-W1!z{FS@dK(s%E{p?~Pc4MDN#7uf@>M)Eu;hbv*vIa_}Hweq>%iCypjX$Qnw zF;-#;(2id`HBDnm`vS$)5u*3@$G*3kpk43y!={aWla zfJ7&7%cUdoLmXY?8L}9SJ#~@`Dsg7HlAUAnQkfkXmAOdv0QXtok3eORM~J929Vd4= zarnc=@wJ0UwvvQX*;^kq{cgbUO4MLCyiP5YBx_*rFb7t(Tn2+X$5{oA>UADihHa%v4H8EPI>g=tAjBN`I(K36ZXQN{=LP!q>#ok}!LK z6p%pIAa6<9lGM$!1h!&1JkITT$l$bIU|F1J`Mg~|!98iCcl=k}hTeE0j+0}g9f2#$ z^WA07g$p(i&G5l?#D3s@l??eM(A+Jn=@cy_memr4zP_n#X|fPP_L7WXDGa}brLaLV zc+G&^HCNt+Br?fVfz*8k64&lqp+k~8xPiGWD``X@LBKT|0wmqHA$w78WgvTBBiY+G z8x&rHf`99x=h01m)R6*QH{j6ZTJ!ZqsI1Ai-rF8h{w;+UpB*Uj8Bv5zJUQ5bz>*cT z{xwn}sowa`vl$?~udsUY!#(>dQlx5I5Jgw7T*|7ECafFS4)w4KI=C|8{~DoKN2V;2 zb{e*Oxr z!8kIFjR#`n0<&%wW<+oLR}-XHNcc4|AIK2*Nh<8JkV)$h8?uG`0Sc^8^%kk#@z9J| z5$t5G!A=&&k||H4mDM`zRU17}*^%l;Jw}AdMUXC!0jKzW2gVdxDDRzLYA*jS-xZ9i8IuQSVnYB?Z>Up&&|0P0XU(eEKok{thV^MyB!c zIDA|My?5ec-rG(qZy$TKk9qPSvUz!qiWIJsuTl0YWv^34!7!X%TDlLqP4J1z3w2L)ik54nG~YN2okQPO%V!a6c|s#?h-=u~L`wdWD(Y0qYs8@+D1XQZbX6sL~%jzYwD_ll>D4 z9(_32bK1Nx6a{}`4F)T`9 zlazz2oas}^L5nk`EsMUnmJ%tEegbK?nI%~X`I&~JmBNV36k0_V4<$xFy>6~$`s8%y zmK^zyVSaN+%A2nFpHD`j0#?4j*VH{b3+(D z!R)}efl?Q>;6Aab&bqR9WCw)eNti!D5h~A>58+BNQ}FQ)#4Hh$Zt6|45y^3(_`$*i z?j95a2&yfmqy^Eg{{`EMCH(@8=Hq3qU}zCsVqu&Xi(sDybtt3OC_8}?%tis@fX&9A zqs}2rM|1Svxo25>#~s=si3jtyk?5u3P4^18#^eI77Tpz?mmtfq8tN>E{FopS$yh!5s{YV%S|ENqf8*&}@R(9HO?Kl|XxDPwt!`KFa%UF$rF!BQJNl^A9$|xQ{4=T|U z37H<*ZMn^iTS)_lNJfycthmbWFizyEG8rprzZx4%CdTg}o&0^w{0F3fZliWE%?8K> zL_^*n=P+-MnUnaA>AmNo4eb;YJ80R9V>PjuivrTelUqnO?`*Mp_F9}q|#2DNQx{Y)< z7;SoTfCkgZAq&R(c;CXMo}i1%?}_Hz1#-1u!@{v~@xUg#Ztqm=Jj8%wpXPoIo=MUZ ziAqRE)-Pn+LOSXzd(K^@&wI7@qNrW?cZ~R7ByGR&RWhh#^z3uxa}d)5B-!SPqs$XN`GpkL-JdDQN>&+|Q;>b|P`6*)q9?PR^c!3e zGKF^24>eG%Z#B#T)of_S9W{~_^< zpEi^xxwsD}#e_&WDUL)Zo-$iol3&+$?s^b#KaT}=@0x9nqi6#M`9|N`-aD)T_+4xx zz=sm{2EWkm!-8y<&{e>(@!`WUHUalwJKR18q!q`j2!T<(&yzmVM(`0 zlF`Ls`^a*Fn>=^{TSQcvgFq2gn6^YmCU9kH$H+37Pu2Q;x4uLdgb7BpS3?{ox%~ds z%O4VTM`$*^0m)J79gPsGx+@6F1>_vcG3q=(oi;z(N2f=&u(BwUr7ZfjM5VCTCQ|8$ z2k|Q#r?W`E!HEuw9Bek1_{SWqb69Y)9N~K)KcFEbGVz-mL{RC4=})MM4spNJg$)q> wJmvyzF(CVsjJ`AuBlf>zFRHV7;SWMC|iAh+C%y#)w@oECe?p^;N^iGv(+$jO(@_y0XF zQnC|-(o|PfSN&D>*Z=nv^OGR?Xnz4dz{;Qs@%|pAJ+u3EpAQ79iN!BLa&8`qg9lrad=DadZ-fuaP*Qp zMo2*4KDqy)DG$geJ~2NQwX!?zPAu(^hCKK{;H@Q}#2i~bMQ`zb(j7b)vOK#YpT!<_p`DXQLM79^&^Fha#cHpDKwZpYAa$D7kl^E`-TQgc=BQY95t7gnO z5o#?tb0IOpNOkwjR)Se)j2v(-yp7`=z?J9iRuE(n_4@sZcm4~VAkwA>^MXf4N= zNhb7~AdaLEx{hir)}^PC9qwwRocgdQY-DD3w`6@RFvngm#zo%imr-#^Y?R{SrchtTMa&nN_a)84evQ4f7ZDquitvpT z(x*ZlipDm|(nL8Pi%pOzY7-J?AQsu!K{GeSZf(;Nnt$LiV<%;PQ*4@$EEnolwgOxBDuZN57oZ~Olqo59gO0vECPApz8$tjmWxiZm% zFv)n~JP1V*9V7-M4-r^XCf0&-T|Y6G0?$tj$el_lF+;aG&s*bV)lSS&Q&jAtqD&x6 zM=gXjA*zi#&E_brB|;_!UjMbGj$`Q8XU?6vE!}&!7qDKa8n+jl&)*K^a-Hhvk3i?) zZ5E7aIoI);@^+8E!fJah$<^zg??v_cQNRmdL!lWNLH}~1gkM3F&4MsRNiXXeJh=yD zM$efOVv0uUB|T#l#I%^wyVKj)x!MQcwP&k0d?25A@R&^ky85~wdgt6mpqwZG|A{1n zGk28VpzEeTdK&mKM@^#w3ez^Va554bx&&oiCn_XCqR%LLUoq8_c<@!I!&KW#y+R$K zI-x8rs;DJnVF!G!*6R11X2*RGT_LkFpRxPI_LFQGJ=mg-X+%!E#eJwqu`XhOX5rRHcptW=-tZ24g{e+uRPb6%{5!P zVMBQ=Q|(}$#c@wosy&#E9Uj7iDf=66UK{}-F*YRpX?l16c5IJ~>+T(q)Q3mZ^x-?u z@kMW_x7Bk1)?kpR6!FX9$5-<&sNf>B@SmlCtt49dx-N*Gj7``;3u2G9Zp1>}!qu6v zSb~hC-gzB%4kR^6XlX$)nw#dj8JkO4{BpXsZmnnh(@}n-5F4A~wy~b2o;bTyl$m8i z{St3V^kzMW+L+A7xzBV73BFYPOq2P~Aq77Yv9(d>U(H;oroWv>uH^UKZl~rViO% z2>*#^7h~fy{c~sy%qeW_Ao_>wV$S8s@?G;?>%??)jL$&uHHFX=^j5D zbehtJHD=F4Xxfh5Tgvu3tvOfOo^J=8sNIQ(PAZd%I3v;2tMn)?xKX`FH?;}X@%xRs z*J?LwrA9|7sNK3BNH>`pvC`ggl;_MfU5MN;l7P=oSE*E>7p?|v*RO}pJWRcwBq0!a z62Ns9s^!aMB%WVwxJ<-}1!3g16CHTTq$-`HcF<{8imAwW1smpF*Rsl4VPycp93~=2 zgqw(VEerin2b3g}o;R_;$&JPBEXrr@;b;*s!(%8kNY9cegI6bnj(-KTC-ezC3t}In z5J}q-zb%PJIfSs-gV-HAJc6dficHq-j>Fq{>M*1u3HYQ4c~fttrg17?m~U8c;5~^m zsx#jZL$f&3LB~4LKCFVA+82qBp_{=!=#R}!veU&3=xk>*2$nnT`kd#JXvICMwPfE6 zA)VB%zp!mnNnu_Et#lmObd6@nn^f1Z@KE?|$LAQ&!XkCj;y=aMkXT*Ikj~18N2T|c z@nDi{%UKP*t_zt(Dk7B}eZ51cCsn{0xQ~hy5ybg&R+VF%I?|~{w%W&#CHo;M@H6qV z_G{~6L0i{Xe~%;!Mwy#rO`TddBH-y`CNNFYMs6cd zJ)7WedVfrHkM}QKN0i=35rj1eN*q8_$r?j|-6fzUzLx;lu&<44`Vi!bmCX<3Xbj_d>fZ?QH!C+zc?-pDdW{`YXyC^U@v@em%h z9s{v9go6>Y1ZgiKCCfUsdgFWe;2k`hjt6df=j@Gr3~b0{jqIB1+D*+rX=+hnxd5oY z7TP*ItL|h}+$cq3F~SBUY3Mejv2Om@yrsRX`T8x5-plb=OKlGLVr0TjbiXRty}z?$ zNZ4L#2a*S5FFGMifu8eZ!-ckCK6c>4tl4b`{*vuQb`-#5Sb!x$2EqUqdG;fQ9F6LP zZq=S$g#VBKXv}w-{l!x1qkghLhJtDUE`S9xZ?CwAX&K+{NkaR`%A(g;v}NF?GZ9vR z8wU=P{Y{6J>HtXB>O}L$UxBj7xqc&%P+l`#{pqK^BFXW!czWoS(h$-oBu>8;C)92X zU@cb5w%4M?z<;4zI?)N$2`H=+5W(Gv8-5483zYSaQYj}USuf;TIpKt|RGWr}2oF#cObBoNfS5Ay zL+>QUO$r+pPWQ>}B4wMKJuuu!{SMqdvX)5Q!q5PrlG0_9y&oRYBXh~ZFY|_mGW!PD zG=d66c;iA$-d6#tRTAm?2P23Sg0Tcc`i!O|LoHEH2}~kQkhe9H-W}~=_CjTBMA+u| zcHPw|v6{h(tKiDRKu)sP>u=qyti7*5mC3CaCzG`B;`78cu4X8ikaaA3QZgUp2<6h4GElg4?cqJ zEfc#FBTf}5mpgq;Ny<1C>~sh8N2U;Agw3HC6%J$NREfefy}O~?(SduqDT9m~bp|Go z$+eeaxKeB^ve|<O-25NfFIDkxrRdu>N5*A&?l=@?57I z+K%$#NCf6TF)bu#Mq~TD%!W$FEa+sZr>#dV^^y4$l)QvpA|N@4O;YgjPNR=(GGhm} z=Rcqk>*``3$teTCQ#DAZvX+GZN&yCt`E#*8Kr^gGvenfaG00kSKf}lnxvNhY@g^f4 zh71r7R5Rk)vPHZR^VRJX-rd_ABg|nw{9MWsY~t+(JY1}iS+(N~;7oIz63i55Q!hb% zK`Y<=0++_CSF+9&%%*Qb%x z{zpaJ}0`z&u`6nRKFGaKr(C*!#~Dq5U_AIz^f3vv7x47 zaybxmgy1ADKgo4gdErS3_k`cVdX_q3NATsN>_!e^_#McJcK|C7KORyeDnLO(5KH5M z4ndrbS;c$eZty+?ISb^9+3gM}_&R4uh@$w02ZRUxHY9~X?~o_#xiy-~ zS>m+MR=OLEn^AuN48U0;Hxz_Imp!5o9BMLo5K*WaV)Z`r`W;2LZI%aew|1`yf# z*0q0#70-^W{YW%-B;vPaQ92f%nrNF&-CvAv_3>f*904N%ODVSgX&=cu^auUlmLrqk z@pw&mIU>=w{81`r zrz2M*rmJPEY?jT*z0*Zq9Ne>eeCotRVRGl>(aGIqgZ}Z{2Br=EOw>5LPBMQ>c72?p zCg9HkfgNOb**v8v=t$Uw2|3N&q`gCo zGBW9!uM%Yu2T(v5`r+ws4wnw{X`oi#AaM}=(dJ0NF*p7H@=)p|=BpQ|AkrNk0vI_$ z9p9s3+y03-Z_xhfB025!?YmDiP>NiZ$FnBEkre9GXD;w!kLOFK)^|r((*72tvFIZi z_7?zN$)?Bq6V%n8Qt@Y0FuyUYaRzaC%pu_ubzP<-{i5kiH=U%ISXwQJsN@$QQD0$B*0MXIS!1A1gUsQG51r z=>aDAE!u$ZqLqqM&au-0&y$@Fd>(;_ZC*|D#}(vF;tjhtIk-0PB!w2i_=%B(+tlBIydo;QJB1+)Brl}M>L-Nm+)$Wd2wU*Lsf0NkTJZ^i=L4?qWX2E(C)b1WV*Ek z5u&f)6n$T)IOR!9n3ON#vl5C@UYT2R8&QgN5`rvNc+(?D7|6*a_gZT5oF-E;Jc6Qx c!;k(e>Eswq;ENJGjme*AKhcg(OiX0|2j2&5H~;_u literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/__pycache__/rewriter.cpython-37.pyc b/devtools/meson/mesonbuild/__pycache__/rewriter.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc842309fb01a5ef61ecc8891a165a71b03ea3d6 GIT binary patch literal 34123 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 OxlAsdOXkwu;r}1RBR+}% literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/_pathlib.py b/devtools/meson/mesonbuild/_pathlib.py new file mode 100644 index 0000000..640b5ed --- /dev/null +++ b/devtools/meson/mesonbuild/_pathlib.py @@ -0,0 +1,73 @@ +# Copyright 2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +''' + This module soly exists to work around a pathlib.resolve bug on + certain Windows systems: + + https://github.com/mesonbuild/meson/issues/7295 + https://bugs.python.org/issue31842 + + It should **never** be used directly. Instead, it is automatically + used when `import pathlib` is used. This is achieved by messing with + `sys.modules['pathlib']` in mesonmain. + + Additionally, the sole purpose of this module is to work around a + python bug. This only bugfixes to pathlib functions and classes are + allowed here. Finally, this file should be removed once all upstream + python bugs are fixed and it is OK to tell our users to "just upgrade + python". +''' + +import pathlib +import os +import platform + +__all__ = [ + 'PurePath', + 'PurePosixPath', + 'PureWindowsPath', + 'Path', +] + +PurePath = pathlib.PurePath +PurePosixPath = pathlib.PurePosixPath +PureWindowsPath = pathlib.PureWindowsPath + +# Only patch on platforms where the bug occurs +if platform.system().lower() in {'windows'}: + # Can not directly inherit from pathlib.Path because the __new__ + # operator of pathlib.Path() returns a {Posix,Windows}Path object. + class Path(type(pathlib.Path())): + def resolve(self, strict: bool = False) -> 'Path': + ''' + Work around a resolve bug on certain Windows systems: + + https://github.com/mesonbuild/meson/issues/7295 + https://bugs.python.org/issue31842 + ''' + + try: + return super().resolve(strict=strict) + except OSError: + return Path(os.path.normpath(self)) +else: + Path = pathlib.Path + PosixPath = pathlib.PosixPath + WindowsPath = pathlib.WindowsPath + + __all__ += [ + 'PosixPath', + 'WindowsPath', + ] diff --git a/devtools/meson/mesonbuild/_typing.py b/devtools/meson/mesonbuild/_typing.py new file mode 100644 index 0000000..d3cfa39 --- /dev/null +++ b/devtools/meson/mesonbuild/_typing.py @@ -0,0 +1,81 @@ +# SPDX-License-Identifer: Apache-2.0 +# Copyright 2020 The Meson development team +# Copyright © 2020-2021 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Meson specific typing helpers. + +Holds typing helper classes, such as the ImmutableProtocol classes +""" + +__all__ = [ + 'Protocol', + 'ImmutableListProtocol' +] + +import typing + +# We can change this to typing when we require python 3.8 +from typing_extensions import Protocol + + +T = typing.TypeVar('T') + + +class StringProtocol(Protocol): + def __str__(self) -> str: ... + +class SizedStringProtocol(Protocol, StringProtocol, typing.Sized): + pass + +class ImmutableListProtocol(Protocol[T]): + + """A protocol used in cases where a list is returned, but should not be + mutated. + + This provides all of the methods of a Sequence, as well as copy(). copy() + returns a list, which allows mutation as it's a copy and that's (hopefully) + safe. + + One particular case this is important is for cached values, since python is + a pass-by-reference language. + """ + + def __iter__(self) -> typing.Iterator[T]: ... + + @typing.overload + def __getitem__(self, index: int) -> T: ... + @typing.overload + def __getitem__(self, index: slice) -> typing.List[T]: ... + + def __contains__(self, item: T) -> bool: ... + + def __reversed__(self) -> typing.Iterator[T]: ... + + def __len__(self) -> int: ... + + def __add__(self, other: typing.List[T]) -> typing.List[T]: ... + + def __eq__(self, other: typing.Any) -> bool: ... + def __ne__(self, other: typing.Any) -> bool: ... + def __le__(self, other: typing.Any) -> bool: ... + def __lt__(self, other: typing.Any) -> bool: ... + def __gt__(self, other: typing.Any) -> bool: ... + def __ge__(self, other: typing.Any) -> bool: ... + + def count(self, item: T) -> int: ... + + def index(self, item: T) -> int: ... + + def copy(self) -> typing.List[T]: ... diff --git a/devtools/meson/mesonbuild/arglist.py b/devtools/meson/mesonbuild/arglist.py new file mode 100644 index 0000000..c44728a --- /dev/null +++ b/devtools/meson/mesonbuild/arglist.py @@ -0,0 +1,331 @@ +# Copyright 2012-2020 The Meson development team +# Copyright © 2020 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from functools import lru_cache +import collections +import enum +import os +import re +import typing as T + +if T.TYPE_CHECKING: + from .linkers.linkers import StaticLinker + from .compilers import Compiler + +# execinfo is a compiler lib on BSD +UNIXY_COMPILER_INTERNAL_LIBS = ['m', 'c', 'pthread', 'dl', 'rt', 'execinfo'] # type: T.List[str] + + +class Dedup(enum.Enum): + + """What kind of deduplication can be done to compiler args. + + OVERRIDDEN - Whether an argument can be 'overridden' by a later argument. + For example, -DFOO defines FOO and -UFOO undefines FOO. In this case, + we can safely remove the previous occurrence and add a new one. The + same is true for include paths and library paths with -I and -L. + UNIQUE - Arguments that once specified cannot be undone, such as `-c` or + `-pipe`. New instances of these can be completely skipped. + NO_DEDUP - Whether it matters where or how many times on the command-line + a particular argument is present. This can matter for symbol + resolution in static or shared libraries, so we cannot de-dup or + reorder them. + """ + + NO_DEDUP = 0 + UNIQUE = 1 + OVERRIDDEN = 2 + + +class CompilerArgs(T.MutableSequence[str]): + ''' + List-like class that manages a list of compiler arguments. Should be used + while constructing compiler arguments from various sources. Can be + operated with ordinary lists, so this does not need to be used + everywhere. + + All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc) + and can converted to the native type of each compiler by using the + .to_native() method to which you must pass an instance of the compiler or + the compiler class. + + New arguments added to this class (either with .append(), .extend(), or +=) + are added in a way that ensures that they override previous arguments. + For example: + + >>> a = ['-Lfoo', '-lbar'] + >>> a += ['-Lpho', '-lbaz'] + >>> print(a) + ['-Lpho', '-Lfoo', '-lbar', '-lbaz'] + + Arguments will also be de-duped if they can be de-duped safely. + + Note that because of all this, this class is not commutative and does not + preserve the order of arguments if it is safe to not. For example: + >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror'] + >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar'] + ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror'] + + ''' + # Arg prefixes that override by prepending instead of appending + prepend_prefixes = () # type: T.Tuple[str, ...] + + # Arg prefixes and args that must be de-duped by returning 2 + dedup2_prefixes = () # type: T.Tuple[str, ...] + dedup2_suffixes = () # type: T.Tuple[str, ...] + dedup2_args = () # type: T.Tuple[str, ...] + + # Arg prefixes and args that must be de-duped by returning 1 + # + # NOTE: not thorough. A list of potential corner cases can be found in + # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 + dedup1_prefixes = () # type: T.Tuple[str, ...] + dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') # type: T.Tuple[str, ...] + # Match a .so of the form path/to/libfoo.so.0.1.0 + # Only UNIX shared libraries require this. Others have a fixed extension. + dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') + dedup1_args = () # type: T.Tuple[str, ...] + # In generate_link() we add external libs without de-dup, but we must + # *always* de-dup these because they're special arguments to the linker + # TODO: these should probably move too + always_dedup_args = tuple('-l' + lib for lib in UNIXY_COMPILER_INTERNAL_LIBS) # type : T.Tuple[str, ...] + + def __init__(self, compiler: T.Union['Compiler', 'StaticLinker'], + iterable: T.Optional[T.Iterable[str]] = None): + self.compiler = compiler + self._container = list(iterable) if iterable is not None else [] # type: T.List[str] + self.pre = collections.deque() # type: T.Deque[str] + self.post = collections.deque() # type: T.Deque[str] + + # Flush the saved pre and post list into the _container list + # + # This correctly deduplicates the entries after _can_dedup definition + # Note: This function is designed to work without delete operations, as deletions are worsening the performance a lot. + def flush_pre_post(self) -> None: + new = [] # type: T.List[str] + pre_flush_set = set() # type: T.Set[str] + post_flush = collections.deque() # type: T.Deque[str] + post_flush_set = set() # type: T.Set[str] + + #The two lists are here walked from the front to the back, in order to not need removals for deduplication + for a in self.pre: + dedup = self._can_dedup(a) + if a not in pre_flush_set: + new.append(a) + if dedup is Dedup.OVERRIDDEN: + pre_flush_set.add(a) + for a in reversed(self.post): + dedup = self._can_dedup(a) + if a not in post_flush_set: + post_flush.appendleft(a) + if dedup is Dedup.OVERRIDDEN: + post_flush_set.add(a) + + #pre and post will overwrite every element that is in the container + #only copy over args that are in _container but not in the post flush or pre flush set + if pre_flush_set or post_flush_set: + for a in self._container: + if a not in post_flush_set and a not in pre_flush_set: + new.append(a) + else: + new.extend(self._container) + new.extend(post_flush) + + self._container = new + self.pre.clear() + self.post.clear() + + def __iter__(self) -> T.Iterator[str]: + self.flush_pre_post() + return iter(self._container) + + @T.overload # noqa: F811 + def __getitem__(self, index: int) -> str: # noqa: F811 + pass + + @T.overload # noqa: F811 + def __getitem__(self, index: slice) -> T.MutableSequence[str]: # noqa: F811 + pass + + def __getitem__(self, index: T.Union[int, slice]) -> T.Union[str, T.MutableSequence[str]]: # noqa: F811 + self.flush_pre_post() + return self._container[index] + + @T.overload # noqa: F811 + def __setitem__(self, index: int, value: str) -> None: # noqa: F811 + pass + + @T.overload # noqa: F811 + def __setitem__(self, index: slice, value: T.Iterable[str]) -> None: # noqa: F811 + pass + + def __setitem__(self, index: T.Union[int, slice], value: T.Union[str, T.Iterable[str]]) -> None: # noqa: F811 + self.flush_pre_post() + self._container[index] = value # type: ignore # TODO: fix 'Invalid index type' and 'Incompatible types in assignment' errors + + def __delitem__(self, index: T.Union[int, slice]) -> None: + self.flush_pre_post() + del self._container[index] + + def __len__(self) -> int: + return len(self._container) + len(self.pre) + len(self.post) + + def insert(self, index: int, value: str) -> None: + self.flush_pre_post() + self._container.insert(index, value) + + def copy(self) -> 'CompilerArgs': + self.flush_pre_post() + return type(self)(self.compiler, self._container.copy()) + + @classmethod + @lru_cache(maxsize=None) + def _can_dedup(cls, arg: str) -> Dedup: + """Returns whether the argument can be safely de-duped. + + In addition to these, we handle library arguments specially. + With GNU ld, we surround library arguments with -Wl,--start/end-group + to recursively search for symbols in the libraries. This is not needed + with other linkers. + """ + + # A standalone argument must never be deduplicated because it is + # defined by what comes _after_ it. Thus deduping this: + # -D FOO -D BAR + # would yield either + # -D FOO BAR + # or + # FOO -D BAR + # both of which are invalid. + if arg in cls.dedup2_prefixes: + return Dedup.NO_DEDUP + if arg in cls.dedup2_args or \ + arg.startswith(cls.dedup2_prefixes) or \ + arg.endswith(cls.dedup2_suffixes): + return Dedup.OVERRIDDEN + if arg in cls.dedup1_args or \ + arg.startswith(cls.dedup1_prefixes) or \ + arg.endswith(cls.dedup1_suffixes) or \ + re.search(cls.dedup1_regex, arg): + return Dedup.UNIQUE + return Dedup.NO_DEDUP + + @classmethod + @lru_cache(maxsize=None) + def _should_prepend(cls, arg: str) -> bool: + return arg.startswith(cls.prepend_prefixes) + + def to_native(self, copy: bool = False) -> T.List[str]: + # Check if we need to add --start/end-group for circular dependencies + # between static libraries, and for recursively searching for symbols + # needed by static libraries that are provided by object files or + # shared libraries. + self.flush_pre_post() + if copy: + new = self.copy() + else: + new = self + return self.compiler.unix_args_to_native(new._container) + + def append_direct(self, arg: str) -> None: + ''' + Append the specified argument without any reordering or de-dup except + for absolute paths to libraries, etc, which can always be de-duped + safely. + ''' + self.flush_pre_post() + if os.path.isabs(arg): + self.append(arg) + else: + self._container.append(arg) + + def extend_direct(self, iterable: T.Iterable[str]) -> None: + ''' + Extend using the elements in the specified iterable without any + reordering or de-dup except for absolute paths where the order of + include search directories is not relevant + ''' + self.flush_pre_post() + for elem in iterable: + self.append_direct(elem) + + def extend_preserving_lflags(self, iterable: T.Iterable[str]) -> None: + normal_flags = [] + lflags = [] + for i in iterable: + if i not in self.always_dedup_args and (i.startswith('-l') or i.startswith('-L')): + lflags.append(i) + else: + normal_flags.append(i) + self.extend(normal_flags) + self.extend_direct(lflags) + + def __add__(self, args: T.Iterable[str]) -> 'CompilerArgs': + self.flush_pre_post() + new = self.copy() + new += args + return new + + def __iadd__(self, args: T.Iterable[str]) -> 'CompilerArgs': + ''' + Add two CompilerArgs while taking into account overriding of arguments + and while preserving the order of arguments as much as possible + ''' + tmp_pre = collections.deque() # type: T.Deque[str] + if not isinstance(args, collections.abc.Iterable): + raise TypeError(f'can only concatenate Iterable[str] (not "{args}") to CompilerArgs') + for arg in args: + # If the argument can be de-duped, do it either by removing the + # previous occurrence of it and adding a new one, or not adding the + # new occurrence. + dedup = self._can_dedup(arg) + if dedup is Dedup.UNIQUE: + # Argument already exists and adding a new instance is useless + if arg in self._container or arg in self.pre or arg in self.post: + continue + if self._should_prepend(arg): + tmp_pre.appendleft(arg) + else: + self.post.append(arg) + self.pre.extendleft(tmp_pre) + #pre and post is going to be merged later before a iter call + return self + + def __radd__(self, args: T.Iterable[str]) -> 'CompilerArgs': + self.flush_pre_post() + new = type(self)(self.compiler, args) + new += self + return new + + def __eq__(self, other: object) -> T.Union[bool]: + self.flush_pre_post() + # Only allow equality checks against other CompilerArgs and lists instances + if isinstance(other, CompilerArgs): + return self.compiler == other.compiler and self._container == other._container + elif isinstance(other, list): + return self._container == other + return NotImplemented + + def append(self, arg: str) -> None: + self += [arg] + + def extend(self, args: T.Iterable[str]) -> None: + self += args + + def __repr__(self) -> str: + self.flush_pre_post() + return f'CompilerArgs({self.compiler!r}, {self._container!r})' diff --git a/devtools/meson/mesonbuild/ast/__init__.py b/devtools/meson/mesonbuild/ast/__init__.py new file mode 100644 index 0000000..d14620f --- /dev/null +++ b/devtools/meson/mesonbuild/ast/__init__.py @@ -0,0 +1,34 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. + +__all__ = [ + 'AstConditionLevel', + 'AstInterpreter', + 'AstIDGenerator', + 'AstIndentationGenerator', + 'AstJSONPrinter', + 'AstVisitor', + 'AstPrinter', + 'IntrospectionInterpreter', + 'BUILD_TARGET_FUNCTIONS', +] + +from .interpreter import AstInterpreter +from .introspection import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS +from .visitor import AstVisitor +from .postprocess import AstConditionLevel, AstIDGenerator, AstIndentationGenerator +from .printer import AstPrinter, AstJSONPrinter diff --git a/devtools/meson/mesonbuild/ast/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/ast/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2588fb9fd2e2882bbc896523bfaa90ae6d1aca8 GIT binary patch literal 615 zcmZ8d&5qMB5RQ|!X_BT}1Omhx^n%0{A;j($Rz<5WqFoMFB&&41ON1Rqwztwg67Rr` zxA1`rCvKcMF_UOjz?Q%H=CkL=b5fRhgzM|CZ&%+3QS^hHyOkk%g~weXKm-h8NMHa% z7(oi->x@T`L9UpNdCZ6xD$xTz&_h1#{D~Url&2jp)mUdd(>c#|!HZ6ts);Unsi%C3 z{?R&`&%(W9=TA)owXaQcF85M}DN4)6OWRtB*!zn!*+{$f#)e1TJ;=syDd=!Pfp6Cr zt9Q1h@Q|bbp>{O|5x>(PV|Hs?D|ZzCcd3Ubm&@~o*c`tw6E)wNOJ?5_Hxo>dM$3*xAIW0b43 wbf)R?<4vug+B#neQ8%?0;%R#u#xJyi8zo=f$DHm7Ld^c%qh!KnY{DL}KisILfB*mh literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/ast/__pycache__/interpreter.cpython-37.pyc b/devtools/meson/mesonbuild/ast/__pycache__/interpreter.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..041966faa9622154db8b9f005542df939ef0a964 GIT binary patch literal 13767 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/ast/__pycache__/postprocess.cpython-37.pyc b/devtools/meson/mesonbuild/ast/__pycache__/postprocess.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e218d0a23cdb109fd5d4c88505035fda49d644db GIT binary patch literal 4683 zcmdT|PmkL~6rZu3|4uf$E#2Mz*|xM$QeY7X(WGB1&ak&!lzg*xRvF z(I}kSPl0+UN4^6$zJ;%xdgI&!;=LI=adtP^AOR{~c|6bKnR&nWd+*K5UaeNk1g>BI z_^tEj0wKSnkX{CKJ|T4ycA&!uqaNwe7Nvw~O!u^&-qN8@nBf_%9M5(0;scgrd9Tnb zwu+Q&5msQur-T)`{zPw;KrXQ|$Ym*)L9Q?pWK+r&W_(Q=)fc#XgT@ux_k+le+`tcC zQ1z~SC5&#np&JFF`9f3g3cVd$gj_f{FTHf=NX>tO4ks7XfP z`DdEc(P$ZPmCUTY4K+dy;M6R<%kPB=nkq@!MAQ#zdiF|}DgIr=OiM+~= zf?Q_D68Shg0dj?{0os%CGC`E$(w+1HRa320jNn8gb821+}gaq)QpS07xu4q+RW~J|x+Zi*h984VP&cq7DxUE;ej&FO2iHR!lOW%m4KkfLSW4;q zf=BlQHXY?v*doIx?b7F3hCw~yRtIj4-6N7)eS+JZrB3hs8f6G_;TZ)t^D z2B<3ojJ19jO(2su@N6ok-23J(`jIgCkq9uOd6=M!XkF>f_v9FK`~r;(b~1etoyv zm$LL@m_wkyH=F)FYmB{MyR(l$FehORAk*7z=#0bRhZS&px=HTTe$<9q>i!RxzJ>JH z)x}Mj{){9<41AY*ItUQ&**XJRc@IJOtVc)c@hke^qBLa=9POU@OJB-Z{Y?iUX@<6O%a|#>D z)wscvS`?r`NFkm8MOxGAMm-OI1$md`xC29@3%yd-cITlpZ*2#~Q8}(5@Xb+)CGe1h zT0+(ySU2H?PYv!-dF6uFXDW}l-~@d?;sPeh>SGriw8u@j)1pY$cjG;0)!IxxKSe)8`0w(F0h0UZ$K04VI-gk2_ws8jcoWC$bW`V$t6}V-@rZcxH5#@ z3LTuDH2k{q&}?zmY~<9gujAHduo-*S*u=6Yw>k@-e1%(KfIbRi_^C@tvB z>nKT)KKG9RaI8b|BH-Idqx1$=-t+m^zNP!ZDBi84h@a|ccK}%GXh-+x@OOO;-G1cy zXld{o^d99avh02b-pd^?`zgeU_pVcQ zZ5r?Cd0L#F;O00c--a#Q>9+Ei)ZvIM349MnH5|~LKK!2m4rqZf92aDc4TQk_80R6a zyZ*hH-ioWYzWef;wejh-jnB86TQL!N_&}brGK0zmGyIx3iWxU9UREW*$M}0qGHq%m NEoymcYW0it%3rrV*o*)G literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/ast/__pycache__/printer.cpython-37.pyc b/devtools/meson/mesonbuild/ast/__pycache__/printer.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19f05a2e1ff7c93e0da8e4d654a1ef0502e89857 GIT binary patch literal 16493 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 N(7$DC?9;+K{|6P!F~0x+ literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/ast/__pycache__/visitor.cpython-37.pyc b/devtools/meson/mesonbuild/ast/__pycache__/visitor.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebdbb1ad6bc2fe59810cbdbec7e6fe734f92e291 GIT binary patch literal 6486 zcmc&&OLx;&5SHXe-ih;mLc$yK2=A6sUU>m2#n2`|N!{b4c;rMNOW{fe;u97<<#g4b zzyg;258d@&XxkOLuDj}tbfqg>iIbC>Q|DxSKY4WTH=~)++&kOV)h^-ZkH7ycwG2qo zUj%|r0tdIHjAUQM0Z1SlQdwS+Wg07nvXame&y(ypBp_*|%ITG~EZvnL1?hJZq<>LX zT0mKnvMrxzzO3wasHSN-s-s(`o%^Kt7hB33Dzi0KB&FaJF6_#Zq)96>NGl4+puCr9 zv3JRp1TG^(`n>`z(26(-Z5+2l2jUcTa@+;oh||!+aRz!3w?H4q{V;&I6$UvTf?>pM zFv9UDj3I7^agHb80OAff$nhjhA?}1j93O@wh`Zn@$H(9};%+#>@kz)c?txPrpN2Dt zGjNvUX*h?t7tV8h0WKo$gG(G=hAW8s;R}wxgsX@L;46-=!Pkff;X21R;3ncBxW(~p zm_a-YvmDRCJmL{p;P?*QMLY`kI9`Nr5Rbuqj=zNmh{qwv@k4locmlrT_O)1qfkuZ z03^Iu&izh7m9#aZ#9HyHC;pk6zm^B>ResGfz-Gn#x^W?I!;1oq@w#JKhMg~Kwq^Qq zwW1r4S8XT%%BL~CvFWxJ3c9H~g~BM#Yg433aYgYS1 zc4)SynnbXM6D6AG)@~eZNgt#w`J%!}e`1Sg$&WiabBlIR>^dgGY?ttAQ zG@n?fPt2eCaD>xvjFYcZ?F;DSD&K8d3p?N6g!FuiLKtOiRG9BHlcp2MVqC8=v3rt5y z#uGNGS?vu7&N5AX(fsG!!_zgG{X&G=Sj>MR3BhZIF?DliUSl|)C?i|)bNPd^B}Ge0 z!Ye6mQe|tln^ucOZNq6)U^wG&-OI$7UILQbE?486Lq$=V=k=oV-zl>}T$2rqLyd*y2tM)kKYc*q|UD$H}&T>KFlu z`Upt!2r#sgb;_%quu;M-8kWU&Ej=~^!67C{bqy;`MmT~_giI43DWsx-_xKG&+?+4GIUe3ef|m2)4H-= z-`4gA0TrS0lnjZa^}%i8DWWb)=AsGOo90H6+oD^m&$VJupmbWIQI_-i8dAyE856Iu zp{nTa9%#t*@D7&1^zevniyoYfkeDJ5#gp^BVH;`dX`99Sbu2 zkx{X0f7`yt-Lv=iWWtD_)A7a48Z(Z>(mH-ebu=&qTX;<^uFn~2#ou3VZ^?e%e{M>5 zw6b5W+|(*n#6~$W?3))O#K^ix**YAvFLsN_kj2tAmerJE>UZ~2iW_uV3BAOvY|{)| z^DT|kXLbbFsISmGm!bq;lcjV%;rCtLay6b$QGHR^9zVd%mfeIhFolcnnoGQTiACSy zU7`rYYnRXz{qACEXS(}}wzi^Wf==boGl0>quu;4P2N)iYpUHwqki}bGpRYLaS=N}T zvIaYei#VkStmsxP8cH}$25)?R?3PV=4LqaB^h|Nv99Hqe%55*HVTd(2*5b!T5t6@> zg(A4Ht&blbMbt$K&9JpftWu|Nwy>L7uCa9IZsyG?&+_C)345K1yz(~jHn|mUU$#O& zygV;DAKw>l8*XPk7Ch0?FJ99Imz~9>(O=?tk5bJ|ywEn?1U7p+Bwf^`-|z;TP6mUd z8=!q}Jn^FUm))-AXO9*NbN3eJ?l0! T.Tuple[_T, _V]: + return args, kwargs + + def _holderify(self, res: _T) -> _T: + return res + + def func_do_nothing(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> bool: + return True + + def load_root_meson_file(self) -> None: + super().load_root_meson_file() + for i in self.visitors: + self.ast.accept(i) + + def func_subdir(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + args = self.flatten_args(args) + if len(args) != 1 or not isinstance(args[0], str): + sys.stderr.write(f'Unable to evaluate subdir({args}) in AstInterpreter --> Skipping\n') + return + + prev_subdir = self.subdir + subdir = os.path.join(prev_subdir, args[0]) + absdir = os.path.join(self.source_root, subdir) + buildfilename = os.path.join(subdir, environment.build_filename) + absname = os.path.join(self.source_root, buildfilename) + symlinkless_dir = os.path.realpath(absdir) + build_file = os.path.join(symlinkless_dir, 'meson.build') + if build_file in self.processed_buildfiles: + sys.stderr.write('Trying to enter {} which has already been visited --> Skipping\n'.format(args[0])) + return + self.processed_buildfiles.add(build_file) + + if not os.path.isfile(absname): + sys.stderr.write(f'Unable to find build file {buildfilename} --> Skipping\n') + return + with open(absname, encoding='utf-8') as f: + code = f.read() + assert isinstance(code, str) + try: + codeblock = mparser.Parser(code, absname).parse() + except mesonlib.MesonException as me: + me.file = absname + raise me + + self.subdir = subdir + for i in self.visitors: + codeblock.accept(i) + self.evaluate_codeblock(codeblock) + self.subdir = prev_subdir + + def method_call(self, node: BaseNode) -> bool: + return True + + def evaluate_fstring(self, node: mparser.FormatStringNode) -> str: + assert isinstance(node, mparser.FormatStringNode) + return node.value + + def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> TYPE_nvar: + return self.reduce_arguments(cur.args)[0] + + def evaluate_arithmeticstatement(self, cur: ArithmeticNode) -> int: + self.evaluate_statement(cur.left) + self.evaluate_statement(cur.right) + return 0 + + def evaluate_uminusstatement(self, cur: UMinusNode) -> int: + self.evaluate_statement(cur.value) + return 0 + + def evaluate_ternary(self, node: TernaryNode) -> None: + assert isinstance(node, TernaryNode) + self.evaluate_statement(node.condition) + self.evaluate_statement(node.trueblock) + self.evaluate_statement(node.falseblock) + + def evaluate_dictstatement(self, node: mparser.DictNode) -> TYPE_nkwargs: + def resolve_key(node: mparser.BaseNode) -> str: + if isinstance(node, mparser.StringNode): + return node.value + return '__AST_UNKNOWN__' + arguments, kwargs = self.reduce_arguments(node.args, key_resolver=resolve_key) + assert not arguments + self.argument_depth += 1 + for key, value in kwargs.items(): + if isinstance(key, BaseNode): + self.evaluate_statement(key) + self.argument_depth -= 1 + return {} + + def evaluate_plusassign(self, node: PlusAssignmentNode) -> None: + assert isinstance(node, PlusAssignmentNode) + # Cheat by doing a reassignment + self.assignments[node.var_name] = node.value # Save a reference to the value node + if node.value.ast_id: + self.reverse_assignment[node.value.ast_id] = node + self.assign_vals[node.var_name] = self.evaluate_statement(node.value) + + def evaluate_indexing(self, node: IndexNode) -> int: + return 0 + + def unknown_function_called(self, func_name: str) -> None: + pass + + def reduce_arguments( + self, + args: mparser.ArgumentNode, + key_resolver: T.Callable[[mparser.BaseNode], str] = default_resolve_key, + duplicate_key_error: T.Optional[str] = None, + ) -> T.Tuple[T.List[TYPE_nvar], TYPE_nkwargs]: + if isinstance(args, ArgumentNode): + kwargs = {} # type: T.Dict[str, TYPE_nvar] + for key, val in args.kwargs.items(): + kwargs[key_resolver(key)] = val + if args.incorrect_order(): + raise InvalidArguments('All keyword arguments must be after positional arguments.') + return self.flatten_args(args.arguments), kwargs + else: + return self.flatten_args(args), {} + + def evaluate_comparison(self, node: ComparisonNode) -> bool: + self.evaluate_statement(node.left) + self.evaluate_statement(node.right) + return False + + def evaluate_andstatement(self, cur: AndNode) -> bool: + self.evaluate_statement(cur.left) + self.evaluate_statement(cur.right) + return False + + def evaluate_orstatement(self, cur: OrNode) -> bool: + self.evaluate_statement(cur.left) + self.evaluate_statement(cur.right) + return False + + def evaluate_notstatement(self, cur: NotNode) -> bool: + self.evaluate_statement(cur.value) + return False + + def evaluate_foreach(self, node: ForeachClauseNode) -> None: + try: + self.evaluate_codeblock(node.block) + except ContinueRequest: + pass + except BreakRequest: + pass + + def evaluate_if(self, node: IfClauseNode) -> None: + for i in node.ifs: + self.evaluate_codeblock(i.block) + if not isinstance(node.elseblock, EmptyNode): + self.evaluate_codeblock(node.elseblock) + + def get_variable(self, varname: str) -> int: + return 0 + + def assignment(self, node: AssignmentNode) -> None: + assert isinstance(node, AssignmentNode) + self.assignments[node.var_name] = node.value # Save a reference to the value node + if node.value.ast_id: + self.reverse_assignment[node.value.ast_id] = node + self.assign_vals[node.var_name] = self.evaluate_statement(node.value) # Evaluate the value just in case + + def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.Optional[T.Any]: + def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T.Any: + if loop_detect is None: + loop_detect = [] + if isinstance(n, IdNode): + assert isinstance(n.value, str) + if n.value in loop_detect or n.value not in self.assignments: + return [] + return quick_resolve(self.assignments[n.value], loop_detect = loop_detect + [n.value]) + elif isinstance(n, ElementaryNode): + return n.value + else: + return n + + if id_loop_detect is None: + id_loop_detect = [] + result = None + + if not isinstance(node, BaseNode): + return None + + assert node.ast_id + if node.ast_id in id_loop_detect: + return None # Loop detected + id_loop_detect += [node.ast_id] + + # Try to evaluate the value of the node + if isinstance(node, IdNode): + result = quick_resolve(node) + + elif isinstance(node, ElementaryNode): + result = node.value + + elif isinstance(node, NotNode): + result = self.resolve_node(node.value, include_unknown_args, id_loop_detect) + if isinstance(result, bool): + result = not result + + elif isinstance(node, ArrayNode): + result = node.args.arguments.copy() + + elif isinstance(node, ArgumentNode): + result = node.arguments.copy() + + elif isinstance(node, ArithmeticNode): + if node.operation != 'add': + return None # Only handle string and array concats + l = quick_resolve(node.left) + r = quick_resolve(node.right) + if isinstance(l, str) and isinstance(r, str): + result = l + r # String concatenation detected + else: + result = self.flatten_args(l, include_unknown_args, id_loop_detect) + self.flatten_args(r, include_unknown_args, id_loop_detect) + + elif isinstance(node, MethodNode): + src = quick_resolve(node.source_object) + margs = self.flatten_args(node.args.arguments, include_unknown_args, id_loop_detect) + mkwargs = {} # type: T.Dict[str, TYPE_nvar] + try: + if isinstance(src, str): + result = StringHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + elif isinstance(src, bool): + result = BooleanHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + elif isinstance(src, int): + result = IntegerHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + elif isinstance(src, list): + result = ArrayHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + elif isinstance(src, dict): + result = DictHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + except mesonlib.MesonException: + return None + + # Ensure that the result is fully resolved (no more nodes) + if isinstance(result, BaseNode): + result = self.resolve_node(result, include_unknown_args, id_loop_detect) + elif isinstance(result, list): + new_res = [] # type: T.List[TYPE_nvar] + for i in result: + if isinstance(i, BaseNode): + resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) + if resolved is not None: + new_res += self.flatten_args(resolved, include_unknown_args, id_loop_detect) + else: + new_res += [i] + result = new_res + + return result + + def flatten_args(self, args_raw: T.Union[TYPE_nvar, T.Sequence[TYPE_nvar]], include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.List[TYPE_nvar]: + # Make sure we are always dealing with lists + if isinstance(args_raw, list): + args = args_raw + else: + args = [args_raw] + + flattened_args = [] # type: T.List[TYPE_nvar] + + # Resolve the contents of args + for i in args: + if isinstance(i, BaseNode): + resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) + if resolved is not None: + if not isinstance(resolved, list): + resolved = [resolved] + flattened_args += resolved + elif isinstance(i, (str, bool, int, float)) or include_unknown_args: + flattened_args += [i] + return flattened_args + + def flatten_kwargs(self, kwargs: T.Dict[str, TYPE_nvar], include_unknown_args: bool = False) -> T.Dict[str, TYPE_nvar]: + flattened_kwargs = {} + for key, val in kwargs.items(): + if isinstance(val, BaseNode): + resolved = self.resolve_node(val, include_unknown_args) + if resolved is not None: + flattened_kwargs[key] = resolved + elif isinstance(val, (str, bool, int, float)) or include_unknown_args: + flattened_kwargs[key] = val + return flattened_kwargs + + def evaluate_testcase(self, node: TestCaseClauseNode) -> Disabler | None: + return Disabler(subproject=self.subproject) diff --git a/devtools/meson/mesonbuild/ast/introspection.py b/devtools/meson/mesonbuild/ast/introspection.py new file mode 100644 index 0000000..d520382 --- /dev/null +++ b/devtools/meson/mesonbuild/ast/introspection.py @@ -0,0 +1,383 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool + +from __future__ import annotations +import argparse +import copy +import os +import typing as T + +from .. import compilers, environment, mesonlib, optinterpreter +from .. import coredata as cdata +from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary +from ..compilers import detect_compiler_for +from ..interpreterbase import InvalidArguments +from ..mesonlib import MachineChoice, OptionKey +from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode +from .interpreter import AstInterpreter + +if T.TYPE_CHECKING: + from ..build import BuildTarget + from ..interpreterbase import TYPE_nvar + from .visitor import AstVisitor + + +# TODO: it would be nice to not have to duplicate this +BUILD_TARGET_FUNCTIONS = [ + 'executable', 'jar', 'library', 'shared_library', 'shared_module', + 'static_library', 'both_libraries' +] + +class IntrospectionHelper(argparse.Namespace): + # mimic an argparse namespace + def __init__(self, cross_file: str): + super().__init__() + self.cross_file = cross_file # type: str + self.native_file = None # type: str + self.cmd_line_options = {} # type: T.Dict[str, str] + + def __eq__(self, other: object) -> bool: + return NotImplemented + +class IntrospectionInterpreter(AstInterpreter): + # Interpreter to detect the options without a build directory + # Most of the code is stolen from interpreter.Interpreter + def __init__(self, + source_root: str, + subdir: str, + backend: str, + visitors: T.Optional[T.List[AstVisitor]] = None, + cross_file: T.Optional[str] = None, + subproject: str = '', + subproject_dir: str = 'subprojects', + env: T.Optional[environment.Environment] = None): + visitors = visitors if visitors is not None else [] + super().__init__(source_root, subdir, subproject, visitors=visitors) + + options = IntrospectionHelper(cross_file) + self.cross_file = cross_file + if env is None: + self.environment = environment.Environment(source_root, None, options) + else: + self.environment = env + self.subproject_dir = subproject_dir + self.coredata = self.environment.get_coredata() + self.backend = backend + self.default_options = {OptionKey('backend'): self.backend} + self.project_data = {} # type: T.Dict[str, T.Any] + self.targets = [] # type: T.List[T.Dict[str, T.Any]] + self.dependencies = [] # type: T.List[T.Dict[str, T.Any]] + self.project_node = None # type: BaseNode + + self.funcs.update({ + 'add_languages': self.func_add_languages, + 'dependency': self.func_dependency, + 'executable': self.func_executable, + 'jar': self.func_jar, + 'library': self.func_library, + 'project': self.func_project, + 'shared_library': self.func_shared_lib, + 'shared_module': self.func_shared_module, + 'static_library': self.func_static_lib, + 'both_libraries': self.func_both_lib, + }) + + def func_project(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + if self.project_node: + raise InvalidArguments('Second call to project()') + self.project_node = node + if len(args) < 1: + raise InvalidArguments('Not enough arguments to project(). Needs at least the project name.') + + proj_name = args[0] + proj_vers = kwargs.get('version', 'undefined') + proj_langs = self.flatten_args(args[1:]) + if isinstance(proj_vers, ElementaryNode): + proj_vers = proj_vers.value + if not isinstance(proj_vers, str): + proj_vers = 'undefined' + self.project_data = {'descriptive_name': proj_name, 'version': proj_vers} + + optfile = os.path.join(self.source_root, self.subdir, 'meson.options') + if not os.path.exists(optfile): + optfile = os.path.join(self.source_root, self.subdir, 'meson_options.txt') + if os.path.exists(optfile): + oi = optinterpreter.OptionInterpreter(self.subproject) + oi.process(optfile) + self.coredata.update_project_options(oi.options) + + def_opts = self.flatten_args(kwargs.get('default_options', [])) + _project_default_options = mesonlib.stringlistify(def_opts) + self.project_default_options = cdata.create_options_dict(_project_default_options, self.subproject) + self.default_options.update(self.project_default_options) + self.coredata.set_default_options(self.default_options, self.subproject, self.environment) + + if not self.is_subproject() and 'subproject_dir' in kwargs: + spdirname = kwargs['subproject_dir'] + if isinstance(spdirname, StringNode): + assert isinstance(spdirname.value, str) + self.subproject_dir = spdirname.value + if not self.is_subproject(): + self.project_data['subprojects'] = [] + subprojects_dir = os.path.join(self.source_root, self.subproject_dir) + if os.path.isdir(subprojects_dir): + for i in os.listdir(subprojects_dir): + if os.path.isdir(os.path.join(subprojects_dir, i)): + self.do_subproject(i) + + self.coredata.init_backend_options(self.backend) + options = {k: v for k, v in self.environment.options.items() if k.is_backend()} + + self.coredata.set_options(options) + self._add_languages(proj_langs, True, MachineChoice.HOST) + self._add_languages(proj_langs, True, MachineChoice.BUILD) + + def do_subproject(self, dirname: str) -> None: + subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) + subpr = os.path.join(subproject_dir_abs, dirname) + try: + subi = IntrospectionInterpreter(subpr, '', self.backend, cross_file=self.cross_file, subproject=dirname, subproject_dir=self.subproject_dir, env=self.environment, visitors=self.visitors) + subi.analyze() + subi.project_data['name'] = dirname + self.project_data['subprojects'] += [subi.project_data] + except (mesonlib.MesonException, RuntimeError): + return + + def func_add_languages(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + kwargs = self.flatten_kwargs(kwargs) + required = kwargs.get('required', True) + if isinstance(required, cdata.UserFeatureOption): + required = required.is_enabled() + if 'native' in kwargs: + native = kwargs.get('native', False) + self._add_languages(args, required, MachineChoice.BUILD if native else MachineChoice.HOST) + else: + for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]: + self._add_languages(args, required, for_machine) + + def _add_languages(self, raw_langs: T.List[TYPE_nvar], required: bool, for_machine: MachineChoice) -> None: + langs = [] # type: T.List[str] + for l in self.flatten_args(raw_langs): + if isinstance(l, str): + langs.append(l) + elif isinstance(l, StringNode): + langs.append(l.value) + + for lang in sorted(langs, key=compilers.sort_clink): + lang = lang.lower() + if lang not in self.coredata.compilers[for_machine]: + try: + comp = detect_compiler_for(self.environment, lang, for_machine, True) + except mesonlib.MesonException: + # do we even care about introspecting this language? + if required: + raise + else: + continue + if self.subproject: + options = {} + for k in comp.get_options(): + v = copy.copy(self.coredata.options[k]) + k = k.evolve(subproject=self.subproject) + options[k] = v + self.coredata.add_compiler_options(options, lang, for_machine, self.environment) + + def func_dependency(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + args = self.flatten_args(args) + kwargs = self.flatten_kwargs(kwargs) + if not args: + return + name = args[0] + has_fallback = 'fallback' in kwargs + required = kwargs.get('required', True) + version = kwargs.get('version', []) + if not isinstance(version, list): + version = [version] + if isinstance(required, ElementaryNode): + required = required.value + if not isinstance(required, bool): + required = False + self.dependencies += [{ + 'name': name, + 'required': required, + 'version': version, + 'has_fallback': has_fallback, + 'conditional': node.condition_level > 0, + 'node': node + }] + + def build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs_raw: T.Dict[str, TYPE_nvar], targetclass: T.Type[BuildTarget]) -> T.Optional[T.Dict[str, T.Any]]: + args = self.flatten_args(args) + if not args or not isinstance(args[0], str): + return None + name = args[0] + srcqueue = [node] + extra_queue = [] + + # Process the sources BEFORE flattening the kwargs, to preserve the original nodes + if 'sources' in kwargs_raw: + srcqueue += mesonlib.listify(kwargs_raw['sources']) + + if 'extra_files' in kwargs_raw: + extra_queue += mesonlib.listify(kwargs_raw['extra_files']) + + kwargs = self.flatten_kwargs(kwargs_raw, True) + + def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: + res = [] # type: T.List[BaseNode] + while inqueue: + curr = inqueue.pop(0) + arg_node = None + assert isinstance(curr, BaseNode) + if isinstance(curr, FunctionNode): + arg_node = curr.args + elif isinstance(curr, ArrayNode): + arg_node = curr.args + elif isinstance(curr, IdNode): + # Try to resolve the ID and append the node to the queue + assert isinstance(curr.value, str) + var_name = curr.value + if var_name in self.assignments: + tmp_node = self.assignments[var_name] + if isinstance(tmp_node, (ArrayNode, IdNode, FunctionNode)): + inqueue += [tmp_node] + elif isinstance(curr, ArithmeticNode): + inqueue += [curr.left, curr.right] + if arg_node is None: + continue + arg_nodes = arg_node.arguments.copy() + # Pop the first element if the function is a build target function + if isinstance(curr, FunctionNode) and curr.func_name in BUILD_TARGET_FUNCTIONS: + arg_nodes.pop(0) + elementary_nodes = [x for x in arg_nodes if isinstance(x, (str, StringNode))] + inqueue += [x for x in arg_nodes if isinstance(x, (FunctionNode, ArrayNode, IdNode, ArithmeticNode))] + if elementary_nodes: + res += [curr] + return res + + source_nodes = traverse_nodes(srcqueue) + extraf_nodes = traverse_nodes(extra_queue) + + # Make sure nothing can crash when creating the build class + kwargs_reduced = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs and k in {'install', 'build_by_default', 'build_always'}} + kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()} + kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)} + for_machine = MachineChoice.HOST + objects = [] # type: T.List[T.Any] + empty_sources = [] # type: T.List[T.Any] + # Passing the unresolved sources list causes errors + kwargs_reduced['_allow_no_sources'] = True + target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, [], objects, + self.environment, self.coredata.compilers[for_machine], kwargs_reduced) + target.process_compilers_late() + + new_target = { + 'name': target.get_basename(), + 'id': target.get_id(), + 'type': target.get_typename(), + 'defined_in': os.path.normpath(os.path.join(self.source_root, self.subdir, environment.build_filename)), + 'subdir': self.subdir, + 'build_by_default': target.build_by_default, + 'installed': target.should_install(), + 'outputs': target.get_outputs(), + 'sources': source_nodes, + 'extra_files': extraf_nodes, + 'kwargs': kwargs, + 'node': node, + } + + self.targets += [new_target] + return new_target + + def build_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + default_library = self.coredata.get_option(OptionKey('default_library')) + if default_library == 'shared': + return self.build_target(node, args, kwargs, SharedLibrary) + elif default_library == 'static': + return self.build_target(node, args, kwargs, StaticLibrary) + elif default_library == 'both': + return self.build_target(node, args, kwargs, SharedLibrary) + return None + + def func_executable(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_target(node, args, kwargs, Executable) + + def func_static_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_target(node, args, kwargs, StaticLibrary) + + def func_shared_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_target(node, args, kwargs, SharedLibrary) + + def func_both_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_target(node, args, kwargs, SharedLibrary) + + def func_shared_module(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_target(node, args, kwargs, SharedModule) + + def func_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_library(node, args, kwargs) + + def func_jar(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + return self.build_target(node, args, kwargs, Jar) + + def func_build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + if 'target_type' not in kwargs: + return None + target_type = kwargs.pop('target_type') + if isinstance(target_type, ElementaryNode): + target_type = target_type.value + if target_type == 'executable': + return self.build_target(node, args, kwargs, Executable) + elif target_type == 'shared_library': + return self.build_target(node, args, kwargs, SharedLibrary) + elif target_type == 'static_library': + return self.build_target(node, args, kwargs, StaticLibrary) + elif target_type == 'both_libraries': + return self.build_target(node, args, kwargs, SharedLibrary) + elif target_type == 'library': + return self.build_library(node, args, kwargs) + elif target_type == 'jar': + return self.build_target(node, args, kwargs, Jar) + return None + + def is_subproject(self) -> bool: + return self.subproject != '' + + def analyze(self) -> None: + self.load_root_meson_file() + self.sanity_check_ast() + self.parse_project() + self.run() + + def extract_subproject_dir(self) -> T.Optional[str]: + '''Fast path to extract subproject_dir kwarg. + This is faster than self.parse_project() which also initialize options + and also calls parse_project() on every subproject. + ''' + if not self.ast.lines: + return + project = self.ast.lines[0] + # first line is always project() + if not isinstance(project, FunctionNode): + return + for kw, val in project.args.kwargs.items(): + assert isinstance(kw, IdNode), 'for mypy' + if kw.value == 'subproject_dir': + # mypy does not understand "and isinstance" + if isinstance(val, StringNode): + return val.value + return None diff --git a/devtools/meson/mesonbuild/ast/postprocess.py b/devtools/meson/mesonbuild/ast/postprocess.py new file mode 100644 index 0000000..09c339d --- /dev/null +++ b/devtools/meson/mesonbuild/ast/postprocess.py @@ -0,0 +1,120 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool +from __future__ import annotations + +from .visitor import AstVisitor +import typing as T + +if T.TYPE_CHECKING: + from .. import mparser + +class AstIndentationGenerator(AstVisitor): + def __init__(self) -> None: + self.level = 0 + + def visit_default_func(self, node: mparser.BaseNode) -> None: + # Store the current level in the node + node.level = self.level + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + self.visit_default_func(node) + self.level += 1 + node.args.accept(self) + self.level -= 1 + + def visit_DictNode(self, node: mparser.DictNode) -> None: + self.visit_default_func(node) + self.level += 1 + node.args.accept(self) + self.level -= 1 + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + self.visit_default_func(node) + node.source_object.accept(self) + self.level += 1 + node.args.accept(self) + self.level -= 1 + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + self.visit_default_func(node) + self.level += 1 + node.args.accept(self) + self.level -= 1 + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + self.visit_default_func(node) + self.level += 1 + node.items.accept(self) + node.block.accept(self) + self.level -= 1 + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + self.visit_default_func(node) + for i in node.ifs: + i.accept(self) + if node.elseblock: + self.level += 1 + node.elseblock.accept(self) + self.level -= 1 + + def visit_IfNode(self, node: mparser.IfNode) -> None: + self.visit_default_func(node) + self.level += 1 + node.condition.accept(self) + node.block.accept(self) + self.level -= 1 + +class AstIDGenerator(AstVisitor): + def __init__(self) -> None: + self.counter = {} # type: T.Dict[str, int] + + def visit_default_func(self, node: mparser.BaseNode) -> None: + name = type(node).__name__ + if name not in self.counter: + self.counter[name] = 0 + node.ast_id = name + '#' + str(self.counter[name]) + self.counter[name] += 1 + +class AstConditionLevel(AstVisitor): + def __init__(self) -> None: + self.condition_level = 0 + + def visit_default_func(self, node: mparser.BaseNode) -> None: + node.condition_level = self.condition_level + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + self.visit_default_func(node) + self.condition_level += 1 + node.items.accept(self) + node.block.accept(self) + self.condition_level -= 1 + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + self.visit_default_func(node) + for i in node.ifs: + i.accept(self) + if node.elseblock: + self.condition_level += 1 + node.elseblock.accept(self) + self.condition_level -= 1 + + def visit_IfNode(self, node: mparser.IfNode) -> None: + self.visit_default_func(node) + self.condition_level += 1 + node.condition.accept(self) + node.block.accept(self) + self.condition_level -= 1 diff --git a/devtools/meson/mesonbuild/ast/printer.py b/devtools/meson/mesonbuild/ast/printer.py new file mode 100644 index 0000000..579a83d --- /dev/null +++ b/devtools/meson/mesonbuild/ast/printer.py @@ -0,0 +1,399 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool +from __future__ import annotations + +from .. import mparser +from .visitor import AstVisitor +import re +import typing as T + +arithmic_map = { + 'add': '+', + 'sub': '-', + 'mod': '%', + 'mul': '*', + 'div': '/' +} + +class AstPrinter(AstVisitor): + def __init__(self, indent: int = 2, arg_newline_cutoff: int = 5, update_ast_line_nos: bool = False): + self.result = '' + self.indent = indent + self.arg_newline_cutoff = arg_newline_cutoff + self.ci = '' + self.is_newline = True + self.last_level = 0 + self.curr_line = 1 if update_ast_line_nos else None + + def post_process(self) -> None: + self.result = re.sub(r'\s+\n', '\n', self.result) + + def append(self, data: str, node: mparser.BaseNode) -> None: + self.last_level = node.level + if self.is_newline: + self.result += ' ' * (node.level * self.indent) + self.result += data + self.is_newline = False + + def append_padded(self, data: str, node: mparser.BaseNode) -> None: + if self.result and self.result[-1] not in [' ', '\n']: + data = ' ' + data + self.append(data + ' ', node) + + def newline(self) -> None: + self.result += '\n' + self.is_newline = True + if self.curr_line is not None: + self.curr_line += 1 + + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: + self.append('true' if node.value else 'false', node) + node.lineno = self.curr_line or node.lineno + + def visit_IdNode(self, node: mparser.IdNode) -> None: + assert isinstance(node.value, str) + self.append(node.value, node) + node.lineno = self.curr_line or node.lineno + + def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.append(str(node.value), node) + node.lineno = self.curr_line or node.lineno + + def escape(self, val: str) -> str: + return val.translate(str.maketrans({'\'': '\\\'', + '\\': '\\\\'})) + + def visit_StringNode(self, node: mparser.StringNode) -> None: + assert isinstance(node.value, str) + self.append("'" + self.escape(node.value) + "'", node) + node.lineno = self.curr_line or node.lineno + + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: + assert isinstance(node.value, str) + self.append("f'" + node.value + "'", node) + node.lineno = self.curr_line or node.lineno + + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: + self.append('continue', node) + node.lineno = self.curr_line or node.lineno + + def visit_BreakNode(self, node: mparser.BreakNode) -> None: + self.append('break', node) + node.lineno = self.curr_line or node.lineno + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append('[', node) + node.args.accept(self) + self.append(']', node) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append('{', node) + node.args.accept(self) + self.append('}', node) + + def visit_OrNode(self, node: mparser.OrNode) -> None: + node.left.accept(self) + self.append_padded('or', node) + node.lineno = self.curr_line or node.lineno + node.right.accept(self) + + def visit_AndNode(self, node: mparser.AndNode) -> None: + node.left.accept(self) + self.append_padded('and', node) + node.lineno = self.curr_line or node.lineno + node.right.accept(self) + + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: + node.left.accept(self) + self.append_padded(node.ctype, node) + node.lineno = self.curr_line or node.lineno + node.right.accept(self) + + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: + node.left.accept(self) + self.append_padded(arithmic_map[node.operation], node) + node.lineno = self.curr_line or node.lineno + node.right.accept(self) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append_padded('not', node) + node.value.accept(self) + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + node.lineno = self.curr_line or node.lineno + for i in node.lines: + i.accept(self) + self.newline() + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + node.iobject.accept(self) + node.lineno = self.curr_line or node.lineno + self.append('[', node) + node.index.accept(self) + self.append(']', node) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + node.lineno = self.curr_line or node.lineno + node.source_object.accept(self) + self.append('.' + node.name + '(', node) + node.args.accept(self) + self.append(')', node) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append(node.func_name + '(', node) + node.args.accept(self) + self.append(')', node) + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append(node.var_name + ' = ', node) + node.value.accept(self) + + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append(node.var_name + ' += ', node) + node.value.accept(self) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append_padded('foreach', node) + self.append_padded(', '.join(node.varnames), node) + self.append_padded(':', node) + node.items.accept(self) + self.newline() + node.block.accept(self) + self.append('endforeach', node) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + node.lineno = self.curr_line or node.lineno + prefix = '' + for i in node.ifs: + self.append_padded(prefix + 'if', node) + prefix = 'el' + i.accept(self) + if not isinstance(node.elseblock, mparser.EmptyNode): + self.append('else', node) + node.elseblock.accept(self) + self.append('endif', node) + + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: + node.lineno = self.curr_line or node.lineno + self.append_padded('-', node) + node.value.accept(self) + + def visit_IfNode(self, node: mparser.IfNode) -> None: + node.lineno = self.curr_line or node.lineno + node.condition.accept(self) + self.newline() + node.block.accept(self) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + node.lineno = self.curr_line or node.lineno + node.condition.accept(self) + self.append_padded('?', node) + node.trueblock.accept(self) + self.append_padded(':', node) + node.falseblock.accept(self) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + node.lineno = self.curr_line or node.lineno + break_args = (len(node.arguments) + len(node.kwargs)) > self.arg_newline_cutoff + for i in node.arguments + list(node.kwargs.values()): + if not isinstance(i, (mparser.ElementaryNode, mparser.IndexNode)): + break_args = True + if break_args: + self.newline() + for i in node.arguments: + i.accept(self) + self.append(', ', node) + if break_args: + self.newline() + for key, val in node.kwargs.items(): + key.accept(self) + self.append_padded(':', node) + val.accept(self) + self.append(', ', node) + if break_args: + self.newline() + if break_args: + self.result = re.sub(r', \n$', '\n', self.result) + else: + self.result = re.sub(r', $', '', self.result) + +class AstJSONPrinter(AstVisitor): + def __init__(self) -> None: + self.result = {} # type: T.Dict[str, T.Any] + self.current = self.result + + def _accept(self, key: str, node: mparser.BaseNode) -> None: + old = self.current + data = {} # type: T.Dict[str, T.Any] + self.current = data + node.accept(self) + self.current = old + self.current[key] = data + + def _accept_list(self, key: str, nodes: T.Sequence[mparser.BaseNode]) -> None: + old = self.current + datalist = [] # type: T.List[T.Dict[str, T.Any]] + for i in nodes: + self.current = {} + i.accept(self) + datalist += [self.current] + self.current = old + self.current[key] = datalist + + def _raw_accept(self, node: mparser.BaseNode, data: T.Dict[str, T.Any]) -> None: + old = self.current + self.current = data + node.accept(self) + self.current = old + + def setbase(self, node: mparser.BaseNode) -> None: + self.current['node'] = type(node).__name__ + self.current['lineno'] = node.lineno + self.current['colno'] = node.colno + self.current['end_lineno'] = node.end_lineno + self.current['end_colno'] = node.end_colno + + def visit_default_func(self, node: mparser.BaseNode) -> None: + self.setbase(node) + + def gen_ElementaryNode(self, node: mparser.ElementaryNode) -> None: + self.current['value'] = node.value + self.setbase(node) + + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: + self.gen_ElementaryNode(node) + + def visit_IdNode(self, node: mparser.IdNode) -> None: + self.gen_ElementaryNode(node) + + def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.gen_ElementaryNode(node) + + def visit_StringNode(self, node: mparser.StringNode) -> None: + self.gen_ElementaryNode(node) + + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: + self.gen_ElementaryNode(node) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + self._accept('args', node.args) + self.setbase(node) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + self._accept('args', node.args) + self.setbase(node) + + def visit_OrNode(self, node: mparser.OrNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.setbase(node) + + def visit_AndNode(self, node: mparser.AndNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.setbase(node) + + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.current['ctype'] = node.ctype + self.setbase(node) + + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: + self._accept('left', node.left) + self._accept('right', node.right) + self.current['op'] = arithmic_map[node.operation] + self.setbase(node) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + self._accept('right', node.value) + self.setbase(node) + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + self._accept_list('lines', node.lines) + self.setbase(node) + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + self._accept('object', node.iobject) + self._accept('index', node.index) + self.setbase(node) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + self._accept('object', node.source_object) + self._accept('args', node.args) + self.current['name'] = node.name + self.setbase(node) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + self._accept('args', node.args) + self.current['name'] = node.func_name + self.setbase(node) + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + self._accept('value', node.value) + self.current['var_name'] = node.var_name + self.setbase(node) + + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: + self._accept('value', node.value) + self.current['var_name'] = node.var_name + self.setbase(node) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + self._accept('items', node.items) + self._accept('block', node.block) + self.current['varnames'] = node.varnames + self.setbase(node) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + self._accept_list('ifs', node.ifs) + self._accept('else', node.elseblock) + self.setbase(node) + + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: + self._accept('right', node.value) + self.setbase(node) + + def visit_IfNode(self, node: mparser.IfNode) -> None: + self._accept('condition', node.condition) + self._accept('block', node.block) + self.setbase(node) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + self._accept('condition', node.condition) + self._accept('true', node.trueblock) + self._accept('false', node.falseblock) + self.setbase(node) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + self._accept_list('positional', node.arguments) + kwargs_list = [] # type: T.List[T.Dict[str, T.Dict[str, T.Any]]] + for key, val in node.kwargs.items(): + key_res = {} # type: T.Dict[str, T.Any] + val_res = {} # type: T.Dict[str, T.Any] + self._raw_accept(key, key_res) + self._raw_accept(val, val_res) + kwargs_list += [{'key': key_res, 'val': val_res}] + self.current['kwargs'] = kwargs_list + self.setbase(node) diff --git a/devtools/meson/mesonbuild/ast/visitor.py b/devtools/meson/mesonbuild/ast/visitor.py new file mode 100644 index 0000000..8a0e77b --- /dev/null +++ b/devtools/meson/mesonbuild/ast/visitor.py @@ -0,0 +1,146 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool +from __future__ import annotations + +import typing as T + +if T.TYPE_CHECKING: + from .. import mparser + +class AstVisitor: + def __init__(self) -> None: + pass + + def visit_default_func(self, node: mparser.BaseNode) -> None: + pass + + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: + self.visit_default_func(node) + + def visit_IdNode(self, node: mparser.IdNode) -> None: + self.visit_default_func(node) + + def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.visit_default_func(node) + + def visit_StringNode(self, node: mparser.StringNode) -> None: + self.visit_default_func(node) + + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: + self.visit_default_func(node) + + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: + self.visit_default_func(node) + + def visit_BreakNode(self, node: mparser.BreakNode) -> None: + self.visit_default_func(node) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + self.visit_default_func(node) + node.args.accept(self) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + self.visit_default_func(node) + node.args.accept(self) + + def visit_EmptyNode(self, node: mparser.EmptyNode) -> None: + self.visit_default_func(node) + + def visit_OrNode(self, node: mparser.OrNode) -> None: + self.visit_default_func(node) + node.left.accept(self) + node.right.accept(self) + + def visit_AndNode(self, node: mparser.AndNode) -> None: + self.visit_default_func(node) + node.left.accept(self) + node.right.accept(self) + + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: + self.visit_default_func(node) + node.left.accept(self) + node.right.accept(self) + + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: + self.visit_default_func(node) + node.left.accept(self) + node.right.accept(self) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + self.visit_default_func(node) + node.value.accept(self) + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + self.visit_default_func(node) + for i in node.lines: + i.accept(self) + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + self.visit_default_func(node) + node.iobject.accept(self) + node.index.accept(self) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + self.visit_default_func(node) + node.source_object.accept(self) + node.args.accept(self) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + self.visit_default_func(node) + node.args.accept(self) + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + self.visit_default_func(node) + node.value.accept(self) + + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: + self.visit_default_func(node) + node.value.accept(self) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + self.visit_default_func(node) + node.items.accept(self) + node.block.accept(self) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + self.visit_default_func(node) + for i in node.ifs: + i.accept(self) + node.elseblock.accept(self) + + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: + self.visit_default_func(node) + node.value.accept(self) + + def visit_IfNode(self, node: mparser.IfNode) -> None: + self.visit_default_func(node) + node.condition.accept(self) + node.block.accept(self) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + self.visit_default_func(node) + node.condition.accept(self) + node.trueblock.accept(self) + node.falseblock.accept(self) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + self.visit_default_func(node) + for i in node.arguments: + i.accept(self) + for key, val in node.kwargs.items(): + key.accept(self) + val.accept(self) diff --git a/devtools/meson/mesonbuild/backend/__init__.py b/devtools/meson/mesonbuild/backend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/backend/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/backend/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84305b69e0321599e39223f09d540eed91456ecb GIT binary patch literal 159 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/backend/__pycache__/vs2010backend.cpython-37.pyc b/devtools/meson/mesonbuild/backend/__pycache__/vs2010backend.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9608098147bb014d759ac4afcde1504d8bf8b20d GIT binary patch literal 55325 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 UZLFfDy~Q2*Bvlx)rEIzQA54yAU;qFB literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/backend/__pycache__/vs2019backend.cpython-37.pyc b/devtools/meson/mesonbuild/backend/__pycache__/vs2019backend.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..108728cf14a6c6f17c4ff7ea5b1b385338a3edd5 GIT binary patch literal 2658 zcmbVO&2Jk;6rY*>@Oo`0PTJBhK_f%~E8r$oh1x1as7@(WOF&IjU~#qD>}*^+<6U=l zou-y^N~GQ@aYY=QBmV>90RP2YIrYXlC*B)>;HH#A*V;F4XXnlPy*Kau*0)L}m%#Pg z-+yi&gZ39bj4uOKmc}$OnXX?>v+l)}s&Up^3Ft{o5ZP#-t ziOg0(e$Op#i(&;Sfhj54I4++ml?t$TzIolu=_a$PeP*n)xILU&n znZ)V(OFEn^Jxs4IEic^)!ksAQFWGR`y47t8jy8AWERr1=fedk<@rCgajORKG5%DM| z5CioL&Jgb}>^a${i1V-rG3B^(NIZ+@xeKHHoS4MR0k(n~`oA&quk2lfbE7x6S^cJi zNCWYs#`36lc4}%0)uRei))vB5h2|7kLjxqlh7rLU2=)(9GIBr$v`_o&h(Y>jpZJV3 zkVc=hApJXeIY6ytwd_`I-{>3iLFQmkhoo-|@<(Ki9MA(QA8-q-+;|06ynq$AWX zdFcp|p5g@3HnZNdmakTqmU`~PNT!gch2_seJW;&x3^Do?BR&U8pFAq>L&Pm8wjK5m z3hN0R73{-$PAG!7@o6a5;jmegLo!))Nzw3EB4@$$`0KTsbsp{38;Rhl4C{}@ay{ic zKI$-^C5cGu?I=y+q0}c)-x`)veR!Iqr)uZfaek!{#nE0zu3koj2-PILiY~%&5mbG@ z88oKU!vsis%p|-fVP)pjKrikRi@{Q_}XYMXvyXu)(z~0<<&6p=o(~Y%zqa!+|^~z~w zrQJ>>l{1dfE2kp%w_y{1cX*WEDV!NS_+ip+M{%YKQM}ufNvt27Fp&`tvOwkGy+)8K z^Kp`9$_RvjE(%09O1*MN1le{X+rB=hC{w0r!lK-0cjcy8AhYyoGkfg0yXn}gVo9oU zBag~xfT1nZOg1~-rKiKVd@zK0f8t@ZWyMxz8i{R*R45A|l!X{monxrxJe}j4r{Qz7K-X8EV7NrA2yyI&hakvl-6WY=)Y&_s)M;Pl&~Z7mgO(HSC9Z zP&myr18`sf=zZ)cW8KTIMO)p*mt7&eb9bOfWspUB>TZlF)Vx_S6uZ5t+>P$mZ4v3S zFtcbcgE~U6nBI8jL?NjQSn{}=&(Q-E_hi3oV5IAdu-?b7hVf>ja7=ATYm>k-9ax|4 z*z!7ZFpw4H^t>i3O=8#kKw;;}0KXXa5zFX+^%>7W3JmUOyAJU4(9W5%>rCu`peA-j zZHK8Vtt%t!bY5vlM74qGz5q%C31}V(2z(QuKC@4MVoyx4r9J0Ln(>?A;$nr$cVY3U zBNg2{k;Y?p1#1^;Y4s*7)M>Lx@AEgL4QaxM@{V~Rxz70%olJJpUHvZz&jvIQj90!7 z=G~wXZH#u%<@=T~+QS%MjZiK^5GP`kpTOMeRB$6p&qP?>{7F!LtzxR2jGzg_NM6Pb zKSY7FRWWr*dU?$)(5$IvhaybkZIw$p*uCiq@9N^D=3Y-8e&$o;MFLGY4{e9dh~r7} z{+~T64)R_cv?JeFuJ5-K-UZ(CRnhmKbOSMZW8x^01!M)q6%eX4Vu~;lV$2pu*pSo@ zaFM2L2egZDr>Hp0WT($Kro@NJ96H?YW?cymB~pTX4}`L_XPsu;P;^tB*=vhxl*uTn zj+%QDbYHPX2*G6%EFia>WoS~UIv-_ok# literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/backend/backends.py b/devtools/meson/mesonbuild/backend/backends.py new file mode 100644 index 0000000..73741a4 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/backends.py @@ -0,0 +1,2030 @@ +# Copyright 2012-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from collections import OrderedDict +from dataclasses import dataclass, InitVar +from functools import lru_cache +from itertools import chain +from pathlib import Path +import copy +import enum +import json +import os +import pickle +import re +import shutil +import typing as T +import hashlib + +from .. import build +from .. import dependencies +from .. import programs +from .. import mesonlib +from .. import mlog +from ..compilers import LANGUAGES_USING_LDFLAGS, detect +from ..mesonlib import ( + File, MachineChoice, MesonException, OrderedSet, + classify_unity_sources, OptionKey, join_args, + ExecutableSerialisation +) + +if T.TYPE_CHECKING: + from .._typing import ImmutableListProtocol + from ..arglist import CompilerArgs + from ..compilers import Compiler + from ..environment import Environment + from ..interpreter import Interpreter, Test + from ..linkers.linkers import StaticLinker + from ..mesonlib import FileMode, FileOrString + + from typing_extensions import TypedDict + + _ALL_SOURCES_TYPE = T.List[T.Union[File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + + class TargetIntrospectionData(TypedDict): + + language: str + compiler: T.List[str] + parameters: T.List[str] + sources: T.List[str] + generated_sources: T.List[str] + + +# Languages that can mix with C or C++ but don't support unity builds yet +# because the syntax we use for unity builds is specific to C/++/ObjC/++. +# Assembly files cannot be unitified and neither can LLVM IR files +LANGS_CANT_UNITY = ('d', 'fortran', 'vala') + +@dataclass(eq=False) +class RegenInfo: + source_dir: str + build_dir: str + depfiles: T.List[str] + +class TestProtocol(enum.Enum): + + EXITCODE = 0 + TAP = 1 + GTEST = 2 + RUST = 3 + + @classmethod + def from_str(cls, string: str) -> 'TestProtocol': + if string == 'exitcode': + return cls.EXITCODE + elif string == 'tap': + return cls.TAP + elif string == 'gtest': + return cls.GTEST + elif string == 'rust': + return cls.RUST + raise MesonException(f'unknown test format {string}') + + def __str__(self) -> str: + cls = type(self) + if self is cls.EXITCODE: + return 'exitcode' + elif self is cls.GTEST: + return 'gtest' + elif self is cls.RUST: + return 'rust' + return 'tap' + + +@dataclass(eq=False) +class CleanTrees: + ''' + Directories outputted by custom targets that have to be manually cleaned + because on Linux `ninja clean` only deletes empty directories. + ''' + build_dir: str + trees: T.List[str] + +@dataclass(eq=False) +class InstallData: + source_dir: str + build_dir: str + prefix: str + libdir: str + strip_bin: T.List[str] + # TODO: in python 3.8 or with typing_Extensions this could be: + # `T.Union[T.Literal['preserve'], int]`, which would be more accurate. + install_umask: T.Union[str, int] + mesonintrospect: T.List[str] + version: str + + def __post_init__(self) -> None: + self.targets: T.List[TargetInstallData] = [] + self.headers: T.List[InstallDataBase] = [] + self.man: T.List[InstallDataBase] = [] + self.emptydir: T.List[InstallEmptyDir] = [] + self.data: T.List[InstallDataBase] = [] + self.symlinks: T.List[InstallSymlinkData] = [] + self.install_scripts: T.List[ExecutableSerialisation] = [] + self.install_subdirs: T.List[SubdirInstallData] = [] + +@dataclass(eq=False) +class TargetInstallData: + fname: str + outdir: str + outdir_name: InitVar[T.Optional[str]] + strip: bool + install_name_mappings: T.Mapping[str, str] + rpath_dirs_to_remove: T.Set[bytes] + install_rpath: str + # TODO: install_mode should just always be a FileMode object + install_mode: T.Optional['FileMode'] + subproject: str + optional: bool = False + tag: T.Optional[str] = None + can_strip: bool = False + + def __post_init__(self, outdir_name: T.Optional[str]) -> None: + if outdir_name is None: + outdir_name = os.path.join('{prefix}', self.outdir) + self.out_name = os.path.join(outdir_name, os.path.basename(self.fname)) + +@dataclass(eq=False) +class InstallEmptyDir: + path: str + install_mode: 'FileMode' + subproject: str + tag: T.Optional[str] = None + +@dataclass(eq=False) +class InstallDataBase: + path: str + install_path: str + install_path_name: str + install_mode: 'FileMode' + subproject: str + tag: T.Optional[str] = None + data_type: T.Optional[str] = None + +@dataclass(eq=False) +class InstallSymlinkData: + target: str + name: str + install_path: str + subproject: str + tag: T.Optional[str] = None + allow_missing: bool = False + +# cannot use dataclass here because "exclude" is out of order +class SubdirInstallData(InstallDataBase): + def __init__(self, path: str, install_path: str, install_path_name: str, + install_mode: 'FileMode', exclude: T.Tuple[T.Set[str], T.Set[str]], + subproject: str, tag: T.Optional[str] = None, data_type: T.Optional[str] = None): + super().__init__(path, install_path, install_path_name, install_mode, subproject, tag, data_type) + self.exclude = exclude + + +@dataclass(eq=False) +class TestSerialisation: + name: str + project_name: str + suite: T.List[str] + fname: T.List[str] + is_cross_built: bool + exe_wrapper: T.Optional[programs.ExternalProgram] + needs_exe_wrapper: bool + is_parallel: bool + cmd_args: T.List[str] + env: build.EnvironmentVariables + should_fail: bool + timeout: T.Optional[int] + workdir: T.Optional[str] + extra_paths: T.List[str] + protocol: TestProtocol + priority: int + cmd_is_built: bool + cmd_is_exe: bool + depends: T.List[str] + version: str + verbose: bool + + def __post_init__(self) -> None: + if self.exe_wrapper is not None: + assert isinstance(self.exe_wrapper, programs.ExternalProgram) + + +def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']: + if backend == 'ninja': + from . import ninjabackend + return ninjabackend.NinjaBackend(build, interpreter) + elif backend == 'vs': + from . import vs2010backend + return vs2010backend.autodetect_vs_version(build, interpreter) + elif backend == 'vs2010': + from . import vs2010backend + return vs2010backend.Vs2010Backend(build, interpreter) + elif backend == 'vs2012': + from . import vs2012backend + return vs2012backend.Vs2012Backend(build, interpreter) + elif backend == 'vs2013': + from . import vs2013backend + return vs2013backend.Vs2013Backend(build, interpreter) + elif backend == 'vs2015': + from . import vs2015backend + return vs2015backend.Vs2015Backend(build, interpreter) + elif backend == 'vs2017': + from . import vs2017backend + return vs2017backend.Vs2017Backend(build, interpreter) + elif backend == 'vs2019': + from . import vs2019backend + return vs2019backend.Vs2019Backend(build, interpreter) + elif backend == 'vs2022': + from . import vs2022backend + return vs2022backend.Vs2022Backend(build, interpreter) + elif backend == 'xcode': + from . import xcodebackend + return xcodebackend.XCodeBackend(build, interpreter) + elif backend == 'none': + from . import nonebackend + return nonebackend.NoneBackend(build, interpreter) + return None + + +def get_genvslite_backend(genvsname: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']: + if genvsname == 'vs2022': + from . import vs2022backend + return vs2022backend.Vs2022Backend(build, interpreter, gen_lite = True) + return None + +# This class contains the basic functionality that is needed by all backends. +# Feel free to move stuff in and out of it as you see fit. +class Backend: + + environment: T.Optional['Environment'] + name = '' + + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional['Interpreter']): + # Make it possible to construct a dummy backend + # This is used for introspection without a build directory + if build is None: + self.environment = None + return + self.build = build + self.interpreter = interpreter + self.environment = build.environment + self.processed_targets: T.Set[str] = set() + self.build_dir = self.environment.get_build_dir() + self.source_dir = self.environment.get_source_dir() + self.build_to_src = mesonlib.relpath(self.environment.get_source_dir(), + self.environment.get_build_dir()) + self.src_to_build = mesonlib.relpath(self.environment.get_build_dir(), + self.environment.get_source_dir()) + + # If requested via 'capture = True', returns captured compile args per + # target (e.g. captured_args[target]) that can be used later, for example, + # to populate things like intellisense fields in generated visual studio + # projects (as is the case when using '--genvslite'). + # + # 'vslite_ctx' is only provided when + # we expect this backend setup/generation to make use of previously captured + # compile args (as is the case when using '--genvslite'). + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + raise RuntimeError(f'generate is not implemented in {type(self).__name__}') + + def get_target_filename(self, t: T.Union[build.Target, build.CustomTargetIndex], *, warn_multi_output: bool = True) -> str: + if isinstance(t, build.CustomTarget): + if warn_multi_output and len(t.get_outputs()) != 1: + mlog.warning(f'custom_target {t.name!r} has more than one output! ' + f'Using the first one. Consider using `{t.name}[0]`.') + filename = t.get_outputs()[0] + elif isinstance(t, build.CustomTargetIndex): + filename = t.get_outputs()[0] + else: + assert isinstance(t, build.BuildTarget), t + filename = t.get_filename() + return os.path.join(self.get_target_dir(t), filename) + + def get_target_filename_abs(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: + return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)) + + def get_source_dir_include_args(self, target: build.BuildTarget, compiler: 'Compiler', *, absolute_path: bool = False) -> T.List[str]: + curdir = target.get_subdir() + if absolute_path: + lead = self.source_dir + else: + lead = self.build_to_src + tmppath = os.path.normpath(os.path.join(lead, curdir)) + return compiler.get_include_args(tmppath, False) + + def get_build_dir_include_args(self, target: build.BuildTarget, compiler: 'Compiler', *, absolute_path: bool = False) -> T.List[str]: + if absolute_path: + curdir = os.path.join(self.build_dir, target.get_subdir()) + else: + curdir = target.get_subdir() + if curdir == '': + curdir = '.' + return compiler.get_include_args(curdir, False) + + def get_target_filename_for_linking(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> T.Optional[str]: + # On some platforms (msvc for instance), the file that is used for + # dynamic linking is not the same as the dynamic library itself. This + # file is called an import library, and we want to link against that. + # On all other platforms, we link to the library directly. + if isinstance(target, build.SharedLibrary): + link_lib = target.get_import_filename() or target.get_filename() + return os.path.join(self.get_target_dir(target), link_lib) + elif isinstance(target, build.StaticLibrary): + return os.path.join(self.get_target_dir(target), target.get_filename()) + elif isinstance(target, (build.CustomTarget, build.CustomTargetIndex)): + if not target.is_linkable_target(): + raise MesonException(f'Tried to link against custom target "{target.name}", which is not linkable.') + return os.path.join(self.get_target_dir(target), target.get_filename()) + elif isinstance(target, build.Executable): + if target.import_filename: + return os.path.join(self.get_target_dir(target), target.get_import_filename()) + else: + return None + raise AssertionError(f'BUG: Tried to link to {target!r} which is not linkable') + + @lru_cache(maxsize=None) + def get_target_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: + if isinstance(target, build.RunTarget): + # this produces no output, only a dummy top-level name + dirname = '' + elif self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + dirname = target.get_subdir() + else: + dirname = 'meson-out' + return dirname + + def get_target_dir_relative_to(self, t: build.Target, o: build.Target) -> str: + '''Get a target dir relative to another target's directory''' + target_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t)) + othert_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(o)) + return os.path.relpath(target_dir, othert_dir) + + def get_target_source_dir(self, target: build.Target) -> str: + # if target dir is empty, avoid extraneous trailing / from os.path.join() + target_dir = self.get_target_dir(target) + if target_dir: + return os.path.join(self.build_to_src, target_dir) + return self.build_to_src + + def get_target_private_dir(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]) -> str: + return os.path.join(self.get_target_filename(target, warn_multi_output=False) + '.p') + + def get_target_private_dir_abs(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]) -> str: + return os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target)) + + @lru_cache(maxsize=None) + def get_target_generated_dir( + self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex], + gensrc: T.Union[build.CustomTarget, build.CustomTargetIndex, build.GeneratedList], + src: str) -> str: + """ + Takes a BuildTarget, a generator source (CustomTarget or GeneratedList), + and a generated source filename. + Returns the full path of the generated source relative to the build root + """ + # CustomTarget generators output to the build dir of the CustomTarget + if isinstance(gensrc, (build.CustomTarget, build.CustomTargetIndex)): + return os.path.join(self.get_target_dir(gensrc), src) + # GeneratedList generators output to the private build directory of the + # target that the GeneratedList is used in + return os.path.join(self.get_target_private_dir(target), src) + + def get_unity_source_file(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex], + suffix: str, number: int) -> mesonlib.File: + # There is a potential conflict here, but it is unlikely that + # anyone both enables unity builds and has a file called foo-unity.cpp. + osrc = f'{target.name}-unity{number}.{suffix}' + return mesonlib.File.from_built_file(self.get_target_private_dir(target), osrc) + + def generate_unity_files(self, target: build.BuildTarget, unity_src: str) -> T.List[mesonlib.File]: + abs_files: T.List[str] = [] + result: T.List[mesonlib.File] = [] + compsrcs = classify_unity_sources(target.compilers.values(), unity_src) + unity_size = target.get_option(OptionKey('unity_size')) + assert isinstance(unity_size, int), 'for mypy' + + def init_language_file(suffix: str, unity_file_number: int) -> T.TextIO: + unity_src = self.get_unity_source_file(target, suffix, unity_file_number) + outfileabs = unity_src.absolute_path(self.environment.get_source_dir(), + self.environment.get_build_dir()) + outfileabs_tmp = outfileabs + '.tmp' + abs_files.append(outfileabs) + outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp) + if not os.path.exists(outfileabs_tmp_dir): + os.makedirs(outfileabs_tmp_dir) + result.append(unity_src) + return open(outfileabs_tmp, 'w', encoding='utf-8') + + # For each language, generate unity source files and return the list + for comp, srcs in compsrcs.items(): + files_in_current = unity_size + 1 + unity_file_number = 0 + # TODO: this could be simplified with an algorithm that pre-sorts + # the sources into the size of chunks we want + ofile = None + for src in srcs: + if files_in_current >= unity_size: + if ofile: + ofile.close() + ofile = init_language_file(comp.get_default_suffix(), unity_file_number) + unity_file_number += 1 + files_in_current = 0 + ofile.write(f'#include<{src}>\n') + files_in_current += 1 + if ofile: + ofile.close() + + for x in abs_files: + mesonlib.replace_if_different(x, x + '.tmp') + return result + + @staticmethod + def relpath(todir: str, fromdir: str) -> str: + return os.path.relpath(os.path.join('dummyprefixdir', todir), + os.path.join('dummyprefixdir', fromdir)) + + def flatten_object_list(self, target: build.BuildTarget, proj_dir_to_build_root: str = '' + ) -> T.Tuple[T.List[str], T.List[build.BuildTargetTypes]]: + obj_list, deps = self._flatten_object_list(target, target.get_objects(), proj_dir_to_build_root) + return list(dict.fromkeys(obj_list)), deps + + def determine_ext_objs(self, objects: build.ExtractedObjects, proj_dir_to_build_root: str = '') -> T.List[str]: + obj_list, _ = self._flatten_object_list(objects.target, [objects], proj_dir_to_build_root) + return list(dict.fromkeys(obj_list)) + + def _flatten_object_list(self, target: build.BuildTarget, + objects: T.Sequence[T.Union[str, 'File', build.ExtractedObjects]], + proj_dir_to_build_root: str) -> T.Tuple[T.List[str], T.List[build.BuildTargetTypes]]: + obj_list: T.List[str] = [] + deps: T.List[build.BuildTargetTypes] = [] + for obj in objects: + if isinstance(obj, str): + o = os.path.join(proj_dir_to_build_root, + self.build_to_src, target.get_subdir(), obj) + obj_list.append(o) + elif isinstance(obj, mesonlib.File): + if obj.is_built: + o = os.path.join(proj_dir_to_build_root, + obj.rel_to_builddir(self.build_to_src)) + obj_list.append(o) + else: + o = os.path.join(proj_dir_to_build_root, + self.build_to_src) + obj_list.append(obj.rel_to_builddir(o)) + elif isinstance(obj, build.ExtractedObjects): + if obj.recursive: + objs, d = self._flatten_object_list(obj.target, obj.objlist, proj_dir_to_build_root) + obj_list.extend(objs) + deps.extend(d) + obj_list.extend(self._determine_ext_objs(obj, proj_dir_to_build_root)) + deps.append(obj.target) + else: + raise MesonException('Unknown data type in object list.') + return obj_list, deps + + @staticmethod + def is_swift_target(target: build.BuildTarget) -> bool: + for s in target.sources: + if s.endswith('swift'): + return True + return False + + def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]: + result: T.List[str] = [] + for l in target.link_targets: + result.append(self.get_target_private_dir_abs(l)) + return result + + def get_executable_serialisation( + self, cmd: T.Sequence[T.Union[programs.ExternalProgram, build.BuildTarget, build.CustomTarget, File, str]], + workdir: T.Optional[str] = None, + extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, + capture: T.Optional[bool] = None, + feed: T.Optional[bool] = None, + env: T.Optional[build.EnvironmentVariables] = None, + tag: T.Optional[str] = None, + verbose: bool = False, + installdir_map: T.Optional[T.Dict[str, str]] = None) -> 'ExecutableSerialisation': + + # XXX: cmd_args either need to be lowered to strings, or need to be checked for non-string arguments, right? + exe, *raw_cmd_args = cmd + if isinstance(exe, programs.ExternalProgram): + exe_cmd = exe.get_command() + exe_for_machine = exe.for_machine + elif isinstance(exe, build.BuildTarget): + exe_cmd = [self.get_target_filename_abs(exe)] + exe_for_machine = exe.for_machine + elif isinstance(exe, build.CustomTarget): + # The output of a custom target can either be directly runnable + # or not, that is, a script, a native binary or a cross compiled + # binary when exe wrapper is available and when it is not. + # This implementation is not exhaustive but it works in the + # common cases. + exe_cmd = [self.get_target_filename_abs(exe)] + exe_for_machine = MachineChoice.BUILD + elif isinstance(exe, mesonlib.File): + exe_cmd = [exe.rel_to_builddir(self.environment.source_dir)] + exe_for_machine = MachineChoice.BUILD + else: + exe_cmd = [exe] + exe_for_machine = MachineChoice.BUILD + + cmd_args: T.List[str] = [] + for c in raw_cmd_args: + if isinstance(c, programs.ExternalProgram): + p = c.get_path() + assert isinstance(p, str) + cmd_args.append(p) + elif isinstance(c, (build.BuildTarget, build.CustomTarget)): + cmd_args.append(self.get_target_filename_abs(c)) + elif isinstance(c, mesonlib.File): + cmd_args.append(c.rel_to_builddir(self.environment.source_dir)) + else: + cmd_args.append(c) + + machine = self.environment.machines[exe_for_machine] + if machine.is_windows() or machine.is_cygwin(): + extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps or []) + else: + extra_paths = [] + + is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) + if is_cross_built and self.environment.need_exe_wrapper(): + exe_wrapper = self.environment.get_exe_wrapper() + if not exe_wrapper or not exe_wrapper.found(): + msg = 'An exe_wrapper is needed but was not found. Please define one ' \ + 'in cross file and check the command and/or add it to PATH.' + raise MesonException(msg) + else: + if exe_cmd[0].endswith('.jar'): + exe_cmd = ['java', '-jar'] + exe_cmd + elif exe_cmd[0].endswith('.exe') and not (mesonlib.is_windows() or mesonlib.is_cygwin() or mesonlib.is_wsl()): + exe_cmd = ['mono'] + exe_cmd + exe_wrapper = None + + workdir = workdir or self.environment.get_build_dir() + return ExecutableSerialisation(exe_cmd + cmd_args, env, + exe_wrapper, workdir, + extra_paths, capture, feed, tag, verbose, installdir_map) + + def as_meson_exe_cmdline(self, exe: T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram], + cmd_args: T.Sequence[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram]], + workdir: T.Optional[str] = None, + extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, + capture: T.Optional[bool] = None, + feed: T.Optional[bool] = None, + force_serialize: bool = False, + env: T.Optional[build.EnvironmentVariables] = None, + verbose: bool = False) -> T.Tuple[T.Sequence[T.Union[str, File, build.Target, programs.ExternalProgram]], str]: + ''' + Serialize an executable for running with a generator or a custom target + ''' + cmd: T.List[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram]] = [] + cmd.append(exe) + cmd.extend(cmd_args) + es = self.get_executable_serialisation(cmd, workdir, extra_bdeps, capture, feed, env, verbose=verbose) + reasons: T.List[str] = [] + if es.extra_paths: + reasons.append('to set PATH') + + if es.exe_wrapper: + reasons.append('to use exe_wrapper') + + if workdir: + reasons.append('to set workdir') + + if any('\n' in c for c in es.cmd_args): + reasons.append('because command contains newlines') + + if env and env.varnames: + reasons.append('to set env') + + # force_serialize passed to this function means that the VS backend has + # decided it absolutely cannot use real commands. This is "always", + # because it's not clear what will work (other than compilers) and so + # we don't bother to handle a variety of common cases that probably do + # work. + # + # It's also overridden for a few conditions that can't be handled + # inside a command line + + can_use_env = not force_serialize + force_serialize = force_serialize or bool(reasons) + + if capture: + reasons.append('to capture output') + if feed: + reasons.append('to feed input') + + if can_use_env and reasons == ['to set env'] and shutil.which('env'): + envlist = [] + for k, v in env.get_env({}).items(): + envlist.append(f'{k}={v}') + return ['env'] + envlist + es.cmd_args, ', '.join(reasons) + + if not force_serialize: + if not capture and not feed: + return es.cmd_args, '' + args: T.List[str] = [] + if capture: + args += ['--capture', str(capture)] + if feed: + args += ['--feed', str(feed)] + + return ( + self.environment.get_build_command() + ['--internal', 'exe'] + args + ['--'] + es.cmd_args, + ', '.join(reasons) + ) + + if isinstance(exe, (programs.ExternalProgram, + build.BuildTarget, build.CustomTarget)): + basename = os.path.basename(exe.name) + elif isinstance(exe, mesonlib.File): + basename = os.path.basename(exe.fname) + else: + basename = os.path.basename(exe) + + # Can't just use exe.name here; it will likely be run more than once + # Take a digest of the cmd args, env, workdir, capture, and feed. This + # avoids collisions and also makes the name deterministic over + # regenerations which avoids a rebuild by Ninja because the cmdline + # stays the same. + hasher = hashlib.sha1() + if es.env: + es.env.hash(hasher) + hasher.update(bytes(str(es.cmd_args), encoding='utf-8')) + hasher.update(bytes(str(es.workdir), encoding='utf-8')) + hasher.update(bytes(str(capture), encoding='utf-8')) + hasher.update(bytes(str(feed), encoding='utf-8')) + digest = hasher.hexdigest() + scratch_file = f'meson_exe_{basename}_{digest}.dat' + exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file) + with open(exe_data, 'wb') as f: + pickle.dump(es, f) + return (self.environment.get_build_command() + ['--internal', 'exe', '--unpickle', exe_data], + ', '.join(reasons)) + + def serialize_tests(self) -> T.Tuple[str, str]: + test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') + with open(test_data, 'wb') as datafile: + self.write_test_file(datafile) + benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat') + with open(benchmark_data, 'wb') as datafile: + self.write_benchmark_file(datafile) + return test_data, benchmark_data + + def determine_linker_and_stdlib_args(self, target: build.BuildTarget) -> T.Tuple[T.Union['Compiler', 'StaticLinker'], T.List[str]]: + ''' + If we're building a static library, there is only one static linker. + Otherwise, we query the target for the dynamic linker. + ''' + if isinstance(target, build.StaticLibrary): + return self.build.static_linker[target.for_machine], [] + l, stdlib_args = target.get_clink_dynamic_linker_and_stdlibs() + return l, stdlib_args + + @staticmethod + def _libdir_is_system(libdir: str, compilers: T.Mapping[str, 'Compiler'], env: 'Environment') -> bool: + libdir = os.path.normpath(libdir) + for cc in compilers.values(): + if libdir in cc.get_library_dirs(env): + return True + return False + + def get_external_rpath_dirs(self, target: build.BuildTarget) -> T.Set[str]: + args: T.List[str] = [] + for lang in LANGUAGES_USING_LDFLAGS: + try: + e = self.environment.coredata.get_external_link_args(target.for_machine, lang) + if isinstance(e, str): + args.append(e) + else: + args.extend(e) + except Exception: + pass + return self.get_rpath_dirs_from_link_args(args) + + @staticmethod + def get_rpath_dirs_from_link_args(args: T.List[str]) -> T.Set[str]: + dirs: T.Set[str] = set() + # Match rpath formats: + # -Wl,-rpath= + # -Wl,-rpath, + rpath_regex = re.compile(r'-Wl,-rpath[=,]([^,]+)') + # Match solaris style compat runpath formats: + # -Wl,-R + # -Wl,-R, + runpath_regex = re.compile(r'-Wl,-R[,]?([^,]+)') + # Match symbols formats: + # -Wl,--just-symbols= + # -Wl,--just-symbols, + symbols_regex = re.compile(r'-Wl,--just-symbols[=,]([^,]+)') + for arg in args: + rpath_match = rpath_regex.match(arg) + if rpath_match: + for dir in rpath_match.group(1).split(':'): + dirs.add(dir) + runpath_match = runpath_regex.match(arg) + if runpath_match: + for dir in runpath_match.group(1).split(':'): + # The symbols arg is an rpath if the path is a directory + if Path(dir).is_dir(): + dirs.add(dir) + symbols_match = symbols_regex.match(arg) + if symbols_match: + for dir in symbols_match.group(1).split(':'): + # Prevent usage of --just-symbols to specify rpath + if Path(dir).is_dir(): + raise MesonException(f'Invalid arg for --just-symbols, {dir} is a directory.') + return dirs + + @lru_cache(maxsize=None) + def rpaths_for_non_system_absolute_shared_libraries(self, target: build.BuildTarget, exclude_system: bool = True) -> 'ImmutableListProtocol[str]': + paths: OrderedSet[str] = OrderedSet() + srcdir = self.environment.get_source_dir() + + for dep in target.external_deps: + if dep.type_name not in {'library', 'pkgconfig'}: + continue + for libpath in dep.link_args: + # For all link args that are absolute paths to a library file, add RPATH args + if not os.path.isabs(libpath): + continue + libdir = os.path.dirname(libpath) + if exclude_system and self._libdir_is_system(libdir, target.compilers, self.environment): + # No point in adding system paths. + continue + # Don't remove rpaths specified in LDFLAGS. + if libdir in self.get_external_rpath_dirs(target): + continue + # Windows doesn't support rpaths, but we use this function to + # emulate rpaths by setting PATH + # .dll is there for mingw gcc + if os.path.splitext(libpath)[1] not in {'.dll', '.lib', '.so', '.dylib'}: + continue + + try: + commonpath = os.path.commonpath((libdir, srcdir)) + except ValueError: # when paths are on different drives on Windows + commonpath = '' + + if commonpath == srcdir: + rel_to_src = libdir[len(srcdir) + 1:] + assert not os.path.isabs(rel_to_src), f'rel_to_src: {rel_to_src} is absolute' + paths.add(os.path.join(self.build_to_src, rel_to_src)) + else: + paths.add(libdir) + # Don't remove rpaths specified by the dependency + paths.difference_update(self.get_rpath_dirs_from_link_args(dep.link_args)) + for i in chain(target.link_targets, target.link_whole_targets): + if isinstance(i, build.BuildTarget): + paths.update(self.rpaths_for_non_system_absolute_shared_libraries(i, exclude_system)) + return list(paths) + + # This may take other types + def determine_rpath_dirs(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex] + ) -> T.Tuple[str, ...]: + result: OrderedSet[str] + if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + # Need a copy here + result = OrderedSet(target.get_link_dep_subdirs()) + else: + result = OrderedSet() + result.add('meson-out') + if isinstance(target, build.BuildTarget): + result.update(self.rpaths_for_non_system_absolute_shared_libraries(target)) + target.rpath_dirs_to_remove.update([d.encode('utf-8') for d in result]) + return tuple(result) + + @staticmethod + def canonicalize_filename(fname: str) -> str: + parts = Path(fname).parts + hashed = '' + if len(parts) > 5: + temp = '/'.join(parts[-5:]) + # is it shorter to hash the beginning of the path? + if len(fname) > len(temp) + 41: + hashed = hashlib.sha1(fname.encode('utf-8')).hexdigest() + '_' + fname = temp + for ch in ('/', '\\', ':'): + fname = fname.replace(ch, '_') + return hashed + fname + + def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOrString') -> str: + assert isinstance(source, mesonlib.File) + if isinstance(target, build.CompileTarget): + return target.sources_map[source] + build_dir = self.environment.get_build_dir() + rel_src = source.rel_to_builddir(self.build_to_src) + + # foo.vala files compile down to foo.c and then foo.c.o, not foo.vala.o + if rel_src.endswith(('.vala', '.gs')): + # See description in generate_vala_compile for this logic. + if source.is_built: + if os.path.isabs(rel_src): + rel_src = rel_src[len(build_dir) + 1:] + rel_src = os.path.relpath(rel_src, self.get_target_private_dir(target)) + else: + rel_src = os.path.basename(rel_src) + # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. + gen_source = 'meson-generated_' + rel_src[:-5] + '.c' + elif source.is_built: + if os.path.isabs(rel_src): + rel_src = rel_src[len(build_dir) + 1:] + targetdir = self.get_target_private_dir(target) + # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. + gen_source = 'meson-generated_' + os.path.relpath(rel_src, targetdir) + else: + if os.path.isabs(rel_src): + # Use the absolute path directly to avoid file name conflicts + gen_source = rel_src + else: + gen_source = os.path.relpath(os.path.join(build_dir, rel_src), + os.path.join(self.environment.get_source_dir(), target.get_subdir())) + machine = self.environment.machines[target.for_machine] + return self.canonicalize_filename(gen_source) + '.' + machine.get_object_suffix() + + def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_build_root: str) -> T.List[str]: + result: T.List[str] = [] + + targetdir = self.get_target_private_dir(extobj.target) + + # Merge sources and generated sources + raw_sources = list(extobj.srclist) + for gensrc in extobj.genlist: + for r in gensrc.get_outputs(): + path = self.get_target_generated_dir(extobj.target, gensrc, r) + dirpart, fnamepart = os.path.split(path) + raw_sources.append(File(True, dirpart, fnamepart)) + + # Filter out headers and all non-source files + sources: T.List['FileOrString'] = [] + for s in raw_sources: + if self.environment.is_source(s): + sources.append(s) + elif self.environment.is_object(s): + result.append(s.relative_name()) + + # MSVC generate an object file for PCH + if extobj.pch: + for lang, pch in extobj.target.pch.items(): + compiler = extobj.target.compilers[lang] + if compiler.get_argument_syntax() == 'msvc': + objname = self.get_msvc_pch_objname(lang, pch) + result.append(os.path.join(proj_dir_to_build_root, targetdir, objname)) + + # extobj could contain only objects and no sources + if not sources: + return result + + # With unity builds, sources don't map directly to objects, + # we only support extracting all the objects in this mode, + # so just return all object files. + if extobj.target.is_unity: + compsrcs = classify_unity_sources(extobj.target.compilers.values(), sources) + sources = [] + unity_size = extobj.target.get_option(OptionKey('unity_size')) + assert isinstance(unity_size, int), 'for mypy' + + for comp, srcs in compsrcs.items(): + if comp.language in LANGS_CANT_UNITY: + sources += srcs + continue + for i in range(len(srcs) // unity_size + 1): + _src = self.get_unity_source_file(extobj.target, + comp.get_default_suffix(), i) + sources.append(_src) + + for osrc in sources: + objname = self.object_filename_from_source(extobj.target, osrc) + objpath = os.path.join(proj_dir_to_build_root, targetdir, objname) + result.append(objpath) + + return result + + def get_pch_include_args(self, compiler: 'Compiler', target: build.BuildTarget) -> T.List[str]: + args: T.List[str] = [] + pchpath = self.get_target_private_dir(target) + includeargs = compiler.get_include_args(pchpath, False) + p = target.get_pch(compiler.get_language()) + if p: + args += compiler.get_pch_use_args(pchpath, p[0]) + return includeargs + args + + def get_msvc_pch_objname(self, lang: str, pch: T.List[str]) -> str: + if len(pch) == 1: + # Same name as in create_msvc_pch_implementation() below. + return f'meson_pch-{lang}.obj' + return os.path.splitext(pch[1])[0] + '.obj' + + def create_msvc_pch_implementation(self, target: build.BuildTarget, lang: str, pch_header: str) -> str: + # We have to include the language in the file name, otherwise + # pch.c and pch.cpp will both end up as pch.obj in VS backends. + impl_name = f'meson_pch-{lang}.{lang}' + pch_rel_to_build = os.path.join(self.get_target_private_dir(target), impl_name) + # Make sure to prepend the build dir, since the working directory is + # not defined. Otherwise, we might create the file in the wrong path. + pch_file = os.path.join(self.build_dir, pch_rel_to_build) + os.makedirs(os.path.dirname(pch_file), exist_ok=True) + + content = f'#include "{os.path.basename(pch_header)}"' + pch_file_tmp = pch_file + '.tmp' + with open(pch_file_tmp, 'w', encoding='utf-8') as f: + f.write(content) + mesonlib.replace_if_different(pch_file, pch_file_tmp) + return pch_rel_to_build + + def target_uses_pch(self, target: build.BuildTarget) -> bool: + try: + return T.cast('bool', target.get_option(OptionKey('b_pch'))) + except KeyError: + return False + + @staticmethod + def escape_extra_args(args: T.List[str]) -> T.List[str]: + # all backslashes in defines are doubly-escaped + extra_args: T.List[str] = [] + for arg in args: + if arg.startswith(('-D', '/D')): + arg = arg.replace('\\', '\\\\') + extra_args.append(arg) + + return extra_args + + def get_no_stdlib_args(self, target: 'build.BuildTarget', compiler: 'Compiler') -> T.List[str]: + if compiler.language in self.build.stdlibs[target.for_machine]: + return compiler.get_no_stdinc_args() + return [] + + def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Compiler', no_warn_args: bool = False) -> 'CompilerArgs': + # Create an empty commands list, and start adding arguments from + # various sources in the order in which they must override each other + # starting from hard-coded defaults followed by build options and so on. + commands = compiler.compiler_args() + + copt_proxy = target.get_options() + # First, the trivial ones that are impossible to override. + # + # Add -nostdinc/-nostdinc++ if needed; can't be overridden + commands += self.get_no_stdlib_args(target, compiler) + # Add things like /NOLOGO or -pipe; usually can't be overridden + commands += compiler.get_always_args() + # Only add warning-flags by default if the buildtype enables it, and if + # we weren't explicitly asked to not emit warnings (for Vala, f.ex) + if no_warn_args: + commands += compiler.get_no_warn_args() + else: + # warning_level is a string, but mypy can't determine that + commands += compiler.get_warn_args(T.cast('str', target.get_option(OptionKey('warning_level')))) + # Add -Werror if werror=true is set in the build options set on the + # command-line or default_options inside project(). This only sets the + # action to be done for warnings if/when they are emitted, so it's ok + # to set it after get_no_warn_args() or get_warn_args(). + if target.get_option(OptionKey('werror')): + commands += compiler.get_werror_args() + # Add compile args for c_* or cpp_* build options set on the + # command-line or default_options inside project(). + commands += compiler.get_option_compile_args(copt_proxy) + + # Add buildtype args: optimization level, debugging, etc. + buildtype = target.get_option(OptionKey('buildtype')) + assert isinstance(buildtype, str), 'for mypy' + commands += compiler.get_buildtype_args(buildtype) + + optimization = target.get_option(OptionKey('optimization')) + assert isinstance(optimization, str), 'for mypy' + commands += compiler.get_optimization_args(optimization) + + debug = target.get_option(OptionKey('debug')) + assert isinstance(debug, bool), 'for mypy' + commands += compiler.get_debug_args(debug) + + # Add compile args added using add_project_arguments() + commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) + # Add compile args added using add_global_arguments() + # These override per-project arguments + commands += self.build.get_global_args(compiler, target.for_machine) + # Compile args added from the env: CFLAGS/CXXFLAGS, etc, or the cross + # file. We want these to override all the defaults, but not the + # per-target compile args. + commands += self.environment.coredata.get_external_args(target.for_machine, compiler.get_language()) + # Using both /Z7 or /ZI and /Zi at the same times produces a compiler warning. + # We do not add /Z7 or /ZI by default. If it is being used it is because the user has explicitly enabled it. + # /Zi needs to be removed in that case to avoid cl's warning to that effect (D9025 : overriding '/Zi' with '/ZI') + if ('/Zi' in commands) and (('/ZI' in commands) or ('/Z7' in commands)): + commands.remove('/Zi') + # Always set -fPIC for shared libraries + if isinstance(target, build.SharedLibrary): + commands += compiler.get_pic_args() + # Set -fPIC for static libraries by default unless explicitly disabled + if isinstance(target, build.StaticLibrary) and target.pic: + commands += compiler.get_pic_args() + elif isinstance(target, (build.StaticLibrary, build.Executable)) and target.pie: + commands += compiler.get_pie_args() + # Add compile args needed to find external dependencies. Link args are + # added while generating the link command. + # NOTE: We must preserve the order in which external deps are + # specified, so we reverse the list before iterating over it. + for dep in reversed(target.get_external_deps()): + if not dep.found(): + continue + + if compiler.language == 'vala': + if dep.type_name == 'pkgconfig': + assert isinstance(dep, dependencies.ExternalDependency) + if dep.name == 'glib-2.0' and dep.version_reqs is not None: + for req in dep.version_reqs: + if req.startswith(('>=', '==')): + commands += ['--target-glib', req[2:]] + break + commands += ['--pkg', dep.name] + elif isinstance(dep, dependencies.ExternalLibrary): + commands += dep.get_link_args('vala') + else: + commands += compiler.get_dependency_compile_args(dep) + # Qt needs -fPIC for executables + # XXX: We should move to -fPIC for all executables + if isinstance(target, build.Executable): + commands += dep.get_exe_args(compiler) + # For 'automagic' deps: Boost and GTest. Also dependency('threads'). + # pkg-config puts the thread flags itself via `Cflags:` + # Fortran requires extra include directives. + if compiler.language == 'fortran': + for lt in chain(target.link_targets, target.link_whole_targets): + priv_dir = self.get_target_private_dir(lt) + commands += compiler.get_include_args(priv_dir, False) + return commands + + def build_target_link_arguments(self, compiler: 'Compiler', deps: T.List[build.Target]) -> T.List[str]: + args: T.List[str] = [] + for d in deps: + if not d.is_linkable_target(): + raise RuntimeError(f'Tried to link with a non-library target "{d.get_basename()}".') + arg = self.get_target_filename_for_linking(d) + if not arg: + continue + if compiler.get_language() == 'd': + arg = '-Wl,' + arg + else: + arg = compiler.get_linker_lib_prefix() + arg + args.append(arg) + return args + + def get_mingw_extra_paths(self, target: build.BuildTarget) -> T.List[str]: + paths: OrderedSet[str] = OrderedSet() + # The cross bindir + root = self.environment.properties[target.for_machine].get_root() + if root: + paths.add(os.path.join(root, 'bin')) + # The toolchain bindir + sys_root = self.environment.properties[target.for_machine].get_sys_root() + if sys_root: + paths.add(os.path.join(sys_root, 'bin')) + # Get program and library dirs from all target compilers + if isinstance(target, build.BuildTarget): + for cc in target.compilers.values(): + paths.update(cc.get_program_dirs(self.environment)) + paths.update(cc.get_library_dirs(self.environment)) + return list(paths) + + @classmethod + @lru_cache(maxsize=None) + def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: + """Find paths to all DLLs needed for a given target, since + we link against import libs, and we don't know the actual + path of the DLLs. + + 1. If there are DLLs in the same directory than the .lib dir, use it + 2. If there is a sibbling directory named 'bin' with DLLs in it, use it + """ + results = set() + for dep in target.external_deps: + + if dep.type_name == 'pkgconfig': + # If by chance pkg-config knows the bin dir... + bindir = dep.get_pkgconfig_variable('bindir', [], default='') + if bindir: + results.add(bindir) + + for link_arg in dep.link_args: + if link_arg.startswith(('-l', '-L')): + link_arg = link_arg[2:] + p = Path(link_arg) + if not p.is_absolute(): + continue + + try: + p = p.resolve(strict=True) + except FileNotFoundError: + continue + + for _ in p.parent.glob('*.dll'): + # path contains dlls + results.add(str(p.parent)) + break + + else: + if p.is_file(): + p = p.parent + # Heuristic: replace *last* occurence of '/lib' + binpath = Path('/bin'.join(p.as_posix().rsplit('/lib', maxsplit=1))) + for _ in binpath.glob('*.dll'): + results.add(str(binpath)) + break + + for i in chain(target.link_targets, target.link_whole_targets): + if isinstance(i, build.BuildTarget): + results.update(cls.extract_dll_paths(i)) + + return results + + def determine_windows_extra_paths( + self, target: T.Union[build.BuildTarget, build.CustomTarget, programs.ExternalProgram, mesonlib.File, str], + extra_bdeps: T.Sequence[T.Union[build.BuildTarget, build.CustomTarget]]) -> T.List[str]: + """On Windows there is no such thing as an rpath. + + We must determine all locations of DLLs that this exe + links to and return them so they can be used in unit + tests. + """ + result: T.Set[str] = set() + prospectives: T.Set[build.BuildTargetTypes] = set() + if isinstance(target, build.BuildTarget): + prospectives.update(target.get_transitive_link_deps()) + # External deps + result.update(self.extract_dll_paths(target)) + + for bdep in extra_bdeps: + prospectives.add(bdep) + if isinstance(bdep, build.BuildTarget): + prospectives.update(bdep.get_transitive_link_deps()) + # Internal deps + for ld in prospectives: + dirseg = os.path.join(self.environment.get_build_dir(), self.get_target_dir(ld)) + result.add(dirseg) + if (isinstance(target, build.BuildTarget) and + not self.environment.machines.matches_build_machine(target.for_machine)): + result.update(self.get_mingw_extra_paths(target)) + return list(result) + + def write_benchmark_file(self, datafile: T.BinaryIO) -> None: + self.write_test_serialisation(self.build.get_benchmarks(), datafile) + + def write_test_file(self, datafile: T.BinaryIO) -> None: + self.write_test_serialisation(self.build.get_tests(), datafile) + + def create_test_serialisation(self, tests: T.List['Test']) -> T.List[TestSerialisation]: + arr: T.List[TestSerialisation] = [] + for t in sorted(tests, key=lambda tst: -1 * tst.priority): + exe = t.get_exe() + if isinstance(exe, programs.ExternalProgram): + cmd = exe.get_command() + else: + cmd = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))] + if isinstance(exe, (build.BuildTarget, programs.ExternalProgram)): + test_for_machine = exe.for_machine + else: + # E.g. an external verifier or simulator program run on a generated executable. + # Can always be run without a wrapper. + test_for_machine = MachineChoice.BUILD + + # we allow passing compiled executables to tests, which may be cross built. + # We need to consider these as well when considering whether the target is cross or not. + for a in t.cmd_args: + if isinstance(a, build.BuildTarget): + if a.for_machine is MachineChoice.HOST: + test_for_machine = MachineChoice.HOST + break + + is_cross = self.environment.is_cross_build(test_for_machine) + exe_wrapper = self.environment.get_exe_wrapper() + machine = self.environment.machines[exe.for_machine] + if machine.is_windows() or machine.is_cygwin(): + extra_bdeps: T.List[T.Union[build.BuildTarget, build.CustomTarget]] = [] + if isinstance(exe, build.CustomTarget): + extra_bdeps = list(exe.get_transitive_build_target_deps()) + extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps) + for a in t.cmd_args: + if isinstance(a, build.BuildTarget): + for p in self.determine_windows_extra_paths(a, []): + if p not in extra_paths: + extra_paths.append(p) + else: + extra_paths = [] + + cmd_args: T.List[str] = [] + depends: T.Set[build.Target] = set(t.depends) + if isinstance(exe, build.Target): + depends.add(exe) + for a in t.cmd_args: + if isinstance(a, build.Target): + depends.add(a) + elif isinstance(a, build.CustomTargetIndex): + depends.add(a.target) + + if isinstance(a, mesonlib.File): + a = os.path.join(self.environment.get_build_dir(), a.rel_to_builddir(self.build_to_src)) + cmd_args.append(a) + elif isinstance(a, str): + cmd_args.append(a) + elif isinstance(a, (build.Target, build.CustomTargetIndex)): + cmd_args.extend(self.construct_target_rel_paths(a, t.workdir)) + else: + raise MesonException('Bad object in test command.') + + t_env = copy.deepcopy(t.env) + if not machine.is_windows() and not machine.is_cygwin() and not machine.is_darwin(): + ld_lib_path: T.Set[str] = set() + for d in depends: + if isinstance(d, build.BuildTarget): + for l in d.get_all_link_deps(): + if isinstance(l, build.SharedLibrary): + ld_lib_path.add(os.path.join(self.environment.get_build_dir(), l.get_subdir())) + if ld_lib_path: + t_env.prepend('LD_LIBRARY_PATH', list(ld_lib_path), ':') + + ts = TestSerialisation(t.get_name(), t.project_name, t.suite, cmd, is_cross, + exe_wrapper, self.environment.need_exe_wrapper(), + t.is_parallel, cmd_args, t_env, + t.should_fail, t.timeout, t.workdir, + extra_paths, t.protocol, t.priority, + isinstance(exe, build.Target), + isinstance(exe, build.Executable), + [x.get_id() for x in depends], + self.environment.coredata.version, + t.verbose) + arr.append(ts) + return arr + + def write_test_serialisation(self, tests: T.List['Test'], datafile: T.BinaryIO) -> None: + pickle.dump(self.create_test_serialisation(tests), datafile) + + def construct_target_rel_paths(self, t: T.Union[build.Target, build.CustomTargetIndex], workdir: T.Optional[str]) -> T.List[str]: + target_dir = self.get_target_dir(t) + # ensure that test executables can be run when passed as arguments + if isinstance(t, build.Executable) and workdir is None: + target_dir = target_dir or '.' + + if isinstance(t, build.BuildTarget): + outputs = [t.get_filename()] + else: + assert isinstance(t, (build.CustomTarget, build.CustomTargetIndex)) + outputs = t.get_outputs() + + outputs = [os.path.join(target_dir, x) for x in outputs] + if workdir is not None: + assert os.path.isabs(workdir) + outputs = [os.path.join(self.environment.get_build_dir(), x) for x in outputs] + outputs = [os.path.relpath(x, workdir) for x in outputs] + return outputs + + def generate_depmf_install(self, d: InstallData) -> None: + depmf_path = self.build.dep_manifest_name + if depmf_path is None: + option_dir = self.environment.coredata.get_option(OptionKey('licensedir')) + assert isinstance(option_dir, str), 'for mypy' + if option_dir: + depmf_path = os.path.join(option_dir, 'depmf.json') + else: + return + ifilename = os.path.join(self.environment.get_build_dir(), 'depmf.json') + ofilename = os.path.join(self.environment.get_prefix(), depmf_path) + odirname = os.path.join(self.environment.get_prefix(), os.path.dirname(depmf_path)) + out_name = os.path.join('{prefix}', depmf_path) + out_dir = os.path.join('{prefix}', os.path.dirname(depmf_path)) + mfobj = {'type': 'dependency manifest', 'version': '1.0', + 'projects': {k: v.to_json() for k, v in self.build.dep_manifest.items()}} + with open(ifilename, 'w', encoding='utf-8') as f: + f.write(json.dumps(mfobj)) + # Copy file from, to, and with mode unchanged + d.data.append(InstallDataBase(ifilename, ofilename, out_name, None, '', + tag='devel', data_type='depmf')) + for m in self.build.dep_manifest.values(): + for ifilename, name in m.license_files: + ofilename = os.path.join(odirname, name.relative_name()) + out_name = os.path.join(out_dir, name.relative_name()) + d.data.append(InstallDataBase(ifilename, ofilename, out_name, None, + m.subproject, tag='devel', data_type='depmf')) + + def get_regen_filelist(self) -> T.List[str]: + '''List of all files whose alteration means that the build + definition needs to be regenerated.''' + deps = OrderedSet([str(Path(self.build_to_src) / df) + for df in self.interpreter.get_build_def_files()]) + if self.environment.is_cross_build(): + deps.update(self.environment.coredata.cross_files) + deps.update(self.environment.coredata.config_files) + deps.add('meson-private/coredata.dat') + self.check_clock_skew(deps) + return list(deps) + + def generate_regen_info(self) -> None: + deps = self.get_regen_filelist() + regeninfo = RegenInfo(self.environment.get_source_dir(), + self.environment.get_build_dir(), + deps) + filename = os.path.join(self.environment.get_scratch_dir(), + 'regeninfo.dump') + with open(filename, 'wb') as f: + pickle.dump(regeninfo, f) + + def check_clock_skew(self, file_list: T.Iterable[str]) -> None: + # If a file that leads to reconfiguration has a time + # stamp in the future, it will trigger an eternal reconfigure + # loop. + import time + now = time.time() + for f in file_list: + absf = os.path.join(self.environment.get_build_dir(), f) + ftime = os.path.getmtime(absf) + delta = ftime - now + # On Windows disk time stamps sometimes point + # to the future by a minuscule amount, less than + # 0.001 seconds. I don't know why. + if delta > 0.001: + raise MesonException(f'Clock skew detected. File {absf} has a time stamp {delta:.4f}s in the future.') + + def build_target_to_cmd_array(self, bt: T.Union[build.BuildTarget, programs.ExternalProgram]) -> T.List[str]: + if isinstance(bt, build.BuildTarget): + arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(bt))] + else: + arr = bt.get_command() + return arr + + def replace_extra_args(self, args: T.List[str], genlist: 'build.GeneratedList') -> T.List[str]: + final_args: T.List[str] = [] + for a in args: + if a == '@EXTRA_ARGS@': + final_args += genlist.get_extra_args() + else: + final_args.append(a) + return final_args + + def replace_outputs(self, args: T.List[str], private_dir: str, output_list: T.List[str]) -> T.List[str]: + newargs: T.List[str] = [] + regex = re.compile(r'@OUTPUT(\d+)@') + for arg in args: + m = regex.search(arg) + while m is not None: + index = int(m.group(1)) + src = f'@OUTPUT{index}@' + arg = arg.replace(src, os.path.join(private_dir, output_list[index])) + m = regex.search(arg) + newargs.append(arg) + return newargs + + def get_build_by_default_targets(self) -> 'T.OrderedDict[str, T.Union[build.BuildTarget, build.CustomTarget]]': + result: 'T.OrderedDict[str, T.Union[build.BuildTarget, build.CustomTarget]]' = OrderedDict() + # Get all build and custom targets that must be built by default + for name, b in self.build.get_targets().items(): + if b.build_by_default: + result[name] = b + return result + + def get_testlike_targets(self, benchmark: bool = False) -> T.OrderedDict[str, T.Union[build.BuildTarget, build.CustomTarget]]: + result: T.OrderedDict[str, T.Union[build.BuildTarget, build.CustomTarget]] = OrderedDict() + targets = self.build.get_benchmarks() if benchmark else self.build.get_tests() + for t in targets: + exe = t.exe + if isinstance(exe, (build.CustomTarget, build.BuildTarget)): + result[exe.get_id()] = exe + for arg in t.cmd_args: + if not isinstance(arg, (build.CustomTarget, build.BuildTarget)): + continue + result[arg.get_id()] = arg + for dep in t.depends: + assert isinstance(dep, (build.CustomTarget, build.BuildTarget)) + result[dep.get_id()] = dep + return result + + @lru_cache(maxsize=None) + def get_custom_target_provided_by_generated_source(self, generated_source: build.CustomTarget) -> 'ImmutableListProtocol[str]': + libs: T.List[str] = [] + for f in generated_source.get_outputs(): + if self.environment.is_library(f): + libs.append(os.path.join(self.get_target_dir(generated_source), f)) + return libs + + @lru_cache(maxsize=None) + def get_custom_target_provided_libraries(self, target: T.Union[build.BuildTarget, build.CustomTarget]) -> 'ImmutableListProtocol[str]': + libs: T.List[str] = [] + for t in target.get_generated_sources(): + if not isinstance(t, build.CustomTarget): + continue + libs.extend(self.get_custom_target_provided_by_generated_source(t)) + return libs + + def get_custom_target_sources(self, target: build.CustomTarget) -> T.List[str]: + ''' + Custom target sources can be of various object types; strings, File, + BuildTarget, even other CustomTargets. + Returns the path to them relative to the build root directory. + ''' + srcs: T.List[str] = [] + for i in target.get_sources(): + if isinstance(i, str): + fname = [os.path.join(self.build_to_src, target.subdir, i)] + elif isinstance(i, build.BuildTarget): + fname = [self.get_target_filename(i)] + elif isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): + fname = [os.path.join(self.get_custom_target_output_dir(i), p) for p in i.get_outputs()] + elif isinstance(i, build.GeneratedList): + fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outputs()] + elif isinstance(i, build.ExtractedObjects): + fname = self.determine_ext_objs(i) + elif isinstance(i, programs.ExternalProgram): + assert i.found(), "This shouldn't be possible" + assert i.path is not None, 'for mypy' + fname = [i.path] + else: + fname = [i.rel_to_builddir(self.build_to_src)] + if target.absolute_paths: + fname = [os.path.join(self.environment.get_build_dir(), f) for f in fname] + srcs += fname + return srcs + + def get_custom_target_depend_files(self, target: build.CustomTarget, absolute_paths: bool = False) -> T.List[str]: + deps: T.List[str] = [] + for i in target.depend_files: + if isinstance(i, mesonlib.File): + if absolute_paths: + deps.append(i.absolute_path(self.environment.get_source_dir(), + self.environment.get_build_dir())) + else: + deps.append(i.rel_to_builddir(self.build_to_src)) + else: + if absolute_paths: + deps.append(os.path.join(self.environment.get_source_dir(), target.subdir, i)) + else: + deps.append(os.path.join(self.build_to_src, target.subdir, i)) + return deps + + def get_custom_target_output_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: + # The XCode backend is special. A target foo/bar does + # not go to ${BUILDDIR}/foo/bar but instead to + # ${BUILDDIR}/${BUILDTYPE}/foo/bar. + # Currently we set the include dir to be the former, + # and not the latter. Thus we need this extra customisation + # point. If in the future we make include dirs et al match + # ${BUILDDIR}/${BUILDTYPE} instead, this becomes unnecessary. + return self.get_target_dir(target) + + @lru_cache(maxsize=None) + def get_normpath_target(self, source: str) -> str: + return os.path.normpath(source) + + def get_custom_target_dirs(self, target: build.CustomTarget, compiler: 'Compiler', *, + absolute_path: bool = False) -> T.List[str]: + custom_target_include_dirs: T.List[str] = [] + for i in target.get_generated_sources(): + # Generator output goes into the target private dir which is + # already in the include paths list. Only custom targets have their + # own target build dir. + if not isinstance(i, (build.CustomTarget, build.CustomTargetIndex)): + continue + idir = self.get_normpath_target(self.get_custom_target_output_dir(i)) + if not idir: + idir = '.' + if absolute_path: + idir = os.path.join(self.environment.get_build_dir(), idir) + if idir not in custom_target_include_dirs: + custom_target_include_dirs.append(idir) + return custom_target_include_dirs + + def get_custom_target_dir_include_args( + self, target: build.CustomTarget, compiler: 'Compiler', *, + absolute_path: bool = False) -> T.List[str]: + incs: T.List[str] = [] + for i in self.get_custom_target_dirs(target, compiler, absolute_path=absolute_path): + incs += compiler.get_include_args(i, False) + return incs + + def eval_custom_target_command( + self, target: build.CustomTarget, absolute_outputs: bool = False) -> \ + T.Tuple[T.List[str], T.List[str], T.List[str]]: + # We want the outputs to be absolute only when using the VS backend + # XXX: Maybe allow the vs backend to use relative paths too? + source_root = self.build_to_src + build_root = '.' + outdir = self.get_custom_target_output_dir(target) + if absolute_outputs: + source_root = self.environment.get_source_dir() + build_root = self.environment.get_build_dir() + outdir = os.path.join(self.environment.get_build_dir(), outdir) + outputs = [os.path.join(outdir, i) for i in target.get_outputs()] + inputs = self.get_custom_target_sources(target) + # Evaluate the command list + cmd: T.List[str] = [] + for i in target.command: + if isinstance(i, build.BuildTarget): + cmd += self.build_target_to_cmd_array(i) + continue + elif isinstance(i, build.CustomTarget): + # GIR scanner will attempt to execute this binary but + # it assumes that it is in path, so always give it a full path. + tmp = i.get_outputs()[0] + i = os.path.join(self.get_custom_target_output_dir(i), tmp) + elif isinstance(i, mesonlib.File): + i = i.rel_to_builddir(self.build_to_src) + if target.absolute_paths or absolute_outputs: + i = os.path.join(self.environment.get_build_dir(), i) + # FIXME: str types are blindly added ignoring 'target.absolute_paths' + # because we can't know if they refer to a file or just a string + elif isinstance(i, str): + if '@SOURCE_ROOT@' in i: + i = i.replace('@SOURCE_ROOT@', source_root) + if '@BUILD_ROOT@' in i: + i = i.replace('@BUILD_ROOT@', build_root) + if '@CURRENT_SOURCE_DIR@' in i: + i = i.replace('@CURRENT_SOURCE_DIR@', os.path.join(source_root, target.subdir)) + if '@DEPFILE@' in i: + if target.depfile is None: + msg = f'Custom target {target.name!r} has @DEPFILE@ but no depfile ' \ + 'keyword argument.' + raise MesonException(msg) + dfilename = os.path.join(outdir, target.depfile) + i = i.replace('@DEPFILE@', dfilename) + if '@PRIVATE_DIR@' in i: + if target.absolute_paths: + pdir = self.get_target_private_dir_abs(target) + else: + pdir = self.get_target_private_dir(target) + i = i.replace('@PRIVATE_DIR@', pdir) + else: + raise RuntimeError(f'Argument {i} is of unknown type {type(i)}') + cmd.append(i) + # Substitute the rest of the template strings + values = mesonlib.get_filenames_templates_dict(inputs, outputs) + cmd = mesonlib.substitute_values(cmd, values) + # This should not be necessary but removing it breaks + # building GStreamer on Windows. The underlying issue + # is problems with quoting backslashes on Windows + # which is the seventh circle of hell. The downside is + # that this breaks custom targets whose command lines + # have backslashes. If you try to fix this be sure to + # check that it does not break GST. + # + # The bug causes file paths such as c:\foo to get escaped + # into c:\\foo. + # + # Unfortunately we have not been able to come up with an + # isolated test case for this so unless you manage to come up + # with one, the only way is to test the building with Gst's + # setup. Note this in your MR or ping us and we will get it + # fixed. + # + # https://github.com/mesonbuild/meson/pull/737 + cmd = [i.replace('\\', '/') for i in cmd] + return inputs, outputs, cmd + + def get_run_target_env(self, target: build.RunTarget) -> build.EnvironmentVariables: + env = target.env if target.env else build.EnvironmentVariables() + if target.default_env: + introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) + env.set('MESON_SOURCE_ROOT', [self.environment.get_source_dir()]) + env.set('MESON_BUILD_ROOT', [self.environment.get_build_dir()]) + env.set('MESON_SUBDIR', [target.subdir]) + env.set('MESONINTROSPECT', [introspect_cmd]) + return env + + def run_postconf_scripts(self) -> None: + from ..scripts.meson_exe import run_exe + introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) + env = {'MESON_SOURCE_ROOT': self.environment.get_source_dir(), + 'MESON_BUILD_ROOT': self.environment.get_build_dir(), + 'MESONINTROSPECT': introspect_cmd, + } + + for s in self.build.postconf_scripts: + name = ' '.join(s.cmd_args) + mlog.log(f'Running postconf script {name!r}') + run_exe(s, env) + + def create_install_data(self) -> InstallData: + strip_bin = self.environment.lookup_binary_entry(MachineChoice.HOST, 'strip') + if strip_bin is None: + if self.environment.is_cross_build(): + mlog.warning('Cross file does not specify strip binary, result will not be stripped.') + else: + # TODO go through all candidates, like others + strip_bin = [detect.defaults['strip'][0]] + + umask = self.environment.coredata.get_option(OptionKey('install_umask')) + assert isinstance(umask, (str, int)), 'for mypy' + + d = InstallData(self.environment.get_source_dir(), + self.environment.get_build_dir(), + self.environment.get_prefix(), + self.environment.get_libdir(), + strip_bin, + umask, + self.environment.get_build_command() + ['introspect'], + self.environment.coredata.version) + self.generate_depmf_install(d) + self.generate_target_install(d) + self.generate_header_install(d) + self.generate_man_install(d) + self.generate_emptydir_install(d) + self.generate_data_install(d) + self.generate_symlink_install(d) + self.generate_custom_install_script(d) + self.generate_subdir_install(d) + return d + + def create_install_data_files(self) -> None: + install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat') + with open(install_data_file, 'wb') as ofile: + pickle.dump(self.create_install_data(), ofile) + + def guess_install_tag(self, fname: str, outdir: T.Optional[str] = None) -> T.Optional[str]: + prefix = self.environment.get_prefix() + bindir = Path(prefix, self.environment.get_bindir()) + libdir = Path(prefix, self.environment.get_libdir()) + incdir = Path(prefix, self.environment.get_includedir()) + _ldir = self.environment.coredata.get_option(mesonlib.OptionKey('localedir')) + assert isinstance(_ldir, str), 'for mypy' + localedir = Path(prefix, _ldir) + dest_path = Path(prefix, outdir, Path(fname).name) if outdir else Path(prefix, fname) + if bindir in dest_path.parents: + return 'runtime' + elif libdir in dest_path.parents: + if dest_path.suffix in {'.a', '.pc'}: + return 'devel' + elif dest_path.suffix in {'.so', '.dll'}: + return 'runtime' + elif incdir in dest_path.parents: + return 'devel' + elif localedir in dest_path.parents: + return 'i18n' + elif 'installed-tests' in dest_path.parts: + return 'tests' + elif 'systemtap' in dest_path.parts: + return 'systemtap' + mlog.debug('Failed to guess install tag for', dest_path) + return None + + def generate_target_install(self, d: InstallData) -> None: + for t in self.build.get_targets().values(): + if not t.should_install(): + continue + outdirs, install_dir_names, custom_install_dir = t.get_install_dir() + # Sanity-check the outputs and install_dirs + num_outdirs, num_out = len(outdirs), len(t.get_outputs()) + if num_outdirs not in {1, num_out}: + m = 'Target {!r} has {} outputs: {!r}, but only {} "install_dir"s were found.\n' \ + "Pass 'false' for outputs that should not be installed and 'true' for\n" \ + 'using the default installation directory for an output.' + raise MesonException(m.format(t.name, num_out, t.get_outputs(), num_outdirs)) + assert len(t.install_tag) == num_out + install_mode = t.get_custom_install_mode() + # because mypy gets confused type narrowing in lists + first_outdir = outdirs[0] + first_outdir_name = install_dir_names[0] + + # Install the target output(s) + if isinstance(t, build.BuildTarget): + # In general, stripping static archives is tricky and full of pitfalls. + # Wholesale stripping of static archives with a command such as + # + # strip libfoo.a + # + # is broken, as GNU's strip will remove *every* symbol in a static + # archive. One solution to this nonintuitive behaviour would be + # to only strip local/debug symbols. Unfortunately, strip arguments + # are not specified by POSIX and therefore not portable. GNU's `-g` + # option (i.e. remove debug symbols) is equivalent to Apple's `-S`. + # + # TODO: Create GNUStrip/AppleStrip/etc. hierarchy for more + # fine-grained stripping of static archives. + can_strip = not isinstance(t, build.StaticLibrary) + should_strip = can_strip and t.get_option(OptionKey('strip')) + assert isinstance(should_strip, bool), 'for mypy' + # Install primary build output (library/executable/jar, etc) + # Done separately because of strip/aliases/rpath + if first_outdir is not False: + tag = t.install_tag[0] or ('devel' if isinstance(t, build.StaticLibrary) else 'runtime') + mappings = t.get_link_deps_mapping(d.prefix) + i = TargetInstallData(self.get_target_filename(t), first_outdir, + first_outdir_name, + should_strip, mappings, t.rpath_dirs_to_remove, + t.install_rpath, install_mode, t.subproject, + tag=tag, can_strip=can_strip) + d.targets.append(i) + + for alias, to, tag in t.get_aliases(): + alias = os.path.join(first_outdir, alias) + s = InstallSymlinkData(to, alias, first_outdir, t.subproject, tag, allow_missing=True) + d.symlinks.append(s) + + if isinstance(t, (build.SharedLibrary, build.SharedModule, build.Executable)): + # On toolchains/platforms that use an import library for + # linking (separate from the shared library with all the + # code), we need to install that too (dll.a/.lib). + if t.get_import_filename(): + if custom_install_dir: + # If the DLL is installed into a custom directory, + # install the import library into the same place so + # it doesn't go into a surprising place + implib_install_dir = first_outdir + else: + implib_install_dir = self.environment.get_import_lib_dir() + # Install the import library; may not exist for shared modules + i = TargetInstallData(self.get_target_filename_for_linking(t), + implib_install_dir, first_outdir_name, + False, {}, set(), '', install_mode, + t.subproject, optional=isinstance(t, build.SharedModule), + tag='devel') + d.targets.append(i) + + if not should_strip and t.get_debug_filename(): + debug_file = os.path.join(self.get_target_dir(t), t.get_debug_filename()) + i = TargetInstallData(debug_file, first_outdir, + first_outdir_name, + False, {}, set(), '', + install_mode, t.subproject, + optional=True, tag='devel') + d.targets.append(i) + # Install secondary outputs. Only used for Vala right now. + if num_outdirs > 1: + for output, outdir, outdir_name, tag in zip(t.get_outputs()[1:], outdirs[1:], install_dir_names[1:], t.install_tag[1:]): + # User requested that we not install this output + if outdir is False: + continue + f = os.path.join(self.get_target_dir(t), output) + i = TargetInstallData(f, outdir, outdir_name, False, {}, set(), None, + install_mode, t.subproject, + tag=tag) + d.targets.append(i) + elif isinstance(t, build.CustomTarget): + # If only one install_dir is specified, assume that all + # outputs will be installed into it. This is for + # backwards-compatibility and because it makes sense to + # avoid repetition since this is a common use-case. + # + # To selectively install only some outputs, pass `false` as + # the install_dir for the corresponding output by index + # + # XXX: this wouldn't be needed if we just always matches outdirs + # to the length of outputs… + if num_outdirs == 1 and num_out > 1: + if first_outdir is not False: + for output, tag in zip(t.get_outputs(), t.install_tag): + tag = tag or self.guess_install_tag(output, first_outdir) + f = os.path.join(self.get_target_dir(t), output) + i = TargetInstallData(f, first_outdir, first_outdir_name, + False, {}, set(), None, install_mode, + t.subproject, optional=not t.build_by_default, + tag=tag) + d.targets.append(i) + else: + for output, outdir, outdir_name, tag in zip(t.get_outputs(), outdirs, install_dir_names, t.install_tag): + # User requested that we not install this output + if outdir is False: + continue + tag = tag or self.guess_install_tag(output, outdir) + f = os.path.join(self.get_target_dir(t), output) + i = TargetInstallData(f, outdir, outdir_name, + False, {}, set(), None, install_mode, + t.subproject, optional=not t.build_by_default, + tag=tag) + d.targets.append(i) + + def generate_custom_install_script(self, d: InstallData) -> None: + d.install_scripts = self.build.install_scripts + for i in d.install_scripts: + if not i.tag: + mlog.debug('Failed to guess install tag for install script:', ' '.join(i.cmd_args)) + + def generate_header_install(self, d: InstallData) -> None: + incroot = self.environment.get_includedir() + headers = self.build.get_headers() + + srcdir = self.environment.get_source_dir() + builddir = self.environment.get_build_dir() + for h in headers: + outdir = outdir_name = h.get_custom_install_dir() + if outdir is None: + subdir = h.get_install_subdir() + if subdir is None: + outdir = incroot + outdir_name = '{includedir}' + else: + outdir = os.path.join(incroot, subdir) + outdir_name = os.path.join('{includedir}', subdir) + + for f in h.get_sources(): + if not isinstance(f, File): + raise MesonException(f'Invalid header type {f!r} can\'t be installed') + abspath = f.absolute_path(srcdir, builddir) + i = InstallDataBase(abspath, outdir, outdir_name, h.get_custom_install_mode(), h.subproject, tag='devel') + d.headers.append(i) + + def generate_man_install(self, d: InstallData) -> None: + manroot = self.environment.get_mandir() + man = self.build.get_man() + for m in man: + for f in m.get_sources(): + num = f.split('.')[-1] + subdir = m.get_custom_install_dir() + if subdir is None: + if m.locale: + subdir = os.path.join('{mandir}', m.locale, 'man' + num) + else: + subdir = os.path.join('{mandir}', 'man' + num) + fname = f.fname + if m.locale: # strip locale from file name + fname = fname.replace(f'.{m.locale}', '') + srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) + dstname = os.path.join(subdir, os.path.basename(fname)) + dstabs = dstname.replace('{mandir}', manroot) + i = InstallDataBase(srcabs, dstabs, dstname, m.get_custom_install_mode(), m.subproject, tag='man') + d.man.append(i) + + def generate_emptydir_install(self, d: InstallData) -> None: + emptydir: T.List[build.EmptyDir] = self.build.get_emptydir() + for e in emptydir: + tag = e.install_tag or self.guess_install_tag(e.path) + i = InstallEmptyDir(e.path, e.install_mode, e.subproject, tag) + d.emptydir.append(i) + + def generate_data_install(self, d: InstallData) -> None: + data = self.build.get_data() + srcdir = self.environment.get_source_dir() + builddir = self.environment.get_build_dir() + for de in data: + assert isinstance(de, build.Data) + subdir = de.install_dir + subdir_name = de.install_dir_name + if not subdir: + subdir = os.path.join(self.environment.get_datadir(), self.interpreter.build.project_name) + subdir_name = os.path.join('{datadir}', self.interpreter.build.project_name) + for src_file, dst_name in zip(de.sources, de.rename): + assert isinstance(src_file, mesonlib.File) + dst_abs = os.path.join(subdir, dst_name) + dstdir_name = os.path.join(subdir_name, dst_name) + tag = de.install_tag or self.guess_install_tag(dst_abs) + i = InstallDataBase(src_file.absolute_path(srcdir, builddir), dst_abs, dstdir_name, + de.install_mode, de.subproject, tag=tag, data_type=de.data_type) + d.data.append(i) + + def generate_symlink_install(self, d: InstallData) -> None: + links: T.List[build.SymlinkData] = self.build.get_symlinks() + for l in links: + assert isinstance(l, build.SymlinkData) + install_dir = l.install_dir + name_abs = os.path.join(install_dir, l.name) + tag = l.install_tag or self.guess_install_tag(name_abs) + s = InstallSymlinkData(l.target, name_abs, install_dir, l.subproject, tag) + d.symlinks.append(s) + + def generate_subdir_install(self, d: InstallData) -> None: + for sd in self.build.get_install_subdirs(): + if sd.from_source_dir: + from_dir = self.environment.get_source_dir() + else: + from_dir = self.environment.get_build_dir() + src_dir = os.path.join(from_dir, + sd.source_subdir, + sd.installable_subdir).rstrip('/') + dst_dir = os.path.join(self.environment.get_prefix(), + sd.install_dir) + dst_name = os.path.join('{prefix}', sd.install_dir) + if sd.install_dir != sd.install_dir_name: + dst_name = sd.install_dir_name + if not sd.strip_directory: + dst_dir = os.path.join(dst_dir, os.path.basename(src_dir)) + dst_name = os.path.join(dst_name, os.path.basename(src_dir)) + tag = sd.install_tag or self.guess_install_tag(os.path.join(sd.install_dir, 'dummy')) + i = SubdirInstallData(src_dir, dst_dir, dst_name, sd.install_mode, sd.exclude, sd.subproject, tag) + d.install_subdirs.append(i) + + def get_introspection_data(self, target_id: str, target: build.Target) -> T.List['TargetIntrospectionData']: + ''' + Returns a list of source dicts with the following format for a given target: + [ + { + "language": "", + "compiler": ["result", "of", "comp.get_exelist()"], + "parameters": ["list", "of", "compiler", "parameters], + "sources": ["list", "of", "all", "", "source", "files"], + "generated_sources": ["list", "of", "generated", "source", "files"] + } + ] + + This is a limited fallback / reference implementation. The backend should override this method. + ''' + if isinstance(target, (build.CustomTarget, build.BuildTarget)): + source_list_raw = target.sources + source_list = [] + for j in source_list_raw: + if isinstance(j, mesonlib.File): + source_list += [j.absolute_path(self.source_dir, self.build_dir)] + elif isinstance(j, str): + source_list += [os.path.join(self.source_dir, j)] + elif isinstance(j, (build.CustomTarget, build.BuildTarget)): + source_list += [os.path.join(self.build_dir, j.get_subdir(), o) for o in j.get_outputs()] + source_list = [os.path.normpath(s) for s in source_list] + + compiler: T.List[str] = [] + if isinstance(target, build.CustomTarget): + tmp_compiler = target.command + for j in tmp_compiler: + if isinstance(j, mesonlib.File): + compiler += [j.absolute_path(self.source_dir, self.build_dir)] + elif isinstance(j, str): + compiler += [j] + elif isinstance(j, (build.BuildTarget, build.CustomTarget)): + compiler += j.get_outputs() + else: + raise RuntimeError(f'Type "{type(j).__name__}" is not supported in get_introspection_data. This is a bug') + + return [{ + 'language': 'unknown', + 'compiler': compiler, + 'parameters': [], + 'sources': source_list, + 'generated_sources': [] + }] + + return [] + + def get_devenv(self) -> build.EnvironmentVariables: + env = build.EnvironmentVariables() + extra_paths = set() + library_paths = set() + build_machine = self.environment.machines[MachineChoice.BUILD] + host_machine = self.environment.machines[MachineChoice.HOST] + need_wine = not build_machine.is_windows() and host_machine.is_windows() + for t in self.build.get_targets().values(): + in_default_dir = t.should_install() and not t.get_install_dir()[2] + if t.for_machine != MachineChoice.HOST or not in_default_dir: + continue + tdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t)) + if isinstance(t, build.Executable): + # Add binaries that are going to be installed in bindir into PATH + # so they get used by default instead of searching on system when + # in developer environment. + extra_paths.add(tdir) + if host_machine.is_windows() or host_machine.is_cygwin(): + # On windows we cannot rely on rpath to run executables from build + # directory. We have to add in PATH the location of every DLL needed. + library_paths.update(self.determine_windows_extra_paths(t, [])) + elif isinstance(t, build.SharedLibrary): + # Add libraries that are going to be installed in libdir into + # LD_LIBRARY_PATH. This allows running system applications using + # that library. + library_paths.add(tdir) + if need_wine: + # Executable paths should be in both PATH and WINEPATH. + # - Having them in PATH makes bash completion find it, + # and make running "foo.exe" find it when wine-binfmt is installed. + # - Having them in WINEPATH makes "wine foo.exe" find it. + library_paths.update(extra_paths) + if library_paths: + if need_wine: + env.prepend('WINEPATH', list(library_paths), separator=';') + elif host_machine.is_windows() or host_machine.is_cygwin(): + extra_paths.update(library_paths) + elif host_machine.is_darwin(): + env.prepend('DYLD_LIBRARY_PATH', list(library_paths)) + else: + env.prepend('LD_LIBRARY_PATH', list(library_paths)) + if extra_paths: + env.prepend('PATH', list(extra_paths)) + return env + + def compiler_to_generator(self, target: build.BuildTarget, + compiler: 'Compiler', + sources: _ALL_SOURCES_TYPE, + output_templ: str) -> build.GeneratedList: + ''' + Some backends don't support custom compilers. This is a convenience + method to convert a Compiler to a Generator. + ''' + exelist = compiler.get_exelist() + exe = programs.ExternalProgram(exelist[0]) + args = exelist[1:] + # FIXME: There are many other args missing + commands = self.generate_basic_compiler_args(target, compiler) + commands += compiler.get_dependency_gen_args('@OUTPUT@', '@DEPFILE@') + commands += compiler.get_output_args('@OUTPUT@') + commands += compiler.get_compile_only_args() + ['@INPUT@'] + commands += self.get_source_dir_include_args(target, compiler) + commands += self.get_build_dir_include_args(target, compiler) + generator = build.Generator(exe, args + commands.to_native(), [output_templ], depfile='@PLAINNAME@.d') + return generator.process_files(sources, self.interpreter) + + def compile_target_to_generator(self, target: build.CompileTarget) -> build.GeneratedList: + all_sources = T.cast('_ALL_SOURCES_TYPE', target.sources) + T.cast('_ALL_SOURCES_TYPE', target.generated) + return self.compiler_to_generator(target, target.compiler, all_sources, target.output_templ) diff --git a/devtools/meson/mesonbuild/backend/ninjabackend.py b/devtools/meson/mesonbuild/backend/ninjabackend.py new file mode 100644 index 0000000..3560d1e --- /dev/null +++ b/devtools/meson/mesonbuild/backend/ninjabackend.py @@ -0,0 +1,3854 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from collections import OrderedDict +from dataclasses import dataclass +from enum import Enum, unique +from functools import lru_cache +from pathlib import PurePath, Path +from textwrap import dedent +import itertools +import json +import os +import pickle +import re +import shlex +import subprocess +import typing as T + +from . import backends +from .. import modules +from .. import environment, mesonlib +from .. import build +from .. import mlog +from .. import compilers +from ..arglist import CompilerArgs +from ..compilers import Compiler +from ..linkers import ArLikeLinker, RSPFileSyntax +from ..mesonlib import ( + File, LibType, MachineChoice, MesonBugException, MesonException, OrderedSet, PerMachine, + ProgressBar, quote_arg +) +from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey +from .backends import CleanTrees +from ..build import GeneratedList, InvalidArguments + +if T.TYPE_CHECKING: + from typing_extensions import Literal + + from .._typing import ImmutableListProtocol + from ..build import ExtractedObjects, LibTypes + from ..interpreter import Interpreter + from ..linkers.linkers import DynamicLinker, StaticLinker + from ..compilers.cs import CsCompiler + from ..compilers.fortran import FortranCompiler + + CommandArgOrStr = T.List[T.Union['NinjaCommandArg', str]] + RUST_EDITIONS = Literal['2015', '2018', '2021'] + + +FORTRAN_INCLUDE_PAT = r"^\s*#?include\s*['\"](\w+\.\w+)['\"]" +FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$" +FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)" +FORTRAN_USE_PAT = r"^\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)" + +def cmd_quote(arg: str) -> str: + # see: https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw#remarks + + # backslash escape any existing double quotes + # any existing backslashes preceding a quote are doubled + arg = re.sub(r'(\\*)"', lambda m: '\\' * (len(m.group(1)) * 2 + 1) + '"', arg) + # any terminal backslashes likewise need doubling + arg = re.sub(r'(\\*)$', lambda m: '\\' * (len(m.group(1)) * 2), arg) + # and double quote + arg = f'"{arg}"' + + return arg + +def gcc_rsp_quote(s: str) -> str: + # see: the function buildargv() in libiberty + # + # this differs from sh-quoting in that a backslash *always* escapes the + # following character, even inside single quotes. + + s = s.replace('\\', '\\\\') + + return shlex.quote(s) + +# How ninja executes command lines differs between Unix and Windows +# (see https://ninja-build.org/manual.html#ref_rule_command) +if mesonlib.is_windows(): + quote_func = cmd_quote + execute_wrapper = ['cmd', '/c'] # unused + rmfile_prefix = ['del', '/f', '/s', '/q', '{}', '&&'] +else: + quote_func = quote_arg + execute_wrapper = [] + rmfile_prefix = ['rm', '-f', '{}', '&&'] + + +def get_rsp_threshold() -> int: + '''Return a conservative estimate of the commandline size in bytes + above which a response file should be used. May be overridden for + debugging by setting environment variable MESON_RSP_THRESHOLD.''' + + if mesonlib.is_windows(): + # Usually 32k, but some projects might use cmd.exe, + # and that has a limit of 8k. + limit = 8192 + else: + # On Linux, ninja always passes the commandline as a single + # big string to /bin/sh, and the kernel limits the size of a + # single argument; see MAX_ARG_STRLEN + limit = 131072 + # Be conservative + limit = limit // 2 + return int(os.environ.get('MESON_RSP_THRESHOLD', limit)) + +# a conservative estimate of the command-line length limit +rsp_threshold = get_rsp_threshold() + +# ninja variables whose value should remain unquoted. The value of these ninja +# variables (or variables we use them in) is interpreted directly by ninja +# (e.g. the value of the depfile variable is a pathname that ninja will read +# from, etc.), so it must not be shell quoted. +raw_names = {'DEPFILE_UNQUOTED', 'DESC', 'pool', 'description', 'targetdep', 'dyndep'} + +NINJA_QUOTE_BUILD_PAT = re.compile(r"[$ :\n]") +NINJA_QUOTE_VAR_PAT = re.compile(r"[$ \n]") + +def ninja_quote(text: str, is_build_line: bool = False) -> str: + if is_build_line: + quote_re = NINJA_QUOTE_BUILD_PAT + else: + quote_re = NINJA_QUOTE_VAR_PAT + # Fast path for when no quoting is necessary + if not quote_re.search(text): + return text + if '\n' in text: + errmsg = f'''Ninja does not support newlines in rules. The content was: + +{text} + +Please report this error with a test case to the Meson bug tracker.''' + raise MesonException(errmsg) + return quote_re.sub(r'$\g<0>', text) + +class TargetDependencyScannerInfo: + def __init__(self, private_dir: str, source2object: T.Dict[str, str]): + self.private_dir = private_dir + self.source2object = source2object + +@unique +class Quoting(Enum): + both = 0 + notShell = 1 + notNinja = 2 + none = 3 + +class NinjaCommandArg: + def __init__(self, s: str, quoting: Quoting = Quoting.both) -> None: + self.s = s + self.quoting = quoting + + def __str__(self) -> str: + return self.s + + @staticmethod + def list(l: str, q: Quoting) -> T.List[NinjaCommandArg]: + return [NinjaCommandArg(i, q) for i in l] + +@dataclass +class NinjaComment: + comment: str + + def write(self, outfile: T.TextIO) -> None: + for l in self.comment.split('\n'): + outfile.write('# ') + outfile.write(l) + outfile.write('\n') + outfile.write('\n') + +class NinjaRule: + def __init__(self, rule: str, command: CommandArgOrStr, args: CommandArgOrStr, + description: str, rspable: bool = False, deps: T.Optional[str] = None, + depfile: T.Optional[str] = None, extra: T.Optional[str] = None, + rspfile_quote_style: RSPFileSyntax = RSPFileSyntax.GCC): + + def strToCommandArg(c: T.Union[NinjaCommandArg, str]) -> NinjaCommandArg: + if isinstance(c, NinjaCommandArg): + return c + + # deal with common cases here, so we don't have to explicitly + # annotate the required quoting everywhere + if c == '&&': + # shell constructs shouldn't be shell quoted + return NinjaCommandArg(c, Quoting.notShell) + if c.startswith('$'): + var = re.search(r'\$\{?(\w*)\}?', c).group(1) + if var not in raw_names: + # ninja variables shouldn't be ninja quoted, and their value + # is already shell quoted + return NinjaCommandArg(c, Quoting.none) + else: + # shell quote the use of ninja variables whose value must + # not be shell quoted (as it also used by ninja) + return NinjaCommandArg(c, Quoting.notNinja) + + return NinjaCommandArg(c) + + self.name = rule + self.command: T.List[NinjaCommandArg] = [strToCommandArg(c) for c in command] # includes args which never go into a rspfile + self.args: T.List[NinjaCommandArg] = [strToCommandArg(a) for a in args] # args which will go into a rspfile, if used + self.description = description + self.deps = deps # depstyle 'gcc' or 'msvc' + self.depfile = depfile + self.extra = extra + self.rspable = rspable # if a rspfile can be used + self.refcount = 0 + self.rsprefcount = 0 + self.rspfile_quote_style = rspfile_quote_style + + if self.depfile == '$DEPFILE': + self.depfile += '_UNQUOTED' + + @staticmethod + def _quoter(x, qf = quote_func): + if isinstance(x, NinjaCommandArg): + if x.quoting == Quoting.none: + return x.s + elif x.quoting == Quoting.notNinja: + return qf(x.s) + elif x.quoting == Quoting.notShell: + return ninja_quote(x.s) + # fallthrough + return ninja_quote(qf(str(x))) + + def write(self, outfile: T.TextIO) -> None: + if self.rspfile_quote_style is RSPFileSyntax.MSVC: + rspfile_quote_func = cmd_quote + else: + rspfile_quote_func = gcc_rsp_quote + + def rule_iter(): + if self.refcount: + yield '' + if self.rsprefcount: + yield '_RSP' + + for rsp in rule_iter(): + outfile.write(f'rule {self.name}{rsp}\n') + if rsp == '_RSP': + outfile.write(' command = {} @$out.rsp\n'.format(' '.join([self._quoter(x) for x in self.command]))) + outfile.write(' rspfile = $out.rsp\n') + outfile.write(' rspfile_content = {}\n'.format(' '.join([self._quoter(x, rspfile_quote_func) for x in self.args]))) + else: + outfile.write(' command = {}\n'.format(' '.join([self._quoter(x) for x in self.command + self.args]))) + if self.deps: + outfile.write(f' deps = {self.deps}\n') + if self.depfile: + outfile.write(f' depfile = {self.depfile}\n') + outfile.write(f' description = {self.description}\n') + if self.extra: + for l in self.extra.split('\n'): + outfile.write(' ') + outfile.write(l) + outfile.write('\n') + outfile.write('\n') + + def length_estimate(self, infiles, outfiles, elems): + # determine variables + # this order of actions only approximates ninja's scoping rules, as + # documented at: https://ninja-build.org/manual.html#ref_scope + ninja_vars = {} + for e in elems: + (name, value) = e + ninja_vars[name] = value + ninja_vars['deps'] = self.deps + ninja_vars['depfile'] = self.depfile + ninja_vars['in'] = infiles + ninja_vars['out'] = outfiles + + # expand variables in command + command = ' '.join([self._quoter(x) for x in self.command + self.args]) + estimate = len(command) + for m in re.finditer(r'(\${\w+}|\$\w+)?[^$]*', command): + if m.start(1) != -1: + estimate -= m.end(1) - m.start(1) + 1 + chunk = m.group(1) + if chunk[1] == '{': + chunk = chunk[2:-1] + else: + chunk = chunk[1:] + chunk = ninja_vars.get(chunk, []) # undefined ninja variables are empty + estimate += len(' '.join(chunk)) + + # determine command length + return estimate + +class NinjaBuildElement: + def __init__(self, all_outputs, outfilenames, rulename, infilenames, implicit_outs=None): + self.implicit_outfilenames = implicit_outs or [] + if isinstance(outfilenames, str): + self.outfilenames = [outfilenames] + else: + self.outfilenames = outfilenames + assert isinstance(rulename, str) + self.rulename = rulename + if isinstance(infilenames, str): + self.infilenames = [infilenames] + else: + self.infilenames = infilenames + self.deps = OrderedSet() + self.orderdeps = OrderedSet() + self.elems = [] + self.all_outputs = all_outputs + self.output_errors = '' + + def add_dep(self, dep): + if isinstance(dep, list): + self.deps.update(dep) + else: + self.deps.add(dep) + + def add_orderdep(self, dep): + if isinstance(dep, list): + self.orderdeps.update(dep) + else: + self.orderdeps.add(dep) + + def add_item(self, name, elems): + # Always convert from GCC-style argument naming to the naming used by the + # current compiler. Also filter system include paths, deduplicate, etc. + if isinstance(elems, CompilerArgs): + elems = elems.to_native() + if isinstance(elems, str): + elems = [elems] + self.elems.append((name, elems)) + + if name == 'DEPFILE': + self.elems.append((name + '_UNQUOTED', elems)) + + def _should_use_rspfile(self): + # 'phony' is a rule built-in to ninja + if self.rulename == 'phony': + return False + + if not self.rule.rspable: + return False + + infilenames = ' '.join([ninja_quote(i, True) for i in self.infilenames]) + outfilenames = ' '.join([ninja_quote(i, True) for i in self.outfilenames]) + + return self.rule.length_estimate(infilenames, + outfilenames, + self.elems) >= rsp_threshold + + def count_rule_references(self): + if self.rulename != 'phony': + if self._should_use_rspfile(): + self.rule.rsprefcount += 1 + else: + self.rule.refcount += 1 + + def write(self, outfile): + if self.output_errors: + raise MesonException(self.output_errors) + ins = ' '.join([ninja_quote(i, True) for i in self.infilenames]) + outs = ' '.join([ninja_quote(i, True) for i in self.outfilenames]) + implicit_outs = ' '.join([ninja_quote(i, True) for i in self.implicit_outfilenames]) + if implicit_outs: + implicit_outs = ' | ' + implicit_outs + use_rspfile = self._should_use_rspfile() + if use_rspfile: + rulename = self.rulename + '_RSP' + mlog.debug(f'Command line for building {self.outfilenames} is long, using a response file') + else: + rulename = self.rulename + line = f'build {outs}{implicit_outs}: {rulename} {ins}' + if len(self.deps) > 0: + line += ' | ' + ' '.join([ninja_quote(x, True) for x in sorted(self.deps)]) + if len(self.orderdeps) > 0: + orderdeps = [str(x) for x in self.orderdeps] + line += ' || ' + ' '.join([ninja_quote(x, True) for x in sorted(orderdeps)]) + line += '\n' + # This is the only way I could find to make this work on all + # platforms including Windows command shell. Slash is a dir separator + # on Windows, too, so all characters are unambiguous and, more importantly, + # do not require quoting, unless explicitly specified, which is necessary for + # the csc compiler. + line = line.replace('\\', '/') + if mesonlib.is_windows(): + # Support network paths as backslash, otherwise they are interpreted as + # arguments for compile/link commands when using MSVC + line = ' '.join( + (l.replace('//', '\\\\', 1) if l.startswith('//') else l) + for l in line.split(' ') + ) + outfile.write(line) + + if use_rspfile: + if self.rule.rspfile_quote_style is RSPFileSyntax.MSVC: + qf = cmd_quote + else: + qf = gcc_rsp_quote + else: + qf = quote_func + + for e in self.elems: + (name, elems) = e + should_quote = name not in raw_names + line = f' {name} = ' + newelems = [] + for i in elems: + if not should_quote or i == '&&': # Hackety hack hack + newelems.append(ninja_quote(i)) + else: + newelems.append(ninja_quote(qf(i))) + line += ' '.join(newelems) + line += '\n' + outfile.write(line) + outfile.write('\n') + + def check_outputs(self): + for n in self.outfilenames: + if n in self.all_outputs: + self.output_errors = f'Multiple producers for Ninja target "{n}". Please rename your targets.' + self.all_outputs[n] = True + +@dataclass +class RustDep: + + name: str + + # equal to the order value of the `RustCrate` + crate: int + + def to_json(self) -> T.Dict[str, object]: + return { + "crate": self.crate, + "name": self.name, + } + +@dataclass +class RustCrate: + + # When the json file is written, the list of Crates will be sorted by this + # value + order: int + + display_name: str + root_module: str + edition: RUST_EDITIONS + deps: T.List[RustDep] + cfg: T.List[str] + is_proc_macro: bool + + # This is set to True for members of this project, and False for all + # subprojects + is_workspace_member: bool + proc_macro_dylib_path: T.Optional[str] = None + + def to_json(self) -> T.Dict[str, object]: + ret: T.Dict[str, object] = { + "display_name": self.display_name, + "root_module": self.root_module, + "edition": self.edition, + "cfg": self.cfg, + "is_proc_macro": self.is_proc_macro, + "deps": [d.to_json() for d in self.deps], + } + + if self.is_proc_macro: + assert self.proc_macro_dylib_path is not None, "This shouldn't happen" + ret["proc_macro_dylib_path"] = self.proc_macro_dylib_path + + return ret + + +class NinjaBackend(backends.Backend): + + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.name = 'ninja' + self.ninja_filename = 'build.ninja' + self.fortran_deps = {} + self.all_outputs = {} + self.introspection_data = {} + self.created_llvm_ir_rule = PerMachine(False, False) + self.rust_crates: T.Dict[str, RustCrate] = {} + self.implicit_meson_outs = [] + + def create_phony_target(self, all_outputs, dummy_outfile, rulename, phony_infilename, implicit_outs=None): + ''' + We need to use aliases for targets that might be used as directory + names to workaround a Ninja bug that breaks `ninja -t clean`. + This is used for 'reserved' targets such as 'test', 'install', + 'benchmark', etc, and also for RunTargets. + https://github.com/mesonbuild/meson/issues/1644 + ''' + if dummy_outfile.startswith('meson-internal__'): + raise AssertionError(f'Invalid usage of create_phony_target with {dummy_outfile!r}') + + to_name = f'meson-internal__{dummy_outfile}' + elem = NinjaBuildElement(all_outputs, dummy_outfile, 'phony', to_name) + self.add_build(elem) + + return NinjaBuildElement(all_outputs, to_name, rulename, phony_infilename, implicit_outs) + + def detect_vs_dep_prefix(self, tempfilename): + '''VS writes its dependency in a locale dependent format. + Detect the search prefix to use.''' + # TODO don't hard-code host + for compiler in self.environment.coredata.compilers.host.values(): + # Have to detect the dependency format + + # IFort / masm on windows is MSVC like, but doesn't have /showincludes + if compiler.language in {'fortran', 'masm'}: + continue + if compiler.id == 'pgi' and mesonlib.is_windows(): + # for the purpose of this function, PGI doesn't act enough like MSVC + return open(tempfilename, 'a', encoding='utf-8') + if compiler.get_argument_syntax() == 'msvc': + break + else: + # None of our compilers are MSVC, we're done. + return open(tempfilename, 'a', encoding='utf-8') + filebase = 'incdetect.' + compilers.lang_suffixes[compiler.language][0] + filename = os.path.join(self.environment.get_scratch_dir(), + filebase) + with open(filename, 'w', encoding='utf-8') as f: + f.write(dedent('''\ + #include + int dummy; + ''')) + + # The output of cl dependency information is language + # and locale dependent. Any attempt at converting it to + # Python strings leads to failure. We _must_ do this detection + # in raw byte mode and write the result in raw bytes. + pc = subprocess.Popen(compiler.get_exelist() + + ['/showIncludes', '/c', filebase], + cwd=self.environment.get_scratch_dir(), + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = pc.communicate() + + # We want to match 'Note: including file: ' in the line + # 'Note: including file: d:\MyDir\include\stdio.h', however + # different locales have different messages with a different + # number of colons. Match up to the drive name 'd:\'. + # When used in cross compilation, the path separator is a + # forward slash rather than a backslash so handle both; i.e. + # the path is /MyDir/include/stdio.h. + # With certain cross compilation wrappings of MSVC, the paths + # use backslashes, but without the leading drive name, so + # allow the path to start with any path separator, i.e. + # \MyDir\include\stdio.h. + matchre = re.compile(rb"^(.*\s)([a-zA-Z]:[\\/]|[\\\/]).*stdio.h$") + + def detect_prefix(out): + for line in re.split(rb'\r?\n', out): + match = matchre.match(line) + if match: + with open(tempfilename, 'ab') as binfile: + binfile.write(b'msvc_deps_prefix = ' + match.group(1) + b'\n') + return open(tempfilename, 'a', encoding='utf-8') + return None + + # Some cl wrappers (e.g. Squish Coco) output dependency info + # to stderr rather than stdout + result = detect_prefix(stdout) or detect_prefix(stderr) + if result: + return result + + raise MesonException(f'Could not determine vs dep dependency prefix string. output: {stderr} {stdout}') + + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + if vslite_ctx: + # We don't yet have a use case where we'd expect to make use of this, + # so no harm in catching and reporting something unexpected. + raise MesonBugException('We do not expect the ninja backend to be given a valid \'vslite_ctx\'') + ninja = environment.detect_ninja_command_and_version(log=True) + if self.environment.coredata.get_option(OptionKey('vsenv')): + builddir = Path(self.environment.get_build_dir()) + try: + # For prettier printing, reduce to a relative path. If + # impossible (e.g., because builddir and cwd are on + # different Windows drives), skip and use the full path. + builddir = builddir.relative_to(Path.cwd()) + except ValueError: + pass + meson_command = mesonlib.join_args(mesonlib.get_meson_command()) + mlog.log() + mlog.log('Visual Studio environment is needed to run Ninja. It is recommended to use Meson wrapper:') + mlog.log(f'{meson_command} compile -C {builddir}') + if ninja is None: + raise MesonException('Could not detect Ninja v1.8.2 or newer') + (self.ninja_command, self.ninja_version) = ninja + outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename) + tempfilename = outfilename + '~' + with open(tempfilename, 'w', encoding='utf-8') as outfile: + outfile.write(f'# This is the build file for project "{self.build.get_project()}"\n') + outfile.write('# It is autogenerated by the Meson build system.\n') + outfile.write('# Do not edit by hand.\n\n') + outfile.write('ninja_required_version = 1.8.2\n\n') + + num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value + if num_pools > 0: + outfile.write(f'''pool link_pool + depth = {num_pools} + +''') + + with self.detect_vs_dep_prefix(tempfilename) as outfile: + self.generate_rules() + + self.build_elements = [] + self.generate_phony() + self.add_build_comment(NinjaComment('Build rules for targets')) + + # Optionally capture compile args per target, for later use (i.e. VisStudio project's NMake intellisense include dirs, defines, and compile options). + if capture: + captured_compile_args_per_target = {} + for target in self.build.get_targets().values(): + if isinstance(target, build.BuildTarget): + captured_compile_args_per_target[target.get_id()] = self.generate_common_compile_args_per_src_type(target) + + for t in ProgressBar(self.build.get_targets().values(), desc='Generating targets'): + self.generate_target(t) + self.add_build_comment(NinjaComment('Test rules')) + self.generate_tests() + self.add_build_comment(NinjaComment('Install rules')) + self.generate_install() + self.generate_dist() + key = OptionKey('b_coverage') + if (key in self.environment.coredata.options and + self.environment.coredata.options[key].value): + gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, _ = environment.find_coverage_tools() + if gcovr_exe or (lcov_exe and genhtml_exe): + self.add_build_comment(NinjaComment('Coverage rules')) + self.generate_coverage_rules(gcovr_exe, gcovr_version) + else: + # FIXME: since we explicitly opted in, should this be an error? + # The docs just say these targets will be created "if possible". + mlog.warning('Need gcovr or lcov/genhtml to generate any coverage reports') + self.add_build_comment(NinjaComment('Suffix')) + self.generate_utils() + self.generate_ending() + + self.write_rules(outfile) + self.write_builds(outfile) + + default = 'default all\n\n' + outfile.write(default) + # Only overwrite the old build file after the new one has been + # fully created. + os.replace(tempfilename, outfilename) + mlog.cmd_ci_include(outfilename) # For CI debugging + # Refresh Ninja's caches. https://github.com/ninja-build/ninja/pull/1685 + if mesonlib.version_compare(self.ninja_version, '>=1.10.0') and os.path.exists(os.path.join(self.environment.build_dir, '.ninja_log')): + subprocess.call(self.ninja_command + ['-t', 'restat'], cwd=self.environment.build_dir) + subprocess.call(self.ninja_command + ['-t', 'cleandead'], cwd=self.environment.build_dir) + self.generate_compdb() + self.generate_rust_project_json() + + if capture: + return captured_compile_args_per_target + + def generate_rust_project_json(self) -> None: + """Generate a rust-analyzer compatible rust-project.json file.""" + if not self.rust_crates: + return + with open(os.path.join(self.environment.get_build_dir(), 'rust-project.json'), + 'w', encoding='utf-8') as f: + json.dump( + { + "sysroot_src": os.path.join(self.environment.coredata.compilers.host['rust'].get_sysroot(), + 'lib/rustlib/src/rust/library/'), + "crates": [c.to_json() for c in self.rust_crates.values()], + }, + f, indent=4) + + # http://clang.llvm.org/docs/JSONCompilationDatabase.html + def generate_compdb(self): + rules = [] + # TODO: Rather than an explicit list here, rules could be marked in the + # rule store as being wanted in compdb + for for_machine in MachineChoice: + for compiler in self.environment.coredata.compilers[for_machine].values(): + rules += [f"{rule}{ext}" for rule in [self.compiler_to_rule_name(compiler)] + for ext in ['', '_RSP']] + rules += [f"{rule}{ext}" for rule in [self.compiler_to_pch_rule_name(compiler)] + for ext in ['', '_RSP']] + compdb_options = ['-x'] if mesonlib.version_compare(self.ninja_version, '>=1.9') else [] + ninja_compdb = self.ninja_command + ['-t', 'compdb'] + compdb_options + rules + builddir = self.environment.get_build_dir() + try: + jsondb = subprocess.check_output(ninja_compdb, cwd=builddir) + with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f: + f.write(jsondb) + except Exception: + mlog.warning('Could not create compilation database.', fatal=False) + + # Get all generated headers. Any source file might need them so + # we need to add an order dependency to them. + def get_generated_headers(self, target): + if hasattr(target, 'cached_generated_headers'): + return target.cached_generated_headers + header_deps = [] + # XXX: Why don't we add deps to CustomTarget headers here? + for genlist in target.get_generated_sources(): + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): + continue + for src in genlist.get_outputs(): + if self.environment.is_header(src): + header_deps.append(self.get_target_generated_dir(target, genlist, src)) + if 'vala' in target.compilers and not isinstance(target, build.Executable): + vala_header = File.from_built_file(self.get_target_dir(target), target.vala_header) + header_deps.append(vala_header) + # Recurse and find generated headers + for dep in itertools.chain(target.link_targets, target.link_whole_targets): + if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): + header_deps += self.get_generated_headers(dep) + target.cached_generated_headers = header_deps + return header_deps + + def get_target_generated_sources(self, target: build.BuildTarget) -> T.MutableMapping[str, File]: + """ + Returns a dictionary with the keys being the path to the file + (relative to the build directory) and the value being the File object + representing the same path. + """ + srcs: T.MutableMapping[str, File] = OrderedDict() + for gensrc in target.get_generated_sources(): + for s in gensrc.get_outputs(): + rel_src = self.get_target_generated_dir(target, gensrc, s) + srcs[rel_src] = File.from_built_relative(rel_src) + return srcs + + def get_target_sources(self, target: build.BuildTarget) -> T.MutableMapping[str, File]: + srcs: T.MutableMapping[str, File] = OrderedDict() + for s in target.get_sources(): + # BuildTarget sources are always mesonlib.File files which are + # either in the source root, or generated with configure_file and + # in the build root + if not isinstance(s, File): + raise InvalidArguments(f'All sources in target {s!r} must be of type mesonlib.File') + f = s.rel_to_builddir(self.build_to_src) + srcs[f] = s + return srcs + + def get_target_source_can_unity(self, target, source): + if isinstance(source, File): + source = source.fname + if self.environment.is_llvm_ir(source) or \ + self.environment.is_assembly(source): + return False + suffix = os.path.splitext(source)[1][1:].lower() + for lang in backends.LANGS_CANT_UNITY: + if lang not in target.compilers: + continue + if suffix in target.compilers[lang].file_suffixes: + return False + return True + + def create_target_source_introspection(self, target: build.Target, comp: compilers.Compiler, parameters, sources, generated_sources, + unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None): + ''' + Adds the source file introspection information for a language of a target + + Internal introspection storage format: + self.introspection_data = { + '': { + : { + 'language: 'lang', + 'compiler': ['comp', 'exe', 'list'], + 'parameters': ['UNIQUE', 'parameter', 'list'], + 'sources': [], + 'generated_sources': [], + } + } + } + ''' + tid = target.get_id() + lang = comp.get_language() + tgt = self.introspection_data[tid] + # Find an existing entry or create a new one + id_hash = (lang, tuple(parameters)) + src_block = tgt.get(id_hash, None) + if src_block is None: + # Convert parameters + if isinstance(parameters, CompilerArgs): + parameters = parameters.to_native(copy=True) + parameters = comp.compute_parameters_with_absolute_paths(parameters, self.build_dir) + # The new entry + src_block = { + 'language': lang, + 'compiler': comp.get_exelist(), + 'parameters': parameters, + 'sources': [], + 'generated_sources': [], + 'unity_sources': [], + } + tgt[id_hash] = src_block + + def compute_path(file: mesonlib.FileOrString) -> str: + """ Make source files absolute """ + if isinstance(file, File): + return file.absolute_path(self.source_dir, self.build_dir) + return os.path.normpath(os.path.join(self.build_dir, file)) + + src_block['sources'].extend(compute_path(x) for x in sources) + src_block['generated_sources'].extend(compute_path(x) for x in generated_sources) + if unity_sources: + src_block['unity_sources'].extend(compute_path(x) for x in unity_sources) + + def create_target_linker_introspection(self, target: build.Target, linker: T.Union[Compiler, StaticLinker], parameters): + tid = target.get_id() + tgt = self.introspection_data[tid] + lnk_hash = tuple(parameters) + lnk_block = tgt.get(lnk_hash, None) + if lnk_block is None: + if isinstance(parameters, CompilerArgs): + parameters = parameters.to_native(copy=True) + + if isinstance(linker, Compiler): + linkers = linker.get_linker_exelist() + else: + linkers = linker.get_exelist() + + lnk_block = { + 'linker': linkers, + 'parameters': parameters, + } + tgt[lnk_hash] = lnk_block + + def generate_target(self, target): + try: + if isinstance(target, build.BuildTarget): + os.makedirs(self.get_target_private_dir_abs(target)) + except FileExistsError: + pass + if isinstance(target, build.CustomTarget): + self.generate_custom_target(target) + if isinstance(target, build.RunTarget): + self.generate_run_target(target) + compiled_sources = [] + source2object = {} + name = target.get_id() + if name in self.processed_targets: + return + self.processed_targets.add(name) + # Initialize an empty introspection source list + self.introspection_data[name] = {} + # Generate rules for all dependency targets + self.process_target_dependencies(target) + + self.generate_shlib_aliases(target, self.get_target_dir(target)) + + # If target uses a language that cannot link to C objects, + # just generate for that language and return. + if isinstance(target, build.Jar): + self.generate_jar_target(target) + return + if target.uses_rust(): + self.generate_rust_target(target) + return + if 'cs' in target.compilers: + self.generate_cs_target(target) + return + if 'swift' in target.compilers: + self.generate_swift_target(target) + return + + # CompileTarget compiles all its sources and does not do a final link. + # This is, for example, a preprocessor. + is_compile_target = isinstance(target, build.CompileTarget) + + # Preexisting target C/C++ sources to be built; dict of full path to + # source relative to build root and the original File object. + target_sources: T.MutableMapping[str, File] + + # GeneratedList and CustomTarget sources to be built; dict of the full + # path to source relative to build root and the generating target/list + generated_sources: T.MutableMapping[str, File] + + # List of sources that have been transpiled from a DSL (like Vala) into + # a language that is handled below, such as C or C++ + transpiled_sources: T.List[str] + + if 'vala' in target.compilers: + # Sources consumed by valac are filtered out. These only contain + # C/C++ sources, objects, generated libs, and unknown sources now. + target_sources, generated_sources, \ + transpiled_sources = self.generate_vala_compile(target) + elif 'cython' in target.compilers: + target_sources, generated_sources, \ + transpiled_sources = self.generate_cython_transpile(target) + else: + target_sources = self.get_target_sources(target) + generated_sources = self.get_target_generated_sources(target) + transpiled_sources = [] + self.scan_fortran_module_outputs(target) + # Generate rules for GeneratedLists + self.generate_generator_list_rules(target) + + # Generate rules for building the remaining source files in this target + outname = self.get_target_filename(target) + obj_list = [] + is_unity = target.is_unity + header_deps = [] + unity_src = [] + unity_deps = [] # Generated sources that must be built before compiling a Unity target. + header_deps += self.get_generated_headers(target) + + if is_unity: + # Warn about incompatible sources if a unity build is enabled + langs = set(target.compilers.keys()) + langs_cant = langs.intersection(backends.LANGS_CANT_UNITY) + if langs_cant: + langs_are = langs = ', '.join(langs_cant).upper() + langs_are += ' are' if len(langs_cant) > 1 else ' is' + msg = f'{langs_are} not supported in Unity builds yet, so {langs} ' \ + f'sources in the {target.name!r} target will be compiled normally' + mlog.log(mlog.red('FIXME'), msg) + + # Get a list of all generated headers that will be needed while building + # this target's sources (generated sources and preexisting sources). + # This will be set as dependencies of all the target's sources. At the + # same time, also deal with generated sources that need to be compiled. + generated_source_files = [] + for rel_src in generated_sources.keys(): + raw_src = File.from_built_relative(rel_src) + if self.environment.is_source(rel_src): + if is_unity and self.get_target_source_can_unity(target, rel_src): + unity_deps.append(raw_src) + abs_src = os.path.join(self.environment.get_build_dir(), rel_src) + unity_src.append(abs_src) + else: + generated_source_files.append(raw_src) + elif self.environment.is_object(rel_src): + obj_list.append(rel_src) + elif self.environment.is_library(rel_src) or modules.is_module_library(rel_src): + pass + elif is_compile_target: + generated_source_files.append(raw_src) + else: + # Assume anything not specifically a source file is a header. This is because + # people generate files with weird suffixes (.inc, .fh) that they then include + # in their source files. + header_deps.append(raw_src) + + # For D language, the object of generated source files are added + # as order only deps because other files may depend on them + d_generated_deps = [] + + # These are the generated source files that need to be built for use by + # this target. We create the Ninja build file elements for this here + # because we need `header_deps` to be fully generated in the above loop. + for src in generated_source_files: + if self.environment.is_llvm_ir(src): + o, s = self.generate_llvm_ir_compile(target, src) + else: + o, s = self.generate_single_compile(target, src, True, + order_deps=header_deps) + compiled_sources.append(s) + source2object[s] = o + obj_list.append(o) + if s.split('.')[-1] in compilers.lang_suffixes['d']: + d_generated_deps.append(o) + + use_pch = self.target_uses_pch(target) + if use_pch and target.has_pch(): + pch_objects = self.generate_pch(target, header_deps=header_deps) + else: + pch_objects = [] + + o, od = self.flatten_object_list(target) + obj_targets = [t for t in od if t.uses_fortran()] + obj_list.extend(o) + + fortran_order_deps = [File(True, *os.path.split(self.get_target_filename(t))) for t in obj_targets] + fortran_inc_args: T.List[str] = [] + if target.uses_fortran(): + fortran_inc_args = mesonlib.listify([target.compilers['fortran'].get_include_args( + self.get_target_private_dir(t), is_system=False) for t in obj_targets]) + + # Generate compilation targets for C sources generated from Vala + # sources. This can be extended to other $LANG->C compilers later if + # necessary. This needs to be separate for at least Vala + # + # Do not try to unity-build the generated c files from vala, as these + # often contain duplicate symbols and will fail to compile properly + vala_generated_source_files = [] + for src in transpiled_sources: + raw_src = File.from_built_relative(src) + # Generated targets are ordered deps because the must exist + # before the sources compiling them are used. After the first + # compile we get precise dependency info from dep files. + # This should work in all cases. If it does not, then just + # move them from orderdeps to proper deps. + if self.environment.is_header(src): + header_deps.append(raw_src) + else: + # We gather all these and generate compile rules below + # after `header_deps` (above) is fully generated + vala_generated_source_files.append(raw_src) + for src in vala_generated_source_files: + # Passing 'vala' here signifies that we want the compile + # arguments to be specialized for C code generated by + # valac. For instance, no warnings should be emitted. + o, s = self.generate_single_compile(target, src, 'vala', [], header_deps) + obj_list.append(o) + + # Generate compile targets for all the preexisting sources for this target + for src in target_sources.values(): + if not self.environment.is_header(src) or is_compile_target: + if self.environment.is_llvm_ir(src): + o, s = self.generate_llvm_ir_compile(target, src) + obj_list.append(o) + elif is_unity and self.get_target_source_can_unity(target, src): + abs_src = os.path.join(self.environment.get_build_dir(), + src.rel_to_builddir(self.build_to_src)) + unity_src.append(abs_src) + else: + o, s = self.generate_single_compile(target, src, False, [], + header_deps + d_generated_deps + fortran_order_deps, + fortran_inc_args) + obj_list.append(o) + compiled_sources.append(s) + source2object[s] = o + + if is_unity: + for src in self.generate_unity_files(target, unity_src): + o, s = self.generate_single_compile(target, src, True, unity_deps + header_deps + d_generated_deps, + fortran_order_deps, fortran_inc_args, unity_src) + obj_list.append(o) + compiled_sources.append(s) + source2object[s] = o + if is_compile_target: + # Skip the link stage for this special type of target + return + linker, stdlib_args = self.determine_linker_and_stdlib_args(target) + if isinstance(target, build.StaticLibrary) and target.prelink: + final_obj_list = self.generate_prelink(target, obj_list) + else: + final_obj_list = obj_list + elem = self.generate_link(target, outname, final_obj_list, linker, pch_objects, stdlib_args=stdlib_args) + self.generate_dependency_scan_target(target, compiled_sources, source2object, generated_source_files, fortran_order_deps) + self.add_build(elem) + #In AIX, we archive shared libraries. If the instance is a shared library, we add a command to archive the shared library + #object and create the build element. + if isinstance(target, build.SharedLibrary) and self.environment.machines[target.for_machine].is_aix(): + elem = NinjaBuildElement(self.all_outputs, linker.get_archive_name(outname), 'AIX_LINKER', [outname]) + self.add_build(elem) + + def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: + if mesonlib.version_compare(self.ninja_version, '<1.10.0'): + return False + if 'fortran' in target.compilers: + return True + if 'cpp' not in target.compilers: + return False + if '-fmodules-ts' in target.extra_args.get('cpp', []): + return True + # Currently only the preview version of Visual Studio is supported. + cpp = target.compilers['cpp'] + if cpp.get_id() != 'msvc': + return False + cppversion = target.get_option(OptionKey('std', machine=target.for_machine, lang='cpp')) + if cppversion not in ('latest', 'c++latest', 'vc++latest'): + return False + if not mesonlib.current_vs_supports_modules(): + return False + if mesonlib.version_compare(cpp.version, '<19.28.28617'): + return False + return True + + def generate_dependency_scan_target(self, target, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File], + object_deps: T.List['mesonlib.FileOrString']) -> None: + if not self.should_use_dyndeps_for_target(target): + return + depscan_file = self.get_dep_scan_file_for(target) + pickle_base = target.name + '.dat' + pickle_file = os.path.join(self.get_target_private_dir(target), pickle_base).replace('\\', '/') + pickle_abs = os.path.join(self.get_target_private_dir_abs(target), pickle_base).replace('\\', '/') + json_abs = os.path.join(self.get_target_private_dir_abs(target), f'{target.name}-deps.json').replace('\\', '/') + rule_name = 'depscan' + scan_sources = self.select_sources_to_scan(compiled_sources) + + # Dump the sources as a json list. This avoids potential problems where + # the number of sources passed to depscan exceeds the limit imposed by + # the OS. + with open(json_abs, 'w', encoding='utf-8') as f: + json.dump(scan_sources, f) + elem = NinjaBuildElement(self.all_outputs, depscan_file, rule_name, json_abs) + elem.add_item('picklefile', pickle_file) + # Add any generated outputs to the order deps of the scan target, so + # that those sources are present + for g in generated_source_files: + elem.orderdeps.add(g.relative_name()) + elem.orderdeps.update(object_deps) + scaninfo = TargetDependencyScannerInfo(self.get_target_private_dir(target), source2object) + with open(pickle_abs, 'wb') as p: + pickle.dump(scaninfo, p) + self.add_build(elem) + + def select_sources_to_scan(self, compiled_sources): + # in practice pick up C++ and Fortran files. If some other language + # requires scanning (possibly Java to deal with inner class files) + # then add them here. + all_suffixes = set(compilers.lang_suffixes['cpp']) | set(compilers.lang_suffixes['fortran']) + selected_sources = [] + for source in compiled_sources: + ext = os.path.splitext(source)[1][1:] + if ext != 'C': + ext = ext.lower() + if ext in all_suffixes: + selected_sources.append(source) + return selected_sources + + def process_target_dependencies(self, target): + for t in target.get_dependencies(): + if t.get_id() not in self.processed_targets: + self.generate_target(t) + + def custom_target_generator_inputs(self, target): + for s in target.sources: + if isinstance(s, build.GeneratedList): + self.generate_genlist_for_target(s, target) + + def unwrap_dep_list(self, target): + deps = [] + for i in target.get_dependencies(): + # FIXME, should not grab element at zero but rather expand all. + if isinstance(i, list): + i = i[0] + # Add a dependency on all the outputs of this target + for output in i.get_outputs(): + deps.append(os.path.join(self.get_target_dir(i), output)) + return deps + + def generate_custom_target(self, target): + self.custom_target_generator_inputs(target) + (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) + deps = self.unwrap_dep_list(target) + deps += self.get_custom_target_depend_files(target) + if target.build_always_stale: + deps.append('PHONY') + if target.depfile is None: + rulename = 'CUSTOM_COMMAND' + else: + rulename = 'CUSTOM_COMMAND_DEP' + elem = NinjaBuildElement(self.all_outputs, ofilenames, rulename, srcs) + elem.add_dep(deps) + for d in target.extra_depends: + # Add a dependency on all the outputs of this target + for output in d.get_outputs(): + elem.add_dep(os.path.join(self.get_target_dir(d), output)) + + cmd, reason = self.as_meson_exe_cmdline(target.command[0], cmd[1:], + extra_bdeps=target.get_transitive_build_target_deps(), + capture=ofilenames[0] if target.capture else None, + feed=srcs[0] if target.feed else None, + env=target.env, + verbose=target.console) + if reason: + cmd_type = f' (wrapped by meson {reason})' + else: + cmd_type = '' + if target.depfile is not None: + depfile = target.get_dep_outname(elem.infilenames) + rel_dfile = os.path.join(self.get_target_dir(target), depfile) + abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + os.makedirs(abs_pdir, exist_ok=True) + elem.add_item('DEPFILE', rel_dfile) + if target.console: + elem.add_item('pool', 'console') + full_name = Path(target.subdir, target.name).as_posix() + elem.add_item('COMMAND', cmd) + elem.add_item('description', f'Generating {full_name} with a custom command{cmd_type}') + self.add_build(elem) + self.processed_targets.add(target.get_id()) + + def build_run_target_name(self, target): + if target.subproject != '': + subproject_prefix = f'{target.subproject}@@' + else: + subproject_prefix = '' + return f'{subproject_prefix}{target.name}' + + def generate_run_target(self, target: build.RunTarget): + target_name = self.build_run_target_name(target) + if not target.command: + # This is an alias target, it has no command, it just depends on + # other targets. + elem = NinjaBuildElement(self.all_outputs, target_name, 'phony', []) + else: + target_env = self.get_run_target_env(target) + _, _, cmd = self.eval_custom_target_command(target) + meson_exe_cmd, reason = self.as_meson_exe_cmdline(target.command[0], cmd[1:], + env=target_env, + verbose=True) + cmd_type = f' (wrapped by meson {reason})' if reason else '' + elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', []) + elem.add_item('COMMAND', meson_exe_cmd) + elem.add_item('description', f'Running external command {target.name}{cmd_type}') + elem.add_item('pool', 'console') + deps = self.unwrap_dep_list(target) + deps += self.get_custom_target_depend_files(target) + elem.add_dep(deps) + self.add_build(elem) + self.processed_targets.add(target.get_id()) + + def generate_coverage_command(self, elem, outputs): + targets = self.build.get_targets().values() + use_llvm_cov = False + for target in targets: + if not hasattr(target, 'compilers'): + continue + for compiler in target.compilers.values(): + if compiler.get_id() == 'clang' and not compiler.info.is_darwin(): + use_llvm_cov = True + break + elem.add_item('COMMAND', self.environment.get_build_command() + + ['--internal', 'coverage'] + + outputs + + [self.environment.get_source_dir(), + os.path.join(self.environment.get_source_dir(), + self.build.get_subproject_dir()), + self.environment.get_build_dir(), + self.environment.get_log_dir()] + + (['--use_llvm_cov'] if use_llvm_cov else [])) + + def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): + e = self.create_phony_target(self.all_outputs, 'coverage', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, []) + e.add_item('description', 'Generates coverage reports') + self.add_build(e) + self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version) + + def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): + e = self.create_phony_target(self.all_outputs, 'coverage-html', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--html']) + e.add_item('description', 'Generates HTML coverage report') + self.add_build(e) + + if gcovr_exe: + e = self.create_phony_target(self.all_outputs, 'coverage-xml', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--xml']) + e.add_item('description', 'Generates XML coverage report') + self.add_build(e) + + e = self.create_phony_target(self.all_outputs, 'coverage-text', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--text']) + e.add_item('description', 'Generates text coverage report') + self.add_build(e) + + if mesonlib.version_compare(gcovr_version, '>=4.2'): + e = self.create_phony_target(self.all_outputs, 'coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') + self.generate_coverage_command(e, ['--sonarqube']) + e.add_item('description', 'Generates Sonarqube XML coverage report') + self.add_build(e) + + def generate_install(self): + self.create_install_data_files() + elem = self.create_phony_target(self.all_outputs, 'install', 'CUSTOM_COMMAND', 'PHONY') + elem.add_dep('all') + elem.add_item('DESC', 'Installing files.') + elem.add_item('COMMAND', self.environment.get_build_command() + ['install', '--no-rebuild']) + elem.add_item('pool', 'console') + self.add_build(elem) + + def generate_tests(self): + self.serialize_tests() + cmd = self.environment.get_build_command(True) + ['test', '--no-rebuild'] + if not self.environment.coredata.get_option(OptionKey('stdsplit')): + cmd += ['--no-stdsplit'] + if self.environment.coredata.get_option(OptionKey('errorlogs')): + cmd += ['--print-errorlogs'] + elem = self.create_phony_target(self.all_outputs, 'test', 'CUSTOM_COMMAND', ['all', 'PHONY']) + elem.add_item('COMMAND', cmd) + elem.add_item('DESC', 'Running all tests.') + elem.add_item('pool', 'console') + self.add_build(elem) + + # And then benchmarks. + cmd = self.environment.get_build_command(True) + [ + 'test', '--benchmark', '--logbase', + 'benchmarklog', '--num-processes=1', '--no-rebuild'] + elem = self.create_phony_target(self.all_outputs, 'benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY']) + elem.add_item('COMMAND', cmd) + elem.add_item('DESC', 'Running benchmark suite.') + elem.add_item('pool', 'console') + self.add_build(elem) + + def generate_rules(self): + self.rules = [] + self.ruledict = {} + + self.add_rule_comment(NinjaComment('Rules for module scanning.')) + self.generate_scanner_rules() + self.add_rule_comment(NinjaComment('Rules for compiling.')) + self.generate_compile_rules() + self.add_rule_comment(NinjaComment('Rules for linking.')) + self.generate_static_link_rules() + self.generate_dynamic_link_rules() + self.add_rule_comment(NinjaComment('Other rules')) + # Ninja errors out if you have deps = gcc but no depfile, so we must + # have two rules for custom commands. + self.add_rule(NinjaRule('CUSTOM_COMMAND', ['$COMMAND'], [], '$DESC', + extra='restat = 1')) + self.add_rule(NinjaRule('CUSTOM_COMMAND_DEP', ['$COMMAND'], [], '$DESC', + deps='gcc', depfile='$DEPFILE', + extra='restat = 1')) + self.add_rule(NinjaRule('COPY_FILE', self.environment.get_build_command() + ['--internal', 'copy'], + ['$in', '$out'], 'Copying $in to $out')) + + c = self.environment.get_build_command() + \ + ['--internal', + 'regenerate', + self.environment.get_source_dir(), + # Ninja always runs from the build_dir. This includes cases where the user moved the + # build directory and invalidated most references. Make sure it still regenerates. + '.'] + self.add_rule(NinjaRule('REGENERATE_BUILD', + c, [], + 'Regenerating build files.', + extra='generator = 1')) + + def add_rule_comment(self, comment): + self.rules.append(comment) + + def add_build_comment(self, comment): + self.build_elements.append(comment) + + def add_rule(self, rule): + if rule.name in self.ruledict: + raise MesonException(f'Tried to add rule {rule.name} twice.') + self.rules.append(rule) + self.ruledict[rule.name] = rule + + def add_build(self, build): + build.check_outputs() + self.build_elements.append(build) + + if build.rulename != 'phony': + # reference rule + if build.rulename in self.ruledict: + build.rule = self.ruledict[build.rulename] + else: + mlog.warning(f"build statement for {build.outfilenames} references nonexistent rule {build.rulename}") + + def write_rules(self, outfile): + for b in self.build_elements: + if isinstance(b, NinjaBuildElement): + b.count_rule_references() + + for r in self.rules: + r.write(outfile) + + def write_builds(self, outfile): + for b in ProgressBar(self.build_elements, desc='Writing build.ninja'): + b.write(outfile) + + def generate_phony(self): + self.add_build_comment(NinjaComment('Phony build target, always out of date')) + elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '') + self.add_build(elem) + + def generate_jar_target(self, target: build.Jar): + fname = target.get_filename() + outname_rel = os.path.join(self.get_target_dir(target), fname) + src_list = target.get_sources() + resources = target.get_java_resources() + class_list = [] + compiler = target.compilers['java'] + c = 'c' + m = 'm' + e = '' + f = 'f' + main_class = target.get_main_class() + if main_class != '': + e = 'e' + + # Add possible java generated files to src list + generated_sources = self.get_target_generated_sources(target) + gen_src_list = [] + for rel_src in generated_sources.keys(): + raw_src = File.from_built_relative(rel_src) + if rel_src.endswith('.java'): + gen_src_list.append(raw_src) + + compile_args = self.determine_single_java_compile_args(target, compiler) + for src in src_list + gen_src_list: + plain_class_path = self.generate_single_java_compile(src, target, compiler, compile_args) + class_list.append(plain_class_path) + class_dep_list = [os.path.join(self.get_target_private_dir(target), i) for i in class_list] + manifest_path = os.path.join(self.get_target_private_dir(target), 'META-INF', 'MANIFEST.MF') + manifest_fullpath = os.path.join(self.environment.get_build_dir(), manifest_path) + os.makedirs(os.path.dirname(manifest_fullpath), exist_ok=True) + with open(manifest_fullpath, 'w', encoding='utf-8') as manifest: + if any(target.link_targets): + manifest.write('Class-Path: ') + cp_paths = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] + manifest.write(' '.join(cp_paths)) + manifest.write('\n') + jar_rule = 'java_LINKER' + commands = [c + m + e + f] + commands.append(manifest_path) + if e != '': + commands.append(main_class) + commands.append(self.get_target_filename(target)) + # Java compilation can produce an arbitrary number of output + # class files for a single source file. Thus tell jar to just + # grab everything in the final package. + commands += ['-C', self.get_target_private_dir(target), '.'] + elem = NinjaBuildElement(self.all_outputs, outname_rel, jar_rule, []) + elem.add_dep(class_dep_list) + if resources: + # Copy all resources into the root of the jar. + elem.add_orderdep(self.__generate_sources_structure(Path(self.get_target_private_dir(target)), resources)[0]) + elem.add_item('ARGS', commands) + self.add_build(elem) + # Create introspection information + self.create_target_source_introspection(target, compiler, compile_args, src_list, gen_src_list) + + def generate_cs_resource_tasks(self, target): + args = [] + deps = [] + for r in target.resources: + rel_sourcefile = os.path.join(self.build_to_src, target.subdir, r) + if r.endswith('.resources'): + a = '-resource:' + rel_sourcefile + elif r.endswith('.txt') or r.endswith('.resx'): + ofilebase = os.path.splitext(os.path.basename(r))[0] + '.resources' + ofilename = os.path.join(self.get_target_private_dir(target), ofilebase) + elem = NinjaBuildElement(self.all_outputs, ofilename, "CUSTOM_COMMAND", rel_sourcefile) + elem.add_item('COMMAND', ['resgen', rel_sourcefile, ofilename]) + elem.add_item('DESC', f'Compiling resource {rel_sourcefile}') + self.add_build(elem) + deps.append(ofilename) + a = '-resource:' + ofilename + else: + raise InvalidArguments(f'Unknown resource file {r}.') + args.append(a) + return args, deps + + def generate_cs_target(self, target: build.BuildTarget): + buildtype = target.get_option(OptionKey('buildtype')) + fname = target.get_filename() + outname_rel = os.path.join(self.get_target_dir(target), fname) + src_list = target.get_sources() + compiler = target.compilers['cs'] + rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list] + deps = [] + commands = compiler.compiler_args(target.extra_args.get('cs', [])) + commands += compiler.get_buildtype_args(buildtype) + commands += compiler.get_optimization_args(target.get_option(OptionKey('optimization'))) + commands += compiler.get_debug_args(target.get_option(OptionKey('debug'))) + if isinstance(target, build.Executable): + commands.append('-target:exe') + elif isinstance(target, build.SharedLibrary): + commands.append('-target:library') + else: + raise MesonException('Unknown C# target type.') + (resource_args, resource_deps) = self.generate_cs_resource_tasks(target) + commands += resource_args + deps += resource_deps + commands += compiler.get_output_args(outname_rel) + for l in target.link_targets: + lname = os.path.join(self.get_target_dir(l), l.get_filename()) + commands += compiler.get_link_args(lname) + deps.append(lname) + if '-g' in commands: + outputs = [outname_rel, outname_rel + '.mdb'] + else: + outputs = [outname_rel] + generated_sources = self.get_target_generated_sources(target) + generated_rel_srcs = [] + for rel_src in generated_sources.keys(): + if rel_src.lower().endswith('.cs'): + generated_rel_srcs.append(os.path.normpath(rel_src)) + deps.append(os.path.normpath(rel_src)) + + for dep in target.get_external_deps(): + commands.extend_direct(dep.get_link_args()) + commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) + commands += self.build.get_global_args(compiler, target.for_machine) + + elem = NinjaBuildElement(self.all_outputs, outputs, self.compiler_to_rule_name(compiler), rel_srcs + generated_rel_srcs) + elem.add_dep(deps) + elem.add_item('ARGS', commands) + self.add_build(elem) + + self.generate_generator_list_rules(target) + self.create_target_source_introspection(target, compiler, commands, rel_srcs, generated_rel_srcs) + + def determine_single_java_compile_args(self, target, compiler): + args = [] + args += compiler.get_buildtype_args(target.get_option(OptionKey('buildtype'))) + args += self.build.get_global_args(compiler, target.for_machine) + args += self.build.get_project_args(compiler, target.subproject, target.for_machine) + args += target.get_java_args() + args += compiler.get_output_args(self.get_target_private_dir(target)) + args += target.get_classpath_args() + curdir = target.get_subdir() + sourcepath = os.path.join(self.build_to_src, curdir) + os.pathsep + sourcepath += os.path.normpath(curdir) + os.pathsep + for i in target.include_dirs: + for idir in i.get_incdirs(): + sourcepath += os.path.join(self.build_to_src, i.curdir, idir) + os.pathsep + args += ['-sourcepath', sourcepath] + return args + + def generate_single_java_compile(self, src, target, compiler, args): + deps = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] + generated_sources = self.get_target_generated_sources(target) + for rel_src in generated_sources.keys(): + if rel_src.endswith('.java'): + deps.append(rel_src) + rel_src = src.rel_to_builddir(self.build_to_src) + plain_class_path = src.fname[:-4] + 'class' + rel_obj = os.path.join(self.get_target_private_dir(target), plain_class_path) + element = NinjaBuildElement(self.all_outputs, rel_obj, self.compiler_to_rule_name(compiler), rel_src) + element.add_dep(deps) + element.add_item('ARGS', args) + self.add_build(element) + return plain_class_path + + def generate_java_link(self): + rule = 'java_LINKER' + command = ['jar', '$ARGS'] + description = 'Creating JAR $out' + self.add_rule(NinjaRule(rule, command, [], description)) + + def determine_dep_vapis(self, target): + """ + Peek into the sources of BuildTargets we're linking with, and if any of + them was built with Vala, assume that it also generated a .vapi file of + the same name as the BuildTarget and return the path to it relative to + the build directory. + """ + result = OrderedSet() + for dep in itertools.chain(target.link_targets, target.link_whole_targets): + if not dep.is_linkable_target(): + continue + for i in dep.sources: + if hasattr(i, 'fname'): + i = i.fname + if i.split('.')[-1] in compilers.lang_suffixes['vala']: + vapiname = dep.vala_vapi + fullname = os.path.join(self.get_target_dir(dep), vapiname) + result.add(fullname) + break + return list(result) + + def split_vala_sources(self, t: build.BuildTarget) -> \ + T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], + T.Tuple[T.MutableMapping[str, File], T.MutableMapping]]: + """ + Splits the target's sources into .vala, .gs, .vapi, and other sources. + Handles both preexisting and generated sources. + + Returns a tuple (vala, vapi, others) each of which is a dictionary with + the keys being the path to the file (relative to the build directory) + and the value being the object that generated or represents the file. + """ + vala: T.MutableMapping[str, File] = OrderedDict() + vapi: T.MutableMapping[str, File] = OrderedDict() + others: T.MutableMapping[str, File] = OrderedDict() + othersgen: T.MutableMapping[str, File] = OrderedDict() + # Split preexisting sources + for s in t.get_sources(): + # BuildTarget sources are always mesonlib.File files which are + # either in the source root, or generated with configure_file and + # in the build root + if not isinstance(s, File): + raise InvalidArguments(f'All sources in target {t!r} must be of type mesonlib.File, not {s!r}') + f = s.rel_to_builddir(self.build_to_src) + if s.endswith(('.vala', '.gs')): + srctype = vala + elif s.endswith('.vapi'): + srctype = vapi + else: + srctype = others + srctype[f] = s + # Split generated sources + for gensrc in t.get_generated_sources(): + for s in gensrc.get_outputs(): + f = self.get_target_generated_dir(t, gensrc, s) + if s.endswith(('.vala', '.gs')): + srctype = vala + elif s.endswith('.vapi'): + srctype = vapi + # Generated non-Vala (C/C++) sources. Won't be used for + # generating the Vala compile rule below. + else: + srctype = othersgen + # Duplicate outputs are disastrous + if f in srctype and srctype[f] is not gensrc: + msg = 'Duplicate output {0!r} from {1!r} {2!r}; ' \ + 'conflicts with {0!r} from {4!r} {3!r}' \ + ''.format(f, type(gensrc).__name__, gensrc.name, + srctype[f].name, type(srctype[f]).__name__) + raise InvalidArguments(msg) + # Store 'somefile.vala': GeneratedList (or CustomTarget) + srctype[f] = gensrc + return vala, vapi, (others, othersgen) + + def generate_vala_compile(self, target: build.BuildTarget) -> \ + T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], T.List[str]]: + """Vala is compiled into C. Set up all necessary build steps here.""" + (vala_src, vapi_src, other_src) = self.split_vala_sources(target) + extra_dep_files = [] + if not vala_src: + raise InvalidArguments(f'Vala library {target.name!r} has no Vala or Genie source files.') + + valac = target.compilers['vala'] + c_out_dir = self.get_target_private_dir(target) + # C files generated by valac + vala_c_src: T.List[str] = [] + # Files generated by valac + valac_outputs: T.List = [] + # All sources that are passed to valac on the commandline + all_files = list(vapi_src) + # Passed as --basedir + srcbasedir = os.path.join(self.build_to_src, target.get_subdir()) + for (vala_file, gensrc) in vala_src.items(): + all_files.append(vala_file) + # Figure out where the Vala compiler will write the compiled C file + # + # If the Vala file is in a subdir of the build dir (in our case + # because it was generated/built by something else), and is also + # a subdir of --basedir (because the builddir is in the source + # tree, and the target subdir is the source root), the subdir + # components from the source root till the private builddir will be + # duplicated inside the private builddir. Otherwise, just the + # basename will be used. + # + # If the Vala file is outside the build directory, the paths from + # the --basedir till the subdir will be duplicated inside the + # private builddir. + if isinstance(gensrc, (build.CustomTarget, build.GeneratedList)) or gensrc.is_built: + vala_c_file = os.path.splitext(os.path.basename(vala_file))[0] + '.c' + # Check if the vala file is in a subdir of --basedir + abs_srcbasedir = os.path.join(self.environment.get_source_dir(), target.get_subdir()) + abs_vala_file = os.path.join(self.environment.get_build_dir(), vala_file) + if PurePath(os.path.commonpath((abs_srcbasedir, abs_vala_file))) == PurePath(abs_srcbasedir): + vala_c_subdir = PurePath(abs_vala_file).parent.relative_to(abs_srcbasedir) + vala_c_file = os.path.join(str(vala_c_subdir), vala_c_file) + else: + path_to_target = os.path.join(self.build_to_src, target.get_subdir()) + if vala_file.startswith(path_to_target): + vala_c_file = os.path.splitext(os.path.relpath(vala_file, path_to_target))[0] + '.c' + else: + vala_c_file = os.path.splitext(os.path.basename(vala_file))[0] + '.c' + # All this will be placed inside the c_out_dir + vala_c_file = os.path.join(c_out_dir, vala_c_file) + vala_c_src.append(vala_c_file) + valac_outputs.append(vala_c_file) + + args = self.generate_basic_compiler_args(target, valac) + args += valac.get_colorout_args(target.get_option(OptionKey('b_colorout'))) + # Tell Valac to output everything in our private directory. Sadly this + # means it will also preserve the directory components of Vala sources + # found inside the build tree (generated sources). + args += ['--directory', c_out_dir] + args += ['--basedir', srcbasedir] + if target.is_linkable_target(): + # Library name + args += ['--library', target.name] + # Outputted header + hname = os.path.join(self.get_target_dir(target), target.vala_header) + args += ['--header', hname] + if target.is_unity: + # Without this the declarations will get duplicated in the .c + # files and cause a build failure when all of them are + # #include-d in one .c file. + # https://github.com/mesonbuild/meson/issues/1969 + args += ['--use-header'] + valac_outputs.append(hname) + # Outputted vapi file + vapiname = os.path.join(self.get_target_dir(target), target.vala_vapi) + # Force valac to write the vapi and gir files in the target build dir. + # Without this, it will write it inside c_out_dir + args += ['--vapi', os.path.join('..', target.vala_vapi)] + valac_outputs.append(vapiname) + # Install header and vapi to default locations if user requests this + if len(target.install_dir) > 1 and target.install_dir[1] is True: + target.install_dir[1] = self.environment.get_includedir() + if len(target.install_dir) > 2 and target.install_dir[2] is True: + target.install_dir[2] = os.path.join(self.environment.get_datadir(), 'vala', 'vapi') + # Generate GIR if requested + if isinstance(target.vala_gir, str): + girname = os.path.join(self.get_target_dir(target), target.vala_gir) + args += ['--gir', os.path.join('..', target.vala_gir)] + valac_outputs.append(girname) + # Install GIR to default location if requested by user + if len(target.install_dir) > 3 and target.install_dir[3] is True: + target.install_dir[3] = os.path.join(self.environment.get_datadir(), 'gir-1.0') + # Detect gresources and add --gresources arguments for each + for gensrc in other_src[1].values(): + if isinstance(gensrc, modules.GResourceTarget): + gres_xml, = self.get_custom_target_sources(gensrc) + args += ['--gresources=' + gres_xml] + extra_args = [] + + for a in target.extra_args.get('vala', []): + if isinstance(a, File): + relname = a.rel_to_builddir(self.build_to_src) + extra_dep_files.append(relname) + extra_args.append(relname) + else: + extra_args.append(a) + dependency_vapis = self.determine_dep_vapis(target) + extra_dep_files += dependency_vapis + args += extra_args + element = NinjaBuildElement(self.all_outputs, valac_outputs, + self.compiler_to_rule_name(valac), + all_files + dependency_vapis) + element.add_item('ARGS', args) + element.add_dep(extra_dep_files) + self.add_build(element) + self.create_target_source_introspection(target, valac, args, all_files, []) + return other_src[0], other_src[1], vala_c_src + + def generate_cython_transpile(self, target: build.BuildTarget) -> \ + T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], T.List[str]]: + """Generate rules for transpiling Cython files to C or C++ + + XXX: Currently only C is handled. + """ + static_sources: T.MutableMapping[str, File] = OrderedDict() + generated_sources: T.MutableMapping[str, File] = OrderedDict() + cython_sources: T.List[str] = [] + + cython = target.compilers['cython'] + + args: T.List[str] = [] + args += cython.get_always_args() + args += cython.get_buildtype_args(target.get_option(OptionKey('buildtype'))) + args += cython.get_debug_args(target.get_option(OptionKey('debug'))) + args += cython.get_optimization_args(target.get_option(OptionKey('optimization'))) + args += cython.get_option_compile_args(target.get_options()) + args += self.build.get_global_args(cython, target.for_machine) + args += self.build.get_project_args(cython, target.subproject, target.for_machine) + args += target.get_extra_args('cython') + + ext = target.get_option(OptionKey('language', machine=target.for_machine, lang='cython')) + + pyx_sources = [] # Keep track of sources we're adding to build + + for src in target.get_sources(): + if src.endswith('.pyx'): + output = os.path.join(self.get_target_private_dir(target), f'{src}.{ext}') + element = NinjaBuildElement( + self.all_outputs, [output], + self.compiler_to_rule_name(cython), + [src.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())]) + element.add_item('ARGS', args) + self.add_build(element) + # TODO: introspection? + cython_sources.append(output) + pyx_sources.append(element) + else: + static_sources[src.rel_to_builddir(self.build_to_src)] = src + + header_deps = [] # Keep track of generated headers for those sources + for gen in target.get_generated_sources(): + for ssrc in gen.get_outputs(): + if isinstance(gen, GeneratedList): + ssrc = os.path.join(self.get_target_private_dir(target), ssrc) + else: + ssrc = os.path.join(gen.get_subdir(), ssrc) + if ssrc.endswith('.pyx'): + output = os.path.join(self.get_target_private_dir(target), f'{ssrc}.{ext}') + element = NinjaBuildElement( + self.all_outputs, [output], + self.compiler_to_rule_name(cython), + [ssrc]) + element.add_item('ARGS', args) + self.add_build(element) + pyx_sources.append(element) + # TODO: introspection? + cython_sources.append(output) + else: + generated_sources[ssrc] = mesonlib.File.from_built_file(gen.get_subdir(), ssrc) + # Following logic in L883-900 where we determine whether to add generated source + # as a header(order-only) dep to the .so compilation rule + if not self.environment.is_source(ssrc) and \ + not self.environment.is_object(ssrc) and \ + not self.environment.is_library(ssrc) and \ + not modules.is_module_library(ssrc): + header_deps.append(ssrc) + for source in pyx_sources: + source.add_orderdep(header_deps) + + return static_sources, generated_sources, cython_sources + + def _generate_copy_target(self, src: 'mesonlib.FileOrString', output: Path) -> None: + """Create a target to copy a source file from one location to another.""" + if isinstance(src, File): + instr = src.absolute_path(self.environment.source_dir, self.environment.build_dir) + else: + instr = src + elem = NinjaBuildElement(self.all_outputs, [str(output)], 'COPY_FILE', [instr]) + elem.add_orderdep(instr) + self.add_build(elem) + + def __generate_sources_structure(self, root: Path, structured_sources: build.StructuredSources) -> T.Tuple[T.List[str], T.Optional[str]]: + first_file: T.Optional[str] = None + orderdeps: T.List[str] = [] + for path, files in structured_sources.sources.items(): + for file in files: + if isinstance(file, File): + out = root / path / Path(file.fname).name + orderdeps.append(str(out)) + self._generate_copy_target(file, out) + if first_file is None: + first_file = str(out) + else: + for f in file.get_outputs(): + out = root / path / f + orderdeps.append(str(out)) + self._generate_copy_target(str(Path(file.subdir) / f), out) + if first_file is None: + first_file = str(out) + return orderdeps, first_file + + def _add_rust_project_entry(self, name: str, main_rust_file: str, args: CompilerArgs, + from_subproject: bool, proc_macro_dylib_path: T.Optional[str], + deps: T.List[RustDep]) -> None: + raw_edition: T.Optional[str] = mesonlib.first(reversed(args), lambda x: x.startswith('--edition')) + edition: RUST_EDITIONS = '2015' if not raw_edition else raw_edition.split('=')[-1] + + cfg: T.List[str] = [] + arg_itr: T.Iterator[str] = iter(args) + for arg in arg_itr: + if arg == '--cfg': + cfg.append(next(arg_itr)) + elif arg.startswith('--cfg'): + cfg.append(arg[len('--cfg'):]) + + crate = RustCrate( + len(self.rust_crates), + name, + main_rust_file, + edition, + deps, + cfg, + is_workspace_member=not from_subproject, + is_proc_macro=proc_macro_dylib_path is not None, + proc_macro_dylib_path=proc_macro_dylib_path, + ) + + self.rust_crates[name] = crate + + def _get_rust_dependency_name(self, target: build.BuildTarget, dependency: LibTypes) -> str: + # Convert crate names with dashes to underscores by default like + # cargo does as dashes can't be used as parts of identifiers + # in Rust + return target.rust_dependency_map.get(dependency.name, dependency.name).replace('-', '_') + + def generate_rust_target(self, target: build.BuildTarget) -> None: + rustc = target.compilers['rust'] + # Rust compiler takes only the main file as input and + # figures out what other files are needed via import + # statements and magic. + base_proxy = target.get_options() + args = rustc.compiler_args() + # Compiler args for compiling this target + args += compilers.get_base_compile_args(base_proxy, rustc) + self.generate_generator_list_rules(target) + + # dependencies need to cause a relink, they're not just for ordering + deps = [ + os.path.join(t.subdir, t.get_filename()) + for t in itertools.chain(target.link_targets, target.link_whole_targets) + ] + + # Dependencies for rust-project.json + project_deps: T.List[RustDep] = [] + + orderdeps: T.List[str] = [] + + main_rust_file = None + if target.structured_sources: + if target.structured_sources.needs_copy(): + _ods, main_rust_file = self.__generate_sources_structure(Path( + self.get_target_private_dir(target)) / 'structured', target.structured_sources) + orderdeps.extend(_ods) + else: + # The only way to get here is to have only files in the "root" + # positional argument, which are all generated into the same + # directory + g = target.structured_sources.first_file() + + if isinstance(g, File): + main_rust_file = g.rel_to_builddir(self.build_to_src) + elif isinstance(g, GeneratedList): + main_rust_file = os.path.join(self.get_target_private_dir(target), g.get_outputs()[0]) + else: + main_rust_file = os.path.join(g.get_subdir(), g.get_outputs()[0]) + + for f in target.structured_sources.as_list(): + if isinstance(f, File): + orderdeps.append(f.rel_to_builddir(self.build_to_src)) + else: + orderdeps.extend([os.path.join(self.build_to_src, f.subdir, s) + for s in f.get_outputs()]) + + for i in target.get_sources(): + if not rustc.can_compile(i): + raise InvalidArguments(f'Rust target {target.get_basename()} contains a non-rust source file.') + if main_rust_file is None: + main_rust_file = i.rel_to_builddir(self.build_to_src) + for g in target.get_generated_sources(): + for i in g.get_outputs(): + if not rustc.can_compile(i): + raise InvalidArguments(f'Rust target {target.get_basename()} contains a non-rust source file.') + if isinstance(g, GeneratedList): + fname = os.path.join(self.get_target_private_dir(target), i) + else: + fname = os.path.join(g.get_subdir(), i) + if main_rust_file is None: + main_rust_file = fname + orderdeps.append(fname) + if main_rust_file is None: + raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report') + target_name = os.path.join(target.subdir, target.get_filename()) + if isinstance(target, build.Executable): + cratetype = 'bin' + elif hasattr(target, 'rust_crate_type'): + cratetype = target.rust_crate_type + elif isinstance(target, build.SharedLibrary): + cratetype = 'dylib' + elif isinstance(target, build.StaticLibrary): + cratetype = 'rlib' + else: + raise InvalidArguments('Unknown target type for rustc.') + args.extend(['--crate-type', cratetype]) + + # If we're dynamically linking, add those arguments + # + # Rust is super annoying, calling -C link-arg foo does not work, it has + # to be -C link-arg=foo + if cratetype in {'bin', 'dylib'}: + args.extend(rustc.get_linker_always_args()) + + args += self.generate_basic_compiler_args(target, rustc, False) + # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores + args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_').replace('.', '_')] + depfile = os.path.join(target.subdir, target.name + '.d') + args += ['--emit', f'dep-info={depfile}', '--emit', 'link'] + args += target.get_extra_args('rust') + output = rustc.get_output_args(os.path.join(target.subdir, target.get_filename())) + args += output + linkdirs = mesonlib.OrderedSet() + external_deps = target.external_deps.copy() + + # Have we already injected msvc-crt args? + # + # If we don't have A C, C++, or Fortran compiler that is + # VisualStudioLike treat this as if we've already injected them + # + # We handle this here rather than in the rust compiler because in + # general we don't want to link rust targets to a non-default crt. + # However, because of the way that MSCRTs work you can only link to one + # per target, so if A links to the debug one, and B links to the normal + # one you can't link A and B. Rust is hardcoded to the default one, + # so if we compile C/C++ code and link against a non-default MSCRT then + # linking will fail. We can work around this by injecting MSCRT link + # arguments early in the rustc command line + # https://github.com/rust-lang/rust/issues/39016 + crt_args_injected = not any(x is not None and x.get_argument_syntax() == 'msvc' for x in + (self.environment.coredata.compilers[target.for_machine].get(l) + for l in ['c', 'cpp', 'fortran'])) + + crt_link_args: T.List[str] = [] + try: + buildtype = target.get_option(OptionKey('buildtype')) + crt = target.get_option(OptionKey('b_vscrt')) + is_debug = buildtype == 'debug' + + if crt == 'from_buildtype': + crt = 'mdd' if is_debug else 'md' + elif crt == 'static_from_buildtype': + crt = 'mtd' if is_debug else 'mt' + + if crt == 'mdd': + crt_link_args = ['-l', 'static=msvcrtd'] + elif crt == 'md': + # this is the default, no need to inject anything + crt_args_injected = True + elif crt == 'mtd': + crt_link_args = ['-l', 'static=libcmtd'] + elif crt == 'mt': + crt_link_args = ['-l', 'static=libcmt'] + + except KeyError: + crt_args_injected = True + + # TODO: we likely need to use verbatim to handle name_prefix and name_suffix + for d in target.link_targets: + linkdirs.add(d.subdir) + # staticlib and cdylib provide a plain C ABI, i.e. contain no Rust + # metadata. As such they should be treated like any other external + # link target + if d.uses_rust() and d.rust_crate_type not in ['staticlib', 'cdylib']: + # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust + # dependency, so that collisions with libraries in rustc's + # sysroot don't cause ambiguity + d_name = self._get_rust_dependency_name(target, d) + args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] + project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) + continue + + if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): + args += crt_link_args + crt_args_injected = True + + if isinstance(d, build.StaticLibrary): + # Rustc doesn't follow Meson's convention that static libraries + # are called .a, and import libraries are .lib, so we have to + # manually handle that. + if rustc.linker.id in {'link', 'lld-link'}: + args += ['-C', f'link-arg={self.get_target_filename_for_linking(d)}'] + else: + args += ['-l', f'static={d.name}'] + external_deps.extend(d.external_deps) + else: + # Rust uses -l for non rust dependencies, but we still need to + # add dylib=foo + args += ['-l', f'dylib={d.name}'] + + # Since 1.61.0 Rust has a special modifier for whole-archive linking, + # before that it would treat linking two static libraries as + # whole-archive linking. However, to make this work we have to disable + # bundling, which can't be done until 1.63.0… So for 1.61–1.62 we just + # have to hope that the default cases of +whole-archive are sufficient. + # See: https://github.com/rust-lang/rust/issues/99429 + if mesonlib.version_compare(rustc.version, '>= 1.63.0'): + whole_archive = ':+whole-archive,-bundle' + else: + whole_archive = '' + + if mesonlib.version_compare(rustc.version, '>= 1.67.0'): + verbatim = ',+verbatim' + else: + verbatim = '' + + for d in target.link_whole_targets: + linkdirs.add(d.subdir) + if d.uses_rust(): + # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust + # dependency, so that collisions with libraries in rustc's + # sysroot don't cause ambiguity + d_name = self._get_rust_dependency_name(target, d) + args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] + project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) + else: + if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): + crt_args_injected = True + crt_args_injected = True + + if rustc.linker.id in {'link', 'lld-link'}: + if verbatim: + # If we can use the verbatim modifier, then everything is great + args += ['-l', f'static{whole_archive}{verbatim}={d.get_outputs()[0]}'] + elif isinstance(target, build.StaticLibrary): + # If we don't, for static libraries the only option is + # to make a copy, since we can't pass objects in, or + # directly affect the archiver. but we're not going to + # do that given how quickly rustc versions go out of + # support unless there's a compelling reason to do so. + # This only affects 1.61–1.66 + mlog.warning('Due to limitations in Rustc versions 1.61–1.66 and meson library naming', + 'whole-archive linking with MSVC may or may not work. Upgrade rustc to', + '>= 1.67. A best effort is being made, but likely won\'t work') + args += ['-l', f'static={d.name}'] + else: + # When doing dynamic linking (binaries and [c]dylibs), + # we can instead just proxy the correct arguments to the linker + for link_whole_arg in rustc.linker.get_link_whole_for([self.get_target_filename_for_linking(d)]): + args += ['-C', f'link-arg={link_whole_arg}'] + else: + args += ['-l', f'static{whole_archive}={d.name}'] + external_deps.extend(d.external_deps) + for e in external_deps: + for a in e.get_link_args(): + if a in rustc.native_static_libs: + # Exclude link args that rustc already add by default + continue + if a.endswith(('.dll', '.so', '.dylib', '.a', '.lib')): + dir_, lib = os.path.split(a) + linkdirs.add(dir_) + lib, ext = os.path.splitext(lib) + if lib.startswith('lib'): + lib = lib[3:] + _type = 'static' if a.endswith(('.a', '.lib')) else 'dylib' + args.extend(['-l', f'{_type}={lib}']) + elif a.startswith('-L'): + args.append(a) + elif a.startswith('-l'): + _type = 'static' if e.static else 'dylib' + args.extend(['-l', f'{_type}={a[2:]}']) + for d in linkdirs: + if d == '': + d = '.' + args += ['-L', d] + + # Because of the way rustc links, this must come after any potential + # library need to link with their stdlibs (C++ and Fortran, for example) + args.extend(target.get_used_stdlib_args('rust')) + + target_deps = target.get_dependencies() + has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps) + has_rust_shared_deps = any(dep.uses_rust() + and dep.rust_crate_type == 'dylib' + for dep in target_deps) + + if cratetype in {'dylib', 'proc-macro'} or has_rust_shared_deps: + # add prefer-dynamic if any of the Rust libraries we link + # against are dynamic or this is a dynamic library itself, + # otherwise we'll end up with multiple implementations of libstd. + args += ['-C', 'prefer-dynamic'] + + if isinstance(target, build.SharedLibrary) or has_shared_deps: + # build the usual rpath arguments as well... + + # Set runtime-paths so we can run executables without needing to set + # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows. + if has_path_sep(target.name): + # Target names really should not have slashes in them, but + # unfortunately we did not check for that and some downstream projects + # now have them. Once slashes are forbidden, remove this bit. + target_slashname_workaround_dir = os.path.join(os.path.dirname(target.name), + self.get_target_dir(target)) + else: + target_slashname_workaround_dir = self.get_target_dir(target) + rpath_args, target.rpath_dirs_to_remove = ( + rustc.build_rpath_args(self.environment, + self.environment.get_build_dir(), + target_slashname_workaround_dir, + self.determine_rpath_dirs(target), + target.build_rpath, + target.install_rpath)) + # ... but then add rustc's sysroot to account for rustup + # installations + for rpath_arg in rpath_args: + args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')] + + proc_macro_dylib_path = None + if getattr(target, 'rust_crate_type', '') == 'proc-macro': + proc_macro_dylib_path = os.path.abspath(os.path.join(target.subdir, target.get_filename())) + + self._add_rust_project_entry(target.name, + os.path.abspath(os.path.join(self.environment.build_dir, main_rust_file)), + args, + bool(target.subproject), + proc_macro_dylib_path, + project_deps) + + compiler_name = self.compiler_to_rule_name(rustc) + element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, main_rust_file) + if orderdeps: + element.add_orderdep(orderdeps) + if deps: + element.add_dep(deps) + element.add_item('ARGS', args) + element.add_item('targetdep', depfile) + element.add_item('cratetype', cratetype) + self.add_build(element) + if isinstance(target, build.SharedLibrary): + self.generate_shsym(target) + self.create_target_source_introspection(target, rustc, args, [main_rust_file], []) + + @staticmethod + def get_rule_suffix(for_machine: MachineChoice) -> str: + return PerMachine('_FOR_BUILD', '')[for_machine] + + @classmethod + def get_compiler_rule_name(cls, lang: str, for_machine: MachineChoice, mode: str = 'COMPILER') -> str: + return f'{lang}_{mode}{cls.get_rule_suffix(for_machine)}' + + @classmethod + def compiler_to_rule_name(cls, compiler: Compiler) -> str: + return cls.get_compiler_rule_name(compiler.get_language(), compiler.for_machine, compiler.mode) + + @classmethod + def compiler_to_pch_rule_name(cls, compiler: Compiler) -> str: + return cls.get_compiler_rule_name(compiler.get_language(), compiler.for_machine, 'PCH') + + def swift_module_file_name(self, target): + return os.path.join(self.get_target_private_dir(target), + self.target_swift_modulename(target) + '.swiftmodule') + + def target_swift_modulename(self, target): + return target.name + + def determine_swift_dep_modules(self, target): + result = [] + for l in target.link_targets: + if self.is_swift_target(l): + result.append(self.swift_module_file_name(l)) + return result + + def get_swift_link_deps(self, target): + result = [] + for l in target.link_targets: + result.append(self.get_target_filename(l)) + return result + + def split_swift_generated_sources(self, target): + all_srcs = self.get_target_generated_sources(target) + srcs = [] + others = [] + for i in all_srcs: + if i.endswith('.swift'): + srcs.append(i) + else: + others.append(i) + return srcs, others + + def generate_swift_target(self, target): + module_name = self.target_swift_modulename(target) + swiftc = target.compilers['swift'] + abssrc = [] + relsrc = [] + abs_headers = [] + header_imports = [] + for i in target.get_sources(): + if swiftc.can_compile(i): + rels = i.rel_to_builddir(self.build_to_src) + abss = os.path.normpath(os.path.join(self.environment.get_build_dir(), rels)) + relsrc.append(rels) + abssrc.append(abss) + elif self.environment.is_header(i): + relh = i.rel_to_builddir(self.build_to_src) + absh = os.path.normpath(os.path.join(self.environment.get_build_dir(), relh)) + abs_headers.append(absh) + header_imports += swiftc.get_header_import_args(absh) + else: + raise InvalidArguments(f'Swift target {target.get_basename()} contains a non-swift source file.') + os.makedirs(self.get_target_private_dir_abs(target), exist_ok=True) + compile_args = swiftc.get_compile_only_args() + compile_args += swiftc.get_optimization_args(target.get_option(OptionKey('optimization'))) + compile_args += swiftc.get_debug_args(target.get_option(OptionKey('debug'))) + compile_args += swiftc.get_module_args(module_name) + compile_args += self.build.get_project_args(swiftc, target.subproject, target.for_machine) + compile_args += self.build.get_global_args(swiftc, target.for_machine) + for i in reversed(target.get_include_dirs()): + basedir = i.get_curdir() + for d in i.get_incdirs(): + if d not in ('', '.'): + expdir = os.path.join(basedir, d) + else: + expdir = basedir + srctreedir = os.path.normpath(os.path.join(self.environment.get_build_dir(), self.build_to_src, expdir)) + sargs = swiftc.get_include_args(srctreedir, False) + compile_args += sargs + link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))) + link_args += self.build.get_project_link_args(swiftc, target.subproject, target.for_machine) + link_args += self.build.get_global_link_args(swiftc, target.for_machine) + rundir = self.get_target_private_dir(target) + out_module_name = self.swift_module_file_name(target) + in_module_files = self.determine_swift_dep_modules(target) + abs_module_dirs = self.determine_swift_dep_dirs(target) + module_includes = [] + for x in abs_module_dirs: + module_includes += swiftc.get_include_args(x, False) + link_deps = self.get_swift_link_deps(target) + abs_link_deps = [os.path.join(self.environment.get_build_dir(), x) for x in link_deps] + for d in target.link_targets: + reldir = self.get_target_dir(d) + if reldir == '': + reldir = '.' + link_args += ['-L', os.path.normpath(os.path.join(self.environment.get_build_dir(), reldir))] + (rel_generated, _) = self.split_swift_generated_sources(target) + abs_generated = [os.path.join(self.environment.get_build_dir(), x) for x in rel_generated] + # We need absolute paths because swiftc needs to be invoked in a subdir + # and this is the easiest way about it. + objects = [] # Relative to swift invocation dir + rel_objects = [] # Relative to build.ninja + for i in abssrc + abs_generated: + base = os.path.basename(i) + oname = os.path.splitext(base)[0] + '.o' + objects.append(oname) + rel_objects.append(os.path.join(self.get_target_private_dir(target), oname)) + + rulename = self.compiler_to_rule_name(swiftc) + + # Swiftc does not seem to be able to emit objects and module files in one go. + elem = NinjaBuildElement(self.all_outputs, rel_objects, rulename, abssrc) + elem.add_dep(in_module_files + rel_generated) + elem.add_dep(abs_headers) + elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes) + elem.add_item('RUNDIR', rundir) + self.add_build(elem) + elem = NinjaBuildElement(self.all_outputs, out_module_name, rulename, abssrc) + elem.add_dep(in_module_files + rel_generated) + elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args()) + elem.add_item('RUNDIR', rundir) + self.add_build(elem) + if isinstance(target, build.StaticLibrary): + elem = self.generate_link(target, self.get_target_filename(target), + rel_objects, self.build.static_linker[target.for_machine]) + self.add_build(elem) + elif isinstance(target, build.Executable): + elem = NinjaBuildElement(self.all_outputs, self.get_target_filename(target), rulename, []) + elem.add_dep(rel_objects) + elem.add_dep(link_deps) + elem.add_item('ARGS', link_args + swiftc.get_std_exe_link_args() + objects + abs_link_deps) + elem.add_item('RUNDIR', rundir) + self.add_build(elem) + else: + raise MesonException('Swift supports only executable and static library targets.') + # Introspection information + self.create_target_source_introspection(target, swiftc, compile_args + header_imports + module_includes, relsrc, rel_generated) + + def _rsp_options(self, tool: T.Union['Compiler', 'StaticLinker', 'DynamicLinker']) -> T.Dict[str, T.Union[bool, RSPFileSyntax]]: + """Helper method to get rsp options. + + rsp_file_syntax() is only guaranteed to be implemented if + can_linker_accept_rsp() returns True. + """ + options = {'rspable': tool.can_linker_accept_rsp()} + if options['rspable']: + options['rspfile_quote_style'] = tool.rsp_file_syntax() + return options + + def generate_static_link_rules(self): + num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value + if 'java' in self.environment.coredata.compilers.host: + self.generate_java_link() + for for_machine in MachineChoice: + static_linker = self.build.static_linker[for_machine] + if static_linker is None: + continue + rule = 'STATIC_LINKER{}'.format(self.get_rule_suffix(for_machine)) + cmdlist: T.List[T.Union[str, NinjaCommandArg]] = [] + args = ['$in'] + # FIXME: Must normalize file names with pathlib.Path before writing + # them out to fix this properly on Windows. See: + # https://github.com/mesonbuild/meson/issues/1517 + # https://github.com/mesonbuild/meson/issues/1526 + if isinstance(static_linker, ArLikeLinker) and not mesonlib.is_windows(): + # `ar` has no options to overwrite archives. It always appends, + # which is never what we want. Delete an existing library first if + # it exists. https://github.com/mesonbuild/meson/issues/1355 + cmdlist = execute_wrapper + [c.format('$out') for c in rmfile_prefix] + cmdlist += static_linker.get_exelist() + cmdlist += ['$LINK_ARGS'] + cmdlist += NinjaCommandArg.list(static_linker.get_output_args('$out'), Quoting.none) + # The default ar on MacOS (at least through version 12), does not + # add extern'd variables to the symbol table by default, and + # requires that apple's ranlib be called with a special flag + # instead after linking + if static_linker.id == 'applear': + # This is a bit of a hack, but we assume that that we won't need + # an rspfile on MacOS, otherwise the arguments are passed to + # ranlib, not to ar + cmdlist.extend(args) + args = [] + cmdlist.extend(['&&', 'ranlib', '-c', '$out']) + description = 'Linking static target $out' + if num_pools > 0: + pool = 'pool = link_pool' + else: + pool = None + + options = self._rsp_options(static_linker) + self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=pool)) + + def generate_dynamic_link_rules(self): + num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value + for for_machine in MachineChoice: + complist = self.environment.coredata.compilers[for_machine] + for langname, compiler in complist.items(): + if langname in {'java', 'vala', 'rust', 'cs', 'cython'}: + continue + rule = '{}_LINKER{}'.format(langname, self.get_rule_suffix(for_machine)) + command = compiler.get_linker_exelist() + args = ['$ARGS'] + NinjaCommandArg.list(compiler.get_linker_output_args('$out'), Quoting.none) + ['$in', '$LINK_ARGS'] + description = 'Linking target $out' + if num_pools > 0: + pool = 'pool = link_pool' + else: + pool = None + + options = self._rsp_options(compiler) + self.add_rule(NinjaRule(rule, command, args, description, **options, extra=pool)) + if self.environment.machines[for_machine].is_aix(): + rule = 'AIX_LINKER{}'.format(self.get_rule_suffix(for_machine)) + description = 'Archiving AIX shared library' + cmdlist = compiler.get_command_to_archive_shlib() + args = [] + options = {} + self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=None)) + + args = self.environment.get_build_command() + \ + ['--internal', + 'symbolextractor', + self.environment.get_build_dir(), + '$in', + '$IMPLIB', + '$out'] + symrule = 'SHSYM' + symcmd = args + ['$CROSS'] + syndesc = 'Generating symbol file $out' + synstat = 'restat = 1' + self.add_rule(NinjaRule(symrule, symcmd, [], syndesc, extra=synstat)) + + def generate_java_compile_rule(self, compiler): + rule = self.compiler_to_rule_name(compiler) + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Java object $in' + self.add_rule(NinjaRule(rule, command, [], description)) + + def generate_cs_compile_rule(self, compiler: 'CsCompiler') -> None: + rule = self.compiler_to_rule_name(compiler) + command = compiler.get_exelist() + args = ['$ARGS', '$in'] + description = 'Compiling C Sharp target $out' + self.add_rule(NinjaRule(rule, command, args, description, + rspable=mesonlib.is_windows(), + rspfile_quote_style=compiler.rsp_file_syntax())) + + def generate_vala_compile_rules(self, compiler): + rule = self.compiler_to_rule_name(compiler) + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Vala source $in' + self.add_rule(NinjaRule(rule, command, [], description, extra='restat = 1')) + + def generate_cython_compile_rules(self, compiler: 'Compiler') -> None: + rule = self.compiler_to_rule_name(compiler) + description = 'Compiling Cython source $in' + command = compiler.get_exelist() + + depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') + depfile = '$out.dep' if depargs else None + + args = depargs + ['$ARGS', '$in'] + args += NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + self.add_rule(NinjaRule(rule, command + args, [], + description, + depfile=depfile, + extra='restat = 1')) + + def generate_rust_compile_rules(self, compiler): + rule = self.compiler_to_rule_name(compiler) + command = compiler.get_exelist() + ['$ARGS', '$in'] + description = 'Compiling Rust source $in' + depfile = '$targetdep' + depstyle = 'gcc' + self.add_rule(NinjaRule(rule, command, [], description, deps=depstyle, + depfile=depfile)) + + def generate_swift_compile_rules(self, compiler): + rule = self.compiler_to_rule_name(compiler) + full_exe = self.environment.get_build_command() + [ + '--internal', + 'dirchanger', + '$RUNDIR', + ] + invoc = full_exe + compiler.get_exelist() + command = invoc + ['$ARGS', '$in'] + description = 'Compiling Swift source $in' + self.add_rule(NinjaRule(rule, command, [], description)) + + def use_dyndeps_for_fortran(self) -> bool: + '''Use the new Ninja feature for scanning dependencies during build, + rather than up front. Remove this and all old scanning code once Ninja + minimum version is bumped to 1.10.''' + return mesonlib.version_compare(self.ninja_version, '>=1.10.0') + + def generate_fortran_dep_hack(self, crstr: str) -> None: + if self.use_dyndeps_for_fortran(): + return + rule = f'FORTRAN_DEP_HACK{crstr}' + if mesonlib.is_windows(): + cmd = ['cmd', '/C'] + else: + cmd = ['true'] + self.add_rule_comment(NinjaComment('''Workaround for these issues: +https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) + self.add_rule(NinjaRule(rule, cmd, [], 'Dep hack', extra='restat = 1')) + + def generate_llvm_ir_compile_rule(self, compiler): + if self.created_llvm_ir_rule[compiler.for_machine]: + return + rule = self.get_compiler_rule_name('llvm_ir', compiler.for_machine) + command = compiler.get_exelist() + args = ['$ARGS'] + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + compiler.get_compile_only_args() + ['$in'] + description = 'Compiling LLVM IR object $in' + + options = self._rsp_options(compiler) + + self.add_rule(NinjaRule(rule, command, args, description, **options)) + self.created_llvm_ir_rule[compiler.for_machine] = True + + def generate_compile_rule_for(self, langname, compiler): + if langname == 'java': + self.generate_java_compile_rule(compiler) + return + if langname == 'cs': + if self.environment.machines.matches_build_machine(compiler.for_machine): + self.generate_cs_compile_rule(compiler) + return + if langname == 'vala': + self.generate_vala_compile_rules(compiler) + return + if langname == 'rust': + self.generate_rust_compile_rules(compiler) + return + if langname == 'swift': + if self.environment.machines.matches_build_machine(compiler.for_machine): + self.generate_swift_compile_rules(compiler) + return + if langname == 'cython': + self.generate_cython_compile_rules(compiler) + return + crstr = self.get_rule_suffix(compiler.for_machine) + options = self._rsp_options(compiler) + if langname == 'fortran': + self.generate_fortran_dep_hack(crstr) + # gfortran does not update the modification time of *.mod files, therefore restat is needed. + # See also: https://github.com/ninja-build/ninja/pull/2275 + options['extra'] = 'restat = 1' + rule = self.compiler_to_rule_name(compiler) + depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$out', '$DEPFILE'), Quoting.none) + command = compiler.get_exelist() + args = ['$ARGS'] + depargs + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + compiler.get_compile_only_args() + ['$in'] + description = f'Compiling {compiler.get_display_language()} object $out' + if compiler.get_argument_syntax() == 'msvc': + deps = 'msvc' + depfile = None + else: + deps = 'gcc' + depfile = '$DEPFILE' + self.add_rule(NinjaRule(rule, command, args, description, **options, + deps=deps, depfile=depfile)) + + def generate_pch_rule_for(self, langname, compiler): + if langname not in {'c', 'cpp'}: + return + rule = self.compiler_to_pch_rule_name(compiler) + depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') + + if compiler.get_argument_syntax() == 'msvc': + output = [] + else: + output = NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + + if 'mwcc' in compiler.id: + output[0].s = '-precompile' + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + ['$in'] # '-c' must be removed + else: + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + compiler.get_compile_only_args() + ['$in'] + description = 'Precompiling header $in' + if compiler.get_argument_syntax() == 'msvc': + deps = 'msvc' + depfile = None + else: + deps = 'gcc' + depfile = '$DEPFILE' + self.add_rule(NinjaRule(rule, command, [], description, deps=deps, + depfile=depfile)) + + def generate_scanner_rules(self): + rulename = 'depscan' + if rulename in self.ruledict: + # Scanning command is the same for native and cross compilation. + return + command = self.environment.get_build_command() + \ + ['--internal', 'depscan'] + args = ['$picklefile', '$out', '$in'] + description = 'Module scanner.' + rule = NinjaRule(rulename, command, args, description) + self.add_rule(rule) + + def generate_compile_rules(self): + for for_machine in MachineChoice: + clist = self.environment.coredata.compilers[for_machine] + for langname, compiler in clist.items(): + if compiler.get_id() == 'clang': + self.generate_llvm_ir_compile_rule(compiler) + self.generate_compile_rule_for(langname, compiler) + self.generate_pch_rule_for(langname, compiler) + for mode in compiler.get_modes(): + self.generate_compile_rule_for(langname, mode) + + def generate_generator_list_rules(self, target): + # CustomTargets have already written their rules and + # CustomTargetIndexes don't actually get generated, so write rules for + # GeneratedLists here + for genlist in target.get_generated_sources(): + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): + continue + self.generate_genlist_for_target(genlist, target) + + def replace_paths(self, target, args, override_subdir=None): + if override_subdir: + source_target_dir = os.path.join(self.build_to_src, override_subdir) + else: + source_target_dir = self.get_target_source_dir(target) + relout = self.get_target_private_dir(target) + args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout) + for x in args] + args = [x.replace("@CURRENT_SOURCE_DIR@", source_target_dir) for x in args] + args = [x.replace("@SOURCE_ROOT@", self.build_to_src).replace("@BUILD_ROOT@", '.') + for x in args] + args = [x.replace('\\', '/') for x in args] + return args + + def generate_genlist_for_target(self, genlist: build.GeneratedList, target: build.BuildTarget) -> None: + for x in genlist.depends: + if isinstance(x, build.GeneratedList): + self.generate_genlist_for_target(x, target) + generator = genlist.get_generator() + subdir = genlist.subdir + exe = generator.get_exe() + infilelist = genlist.get_inputs() + outfilelist = genlist.get_outputs() + extra_dependencies = self.get_custom_target_depend_files(genlist) + for i, curfile in enumerate(infilelist): + if len(generator.outputs) == 1: + sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) + else: + sole_output = f'{curfile}' + infilename = curfile.rel_to_builddir(self.build_to_src, self.get_target_private_dir(target)) + base_args = generator.get_arglist(infilename) + outfiles = genlist.get_outputs_for(curfile) + outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles] + if generator.depfile is None: + rulename = 'CUSTOM_COMMAND' + args = base_args + else: + rulename = 'CUSTOM_COMMAND_DEP' + depfilename = generator.get_dep_outname(infilename) + depfile = os.path.join(self.get_target_private_dir(target), depfilename) + args = [x.replace('@DEPFILE@', depfile) for x in base_args] + args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) + for x in args] + args = self.replace_outputs(args, self.get_target_private_dir(target), outfilelist) + # We have consumed output files, so drop them from the list of remaining outputs. + if len(generator.outputs) > 1: + outfilelist = outfilelist[len(generator.outputs):] + args = self.replace_paths(target, args, override_subdir=subdir) + cmdlist, reason = self.as_meson_exe_cmdline(exe, + self.replace_extra_args(args, genlist), + capture=outfiles[0] if generator.capture else None) + abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + os.makedirs(abs_pdir, exist_ok=True) + + elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename) + elem.add_dep([self.get_target_filename(x) for x in generator.depends]) + if generator.depfile is not None: + elem.add_item('DEPFILE', depfile) + if len(extra_dependencies) > 0: + elem.add_dep(extra_dependencies) + + if len(generator.outputs) == 1: + what = f'{sole_output!r}' + else: + # since there are multiple outputs, we log the source that caused the rebuild + what = f'from {sole_output!r}' + if reason: + reason = f' (wrapped by meson {reason})' + elem.add_item('DESC', f'Generating {what}{reason}') + + if isinstance(exe, build.BuildTarget): + elem.add_dep(self.get_target_filename(exe)) + elem.add_item('COMMAND', cmdlist) + self.add_build(elem) + + def scan_fortran_module_outputs(self, target): + """ + Find all module and submodule made available in a Fortran code file. + """ + if self.use_dyndeps_for_fortran(): + return + compiler = None + # TODO other compilers + for lang, c in self.environment.coredata.compilers.host.items(): + if lang == 'fortran': + compiler = c + break + if compiler is None: + self.fortran_deps[target.get_basename()] = {} + return + + modre = re.compile(FORTRAN_MODULE_PAT, re.IGNORECASE) + submodre = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE) + module_files = {} + submodule_files = {} + for s in target.get_sources(): + # FIXME, does not work for Fortran sources generated by + # custom_target() and generator() as those are run after + # the configuration (configure_file() is OK) + if not compiler.can_compile(s): + continue + filename = s.absolute_path(self.environment.get_source_dir(), + self.environment.get_build_dir()) + # Fortran keywords must be ASCII. + with open(filename, encoding='ascii', errors='ignore') as f: + for line in f: + modmatch = modre.match(line) + if modmatch is not None: + modname = modmatch.group(1).lower() + if modname in module_files: + raise InvalidArguments( + f'Namespace collision: module {modname} defined in ' + f'two files {module_files[modname]} and {s}.') + module_files[modname] = s + else: + submodmatch = submodre.match(line) + if submodmatch is not None: + # '_' is arbitrarily used to distinguish submod from mod. + parents = submodmatch.group(1).lower().split(':') + submodname = parents[0] + '_' + submodmatch.group(2).lower() + + if submodname in submodule_files: + raise InvalidArguments( + f'Namespace collision: submodule {submodname} defined in ' + f'two files {submodule_files[submodname]} and {s}.') + submodule_files[submodname] = s + + self.fortran_deps[target.get_basename()] = {**module_files, **submodule_files} + + def get_fortran_deps(self, compiler: FortranCompiler, src: Path, target) -> T.List[str]: + """ + Find all module and submodule needed by a Fortran target + """ + if self.use_dyndeps_for_fortran(): + return [] + + dirname = Path(self.get_target_private_dir(target)) + tdeps = self.fortran_deps[target.get_basename()] + srcdir = Path(self.source_dir) + + mod_files = _scan_fortran_file_deps(src, srcdir, dirname, tdeps, compiler) + return mod_files + + def get_no_stdlib_link_args(self, target, linker): + if hasattr(linker, 'language') and linker.language in self.build.stdlibs[target.for_machine]: + return linker.get_no_stdlib_link_args() + return [] + + def get_compile_debugfile_args(self, compiler, target, objfile): + # The way MSVC uses PDB files is documented exactly nowhere so + # the following is what we have been able to decipher via + # reverse engineering. + # + # Each object file gets the path of its PDB file written + # inside it. This can be either the final PDB (for, say, + # foo.exe) or an object pdb (for foo.obj). If the former, then + # each compilation step locks the pdb file for writing, which + # is a bottleneck and object files from one target cannot be + # used in a different target. The latter seems to be the + # sensible one (and what Unix does) but there is a catch. If + # you try to use precompiled headers MSVC will error out + # because both source and pch pdbs go in the same file and + # they must be the same. + # + # This means: + # + # - pch files must be compiled anew for every object file (negating + # the entire point of having them in the first place) + # - when using pch, output must go to the target pdb + # + # Since both of these are broken in some way, use the one that + # works for each target. This unfortunately means that you + # can't combine pch and object extraction in a single target. + # + # PDB files also lead to filename collisions. A target foo.exe + # has a corresponding foo.pdb. A shared library foo.dll _also_ + # has pdb file called foo.pdb. So will a static library + # foo.lib, which clobbers both foo.pdb _and_ the dll file's + # export library called foo.lib (by default, currently we name + # them libfoo.a to avoid this issue). You can give the files + # unique names such as foo_exe.pdb but VC also generates a + # bunch of other files which take their names from the target + # basename (i.e. "foo") and stomp on each other. + # + # CMake solves this problem by doing two things. First of all + # static libraries do not generate pdb files at + # all. Presumably you don't need them and VC is smart enough + # to look up the original data when linking (speculation, not + # tested). The second solution is that you can only have + # target named "foo" as an exe, shared lib _or_ static + # lib. This makes filename collisions not happen. The downside + # is that you can't have an executable foo that uses a shared + # library libfoo.so, which is a common idiom on Unix. + # + # If you feel that the above is completely wrong and all of + # this is actually doable, please send patches. + + if target.has_pch(): + tfilename = self.get_target_filename_abs(target) + return compiler.get_compile_debugfile_args(tfilename, pch=True) + else: + return compiler.get_compile_debugfile_args(objfile, pch=False) + + def get_link_debugfile_name(self, linker, target, outname): + return linker.get_link_debugfile_name(outname) + + def get_link_debugfile_args(self, linker, target, outname): + return linker.get_link_debugfile_args(outname) + + def generate_llvm_ir_compile(self, target, src): + base_proxy = target.get_options() + compiler = get_compiler_for_source(target.compilers.values(), src) + commands = compiler.compiler_args() + # Compiler args for compiling this target + commands += compilers.get_base_compile_args(base_proxy, compiler) + if isinstance(src, File): + if src.is_built: + src_filename = os.path.join(src.subdir, src.fname) + else: + src_filename = src.fname + elif os.path.isabs(src): + src_filename = os.path.basename(src) + else: + src_filename = src + obj_basename = self.canonicalize_filename(src_filename) + rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) + rel_obj += '.' + self.environment.machines[target.for_machine].get_object_suffix() + commands += self.get_compile_debugfile_args(compiler, target, rel_obj) + if isinstance(src, File) and src.is_built: + rel_src = src.fname + elif isinstance(src, File): + rel_src = src.rel_to_builddir(self.build_to_src) + else: + raise InvalidArguments(f'Invalid source type: {src!r}') + # Write the Ninja build command + compiler_name = self.get_compiler_rule_name('llvm_ir', compiler.for_machine) + element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) + element.add_item('ARGS', commands) + self.add_build(element) + return (rel_obj, rel_src) + + @lru_cache(maxsize=None) + def generate_inc_dir(self, compiler: 'Compiler', d: str, basedir: str, is_system: bool) -> \ + T.Tuple['ImmutableListProtocol[str]', 'ImmutableListProtocol[str]']: + # Avoid superfluous '/.' at the end of paths when d is '.' + if d not in ('', '.'): + expdir = os.path.normpath(os.path.join(basedir, d)) + else: + expdir = basedir + srctreedir = os.path.normpath(os.path.join(self.build_to_src, expdir)) + sargs = compiler.get_include_args(srctreedir, is_system) + # There may be include dirs where a build directory has not been + # created for some source dir. For example if someone does this: + # + # inc = include_directories('foo/bar/baz') + # + # But never subdir()s into the actual dir. + if os.path.isdir(os.path.join(self.environment.get_build_dir(), expdir)): + bargs = compiler.get_include_args(expdir, is_system) + else: + bargs = [] + return (sargs, bargs) + + def _generate_single_compile(self, target: build.BuildTarget, compiler: 'Compiler', + is_generated: bool = False) -> 'CompilerArgs': + commands = self._generate_single_compile_base_args(target, compiler) + commands += self._generate_single_compile_target_args(target, compiler, is_generated) + return commands + + def _generate_single_compile_base_args(self, target: build.BuildTarget, compiler: 'Compiler') -> 'CompilerArgs': + base_proxy = target.get_options() + # Create an empty commands list, and start adding arguments from + # various sources in the order in which they must override each other + commands = compiler.compiler_args() + # Start with symbol visibility. + commands += compiler.gnu_symbol_visibility_args(target.gnu_symbol_visibility) + # Add compiler args for compiling this target derived from 'base' build + # options passed on the command-line, in default_options, etc. + # These have the lowest priority. + commands += compilers.get_base_compile_args(base_proxy, + compiler) + return commands + + @lru_cache(maxsize=None) + def _generate_single_compile_target_args(self, target: build.BuildTarget, compiler: 'Compiler', + is_generated: bool = False) -> 'ImmutableListProtocol[str]': + # The code generated by valac is usually crap and has tons of unused + # variables and such, so disable warnings for Vala C sources. + no_warn_args = is_generated == 'vala' + # Add compiler args and include paths from several sources; defaults, + # build options, external dependencies, etc. + commands = self.generate_basic_compiler_args(target, compiler, no_warn_args) + # Add custom target dirs as includes automatically, but before + # target-specific include directories. + if target.implicit_include_directories: + commands += self.get_custom_target_dir_include_args(target, compiler) + # Add include dirs from the `include_directories:` kwarg on the target + # and from `include_directories:` of internal deps of the target. + # + # Target include dirs should override internal deps include dirs. + # This is handled in BuildTarget.process_kwargs() + # + # Include dirs from internal deps should override include dirs from + # external deps and must maintain the order in which they are specified. + # Hence, we must reverse the list so that the order is preserved. + for i in reversed(target.get_include_dirs()): + basedir = i.get_curdir() + # We should iterate include dirs in reversed orders because + # -Ipath will add to begin of array. And without reverse + # flags will be added in reversed order. + for d in reversed(i.get_incdirs()): + # Add source subdir first so that the build subdir overrides it + (compile_obj, includeargs) = self.generate_inc_dir(compiler, d, basedir, i.is_system) + commands += compile_obj + commands += includeargs + for d in i.get_extra_build_dirs(): + commands += compiler.get_include_args(d, i.is_system) + # Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these + # near the end since these are supposed to override everything else. + commands += self.escape_extra_args(target.get_extra_args(compiler.get_language())) + + # D specific additional flags + if compiler.language == 'd': + commands += compiler.get_feature_args(target.d_features, self.build_to_src) + + # Add source dir and build dir. Project-specific and target-specific + # include paths must override per-target compile args, include paths + # from external dependencies, internal dependencies, and from + # per-target `include_directories:` + # + # We prefer headers in the build dir over the source dir since, for + # instance, the user might have an srcdir == builddir Autotools build + # in their source tree. Many projects that are moving to Meson have + # both Meson and Autotools in parallel as part of the transition. + if target.implicit_include_directories: + commands += self.get_source_dir_include_args(target, compiler) + if target.implicit_include_directories: + commands += self.get_build_dir_include_args(target, compiler) + # Finally add the private dir for the target to the include path. This + # must override everything else and must be the final path added. + commands += compiler.get_include_args(self.get_target_private_dir(target), False) + return commands + + # Returns a dictionary, mapping from each compiler src type (e.g. 'c', 'cpp', etc.) to a list of compiler arg strings + # used for that respective src type. + # Currently used for the purpose of populating VisualStudio intellisense fields but possibly useful in other scenarios. + def generate_common_compile_args_per_src_type(self, target: build.BuildTarget) -> dict[str, list[str]]: + src_type_to_args = {} + + use_pch = self.target_uses_pch(target) + + for src_type_str in target.compilers.keys(): + compiler = target.compilers[src_type_str] + commands = self._generate_single_compile_base_args(target, compiler) + + # Include PCH header as first thing as it must be the first one or it will be + # ignored by gcc https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100462 + if use_pch and 'mw' not in compiler.id: + commands += self.get_pch_include_args(compiler, target) + + commands += self._generate_single_compile_target_args(target, compiler, is_generated=False) + + # Metrowerks compilers require PCH include args to come after intraprocedural analysis args + if use_pch and 'mw' in compiler.id: + commands += self.get_pch_include_args(compiler, target) + + commands = commands.compiler.compiler_args(commands) + + src_type_to_args[src_type_str] = commands.to_native() + return src_type_to_args + + def generate_single_compile(self, target: build.BuildTarget, src, + is_generated=False, header_deps=None, + order_deps: T.Optional[T.List['mesonlib.FileOrString']] = None, + extra_args: T.Optional[T.List[str]] = None, + unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None) -> None: + """ + Compiles C/C++, ObjC/ObjC++, Fortran, and D sources + """ + header_deps = header_deps if header_deps is not None else [] + order_deps = order_deps if order_deps is not None else [] + + if isinstance(src, str) and src.endswith('.h'): + raise AssertionError(f'BUG: sources should not contain headers {src!r}') + + compiler = get_compiler_for_source(target.compilers.values(), src) + commands = self._generate_single_compile_base_args(target, compiler) + + # Include PCH header as first thing as it must be the first one or it will be + # ignored by gcc https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100462 + use_pch = self.target_uses_pch(target) and is_generated != 'pch' + if use_pch and 'mw' not in compiler.id: + commands += self.get_pch_include_args(compiler, target) + + commands += self._generate_single_compile_target_args(target, compiler, is_generated) + + # Metrowerks compilers require PCH include args to come after intraprocedural analysis args + if use_pch and 'mw' in compiler.id: + commands += self.get_pch_include_args(compiler, target) + + commands = commands.compiler.compiler_args(commands) + + # Create introspection information + if is_generated is False: + self.create_target_source_introspection(target, compiler, commands, [src], [], unity_sources) + else: + self.create_target_source_introspection(target, compiler, commands, [], [src], unity_sources) + + build_dir = self.environment.get_build_dir() + if isinstance(src, File): + rel_src = src.rel_to_builddir(self.build_to_src) + if os.path.isabs(rel_src): + # Source files may not be from the source directory if they originate in source-only libraries, + # so we can't assert that the absolute path is anywhere in particular. + if src.is_built: + assert rel_src.startswith(build_dir) + rel_src = rel_src[len(build_dir) + 1:] + elif is_generated: + raise AssertionError(f'BUG: broken generated source file handling for {src!r}') + else: + raise InvalidArguments(f'Invalid source type: {src!r}') + obj_basename = self.object_filename_from_source(target, src) + rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) + dep_file = compiler.depfile_for_object(rel_obj) + + # Add MSVC debug file generation compile flags: /Fd /FS + commands += self.get_compile_debugfile_args(compiler, target, rel_obj) + + # PCH handling + if self.target_uses_pch(target): + pchlist = target.get_pch(compiler.language) + else: + pchlist = [] + if not pchlist: + pch_dep = [] + elif compiler.id == 'intel': + pch_dep = [] + else: + arr = [] + i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0])) + arr.append(i) + pch_dep = arr + + compiler_name = self.compiler_to_rule_name(compiler) + extra_deps = [] + if compiler.get_language() == 'fortran': + # Can't read source file to scan for deps if it's generated later + # at build-time. Skip scanning for deps, and just set the module + # outdir argument instead. + # https://github.com/mesonbuild/meson/issues/1348 + if not is_generated: + abs_src = Path(build_dir) / rel_src + extra_deps += self.get_fortran_deps(compiler, abs_src, target) + if not self.use_dyndeps_for_fortran(): + # Dependency hack. Remove once multiple outputs in Ninja is fixed: + # https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 + for modname, srcfile in self.fortran_deps[target.get_basename()].items(): + modfile = os.path.join(self.get_target_private_dir(target), + compiler.module_name_to_filename(modname)) + + if srcfile == src: + crstr = self.get_rule_suffix(target.for_machine) + depelem = NinjaBuildElement(self.all_outputs, + modfile, + 'FORTRAN_DEP_HACK' + crstr, + rel_obj) + self.add_build(depelem) + commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) + if extra_args is not None: + commands.extend(extra_args) + + element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) + self.add_header_deps(target, element, header_deps) + for d in extra_deps: + element.add_dep(d) + for d in order_deps: + if isinstance(d, File): + d = d.rel_to_builddir(self.build_to_src) + elif not self.has_dir_part(d): + d = os.path.join(self.get_target_private_dir(target), d) + element.add_orderdep(d) + element.add_dep(pch_dep) + for i in self.get_fortran_orderdeps(target, compiler): + element.add_orderdep(i) + if dep_file: + element.add_item('DEPFILE', dep_file) + element.add_item('ARGS', commands) + + self.add_dependency_scanner_entries_to_element(target, compiler, element, src) + self.add_build(element) + assert isinstance(rel_obj, str) + assert isinstance(rel_src, str) + return (rel_obj, rel_src.replace('\\', '/')) + + def add_dependency_scanner_entries_to_element(self, target, compiler, element, src): + if not self.should_use_dyndeps_for_target(target): + return + if isinstance(target, build.CompileTarget): + return + extension = os.path.splitext(src.fname)[1][1:] + if extension != 'C': + extension = extension.lower() + if not (extension in compilers.lang_suffixes['fortran'] or extension in compilers.lang_suffixes['cpp']): + return + dep_scan_file = self.get_dep_scan_file_for(target) + element.add_item('dyndep', dep_scan_file) + element.add_orderdep(dep_scan_file) + + def get_dep_scan_file_for(self, target): + return os.path.join(self.get_target_private_dir(target), 'depscan.dd') + + def add_header_deps(self, target, ninja_element, header_deps): + for d in header_deps: + if isinstance(d, File): + d = d.rel_to_builddir(self.build_to_src) + elif not self.has_dir_part(d): + d = os.path.join(self.get_target_private_dir(target), d) + ninja_element.add_dep(d) + + def has_dir_part(self, fname): + # FIXME FIXME: The usage of this is a terrible and unreliable hack + if isinstance(fname, File): + return fname.subdir != '' + return has_path_sep(fname) + + # Fortran is a bit weird (again). When you link against a library, just compiling a source file + # requires the mod files that are output when single files are built. To do this right we would need to + # scan all inputs and write out explicit deps for each file. That is stoo slow and too much effort so + # instead just have an ordered dependency on the library. This ensures all required mod files are created. + # The real deps are then detected via dep file generation from the compiler. This breaks on compilers that + # produce incorrect dep files but such is life. + def get_fortran_orderdeps(self, target, compiler): + if compiler.language != 'fortran': + return [] + return [ + os.path.join(self.get_target_dir(lt), lt.get_filename()) + for lt in itertools.chain(target.link_targets, target.link_whole_targets) + ] + + def generate_msvc_pch_command(self, target, compiler, pch): + header = pch[0] + pchname = compiler.get_pch_name(header) + dst = os.path.join(self.get_target_private_dir(target), pchname) + + commands = [] + commands += self.generate_basic_compiler_args(target, compiler) + + if len(pch) == 1: + # Auto generate PCH. + source = self.create_msvc_pch_implementation(target, compiler.get_language(), pch[0]) + pch_header_dir = os.path.dirname(os.path.join(self.build_to_src, target.get_source_subdir(), header)) + commands += compiler.get_include_args(pch_header_dir, False) + else: + source = os.path.join(self.build_to_src, target.get_source_subdir(), pch[1]) + + just_name = os.path.basename(header) + (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) + commands += pch_args + commands += self._generate_single_compile(target, compiler) + commands += self.get_compile_debugfile_args(compiler, target, objname) + dep = dst + '.' + compiler.get_depfile_suffix() + return commands, dep, dst, [objname], source + + def generate_gcc_pch_command(self, target, compiler, pch): + commands = self._generate_single_compile(target, compiler) + if pch.split('.')[-1] == 'h' and compiler.language == 'cpp': + # Explicitly compile pch headers as C++. If Clang is invoked in C++ mode, it actually warns if + # this option is not set, and for gcc it also makes sense to use it. + commands += ['-x', 'c++-header'] + dst = os.path.join(self.get_target_private_dir(target), + os.path.basename(pch) + '.' + compiler.get_pch_suffix()) + dep = dst + '.' + compiler.get_depfile_suffix() + return commands, dep, dst, [] # Gcc does not create an object file during pch generation. + + def generate_mwcc_pch_command(self, target, compiler, pch): + commands = self._generate_single_compile(target, compiler) + dst = os.path.join(self.get_target_private_dir(target), + os.path.basename(pch) + '.' + compiler.get_pch_suffix()) + dep = os.path.splitext(dst)[0] + '.' + compiler.get_depfile_suffix() + return commands, dep, dst, [] # mwcc compilers do not create an object file during pch generation. + + def generate_pch(self, target, header_deps=None): + header_deps = header_deps if header_deps is not None else [] + pch_objects = [] + for lang in ['c', 'cpp']: + pch = target.get_pch(lang) + if not pch: + continue + if not has_path_sep(pch[0]) or not has_path_sep(pch[-1]): + msg = f'Precompiled header of {target.get_basename()!r} must not be in the same ' \ + 'directory as source, please put it in a subdirectory.' + raise InvalidArguments(msg) + compiler: Compiler = target.compilers[lang] + if compiler.get_argument_syntax() == 'msvc': + (commands, dep, dst, objs, src) = self.generate_msvc_pch_command(target, compiler, pch) + extradep = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) + elif compiler.id == 'intel': + # Intel generates on target generation + continue + elif 'mwcc' in compiler.id: + src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) + (commands, dep, dst, objs) = self.generate_mwcc_pch_command(target, compiler, pch[0]) + extradep = None + else: + src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) + (commands, dep, dst, objs) = self.generate_gcc_pch_command(target, compiler, pch[0]) + extradep = None + pch_objects += objs + rulename = self.compiler_to_pch_rule_name(compiler) + elem = NinjaBuildElement(self.all_outputs, objs + [dst], rulename, src) + if extradep is not None: + elem.add_dep(extradep) + self.add_header_deps(target, elem, header_deps) + elem.add_item('ARGS', commands) + elem.add_item('DEPFILE', dep) + self.add_build(elem) + return pch_objects + + def get_target_shsym_filename(self, target): + # Always name the .symbols file after the primary build output because it always exists + targetdir = self.get_target_private_dir(target) + return os.path.join(targetdir, target.get_filename() + '.symbols') + + def generate_shsym(self, target): + target_file = self.get_target_filename(target) + symname = self.get_target_shsym_filename(target) + elem = NinjaBuildElement(self.all_outputs, symname, 'SHSYM', target_file) + # The library we will actually link to, which is an import library on Windows (not the DLL) + elem.add_item('IMPLIB', self.get_target_filename_for_linking(target)) + if self.environment.is_cross_build(): + elem.add_item('CROSS', '--cross-host=' + self.environment.machines[target.for_machine].system) + self.add_build(elem) + + def get_import_filename(self, target): + return os.path.join(self.get_target_dir(target), target.import_filename) + + def get_target_type_link_args(self, target, linker): + commands = [] + if isinstance(target, build.Executable): + # Currently only used with the Swift compiler to add '-emit-executable' + commands += linker.get_std_exe_link_args() + # If export_dynamic, add the appropriate linker arguments + if target.export_dynamic: + commands += linker.gen_export_dynamic_link_args(self.environment) + # If implib, and that's significant on this platform (i.e. Windows using either GCC or Visual Studio) + if target.import_filename: + commands += linker.gen_import_library_args(self.get_import_filename(target)) + if target.pie: + commands += linker.get_pie_link_args() + elif isinstance(target, build.SharedLibrary): + if isinstance(target, build.SharedModule): + commands += linker.get_std_shared_module_link_args(target.get_options()) + else: + commands += linker.get_std_shared_lib_link_args() + # All shared libraries are PIC + commands += linker.get_pic_args() + if not isinstance(target, build.SharedModule) or target.force_soname: + # Add -Wl,-soname arguments on Linux, -install_name on OS X + commands += linker.get_soname_args( + self.environment, target.prefix, target.name, target.suffix, + target.soversion, target.darwin_versions) + # This is only visited when building for Windows using either GCC or Visual Studio + if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): + commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) + # This is only visited when building for Windows using either GCC or Visual Studio + if target.import_filename: + commands += linker.gen_import_library_args(self.get_import_filename(target)) + elif isinstance(target, build.StaticLibrary): + commands += linker.get_std_link_args(self.environment, not target.should_install()) + else: + raise RuntimeError('Unknown build target type.') + return commands + + def get_target_type_link_args_post_dependencies(self, target, linker): + commands = [] + if isinstance(target, build.Executable): + # If gui_app is significant on this platform, add the appropriate linker arguments. + # Unfortunately this can't be done in get_target_type_link_args, because some misguided + # libraries (such as SDL2) add -mwindows to their link flags. + m = self.environment.machines[target.for_machine] + + if m.is_windows() or m.is_cygwin(): + if target.gui_app is not None: + commands += linker.get_gui_app_args(target.gui_app) + else: + commands += linker.get_win_subsystem_args(target.win_subsystem) + return commands + + def get_link_whole_args(self, linker, target): + use_custom = False + if linker.id == 'msvc': + # Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2 + # (incidentally, the "linker" here actually refers to cl.exe) + if mesonlib.version_compare(linker.version, '<19.00.23918'): + use_custom = True + + if use_custom: + objects_from_static_libs: T.List[ExtractedObjects] = [] + for dep in target.link_whole_targets: + l = dep.extract_all_objects(False) + objects_from_static_libs += self.determine_ext_objs(l, '') + objects_from_static_libs.extend(self.flatten_object_list(dep)[0]) + + return objects_from_static_libs + else: + target_args = self.build_target_link_arguments(linker, target.link_whole_targets) + return linker.get_link_whole_for(target_args) if target_args else [] + + @lru_cache(maxsize=None) + def guess_library_absolute_path(self, linker, libname, search_dirs, patterns) -> Path: + from ..compilers.c import CCompiler + for d in search_dirs: + for p in patterns: + trial = CCompiler._get_trials_from_pattern(p, d, libname) + if not trial: + continue + trial = CCompiler._get_file_from_list(self.environment, trial) + if not trial: + continue + # Return the first result + return trial + + def guess_external_link_dependencies(self, linker, target, commands, internal): + # Ideally the linker would generate dependency information that could be used. + # But that has 2 problems: + # * currently ld cannot create dependency information in a way that ninja can use: + # https://sourceware.org/bugzilla/show_bug.cgi?id=22843 + # * Meson optimizes libraries from the same build using the symbol extractor. + # Just letting ninja use ld generated dependencies would undo this optimization. + search_dirs = OrderedSet() + libs = OrderedSet() + absolute_libs = [] + + build_dir = self.environment.get_build_dir() + # the following loop sometimes consumes two items from command in one pass + it = iter(linker.native_args_to_unix(commands)) + for item in it: + if item in internal and not item.startswith('-'): + continue + + if item.startswith('-L'): + if len(item) > 2: + path = item[2:] + else: + try: + path = next(it) + except StopIteration: + mlog.warning("Generated linker command has -L argument without following path") + break + if not os.path.isabs(path): + path = os.path.join(build_dir, path) + search_dirs.add(path) + elif item.startswith('-l'): + if len(item) > 2: + lib = item[2:] + else: + try: + lib = next(it) + except StopIteration: + mlog.warning("Generated linker command has '-l' argument without following library name") + break + libs.add(lib) + elif os.path.isabs(item) and self.environment.is_library(item) and os.path.isfile(item): + absolute_libs.append(item) + + guessed_dependencies = [] + # TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker + try: + static_patterns = linker.get_library_naming(self.environment, LibType.STATIC, strict=True) + shared_patterns = linker.get_library_naming(self.environment, LibType.SHARED, strict=True) + search_dirs = tuple(search_dirs) + tuple(linker.get_library_dirs(self.environment)) + for libname in libs: + # be conservative and record most likely shared and static resolution, because we don't know exactly + # which one the linker will prefer + staticlibs = self.guess_library_absolute_path(linker, libname, + search_dirs, static_patterns) + sharedlibs = self.guess_library_absolute_path(linker, libname, + search_dirs, shared_patterns) + if staticlibs: + guessed_dependencies.append(staticlibs.resolve().as_posix()) + if sharedlibs: + guessed_dependencies.append(sharedlibs.resolve().as_posix()) + except (mesonlib.MesonException, AttributeError) as e: + if 'get_library_naming' not in str(e): + raise + + return guessed_dependencies + absolute_libs + + def generate_prelink(self, target, obj_list): + assert isinstance(target, build.StaticLibrary) + prelink_name = os.path.join(self.get_target_private_dir(target), target.name + '-prelink.o') + elem = NinjaBuildElement(self.all_outputs, [prelink_name], 'CUSTOM_COMMAND', obj_list) + + prelinker = target.get_prelinker() + cmd = prelinker.exelist[:] + cmd += prelinker.get_prelink_args(prelink_name, obj_list) + + cmd = self.replace_paths(target, cmd) + elem.add_item('COMMAND', cmd) + elem.add_item('description', f'Prelinking {prelink_name}.') + self.add_build(elem) + return [prelink_name] + + def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T.Union['Compiler', 'StaticLinker'], extra_args=None, stdlib_args=None): + extra_args = extra_args if extra_args is not None else [] + stdlib_args = stdlib_args if stdlib_args is not None else [] + implicit_outs = [] + if isinstance(target, build.StaticLibrary): + linker_base = 'STATIC' + else: + linker_base = linker.get_language() # Fixme. + if isinstance(target, build.SharedLibrary): + self.generate_shsym(target) + crstr = self.get_rule_suffix(target.for_machine) + linker_rule = linker_base + '_LINKER' + crstr + # Create an empty commands list, and start adding link arguments from + # various sources in the order in which they must override each other + # starting from hard-coded defaults followed by build options and so on. + # + # Once all the linker options have been passed, we will start passing + # libraries and library paths from internal and external sources. + commands = linker.compiler_args() + # First, the trivial ones that are impossible to override. + # + # Add linker args for linking this target derived from 'base' build + # options passed on the command-line, in default_options, etc. + # These have the lowest priority. + if isinstance(target, build.StaticLibrary): + commands += linker.get_base_link_args(target.get_options()) + else: + commands += compilers.get_base_link_args(target.get_options(), + linker, + isinstance(target, build.SharedModule), + self.environment.get_build_dir()) + # Add -nostdlib if needed; can't be overridden + commands += self.get_no_stdlib_link_args(target, linker) + # Add things like /NOLOGO; usually can't be overridden + commands += linker.get_linker_always_args() + # Add buildtype linker args: optimization level, etc. + commands += linker.get_buildtype_linker_args(target.get_option(OptionKey('buildtype'))) + # Add /DEBUG and the pdb filename when using MSVC + if target.get_option(OptionKey('debug')): + commands += self.get_link_debugfile_args(linker, target, outname) + debugfile = self.get_link_debugfile_name(linker, target, outname) + if debugfile is not None: + implicit_outs += [debugfile] + # Add link args specific to this BuildTarget type, such as soname args, + # PIC, import library generation, etc. + commands += self.get_target_type_link_args(target, linker) + # Archives that are copied wholesale in the result. Must be before any + # other link targets so missing symbols from whole archives are found in those. + if not isinstance(target, build.StaticLibrary): + commands += self.get_link_whole_args(linker, target) + + if not isinstance(target, build.StaticLibrary): + # Add link args added using add_project_link_arguments() + commands += self.build.get_project_link_args(linker, target.subproject, target.for_machine) + # Add link args added using add_global_link_arguments() + # These override per-project link arguments + commands += self.build.get_global_link_args(linker, target.for_machine) + # Link args added from the env: LDFLAGS. We want these to override + # all the defaults but not the per-target link args. + commands += self.environment.coredata.get_external_link_args(target.for_machine, linker.get_language()) + + # Now we will add libraries and library paths from various sources + + # Set runtime-paths so we can run executables without needing to set + # LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows. + if has_path_sep(target.name): + # Target names really should not have slashes in them, but + # unfortunately we did not check for that and some downstream projects + # now have them. Once slashes are forbidden, remove this bit. + target_slashname_workaround_dir = os.path.join( + os.path.dirname(target.name), + self.get_target_dir(target)) + else: + target_slashname_workaround_dir = self.get_target_dir(target) + (rpath_args, target.rpath_dirs_to_remove) = ( + linker.build_rpath_args(self.environment, + self.environment.get_build_dir(), + target_slashname_workaround_dir, + self.determine_rpath_dirs(target), + target.build_rpath, + target.install_rpath)) + commands += rpath_args + + # Add link args to link to all internal libraries (link_with:) and + # internal dependencies needed by this target. + if linker_base == 'STATIC': + # Link arguments of static libraries are not put in the command + # line of the library. They are instead appended to the command + # line where the static library is used. + dependencies = [] + else: + dependencies = target.get_dependencies() + internal = self.build_target_link_arguments(linker, dependencies) + #In AIX since shared libraries are archived the dependencies must + #depend on .a file with the .so and not directly on the .so file. + if self.environment.machines[target.for_machine].is_aix(): + for i, val in enumerate(internal): + internal[i] = linker.get_archive_name(val) + commands += internal + # Only non-static built targets need link args and link dependencies + if not isinstance(target, build.StaticLibrary): + # For 'automagic' deps: Boost and GTest. Also dependency('threads'). + # pkg-config puts the thread flags itself via `Cflags:` + + commands += linker.get_target_link_args(target) + # External deps must be last because target link libraries may depend on them. + for dep in target.get_external_deps(): + # Extend without reordering or de-dup to preserve `-L -l` sets + # https://github.com/mesonbuild/meson/issues/1718 + commands.extend_preserving_lflags(linker.get_dependency_link_args(dep)) + for d in target.get_dependencies(): + if isinstance(d, build.StaticLibrary): + for dep in d.get_external_deps(): + commands.extend_preserving_lflags(linker.get_dependency_link_args(dep)) + + # Add link args specific to this BuildTarget type that must not be overridden by dependencies + commands += self.get_target_type_link_args_post_dependencies(target, linker) + + # Add link args for c_* or cpp_* build options. Currently this only + # adds c_winlibs and cpp_winlibs when building for Windows. This needs + # to be after all internal and external libraries so that unresolved + # symbols from those can be found here. This is needed when the + # *_winlibs that we want to link to are static mingw64 libraries. + if isinstance(linker, Compiler): + # The static linker doesn't know what language it is building, so we + # don't know what option. Fortunately, it doesn't care to see the + # language-specific options either. + # + # We shouldn't check whether we are making a static library, because + # in the LTO case we do use a real compiler here. + commands += linker.get_option_link_args(target.get_options()) + + dep_targets = [] + dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal)) + + # Add libraries generated by custom targets + custom_target_libraries = self.get_custom_target_provided_libraries(target) + commands += extra_args + commands += custom_target_libraries + commands += stdlib_args # Standard library arguments go last, because they never depend on anything. + dep_targets.extend([self.get_dependency_filename(t) for t in dependencies]) + dep_targets.extend([self.get_dependency_filename(t) + for t in target.link_depends]) + elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list, implicit_outs=implicit_outs) + elem.add_dep(dep_targets + custom_target_libraries) + elem.add_item('LINK_ARGS', commands) + self.create_target_linker_introspection(target, linker, commands) + return elem + + def get_dependency_filename(self, t): + if isinstance(t, build.SharedLibrary): + return self.get_target_shsym_filename(t) + elif isinstance(t, mesonlib.File): + if t.is_built: + return t.relative_name() + else: + return t.absolute_path(self.environment.get_source_dir(), + self.environment.get_build_dir()) + return self.get_target_filename(t) + + def generate_shlib_aliases(self, target, outdir): + for alias, to, tag in target.get_aliases(): + aliasfile = os.path.join(outdir, alias) + abs_aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias) + try: + os.remove(abs_aliasfile) + except Exception: + pass + try: + os.symlink(to, abs_aliasfile) + except NotImplementedError: + mlog.debug("Library versioning disabled because symlinks are not supported.") + except OSError: + mlog.debug("Library versioning disabled because we do not have symlink creation privileges.") + else: + self.implicit_meson_outs.append(aliasfile) + + def generate_custom_target_clean(self, trees: T.List[str]) -> str: + e = self.create_phony_target(self.all_outputs, 'clean-ctlist', 'CUSTOM_COMMAND', 'PHONY') + d = CleanTrees(self.environment.get_build_dir(), trees) + d_file = os.path.join(self.environment.get_scratch_dir(), 'cleantrees.dat') + e.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'cleantrees', d_file]) + e.add_item('description', 'Cleaning custom target directories') + self.add_build(e) + # Write out the data file passed to the script + with open(d_file, 'wb') as ofile: + pickle.dump(d, ofile) + return 'clean-ctlist' + + def generate_gcov_clean(self): + gcno_elem = self.create_phony_target(self.all_outputs, 'clean-gcno', 'CUSTOM_COMMAND', 'PHONY') + gcno_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcno']) + gcno_elem.add_item('description', 'Deleting gcno files') + self.add_build(gcno_elem) + + gcda_elem = self.create_phony_target(self.all_outputs, 'clean-gcda', 'CUSTOM_COMMAND', 'PHONY') + gcda_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcda']) + gcda_elem.add_item('description', 'Deleting gcda files') + self.add_build(gcda_elem) + + def get_user_option_args(self): + cmds = [] + for (k, v) in self.environment.coredata.options.items(): + if k.is_project(): + cmds.append('-D' + str(k) + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower())) + # The order of these arguments must be the same between runs of Meson + # to ensure reproducible output. The order we pass them shouldn't + # affect behavior in any other way. + return sorted(cmds) + + def generate_dist(self): + elem = self.create_phony_target(self.all_outputs, 'dist', 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('DESC', 'Creating source packages') + elem.add_item('COMMAND', self.environment.get_build_command() + ['dist']) + elem.add_item('pool', 'console') + self.add_build(elem) + + def generate_scanbuild(self): + if not environment.detect_scanbuild(): + return + if 'scan-build' in self.all_outputs: + return + cmd = self.environment.get_build_command() + \ + ['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir] + \ + self.environment.get_build_command() + self.get_user_option_args() + elem = self.create_phony_target(self.all_outputs, 'scan-build', 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', cmd) + elem.add_item('pool', 'console') + self.add_build(elem) + + def generate_clangtool(self, name, extra_arg=None): + target_name = 'clang-' + name + extra_args = [] + if extra_arg: + target_name += f'-{extra_arg}' + extra_args.append(f'--{extra_arg}') + if not os.path.exists(os.path.join(self.environment.source_dir, '.clang-' + name)) and \ + not os.path.exists(os.path.join(self.environment.source_dir, '_clang-' + name)): + return + if target_name in self.all_outputs: + return + cmd = self.environment.get_build_command() + \ + ['--internal', 'clang' + name, self.environment.source_dir, self.environment.build_dir] + \ + extra_args + elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', cmd) + elem.add_item('pool', 'console') + self.add_build(elem) + + def generate_clangformat(self): + if not environment.detect_clangformat(): + return + self.generate_clangtool('format') + self.generate_clangtool('format', 'check') + + def generate_clangtidy(self): + import shutil + if not shutil.which('clang-tidy'): + return + self.generate_clangtool('tidy') + + def generate_tags(self, tool, target_name): + import shutil + if not shutil.which(tool): + return + if target_name in self.all_outputs: + return + cmd = self.environment.get_build_command() + \ + ['--internal', 'tags', tool, self.environment.source_dir] + elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', cmd) + elem.add_item('pool', 'console') + self.add_build(elem) + + # For things like scan-build and other helper tools we might have. + def generate_utils(self): + self.generate_scanbuild() + self.generate_clangformat() + self.generate_clangtidy() + self.generate_tags('etags', 'TAGS') + self.generate_tags('ctags', 'ctags') + self.generate_tags('cscope', 'cscope') + cmd = self.environment.get_build_command() + ['--internal', 'uninstall'] + elem = self.create_phony_target(self.all_outputs, 'uninstall', 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', cmd) + elem.add_item('pool', 'console') + self.add_build(elem) + + def generate_ending(self): + for targ, deps in [ + ('all', self.get_build_by_default_targets()), + ('meson-test-prereq', self.get_testlike_targets()), + ('meson-benchmark-prereq', self.get_testlike_targets(True))]: + targetlist = [] + # These must also be built by default. + # XXX: Sometime in the future these should be built only before running tests. + if targ == 'all': + targetlist.extend(['meson-test-prereq', 'meson-benchmark-prereq']) + for t in deps.values(): + # Add the first output of each target to the 'all' target so that + # they are all built + #Add archive file if shared library in AIX for build all. + if isinstance(t, build.SharedLibrary): + if self.environment.machines[t.for_machine].is_aix(): + linker, stdlib_args = self.determine_linker_and_stdlib_args(t) + t.get_outputs()[0] = linker.get_archive_name(t.get_outputs()[0]) + targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0])) + + elem = NinjaBuildElement(self.all_outputs, targ, 'phony', targetlist) + self.add_build(elem) + + elem = self.create_phony_target(self.all_outputs, 'clean', 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', self.ninja_command + ['-t', 'clean']) + elem.add_item('description', 'Cleaning') + + # If we have custom targets in this project, add all their outputs to + # the list that is passed to the `cleantrees.py` script. The script + # will manually delete all custom_target outputs that are directories + # instead of files. This is needed because on platforms other than + # Windows, Ninja only deletes directories while cleaning if they are + # empty. https://github.com/mesonbuild/meson/issues/1220 + ctlist = [] + for t in self.build.get_targets().values(): + if isinstance(t, build.CustomTarget): + # Create a list of all custom target outputs + for o in t.get_outputs(): + ctlist.append(os.path.join(self.get_target_dir(t), o)) + if ctlist: + elem.add_dep(self.generate_custom_target_clean(ctlist)) + + if OptionKey('b_coverage') in self.environment.coredata.options and \ + self.environment.coredata.options[OptionKey('b_coverage')].value: + self.generate_gcov_clean() + elem.add_dep('clean-gcda') + elem.add_dep('clean-gcno') + self.add_build(elem) + + deps = self.get_regen_filelist() + elem = NinjaBuildElement(self.all_outputs, 'build.ninja', 'REGENERATE_BUILD', deps) + elem.add_item('pool', 'console') + self.add_build(elem) + + # If these files used to be explicitly created, they need to appear on the build graph somehow, + # otherwise cleandead deletes them. See https://github.com/ninja-build/ninja/issues/2299 + if self.implicit_meson_outs: + elem = NinjaBuildElement(self.all_outputs, 'meson-implicit-outs', 'phony', self.implicit_meson_outs) + self.add_build(elem) + + elem = NinjaBuildElement(self.all_outputs, 'reconfigure', 'REGENERATE_BUILD', 'PHONY') + elem.add_item('pool', 'console') + self.add_build(elem) + + elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '') + self.add_build(elem) + + def get_introspection_data(self, target_id: str, target: build.Target) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]: + data = self.introspection_data.get(target_id) + if not data: + return super().get_introspection_data(target_id, target) + + return list(data.values()) + + +def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compiler) -> T.List[str]: + """ + scan a Fortran file for dependencies. Needs to be distinct from target + to allow for recursion induced by `include` statements.er + + It makes a number of assumptions, including + + * `use`, `module`, `submodule` name is not on a continuation line + + Regex + ----- + + * `incre` works for `#include "foo.f90"` and `include "foo.f90"` + * `usere` works for legacy and Fortran 2003 `use` statements + * `submodre` is for Fortran >= 2008 `submodule` + """ + + incre = re.compile(FORTRAN_INCLUDE_PAT, re.IGNORECASE) + usere = re.compile(FORTRAN_USE_PAT, re.IGNORECASE) + submodre = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE) + + mod_files = [] + src = Path(src) + with src.open(encoding='ascii', errors='ignore') as f: + for line in f: + # included files + incmatch = incre.match(line) + if incmatch is not None: + incfile = src.parent / incmatch.group(1) + # NOTE: src.parent is most general, in particular for CMake subproject with Fortran file + # having an `include 'foo.f'` statement. + if incfile.suffix.lower()[1:] in compiler.file_suffixes: + mod_files.extend(_scan_fortran_file_deps(incfile, srcdir, dirname, tdeps, compiler)) + # modules + usematch = usere.match(line) + if usematch is not None: + usename = usematch.group(1).lower() + if usename == 'intrinsic': # this keeps the regex simpler + continue + if usename not in tdeps: + # The module is not provided by any source file. This + # is due to: + # a) missing file/typo/etc + # b) using a module provided by the compiler, such as + # OpenMP + # There's no easy way to tell which is which (that I + # know of) so just ignore this and go on. Ideally we + # would print a warning message to the user but this is + # a common occurrence, which would lead to lots of + # distracting noise. + continue + srcfile = srcdir / tdeps[usename].fname # type: Path + if not srcfile.is_file(): + if srcfile.name != src.name: # generated source file + pass + else: # subproject + continue + elif srcfile.samefile(src): # self-reference + continue + + mod_name = compiler.module_name_to_filename(usename) + mod_files.append(str(dirname / mod_name)) + else: # submodules + submodmatch = submodre.match(line) + if submodmatch is not None: + parents = submodmatch.group(1).lower().split(':') + assert len(parents) in {1, 2}, ( + 'submodule ancestry must be specified as' + f' ancestor:parent but Meson found {parents}') + + ancestor_child = '_'.join(parents) + if ancestor_child not in tdeps: + raise MesonException("submodule {} relies on ancestor module {} that was not found.".format(submodmatch.group(2).lower(), ancestor_child.split('_', maxsplit=1)[0])) + submodsrcfile = srcdir / tdeps[ancestor_child].fname # type: Path + if not submodsrcfile.is_file(): + if submodsrcfile.name != src.name: # generated source file + pass + else: # subproject + continue + elif submodsrcfile.samefile(src): # self-reference + continue + mod_name = compiler.module_name_to_filename(ancestor_child) + mod_files.append(str(dirname / mod_name)) + return mod_files diff --git a/devtools/meson/mesonbuild/backend/nonebackend.py b/devtools/meson/mesonbuild/backend/nonebackend.py new file mode 100644 index 0000000..35ec958 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/nonebackend.py @@ -0,0 +1,39 @@ +# Copyright 2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +import typing as T + +from .backends import Backend +from .. import mlog +from ..mesonlib import MesonBugException + + +class NoneBackend(Backend): + + name = 'none' + + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + # Check for (currently) unexpected capture arg use cases - + if capture: + raise MesonBugException('We do not expect the none backend to generate with \'capture = True\'') + if vslite_ctx: + raise MesonBugException('We do not expect the none backend to be given a valid \'vslite_ctx\'') + + if self.build.get_targets(): + raise MesonBugException('None backend cannot generate target rules, but should have failed earlier.') + mlog.log('Generating simple install-only backend') + self.serialize_tests() + self.create_install_data_files() diff --git a/devtools/meson/mesonbuild/backend/vs2010backend.py b/devtools/meson/mesonbuild/backend/vs2010backend.py new file mode 100644 index 0000000..c3dcaeb --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2010backend.py @@ -0,0 +1,2121 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import copy +import itertools +import os +import xml.dom.minidom +import xml.etree.ElementTree as ET +import uuid +import typing as T +from pathlib import Path, PurePath +import re +from collections import Counter + +from . import backends +from .. import build +from .. import mlog +from .. import compilers +from .. import mesonlib +from ..mesonlib import ( + File, MesonBugException, MesonException, replace_if_different, OptionKey, version_compare, MachineChoice +) +from ..environment import Environment, build_filename +from .. import coredata + +if T.TYPE_CHECKING: + from ..arglist import CompilerArgs + from ..interpreter import Interpreter + + Project = T.Tuple[str, Path, str, MachineChoice] + +def autodetect_vs_version(build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]) -> backends.Backend: + vs_version = os.getenv('VisualStudioVersion', None) + vs_install_dir = os.getenv('VSINSTALLDIR', None) + if not vs_install_dir: + raise MesonException('Could not detect Visual Studio: Environment variable VSINSTALLDIR is not set!\n' + 'Are you running meson from the Visual Studio Developer Command Prompt?') + # VisualStudioVersion is set since Visual Studio 11.0, but sometimes + # vcvarsall.bat doesn't set it, so also use VSINSTALLDIR + if vs_version == '11.0' or 'Visual Studio 11' in vs_install_dir: + from mesonbuild.backend.vs2012backend import Vs2012Backend + return Vs2012Backend(build, interpreter) + if vs_version == '12.0' or 'Visual Studio 12' in vs_install_dir: + from mesonbuild.backend.vs2013backend import Vs2013Backend + return Vs2013Backend(build, interpreter) + if vs_version == '14.0' or 'Visual Studio 14' in vs_install_dir: + from mesonbuild.backend.vs2015backend import Vs2015Backend + return Vs2015Backend(build, interpreter) + if vs_version == '15.0' or 'Visual Studio 17' in vs_install_dir or \ + 'Visual Studio\\2017' in vs_install_dir: + from mesonbuild.backend.vs2017backend import Vs2017Backend + return Vs2017Backend(build, interpreter) + if vs_version == '16.0' or 'Visual Studio 19' in vs_install_dir or \ + 'Visual Studio\\2019' in vs_install_dir: + from mesonbuild.backend.vs2019backend import Vs2019Backend + return Vs2019Backend(build, interpreter) + if vs_version == '17.0' or 'Visual Studio 22' in vs_install_dir or \ + 'Visual Studio\\2022' in vs_install_dir: + from mesonbuild.backend.vs2022backend import Vs2022Backend + return Vs2022Backend(build, interpreter) + if 'Visual Studio 10.0' in vs_install_dir: + return Vs2010Backend(build, interpreter) + raise MesonException('Could not detect Visual Studio using VisualStudioVersion: {!r} or VSINSTALLDIR: {!r}!\n' + 'Please specify the exact backend to use.'.format(vs_version, vs_install_dir)) + + +def split_o_flags_args(args: T.List[str]) -> T.List[str]: + """ + Splits any /O args and returns them. Does not take care of flags overriding + previous ones. Skips non-O flag arguments. + + ['/Ox', '/Ob1'] returns ['/Ox', '/Ob1'] + ['/Oxj', '/MP'] returns ['/Ox', '/Oj'] + """ + o_flags = [] + for arg in args: + if not arg.startswith('/O'): + continue + flags = list(arg[2:]) + # Assume that this one can't be clumped with the others since it takes + # an argument itself + if 'b' in flags: + o_flags.append(arg) + else: + o_flags += ['/O' + f for f in flags] + return o_flags + +def generate_guid_from_path(path, path_type) -> str: + return str(uuid.uuid5(uuid.NAMESPACE_URL, 'meson-vs-' + path_type + ':' + str(path))).upper() + +def detect_microsoft_gdk(platform: str) -> bool: + return re.match(r'Gaming\.(Desktop|Xbox.XboxOne|Xbox.Scarlett)\.x64', platform, re.IGNORECASE) + +def filtered_src_langs_generator(sources: T.List[str]): + for src in sources: + ext = src.split('.')[-1] + if compilers.compilers.is_source_suffix(ext): + yield compilers.compilers.SUFFIX_TO_LANG[ext] + +# Returns the source language (i.e. a key from 'lang_suffixes') of the most frequent source language in the given +# list of sources. +# We choose the most frequent language as 'primary' because it means the most sources in a target/project can +# simply refer to the project's shared intellisense define and include fields, rather than have to fill out their +# own duplicate full set of defines/includes/opts intellisense fields. All of which helps keep the vcxproj file +# size down. +def get_primary_source_lang(target_sources: T.List[File], custom_sources: T.List[str]) -> T.Optional[str]: + lang_counts = Counter([compilers.compilers.SUFFIX_TO_LANG[src.suffix] for src in target_sources if compilers.compilers.is_source_suffix(src.suffix)]) + lang_counts += Counter(filtered_src_langs_generator(custom_sources)) + most_common_lang_list = lang_counts.most_common(1) + # It may be possible that we have a target with no actual src files of interest (e.g. a generator target), + # leaving us with an empty list, which we should handle - + return most_common_lang_list[0][0] if most_common_lang_list else None + +# Returns a dictionary (by [src type][build type]) that contains a tuple of - +# (pre-processor defines, include paths, additional compiler options) +# fields to use to fill in the respective intellisense fields of sources that can't simply +# reference and re-use the shared 'primary' language intellisense fields of the vcxproj. +def get_non_primary_lang_intellisense_fields(vslite_ctx: dict, + target_id: str, + primary_src_lang: str) -> T.Dict[str, T.Dict[str, T.Tuple[str, str, str]]]: + defs_paths_opts_per_lang_and_buildtype = {} + for buildtype in coredata.get_genvs_default_buildtype_list(): + captured_build_args = vslite_ctx[buildtype][target_id] # Results in a 'Src types to compile args' dict + non_primary_build_args_per_src_lang = [(lang, build_args) for lang, build_args in captured_build_args.items() if lang != primary_src_lang] # Only need to individually populate intellisense fields for sources of non-primary types. + for src_lang, args_list in non_primary_build_args_per_src_lang: + if src_lang not in defs_paths_opts_per_lang_and_buildtype: + defs_paths_opts_per_lang_and_buildtype[src_lang] = {} + defs = Vs2010Backend.extract_nmake_preprocessor_defs(args_list) + paths = Vs2010Backend.extract_nmake_include_paths(args_list) + opts = Vs2010Backend.extract_intellisense_additional_compiler_options(args_list) + defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = (defs, paths, opts) + return defs_paths_opts_per_lang_and_buildtype + +class Vs2010Backend(backends.Backend): + + name = 'vs2010' + + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter], gen_lite: bool = False): + super().__init__(build, interpreter) + self.project_file_version = '10.0.30319.1' + self.sln_file_version = '11.00' + self.sln_version_comment = '2010' + self.platform_toolset = None + self.vs_version = '2010' + self.windows_target_platform_version = None + self.subdirs = {} + self.handled_target_deps = {} + self.gen_lite = gen_lite # Synonymous with generating the simpler makefile-style multi-config projects that invoke 'meson compile' builds, avoiding native MSBuild complications + + def get_target_private_dir(self, target): + return os.path.join(self.get_target_dir(target), target.get_id()) + + def generate_genlist_for_target(self, genlist: T.Union[build.GeneratedList, build.CustomTarget, build.CustomTargetIndex], target: build.BuildTarget, parent_node: ET.Element, generator_output_files: T.List[str], custom_target_include_dirs: T.List[str], custom_target_output_files: T.List[str]) -> None: + if isinstance(genlist, build.GeneratedList): + for x in genlist.depends: + self.generate_genlist_for_target(x, target, parent_node, [], [], []) + target_private_dir = self.relpath(self.get_target_private_dir(target), self.get_target_dir(target)) + down = self.target_to_build_root(target) + if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): + for i in genlist.get_outputs(): + # Path to the generated source from the current vcxproj dir via the build root + ipath = os.path.join(down, self.get_target_dir(genlist), i) + custom_target_output_files.append(ipath) + idir = self.relpath(self.get_target_dir(genlist), self.get_target_dir(target)) + if idir not in custom_target_include_dirs: + custom_target_include_dirs.append(idir) + else: + generator = genlist.get_generator() + exe = generator.get_exe() + infilelist = genlist.get_inputs() + outfilelist = genlist.get_outputs() + source_dir = os.path.join(down, self.build_to_src, genlist.subdir) + idgroup = ET.SubElement(parent_node, 'ItemGroup') + samelen = len(infilelist) == len(outfilelist) + for i, curfile in enumerate(infilelist): + if samelen: + sole_output = os.path.join(target_private_dir, outfilelist[i]) + else: + sole_output = '' + infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src, target_private_dir)) + deps = self.get_custom_target_depend_files(genlist, True) + base_args = generator.get_arglist(infilename) + outfiles_rel = genlist.get_outputs_for(curfile) + outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel] + generator_output_files += outfiles + args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) + for x in base_args] + args = self.replace_outputs(args, target_private_dir, outfiles_rel) + args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()) + .replace("@BUILD_DIR@", target_private_dir) + for x in args] + args = [x.replace("@CURRENT_SOURCE_DIR@", source_dir) for x in args] + args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir()) + .replace("@BUILD_ROOT@", self.environment.get_build_dir()) + for x in args] + args = [x.replace('\\', '/') for x in args] + # Always use a wrapper because MSBuild eats random characters when + # there are many arguments. + tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + cmd, _ = self.as_meson_exe_cmdline( + exe, + self.replace_extra_args(args, genlist), + workdir=tdir_abs, + capture=outfiles[0] if generator.capture else None, + force_serialize=True + ) + deps = cmd[-1:] + deps + abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + os.makedirs(abs_pdir, exist_ok=True) + cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename) + ET.SubElement(cbs, 'Command').text = ' '.join(self.quote_arguments(cmd)) + ET.SubElement(cbs, 'Outputs').text = ';'.join(outfiles) + ET.SubElement(cbs, 'AdditionalInputs').text = ';'.join(deps) + + def generate_custom_generator_commands(self, target, parent_node): + generator_output_files = [] + custom_target_include_dirs = [] + custom_target_output_files = [] + for genlist in target.get_generated_sources(): + self.generate_genlist_for_target(genlist, target, parent_node, generator_output_files, custom_target_include_dirs, custom_target_output_files) + return generator_output_files, custom_target_output_files, custom_target_include_dirs + + def generate(self, + capture: bool = False, + vslite_ctx: dict = None) -> T.Optional[dict]: + # Check for (currently) unexpected capture arg use cases - + if capture: + raise MesonBugException('We do not expect any vs backend to generate with \'capture = True\'') + target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None) + if target_machine in {'64', 'x86_64'}: + # amd64 or x86_64 + target_system = self.interpreter.builtin['target_machine'].system_method(None, None) + if detect_microsoft_gdk(target_system): + self.platform = target_system + else: + self.platform = 'x64' + elif target_machine == 'x86': + # x86 + self.platform = 'Win32' + elif target_machine in {'aarch64', 'arm64'}: + target_cpu = self.interpreter.builtin['target_machine'].cpu_method(None, None) + if target_cpu == 'arm64ec': + self.platform = 'arm64ec' + else: + self.platform = 'arm64' + elif 'arm' in target_machine.lower(): + self.platform = 'ARM' + else: + raise MesonException('Unsupported Visual Studio platform: ' + target_machine) + + build_machine = self.interpreter.builtin['build_machine'].cpu_family_method(None, None) + if build_machine in {'64', 'x86_64'}: + # amd64 or x86_64 + self.build_platform = 'x64' + elif build_machine == 'x86': + # x86 + self.build_platform = 'Win32' + elif build_machine in {'aarch64', 'arm64'}: + target_cpu = self.interpreter.builtin['build_machine'].cpu_method(None, None) + if target_cpu == 'arm64ec': + self.build_platform = 'arm64ec' + else: + self.build_platform = 'arm64' + elif 'arm' in build_machine.lower(): + self.build_platform = 'ARM' + else: + raise MesonException('Unsupported Visual Studio platform: ' + build_machine) + + self.buildtype = self.environment.coredata.get_option(OptionKey('buildtype')) + self.optimization = self.environment.coredata.get_option(OptionKey('optimization')) + self.debug = self.environment.coredata.get_option(OptionKey('debug')) + try: + self.sanitize = self.environment.coredata.get_option(OptionKey('b_sanitize')) + except MesonException: + self.sanitize = 'none' + sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') + projlist = self.generate_projects(vslite_ctx) + self.gen_testproj() + self.gen_installproj() + self.gen_regenproj() + self.generate_solution(sln_filename, projlist) + self.generate_regen_info() + Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir()) + + @staticmethod + def get_regen_stampfile(build_dir: str) -> None: + return os.path.join(os.path.join(build_dir, Environment.private_dir), 'regen.stamp') + + @staticmethod + def touch_regen_timestamp(build_dir: str) -> None: + with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w', encoding='utf-8'): + pass + + def get_vcvars_command(self): + has_arch_values = 'VSCMD_ARG_TGT_ARCH' in os.environ and 'VSCMD_ARG_HOST_ARCH' in os.environ + + # Use vcvarsall.bat if we found it. + if 'VCINSTALLDIR' in os.environ: + vs_version = os.environ['VisualStudioVersion'] \ + if 'VisualStudioVersion' in os.environ else None + relative_path = 'Auxiliary\\Build\\' if vs_version is not None and vs_version >= '15.0' else '' + script_path = os.environ['VCINSTALLDIR'] + relative_path + 'vcvarsall.bat' + if os.path.exists(script_path): + if has_arch_values: + target_arch = os.environ['VSCMD_ARG_TGT_ARCH'] + host_arch = os.environ['VSCMD_ARG_HOST_ARCH'] + else: + target_arch = os.environ.get('Platform', 'x86') + host_arch = target_arch + arch = host_arch + '_' + target_arch if host_arch != target_arch else target_arch + return f'"{script_path}" {arch}' + + # Otherwise try the VS2017 Developer Command Prompt. + if 'VS150COMNTOOLS' in os.environ and has_arch_values: + script_path = os.environ['VS150COMNTOOLS'] + 'VsDevCmd.bat' + if os.path.exists(script_path): + return '"%s" -arch=%s -host_arch=%s' % \ + (script_path, os.environ['VSCMD_ARG_TGT_ARCH'], os.environ['VSCMD_ARG_HOST_ARCH']) + return '' + + def get_obj_target_deps(self, obj_list): + result = {} + for o in obj_list: + if isinstance(o, build.ExtractedObjects): + result[o.target.get_id()] = o.target + return result.items() + + def get_target_deps(self, t: T.Dict[T.Any, build.Target], recursive=False): + all_deps: T.Dict[str, build.Target] = {} + for target in t.values(): + if isinstance(target, build.CustomTarget): + for d in target.get_target_dependencies(): + # FIXME: this isn't strictly correct, as the target doesn't + # Get dependencies on non-targets, such as Files + if isinstance(d, build.Target): + all_deps[d.get_id()] = d + elif isinstance(target, build.RunTarget): + for d in target.get_dependencies(): + all_deps[d.get_id()] = d + elif isinstance(target, build.BuildTarget): + for ldep in target.link_targets: + if isinstance(ldep, build.CustomTargetIndex): + all_deps[ldep.get_id()] = ldep.target + else: + all_deps[ldep.get_id()] = ldep + for ldep in target.link_whole_targets: + if isinstance(ldep, build.CustomTargetIndex): + all_deps[ldep.get_id()] = ldep.target + else: + all_deps[ldep.get_id()] = ldep + + for ldep in target.link_depends: + if isinstance(ldep, build.CustomTargetIndex): + all_deps[ldep.get_id()] = ldep.target + elif isinstance(ldep, File): + # Already built, no target references needed + pass + else: + all_deps[ldep.get_id()] = ldep + + for obj_id, objdep in self.get_obj_target_deps(target.objects): + all_deps[obj_id] = objdep + else: + raise MesonException(f'Unknown target type for target {target}') + + for gendep in target.get_generated_sources(): + if isinstance(gendep, build.CustomTarget): + all_deps[gendep.get_id()] = gendep + elif isinstance(gendep, build.CustomTargetIndex): + all_deps[gendep.target.get_id()] = gendep.target + else: + generator = gendep.get_generator() + gen_exe = generator.get_exe() + if isinstance(gen_exe, build.Executable): + all_deps[gen_exe.get_id()] = gen_exe + for d in itertools.chain(generator.depends, gendep.depends): + if isinstance(d, build.CustomTargetIndex): + all_deps[d.get_id()] = d.target + elif isinstance(d, build.Target): + all_deps[d.get_id()] = d + # FIXME: we don't handle other kinds of deps correctly here, such + # as GeneratedLists, StructuredSources, and generated File. + + if not t or not recursive: + return all_deps + ret = self.get_target_deps(all_deps, recursive) + ret.update(all_deps) + return ret + + def generate_solution_dirs(self, ofile: str, parents: T.Sequence[Path]) -> None: + prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' + iterpaths = reversed(parents) + # Skip first path + next(iterpaths) + for path in iterpaths: + if path not in self.subdirs: + basename = path.name + identifier = generate_guid_from_path(path, 'subdir') + # top-level directories have None as their parent_dir + parent_dir = path.parent + parent_identifier = self.subdirs[parent_dir][0] \ + if parent_dir != PurePath('.') else None + self.subdirs[path] = (identifier, parent_identifier) + prj_line = prj_templ % ( + self.environment.coredata.lang_guids['directory'], + basename, basename, self.subdirs[path][0]) + ofile.write(prj_line) + ofile.write('EndProject\n') + + def generate_solution(self, sln_filename: str, projlist: T.List[Project]) -> None: + default_projlist = self.get_build_by_default_targets() + default_projlist.update(self.get_testlike_targets()) + sln_filename_tmp = sln_filename + '~' + # Note using the utf-8 BOM requires the blank line, otherwise Visual Studio Version Selector fails. + # Without the BOM, VSVS fails if there is a blank line. + with open(sln_filename_tmp, 'w', encoding='utf-8-sig') as ofile: + ofile.write('\nMicrosoft Visual Studio Solution File, Format Version %s\n' % self.sln_file_version) + ofile.write('# Visual Studio %s\n' % self.sln_version_comment) + prj_templ = 'Project("{%s}") = "%s", "%s", "{%s}"\n' + for prj in projlist: + if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + self.generate_solution_dirs(ofile, prj[1].parents) + target = self.build.targets[prj[0]] + lang = 'default' + if hasattr(target, 'compilers') and target.compilers: + for lang_out in target.compilers.keys(): + lang = lang_out + break + prj_line = prj_templ % ( + self.environment.coredata.lang_guids[lang], + prj[0], prj[1], prj[2]) + ofile.write(prj_line) + target_dict = {target.get_id(): target} + # Get recursive deps + recursive_deps = self.get_target_deps( + target_dict, recursive=True) + ofile.write('EndProject\n') + for dep, target in recursive_deps.items(): + if prj[0] in default_projlist: + default_projlist[dep] = target + + test_line = prj_templ % (self.environment.coredata.lang_guids['default'], + 'RUN_TESTS', 'RUN_TESTS.vcxproj', + self.environment.coredata.test_guid) + ofile.write(test_line) + ofile.write('EndProject\n') + if self.gen_lite: # REGEN is replaced by the lighter-weight RECONFIGURE utility, for now. See comment in 'gen_regenproj' + regen_proj_name = 'RECONFIGURE' + regen_proj_fname = 'RECONFIGURE.vcxproj' + else: + regen_proj_name = 'REGEN' + regen_proj_fname = 'REGEN.vcxproj' + regen_line = prj_templ % (self.environment.coredata.lang_guids['default'], + regen_proj_name, regen_proj_fname, + self.environment.coredata.regen_guid) + ofile.write(regen_line) + ofile.write('EndProject\n') + install_line = prj_templ % (self.environment.coredata.lang_guids['default'], + 'RUN_INSTALL', 'RUN_INSTALL.vcxproj', + self.environment.coredata.install_guid) + ofile.write(install_line) + ofile.write('EndProject\n') + ofile.write('Global\n') + ofile.write('\tGlobalSection(SolutionConfigurationPlatforms) = ' + 'preSolution\n') + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() if self.gen_lite else [self.buildtype] + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t%s|%s = %s|%s\n' % + (buildtype, self.platform, buildtype, + self.platform)) + ofile.write('\tEndGlobalSection\n') + ofile.write('\tGlobalSection(ProjectConfigurationPlatforms) = ' + 'postSolution\n') + # REGEN project (multi-)configurations + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (self.environment.coredata.regen_guid, buildtype, + self.platform, buildtype, self.platform)) + if not self.gen_lite: # With a 'genvslite'-generated solution, the regen (i.e. reconfigure) utility is only intended to run when the user explicitly builds this proj. + ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % + (self.environment.coredata.regen_guid, buildtype, + self.platform, buildtype, self.platform)) + # Create the solution configuration + for p in projlist: + if p[3] is MachineChoice.BUILD: + config_platform = self.build_platform + else: + config_platform = self.platform + # Add to the list of projects in this solution + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (p[2], buildtype, self.platform, + buildtype, config_platform)) + # If we're building the solution with Visual Studio's build system, enable building of buildable + # projects. However, if we're building with meson (via --genvslite), then, since each project's + # 'build' action just ends up doing the same 'meson compile ...' we don't want the 'solution build' + # repeatedly going off and doing the same 'meson compile ...' multiple times over, so we just + # leave it up to the user to select or build just one project. + # FIXME: Would be slightly nicer if we could enable building of just one top level target/project, + # but not sure how to identify that. + if not self.gen_lite and \ + p[0] in default_projlist and \ + not isinstance(self.build.targets[p[0]], build.RunTarget): + ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % + (p[2], buildtype, self.platform, + buildtype, config_platform)) + # RUN_TESTS and RUN_INSTALL project (multi-)configurations + for buildtype in multi_config_buildtype_list: + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (self.environment.coredata.test_guid, buildtype, + self.platform, buildtype, self.platform)) + ofile.write('\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n' % + (self.environment.coredata.install_guid, buildtype, + self.platform, buildtype, self.platform)) + ofile.write('\tEndGlobalSection\n') + ofile.write('\tGlobalSection(SolutionProperties) = preSolution\n') + ofile.write('\t\tHideSolutionNode = FALSE\n') + ofile.write('\tEndGlobalSection\n') + if self.subdirs: + ofile.write('\tGlobalSection(NestedProjects) = ' + 'preSolution\n') + for p in projlist: + if p[1].parent != PurePath('.'): + ofile.write("\t\t{{{}}} = {{{}}}\n".format(p[2], self.subdirs[p[1].parent][0])) + for subdir in self.subdirs.values(): + if subdir[1]: + ofile.write("\t\t{{{}}} = {{{}}}\n".format(subdir[0], subdir[1])) + ofile.write('\tEndGlobalSection\n') + ofile.write('EndGlobal\n') + replace_if_different(sln_filename, sln_filename_tmp) + + def generate_projects(self, vslite_ctx: dict = None) -> T.List[Project]: + startup_project = self.environment.coredata.options[OptionKey('backend_startup_project')].value + projlist: T.List[Project] = [] + startup_idx = 0 + for (i, (name, target)) in enumerate(self.build.targets.items()): + if startup_project and startup_project == target.get_basename(): + startup_idx = i + outdir = Path( + self.environment.get_build_dir(), + self.get_target_dir(target) + ) + outdir.mkdir(exist_ok=True, parents=True) + fname = target.get_basename() + '.vcxproj' + target_dir = PurePath(self.get_target_dir(target)) + relname = target_dir / fname + projfile_path = outdir / fname + proj_uuid = self.environment.coredata.target_guids[name] + generated = self.gen_vcxproj(target, str(projfile_path), proj_uuid, vslite_ctx) + if generated: + projlist.append((name, relname, proj_uuid, target.for_machine)) + + # Put the startup project first in the project list + if startup_idx: + projlist.insert(0, projlist.pop(startup_idx)) + + return projlist + + def split_sources(self, srclist): + sources = [] + headers = [] + objects = [] + languages = [] + for i in srclist: + if self.environment.is_header(i): + headers.append(i) + elif self.environment.is_object(i): + objects.append(i) + elif self.environment.is_source(i): + sources.append(i) + lang = self.lang_from_source_file(i) + if lang not in languages: + languages.append(lang) + elif self.environment.is_library(i): + pass + else: + # Everything that is not an object or source file is considered a header. + headers.append(i) + return sources, headers, objects, languages + + def target_to_build_root(self, target): + if self.get_target_dir(target) == '': + return '' + + directories = os.path.normpath(self.get_target_dir(target)).split(os.sep) + return os.sep.join(['..'] * len(directories)) + + def quote_arguments(self, arr): + return ['"%s"' % i for i in arr] + + def add_project_reference(self, root: ET.Element, include: str, projid: str, link_outputs: bool = False) -> None: + ig = ET.SubElement(root, 'ItemGroup') + pref = ET.SubElement(ig, 'ProjectReference', Include=include) + ET.SubElement(pref, 'Project').text = '{%s}' % projid + if not link_outputs: + # Do not link in generated .lib files from dependencies automatically. + # We only use the dependencies for ordering and link in the generated + # objects and .lib files manually. + ET.SubElement(pref, 'LinkLibraryDependencies').text = 'false' + + def add_target_deps(self, root: ET.Element, target): + target_dict = {target.get_id(): target} + for dep in self.get_target_deps(target_dict).values(): + if dep.get_id() in self.handled_target_deps[target.get_id()]: + # This dependency was already handled manually. + continue + relpath = self.get_target_dir_relative_to(dep, target) + vcxproj = os.path.join(relpath, dep.get_id() + '.vcxproj') + tid = self.environment.coredata.target_guids[dep.get_id()] + self.add_project_reference(root, vcxproj, tid) + + def create_basic_project_filters(self) -> ET.Element: + root = ET.Element('Project', {'ToolsVersion': '4.0', + 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) + return root + + def create_basic_project(self, target_name, *, + temp_dir, + guid, + conftype='Utility', + target_ext=None, + target_platform=None) -> T.Tuple[ET.Element, ET.Element]: + root = ET.Element('Project', {'DefaultTargets': "Build", + 'ToolsVersion': '4.0', + 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) + + confitems = ET.SubElement(root, 'ItemGroup', {'Label': 'ProjectConfigurations'}) + if not target_platform: + target_platform = self.platform + + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() if self.gen_lite else [self.buildtype] + for buildtype in multi_config_buildtype_list: + prjconf = ET.SubElement(confitems, 'ProjectConfiguration', + {'Include': buildtype + '|' + target_platform}) + ET.SubElement(prjconf, 'Configuration').text = buildtype + ET.SubElement(prjconf, 'Platform').text = target_platform + + # Globals + globalgroup = ET.SubElement(root, 'PropertyGroup', Label='Globals') + guidelem = ET.SubElement(globalgroup, 'ProjectGuid') + guidelem.text = '{%s}' % guid + kw = ET.SubElement(globalgroup, 'Keyword') + kw.text = self.platform + 'Proj' + + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.Default.props') + + # Configuration + type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration') + ET.SubElement(type_config, 'ConfigurationType').text = conftype + if self.platform_toolset: + ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset + + # This must come AFTER the '' element; importing before the 'PlatformToolset' elt + # gets set leads to msbuild failures reporting - + # "The build tools for v142 (Platform Toolset = 'v142') cannot be found. ... please install v142 build tools." + # This is extremely unhelpful and misleading since the v14x build tools ARE installed. + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') + + if not self.gen_lite: # Plenty of elements aren't necessary for 'makefile'-style project that just redirects to meson builds + # XXX Wasn't here before for anything but gen_vcxproj , but seems fine? + ns = ET.SubElement(globalgroup, 'RootNamespace') + ns.text = target_name + + p = ET.SubElement(globalgroup, 'Platform') + p.text = target_platform + pname = ET.SubElement(globalgroup, 'ProjectName') + pname.text = target_name + if self.windows_target_platform_version: + ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version + ET.SubElement(globalgroup, 'UseMultiToolTask').text = 'true' + + ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte' + # Fixme: wasn't here before for gen_vcxproj() + ET.SubElement(type_config, 'UseOfMfc').text = 'false' + + # Project information + direlem = ET.SubElement(root, 'PropertyGroup') + fver = ET.SubElement(direlem, '_ProjectFileVersion') + fver.text = self.project_file_version + outdir = ET.SubElement(direlem, 'OutDir') + outdir.text = '.\\' + intdir = ET.SubElement(direlem, 'IntDir') + intdir.text = temp_dir + '\\' + + tname = ET.SubElement(direlem, 'TargetName') + tname.text = target_name + + if target_ext: + ET.SubElement(direlem, 'TargetExt').text = target_ext + + return (root, type_config) + + def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str) -> None: + (root, type_config) = self.create_basic_project(target.name, + temp_dir=target.get_id(), + guid=guid) + depend_files = self.get_custom_target_depend_files(target) + + if not target.command: + # This is an alias target and thus doesn't run any command. It's + # enough to emit the references to the other projects for them to + # be built/run/..., if necessary. + assert isinstance(target, build.AliasTarget) + assert len(depend_files) == 0 + else: + assert not isinstance(target, build.AliasTarget) + + target_env = self.get_run_target_env(target) + _, _, cmd_raw = self.eval_custom_target_command(target) + wrapper_cmd, _ = self.as_meson_exe_cmdline(target.command[0], cmd_raw[1:], + force_serialize=True, env=target_env, + verbose=True) + self.add_custom_build(root, 'run_target', ' '.join(self.quote_arguments(wrapper_cmd)), + deps=depend_files) + + # The import is needed even for alias targets, otherwise the build + # target isn't defined + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) + self.add_target_deps(root, target) + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + + def gen_custom_target_vcxproj(self, target: build.CustomTarget, ofname: str, guid: str) -> None: + if target.for_machine is MachineChoice.BUILD: + platform = self.build_platform + else: + platform = self.platform + (root, type_config) = self.create_basic_project(target.name, + temp_dir=target.get_id(), + guid=guid, + target_platform=platform) + # We need to always use absolute paths because our invocation is always + # from the target dir, not the build root. + target.absolute_paths = True + (srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True) + depend_files = self.get_custom_target_depend_files(target, True) + # Always use a wrapper because MSBuild eats random characters when + # there are many arguments. + tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) + extra_bdeps = target.get_transitive_build_target_deps() + wrapper_cmd, _ = self.as_meson_exe_cmdline(target.command[0], cmd[1:], + # All targets run from the target dir + workdir=tdir_abs, + extra_bdeps=extra_bdeps, + capture=ofilenames[0] if target.capture else None, + feed=srcs[0] if target.feed else None, + force_serialize=True, + env=target.env, + verbose=target.console) + if target.build_always_stale: + # Use a nonexistent file to always consider the target out-of-date. + ofilenames += [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(), + 'outofdate.file'))] + self.add_custom_build(root, 'custom_target', ' '.join(self.quote_arguments(wrapper_cmd)), + deps=wrapper_cmd[-1:] + srcs + depend_files, outputs=ofilenames, + verify_files=not target.build_always_stale) + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.generate_custom_generator_commands(target, root) + self.add_regen_dependency(root) + self.add_target_deps(root, target) + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + + def gen_compile_target_vcxproj(self, target: build.CompileTarget, ofname: str, guid: str) -> None: + if target.for_machine is MachineChoice.BUILD: + platform = self.build_platform + else: + platform = self.platform + (root, type_config) = self.create_basic_project(target.name, + temp_dir=target.get_id(), + guid=guid, + target_platform=platform) + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + target.generated = [self.compile_target_to_generator(target)] + target.sources = [] + self.generate_custom_generator_commands(target, root) + self.add_regen_dependency(root) + self.add_target_deps(root, target) + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + + @classmethod + def lang_from_source_file(cls, src): + ext = src.split('.')[-1] + if ext in compilers.c_suffixes: + return 'c' + if ext in compilers.cpp_suffixes: + return 'cpp' + raise MesonException(f'Could not guess language from source file {src}.') + + def add_pch(self, pch_sources, lang, inc_cl): + if lang in pch_sources: + self.use_pch(pch_sources, lang, inc_cl) + + def create_pch(self, pch_sources, lang, inc_cl): + pch = ET.SubElement(inc_cl, 'PrecompiledHeader') + pch.text = 'Create' + self.add_pch_files(pch_sources, lang, inc_cl) + + def use_pch(self, pch_sources, lang, inc_cl): + pch = ET.SubElement(inc_cl, 'PrecompiledHeader') + pch.text = 'Use' + header = self.add_pch_files(pch_sources, lang, inc_cl) + pch_include = ET.SubElement(inc_cl, 'ForcedIncludeFiles') + pch_include.text = header + ';%(ForcedIncludeFiles)' + + def add_pch_files(self, pch_sources, lang, inc_cl): + header = os.path.basename(pch_sources[lang][0]) + pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile') + # When USING PCHs, MSVC will not do the regular include + # directory lookup, but simply use a string match to find the + # PCH to use. That means the #include directive must match the + # pch_file.text used during PCH CREATION verbatim. + # When CREATING a PCH, MSVC will do the include directory + # lookup to find the actual PCH header to use. Thus, the PCH + # header must either be in the include_directories of the target + # or be in the same directory as the PCH implementation. + pch_file.text = header + pch_out = ET.SubElement(inc_cl, 'PrecompiledHeaderOutputFile') + pch_out.text = f'$(IntDir)$(TargetName)-{lang}.pch' + + # Need to set the name for the pdb, as cl otherwise gives it a static + # name. Which leads to problems when there is more than one pch + # (e.g. for different languages). + pch_pdb = ET.SubElement(inc_cl, 'ProgramDataBaseFileName') + pch_pdb.text = f'$(IntDir)$(TargetName)-{lang}.pdb' + + return header + + def is_argument_with_msbuild_xml_entry(self, entry): + # Remove arguments that have a top level XML entry so + # they are not used twice. + # FIXME add args as needed. + if entry[1:].startswith('fsanitize'): + return True + return entry[1:].startswith('M') + + def add_additional_options(self, lang, parent_node, file_args): + args = [] + for arg in file_args[lang].to_native(): + if self.is_argument_with_msbuild_xml_entry(arg): + continue + if arg == '%(AdditionalOptions)': + args.append(arg) + else: + args.append(self.escape_additional_option(arg)) + ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(args) + + # Set up each project's source file ('CLCompile') element with appropriate preprocessor, include dir, and compile option values for correct intellisense. + def add_project_nmake_defs_incs_and_opts(self, parent_node, src: str, defs_paths_opts_per_lang_and_buildtype: dict, platform: str): + # For compactness, sources whose type matches the primary src type (i.e. most frequent in the set of source types used in the target/project, + # according to the 'captured_build_args' map), can simply reference the preprocessor definitions, include dirs, and compile option NMake fields of + # the project itself. + # However, if a src is of a non-primary type, it could have totally different defs/dirs/options so we're going to have to fill in the full, verbose + # set of values for these fields, which needs to be fully expanded per build type / configuration. + # + # FIXME: Suppose a project contains .cpp and .c src files with different compile defs/dirs/options, while also having .h files, some of which + # are included by .cpp sources and others included by .c sources: How do we know whether the .h source should be using the .cpp or .c src + # defs/dirs/options? Might it also be possible for a .h header to be shared between .cpp and .c sources? If so, I don't see how we can + # correctly configure these intellisense fields. + # For now, all sources/headers that fail to find their extension's language in the '...nmake_defs_paths_opts...' map will just adopt the project + # defs/dirs/opts that are set for the nominal 'primary' src type. + ext = src.split('.')[-1] + lang = compilers.compilers.SUFFIX_TO_LANG.get(ext, None) + if lang in defs_paths_opts_per_lang_and_buildtype.keys(): + # This is a non-primary src type for which can't simply reference the project's nmake fields; + # we must laboriously fill in the fields for all buildtypes. + for buildtype in coredata.get_genvs_default_buildtype_list(): + (defs, paths, opts) = defs_paths_opts_per_lang_and_buildtype[lang][buildtype] + condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{platform}\'' + ET.SubElement(parent_node, 'PreprocessorDefinitions', Condition=condition).text = defs + ET.SubElement(parent_node, 'AdditionalIncludeDirectories', Condition=condition).text = paths + ET.SubElement(parent_node, 'AdditionalOptions', Condition=condition).text = opts + else: # Can't find bespoke nmake defs/dirs/opts fields for this extention, so just reference the project's fields + ET.SubElement(parent_node, 'PreprocessorDefinitions').text = '$(NMakePreprocessorDefinitions)' + ET.SubElement(parent_node, 'AdditionalIncludeDirectories').text = '$(NMakeIncludeSearchPath)' + ET.SubElement(parent_node, 'AdditionalOptions').text = '$(AdditionalOptions)' + + def add_preprocessor_defines(self, lang, parent_node, file_defines): + defines = [] + for define in file_defines[lang]: + if define == '%(PreprocessorDefinitions)': + defines.append(define) + else: + defines.append(self.escape_preprocessor_define(define)) + ET.SubElement(parent_node, "PreprocessorDefinitions").text = ';'.join(defines) + + def add_include_dirs(self, lang, parent_node, file_inc_dirs): + dirs = file_inc_dirs[lang] + ET.SubElement(parent_node, "AdditionalIncludeDirectories").text = ';'.join(dirs) + + @staticmethod + def has_objects(objects, additional_objects, generated_objects): + # Ignore generated objects, those are automatically used by MSBuild because they are part of + # the CustomBuild Outputs. + return len(objects) + len(additional_objects) > 0 + + @staticmethod + def add_generated_objects(node, generated_objects): + # Do not add generated objects to project file. Those are automatically used by MSBuild, because + # they are part of the CustomBuild Outputs. + return + + @staticmethod + def escape_preprocessor_define(define: str) -> str: + # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx + table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', + "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', + # We need to escape backslash because it'll be un-escaped by + # Windows during process creation when it parses the arguments + # Basically, this converts `\` to `\\`. + '\\': '\\\\'}) + return define.translate(table) + + @staticmethod + def escape_additional_option(option: str) -> str: + # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx + table = str.maketrans({'%': '%25', '$': '%24', '@': '%40', + "'": '%27', ';': '%3B', '?': '%3F', '*': '%2A', ' ': '%20'}) + option = option.translate(table) + # Since we're surrounding the option with ", if it ends in \ that will + # escape the " when the process arguments are parsed and the starting + # " will not terminate. So we escape it if that's the case. I'm not + # kidding, this is how escaping works for process args on Windows. + if option.endswith('\\'): + option += '\\' + return f'"{option}"' + + @staticmethod + def add_filter_info(list_filters_path, filter_group, sub_element, file_path, forced_filter_name=None, down=''): + filter_inc_cl = ET.SubElement(filter_group, sub_element, Include=file_path) + + # Force the subdir + if forced_filter_name: + filter_path = forced_filter_name + else: + # Create a subdir following the placement if on the same drive + filter_path = Path(file_path).resolve().parent + if Path(file_path).drive == Path(down).drive: + filter_path = Path(os.path.relpath(str(filter_path), down)).as_posix().replace('../', '').replace('..', '') + else: + return # No filter needed + + # Needed to have non posix path + filter_path = filter_path.replace('/', '\\') + + if filter_path and filter_path != '.': + # Remove ending backslash + filter_path = filter_path.rstrip('\\') + # Create a hierarchical level of directories + list_path = filter_path.split('\\') + new_filter_path = '' + for path in list_path: + if new_filter_path: + new_filter_path = new_filter_path + '\\' + path + else: + new_filter_path = path + list_filters_path.add(new_filter_path) + # Create a new filter node for the current file added + ET.SubElement(filter_inc_cl, 'Filter').text = filter_path + + @staticmethod + def split_link_args(args): + """ + Split a list of link arguments into three lists: + * library search paths + * library filenames (or paths) + * other link arguments + """ + lpaths = [] + libs = [] + other = [] + for arg in args: + if arg.startswith('/LIBPATH:'): + lpath = arg[9:] + # De-dup library search paths by removing older entries when + # a new one is found. This is necessary because unlike other + # search paths such as the include path, the library is + # searched for in the newest (right-most) search path first. + if lpath in lpaths: + lpaths.remove(lpath) + lpaths.append(lpath) + elif arg.startswith(('/', '-')): + other.append(arg) + # It's ok if we miss libraries with non-standard extensions here. + # They will go into the general link arguments. + elif arg.endswith('.lib') or arg.endswith('.a'): + # De-dup + if arg not in libs: + libs.append(arg) + else: + other.append(arg) + return lpaths, libs, other + + def _get_cl_compiler(self, target): + for lang, c in target.compilers.items(): + if lang in {'c', 'cpp'}: + return c + # No source files, only objects, but we still need a compiler, so + # return a found compiler + if len(target.objects) > 0: + for lang, c in self.environment.coredata.compilers[target.for_machine].items(): + if lang in {'c', 'cpp'}: + return c + raise MesonException('Could not find a C or C++ compiler. MSVC can only build C/C++ projects.') + + def _prettyprint_vcxproj_xml(self, tree: ET.ElementTree, ofname: str) -> None: + ofname_tmp = ofname + '~' + tree.write(ofname_tmp, encoding='utf-8', xml_declaration=True) + + # ElementTree cannot do pretty-printing, so do it manually + doc = xml.dom.minidom.parse(ofname_tmp) + with open(ofname_tmp, 'w', encoding='utf-8') as of: + of.write(doc.toprettyxml()) + replace_if_different(ofname, ofname_tmp) + + # Returns: (target_args,file_args), (target_defines,file_defines), (target_inc_dirs,file_inc_dirs) + def get_args_defines_and_inc_dirs(self, target, compiler, generated_files_include_dirs, proj_to_src_root, proj_to_src_dir, build_args): + # Arguments, include dirs, defines for all files in the current target + target_args = [] + target_defines = [] + target_inc_dirs = [] + # Arguments, include dirs, defines passed to individual files in + # a target; perhaps because the args are language-specific + # + # file_args is also later split out into defines and include_dirs in + # case someone passed those in there + file_args: T.Dict[str, CompilerArgs] = {l: c.compiler_args() for l, c in target.compilers.items()} + file_defines = {l: [] for l in target.compilers} + file_inc_dirs = {l: [] for l in target.compilers} + # The order in which these compile args are added must match + # generate_single_compile() and generate_basic_compiler_args() + for l, comp in target.compilers.items(): + if l in file_args: + file_args[l] += compilers.get_base_compile_args( + target.get_options(), comp) + file_args[l] += comp.get_option_compile_args( + target.get_options()) + + # Add compile args added using add_project_arguments() + for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items(): + if l in file_args: + file_args[l] += args + # Add compile args added using add_global_arguments() + # These override per-project arguments + for l, args in self.build.global_args[target.for_machine].items(): + if l in file_args: + file_args[l] += args + # Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these + # to override all the defaults, but not the per-target compile args. + for l in file_args.keys(): + file_args[l] += target.get_option(OptionKey('args', machine=target.for_machine, lang=l)) + for args in file_args.values(): + # This is where Visual Studio will insert target_args, target_defines, + # etc, which are added later from external deps (see below). + args += ['%(AdditionalOptions)', '%(PreprocessorDefinitions)', '%(AdditionalIncludeDirectories)'] + # Add custom target dirs as includes automatically, but before + # target-specific include dirs. See _generate_single_compile() in + # the ninja backend for caveats. + args += ['-I' + arg for arg in generated_files_include_dirs] + # Add include dirs from the `include_directories:` kwarg on the target + # and from `include_directories:` of internal deps of the target. + # + # Target include dirs should override internal deps include dirs. + # This is handled in BuildTarget.process_kwargs() + # + # Include dirs from internal deps should override include dirs from + # external deps and must maintain the order in which they are + # specified. Hence, we must reverse so that the order is preserved. + # + # These are per-target, but we still add them as per-file because we + # need them to be looked in first. + for d in reversed(target.get_include_dirs()): + # reversed is used to keep order of includes + for i in reversed(d.get_incdirs()): + curdir = os.path.join(d.get_curdir(), i) + try: + # Add source subdir first so that the build subdir overrides it + args.append('-I' + os.path.join(proj_to_src_root, curdir)) # src dir + args.append('-I' + self.relpath(curdir, target.subdir)) # build dir + except ValueError: + # Include is on different drive + args.append('-I' + os.path.normpath(curdir)) + for i in d.get_extra_build_dirs(): + curdir = os.path.join(d.get_curdir(), i) + args.append('-I' + self.relpath(curdir, target.subdir)) # build dir + # Add per-target compile args, f.ex, `c_args : ['/DFOO']`. We set these + # near the end since these are supposed to override everything else. + for l, args in target.extra_args.items(): + if l in file_args: + file_args[l] += args + # The highest priority includes. In order of directory search: + # target private dir, target build dir, target source dir + for args in file_args.values(): + t_inc_dirs = [self.relpath(self.get_target_private_dir(target), + self.get_target_dir(target))] + if target.implicit_include_directories: + t_inc_dirs += ['.', proj_to_src_dir] + args += ['-I' + arg for arg in t_inc_dirs] + + # Split preprocessor defines and include directories out of the list of + # all extra arguments. The rest go into %(AdditionalOptions). + for l, args in file_args.items(): + for arg in args[:]: + if arg.startswith(('-D', '/D')) or arg == '%(PreprocessorDefinitions)': + file_args[l].remove(arg) + # Don't escape the marker + if arg == '%(PreprocessorDefinitions)': + define = arg + else: + define = arg[2:] + # De-dup + if define not in file_defines[l]: + file_defines[l].append(define) + elif arg.startswith(('-I', '/I')) or arg == '%(AdditionalIncludeDirectories)': + file_args[l].remove(arg) + # Don't escape the marker + if arg == '%(AdditionalIncludeDirectories)': + inc_dir = arg + else: + inc_dir = arg[2:] + # De-dup + if inc_dir not in file_inc_dirs[l]: + file_inc_dirs[l].append(inc_dir) + # Add include dirs to target as well so that "Go to Document" works in headers + if inc_dir not in target_inc_dirs: + target_inc_dirs.append(inc_dir) + + # Split compile args needed to find external dependencies + # Link args are added while generating the link command + for d in reversed(target.get_external_deps()): + # Cflags required by external deps might have UNIX-specific flags, + # so filter them out if needed + if d.name != 'openmp': + d_compile_args = compiler.unix_args_to_native(d.get_compile_args()) + for arg in d_compile_args: + if arg.startswith(('-D', '/D')): + define = arg[2:] + # De-dup + if define in target_defines: + target_defines.remove(define) + target_defines.append(define) + elif arg.startswith(('-I', '/I')): + inc_dir = arg[2:] + # De-dup + if inc_dir not in target_inc_dirs: + target_inc_dirs.append(inc_dir) + else: + target_args.append(arg) + + if '/Gw' in build_args: + target_args.append('/Gw') + + return (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs) + + @staticmethod + def get_build_args(compiler, buildtype: str, optimization_level: str, debug: bool, sanitize: str) -> T.List[str]: + build_args = compiler.get_buildtype_args(buildtype) + build_args += compiler.get_optimization_args(optimization_level) + build_args += compiler.get_debug_args(debug) + build_args += compiler.sanitizer_compile_args(sanitize) + + return build_args + + #Convert a list of compile arguments from - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + #to - + # 'SOME_DEF=1;ANOTHER_DEF=someval;' + #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + @staticmethod + def extract_nmake_preprocessor_defs(captured_build_args: list[str]) -> str: + defs = '' + for arg in captured_build_args: + if arg.startswith(('-D', '/D')): + defs += arg[2:] + ';' + return defs + + #Convert a list of compile arguments from - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + #to - + # '..\\some\\dir\\include;../../some/other/dir;' + #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + @staticmethod + def extract_nmake_include_paths(captured_build_args: list[str]) -> str: + paths = '' + for arg in captured_build_args: + if arg.startswith(('-I', '/I')): + paths += arg[2:] + ';' + return paths + + #Convert a list of compile arguments from - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + #to - + # '/MDd;/W2;/std:c++17;/Od/Zi' + #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + @staticmethod + def extract_intellisense_additional_compiler_options(captured_build_args: list[str]) -> str: + additional_opts = '' + for arg in captured_build_args: + if (not arg.startswith(('-D', '/D', '-I', '/I'))) and arg.startswith(('-', '/')): + additional_opts += arg + ';' + return additional_opts + + @staticmethod + def get_nmake_base_meson_command_and_exe_search_paths() -> T.Tuple[str, str]: + meson_cmd_list = mesonlib.get_meson_command() + assert (len(meson_cmd_list) == 1) or (len(meson_cmd_list) == 2) + # We expect get_meson_command() to either be of the form - + # 1: ['path/to/meson.exe'] + # or - + # 2: ['path/to/python.exe', 'and/path/to/meson.py'] + # so we'd like to ensure our makefile-style project invokes the same meson executable or python src as this instance. + exe_search_paths = os.path.dirname(meson_cmd_list[0]) + nmake_base_meson_command = os.path.basename(meson_cmd_list[0]) + if len(meson_cmd_list) != 1: + # We expect to be dealing with case '2', shown above. + # With Windows, it's also possible that we get a path to the second element of meson_cmd_list that contains spaces + # (e.g. 'and/path to/meson.py'). So, because this will end up directly in the makefile/NMake command lines, we'd + # better always enclose it in quotes. Only strictly necessary for paths with spaces but no harm for paths without - + nmake_base_meson_command += ' \"' + meson_cmd_list[1] + '\"' + exe_search_paths += ';' + os.path.dirname(meson_cmd_list[1]) + + # Additionally, in some cases, we appear to have to add 'C:\Windows\system32;C:\Windows' to the 'Path' environment (via the + # ExecutablePath element), without which, the 'meson compile ...' (NMakeBuildCommandLine) command can fail (failure to find + # stdio.h and similar), so something is quietly switching some critical build behaviour based on the presence of these in + # the 'Path'. + # Not sure if this ultimately comes down to some 'find and guess' hidden behaviours within meson or within MSVC tools, but + # I guess some projects may implicitly rely on this behaviour. + # Things would be cleaner, more robust, repeatable, and portable if meson (and msvc tools) replaced all this kind of + # find/guess behaviour with the requirement that things just be explicitly specified by the user. + # An example of this can be seen with - + # 1: Download https://github.com/facebook/zstd source + # 2: cd to the 'zstd-dev\build\meson' dir + # 3: meson setup -Dbin_programs=true -Dbin_contrib=true --genvslite vs2022 builddir_vslite + # 4: Open the generated 'builddir_vslite_vs\zstd.sln' and build through a project, which should explicitly add the above to + # the project's 'Executable Directories' paths and build successfully. + # 5: Remove 'C:\Windows\system32;C:\Windows;' from the same project's 'Executable Directories' paths and rebuild. + # This should now fail. + # It feels uncomfortable to do this but what better alternative is there (and might this introduce new problems)? - + exe_search_paths += ';C:\\Windows\\system32;C:\\Windows' + # A meson project that explicitly specifies compiler/linker tools and sdk/include paths is not going to have any problems + # with this addition. + + return (nmake_base_meson_command, exe_search_paths) + + def add_gen_lite_makefile_vcxproj_elements(self, + root: ET.Element, + platform: str, + target_ext: str, + vslite_ctx: dict, + target, + proj_to_build_root: str, + primary_src_lang: T.Optional[str]) -> None: + ET.SubElement(root, 'ImportGroup', Label='ExtensionSettings') + ET.SubElement(root, 'ImportGroup', Label='Shared') + prop_sheets_grp = ET.SubElement(root, 'ImportGroup', Label='PropertySheets') + ET.SubElement(prop_sheets_grp, 'Import', {'Project': r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props', + 'Condition': r"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')", + 'Label': 'LocalAppDataPlatform' + }) + ET.SubElement(root, 'PropertyGroup', Label='UserMacros') + + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + + # Relative path from this .vcxproj to the directory containing the set of '..._[debug/debugoptimized/release]' setup meson build dirs. + proj_to_multiconfigured_builds_parent_dir = os.path.join(proj_to_build_root, '..') + + # Conditional property groups per configuration (buildtype). E.g. - + # + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + for buildtype in multi_config_buildtype_list: + per_config_prop_group = ET.SubElement(root, 'PropertyGroup', Condition=f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{platform}\'') + (_, build_dir_tail) = os.path.split(self.src_to_build) + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + ET.SubElement(per_config_prop_group, 'OutDir').text = f'{proj_to_build_dir_for_buildtype}\\' + ET.SubElement(per_config_prop_group, 'IntDir').text = f'{proj_to_build_dir_for_buildtype}\\' + ET.SubElement(per_config_prop_group, 'NMakeBuildCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}"' + ET.SubElement(per_config_prop_group, 'NMakeOutput').text = f'$(OutDir){target.name}{target_ext}' + captured_build_args = vslite_ctx[buildtype][target.get_id()] + # 'captured_build_args' is a dictionary, mapping from each src file type to a list of compile args to use for that type. + # Usually, there's just one but we could have multiple src types. However, since there's only one field for the makefile + # project's NMake... preprocessor/include intellisense fields, we'll just use the first src type we have to fill in + # these fields. Then, any src files in this VS project that aren't of this first src type will then need to override + # its intellisense fields instead of simply referencing the values in the project. + ET.SubElement(per_config_prop_group, 'NMakeReBuildCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}" --clean && {nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}"' + ET.SubElement(per_config_prop_group, 'NMakeCleanCommandLine').text = f'{nmake_base_meson_command} compile -C "{proj_to_build_dir_for_buildtype}" --clean' + # Need to set the 'ExecutablePath' element for the above NMake... commands to be able to invoke the meson command. + ET.SubElement(per_config_prop_group, 'ExecutablePath').text = exe_search_paths + # We may not have any src files and so won't have a primary src language. In which case, we've nothing to fill in for this target's intellisense fields - + if primary_src_lang: + primary_src_type_build_args = captured_build_args[primary_src_lang] + ET.SubElement(per_config_prop_group, 'NMakePreprocessorDefinitions').text = Vs2010Backend.extract_nmake_preprocessor_defs(primary_src_type_build_args) + ET.SubElement(per_config_prop_group, 'NMakeIncludeSearchPath').text = Vs2010Backend.extract_nmake_include_paths(primary_src_type_build_args) + ET.SubElement(per_config_prop_group, 'AdditionalOptions').text = Vs2010Backend.extract_intellisense_additional_compiler_options(primary_src_type_build_args) + + # Unless we explicitly specify the following empty path elements, the project is assigned a load of nasty defaults that fill these + # with values like - + # $(VC_IncludePath);$(WindowsSDK_IncludePath); + # which are all based on the current install environment (a recipe for non-reproducibility problems), not the paths that will be used by + # the actual meson compile jobs. Although these elements look like they're only for MSBuild operations, they're not needed with our simple, + # lite/makefile-style projects so let's just remove them in case they do get used/confused by intellisense. + ET.SubElement(per_config_prop_group, 'IncludePath') + ET.SubElement(per_config_prop_group, 'ExternalIncludePath') + ET.SubElement(per_config_prop_group, 'ReferencePath') + ET.SubElement(per_config_prop_group, 'LibraryPath') + ET.SubElement(per_config_prop_group, 'LibraryWPath') + ET.SubElement(per_config_prop_group, 'SourcePath') + ET.SubElement(per_config_prop_group, 'ExcludePath') + + def add_non_makefile_vcxproj_elements( + self, + root: ET.Element, + type_config: ET.Element, + target, + platform: str, + subsystem, + build_args, + target_args, + target_defines, + target_inc_dirs, + file_args + ) -> None: + compiler = self._get_cl_compiler(target) + buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype) + + # Prefix to use to access the build root from the vcxproj dir + down = self.target_to_build_root(target) + + # FIXME: Should the following just be set in create_basic_project(), even if + # irrelevant for current target? + + # FIXME: Meson's LTO support needs to be integrated here + ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false' + # Let VS auto-set the RTC level + ET.SubElement(type_config, 'BasicRuntimeChecks').text = 'Default' + # Incremental linking increases code size + if '/INCREMENTAL:NO' in buildtype_link_args: + ET.SubElement(type_config, 'LinkIncremental').text = 'false' + + # Build information + compiles = ET.SubElement(root, 'ItemDefinitionGroup') + clconf = ET.SubElement(compiles, 'ClCompile') + if True in ((dep.name == 'openmp') for dep in target.get_external_deps()): + ET.SubElement(clconf, 'OpenMPSupport').text = 'true' + # CRT type; debug or release + vscrt_type = target.get_option(OptionKey('b_vscrt')) + if vscrt_type == 'from_buildtype': + if self.buildtype == 'debug': + ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' + else: + ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL' + elif vscrt_type == 'static_from_buildtype': + if self.buildtype == 'debug': + ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebug' + else: + ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' + elif vscrt_type == 'mdd': + ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' + elif vscrt_type == 'mt': + # FIXME, wrong + ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' + elif vscrt_type == 'mtd': + # FIXME, wrong + ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebug' + else: + ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' + ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL' + # Sanitizers + if '/fsanitize=address' in build_args: + ET.SubElement(type_config, 'EnableASAN').text = 'true' + # Debug format + if '/ZI' in build_args: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'EditAndContinue' + elif '/Zi' in build_args: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'ProgramDatabase' + elif '/Z7' in build_args: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'OldStyle' + else: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'None' + # Runtime checks + if '/RTC1' in build_args: + ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'EnableFastChecks' + elif '/RTCu' in build_args: + ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck' + elif '/RTCs' in build_args: + ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck' + # Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise + # cl will give warning D9025: overriding '/Ehs' with cpp_eh value + if 'cpp' in target.compilers: + eh = target.get_option(OptionKey('eh', machine=target.for_machine, lang='cpp')) + if eh == 'a': + ET.SubElement(clconf, 'ExceptionHandling').text = 'Async' + elif eh == 's': + ET.SubElement(clconf, 'ExceptionHandling').text = 'SyncCThrow' + elif eh == 'none': + ET.SubElement(clconf, 'ExceptionHandling').text = 'false' + else: # 'sc' or 'default' + ET.SubElement(clconf, 'ExceptionHandling').text = 'Sync' + + if len(target_args) > 0: + target_args.append('%(AdditionalOptions)') + ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args) + ET.SubElement(clconf, 'AdditionalIncludeDirectories').text = ';'.join(target_inc_dirs) + target_defines.append('%(PreprocessorDefinitions)') + ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines) + ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' + # Warning level + warning_level = T.cast('str', target.get_option(OptionKey('warning_level'))) + ET.SubElement(clconf, 'WarningLevel').text = 'Level' + str(1 + int(warning_level)) + if target.get_option(OptionKey('werror')): + ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' + # Optimization flags + o_flags = split_o_flags_args(build_args) + if '/Ox' in o_flags: + ET.SubElement(clconf, 'Optimization').text = 'Full' + elif '/O2' in o_flags: + ET.SubElement(clconf, 'Optimization').text = 'MaxSpeed' + elif '/O1' in o_flags: + ET.SubElement(clconf, 'Optimization').text = 'MinSpace' + elif '/Od' in o_flags: + ET.SubElement(clconf, 'Optimization').text = 'Disabled' + if '/Oi' in o_flags: + ET.SubElement(clconf, 'IntrinsicFunctions').text = 'true' + if '/Ob1' in o_flags: + ET.SubElement(clconf, 'InlineFunctionExpansion').text = 'OnlyExplicitInline' + elif '/Ob2' in o_flags: + ET.SubElement(clconf, 'InlineFunctionExpansion').text = 'AnySuitable' + # Size-preserving flags + if '/Os' in o_flags: + ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Size' + # Note: setting FavorSizeOrSpeed with clang-cl conflicts with /Od and can make debugging difficult, so don't. + elif '/Od' not in o_flags: + ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Speed' + # Note: SuppressStartupBanner is /NOLOGO and is 'true' by default + self.generate_lang_standard_info(file_args, clconf) + + resourcecompile = ET.SubElement(compiles, 'ResourceCompile') + ET.SubElement(resourcecompile, 'PreprocessorDefinitions') + + # Linker options + link = ET.SubElement(compiles, 'Link') + extra_link_args = compiler.compiler_args() + # FIXME: Can these buildtype linker args be added as tags in the + # vcxproj file (similar to buildtype compiler args) instead of in + # AdditionalOptions? + extra_link_args += compiler.get_buildtype_linker_args(self.buildtype) + # BEN: always generate PDBs actually. + self.generate_debug_information(link) + # Generate Debug info + #if self.debug: + # self.generate_debug_information(link) + #else: + # ET.SubElement(link, 'GenerateDebugInformation').text = 'false' + if not isinstance(target, build.StaticLibrary): + if isinstance(target, build.SharedModule): + extra_link_args += compiler.get_std_shared_module_link_args(target.get_options()) + # Add link args added using add_project_link_arguments() + extra_link_args += self.build.get_project_link_args(compiler, target.subproject, target.for_machine) + # Add link args added using add_global_link_arguments() + # These override per-project link arguments + extra_link_args += self.build.get_global_link_args(compiler, target.for_machine) + # Link args added from the env: LDFLAGS, or the cross file. We want + # these to override all the defaults but not the per-target link + # args. + extra_link_args += self.environment.coredata.get_external_link_args( + target.for_machine, compiler.get_language()) + # Only non-static built targets need link args and link dependencies + extra_link_args += target.link_args + # External deps must be last because target link libraries may depend on them. + for dep in target.get_external_deps(): + # Extend without reordering or de-dup to preserve `-L -l` sets + # https://github.com/mesonbuild/meson/issues/1718 + if dep.name == 'openmp': + ET.SubElement(clconf, 'OpenMPSupport').text = 'true' + else: + extra_link_args.extend_direct(dep.get_link_args()) + for d in target.get_dependencies(): + if isinstance(d, build.StaticLibrary): + for dep in d.get_external_deps(): + if dep.name == 'openmp': + ET.SubElement(clconf, 'OpenMPSupport').text = 'true' + else: + extra_link_args.extend_direct(dep.get_link_args()) + # Add link args for c_* or cpp_* build options. Currently this only + # adds c_winlibs and cpp_winlibs when building for Windows. This needs + # to be after all internal and external libraries so that unresolved + # symbols from those can be found here. This is needed when the + # *_winlibs that we want to link to are static mingw64 libraries. + extra_link_args += compiler.get_option_link_args(target.get_options()) + (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native()) + + # Add more libraries to be linked if needed + for t in target.get_dependencies(): + if isinstance(t, build.CustomTargetIndex): + # We don't need the actual project here, just the library name + lobj = t + else: + lobj = self.build.targets[t.get_id()] + linkname = os.path.join(down, self.get_target_filename_for_linking(lobj)) + if t in target.link_whole_targets: + if compiler.id == 'msvc' and version_compare(compiler.version, '<19.00.23918'): + # Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2 + l = t.extract_all_objects(False) + + # Unfortunately, we can't use self.object_filename_from_source() + for gen in l.genlist: + for src in gen.get_outputs(): + if self.environment.is_source(src): + path = self.get_target_generated_dir(t, gen, src) + gen_src_ext = '.' + os.path.splitext(path)[1][1:] + extra_link_args.append(path[:-len(gen_src_ext)] + '.obj') + + for src in l.srclist: + obj_basename = None + if self.environment.is_source(src): + obj_basename = self.object_filename_from_source(t, src) + target_private_dir = self.relpath(self.get_target_private_dir(t), + self.get_target_dir(t)) + rel_obj = os.path.join(target_private_dir, obj_basename) + extra_link_args.append(rel_obj) + + extra_link_args.extend(self.flatten_object_list(t)) + else: + # /WHOLEARCHIVE:foo must go into AdditionalOptions + extra_link_args += compiler.get_link_whole_for(linkname) + # To force Visual Studio to build this project even though it + # has no sources, we include a reference to the vcxproj file + # that builds this target. Technically we should add this only + # if the current target has no sources, but it doesn't hurt to + # have 'extra' references. + trelpath = self.get_target_dir_relative_to(t, target) + tvcxproj = os.path.join(trelpath, t.get_id() + '.vcxproj') + tid = self.environment.coredata.target_guids[t.get_id()] + self.add_project_reference(root, tvcxproj, tid, link_outputs=True) + # Mark the dependency as already handled to not have + # multiple references to the same target. + self.handled_target_deps[target.get_id()].append(t.get_id()) + else: + # Other libraries go into AdditionalDependencies + if linkname not in additional_links: + additional_links.append(linkname) + for lib in self.get_custom_target_provided_libraries(target): + additional_links.append(self.relpath(lib, self.get_target_dir(target))) + + if len(extra_link_args) > 0: + extra_link_args.append('%(AdditionalOptions)') + ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args) + if len(additional_libpaths) > 0: + additional_libpaths.insert(0, '%(AdditionalLibraryDirectories)') + ET.SubElement(link, 'AdditionalLibraryDirectories').text = ';'.join(additional_libpaths) + if len(additional_links) > 0: + additional_links.append('%(AdditionalDependencies)') + ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links) + ofile = ET.SubElement(link, 'OutputFile') + ofile.text = f'$(OutDir){target.get_filename()}' + subsys = ET.SubElement(link, 'SubSystem') + subsys.text = subsystem + if isinstance(target, (build.SharedLibrary, build.Executable)) and target.get_import_filename(): + # DLLs built with MSVC always have an import library except when + # they're data-only DLLs, but we don't support those yet. + ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename() + if isinstance(target, build.SharedLibrary): + # Add module definitions file, if provided + if target.vs_module_defs: + relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src)) + ET.SubElement(link, 'ModuleDefinitionFile').text = relpath + # BEN: always generate PDBs actually. + #if self.debug: + pdb = ET.SubElement(link, 'ProgramDataBaseFileName') + pdb.text = f'$(OutDir){target.name}.pdb' + targetmachine = ET.SubElement(link, 'TargetMachine') + if target.for_machine is MachineChoice.BUILD: + targetplatform = platform.lower() + else: + targetplatform = self.platform.lower() + if targetplatform == 'win32': + targetmachine.text = 'MachineX86' + elif targetplatform == 'x64' or detect_microsoft_gdk(targetplatform): + targetmachine.text = 'MachineX64' + elif targetplatform == 'arm': + targetmachine.text = 'MachineARM' + elif targetplatform == 'arm64': + targetmachine.text = 'MachineARM64' + elif targetplatform == 'arm64ec': + targetmachine.text = 'MachineARM64EC' + else: + raise MesonException('Unsupported Visual Studio target machine: ' + targetplatform) + # /nologo + ET.SubElement(link, 'SuppressStartupBanner').text = 'true' + # /release + if not target.get_option(OptionKey('debug')): + ET.SubElement(link, 'SetChecksum').text = 'true' + + # Visual studio doesn't simply allow the src files of a project to be added with the 'Condition=...' attribute, + # to allow us to point to the different debug/debugoptimized/release sets of generated src files for each of + # the solution's configurations. Similarly, 'ItemGroup' also doesn't support 'Condition'. So, without knowing + # a better (simple) alternative, for now, we'll repoint these generated sources (which will be incorrectly + # pointing to non-existent files under our '[builddir]_vs' directory) to the appropriate location under one of + # our buildtype build directores (e.g. '[builddir]_debug'). + # This will at least allow the user to open the files of generated sources listed in the solution explorer, + # once a build/compile has generated these sources. + # + # This modifies the paths in 'gen_files' in place, as opposed to returning a new list of modified paths. + def relocate_generated_file_paths_to_concrete_build_dir(self, gen_files: T.List[str], target: T.Union[build.Target, build.CustomTargetIndex]) -> None: + (_, build_dir_tail) = os.path.split(self.src_to_build) + meson_build_dir_for_buildtype = build_dir_tail[:-2] + coredata.get_genvs_default_buildtype_list()[0] # Get the first buildtype suffixed dir (i.e. '[builddir]_debug') from '[builddir]_vs' + # Relative path from this .vcxproj to the directory containing the set of '..._[debug/debugoptimized/release]' setup meson build dirs. + proj_to_build_root = self.target_to_build_root(target) + proj_to_multiconfigured_builds_parent_dir = os.path.join(proj_to_build_root, '..') + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + relocate_to_concrete_builddir_target = os.path.normpath(os.path.join(proj_to_build_dir_for_buildtype, self.get_target_dir(target))) + for idx, file_path in enumerate(gen_files): + gen_files[idx] = os.path.normpath(os.path.join(relocate_to_concrete_builddir_target, file_path)) + + # Returns bool indicating whether the .vcxproj has been generated. + # Under some circumstances, it's unnecessary to create some .vcxprojs, so, when generating the .sln, + # we need to respect that not all targets will have generated a project. + def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ctx: dict = None) -> bool: + mlog.debug(f'Generating vcxproj {target.name}.') + subsystem = 'Windows' + self.handled_target_deps[target.get_id()] = [] + + if self.gen_lite: + if not isinstance(target, build.BuildTarget): + # Since we're going to delegate all building to the one true meson build command, we don't need + # to generate .vcxprojs for targets that don't add any source files or just perform custom build + # commands. These are targets of types CustomTarget or RunTarget. So let's just skip generating + # these otherwise insubstantial non-BuildTarget targets. + return False + conftype = 'Makefile' + elif isinstance(target, build.Executable): + conftype = 'Application' + if target.gui_app is not None: + if not target.gui_app: + subsystem = 'Console' + else: + # If someone knows how to set the version properly, + # please send a patch. + subsystem = target.win_subsystem.split(',')[0] + elif isinstance(target, build.StaticLibrary): + conftype = 'StaticLibrary' + elif isinstance(target, build.SharedLibrary): + conftype = 'DynamicLibrary' + elif isinstance(target, build.CustomTarget): + self.gen_custom_target_vcxproj(target, ofname, guid) + return True + elif isinstance(target, build.RunTarget): + self.gen_run_target_vcxproj(target, ofname, guid) + return True + elif isinstance(target, build.CompileTarget): + self.gen_compile_target_vcxproj(target, ofname, guid) + return True + else: + raise MesonException(f'Unknown target type for {target.get_basename()}') + + (sources, headers, objects, _languages) = self.split_sources(target.sources) + if target.is_unity: + sources = self.generate_unity_files(target, sources) + if target.for_machine is MachineChoice.BUILD: + platform = self.build_platform + else: + platform = self.platform + + tfilename = os.path.splitext(target.get_filename()) + + (root, type_config) = self.create_basic_project(tfilename[0], + temp_dir=target.get_id(), + guid=guid, + conftype=conftype, + target_ext=tfilename[1], + target_platform=platform) + + # vcxproj.filters file + root_filter = self.create_basic_project_filters() + + generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands( + target, root) + (gen_src, gen_hdrs, gen_objs, _gen_langs) = self.split_sources(generated_files) + (custom_src, custom_hdrs, custom_objs, _custom_langs) = self.split_sources(custom_target_output_files) + gen_src += custom_src + gen_hdrs += custom_hdrs + + compiler = self._get_cl_compiler(target) + build_args = Vs2010Backend.get_build_args(compiler, self.buildtype, self.optimization, self.debug, self.sanitize) + + assert isinstance(target, (build.Executable, build.SharedLibrary, build.StaticLibrary, build.SharedModule)), 'for mypy' + # Prefix to use to access the build root from the vcxproj dir + proj_to_build_root = self.target_to_build_root(target) + # Prefix to use to access the source tree's root from the vcxproj dir + proj_to_src_root = os.path.join(proj_to_build_root, self.build_to_src) + # Prefix to use to access the source tree's subdir from the vcxproj dir + proj_to_src_dir = os.path.join(proj_to_src_root, self.get_target_dir(target)) + + (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs) = self.get_args_defines_and_inc_dirs( + target, compiler, generated_files_include_dirs, proj_to_src_root, proj_to_src_dir, build_args) + + if self.gen_lite: + assert vslite_ctx is not None + primary_src_lang = get_primary_source_lang(target.sources, custom_src) + self.add_gen_lite_makefile_vcxproj_elements(root, platform, tfilename[1], vslite_ctx, target, proj_to_build_root, primary_src_lang) + else: + self.add_non_makefile_vcxproj_elements(root, type_config, target, platform, subsystem, build_args, target_args, target_defines, target_inc_dirs, file_args) + + meson_file_group = ET.SubElement(root, 'ItemGroup') + ET.SubElement(meson_file_group, 'None', Include=os.path.join(proj_to_src_dir, build_filename)) + + # Visual Studio can't load projects that present duplicated items. Filter them out + # by keeping track of already added paths. + def path_normalize_add(path, lis): + normalized = os.path.normcase(os.path.normpath(path)) + if normalized not in lis: + lis.append(normalized) + return True + else: + return False + + pch_sources = {} + if self.target_uses_pch(target): + for lang in ['c', 'cpp']: + pch = target.get_pch(lang) + if not pch: + continue + if compiler.id == 'msvc': + if len(pch) == 1: + # Auto generate PCH. + src = os.path.join(proj_to_build_root, self.create_msvc_pch_implementation(target, lang, pch[0])) + pch_header_dir = os.path.dirname(os.path.join(proj_to_src_dir, pch[0])) + else: + src = os.path.join(proj_to_src_dir, pch[1]) + pch_header_dir = None + pch_sources[lang] = [pch[0], src, lang, pch_header_dir] + else: + # I don't know whether its relevant but let's handle other compilers + # used with a vs backend + pch_sources[lang] = [pch[0], None, lang, None] + + list_filters_path = set() + + previous_includes = [] + if len(headers) + len(gen_hdrs) + len(target.extra_files) + len(pch_sources) > 0: + if self.gen_lite and gen_hdrs: + # Although we're constructing our .vcxproj under our '..._vs' directory, we want to reference generated files + # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building. + self.relocate_generated_file_paths_to_concrete_build_dir(gen_hdrs, target) + + # Filter information + filter_group_include = ET.SubElement(root_filter, 'ItemGroup') + + inc_hdrs = ET.SubElement(root, 'ItemGroup') + for h in headers: + relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src)) + if path_normalize_add(relpath, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', relpath, h.subdir) + ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) + for h in gen_hdrs: + if path_normalize_add(h, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', h) + ET.SubElement(inc_hdrs, 'CLInclude', Include=h) + for h in target.extra_files: + relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src)) + if path_normalize_add(relpath, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', relpath, h.subdir) + ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) + for headers in pch_sources.values(): + path = os.path.join(proj_to_src_dir, headers[0]) + if path_normalize_add(path, previous_includes): + self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', path, 'pch') + ET.SubElement(inc_hdrs, 'CLInclude', Include=path) + + previous_sources = [] + if len(sources) + len(gen_src) + len(pch_sources) > 0: + if self.gen_lite: + # Get data to fill in intellisense fields for sources that can't reference the project-wide values + defs_paths_opts_per_lang_and_buildtype = get_non_primary_lang_intellisense_fields( + vslite_ctx, + target.get_id(), + primary_src_lang) + if gen_src: + # Although we're constructing our .vcxproj under our '..._vs' directory, we want to reference generated files + # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building. + self.relocate_generated_file_paths_to_concrete_build_dir(gen_src, target) + + # Filter information + filter_group_compile = ET.SubElement(root_filter, 'ItemGroup') + + inc_src = ET.SubElement(root, 'ItemGroup') + for s in sources: + relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src)) + if path_normalize_add(relpath, previous_sources): + self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', relpath, s.subdir) + inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) + if self.gen_lite: + self.add_project_nmake_defs_incs_and_opts(inc_cl, relpath, defs_paths_opts_per_lang_and_buildtype, platform) + else: + lang = Vs2010Backend.lang_from_source_file(s) + self.add_pch(pch_sources, lang, inc_cl) + self.add_additional_options(lang, inc_cl, file_args) + self.add_preprocessor_defines(lang, inc_cl, file_defines) + self.add_include_dirs(lang, inc_cl, file_inc_dirs) + ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \ + self.object_filename_from_source(target, s) + for s in gen_src: + if path_normalize_add(s, previous_sources): + self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', s) + inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s) + if self.gen_lite: + self.add_project_nmake_defs_incs_and_opts(inc_cl, s, defs_paths_opts_per_lang_and_buildtype, platform) + else: + lang = Vs2010Backend.lang_from_source_file(s) + self.add_pch(pch_sources, lang, inc_cl) + self.add_additional_options(lang, inc_cl, file_args) + self.add_preprocessor_defines(lang, inc_cl, file_defines) + self.add_include_dirs(lang, inc_cl, file_inc_dirs) + s = File.from_built_file(target.get_subdir(), s) + ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \ + self.object_filename_from_source(target, s) + for lang, headers in pch_sources.items(): + impl = headers[1] + if impl and path_normalize_add(impl, previous_sources): + self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', impl, 'pch') + inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=impl) + self.create_pch(pch_sources, lang, inc_cl) + if self.gen_lite: + self.add_project_nmake_defs_incs_and_opts(inc_cl, impl, defs_paths_opts_per_lang_and_buildtype, platform) + else: + self.add_additional_options(lang, inc_cl, file_args) + self.add_preprocessor_defines(lang, inc_cl, file_defines) + pch_header_dir = pch_sources[lang][3] + if pch_header_dir: + inc_dirs = copy.deepcopy(file_inc_dirs) + inc_dirs[lang] = [pch_header_dir] + inc_dirs[lang] + else: + inc_dirs = file_inc_dirs + self.add_include_dirs(lang, inc_cl, inc_dirs) + # XXX: Do we need to set the object file name here too? + + # Filter information + filter_group = ET.SubElement(root_filter, 'ItemGroup') + for filter_dir in list_filters_path: + filter = ET.SubElement(filter_group, 'Filter', Include=filter_dir) + ET.SubElement(filter, 'UniqueIdentifier').text = '{' + str(uuid.uuid4()) + '}' + + additional_objects = [] + for o in self.flatten_object_list(target, proj_to_build_root)[0]: + assert isinstance(o, str) + additional_objects.append(o) + for o in custom_objs: + additional_objects.append(o) + + previous_objects = [] + if self.has_objects(objects, additional_objects, gen_objs): + inc_objs = ET.SubElement(root, 'ItemGroup') + for s in objects: + relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src)) + if path_normalize_add(relpath, previous_objects): + ET.SubElement(inc_objs, 'Object', Include=relpath) + for s in additional_objects: + if path_normalize_add(s, previous_objects): + ET.SubElement(inc_objs, 'Object', Include=s) + self.add_generated_objects(inc_objs, gen_objs) + + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) + if not self.gen_lite: + # Injecting further target dependencies into this vcxproj implies and forces a Visual Studio BUILD dependency, + # which we don't want when using 'genvslite'. A gen_lite build as little involvement with the visual studio's + # build system as possible. + self.add_target_deps(root, target) + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + self._prettyprint_vcxproj_xml(ET.ElementTree(root_filter), ofname + '.filters') + return True + + def gen_regenproj(self): + # To fully adapt the REGEN work for a 'genvslite' solution, to check timestamps, settings, and regenerate the + # '[builddir]_vs' solution/vcxprojs, as well as regenerating the accompanying buildtype-suffixed ninja build + # directories (from which we need to first collect correct, updated preprocessor defs and compiler options in + # order to fill in the regenerated solution's intellisense settings) would require some non-trivial intrusion + # into the 'meson --internal regencheck ./meson-private' execution path (and perhaps also the '--internal + # regenerate' and even 'meson setup --reconfigure' code). So, for now, we'll instead give the user a simpler + # 'reconfigure' utility project that just runs 'meson setup --reconfigure [builddir]_[buildtype] [srcdir]' on + # each of the ninja build dirs. + # + # FIXME: That will keep the building and compiling correctly configured but obviously won't update the + # solution and vcxprojs, which may allow solution src files and intellisense options to go out-of-date; the + # user would still have to manually 'meson setup --genvslite [vsxxxx] [builddir] [srcdir]' to fully regenerate + # a complete and correct solution. + if self.gen_lite: + project_name = 'RECONFIGURE' + ofname = os.path.join(self.environment.get_build_dir(), 'RECONFIGURE.vcxproj') + conftype = 'Makefile' + # I find the REGEN project doesn't work; it fails to invoke the appropriate - + # python meson.py --internal regencheck builddir\meson-private + # command, despite the fact that manually running such a command in a shell runs just fine. + # Running/building the regen project produces the error - + # ...Microsoft.CppBuild.targets(460,5): error MSB8020: The build tools for ClangCL (Platform Toolset = 'ClangCL') cannot be found. To build using the ClangCL build tools, please install ... + # Not sure why but a simple makefile-style project that executes the full '...regencheck...' command actually works (and seems a little simpler). + # Although I've limited this change to only happen under '--genvslite', perhaps ... + # FIXME : Should all utility projects use the simpler and less problematic makefile-style project? + else: + project_name = 'REGEN' + ofname = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') + conftype = 'Utility' + + guid = self.environment.coredata.regen_guid + (root, type_config) = self.create_basic_project(project_name, + temp_dir='regen-temp', + guid=guid, + conftype=conftype + ) + + if self.gen_lite: + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + all_configs_prop_group = ET.SubElement(root, 'PropertyGroup') + + # Multi-line command to reconfigure all buildtype-suffixed build dirs + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + (_, build_dir_tail) = os.path.split(self.src_to_build) + proj_to_multiconfigured_builds_parent_dir = '..' # We know this RECONFIGURE.vcxproj will always be in the '[buildir]_vs' dir. + proj_to_src_dir = self.build_to_src + reconfigure_all_cmd = '' + for buildtype in multi_config_buildtype_list: + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + reconfigure_all_cmd += f'{nmake_base_meson_command} setup --reconfigure "{proj_to_build_dir_for_buildtype}" "{proj_to_src_dir}"\n' + ET.SubElement(all_configs_prop_group, 'NMakeBuildCommandLine').text = reconfigure_all_cmd + ET.SubElement(all_configs_prop_group, 'NMakeReBuildCommandLine').text = reconfigure_all_cmd + ET.SubElement(all_configs_prop_group, 'NMakeCleanCommandLine').text = '' + + #Need to set the 'ExecutablePath' element for the above NMake... commands to be able to execute + ET.SubElement(all_configs_prop_group, 'ExecutablePath').text = exe_search_paths + else: + action = ET.SubElement(root, 'ItemDefinitionGroup') + midl = ET.SubElement(action, 'Midl') + ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' + ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' + ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' + ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' + ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' + ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' + regen_command = self.environment.get_build_command() + ['--internal', 'regencheck'] + cmd_templ = '''call %s > NUL +"%s" "%s"''' + regen_command = cmd_templ % \ + (self.get_vcvars_command(), '" "'.join(regen_command), self.environment.get_scratch_dir()) + self.add_custom_build(root, 'regen', regen_command, deps=self.get_regen_filelist(), + outputs=[Vs2010Backend.get_regen_stampfile(self.environment.get_build_dir())], + msg='Checking whether solution needs to be regenerated.') + + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + ET.SubElement(root, 'ImportGroup', Label='ExtensionTargets') + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + + def gen_testproj(self): + project_name = 'RUN_TESTS' + ofname = os.path.join(self.environment.get_build_dir(), f'{project_name}.vcxproj') + guid = self.environment.coredata.test_guid + if self.gen_lite: + (root, type_config) = self.create_basic_project(project_name, + temp_dir='install-temp', + guid=guid, + conftype='Makefile' + ) + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + (_, build_dir_tail) = os.path.split(self.src_to_build) + proj_to_multiconfigured_builds_parent_dir = '..' # We know this .vcxproj will always be in the '[buildir]_vs' dir. + # Add appropriate 'test' commands for the 'build' action of this project, for all buildtypes + for buildtype in multi_config_buildtype_list: + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + test_cmd = f'{nmake_base_meson_command} test -C "{proj_to_build_dir_for_buildtype}" --no-rebuild' + if not self.environment.coredata.get_option(OptionKey('stdsplit')): + test_cmd += ' --no-stdsplit' + if self.environment.coredata.get_option(OptionKey('errorlogs')): + test_cmd += ' --print-errorlogs' + condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\'' + prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition) + ET.SubElement(prop_group, 'NMakeBuildCommandLine').text = test_cmd + #Need to set the 'ExecutablePath' element for the NMake... commands to be able to execute + ET.SubElement(prop_group, 'ExecutablePath').text = exe_search_paths + else: + (root, type_config) = self.create_basic_project(project_name, + temp_dir='test-temp', + guid=guid) + + action = ET.SubElement(root, 'ItemDefinitionGroup') + midl = ET.SubElement(action, 'Midl') + ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' + ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' + ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' + ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' + ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' + ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' + # FIXME: No benchmarks? + test_command = self.environment.get_build_command() + ['test', '--no-rebuild'] + if not self.environment.coredata.get_option(OptionKey('stdsplit')): + test_command += ['--no-stdsplit'] + if self.environment.coredata.get_option(OptionKey('errorlogs')): + test_command += ['--print-errorlogs'] + self.serialize_tests() + self.add_custom_build(root, 'run_tests', '"%s"' % ('" "'.join(test_command))) + + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + + def gen_installproj(self): + project_name = 'RUN_INSTALL' + ofname = os.path.join(self.environment.get_build_dir(), f'{project_name}.vcxproj') + guid = self.environment.coredata.install_guid + if self.gen_lite: + (root, type_config) = self.create_basic_project(project_name, + temp_dir='install-temp', + guid=guid, + conftype='Makefile' + ) + (nmake_base_meson_command, exe_search_paths) = Vs2010Backend.get_nmake_base_meson_command_and_exe_search_paths() + multi_config_buildtype_list = coredata.get_genvs_default_buildtype_list() + (_, build_dir_tail) = os.path.split(self.src_to_build) + proj_to_multiconfigured_builds_parent_dir = '..' # We know this .vcxproj will always be in the '[buildir]_vs' dir. + # Add appropriate 'install' commands for the 'build' action of this project, for all buildtypes + for buildtype in multi_config_buildtype_list: + meson_build_dir_for_buildtype = build_dir_tail[:-2] + buildtype # Get the buildtype suffixed 'builddir_[debug/release/etc]' from 'builddir_vs', for example. + proj_to_build_dir_for_buildtype = str(os.path.join(proj_to_multiconfigured_builds_parent_dir, meson_build_dir_for_buildtype)) + install_cmd = f'{nmake_base_meson_command} install -C "{proj_to_build_dir_for_buildtype}" --no-rebuild' + condition = f'\'$(Configuration)|$(Platform)\'==\'{buildtype}|{self.platform}\'' + prop_group = ET.SubElement(root, 'PropertyGroup', Condition=condition) + ET.SubElement(prop_group, 'NMakeBuildCommandLine').text = install_cmd + #Need to set the 'ExecutablePath' element for the NMake... commands to be able to execute + ET.SubElement(prop_group, 'ExecutablePath').text = exe_search_paths + else: + self.create_install_data_files() + + (root, type_config) = self.create_basic_project(project_name, + temp_dir='install-temp', + guid=guid) + + action = ET.SubElement(root, 'ItemDefinitionGroup') + midl = ET.SubElement(action, 'Midl') + ET.SubElement(midl, "AdditionalIncludeDirectories").text = '%(AdditionalIncludeDirectories)' + ET.SubElement(midl, "OutputDirectory").text = '$(IntDir)' + ET.SubElement(midl, 'HeaderFileName').text = '%(Filename).h' + ET.SubElement(midl, 'TypeLibraryName').text = '%(Filename).tlb' + ET.SubElement(midl, 'InterfaceIdentifierFilename').text = '%(Filename)_i.c' + ET.SubElement(midl, 'ProxyFileName').text = '%(Filename)_p.c' + install_command = self.environment.get_build_command() + ['install', '--no-rebuild'] + self.add_custom_build(root, 'run_install', '"%s"' % ('" "'.join(install_command))) + + ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') + self.add_regen_dependency(root) + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + + def add_custom_build(self, node: ET.Element, rulename: str, command: str, deps: T.Optional[T.List[str]] = None, + outputs: T.Optional[T.List[str]] = None, msg: T.Optional[str] = None, verify_files: bool = True) -> None: + igroup = ET.SubElement(node, 'ItemGroup') + rulefile = os.path.join(self.environment.get_scratch_dir(), rulename + '.rule') + if not os.path.exists(rulefile): + with open(rulefile, 'w', encoding='utf-8') as f: + f.write("# Meson regen file.") + custombuild = ET.SubElement(igroup, 'CustomBuild', Include=rulefile) + if msg: + message = ET.SubElement(custombuild, 'Message') + message.text = msg + if not verify_files: + ET.SubElement(custombuild, 'VerifyInputsAndOutputsExist').text = 'false' + + # If a command ever were to change the current directory or set local + # variables this would need to be more complicated, as msbuild by + # default executes all CustomBuilds in a project using the same + # shell. Right now such tasks are all done inside the meson_exe + # wrapper. The trailing newline appears to be necessary to allow + # parallel custom builds to work. + ET.SubElement(custombuild, 'Command').text = f"{command}\n" + + if not outputs: + # Use a nonexistent file to always consider the target out-of-date. + outputs = [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(), + 'outofdate.file'))] + ET.SubElement(custombuild, 'Outputs').text = ';'.join(outputs) + if deps: + ET.SubElement(custombuild, 'AdditionalInputs').text = ';'.join(deps) + + @staticmethod + def nonexistent_file(prefix: str) -> str: + i = 0 + file = prefix + while os.path.exists(file): + file = '%s%d' % (prefix, i) + return file + + def generate_debug_information(self, link: ET.Element) -> None: + # valid values for vs2015 is 'false', 'true', 'DebugFastLink' + ET.SubElement(link, 'GenerateDebugInformation').text = 'true' + + def add_regen_dependency(self, root: ET.Element) -> None: + # For now, with 'genvslite' solutions, REGEN is replaced by the lighter-weight RECONFIGURE utility that is + # no longer a forced build dependency. See comment in 'gen_regenproj' + if not self.gen_lite: + regen_vcxproj = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') + self.add_project_reference(root, regen_vcxproj, self.environment.coredata.regen_guid) + + def generate_lang_standard_info(self, file_args: T.Dict[str, CompilerArgs], clconf: ET.Element) -> None: + pass diff --git a/devtools/meson/mesonbuild/backend/vs2012backend.py b/devtools/meson/mesonbuild/backend/vs2012backend.py new file mode 100644 index 0000000..76e5c40 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2012backend.py @@ -0,0 +1,45 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import typing as T + +from .vs2010backend import Vs2010Backend +from ..mesonlib import MesonException + +if T.TYPE_CHECKING: + from ..build import Build + from ..interpreter import Interpreter + +class Vs2012Backend(Vs2010Backend): + + name = 'vs2012' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.vs_version = '2012' + self.sln_file_version = '12.00' + self.sln_version_comment = '2012' + if self.environment is not None: + # TODO: we assume host == build + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + else: + # We don't have support for versions older than 2019 right now. + raise MesonException('There is currently no support for ICL before 19, patches welcome.') + if self.platform_toolset is None: + self.platform_toolset = 'v110' diff --git a/devtools/meson/mesonbuild/backend/vs2013backend.py b/devtools/meson/mesonbuild/backend/vs2013backend.py new file mode 100644 index 0000000..1fbde46 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2013backend.py @@ -0,0 +1,44 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .vs2010backend import Vs2010Backend +from ..mesonlib import MesonException +import typing as T + +if T.TYPE_CHECKING: + from ..build import Build + from ..interpreter import Interpreter + +class Vs2013Backend(Vs2010Backend): + + name = 'vs2013' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.vs_version = '2013' + self.sln_file_version = '12.00' + self.sln_version_comment = '2013' + if self.environment is not None: + # TODO: we assume host == build + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + else: + # We don't have support for versions older than 2019 right now. + raise MesonException('There is currently no support for ICL before 19, patches welcome.') + if self.platform_toolset is None: + self.platform_toolset = 'v120' diff --git a/devtools/meson/mesonbuild/backend/vs2015backend.py b/devtools/meson/mesonbuild/backend/vs2015backend.py new file mode 100644 index 0000000..8e4da36 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2015backend.py @@ -0,0 +1,45 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import typing as T + +from .vs2010backend import Vs2010Backend +from ..mesonlib import MesonException + +if T.TYPE_CHECKING: + from ..build import Build + from ..interpreter import Interpreter + +class Vs2015Backend(Vs2010Backend): + + name = 'vs2015' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.vs_version = '2015' + self.sln_file_version = '12.00' + self.sln_version_comment = '14' + if self.environment is not None: + # TODO: we assume host == build + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + else: + # We don't have support for versions older than 2019 right now. + raise MesonException('There is currently no support for ICL before 19, patches welcome.') + if self.platform_toolset is None: + self.platform_toolset = 'v140' diff --git a/devtools/meson/mesonbuild/backend/vs2017backend.py b/devtools/meson/mesonbuild/backend/vs2017backend.py new file mode 100644 index 0000000..375d660 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2017backend.py @@ -0,0 +1,69 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import typing as T +import xml.etree.ElementTree as ET + +from .vs2010backend import Vs2010Backend +from ..mesonlib import MesonException + +if T.TYPE_CHECKING: + from ..build import Build + from ..interpreter import Interpreter + + +class Vs2017Backend(Vs2010Backend): + + name = 'vs2017' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.vs_version = '2017' + self.sln_file_version = '12.00' + self.sln_version_comment = '15' + # We assume that host == build + if self.environment is not None: + comps = self.environment.coredata.compilers.host + if comps: + if comps and all(c.id == 'clang-cl' for c in comps.values()): + self.platform_toolset = 'llvm' + elif comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + else: + # We don't have support for versions older than 2019 right now. + raise MesonException('There is currently no support for ICL before 19, patches welcome.') + if self.platform_toolset is None: + self.platform_toolset = 'v141' + # WindowsSDKVersion should be set by command prompt. + sdk_version = os.environ.get('WindowsSDKVersion', None) + if sdk_version: + self.windows_target_platform_version = sdk_version.rstrip('\\') + + def generate_debug_information(self, link): + # valid values for vs2017 is 'false', 'true', 'DebugFastLink', 'DebugFull' + ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' + + def generate_lang_standard_info(self, file_args, clconf): + if 'cpp' in file_args: + optargs = [x for x in file_args['cpp'] if x.startswith('/std:c++')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard').text = optargs[0].replace("/std:c++", "stdcpp") + if 'c' in file_args: + optargs = [x for x in file_args['c'] if x.startswith('/std:c')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard_C').text = optargs[0].replace("/std:c", "stdc") diff --git a/devtools/meson/mesonbuild/backend/vs2019backend.py b/devtools/meson/mesonbuild/backend/vs2019backend.py new file mode 100644 index 0000000..f01f7ec --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2019backend.py @@ -0,0 +1,64 @@ +# Copyright 2014-2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import typing as T +import xml.etree.ElementTree as ET + +from .vs2010backend import Vs2010Backend + +if T.TYPE_CHECKING: + from ..build import Build + from ..interpreter import Interpreter + + +class Vs2019Backend(Vs2010Backend): + + name = 'vs2019' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.sln_file_version = '12.00' + self.sln_version_comment = 'Version 16' + if self.environment is not None: + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'clang-cl' for c in comps.values()): + self.platform_toolset = 'ClangCL' + elif comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + # We don't have support for versions older than 2019 right now. + if not self.platform_toolset: + self.platform_toolset = 'v142' + self.vs_version = '2019' + # WindowsSDKVersion should be set by command prompt. + sdk_version = os.environ.get('WindowsSDKVersion', None) + if sdk_version: + self.windows_target_platform_version = sdk_version.rstrip('\\') + + def generate_debug_information(self, link): + # valid values for vs2019 is 'false', 'true', 'DebugFastLink', 'DebugFull' + ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' + + def generate_lang_standard_info(self, file_args, clconf): + if 'cpp' in file_args: + optargs = [x for x in file_args['cpp'] if x.startswith('/std:c++')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard').text = optargs[0].replace("/std:c++", "stdcpp") + if 'c' in file_args: + optargs = [x for x in file_args['c'] if x.startswith('/std:c')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard_C').text = optargs[0].replace("/std:c", "stdc") diff --git a/devtools/meson/mesonbuild/backend/vs2022backend.py b/devtools/meson/mesonbuild/backend/vs2022backend.py new file mode 100644 index 0000000..ea715d8 --- /dev/null +++ b/devtools/meson/mesonbuild/backend/vs2022backend.py @@ -0,0 +1,64 @@ +# Copyright 2014-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import typing as T +import xml.etree.ElementTree as ET + +from .vs2010backend import Vs2010Backend + +if T.TYPE_CHECKING: + from ..build import Build + from ..interpreter import Interpreter + + +class Vs2022Backend(Vs2010Backend): + + name = 'vs2022' + + def __init__(self, build: T.Optional[Build], interpreter: T.Optional[Interpreter], gen_lite: bool = False): + super().__init__(build, interpreter, gen_lite=gen_lite) + self.sln_file_version = '12.00' + self.sln_version_comment = 'Version 17' + if self.environment is not None: + comps = self.environment.coredata.compilers.host + if comps and all(c.id == 'clang-cl' for c in comps.values()): + self.platform_toolset = 'ClangCL' + elif comps and all(c.id == 'intel-cl' for c in comps.values()): + c = list(comps.values())[0] + if c.version.startswith('19'): + self.platform_toolset = 'Intel C++ Compiler 19.0' + # We don't have support for versions older than 2022 right now. + if not self.platform_toolset: + self.platform_toolset = 'v143' + self.vs_version = '2022' + # WindowsSDKVersion should be set by command prompt. + sdk_version = os.environ.get('WindowsSDKVersion', None) + if sdk_version: + self.windows_target_platform_version = sdk_version.rstrip('\\') + + def generate_debug_information(self, link): + # valid values for vs2022 is 'false', 'true', 'DebugFastLink', 'DebugFull' + ET.SubElement(link, 'GenerateDebugInformation').text = 'DebugFull' + + def generate_lang_standard_info(self, file_args, clconf): + if 'cpp' in file_args: + optargs = [x for x in file_args['cpp'] if x.startswith('/std:c++')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard').text = optargs[0].replace("/std:c++", "stdcpp") + if 'c' in file_args: + optargs = [x for x in file_args['c'] if x.startswith('/std:c')] + if optargs: + ET.SubElement(clconf, 'LanguageStandard_C').text = optargs[0].replace("/std:c", "stdc") diff --git a/devtools/meson/mesonbuild/backend/xcodebackend.py b/devtools/meson/mesonbuild/backend/xcodebackend.py new file mode 100644 index 0000000..bc4ba0b --- /dev/null +++ b/devtools/meson/mesonbuild/backend/xcodebackend.py @@ -0,0 +1,1718 @@ +# Copyright 2014-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import uuid, os, operator +import typing as T + +from . import backends +from .. import build +from .. import dependencies +from .. import mesonlib +from .. import mlog +from ..mesonlib import MesonBugException, MesonException, OptionKey + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + +INDENT = '\t' +XCODETYPEMAP = {'c': 'sourcecode.c.c', + 'a': 'archive.ar', + 'cc': 'sourcecode.cpp.cpp', + 'cxx': 'sourcecode.cpp.cpp', + 'cpp': 'sourcecode.cpp.cpp', + 'c++': 'sourcecode.cpp.cpp', + 'm': 'sourcecode.c.objc', + 'mm': 'sourcecode.cpp.objcpp', + 'h': 'sourcecode.c.h', + 'hpp': 'sourcecode.cpp.h', + 'hxx': 'sourcecode.cpp.h', + 'hh': 'sourcecode.cpp.hh', + 'inc': 'sourcecode.c.h', + 'swift': 'sourcecode.swift', + 'dylib': 'compiled.mach-o.dylib', + 'o': 'compiled.mach-o.objfile', + 's': 'sourcecode.asm', + 'asm': 'sourcecode.asm', + } +LANGNAMEMAP = {'c': 'C', + 'cpp': 'CPLUSPLUS', + 'objc': 'OBJC', + 'objcpp': 'OBJCPLUSPLUS', + 'swift': 'SWIFT_' + } +OPT2XCODEOPT = {'plain': None, + '0': '0', + 'g': '0', + '1': '1', + '2': '2', + '3': '3', + 's': 's', + } +BOOL2XCODEBOOL = {True: 'YES', False: 'NO'} +LINKABLE_EXTENSIONS = {'.o', '.a', '.obj', '.so', '.dylib'} + +class FileTreeEntry: + + def __init__(self) -> None: + self.subdirs = {} + self.targets = [] + +class PbxArray: + def __init__(self) -> None: + self.items = [] + + def add_item(self, item: T.Union[PbxArrayItem, str], comment: str = '') -> None: + if isinstance(item, PbxArrayItem): + self.items.append(item) + else: + self.items.append(PbxArrayItem(item, comment)) + + def write(self, ofile: T.TextIO, indent_level: int) -> None: + ofile.write('(\n') + indent_level += 1 + for i in self.items: + if i.comment: + ofile.write(indent_level*INDENT + f'{i.value} {i.comment},\n') + else: + ofile.write(indent_level*INDENT + f'{i.value},\n') + indent_level -= 1 + ofile.write(indent_level*INDENT + ');\n') + +class PbxArrayItem: + def __init__(self, value: str, comment: str = ''): + self.value = value + if comment: + if '/*' in comment: + self.comment = comment + else: + self.comment = f'/* {comment} */' + else: + self.comment = comment + +class PbxComment: + def __init__(self, text: str): + assert isinstance(text, str) + assert '/*' not in text + self.text = f'/* {text} */' + + def write(self, ofile: T.TextIO, indent_level: int) -> None: + ofile.write(f'\n{self.text}\n') + +class PbxDictItem: + def __init__(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = ''): + self.key = key + self.value = value + if comment: + if '/*' in comment: + self.comment = comment + else: + self.comment = f'/* {comment} */' + else: + self.comment = comment + +class PbxDict: + def __init__(self) -> None: + # This class is a bit weird, because we want to write PBX dicts in + # defined order _and_ we want to write intermediate comments also in order. + self.keys = set() + self.items = [] + + def add_item(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = '') -> None: + assert key not in self.keys + item = PbxDictItem(key, value, comment) + self.keys.add(key) + self.items.append(item) + + def has_item(self, key): + return key in self.keys + + def add_comment(self, comment: PbxComment) -> None: + assert isinstance(comment, PbxComment) + self.items.append(comment) + + def write(self, ofile: T.TextIO, indent_level: int) -> None: + ofile.write('{\n') + indent_level += 1 + for i in self.items: + if isinstance(i, PbxComment): + i.write(ofile, indent_level) + elif isinstance(i, PbxDictItem): + if isinstance(i.value, (str, int)): + if i.comment: + ofile.write(indent_level*INDENT + f'{i.key} = {i.value} {i.comment};\n') + else: + ofile.write(indent_level*INDENT + f'{i.key} = {i.value};\n') + elif isinstance(i.value, PbxDict): + if i.comment: + ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ') + else: + ofile.write(indent_level*INDENT + f'{i.key} = ') + i.value.write(ofile, indent_level) + elif isinstance(i.value, PbxArray): + if i.comment: + ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ') + else: + ofile.write(indent_level*INDENT + f'{i.key} = ') + i.value.write(ofile, indent_level) + else: + print(i) + print(i.key) + print(i.value) + raise RuntimeError('missing code') + else: + print(i) + raise RuntimeError('missing code2') + + indent_level -= 1 + ofile.write(indent_level*INDENT + '}') + if indent_level == 0: + ofile.write('\n') + else: + ofile.write(';\n') + +class XCodeBackend(backends.Backend): + + name = 'xcode' + + def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]): + super().__init__(build, interpreter) + self.project_uid = self.environment.coredata.lang_guids['default'].replace('-', '')[:24] + self.buildtype = T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype'))) + self.project_conflist = self.gen_id() + self.maingroup_id = self.gen_id() + self.all_id = self.gen_id() + self.all_buildconf_id = self.gen_id() + self.buildtypes = [self.buildtype] + self.test_id = self.gen_id() + self.test_command_id = self.gen_id() + self.test_buildconf_id = self.gen_id() + self.regen_id = self.gen_id() + self.regen_command_id = self.gen_id() + self.regen_buildconf_id = self.gen_id() + self.regen_dependency_id = self.gen_id() + self.top_level_dict = PbxDict() + self.generator_outputs = {} + # In Xcode files are not accessed via their file names, but rather every one of them + # gets an unique id. More precisely they get one unique id per target they are used + # in. If you generate only one id per file and use them, compilation will work but the + # UI will only show the file in one target but not the others. Thus they key is + # a tuple containing the target and filename. + self.buildfile_ids = {} + # That is not enough, though. Each target/file combination also gets a unique id + # in the file reference section. Because why not. This means that a source file + # that is used in two targets gets a total of four unique ID numbers. + self.fileref_ids = {} + + def write_pbxfile(self, top_level_dict, ofilename): + tmpname = ofilename + '.tmp' + with open(tmpname, 'w', encoding='utf-8') as ofile: + ofile.write('// !$*UTF8*$!\n') + top_level_dict.write(ofile, 0) + os.replace(tmpname, ofilename) + + def gen_id(self) -> str: + return str(uuid.uuid4()).upper().replace('-', '')[:24] + + def get_target_dir(self, target): + dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype')))) + #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) + return dirname + + def get_custom_target_output_dir(self, target): + dirname = target.get_subdir() + os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) + return dirname + + def target_to_build_root(self, target): + if self.get_target_dir(target) == '': + return '' + directories = os.path.normpath(self.get_target_dir(target)).split(os.sep) + return os.sep.join(['..'] * len(directories)) + + def object_filename_from_source(self, target, source): + # Xcode has the following naming scheme: + # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o + project = self.build.project_name + buildtype = self.buildtype + tname = target.get_id() + arch = 'x86_64' + if isinstance(source, mesonlib.File): + source = source.fname + stem = os.path.splitext(os.path.basename(source))[0] + obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{arch}/{stem}.o' + return obj_path + + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + # Check for (currently) unexpected capture arg use cases - + if capture: + raise MesonBugException('We do not expect the xcode backend to generate with \'capture = True\'') + if vslite_ctx: + raise MesonBugException('We do not expect the xcode backend to be given a valid \'vslite_ctx\'') + self.serialize_tests() + # Cache the result as the method rebuilds the array every time it is called. + self.build_targets = self.build.get_build_targets() + self.custom_targets = self.build.get_custom_targets() + self.generate_filemap() + self.generate_buildstylemap() + self.generate_build_phase_map() + self.generate_build_configuration_map() + self.generate_build_configurationlist_map() + self.generate_project_configurations_map() + self.generate_buildall_configurations_map() + self.generate_test_configurations_map() + self.generate_native_target_map() + self.generate_native_frameworks_map() + self.generate_custom_target_map() + self.generate_generator_target_map() + self.generate_source_phase_map() + self.generate_target_dependency_map() + self.generate_pbxdep_map() + self.generate_containerproxy_map() + self.generate_target_file_maps() + self.generate_build_file_maps() + self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj') + os.makedirs(self.proj_dir, exist_ok=True) + self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj') + objects_dict = self.generate_prefix(self.top_level_dict) + objects_dict.add_comment(PbxComment('Begin PBXAggregateTarget section')) + self.generate_pbx_aggregate_target(objects_dict) + objects_dict.add_comment(PbxComment('End PBXAggregateTarget section')) + objects_dict.add_comment(PbxComment('Begin PBXBuildFile section')) + self.generate_pbx_build_file(objects_dict) + objects_dict.add_comment(PbxComment('End PBXBuildFile section')) + objects_dict.add_comment(PbxComment('Begin PBXBuildStyle section')) + self.generate_pbx_build_style(objects_dict) + objects_dict.add_comment(PbxComment('End PBXBuildStyle section')) + objects_dict.add_comment(PbxComment('Begin PBXContainerItemProxy section')) + self.generate_pbx_container_item_proxy(objects_dict) + objects_dict.add_comment(PbxComment('End PBXContainerItemProxy section')) + objects_dict.add_comment(PbxComment('Begin PBXFileReference section')) + self.generate_pbx_file_reference(objects_dict) + objects_dict.add_comment(PbxComment('End PBXFileReference section')) + objects_dict.add_comment(PbxComment('Begin PBXFrameworksBuildPhase section')) + self.generate_pbx_frameworks_buildphase(objects_dict) + objects_dict.add_comment(PbxComment('End PBXFrameworksBuildPhase section')) + objects_dict.add_comment(PbxComment('Begin PBXGroup section')) + self.generate_pbx_group(objects_dict) + objects_dict.add_comment(PbxComment('End PBXGroup section')) + objects_dict.add_comment(PbxComment('Begin PBXNativeTarget section')) + self.generate_pbx_native_target(objects_dict) + objects_dict.add_comment(PbxComment('End PBXNativeTarget section')) + objects_dict.add_comment(PbxComment('Begin PBXProject section')) + self.generate_pbx_project(objects_dict) + objects_dict.add_comment(PbxComment('End PBXProject section')) + objects_dict.add_comment(PbxComment('Begin PBXShellScriptBuildPhase section')) + self.generate_pbx_shell_build_phase(objects_dict) + objects_dict.add_comment(PbxComment('End PBXShellScriptBuildPhase section')) + objects_dict.add_comment(PbxComment('Begin PBXSourcesBuildPhase section')) + self.generate_pbx_sources_build_phase(objects_dict) + objects_dict.add_comment(PbxComment('End PBXSourcesBuildPhase section')) + objects_dict.add_comment(PbxComment('Begin PBXTargetDependency section')) + self.generate_pbx_target_dependency(objects_dict) + objects_dict.add_comment(PbxComment('End PBXTargetDependency section')) + objects_dict.add_comment(PbxComment('Begin XCBuildConfiguration section')) + self.generate_xc_build_configuration(objects_dict) + objects_dict.add_comment(PbxComment('End XCBuildConfiguration section')) + objects_dict.add_comment(PbxComment('Begin XCConfigurationList section')) + self.generate_xc_configurationList(objects_dict) + objects_dict.add_comment(PbxComment('End XCConfigurationList section')) + self.generate_suffix(self.top_level_dict) + self.write_pbxfile(self.top_level_dict, self.proj_file) + self.generate_regen_info() + + def get_xcodetype(self, fname): + extension = fname.split('.')[-1] + if extension == 'C': + extension = 'cpp' + xcodetype = XCODETYPEMAP.get(extension.lower()) + if not xcodetype: + xcodetype = 'sourcecode.unknown' + return xcodetype + + def generate_filemap(self) -> None: + self.filemap = {} # Key is source file relative to src root. + self.target_filemap = {} + for name, t in self.build_targets.items(): + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + self.filemap[s] = self.gen_id() + for o in t.objects: + if isinstance(o, str): + o = os.path.join(t.subdir, o) + self.filemap[o] = self.gen_id() + self.target_filemap[name] = self.gen_id() + + def generate_buildstylemap(self) -> None: + self.buildstylemap = {self.buildtype: self.gen_id()} + + def generate_build_phase_map(self) -> None: + for tname, t in self.build_targets.items(): + # generate id for our own target-name + t.buildphasemap = {} + t.buildphasemap[tname] = self.gen_id() + # each target can have it's own Frameworks/Sources/..., generate id's for those + t.buildphasemap['Frameworks'] = self.gen_id() + t.buildphasemap['Resources'] = self.gen_id() + t.buildphasemap['Sources'] = self.gen_id() + + def generate_build_configuration_map(self) -> None: + self.buildconfmap = {} + for t in self.build_targets: + bconfs = {self.buildtype: self.gen_id()} + self.buildconfmap[t] = bconfs + for t in self.custom_targets: + bconfs = {self.buildtype: self.gen_id()} + self.buildconfmap[t] = bconfs + + def generate_project_configurations_map(self) -> None: + self.project_configurations = {self.buildtype: self.gen_id()} + + def generate_buildall_configurations_map(self) -> None: + self.buildall_configurations = {self.buildtype: self.gen_id()} + + def generate_test_configurations_map(self) -> None: + self.test_configurations = {self.buildtype: self.gen_id()} + + def generate_build_configurationlist_map(self) -> None: + self.buildconflistmap = {} + for t in self.build_targets: + self.buildconflistmap[t] = self.gen_id() + for t in self.custom_targets: + self.buildconflistmap[t] = self.gen_id() + + def generate_native_target_map(self) -> None: + self.native_targets = {} + for t in self.build_targets: + self.native_targets[t] = self.gen_id() + + def generate_custom_target_map(self) -> None: + self.shell_targets = {} + self.custom_target_output_buildfile = {} + self.custom_target_output_fileref = {} + for tname, t in self.custom_targets.items(): + self.shell_targets[tname] = self.gen_id() + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t) + for o in ofilenames: + self.custom_target_output_buildfile[o] = self.gen_id() + self.custom_target_output_fileref[o] = self.gen_id() + + def generate_generator_target_map(self) -> None: + # Generator objects do not have natural unique ids + # so use a counter. + self.generator_fileref_ids = {} + self.generator_buildfile_ids = {} + for tname, t in self.build_targets.items(): + generator_id = 0 + for genlist in t.generated: + if not isinstance(genlist, build.GeneratedList): + continue + self.gen_single_target_map(genlist, tname, t, generator_id) + generator_id += 1 + # FIXME add outputs. + for tname, t in self.custom_targets.items(): + generator_id = 0 + for genlist in t.sources: + if not isinstance(genlist, build.GeneratedList): + continue + self.gen_single_target_map(genlist, tname, t, generator_id) + generator_id += 1 + + def gen_single_target_map(self, genlist, tname, t, generator_id): + k = (tname, generator_id) + assert k not in self.shell_targets + self.shell_targets[k] = self.gen_id() + ofile_abs = [] + for i in genlist.get_inputs(): + for o_base in genlist.get_outputs_for(i): + o = os.path.join(self.get_target_private_dir(t), o_base) + ofile_abs.append(os.path.join(self.environment.get_build_dir(), o)) + assert k not in self.generator_outputs + self.generator_outputs[k] = ofile_abs + buildfile_ids = [] + fileref_ids = [] + for i in range(len(ofile_abs)): + buildfile_ids.append(self.gen_id()) + fileref_ids.append(self.gen_id()) + self.generator_buildfile_ids[k] = buildfile_ids + self.generator_fileref_ids[k] = fileref_ids + + def generate_native_frameworks_map(self) -> None: + self.native_frameworks = {} + self.native_frameworks_fileref = {} + for t in self.build_targets.values(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + self.native_frameworks[f] = self.gen_id() + self.native_frameworks_fileref[f] = self.gen_id() + + def generate_target_dependency_map(self) -> None: + self.target_dependency_map = {} + for tname, t in self.build_targets.items(): + for target in t.link_targets: + if isinstance(target, build.CustomTargetIndex): + k = (tname, target.target.get_basename()) + if k in self.target_dependency_map: + continue + else: + k = (tname, target.get_basename()) + assert k not in self.target_dependency_map + self.target_dependency_map[k] = self.gen_id() + for tname, t in self.custom_targets.items(): + k = tname + assert k not in self.target_dependency_map + self.target_dependency_map[k] = self.gen_id() + + def generate_pbxdep_map(self) -> None: + self.pbx_dep_map = {} + self.pbx_custom_dep_map = {} + for t in self.build_targets: + self.pbx_dep_map[t] = self.gen_id() + for t in self.custom_targets: + self.pbx_custom_dep_map[t] = self.gen_id() + + def generate_containerproxy_map(self) -> None: + self.containerproxy_map = {} + for t in self.build_targets: + self.containerproxy_map[t] = self.gen_id() + + def generate_target_file_maps(self) -> None: + self.generate_target_file_maps_impl(self.build_targets) + self.generate_target_file_maps_impl(self.custom_targets) + + def generate_target_file_maps_impl(self, targets): + for tname, t in targets.items(): + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + if not isinstance(s, str): + continue + k = (tname, s) + assert k not in self.buildfile_ids + self.buildfile_ids[k] = self.gen_id() + assert k not in self.fileref_ids + self.fileref_ids[k] = self.gen_id() + if not hasattr(t, 'objects'): + continue + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Extracted objects do not live in "the Xcode world". + continue + if isinstance(o, mesonlib.File): + o = os.path.join(o.subdir, o.fname) + if isinstance(o, str): + o = os.path.join(t.subdir, o) + k = (tname, o) + assert k not in self.buildfile_ids + self.buildfile_ids[k] = self.gen_id() + assert k not in self.fileref_ids + self.fileref_ids[k] = self.gen_id() + else: + raise RuntimeError('Unknown input type ' + str(o)) + + def generate_build_file_maps(self) -> None: + for buildfile in self.interpreter.get_build_def_files(): + assert isinstance(buildfile, str) + self.buildfile_ids[buildfile] = self.gen_id() + self.fileref_ids[buildfile] = self.gen_id() + + def generate_source_phase_map(self) -> None: + self.source_phase = {} + for t in self.build_targets: + self.source_phase[t] = self.gen_id() + + def generate_pbx_aggregate_target(self, objects_dict): + self.custom_aggregate_targets = {} + self.build_all_tdep_id = self.gen_id() + # FIXME: filter out targets that are not built by default. + target_dependencies = [self.pbx_dep_map[t] for t in self.build_targets] + custom_target_dependencies = [self.pbx_custom_dep_map[t] for t in self.custom_targets] + aggregated_targets = [] + aggregated_targets.append((self.all_id, 'ALL_BUILD', + self.all_buildconf_id, + [], + [self.regen_dependency_id] + target_dependencies + custom_target_dependencies)) + aggregated_targets.append((self.test_id, + 'RUN_TESTS', + self.test_buildconf_id, + [self.test_command_id], + [self.regen_dependency_id, self.build_all_tdep_id])) + aggregated_targets.append((self.regen_id, + 'REGENERATE', + self.regen_buildconf_id, + [self.regen_command_id], + [])) + for tname, t in self.build.get_custom_targets().items(): + ct_id = self.gen_id() + self.custom_aggregate_targets[tname] = ct_id + build_phases = [] + dependencies = [self.regen_dependency_id] + generator_id = 0 + for s in t.sources: + if not isinstance(s, build.GeneratedList): + continue + build_phases.append(self.shell_targets[(tname, generator_id)]) + for d in s.depends: + dependencies.append(self.pbx_custom_dep_map[d.get_id()]) + generator_id += 1 + build_phases.append(self.shell_targets[tname]) + aggregated_targets.append((ct_id, tname, self.buildconflistmap[tname], build_phases, dependencies)) + + # Sort objects by ID before writing + sorted_aggregated_targets = sorted(aggregated_targets, key=operator.itemgetter(0)) + for t in sorted_aggregated_targets: + agt_dict = PbxDict() + name = t[1] + buildconf_id = t[2] + build_phases = t[3] + dependencies = t[4] + agt_dict.add_item('isa', 'PBXAggregateTarget') + agt_dict.add_item('buildConfigurationList', buildconf_id, f'Build configuration list for PBXAggregateTarget "{name}"') + bp_arr = PbxArray() + agt_dict.add_item('buildPhases', bp_arr) + for bp in build_phases: + bp_arr.add_item(bp, 'ShellScript') + dep_arr = PbxArray() + agt_dict.add_item('dependencies', dep_arr) + for td in dependencies: + dep_arr.add_item(td, 'PBXTargetDependency') + agt_dict.add_item('name', f'"{name}"') + agt_dict.add_item('productName', f'"{name}"') + objects_dict.add_item(t[0], agt_dict, name) + + def generate_pbx_build_file(self, objects_dict): + for tname, t in self.build_targets.items(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + fw_dict = PbxDict() + fwkey = self.native_frameworks[f] + if fwkey not in objects_dict.keys: + objects_dict.add_item(fwkey, fw_dict, f'{f}.framework in Frameworks') + fw_dict.add_item('isa', 'PBXBuildFile') + fw_dict.add_item('fileRef', self.native_frameworks_fileref[f], f) + + for s in t.sources: + in_build_dir = False + if isinstance(s, mesonlib.File): + if s.is_built: + in_build_dir = True + s = os.path.join(s.subdir, s.fname) + + if not isinstance(s, str): + continue + sdict = PbxDict() + k = (tname, s) + idval = self.buildfile_ids[k] + fileref = self.fileref_ids[k] + if in_build_dir: + fullpath = os.path.join(self.environment.get_build_dir(), s) + else: + fullpath = os.path.join(self.environment.get_source_dir(), s) + sdict.add_item('isa', 'PBXBuildFile') + sdict.add_item('fileRef', fileref, fullpath) + objects_dict.add_item(idval, sdict) + + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Object files are not source files as such. We add them + # by hand in linker flags. It is also not particularly + # clear how to define build files in Xcode's file format. + continue + if isinstance(o, mesonlib.File): + o = os.path.join(o.subdir, o.fname) + elif isinstance(o, str): + o = os.path.join(t.subdir, o) + idval = self.buildfile_ids[(tname, o)] + k = (tname, o) + fileref = self.fileref_ids[k] + assert o not in self.filemap + self.filemap[o] = idval + fullpath = os.path.join(self.environment.get_source_dir(), o) + fullpath2 = fullpath + o_dict = PbxDict() + objects_dict.add_item(idval, o_dict, fullpath) + o_dict.add_item('isa', 'PBXBuildFile') + o_dict.add_item('fileRef', fileref, fullpath2) + + generator_id = 0 + for g in t.generated: + if not isinstance(g, build.GeneratedList): + continue + self.create_generator_shellphase(objects_dict, tname, generator_id) + generator_id += 1 + + # Custom targets are shell build phases in Xcode terminology. + for tname, t in self.custom_targets.items(): + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t) + for o in ofilenames: + custom_dict = PbxDict() + objects_dict.add_item(self.custom_target_output_buildfile[o], custom_dict, f'/* {o} */') + custom_dict.add_item('isa', 'PBXBuildFile') + custom_dict.add_item('fileRef', self.custom_target_output_fileref[o]) + generator_id = 0 + for g in t.sources: + if not isinstance(g, build.GeneratedList): + continue + self.create_generator_shellphase(objects_dict, tname, generator_id) + generator_id += 1 + + def create_generator_shellphase(self, objects_dict, tname, generator_id): + file_ids = self.generator_buildfile_ids[(tname, generator_id)] + ref_ids = self.generator_fileref_ids[(tname, generator_id)] + assert len(ref_ids) == len(file_ids) + for file_o, ref_id in zip(file_ids, ref_ids): + odict = PbxDict() + objects_dict.add_item(file_o, odict) + odict.add_item('isa', 'PBXBuildFile') + odict.add_item('fileRef', ref_id) + + def generate_pbx_build_style(self, objects_dict): + # FIXME: Xcode 9 and later does not uses PBXBuildStyle and it gets removed. Maybe we can remove this part. + for name, idval in self.buildstylemap.items(): + styledict = PbxDict() + objects_dict.add_item(idval, styledict, name) + styledict.add_item('isa', 'PBXBuildStyle') + settings_dict = PbxDict() + styledict.add_item('buildSettings', settings_dict) + settings_dict.add_item('COPY_PHASE_STRIP', 'NO') + styledict.add_item('name', f'"{name}"') + + def generate_pbx_container_item_proxy(self, objects_dict): + for t in self.build_targets: + proxy_dict = PbxDict() + objects_dict.add_item(self.containerproxy_map[t], proxy_dict, 'PBXContainerItemProxy') + proxy_dict.add_item('isa', 'PBXContainerItemProxy') + proxy_dict.add_item('containerPortal', self.project_uid, 'Project object') + proxy_dict.add_item('proxyType', '1') + proxy_dict.add_item('remoteGlobalIDString', self.native_targets[t]) + proxy_dict.add_item('remoteInfo', '"' + t + '"') + + def generate_pbx_file_reference(self, objects_dict): + for tname, t in self.build_targets.items(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + fw_dict = PbxDict() + framework_fileref = self.native_frameworks_fileref[f] + if objects_dict.has_item(framework_fileref): + continue + objects_dict.add_item(framework_fileref, fw_dict, f) + fw_dict.add_item('isa', 'PBXFileReference') + fw_dict.add_item('lastKnownFileType', 'wrapper.framework') + fw_dict.add_item('name', f'{f}.framework') + fw_dict.add_item('path', f'System/Library/Frameworks/{f}.framework') + fw_dict.add_item('sourceTree', 'SDKROOT') + for s in t.sources: + in_build_dir = False + if isinstance(s, mesonlib.File): + if s.is_built: + in_build_dir = True + s = os.path.join(s.subdir, s.fname) + if not isinstance(s, str): + continue + idval = self.fileref_ids[(tname, s)] + fullpath = os.path.join(self.environment.get_source_dir(), s) + src_dict = PbxDict() + xcodetype = self.get_xcodetype(s) + name = os.path.basename(s) + path = s + objects_dict.add_item(idval, src_dict, fullpath) + src_dict.add_item('isa', 'PBXFileReference') + src_dict.add_item('explicitFileType', '"' + xcodetype + '"') + src_dict.add_item('fileEncoding', '4') + if in_build_dir: + src_dict.add_item('name', '"' + name + '"') + # This makes no sense. This should say path instead of name + # but then the path gets added twice. + src_dict.add_item('path', '"' + name + '"') + src_dict.add_item('sourceTree', 'BUILD_ROOT') + else: + src_dict.add_item('name', '"' + name + '"') + src_dict.add_item('path', '"' + path + '"') + src_dict.add_item('sourceTree', 'SOURCE_ROOT') + + generator_id = 0 + for g in t.generated: + if not isinstance(g, build.GeneratedList): + continue + outputs = self.generator_outputs[(tname, generator_id)] + ref_ids = self.generator_fileref_ids[tname, generator_id] + assert len(ref_ids) == len(outputs) + for o, ref_id in zip(outputs, ref_ids): + odict = PbxDict() + name = os.path.basename(o) + objects_dict.add_item(ref_id, odict, o) + xcodetype = self.get_xcodetype(o) + rel_name = mesonlib.relpath(o, self.environment.get_source_dir()) + odict.add_item('isa', 'PBXFileReference') + odict.add_item('explicitFileType', '"' + xcodetype + '"') + odict.add_item('fileEncoding', '4') + odict.add_item('name', f'"{name}"') + odict.add_item('path', f'"{rel_name}"') + odict.add_item('sourceTree', 'SOURCE_ROOT') + + generator_id += 1 + + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Same as with pbxbuildfile. + continue + if isinstance(o, mesonlib.File): + fullpath = o.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) + o = os.path.join(o.subdir, o.fname) + else: + o = os.path.join(t.subdir, o) + fullpath = os.path.join(self.environment.get_source_dir(), o) + idval = self.fileref_ids[(tname, o)] + rel_name = mesonlib.relpath(fullpath, self.environment.get_source_dir()) + o_dict = PbxDict() + name = os.path.basename(o) + objects_dict.add_item(idval, o_dict, fullpath) + o_dict.add_item('isa', 'PBXFileReference') + o_dict.add_item('explicitFileType', '"' + self.get_xcodetype(o) + '"') + o_dict.add_item('fileEncoding', '4') + o_dict.add_item('name', f'"{name}"') + o_dict.add_item('path', f'"{rel_name}"') + o_dict.add_item('sourceTree', 'SOURCE_ROOT') + for tname, idval in self.target_filemap.items(): + target_dict = PbxDict() + objects_dict.add_item(idval, target_dict, tname) + t = self.build_targets[tname] + fname = t.get_filename() + reftype = 0 + if isinstance(t, build.Executable): + typestr = 'compiled.mach-o.executable' + path = fname + elif isinstance(t, build.SharedLibrary): + typestr = self.get_xcodetype('dummy.dylib') + path = fname + else: + typestr = self.get_xcodetype(fname) + path = '"%s"' % t.get_filename() + target_dict.add_item('isa', 'PBXFileReference') + target_dict.add_item('explicitFileType', '"' + typestr + '"') + if ' ' in path and path[0] != '"': + target_dict.add_item('path', f'"{path}"') + else: + target_dict.add_item('path', path) + target_dict.add_item('refType', reftype) + target_dict.add_item('sourceTree', 'BUILT_PRODUCTS_DIR') + + for tname, t in self.custom_targets.items(): + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t) + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + elif isinstance(s, str): + s = os.path.join(t.subdir, s) + else: + continue + custom_dict = PbxDict() + typestr = self.get_xcodetype(s) + custom_dict.add_item('isa', 'PBXFileReference') + custom_dict.add_item('explicitFileType', '"' + typestr + '"') + custom_dict.add_item('name', f'"{s}"') + custom_dict.add_item('path', f'"{s}"') + custom_dict.add_item('refType', 0) + custom_dict.add_item('sourceTree', 'SOURCE_ROOT') + objects_dict.add_item(self.fileref_ids[(tname, s)], custom_dict) + for o in ofilenames: + custom_dict = PbxDict() + typestr = self.get_xcodetype(o) + custom_dict.add_item('isa', 'PBXFileReference') + custom_dict.add_item('explicitFileType', '"' + typestr + '"') + custom_dict.add_item('name', o) + custom_dict.add_item('path', os.path.join(self.src_to_build, o)) + custom_dict.add_item('refType', 0) + custom_dict.add_item('sourceTree', 'SOURCE_ROOT') + objects_dict.add_item(self.custom_target_output_fileref[o], custom_dict) + + for buildfile in self.interpreter.get_build_def_files(): + basename = os.path.split(buildfile)[1] + buildfile_dict = PbxDict() + typestr = self.get_xcodetype(buildfile) + buildfile_dict.add_item('isa', 'PBXFileReference') + buildfile_dict.add_item('explicitFileType', '"' + typestr + '"') + buildfile_dict.add_item('name', f'"{basename}"') + buildfile_dict.add_item('path', f'"{buildfile}"') + buildfile_dict.add_item('refType', 0) + buildfile_dict.add_item('sourceTree', 'SOURCE_ROOT') + objects_dict.add_item(self.fileref_ids[buildfile], buildfile_dict) + + def generate_pbx_frameworks_buildphase(self, objects_dict): + for t in self.build_targets.values(): + bt_dict = PbxDict() + objects_dict.add_item(t.buildphasemap['Frameworks'], bt_dict, 'Frameworks') + bt_dict.add_item('isa', 'PBXFrameworksBuildPhase') + bt_dict.add_item('buildActionMask', 2147483647) + file_list = PbxArray() + bt_dict.add_item('files', file_list) + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks') + bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + + def generate_pbx_group(self, objects_dict): + groupmap = {} + target_src_map = {} + for t in self.build_targets: + groupmap[t] = self.gen_id() + target_src_map[t] = self.gen_id() + for t in self.custom_targets: + groupmap[t] = self.gen_id() + target_src_map[t] = self.gen_id() + projecttree_id = self.gen_id() + resources_id = self.gen_id() + products_id = self.gen_id() + frameworks_id = self.gen_id() + main_dict = PbxDict() + objects_dict.add_item(self.maingroup_id, main_dict) + main_dict.add_item('isa', 'PBXGroup') + main_children = PbxArray() + main_dict.add_item('children', main_children) + main_children.add_item(projecttree_id, 'Project tree') + main_children.add_item(resources_id, 'Resources') + main_children.add_item(products_id, 'Products') + main_children.add_item(frameworks_id, 'Frameworks') + main_dict.add_item('sourceTree', '""') + + self.add_projecttree(objects_dict, projecttree_id) + + resource_dict = PbxDict() + objects_dict.add_item(resources_id, resource_dict, 'Resources') + resource_dict.add_item('isa', 'PBXGroup') + resource_children = PbxArray() + resource_dict.add_item('children', resource_children) + resource_dict.add_item('name', 'Resources') + resource_dict.add_item('sourceTree', '""') + + frameworks_dict = PbxDict() + objects_dict.add_item(frameworks_id, frameworks_dict, 'Frameworks') + frameworks_dict.add_item('isa', 'PBXGroup') + frameworks_children = PbxArray() + frameworks_dict.add_item('children', frameworks_children) + # write frameworks + + for t in self.build_targets.values(): + for dep in t.get_external_deps(): + if isinstance(dep, dependencies.AppleFrameworks): + for f in dep.frameworks: + frameworks_children.add_item(self.native_frameworks_fileref[f], f) + + frameworks_dict.add_item('name', 'Frameworks') + frameworks_dict.add_item('sourceTree', '""') + + for tname, t in self.custom_targets.items(): + target_dict = PbxDict() + objects_dict.add_item(groupmap[tname], target_dict, tname) + target_dict.add_item('isa', 'PBXGroup') + target_children = PbxArray() + target_dict.add_item('children', target_children) + target_children.add_item(target_src_map[tname], 'Source files') + if t.subproject: + target_dict.add_item('name', f'"{t.subproject} • {t.name}"') + else: + target_dict.add_item('name', f'"{t.name}"') + target_dict.add_item('sourceTree', '""') + source_files_dict = PbxDict() + objects_dict.add_item(target_src_map[tname], source_files_dict, 'Source files') + source_files_dict.add_item('isa', 'PBXGroup') + source_file_children = PbxArray() + source_files_dict.add_item('children', source_file_children) + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + elif isinstance(s, str): + s = os.path.join(t.subdir, s) + else: + continue + source_file_children.add_item(self.fileref_ids[(tname, s)], s) + source_files_dict.add_item('name', '"Source files"') + source_files_dict.add_item('sourceTree', '""') + + # And finally products + product_dict = PbxDict() + objects_dict.add_item(products_id, product_dict, 'Products') + product_dict.add_item('isa', 'PBXGroup') + product_children = PbxArray() + product_dict.add_item('children', product_children) + for t in self.build_targets: + product_children.add_item(self.target_filemap[t], t) + product_dict.add_item('name', 'Products') + product_dict.add_item('sourceTree', '""') + + def write_group_target_entry(self, objects_dict, t): + tid = t.get_id() + group_id = self.gen_id() + target_dict = PbxDict() + objects_dict.add_item(group_id, target_dict, tid) + target_dict.add_item('isa', 'PBXGroup') + target_children = PbxArray() + target_dict.add_item('children', target_children) + target_dict.add_item('name', f'"{t} · target"') + target_dict.add_item('sourceTree', '""') + source_files_dict = PbxDict() + for s in t.sources: + if isinstance(s, mesonlib.File): + s = os.path.join(s.subdir, s.fname) + elif isinstance(s, str): + s = os.path.join(t.subdir, s) + else: + continue + target_children.add_item(self.fileref_ids[(tid, s)], s) + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + # Do not show built object files in the project tree. + continue + if isinstance(o, mesonlib.File): + o = os.path.join(o.subdir, o.fname) + else: + o = os.path.join(t.subdir, o) + target_children.add_item(self.fileref_ids[(tid, o)], o) + source_files_dict.add_item('name', '"Source files"') + source_files_dict.add_item('sourceTree', '""') + return group_id + + def add_projecttree(self, objects_dict, projecttree_id): + root_dict = PbxDict() + objects_dict.add_item(projecttree_id, root_dict, "Root of project tree") + root_dict.add_item('isa', 'PBXGroup') + target_children = PbxArray() + root_dict.add_item('children', target_children) + root_dict.add_item('name', '"Project root"') + root_dict.add_item('sourceTree', '""') + + project_tree = self.generate_project_tree() + self.write_tree(objects_dict, project_tree, target_children, '') + + def write_tree(self, objects_dict, tree_node, children_array, current_subdir): + for subdir_name, subdir_node in tree_node.subdirs.items(): + subdir_dict = PbxDict() + subdir_children = PbxArray() + subdir_id = self.gen_id() + objects_dict.add_item(subdir_id, subdir_dict) + children_array.add_item(subdir_id) + subdir_dict.add_item('isa', 'PBXGroup') + subdir_dict.add_item('children', subdir_children) + subdir_dict.add_item('name', f'"{subdir_name}"') + subdir_dict.add_item('sourceTree', '""') + self.write_tree(objects_dict, subdir_node, subdir_children, os.path.join(current_subdir, subdir_name)) + for target in tree_node.targets: + group_id = self.write_group_target_entry(objects_dict, target) + children_array.add_item(group_id) + potentials = [os.path.join(current_subdir, 'meson.build'), + os.path.join(current_subdir, 'meson.options'), + os.path.join(current_subdir, 'meson_options.txt')] + for bf in potentials: + i = self.fileref_ids.get(bf, None) + if i: + children_array.add_item(i) + + def generate_project_tree(self): + tree_info = FileTreeEntry() + for tname, t in self.build_targets.items(): + self.add_target_to_tree(tree_info, t) + return tree_info + + def add_target_to_tree(self, tree_root, t): + current_node = tree_root + path_segments = t.subdir.split('/') + for s in path_segments: + if not s: + continue + if s not in current_node.subdirs: + current_node.subdirs[s] = FileTreeEntry() + current_node = current_node.subdirs[s] + current_node.targets.append(t) + + def generate_pbx_native_target(self, objects_dict): + for tname, idval in self.native_targets.items(): + ntarget_dict = PbxDict() + t = self.build_targets[tname] + objects_dict.add_item(idval, ntarget_dict, tname) + ntarget_dict.add_item('isa', 'PBXNativeTarget') + ntarget_dict.add_item('buildConfigurationList', self.buildconflistmap[tname], f'Build configuration list for PBXNativeTarget "{tname}"') + buildphases_array = PbxArray() + ntarget_dict.add_item('buildPhases', buildphases_array) + generator_id = 0 + for g in t.generated: + # Custom target are handled via inter-target dependencies. + # Generators are built as a shellscriptbuildphase. + if isinstance(g, build.GeneratedList): + buildphases_array.add_item(self.shell_targets[(tname, generator_id)], f'Generator {generator_id}/{tname}') + generator_id += 1 + for bpname, bpval in t.buildphasemap.items(): + buildphases_array.add_item(bpval, f'{bpname} yyy') + ntarget_dict.add_item('buildRules', PbxArray()) + dep_array = PbxArray() + ntarget_dict.add_item('dependencies', dep_array) + dep_array.add_item(self.regen_dependency_id) + # These dependencies only tell Xcode that the deps must be built + # before this one. They don't set up linkage or anything + # like that. Those are set up in the XCBuildConfiguration. + for lt in self.build_targets[tname].link_targets: + # NOT DOCUMENTED, may need to make different links + # to same target have different targetdependency item. + if isinstance(lt, build.CustomTarget): + dep_array.add_item(self.pbx_custom_dep_map[lt.get_id()], lt.name) + elif isinstance(lt, build.CustomTargetIndex): + dep_array.add_item(self.pbx_custom_dep_map[lt.target.get_id()], lt.target.name) + else: + idval = self.pbx_dep_map[lt.get_id()] + dep_array.add_item(idval, 'PBXTargetDependency') + for o in t.objects: + if isinstance(o, build.ExtractedObjects): + source_target_id = o.target.get_id() + idval = self.pbx_dep_map[source_target_id] + dep_array.add_item(idval, 'PBXTargetDependency') + generator_id = 0 + for o in t.generated: + if isinstance(o, build.CustomTarget): + dep_array.add_item(self.pbx_custom_dep_map[o.get_id()], o.name) + elif isinstance(o, build.CustomTargetIndex): + dep_array.add_item(self.pbx_custom_dep_map[o.target.get_id()], o.target.name) + + generator_id += 1 + + ntarget_dict.add_item('name', f'"{tname}"') + ntarget_dict.add_item('productName', f'"{tname}"') + ntarget_dict.add_item('productReference', self.target_filemap[tname], tname) + if isinstance(t, build.Executable): + typestr = 'com.apple.product-type.tool' + elif isinstance(t, build.StaticLibrary): + typestr = 'com.apple.product-type.library.static' + elif isinstance(t, build.SharedLibrary): + typestr = 'com.apple.product-type.library.dynamic' + else: + raise MesonException('Unknown target type for %s' % tname) + ntarget_dict.add_item('productType', f'"{typestr}"') + + def generate_pbx_project(self, objects_dict): + project_dict = PbxDict() + objects_dict.add_item(self.project_uid, project_dict, 'Project object') + project_dict.add_item('isa', 'PBXProject') + attr_dict = PbxDict() + project_dict.add_item('attributes', attr_dict) + attr_dict.add_item('BuildIndependentTargetsInParallel', 'YES') + project_dict.add_item('buildConfigurationList', self.project_conflist, f'Build configuration list for PBXProject "{self.build.project_name}"') + project_dict.add_item('buildSettings', PbxDict()) + style_arr = PbxArray() + project_dict.add_item('buildStyles', style_arr) + for name, idval in self.buildstylemap.items(): + style_arr.add_item(idval, name) + project_dict.add_item('compatibilityVersion', '"Xcode 3.2"') + project_dict.add_item('hasScannedForEncodings', 0) + project_dict.add_item('mainGroup', self.maingroup_id) + project_dict.add_item('projectDirPath', '"' + self.environment.get_source_dir() + '"') + project_dict.add_item('projectRoot', '""') + targets_arr = PbxArray() + project_dict.add_item('targets', targets_arr) + targets_arr.add_item(self.all_id, 'ALL_BUILD') + targets_arr.add_item(self.test_id, 'RUN_TESTS') + targets_arr.add_item(self.regen_id, 'REGENERATE') + for t in self.build_targets: + targets_arr.add_item(self.native_targets[t], t) + for t in self.custom_targets: + targets_arr.add_item(self.custom_aggregate_targets[t], t) + + def generate_pbx_shell_build_phase(self, objects_dict): + self.generate_test_shell_build_phase(objects_dict) + self.generate_regen_shell_build_phase(objects_dict) + self.generate_custom_target_shell_build_phases(objects_dict) + self.generate_generator_target_shell_build_phases(objects_dict) + + def generate_test_shell_build_phase(self, objects_dict): + shell_dict = PbxDict() + objects_dict.add_item(self.test_command_id, shell_dict, 'ShellScript') + shell_dict.add_item('isa', 'PBXShellScriptBuildPhase') + shell_dict.add_item('buildActionMask', 2147483647) + shell_dict.add_item('files', PbxArray()) + shell_dict.add_item('inputPaths', PbxArray()) + shell_dict.add_item('outputPaths', PbxArray()) + shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + shell_dict.add_item('shellPath', '/bin/sh') + cmd = mesonlib.get_meson_command() + ['test', '--no-rebuild', '-C', self.environment.get_build_dir()] + cmdstr = ' '.join(["'%s'" % i for i in cmd]) + shell_dict.add_item('shellScript', f'"{cmdstr}"') + shell_dict.add_item('showEnvVarsInLog', 0) + + def generate_regen_shell_build_phase(self, objects_dict): + shell_dict = PbxDict() + objects_dict.add_item(self.regen_command_id, shell_dict, 'ShellScript') + shell_dict.add_item('isa', 'PBXShellScriptBuildPhase') + shell_dict.add_item('buildActionMask', 2147483647) + shell_dict.add_item('files', PbxArray()) + shell_dict.add_item('inputPaths', PbxArray()) + shell_dict.add_item('outputPaths', PbxArray()) + shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + shell_dict.add_item('shellPath', '/bin/sh') + cmd = mesonlib.get_meson_command() + ['--internal', 'regencheck', os.path.join(self.environment.get_build_dir(), 'meson-private')] + cmdstr = ' '.join(["'%s'" % i for i in cmd]) + shell_dict.add_item('shellScript', f'"{cmdstr}"') + shell_dict.add_item('showEnvVarsInLog', 0) + + def generate_custom_target_shell_build_phases(self, objects_dict): + # Custom targets are shell build phases in Xcode terminology. + for tname, t in self.custom_targets.items(): + if not isinstance(t, build.CustomTarget): + continue + (srcs, ofilenames, cmd) = self.eval_custom_target_command(t, absolute_outputs=True) + fixed_cmd, _ = self.as_meson_exe_cmdline(cmd[0], + cmd[1:], + capture=ofilenames[0] if t.capture else None, + feed=srcs[0] if t.feed else None, + env=t.env) + custom_dict = PbxDict() + objects_dict.add_item(self.shell_targets[tname], custom_dict, f'/* Custom target {tname} */') + custom_dict.add_item('isa', 'PBXShellScriptBuildPhase') + custom_dict.add_item('buildActionMask', 2147483647) + custom_dict.add_item('files', PbxArray()) + custom_dict.add_item('inputPaths', PbxArray()) + outarray = PbxArray() + custom_dict.add_item('name', '"Generate {}."'.format(ofilenames[0])) + custom_dict.add_item('outputPaths', outarray) + for o in ofilenames: + outarray.add_item(os.path.join(self.environment.get_build_dir(), o)) + custom_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + custom_dict.add_item('shellPath', '/bin/sh') + workdir = self.environment.get_build_dir() + quoted_cmd = [] + for c in fixed_cmd: + quoted_cmd.append(c.replace('"', chr(92) + '"')) + cmdstr = ' '.join([f"\\'{x}\\'" for x in quoted_cmd]) + custom_dict.add_item('shellScript', f'"cd {workdir}; {cmdstr}"') + custom_dict.add_item('showEnvVarsInLog', 0) + + def generate_generator_target_shell_build_phases(self, objects_dict): + for tname, t in self.build_targets.items(): + generator_id = 0 + for genlist in t.generated: + if isinstance(genlist, build.GeneratedList): + self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict) + generator_id += 1 + for tname, t in self.custom_targets.items(): + generator_id = 0 + for genlist in t.sources: + if isinstance(genlist, build.GeneratedList): + self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict) + generator_id += 1 + + def generate_single_generator_phase(self, tname, t, genlist, generator_id, objects_dict): + # TODO: this should be rewritten to use the meson wrapper, like the other generators do + # Currently it doesn't handle a host binary that requires an exe wrapper correctly. + generator = genlist.get_generator() + exe = generator.get_exe() + exe_arr = self.build_target_to_cmd_array(exe) + workdir = self.environment.get_build_dir() + gen_dict = PbxDict() + objects_dict.add_item(self.shell_targets[(tname, generator_id)], gen_dict, f'"Generator {generator_id}/{tname}"') + infilelist = genlist.get_inputs() + outfilelist = genlist.get_outputs() + gen_dict.add_item('isa', 'PBXShellScriptBuildPhase') + gen_dict.add_item('buildActionMask', 2147483647) + gen_dict.add_item('files', PbxArray()) + gen_dict.add_item('inputPaths', PbxArray()) + gen_dict.add_item('name', f'"Generator {generator_id}/{tname}"') + commands = [["cd", workdir]] # Array of arrays, each one a single command, will get concatenated below. + k = (tname, generator_id) + ofile_abs = self.generator_outputs[k] + outarray = PbxArray() + gen_dict.add_item('outputPaths', outarray) + for of in ofile_abs: + outarray.add_item(of) + for i in infilelist: + # This might be needed to be added to inputPaths. It's not done yet as it is + # unclear whether it is necessary, what actually happens when it is defined + # and currently the build works without it. + #infile_abs = i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) + infilename = i.rel_to_builddir(self.build_to_src) + base_args = generator.get_arglist(infilename) + for o_base in genlist.get_outputs_for(i): + o = os.path.join(self.get_target_private_dir(t), o_base) + args = [] + for arg in base_args: + arg = arg.replace("@INPUT@", infilename) + arg = arg.replace('@OUTPUT@', o).replace('@BUILD_DIR@', self.get_target_private_dir(t)) + arg = arg.replace("@CURRENT_SOURCE_DIR@", os.path.join(self.build_to_src, t.subdir)) + args.append(arg) + args = self.replace_outputs(args, self.get_target_private_dir(t), outfilelist) + args = self.replace_extra_args(args, genlist) + if generator.capture: + # When capturing, stdout is the output. Forward it with the shell. + full_command = ['('] + exe_arr + args + ['>', o, ')'] + else: + full_command = exe_arr + args + commands.append(full_command) + gen_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + gen_dict.add_item('shellPath', '/bin/sh') + quoted_cmds = [] + for cmnd in commands: + q = [] + for c in cmnd: + if ' ' in c: + q.append(f'\\"{c}\\"') + else: + q.append(c) + quoted_cmds.append(' '.join(q)) + cmdstr = '"' + ' && '.join(quoted_cmds) + '"' + gen_dict.add_item('shellScript', cmdstr) + gen_dict.add_item('showEnvVarsInLog', 0) + + def generate_pbx_sources_build_phase(self, objects_dict): + for name in self.source_phase: + phase_dict = PbxDict() + t = self.build_targets[name] + objects_dict.add_item(t.buildphasemap[name], phase_dict, 'Sources') + phase_dict.add_item('isa', 'PBXSourcesBuildPhase') + phase_dict.add_item('buildActionMask', 2147483647) + file_arr = PbxArray() + phase_dict.add_item('files', file_arr) + for s in self.build_targets[name].sources: + s = os.path.join(s.subdir, s.fname) + if not self.environment.is_header(s): + file_arr.add_item(self.buildfile_ids[(name, s)], os.path.join(self.environment.get_source_dir(), s)) + generator_id = 0 + for gt in t.generated: + if isinstance(gt, build.CustomTarget): + (srcs, ofilenames, cmd) = self.eval_custom_target_command(gt) + for o in ofilenames: + file_arr.add_item(self.custom_target_output_buildfile[o], + os.path.join(self.environment.get_build_dir(), o)) + elif isinstance(gt, build.CustomTargetIndex): + for o in gt.get_outputs(): + file_arr.add_item(self.custom_target_output_buildfile[o], + os.path.join(self.environment.get_build_dir(), o)) + elif isinstance(gt, build.GeneratedList): + genfiles = self.generator_buildfile_ids[(name, generator_id)] + generator_id += 1 + for o in genfiles: + file_arr.add_item(o) + else: + raise RuntimeError('Unknown input type: ' + str(gt)) + phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0) + + def generate_pbx_target_dependency(self, objects_dict): + all_dict = PbxDict() + objects_dict.add_item(self.build_all_tdep_id, all_dict, 'ALL_BUILD') + all_dict.add_item('isa', 'PBXTargetDependency') + all_dict.add_item('target', self.all_id) + targets = [] + targets.append((self.regen_dependency_id, self.regen_id, 'REGEN', None)) + for t in self.build_targets: + idval = self.pbx_dep_map[t] # VERIFY: is this correct? + targets.append((idval, self.native_targets[t], t, self.containerproxy_map[t])) + + for t in self.custom_targets: + idval = self.pbx_custom_dep_map[t] + targets.append((idval, self.custom_aggregate_targets[t], t, None)) # self.containerproxy_map[t])) + + # Sort object by ID + sorted_targets = sorted(targets, key=operator.itemgetter(0)) + for t in sorted_targets: + t_dict = PbxDict() + objects_dict.add_item(t[0], t_dict, 'PBXTargetDependency') + t_dict.add_item('isa', 'PBXTargetDependency') + t_dict.add_item('target', t[1], t[2]) + if t[3] is not None: + t_dict.add_item('targetProxy', t[3], 'PBXContainerItemProxy') + + def generate_xc_build_configuration(self, objects_dict): + # First the setup for the toplevel project. + for buildtype in self.buildtypes: + bt_dict = PbxDict() + objects_dict.add_item(self.project_configurations[buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') + settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') + settings_dict.add_item('SWIFT_VERSION', '5.0') + settings_dict.add_item('SDKROOT', '"macosx"') + settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) + bt_dict.add_item('name', f'"{buildtype}"') + + # Then the all target. + for buildtype in self.buildtypes: + bt_dict = PbxDict() + objects_dict.add_item(self.buildall_configurations[buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('SYMROOT', '"%s"' % self.environment.get_build_dir()) + warn_array = PbxArray() + warn_array.add_item('"$(inherited)"') + settings_dict.add_item('WARNING_CFLAGS', warn_array) + + bt_dict.add_item('name', f'"{buildtype}"') + + # Then the test target. + for buildtype in self.buildtypes: + bt_dict = PbxDict() + objects_dict.add_item(self.test_configurations[buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('SYMROOT', '"%s"' % self.environment.get_build_dir()) + warn_array = PbxArray() + settings_dict.add_item('WARNING_CFLAGS', warn_array) + warn_array.add_item('"$(inherited)"') + bt_dict.add_item('name', f'"{buildtype}"') + + # Now finally targets. + for target_name, target in self.build_targets.items(): + self.generate_single_build_target(objects_dict, target_name, target) + + for target_name, target in self.custom_targets.items(): + bt_dict = PbxDict() + objects_dict.add_item(self.buildconfmap[target_name][buildtype], bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') + settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') + settings_dict.add_item('SDKROOT', '"macosx"') + settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) + bt_dict.add_item('name', f'"{buildtype}"') + + def determine_internal_dep_link_args(self, target, buildtype): + links_dylib = False + dep_libs = [] + for l in target.link_targets: + if isinstance(target, build.SharedModule) and isinstance(l, build.Executable): + continue + if isinstance(l, build.CustomTargetIndex): + rel_dir = self.get_custom_target_output_dir(l.target) + libname = l.get_filename() + elif isinstance(l, build.CustomTarget): + rel_dir = self.get_custom_target_output_dir(l) + libname = l.get_filename() + else: + rel_dir = self.get_target_dir(l) + libname = l.get_filename() + abs_path = os.path.join(self.environment.get_build_dir(), rel_dir, libname) + dep_libs.append("'%s'" % abs_path) + if isinstance(l, build.SharedLibrary): + links_dylib = True + if isinstance(l, build.StaticLibrary): + (sub_libs, sub_links_dylib) = self.determine_internal_dep_link_args(l, buildtype) + dep_libs += sub_libs + links_dylib = links_dylib or sub_links_dylib + return (dep_libs, links_dylib) + + def generate_single_build_target(self, objects_dict, target_name, target): + for buildtype in self.buildtypes: + dep_libs = [] + links_dylib = False + headerdirs = [] + for d in target.include_dirs: + for sd in d.incdirs: + cd = os.path.join(d.curdir, sd) + headerdirs.append(os.path.join(self.environment.get_source_dir(), cd)) + headerdirs.append(os.path.join(self.environment.get_build_dir(), cd)) + for extra in d.extra_build_dirs: + headerdirs.append(os.path.join(self.environment.get_build_dir(), extra)) + (dep_libs, links_dylib) = self.determine_internal_dep_link_args(target, buildtype) + if links_dylib: + dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs + dylib_version = None + if isinstance(target, build.SharedLibrary): + if isinstance(target, build.SharedModule): + ldargs = [] + else: + ldargs = ['-dynamiclib'] + ldargs += ['-Wl,-headerpad_max_install_names'] + dep_libs + install_path = os.path.join(self.environment.get_build_dir(), target.subdir, buildtype) + dylib_version = target.soversion + else: + ldargs = dep_libs + install_path = '' + if dylib_version is not None: + product_name = target.get_basename() + '.' + dylib_version + else: + product_name = target.get_basename() + ldargs += target.link_args + # Swift is special. Again. You can't mix Swift with other languages + # in the same target. Thus for Swift we only use + if self.is_swift_target(target): + linker, stdlib_args = target.compilers['swift'], [] + else: + linker, stdlib_args = self.determine_linker_and_stdlib_args(target) + if not isinstance(target, build.StaticLibrary): + ldargs += self.build.get_project_link_args(linker, target.subproject, target.for_machine) + ldargs += self.build.get_global_link_args(linker, target.for_machine) + cargs = [] + for dep in target.get_external_deps(): + cargs += dep.get_compile_args() + ldargs += dep.get_link_args() + for o in target.objects: + # Add extracted objects to the link line by hand. + if isinstance(o, build.ExtractedObjects): + added_objs = set() + for objname_rel in self.determine_ext_objs(o): + objname_abs = os.path.join(self.environment.get_build_dir(), o.target.subdir, objname_rel) + if objname_abs not in added_objs: + added_objs.add(objname_abs) + ldargs += [r'\"' + objname_abs + r'\"'] + generator_id = 0 + for o in target.generated: + if isinstance(o, build.GeneratedList): + outputs = self.generator_outputs[target_name, generator_id] + generator_id += 1 + for o_abs in outputs: + if o_abs.endswith('.o') or o_abs.endswith('.obj'): + ldargs += [r'\"' + o_abs + r'\"'] + else: + if isinstance(o, build.CustomTarget): + (srcs, ofilenames, cmd) = self.eval_custom_target_command(o) + for ofname in ofilenames: + if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: + ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + elif isinstance(o, build.CustomTargetIndex): + for ofname in o.get_outputs(): + if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS: + ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"'] + else: + raise RuntimeError(o) + if isinstance(target, build.SharedModule): + ldargs += linker.get_std_shared_module_link_args(target.get_options()) + elif isinstance(target, build.SharedLibrary): + ldargs += linker.get_std_shared_lib_link_args() + ldstr = ' '.join(ldargs) + valid = self.buildconfmap[target_name][buildtype] + langargs = {} + for lang in self.environment.coredata.compilers[target.for_machine]: + if lang not in LANGNAMEMAP: + continue + compiler = target.compilers.get(lang) + if compiler is None: + continue + # Start with warning args + warn_args = compiler.get_warn_args(target.get_option(OptionKey('warning_level'))) + copt_proxy = target.get_options() + std_args = compiler.get_option_compile_args(copt_proxy) + # Add compile args added using add_project_arguments() + pargs = self.build.projects_args[target.for_machine].get(target.subproject, {}).get(lang, []) + # Add compile args added using add_global_arguments() + # These override per-project arguments + gargs = self.build.global_args[target.for_machine].get(lang, []) + targs = target.get_extra_args(lang) + args = warn_args + std_args + pargs + gargs + targs + if lang == 'swift': + # For some reason putting Swift module dirs in HEADER_SEARCH_PATHS does not work, + # but adding -I/path to manual args does work. + swift_dep_dirs = self.determine_swift_dep_dirs(target) + for d in swift_dep_dirs: + args += compiler.get_include_args(d, False) + if args: + lang_cargs = cargs + if compiler and target.implicit_include_directories: + # It is unclear what is the cwd when xcode runs. -I. does not seem to + # add the root build dir to the search path. So add an absolute path instead. + # This may break reproducible builds, in which case patches are welcome. + lang_cargs += self.get_custom_target_dir_include_args(target, compiler, absolute_path=True) + # Xcode cannot handle separate compilation flags for C and ObjectiveC. They are both + # put in OTHER_CFLAGS. Same with C++ and ObjectiveC++. + if lang == 'objc': + lang = 'c' + elif lang == 'objcpp': + lang = 'cpp' + langname = LANGNAMEMAP[lang] + if langname in langargs: + langargs[langname] += args + else: + langargs[langname] = args + langargs[langname] += lang_cargs + symroot = os.path.join(self.environment.get_build_dir(), target.subdir) + bt_dict = PbxDict() + objects_dict.add_item(valid, bt_dict, buildtype) + bt_dict.add_item('isa', 'XCBuildConfiguration') + settings_dict = PbxDict() + bt_dict.add_item('buildSettings', settings_dict) + settings_dict.add_item('COMBINE_HIDPI_IMAGES', 'YES') + if isinstance(target, build.SharedModule): + settings_dict.add_item('DYLIB_CURRENT_VERSION', '""') + settings_dict.add_item('DYLIB_COMPATIBILITY_VERSION', '""') + else: + if dylib_version is not None: + settings_dict.add_item('DYLIB_CURRENT_VERSION', f'"{dylib_version}"') + if target.prefix: + settings_dict.add_item('EXECUTABLE_PREFIX', target.prefix) + if target.suffix: + suffix = '.' + target.suffix + settings_dict.add_item('EXECUTABLE_SUFFIX', suffix) + settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[target.get_option(OptionKey('debug'))]) + settings_dict.add_item('GCC_INLINES_ARE_PRIVATE_EXTERN', 'NO') + opt_flag = OPT2XCODEOPT[target.get_option(OptionKey('optimization'))] + if opt_flag is not None: + settings_dict.add_item('GCC_OPTIMIZATION_LEVEL', opt_flag) + if target.has_pch: + # Xcode uses GCC_PREFIX_HEADER which only allows one file per target/executable. Precompiling various header files and + # applying a particular pch to each source file will require custom scripts (as a build phase) and build flags per each + # file. Since Xcode itself already discourages precompiled headers in favor of modules we don't try much harder here. + pchs = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp') + # Make sure to use headers (other backends require implementation files like *.c *.cpp, etc; these should not be used here) + pchs = [pch for pch in pchs if pch.endswith('.h') or pch.endswith('.hh') or pch.endswith('hpp')] + if pchs: + if len(pchs) > 1: + mlog.warning(f'Unsupported Xcode configuration: More than 1 precompiled header found "{pchs!s}". Target "{target.name}" might not compile correctly.') + relative_pch_path = os.path.join(target.get_subdir(), pchs[0]) # Path relative to target so it can be used with "$(PROJECT_DIR)" + settings_dict.add_item('GCC_PRECOMPILE_PREFIX_HEADER', 'YES') + settings_dict.add_item('GCC_PREFIX_HEADER', f'"$(PROJECT_DIR)/{relative_pch_path}"') + settings_dict.add_item('GCC_PREPROCESSOR_DEFINITIONS', '""') + settings_dict.add_item('GCC_SYMBOLS_PRIVATE_EXTERN', 'NO') + header_arr = PbxArray() + unquoted_headers = [] + unquoted_headers.append(self.get_target_private_dir_abs(target)) + if target.implicit_include_directories: + unquoted_headers.append(os.path.join(self.environment.get_build_dir(), target.get_subdir())) + unquoted_headers.append(os.path.join(self.environment.get_source_dir(), target.get_subdir())) + if headerdirs: + for i in headerdirs: + i = os.path.normpath(i) + unquoted_headers.append(i) + for i in unquoted_headers: + header_arr.add_item(f'"\\"{i}\\""') + settings_dict.add_item('HEADER_SEARCH_PATHS', header_arr) + settings_dict.add_item('INSTALL_PATH', f'"{install_path}"') + settings_dict.add_item('LIBRARY_SEARCH_PATHS', '""') + if isinstance(target, build.SharedModule): + settings_dict.add_item('LIBRARY_STYLE', 'BUNDLE') + settings_dict.add_item('MACH_O_TYPE', 'mh_bundle') + elif isinstance(target, build.SharedLibrary): + settings_dict.add_item('LIBRARY_STYLE', 'DYNAMIC') + self.add_otherargs(settings_dict, langargs) + settings_dict.add_item('OTHER_LDFLAGS', f'"{ldstr}"') + settings_dict.add_item('OTHER_REZFLAGS', '""') + if ' ' in product_name: + settings_dict.add_item('PRODUCT_NAME', f'"{product_name}"') + else: + settings_dict.add_item('PRODUCT_NAME', product_name) + settings_dict.add_item('SECTORDER_FLAGS', '""') + settings_dict.add_item('SYMROOT', f'"{symroot}"') + sysheader_arr = PbxArray() + # XCode will change every -I flag that points inside these directories + # to an -isystem. Thus set nothing in it since we control our own + # include flags. + settings_dict.add_item('SYSTEM_HEADER_SEARCH_PATHS', sysheader_arr) + settings_dict.add_item('USE_HEADERMAP', 'NO') + warn_array = PbxArray() + settings_dict.add_item('WARNING_CFLAGS', warn_array) + warn_array.add_item('"$(inherited)"') + bt_dict.add_item('name', buildtype) + + def add_otherargs(self, settings_dict, langargs): + for langname, args in langargs.items(): + if args: + quoted_args = [] + for a in args: + # This works but + # a) it's ugly as sin + # b) I don't know why it works or why every backslash must be escaped into eight backslashes + a = a.replace(chr(92), 8*chr(92)) # chr(92) is backslash, this how we smuggle it in without Python's quoting grabbing it. + a = a.replace(r'"', r'\\\"') + if ' ' in a or "'" in a: + a = r'\"' + a + r'\"' + quoted_args.append(a) + settings_dict.add_item(f'OTHER_{langname}FLAGS', '"' + ' '.join(quoted_args) + '"') + + def generate_xc_configurationList(self, objects_dict: PbxDict) -> None: + # FIXME: sort items + conf_dict = PbxDict() + objects_dict.add_item(self.project_conflist, conf_dict, f'Build configuration list for PBXProject "{self.build.project_name}"') + conf_dict.add_item('isa', 'XCConfigurationList') + confs_arr = PbxArray() + conf_dict.add_item('buildConfigurations', confs_arr) + for buildtype in self.buildtypes: + confs_arr.add_item(self.project_configurations[buildtype], buildtype) + conf_dict.add_item('defaultConfigurationIsVisible', 0) + conf_dict.add_item('defaultConfigurationName', self.buildtype) + + # Now the all target + all_dict = PbxDict() + objects_dict.add_item(self.all_buildconf_id, all_dict, 'Build configuration list for PBXAggregateTarget "ALL_BUILD"') + all_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + all_dict.add_item('buildConfigurations', conf_arr) + for buildtype in self.buildtypes: + conf_arr.add_item(self.buildall_configurations[buildtype], buildtype) + all_dict.add_item('defaultConfigurationIsVisible', 0) + all_dict.add_item('defaultConfigurationName', self.buildtype) + + # Test target + test_dict = PbxDict() + objects_dict.add_item(self.test_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "RUN_TEST"') + test_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + test_dict.add_item('buildConfigurations', conf_arr) + for buildtype in self.buildtypes: + conf_arr.add_item(self.test_configurations[buildtype], buildtype) + test_dict.add_item('defaultConfigurationIsVisible', 0) + test_dict.add_item('defaultConfigurationName', self.buildtype) + + # Regen target + regen_dict = PbxDict() + objects_dict.add_item(self.regen_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "REGENERATE"') + regen_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + regen_dict.add_item('buildConfigurations', conf_arr) + for buildtype in self.buildtypes: + conf_arr.add_item(self.test_configurations[buildtype], buildtype) + regen_dict.add_item('defaultConfigurationIsVisible', 0) + regen_dict.add_item('defaultConfigurationName', self.buildtype) + + for target_name in self.build_targets: + t_dict = PbxDict() + listid = self.buildconflistmap[target_name] + objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXNativeTarget "{target_name}"') + t_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + t_dict.add_item('buildConfigurations', conf_arr) + idval = self.buildconfmap[target_name][self.buildtype] + conf_arr.add_item(idval, self.buildtype) + t_dict.add_item('defaultConfigurationIsVisible', 0) + t_dict.add_item('defaultConfigurationName', self.buildtype) + + for target_name in self.custom_targets: + t_dict = PbxDict() + listid = self.buildconflistmap[target_name] + objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXAggregateTarget "{target_name}"') + t_dict.add_item('isa', 'XCConfigurationList') + conf_arr = PbxArray() + t_dict.add_item('buildConfigurations', conf_arr) + idval = self.buildconfmap[target_name][self.buildtype] + conf_arr.add_item(idval, self.buildtype) + t_dict.add_item('defaultConfigurationIsVisible', 0) + t_dict.add_item('defaultConfigurationName', self.buildtype) + + def generate_prefix(self, pbxdict: PbxDict) -> PbxDict: + pbxdict.add_item('archiveVersion', '1') + pbxdict.add_item('classes', PbxDict()) + pbxdict.add_item('objectVersion', '46') + objects_dict = PbxDict() + pbxdict.add_item('objects', objects_dict) + + return objects_dict + + def generate_suffix(self, pbxdict: PbxDict) -> None: + pbxdict.add_item('rootObject', self.project_uid, 'Project object') diff --git a/devtools/meson/mesonbuild/build.py b/devtools/meson/mesonbuild/build.py new file mode 100644 index 0000000..06e1714 --- /dev/null +++ b/devtools/meson/mesonbuild/build.py @@ -0,0 +1,3129 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +from collections import defaultdict, OrderedDict +from dataclasses import dataclass, field, InitVar +from functools import lru_cache +import abc +import hashlib +import itertools, pathlib +import os +import pickle +import re +import textwrap +import typing as T + +from . import coredata +from . import environment +from . import dependencies +from . import mlog +from . import programs +from .mesonlib import ( + HoldableObject, SecondLevelHolder, + File, MesonException, MachineChoice, PerMachine, OrderedSet, listify, + extract_as_list, typeslistify, stringlistify, classify_unity_sources, + get_filenames_templates_dict, substitute_values, has_path_sep, + OptionKey, PerMachineDefaultable, OptionOverrideProxy, + MesonBugException, EnvironmentVariables, pickle_load, +) +from .compilers import ( + is_object, clink_langs, sort_clink, all_languages, + is_known_suffix, detect_static_linker +) +from .interpreterbase import FeatureNew, FeatureDeprecated + +if T.TYPE_CHECKING: + from typing_extensions import Literal + from ._typing import ImmutableListProtocol + from .backend.backends import Backend, ExecutableSerialisation + from .compilers import Compiler + from .interpreter.interpreter import Test, SourceOutputs, Interpreter + from .interpreterbase import SubProject + from .linkers.linkers import StaticLinker + from .mesonlib import FileMode, FileOrString + from .modules import ModuleState + from .mparser import BaseNode + from .wrap import WrapMode + + GeneratedTypes = T.Union['CustomTarget', 'CustomTargetIndex', 'GeneratedList'] + LibTypes = T.Union['SharedLibrary', 'StaticLibrary', 'CustomTarget', 'CustomTargetIndex'] + BuildTargetTypes = T.Union['BuildTarget', 'CustomTarget', 'CustomTargetIndex'] + ObjectTypes = T.Union[str, 'File', 'ExtractedObjects', 'GeneratedTypes'] + +pch_kwargs = {'c_pch', 'cpp_pch'} + +lang_arg_kwargs = {f'{lang}_args' for lang in all_languages} +lang_arg_kwargs |= { + 'd_import_dirs', + 'd_unittest', + 'd_module_versions', + 'd_debug', +} + +vala_kwargs = {'vala_header', 'vala_gir', 'vala_vapi'} +rust_kwargs = {'rust_crate_type', 'rust_dependency_map'} +cs_kwargs = {'resources', 'cs_args'} + +buildtarget_kwargs = { + 'build_by_default', + 'build_rpath', + 'dependencies', + 'extra_files', + 'gui_app', + 'link_with', + 'link_whole', + 'link_args', + 'link_depends', + 'implicit_include_directories', + 'include_directories', + 'install', + 'install_rpath', + 'install_dir', + 'install_mode', + 'install_tag', + 'name_prefix', + 'name_suffix', + 'native', + 'objects', + 'override_options', + 'sources', + 'gnu_symbol_visibility', + 'link_language', + 'win_subsystem', +} + +known_build_target_kwargs = ( + buildtarget_kwargs | + lang_arg_kwargs | + pch_kwargs | + vala_kwargs | + rust_kwargs | + cs_kwargs) + +known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'} +known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} +known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'} +known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'} +known_jar_kwargs = known_exe_kwargs | {'main_class', 'java_resources'} + +def _process_install_tag(install_tag: T.Optional[T.List[T.Optional[str]]], + num_outputs: int) -> T.List[T.Optional[str]]: + _install_tag: T.List[T.Optional[str]] + if not install_tag: + _install_tag = [None] * num_outputs + elif len(install_tag) == 1: + _install_tag = install_tag * num_outputs + else: + _install_tag = install_tag + return _install_tag + + +@lru_cache(maxsize=None) +def get_target_macos_dylib_install_name(ld) -> str: + name = ['@rpath/', ld.prefix, ld.name] + if ld.soversion is not None: + name.append('.' + ld.soversion) + name.append('.dylib') + return ''.join(name) + +class InvalidArguments(MesonException): + pass + +@dataclass(eq=False) +class DependencyOverride(HoldableObject): + dep: dependencies.Dependency + node: 'BaseNode' + explicit: bool = True + +@dataclass(eq=False) +class Headers(HoldableObject): + sources: T.List[File] + install_subdir: T.Optional[str] + custom_install_dir: T.Optional[str] + custom_install_mode: 'FileMode' + subproject: str + + # TODO: we really don't need any of these methods, but they're preserved to + # keep APIs relying on them working. + + def set_install_subdir(self, subdir: str) -> None: + self.install_subdir = subdir + + def get_install_subdir(self) -> T.Optional[str]: + return self.install_subdir + + def get_sources(self) -> T.List[File]: + return self.sources + + def get_custom_install_dir(self) -> T.Optional[str]: + return self.custom_install_dir + + def get_custom_install_mode(self) -> 'FileMode': + return self.custom_install_mode + + +@dataclass(eq=False) +class Man(HoldableObject): + sources: T.List[File] + custom_install_dir: T.Optional[str] + custom_install_mode: 'FileMode' + subproject: str + locale: T.Optional[str] + + def get_custom_install_dir(self) -> T.Optional[str]: + return self.custom_install_dir + + def get_custom_install_mode(self) -> 'FileMode': + return self.custom_install_mode + + def get_sources(self) -> T.List['File']: + return self.sources + + +@dataclass(eq=False) +class EmptyDir(HoldableObject): + path: str + install_mode: 'FileMode' + subproject: str + install_tag: T.Optional[str] = None + + +@dataclass(eq=False) +class InstallDir(HoldableObject): + source_subdir: str + installable_subdir: str + install_dir: str + install_dir_name: str + install_mode: 'FileMode' + exclude: T.Tuple[T.Set[str], T.Set[str]] + strip_directory: bool + subproject: str + from_source_dir: bool = True + install_tag: T.Optional[str] = None + +@dataclass(eq=False) +class DepManifest: + version: str + license: T.List[str] + license_files: T.List[T.Tuple[str, File]] + subproject: str + + def to_json(self) -> T.Dict[str, T.Union[str, T.List[str]]]: + return { + 'version': self.version, + 'license': self.license, + 'license_files': [l[1].relative_name() for l in self.license_files], + } + + +# literally everything isn't dataclass stuff +class Build: + """A class that holds the status of one build including + all dependencies and so on. + """ + + def __init__(self, environment: environment.Environment): + self.version = coredata.version + self.project_name = 'name of master project' + self.project_version = None + self.environment = environment + self.projects = {} + self.targets: 'T.OrderedDict[str, T.Union[CustomTarget, BuildTarget]]' = OrderedDict() + self.global_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {}) + self.global_link_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {}) + self.projects_args: PerMachine[T.Dict[str, T.Dict[str, T.List[str]]]] = PerMachine({}, {}) + self.projects_link_args: PerMachine[T.Dict[str, T.Dict[str, T.List[str]]]] = PerMachine({}, {}) + self.tests: T.List['Test'] = [] + self.benchmarks: T.List['Test'] = [] + self.headers: T.List[Headers] = [] + self.man: T.List[Man] = [] + self.emptydir: T.List[EmptyDir] = [] + self.data: T.List[Data] = [] + self.symlinks: T.List[SymlinkData] = [] + self.static_linker: PerMachine[StaticLinker] = PerMachine(None, None) + self.subprojects = {} + self.subproject_dir = '' + self.install_scripts: T.List['ExecutableSerialisation'] = [] + self.postconf_scripts: T.List['ExecutableSerialisation'] = [] + self.dist_scripts: T.List['ExecutableSerialisation'] = [] + self.install_dirs: T.List[InstallDir] = [] + self.dep_manifest_name: T.Optional[str] = None + self.dep_manifest: T.Dict[str, DepManifest] = {} + self.stdlibs = PerMachine({}, {}) + self.test_setups: T.Dict[str, TestSetup] = {} + self.test_setup_default_name = None + self.find_overrides: T.Dict[str, T.Union['Executable', programs.ExternalProgram, programs.OverrideProgram]] = {} + self.searched_programs: T.Set[str] = set() # The list of all programs that have been searched for. + + # If we are doing a cross build we need two caches, if we're doing a + # build == host compilation the both caches should point to the same place. + self.dependency_overrides: PerMachine[T.Dict[T.Tuple, DependencyOverride]] = PerMachineDefaultable.default( + environment.is_cross_build(), {}, {}) + self.devenv: T.List[EnvironmentVariables] = [] + self.modules: T.List[str] = [] + + def get_build_targets(self): + build_targets = OrderedDict() + for name, t in self.targets.items(): + if isinstance(t, BuildTarget): + build_targets[name] = t + return build_targets + + def get_custom_targets(self): + custom_targets = OrderedDict() + for name, t in self.targets.items(): + if isinstance(t, CustomTarget): + custom_targets[name] = t + return custom_targets + + def copy(self) -> Build: + other = Build(self.environment) + for k, v in self.__dict__.items(): + if isinstance(v, (list, dict, set, OrderedDict)): + other.__dict__[k] = v.copy() + else: + other.__dict__[k] = v + return other + + def merge(self, other: Build) -> None: + for k, v in other.__dict__.items(): + self.__dict__[k] = v + + def ensure_static_linker(self, compiler: Compiler) -> None: + if self.static_linker[compiler.for_machine] is None and compiler.needs_static_linker(): + self.static_linker[compiler.for_machine] = detect_static_linker(self.environment, compiler) + + def get_project(self): + return self.projects[''] + + def get_subproject_dir(self): + return self.subproject_dir + + def get_targets(self) -> 'T.OrderedDict[str, T.Union[CustomTarget, BuildTarget]]': + return self.targets + + def get_tests(self) -> T.List['Test']: + return self.tests + + def get_benchmarks(self) -> T.List['Test']: + return self.benchmarks + + def get_headers(self) -> T.List['Headers']: + return self.headers + + def get_man(self) -> T.List['Man']: + return self.man + + def get_data(self) -> T.List['Data']: + return self.data + + def get_symlinks(self) -> T.List['SymlinkData']: + return self.symlinks + + def get_emptydir(self) -> T.List['EmptyDir']: + return self.emptydir + + def get_install_subdirs(self) -> T.List['InstallDir']: + return self.install_dirs + + def get_global_args(self, compiler: 'Compiler', for_machine: 'MachineChoice') -> T.List[str]: + d = self.global_args[for_machine] + return d.get(compiler.get_language(), []) + + def get_project_args(self, compiler: 'Compiler', project: str, for_machine: 'MachineChoice') -> T.List[str]: + d = self.projects_args[for_machine] + args = d.get(project) + if not args: + return [] + return args.get(compiler.get_language(), []) + + def get_global_link_args(self, compiler: 'Compiler', for_machine: 'MachineChoice') -> T.List[str]: + d = self.global_link_args[for_machine] + return d.get(compiler.get_language(), []) + + def get_project_link_args(self, compiler: 'Compiler', project: str, for_machine: 'MachineChoice') -> T.List[str]: + d = self.projects_link_args[for_machine] + + link_args = d.get(project) + if not link_args: + return [] + + return link_args.get(compiler.get_language(), []) + +@dataclass(eq=False) +class IncludeDirs(HoldableObject): + + """Internal representation of an include_directories call.""" + + curdir: str + incdirs: T.List[str] + is_system: bool + # Interpreter has validated that all given directories + # actually exist. + extra_build_dirs: T.List[str] = field(default_factory=list) + + def __repr__(self) -> str: + r = '<{} {}/{}>' + return r.format(self.__class__.__name__, self.curdir, self.incdirs) + + def get_curdir(self) -> str: + return self.curdir + + def get_incdirs(self) -> T.List[str]: + return self.incdirs + + def get_extra_build_dirs(self) -> T.List[str]: + return self.extra_build_dirs + + def to_string_list(self, sourcedir: str, builddir: T.Optional[str] = None) -> T.List[str]: + """Convert IncludeDirs object to a list of strings. + + :param sourcedir: The absolute source directory + :param builddir: The absolute build directory, option, build dir will not + be added if this is unset + :returns: A list of strings (without compiler argument) + """ + strlist: T.List[str] = [] + for idir in self.incdirs: + strlist.append(os.path.join(sourcedir, self.curdir, idir)) + if builddir: + strlist.append(os.path.join(builddir, self.curdir, idir)) + return strlist + +@dataclass(eq=False) +class ExtractedObjects(HoldableObject): + ''' + Holds a list of sources for which the objects must be extracted + ''' + target: 'BuildTarget' + srclist: T.List[File] = field(default_factory=list) + genlist: T.List['GeneratedTypes'] = field(default_factory=list) + objlist: T.List[T.Union[str, 'File', 'ExtractedObjects']] = field(default_factory=list) + recursive: bool = True + pch: bool = False + + def __post_init__(self) -> None: + if self.target.is_unity: + self.check_unity_compatible() + + def __repr__(self) -> str: + r = '<{0} {1!r}: {2}>' + return r.format(self.__class__.__name__, self.target.name, self.srclist) + + @staticmethod + def get_sources(sources: T.Sequence['FileOrString'], generated_sources: T.Sequence['GeneratedTypes']) -> T.List['FileOrString']: + # Merge sources and generated sources + sources = list(sources) + for gensrc in generated_sources: + for s in gensrc.get_outputs(): + # We cannot know the path where this source will be generated, + # but all we need here is the file extension to determine the + # compiler. + sources.append(s) + + # Filter out headers and all non-source files + return [s for s in sources if environment.is_source(s)] + + def classify_all_sources(self, sources: T.List[FileOrString], generated_sources: T.Sequence['GeneratedTypes']) -> T.Dict['Compiler', T.List['FileOrString']]: + sources_ = self.get_sources(sources, generated_sources) + return classify_unity_sources(self.target.compilers.values(), sources_) + + def check_unity_compatible(self) -> None: + # Figure out if the extracted object list is compatible with a Unity + # build. When we're doing a Unified build, we go through the sources, + # and create a single source file from each subset of the sources that + # can be compiled with a specific compiler. Then we create one object + # from each unified source file. So for each compiler we can either + # extra all its sources or none. + cmpsrcs = self.classify_all_sources(self.target.sources, self.target.generated) + extracted_cmpsrcs = self.classify_all_sources(self.srclist, self.genlist) + + for comp, srcs in extracted_cmpsrcs.items(): + if set(srcs) != set(cmpsrcs[comp]): + raise MesonException('Single object files cannot be extracted ' + 'in Unity builds. You can only extract all ' + 'the object files for each compiler at once.') + + +@dataclass(eq=False, order=False) +class StructuredSources(HoldableObject): + + """A container for sources in languages that use filesystem hierarchy. + + Languages like Rust and Cython rely on the layout of files in the filesystem + as part of the compiler implementation. This structure allows us to + represent the required filesystem layout. + """ + + sources: T.DefaultDict[str, T.List[T.Union[File, CustomTarget, CustomTargetIndex, GeneratedList]]] = field( + default_factory=lambda: defaultdict(list)) + + def __add__(self, other: StructuredSources) -> StructuredSources: + sources = self.sources.copy() + for k, v in other.sources.items(): + sources[k].extend(v) + return StructuredSources(sources) + + def __bool__(self) -> bool: + return bool(self.sources) + + def first_file(self) -> T.Union[File, CustomTarget, CustomTargetIndex, GeneratedList]: + """Get the first source in the root + + :return: The first source in the root + """ + return self.sources[''][0] + + def as_list(self) -> T.List[T.Union[File, CustomTarget, CustomTargetIndex, GeneratedList]]: + return list(itertools.chain.from_iterable(self.sources.values())) + + def needs_copy(self) -> bool: + """Do we need to create a structure in the build directory. + + This allows us to avoid making copies if the structures exists in the + source dir. Which could happen in situations where a generated source + only exists in some configurations + """ + for files in self.sources.values(): + for f in files: + if isinstance(f, File): + if f.is_built: + return True + else: + return True + return False + + +@dataclass(eq=False) +class Target(HoldableObject, metaclass=abc.ABCMeta): + + name: str + subdir: str + subproject: 'SubProject' + build_by_default: bool + for_machine: MachineChoice + environment: environment.Environment + install: bool = False + build_always_stale: bool = False + extra_files: T.List[File] = field(default_factory=list) + override_options: InitVar[T.Optional[T.Dict[OptionKey, str]]] = None + + @abc.abstractproperty + def typename(self) -> str: + pass + + @abc.abstractmethod + def type_suffix(self) -> str: + pass + + def __post_init__(self, overrides: T.Optional[T.Dict[OptionKey, str]]) -> None: + if overrides: + ovr = {k.evolve(machine=self.for_machine) if k.lang else k: v + for k, v in overrides.items()} + else: + ovr = {} + self.options = OptionOverrideProxy(ovr, self.environment.coredata.options, self.subproject) + # XXX: this should happen in the interpreter + if has_path_sep(self.name): + # Fix failing test 53 when this becomes an error. + mlog.warning(textwrap.dedent(f'''\ + Target "{self.name}" has a path separator in its name. + This is not supported, it can cause unexpected failures and will become + a hard error in the future.''')) + + # dataclass comparators? + def __lt__(self, other: object) -> bool: + if not isinstance(other, Target): + return NotImplemented + return self.get_id() < other.get_id() + + def __le__(self, other: object) -> bool: + if not isinstance(other, Target): + return NotImplemented + return self.get_id() <= other.get_id() + + def __gt__(self, other: object) -> bool: + if not isinstance(other, Target): + return NotImplemented + return self.get_id() > other.get_id() + + def __ge__(self, other: object) -> bool: + if not isinstance(other, Target): + return NotImplemented + return self.get_id() >= other.get_id() + + def get_default_install_dir(self) -> T.Tuple[str, str]: + raise NotImplementedError + + def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: + raise NotImplementedError + + def get_install_dir(self) -> T.Tuple[T.List[T.Union[str, Literal[False]]], str, Literal[False]]: + # Find the installation directory. + default_install_dir, default_install_dir_name = self.get_default_install_dir() + outdirs = self.get_custom_install_dir() + if outdirs and outdirs[0] != default_install_dir and outdirs[0] is not True: + # Either the value is set to a non-default value, or is set to + # False (which means we want this specific output out of many + # outputs to not be installed). + custom_install_dir = True + install_dir_names = [getattr(i, 'optname', None) for i in outdirs] + else: + custom_install_dir = False + # if outdirs is empty we need to set to something, otherwise we set + # only the first value to the default. + if outdirs: + outdirs[0] = default_install_dir + else: + outdirs = [default_install_dir] + install_dir_names = [default_install_dir_name] * len(outdirs) + + return outdirs, install_dir_names, custom_install_dir + + def get_basename(self) -> str: + return self.name + + def get_subdir(self) -> str: + return self.subdir + + def get_typename(self) -> str: + return self.typename + + @staticmethod + def _get_id_hash(target_id: str) -> str: + # We don't really need cryptographic security here. + # Small-digest hash function with unlikely collision is good enough. + h = hashlib.sha256() + h.update(target_id.encode(encoding='utf-8', errors='replace')) + # This ID should be case-insensitive and should work in Visual Studio, + # e.g. it should not start with leading '-'. + return h.hexdigest()[:7] + + @staticmethod + def construct_id_from_path(subdir: str, name: str, type_suffix: str) -> str: + """Construct target ID from subdir, name and type suffix. + + This helper function is made public mostly for tests.""" + # This ID must also be a valid file name on all OSs. + # It should also avoid shell metacharacters for obvious + # reasons. '@' is not used as often as '_' in source code names. + # In case of collisions consider using checksums. + # FIXME replace with assert when slash in names is prohibited + name_part = name.replace('/', '@').replace('\\', '@') + assert not has_path_sep(type_suffix) + my_id = name_part + type_suffix + if subdir: + subdir_part = Target._get_id_hash(subdir) + # preserve myid for better debuggability + return subdir_part + '@@' + my_id + return my_id + + def get_id(self) -> str: + return self.construct_id_from_path( + self.subdir, self.name, self.type_suffix()) + + def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None: + if 'build_by_default' in kwargs: + self.build_by_default = kwargs['build_by_default'] + if not isinstance(self.build_by_default, bool): + raise InvalidArguments('build_by_default must be a boolean value.') + elif kwargs.get('install', False): + # For backward compatibility, if build_by_default is not explicitly + # set, use the value of 'install' if it's enabled. + self.build_by_default = True + + self.set_option_overrides(self.parse_overrides(kwargs)) + + def set_option_overrides(self, option_overrides: T.Dict[OptionKey, str]) -> None: + self.options.overrides = {} + for k, v in option_overrides.items(): + if k.lang: + self.options.overrides[k.evolve(machine=self.for_machine)] = v + else: + self.options.overrides[k] = v + + def get_options(self) -> OptionOverrideProxy: + return self.options + + def get_option(self, key: 'OptionKey') -> T.Union[str, int, bool, 'WrapMode']: + # We don't actually have wrapmode here to do an assert, so just do a + # cast, we know what's in coredata anyway. + # TODO: if it's possible to annotate get_option or validate_option_value + # in the future we might be able to remove the cast here + return T.cast('T.Union[str, int, bool, WrapMode]', self.options[key].value) + + @staticmethod + def parse_overrides(kwargs: T.Dict[str, T.Any]) -> T.Dict[OptionKey, str]: + opts = kwargs.get('override_options', []) + + # In this case we have an already parsed and ready to go dictionary + # provided by typed_kwargs + if isinstance(opts, dict): + return T.cast('T.Dict[OptionKey, str]', opts) + + result: T.Dict[OptionKey, str] = {} + overrides = stringlistify(opts) + for o in overrides: + if '=' not in o: + raise InvalidArguments('Overrides must be of form "key=value"') + k, v = o.split('=', 1) + key = OptionKey.from_string(k.strip()) + v = v.strip() + result[key] = v + return result + + def is_linkable_target(self) -> bool: + return False + + def get_outputs(self) -> T.List[str]: + return [] + + def should_install(self) -> bool: + return False + +class BuildTarget(Target): + known_kwargs = known_build_target_kwargs + + install_dir: T.List[T.Union[str, Literal[False]]] + + # This set contains all the languages a linker can link natively + # without extra flags. For instance, nvcc (cuda) can link C++ + # without injecting -lc++/-lstdc++, see + # https://github.com/mesonbuild/meson/issues/10570 + _MASK_LANGS: T.FrozenSet[T.Tuple[str, str]] = frozenset([ + # (language, linker) + ('cpp', 'cuda'), + ]) + + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): + super().__init__(name, subdir, subproject, True, for_machine, environment, install=kwargs.get('install', False)) + self.all_compilers = compilers + self.compilers = OrderedDict() # type: OrderedDict[str, Compiler] + self.objects: T.List[ObjectTypes] = [] + self.structured_sources = structured_sources + self.external_deps: T.List[dependencies.Dependency] = [] + self.include_dirs: T.List['IncludeDirs'] = [] + self.link_language = kwargs.get('link_language') + self.link_targets: T.List[LibTypes] = [] + self.link_whole_targets: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]] = [] + self.link_depends = [] + self.added_deps = set() + self.name_prefix_set = False + self.name_suffix_set = False + self.filename = 'no_name' + # The list of all files outputted by this target. Useful in cases such + # as Vala which generates .vapi and .h besides the compiled output. + self.outputs = [self.filename] + self.pch: T.Dict[str, T.List[str]] = {} + self.extra_args: T.Dict[str, T.List['FileOrString']] = {} + self.sources: T.List[File] = [] + self.generated: T.List['GeneratedTypes'] = [] + self.extra_files: T.List[File] = [] + self.d_features = defaultdict(list) + self.pic = False + self.pie = False + # Track build_rpath entries so we can remove them at install time + self.rpath_dirs_to_remove: T.Set[bytes] = set() + self.process_sourcelist(sources) + # Objects can be: + # 1. Preexisting objects provided by the user with the `objects:` kwarg + # 2. Compiled objects created by and extracted from another target + self.process_objectlist(objects) + self.process_kwargs(kwargs) + self.missing_languages = self.process_compilers() + + # self.link_targets and self.link_whole_targets contains libraries from + # dependencies (see add_deps()). They have not been processed yet because + # we have to call process_compilers() first and we need to process libraries + # from link_with and link_whole first. + # See https://github.com/mesonbuild/meson/pull/11957#issuecomment-1629243208. + link_targets = extract_as_list(kwargs, 'link_with') + self.link_targets + link_whole_targets = extract_as_list(kwargs, 'link_whole') + self.link_whole_targets + self.link_targets.clear() + self.link_whole_targets.clear() + self.link(link_targets) + self.link_whole(link_whole_targets) + + if not any([self.sources, self.generated, self.objects, self.link_whole_targets, self.structured_sources, + kwargs.pop('_allow_no_sources', False)]): + mlog.warning(f'Build target {name} has no sources. ' + 'This was never supposed to be allowed but did because of a bug, ' + 'support will be removed in a future release of Meson') + self.check_unknown_kwargs(kwargs) + self.validate_install() + self.check_module_linking() + + def post_init(self) -> None: + ''' Initialisations and checks requiring the final list of compilers to be known + ''' + self.validate_sources() + if self.structured_sources and any([self.sources, self.generated]): + raise MesonException('cannot mix structured sources and unstructured sources') + if self.structured_sources and 'rust' not in self.compilers: + raise MesonException('structured sources are only supported in Rust targets') + if self.uses_rust(): + # relocation-model=pic is rustc's default and Meson does not + # currently have a way to disable PIC. + self.pic = True + if 'vala' in self.compilers and self.is_linkable_target(): + self.outputs += [self.vala_header, self.vala_vapi] + self.install_tag += ['devel', 'devel'] + if self.vala_gir: + self.outputs.append(self.vala_gir) + self.install_tag.append('devel') + + def __repr__(self): + repr_str = "<{0} {1}: {2}>" + return repr_str.format(self.__class__.__name__, self.get_id(), self.filename) + + def __str__(self): + return f"{self.name}" + + @property + def is_unity(self) -> bool: + unity_opt = self.get_option(OptionKey('unity')) + return unity_opt == 'on' or (unity_opt == 'subprojects' and self.subproject != '') + + def validate_install(self): + if self.for_machine is MachineChoice.BUILD and self.install: + if self.environment.is_cross_build(): + raise InvalidArguments('Tried to install a target for the build machine in a cross build.') + else: + mlog.warning('Installing target build for the build machine. This will fail in a cross build.') + + def check_unknown_kwargs(self, kwargs): + # Override this method in derived classes that have more + # keywords. + self.check_unknown_kwargs_int(kwargs, self.known_kwargs) + + def check_unknown_kwargs_int(self, kwargs, known_kwargs): + unknowns = [] + for k in kwargs: + if k not in known_kwargs: + unknowns.append(k) + if len(unknowns) > 0: + mlog.warning('Unknown keyword argument(s) in target {}: {}.'.format(self.name, ', '.join(unknowns))) + + def process_objectlist(self, objects): + assert isinstance(objects, list) + for s in objects: + if isinstance(s, (str, File, ExtractedObjects)): + self.objects.append(s) + elif isinstance(s, (CustomTarget, CustomTargetIndex, GeneratedList)): + non_objects = [o for o in s.get_outputs() if not is_object(o)] + if non_objects: + raise InvalidArguments(f'Generated file {non_objects[0]} in the \'objects\' kwarg is not an object.') + self.generated.append(s) + else: + raise InvalidArguments(f'Bad object of type {type(s).__name__!r} in target {self.name!r}.') + + def process_sourcelist(self, sources: T.List['SourceOutputs']) -> None: + """Split sources into generated and static sources. + + Sources can be: + 1. Preexisting source files in the source tree (static) + 2. Preexisting sources generated by configure_file in the build tree. + (static as they are only regenerated if meson itself is regenerated) + 3. Sources files generated by another target or a Generator (generated) + """ + added_sources: T.Set[File] = set() # If the same source is defined multiple times, use it only once. + for s in sources: + if isinstance(s, File): + if s not in added_sources: + self.sources.append(s) + added_sources.add(s) + elif isinstance(s, (CustomTarget, CustomTargetIndex, GeneratedList)): + self.generated.append(s) + + @staticmethod + def can_compile_remove_sources(compiler: 'Compiler', sources: T.List['FileOrString']) -> bool: + removed = False + for s in sources[:]: + if compiler.can_compile(s): + sources.remove(s) + removed = True + return removed + + def process_compilers_late(self): + """Processes additional compilers after kwargs have been evaluated. + + This can add extra compilers that might be required by keyword + arguments, such as link_with or dependencies. It will also try to guess + which compiler to use if one hasn't been selected already. + """ + for lang in self.missing_languages: + self.compilers[lang] = self.all_compilers[lang] + + # did user override clink_langs for this target? + link_langs = [self.link_language] if self.link_language else clink_langs + + # If this library is linked against another library we need to consider + # the languages of those libraries as well. + if self.link_targets or self.link_whole_targets: + for t in itertools.chain(self.link_targets, self.link_whole_targets): + if isinstance(t, (CustomTarget, CustomTargetIndex)): + continue # We can't know anything about these. + for name, compiler in t.compilers.items(): + if name in link_langs and name not in self.compilers: + self.compilers[name] = compiler + + if not self.compilers: + # No source files or parent targets, target consists of only object + # files of unknown origin. Just add the first clink compiler + # that we have and hope that it can link these objects + for lang in link_langs: + if lang in self.all_compilers: + self.compilers[lang] = self.all_compilers[lang] + break + + # Now that we have the final list of compilers we can sort it according + # to clink_langs and do sanity checks. + self.compilers = OrderedDict(sorted(self.compilers.items(), + key=lambda t: sort_clink(t[0]))) + self.post_init() + + def process_compilers(self) -> T.List[str]: + ''' + Populate self.compilers, which is the list of compilers that this + target will use for compiling all its sources. + We also add compilers that were used by extracted objects to simplify + dynamic linker determination. + Returns a list of missing languages that we can add implicitly, such as + C/C++ compiler for cython. + ''' + missing_languages: T.List[str] = [] + if not any([self.sources, self.generated, self.objects, self.structured_sources]): + return missing_languages + # Preexisting sources + sources: T.List['FileOrString'] = list(self.sources) + generated = self.generated.copy() + + if self.structured_sources: + for v in self.structured_sources.sources.values(): + for src in v: + if isinstance(src, (str, File)): + sources.append(src) + else: + generated.append(src) + + # All generated sources + for gensrc in generated: + for s in gensrc.get_outputs(): + # Generated objects can't be compiled, so don't use them for + # compiler detection. If our target only has generated objects, + # we will fall back to using the first c-like compiler we find, + # which is what we need. + if not is_object(s): + sources.append(s) + for d in self.external_deps: + for s in d.sources: + if isinstance(s, (str, File)): + sources.append(s) + + # Sources that were used to create our extracted objects + for o in self.objects: + if not isinstance(o, ExtractedObjects): + continue + compsrcs = o.classify_all_sources(o.srclist, []) + for comp in compsrcs: + # Don't add Vala sources since that will pull in the Vala + # compiler even though we will never use it since we are + # dealing with compiled C code. + if comp.language == 'vala': + continue + if comp.language not in self.compilers: + self.compilers[comp.language] = comp + if sources: + # For each source, try to add one compiler that can compile it. + # + # If it has a suffix that belongs to a known language, we must have + # a compiler for that language. + # + # Otherwise, it's ok if no compilers can compile it, because users + # are expected to be able to add arbitrary non-source files to the + # sources list + for s in sources: + for lang, compiler in self.all_compilers.items(): + if compiler.can_compile(s): + if lang not in self.compilers: + self.compilers[lang] = compiler + break + else: + if is_known_suffix(s): + path = pathlib.Path(str(s)).as_posix() + m = f'No {self.for_machine.get_lower_case_name()} machine compiler for {path!r}' + raise MesonException(m) + + # If all our sources are Vala, our target also needs the C compiler but + # it won't get added above. + if 'vala' in self.compilers and 'c' not in self.compilers: + self.compilers['c'] = self.all_compilers['c'] + if 'cython' in self.compilers: + key = OptionKey('language', machine=self.for_machine, lang='cython') + value = self.get_option(key) + + try: + self.compilers[value] = self.all_compilers[value] + except KeyError: + missing_languages.append(value) + + return missing_languages + + def validate_sources(self): + if len(self.compilers) > 1 and any(lang in self.compilers for lang in ['cs', 'java']): + langs = ', '.join(self.compilers.keys()) + raise InvalidArguments(f'Cannot mix those languages into a target: {langs}') + + def process_link_depends(self, sources): + """Process the link_depends keyword argument. + + This is designed to handle strings, Files, and the output of Custom + Targets. Notably it doesn't handle generator() returned objects, since + adding them as a link depends would inherently cause them to be + generated twice, since the output needs to be passed to the ld_args and + link_depends. + """ + sources = listify(sources) + for s in sources: + if isinstance(s, File): + self.link_depends.append(s) + elif isinstance(s, str): + self.link_depends.append( + File.from_source_file(self.environment.source_dir, self.subdir, s)) + elif hasattr(s, 'get_outputs'): + self.link_depends.append(s) + else: + raise InvalidArguments( + 'Link_depends arguments must be strings, Files, ' + 'or a Custom Target, or lists thereof.') + + def extract_objects(self, srclist: T.List[T.Union['FileOrString', 'GeneratedTypes']]) -> ExtractedObjects: + sources_set = set(self.sources) + generated_set = set(self.generated) + + obj_src: T.List['File'] = [] + obj_gen: T.List['GeneratedTypes'] = [] + for src in srclist: + if isinstance(src, (str, File)): + if isinstance(src, str): + src = File(False, self.subdir, src) + else: + FeatureNew.single_use('File argument for extract_objects', '0.50.0', self.subproject) + if src not in sources_set: + raise MesonException(f'Tried to extract unknown source {src}.') + obj_src.append(src) + elif isinstance(src, (CustomTarget, CustomTargetIndex, GeneratedList)): + FeatureNew.single_use('Generated sources for extract_objects', '0.61.0', self.subproject) + target = src.target if isinstance(src, CustomTargetIndex) else src + if src not in generated_set and target not in generated_set: + raise MesonException(f'Tried to extract unknown source {target.get_basename()}.') + obj_gen.append(src) + else: + raise MesonException(f'Object extraction arguments must be strings, Files or targets (got {type(src).__name__}).') + return ExtractedObjects(self, obj_src, obj_gen) + + def extract_all_objects(self, recursive: bool = True) -> ExtractedObjects: + return ExtractedObjects(self, self.sources, self.generated, self.objects, + recursive, pch=True) + + def get_all_link_deps(self) -> ImmutableListProtocol[BuildTargetTypes]: + return self.get_transitive_link_deps() + + @lru_cache(maxsize=None) + def get_transitive_link_deps(self) -> ImmutableListProtocol[BuildTargetTypes]: + result: T.List[Target] = [] + for i in self.link_targets: + result += i.get_all_link_deps() + return result + + def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: + return self.get_transitive_link_deps_mapping(prefix) + + @lru_cache(maxsize=None) + def get_transitive_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: + result: T.Dict[str, str] = {} + for i in self.link_targets: + mapping = i.get_link_deps_mapping(prefix) + #we are merging two dictionaries, while keeping the earlier one dominant + result_tmp = mapping.copy() + result_tmp.update(result) + result = result_tmp + return result + + @lru_cache(maxsize=None) + def get_link_dep_subdirs(self) -> T.AbstractSet[str]: + result: OrderedSet[str] = OrderedSet() + for i in self.link_targets: + if not isinstance(i, StaticLibrary): + result.add(i.get_subdir()) + result.update(i.get_link_dep_subdirs()) + return result + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return self.environment.get_libdir(), '{libdir}' + + def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: + return self.install_dir + + def get_custom_install_mode(self) -> T.Optional['FileMode']: + return self.install_mode + + def process_kwargs(self, kwargs): + self.process_kwargs_base(kwargs) + self.original_kwargs = kwargs + + for lang in all_languages: + lang_args = extract_as_list(kwargs, f'{lang}_args') + self.add_compiler_args(lang, lang_args) + + self.add_pch('c', extract_as_list(kwargs, 'c_pch')) + self.add_pch('cpp', extract_as_list(kwargs, 'cpp_pch')) + + if not isinstance(self, Executable) or kwargs.get('export_dynamic', False): + self.vala_header = kwargs.get('vala_header', self.name + '.h') + self.vala_vapi = kwargs.get('vala_vapi', self.name + '.vapi') + self.vala_gir = kwargs.get('vala_gir', None) + + dfeatures = defaultdict(list) + dfeature_unittest = kwargs.get('d_unittest', False) + if dfeature_unittest: + dfeatures['unittest'] = dfeature_unittest + dfeature_versions = kwargs.get('d_module_versions', []) + if dfeature_versions: + dfeatures['versions'] = dfeature_versions + dfeature_debug = kwargs.get('d_debug', []) + if dfeature_debug: + dfeatures['debug'] = dfeature_debug + if 'd_import_dirs' in kwargs: + dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs') + for d in dfeature_import_dirs: + if not isinstance(d, IncludeDirs): + raise InvalidArguments('Arguments to d_import_dirs must be include_directories.') + dfeatures['import_dirs'] = dfeature_import_dirs + if dfeatures: + self.d_features = dfeatures + + self.link_args = extract_as_list(kwargs, 'link_args') + for i in self.link_args: + if not isinstance(i, str): + raise InvalidArguments('Link_args arguments must be strings.') + for l in self.link_args: + if '-Wl,-rpath' in l or l.startswith('-rpath'): + mlog.warning(textwrap.dedent('''\ + Please do not define rpath with a linker argument, use install_rpath + or build_rpath properties instead. + This will become a hard error in a future Meson release. + ''')) + self.process_link_depends(kwargs.get('link_depends', [])) + # Target-specific include dirs must be added BEFORE include dirs from + # internal deps (added inside self.add_deps()) to override them. + inclist = extract_as_list(kwargs, 'include_directories') + self.add_include_dirs(inclist) + # Add dependencies (which also have include_directories) + deplist = extract_as_list(kwargs, 'dependencies') + self.add_deps(deplist) + # If an item in this list is False, the output corresponding to + # the list index of that item will not be installed + self.install_dir = typeslistify(kwargs.get('install_dir', []), + (str, bool)) + self.install_mode = kwargs.get('install_mode', None) + self.install_tag = stringlistify(kwargs.get('install_tag', [None])) + main_class = kwargs.get('main_class', '') + if not isinstance(main_class, str): + raise InvalidArguments('Main class must be a string') + self.main_class = main_class + if isinstance(self, Executable): + # This kwarg is deprecated. The value of "none" means that the kwarg + # was not specified and win_subsystem should be used instead. + self.gui_app = None + if 'gui_app' in kwargs: + if 'win_subsystem' in kwargs: + raise InvalidArguments('Can specify only gui_app or win_subsystem for a target, not both.') + self.gui_app = kwargs['gui_app'] + if not isinstance(self.gui_app, bool): + raise InvalidArguments('Argument gui_app must be boolean.') + self.win_subsystem = self.validate_win_subsystem(kwargs.get('win_subsystem', 'console')) + elif 'gui_app' in kwargs: + raise InvalidArguments('Argument gui_app can only be used on executables.') + elif 'win_subsystem' in kwargs: + raise InvalidArguments('Argument win_subsystem can only be used on executables.') + extra_files = extract_as_list(kwargs, 'extra_files') + for i in extra_files: + assert isinstance(i, File) + if i in self.extra_files: + continue + trial = os.path.join(self.environment.get_source_dir(), i.subdir, i.fname) + if not os.path.isfile(trial): + raise InvalidArguments(f'Tried to add non-existing extra file {i}.') + self.extra_files.append(i) + self.install_rpath: str = kwargs.get('install_rpath', '') + if not isinstance(self.install_rpath, str): + raise InvalidArguments('Install_rpath is not a string.') + self.build_rpath = kwargs.get('build_rpath', '') + if not isinstance(self.build_rpath, str): + raise InvalidArguments('Build_rpath is not a string.') + resources = extract_as_list(kwargs, 'resources') + for r in resources: + if not isinstance(r, str): + raise InvalidArguments('Resource argument is not a string.') + trial = os.path.join(self.environment.get_source_dir(), self.subdir, r) + if not os.path.isfile(trial): + raise InvalidArguments(f'Tried to add non-existing resource {r}.') + self.resources = resources + if 'name_prefix' in kwargs: + name_prefix = kwargs['name_prefix'] + if isinstance(name_prefix, list): + if name_prefix: + raise InvalidArguments('name_prefix array must be empty to signify default.') + else: + if not isinstance(name_prefix, str): + raise InvalidArguments('name_prefix must be a string.') + self.prefix = name_prefix + self.name_prefix_set = True + if 'name_suffix' in kwargs: + name_suffix = kwargs['name_suffix'] + if isinstance(name_suffix, list): + if name_suffix: + raise InvalidArguments('name_suffix array must be empty to signify default.') + else: + if not isinstance(name_suffix, str): + raise InvalidArguments('name_suffix must be a string.') + if name_suffix == '': + raise InvalidArguments('name_suffix should not be an empty string. ' + 'If you want meson to use the default behaviour ' + 'for each platform pass `[]` (empty array)') + self.suffix = name_suffix + self.name_suffix_set = True + if isinstance(self, StaticLibrary): + # You can't disable PIC on OS X. The compiler ignores -fno-PIC. + # PIC is always on for Windows (all code is position-independent + # since library loading is done differently) + m = self.environment.machines[self.for_machine] + if m.is_darwin() or m.is_windows(): + self.pic = True + else: + self.pic = self._extract_pic_pie(kwargs, 'pic', 'b_staticpic') + if isinstance(self, Executable) or (isinstance(self, StaticLibrary) and not self.pic): + # Executables must be PIE on Android + if self.environment.machines[self.for_machine].is_android(): + self.pie = True + else: + self.pie = self._extract_pic_pie(kwargs, 'pie', 'b_pie') + self.implicit_include_directories = kwargs.get('implicit_include_directories', True) + if not isinstance(self.implicit_include_directories, bool): + raise InvalidArguments('Implicit_include_directories must be a boolean.') + self.gnu_symbol_visibility = kwargs.get('gnu_symbol_visibility', '') + if not isinstance(self.gnu_symbol_visibility, str): + raise InvalidArguments('GNU symbol visibility must be a string.') + if self.gnu_symbol_visibility != '': + permitted = ['default', 'internal', 'hidden', 'protected', 'inlineshidden'] + if self.gnu_symbol_visibility not in permitted: + raise InvalidArguments('GNU symbol visibility arg {} not one of: {}'.format(self.gnu_symbol_visibility, ', '.join(permitted))) + + rust_dependency_map = kwargs.get('rust_dependency_map', {}) + if not isinstance(rust_dependency_map, dict): + raise InvalidArguments(f'Invalid rust_dependency_map "{rust_dependency_map}": must be a dictionary.') + if any(not isinstance(v, str) for v in rust_dependency_map.values()): + raise InvalidArguments(f'Invalid rust_dependency_map "{rust_dependency_map}": must be a dictionary with string values.') + self.rust_dependency_map = rust_dependency_map + + def validate_win_subsystem(self, value: str) -> str: + value = value.lower() + if re.fullmatch(r'(boot_application|console|efi_application|efi_boot_service_driver|efi_rom|efi_runtime_driver|native|posix|windows)(,\d+(\.\d+)?)?', value) is None: + raise InvalidArguments(f'Invalid value for win_subsystem: {value}.') + return value + + def _extract_pic_pie(self, kwargs, arg: str, option: str): + # Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags + all_flags = self.extra_args['c'] + self.extra_args['cpp'] + if '-f' + arg.lower() in all_flags or '-f' + arg.upper() in all_flags: + mlog.warning(f"Use the '{arg}' kwarg instead of passing '-f{arg}' manually to {self.name!r}") + return True + + k = OptionKey(option) + if arg in kwargs: + val = kwargs[arg] + elif k in self.environment.coredata.options: + val = self.environment.coredata.options[k].value + else: + val = False + + if not isinstance(val, bool): + raise InvalidArguments(f'Argument {arg} to {self.name!r} must be boolean') + return val + + def get_filename(self) -> str: + return self.filename + + def get_outputs(self) -> T.List[str]: + return self.outputs + + def get_extra_args(self, language): + return self.extra_args.get(language, []) + + @lru_cache(maxsize=None) + def get_dependencies(self) -> OrderedSet[Target]: + # Get all targets needed for linking. This includes all link_with and + # link_whole targets, and also all dependencies of static libraries + # recursively. The algorithm here is closely related to what we do in + # get_internal_static_libraries(): Installed static libraries include + # objects from all their dependencies already. + result: OrderedSet[Target] = OrderedSet() + for t in itertools.chain(self.link_targets, self.link_whole_targets): + if t not in result: + result.add(t) + if isinstance(t, StaticLibrary): + t.get_dependencies_recurse(result) + return result + + def get_dependencies_recurse(self, result: OrderedSet[Target], include_internals: bool = True) -> None: + # self is always a static library because we don't need to pull dependencies + # of shared libraries. If self is installed (not internal) it already + # include objects extracted from all its internal dependencies so we can + # skip them. + include_internals = include_internals and self.is_internal() + for t in self.link_targets: + if t in result: + continue + if include_internals or not t.is_internal(): + result.add(t) + if isinstance(t, StaticLibrary): + t.get_dependencies_recurse(result, include_internals) + for t in self.link_whole_targets: + t.get_dependencies_recurse(result, include_internals) + + def get_source_subdir(self): + return self.subdir + + def get_sources(self): + return self.sources + + def get_objects(self) -> T.List[T.Union[str, 'File', 'ExtractedObjects']]: + return self.objects + + def get_generated_sources(self) -> T.List['GeneratedTypes']: + return self.generated + + def should_install(self) -> bool: + return self.install + + def has_pch(self) -> bool: + return bool(self.pch) + + def get_pch(self, language: str) -> T.List[str]: + return self.pch.get(language, []) + + def get_include_dirs(self) -> T.List['IncludeDirs']: + return self.include_dirs + + def add_deps(self, deps): + deps = listify(deps) + for dep in deps: + if dep in self.added_deps: + continue + + if isinstance(dep, dependencies.InternalDependency): + # Those parts that are internal. + self.process_sourcelist(dep.sources) + self.extra_files.extend(f for f in dep.extra_files if f not in self.extra_files) + self.add_include_dirs(dep.include_directories, dep.get_include_type()) + self.objects.extend(dep.objects) + self.link_targets.extend(dep.libraries) + self.link_whole_targets.extend(dep.whole_libraries) + if dep.get_compile_args() or dep.get_link_args(): + # Those parts that are external. + extpart = dependencies.InternalDependency('undefined', + [], + dep.get_compile_args(), + dep.get_link_args(), + [], [], [], [], [], {}, [], [], []) + self.external_deps.append(extpart) + # Deps of deps. + self.add_deps(dep.ext_deps) + elif isinstance(dep, dependencies.Dependency): + if dep not in self.external_deps: + self.external_deps.append(dep) + self.process_sourcelist(dep.get_sources()) + self.add_deps(dep.ext_deps) + elif isinstance(dep, BuildTarget): + raise InvalidArguments('''Tried to use a build target as a dependency. +You probably should put it in link_with instead.''') + else: + # This is a bit of a hack. We do not want Build to know anything + # about the interpreter so we can't import it and use isinstance. + # This should be reliable enough. + if hasattr(dep, 'held_object'): + # FIXME: subproject is not a real ObjectHolder so we have to do this by hand + dep = dep.held_object + if hasattr(dep, 'project_args_frozen') or hasattr(dep, 'global_args_frozen'): + raise InvalidArguments('Tried to use subproject object as a dependency.\n' + 'You probably wanted to use a dependency declared in it instead.\n' + 'Access it by calling get_variable() on the subproject object.') + raise InvalidArguments(f'Argument is of an unacceptable type {type(dep).__name__!r}.\nMust be ' + 'either an external dependency (returned by find_library() or ' + 'dependency()) or an internal dependency (returned by ' + 'declare_dependency()).') + + dep_d_features = dep.d_features + + for feature in ('versions', 'import_dirs'): + if feature in dep_d_features: + self.d_features[feature].extend(dep_d_features[feature]) + + self.added_deps.add(dep) + + def get_external_deps(self) -> T.List[dependencies.Dependency]: + return self.external_deps + + def is_internal(self) -> bool: + return False + + def link(self, targets): + for t in targets: + if not isinstance(t, (Target, CustomTargetIndex)): + if isinstance(t, dependencies.ExternalLibrary): + raise MesonException(textwrap.dedent('''\ + An external library was used in link_with keyword argument, which + is reserved for libraries built as part of this project. External + libraries must be passed using the dependencies keyword argument + instead, because they are conceptually "external dependencies", + just like those detected with the dependency() function. + ''')) + raise InvalidArguments(f'{t!r} is not a target.') + if not t.is_linkable_target(): + raise InvalidArguments(f"Link target '{t!s}' is not linkable.") + if isinstance(self, StaticLibrary) and self.install and t.is_internal(): + # When we're a static library and we link_with to an + # internal/convenience library, promote to link_whole. + self.link_whole([t], promoted=True) + continue + if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic: + msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " + msg += "Use the 'pic' option to static_library to build with PIC." + raise InvalidArguments(msg) + if self.for_machine is not t.for_machine: + msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' + if self.environment.is_cross_build(): + raise InvalidArguments(msg + ' This is not possible in a cross build.') + else: + mlog.warning(msg + ' This will fail in cross build.') + self.link_targets.append(t) + + def link_whole(self, targets, promoted: bool = False): + for t in targets: + if isinstance(t, (CustomTarget, CustomTargetIndex)): + if not t.is_linkable_target(): + raise InvalidArguments(f'Custom target {t!r} is not linkable.') + if t.links_dynamically(): + raise InvalidArguments('Can only link_whole custom targets that are static archives.') + elif not isinstance(t, StaticLibrary): + raise InvalidArguments(f'{t!r} is not a static library.') + elif isinstance(self, SharedLibrary) and not t.pic: + msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " + msg += "Use the 'pic' option to static_library to build with PIC." + raise InvalidArguments(msg) + if self.for_machine is not t.for_machine: + msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' + if self.environment.is_cross_build(): + raise InvalidArguments(msg + ' This is not possible in a cross build.') + else: + mlog.warning(msg + ' This will fail in cross build.') + if isinstance(self, StaticLibrary) and not self.uses_rust(): + # When we're a static library and we link_whole: to another static + # library, we need to add that target's objects to ourselves. + self.check_can_extract_objects(t, origin=self, promoted=promoted) + self.objects += [t.extract_all_objects()] + # If we install this static library we also need to include objects + # from all uninstalled static libraries it depends on. + if self.install: + for lib in t.get_internal_static_libraries(origin=self): + self.objects += [lib.extract_all_objects()] + self.link_whole_targets.append(t) + + @lru_cache(maxsize=None) + def get_internal_static_libraries(self, origin: StaticLibrary) -> OrderedSet[Target]: + result: OrderedSet[Target] = OrderedSet() + self.get_internal_static_libraries_recurse(result, origin) + return result + + def get_internal_static_libraries_recurse(self, result: OrderedSet[Target], origin: StaticLibrary) -> None: + for t in self.link_targets: + if t.is_internal() and t not in result: + self.check_can_extract_objects(t, origin, promoted=True) + result.add(t) + t.get_internal_static_libraries_recurse(result, origin) + for t in self.link_whole_targets: + if t.is_internal(): + t.get_internal_static_libraries_recurse(result, origin) + + def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origin: StaticLibrary, promoted: bool = False) -> None: + if isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): + # To extract objects from a custom target we would have to extract + # the archive, WIP implementation can be found in + # https://github.com/mesonbuild/meson/pull/9218. + # For Rust C ABI we could in theory have access to objects, but there + # are several meson issues that need to be fixed: + # https://github.com/mesonbuild/meson/issues/10722 + # https://github.com/mesonbuild/meson/issues/10723 + # https://github.com/mesonbuild/meson/issues/10724 + m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {origin.name!r}. ' + 'Instead, pass individual object files with the "objects:" keyword argument if possible.') + if promoted: + m += (f' Meson had to promote link to link_whole because {origin.name!r} is installed but not {t.name!r},' + f' and thus has to include objects from {t.name!r} to be usable.') + raise InvalidArguments(m) + + def add_pch(self, language: str, pchlist: T.List[str]) -> None: + if not pchlist: + return + elif len(pchlist) == 1: + if not environment.is_header(pchlist[0]): + raise InvalidArguments(f'PCH argument {pchlist[0]} is not a header.') + elif len(pchlist) == 2: + if environment.is_header(pchlist[0]): + if not environment.is_source(pchlist[1]): + raise InvalidArguments('PCH definition must contain one header and at most one source.') + elif environment.is_source(pchlist[0]): + if not environment.is_header(pchlist[1]): + raise InvalidArguments('PCH definition must contain one header and at most one source.') + pchlist = [pchlist[1], pchlist[0]] + else: + raise InvalidArguments(f'PCH argument {pchlist[0]} is of unknown type.') + + if os.path.dirname(pchlist[0]) != os.path.dirname(pchlist[1]): + raise InvalidArguments('PCH files must be stored in the same folder.') + + FeatureDeprecated.single_use('PCH source files', '0.50.0', self.subproject, + 'Only a single header file should be used.') + elif len(pchlist) > 2: + raise InvalidArguments('PCH definition may have a maximum of 2 files.') + for f in pchlist: + if not isinstance(f, str): + raise MesonException('PCH arguments must be strings.') + if not os.path.isfile(os.path.join(self.environment.source_dir, self.subdir, f)): + raise MesonException(f'File {f} does not exist.') + self.pch[language] = pchlist + + def add_include_dirs(self, args: T.Sequence['IncludeDirs'], set_is_system: T.Optional[str] = None) -> None: + ids: T.List['IncludeDirs'] = [] + for a in args: + if not isinstance(a, IncludeDirs): + raise InvalidArguments('Include directory to be added is not an include directory object.') + ids.append(a) + if set_is_system is None: + set_is_system = 'preserve' + if set_is_system != 'preserve': + is_system = set_is_system == 'system' + ids = [IncludeDirs(x.get_curdir(), x.get_incdirs(), is_system, x.get_extra_build_dirs()) for x in ids] + self.include_dirs += ids + + def add_compiler_args(self, language: str, args: T.List['FileOrString']) -> None: + args = listify(args) + for a in args: + if not isinstance(a, (str, File)): + raise InvalidArguments('A non-string passed to compiler args.') + if language in self.extra_args: + self.extra_args[language] += args + else: + self.extra_args[language] = args + + def get_aliases(self) -> T.List[T.Tuple[str, str, str]]: + return [] + + def get_langs_used_by_deps(self) -> T.List[str]: + ''' + Sometimes you want to link to a C++ library that exports C API, which + means the linker must link in the C++ stdlib, and we must use a C++ + compiler for linking. The same is also applicable for objc/objc++, etc, + so we can keep using clink_langs for the priority order. + + See: https://github.com/mesonbuild/meson/issues/1653 + ''' + langs = [] # type: T.List[str] + + # Check if any of the external libraries were written in this language + for dep in self.external_deps: + if dep.language is None: + continue + if dep.language not in langs: + langs.append(dep.language) + # Check if any of the internal libraries this target links to were + # written in this language + for link_target in itertools.chain(self.link_targets, self.link_whole_targets): + if isinstance(link_target, (CustomTarget, CustomTargetIndex)): + continue + for language in link_target.compilers: + if language not in langs: + langs.append(language) + + return langs + + def get_prelinker(self): + if self.link_language: + comp = self.all_compilers[self.link_language] + return comp + for l in clink_langs: + if l in self.compilers: + try: + prelinker = self.all_compilers[l] + except KeyError: + raise MesonException( + f'Could not get a prelinker linker for build target {self.name!r}. ' + f'Requires a compiler for language "{l}", but that is not ' + 'a project language.') + return prelinker + raise MesonException(f'Could not determine prelinker for {self.name!r}.') + + def get_clink_dynamic_linker_and_stdlibs(self) -> T.Tuple['Compiler', T.List[str]]: + ''' + We use the order of languages in `clink_langs` to determine which + linker to use in case the target has sources compiled with multiple + compilers. All languages other than those in this list have their own + linker. + Note that Vala outputs C code, so Vala sources can use any linker + that can link compiled C. We don't actually need to add an exception + for Vala here because of that. + ''' + # If the user set the link_language, just return that. + if self.link_language: + comp = self.all_compilers[self.link_language] + return comp, comp.language_stdlib_only_link_flags(self.environment) + + # Since dependencies could come from subprojects, they could have + # languages we don't have in self.all_compilers. Use the global list of + # all compilers here. + all_compilers = self.environment.coredata.compilers[self.for_machine] + + # Languages used by dependencies + dep_langs = self.get_langs_used_by_deps() + + # Pick a compiler based on the language priority-order + for l in clink_langs: + if l in self.compilers or l in dep_langs: + try: + linker = all_compilers[l] + except KeyError: + raise MesonException( + f'Could not get a dynamic linker for build target {self.name!r}. ' + f'Requires a linker for language "{l}", but that is not ' + 'a project language.') + stdlib_args: T.List[str] = self.get_used_stdlib_args(linker.language) + # Type of var 'linker' is Compiler. + # Pretty hard to fix because the return value is passed everywhere + return linker, stdlib_args + + # None of our compilers can do clink, this happens for example if the + # target only has ASM sources. Pick the first capable compiler. + for l in clink_langs: + try: + comp = self.all_compilers[l] + return comp, comp.language_stdlib_only_link_flags(self.environment) + except KeyError: + pass + + raise AssertionError(f'Could not get a dynamic linker for build target {self.name!r}') + + def get_used_stdlib_args(self, link_language: str) -> T.List[str]: + all_compilers = self.environment.coredata.compilers[self.for_machine] + all_langs = set(self.compilers).union(self.get_langs_used_by_deps()) + stdlib_args: T.List[str] = [] + for dl in all_langs: + if dl != link_language and (dl, link_language) not in self._MASK_LANGS: + # We need to use all_compilers here because + # get_langs_used_by_deps could return a language from a + # subproject + stdlib_args.extend(all_compilers[dl].language_stdlib_only_link_flags(self.environment)) + return stdlib_args + + def uses_rust(self) -> bool: + return 'rust' in self.compilers + + def uses_fortran(self) -> bool: + return 'fortran' in self.compilers + + def get_using_msvc(self) -> bool: + ''' + Check if the dynamic linker is MSVC. Used by Executable, StaticLibrary, + and SharedLibrary for deciding when to use MSVC-specific file naming + and debug filenames. + + If at least some code is built with MSVC and the final library is + linked with MSVC, we can be sure that some debug info will be + generated. We only check the dynamic linker here because the static + linker is guaranteed to be of the same type. + + Interesting cases: + 1. The Vala compiler outputs C code to be compiled by whatever + C compiler we're using, so all objects will still be created by the + MSVC compiler. + 2. If the target contains only objects, process_compilers guesses and + picks the first compiler that smells right. + ''' + # Rustc can use msvc style linkers + if self.uses_rust(): + compiler = self.all_compilers['rust'] + else: + compiler, _ = self.get_clink_dynamic_linker_and_stdlibs() + # Mixing many languages with MSVC is not supported yet so ignore stdlibs. + return compiler and compiler.get_linker_id() in {'link', 'lld-link', 'xilink', 'optlink'} + + def check_module_linking(self): + ''' + Warn if shared modules are linked with target: (link_with) #2865 + ''' + for link_target in self.link_targets: + if isinstance(link_target, SharedModule) and not link_target.force_soname: + if self.environment.machines[self.for_machine].is_darwin(): + raise MesonException( + f'target {self.name} links against shared module {link_target.name}. This is not permitted on OSX') + elif self.environment.machines[self.for_machine].is_android() and isinstance(self, SharedModule): + # Android requires shared modules that use symbols from other shared modules to + # be linked before they can be dlopen()ed in the correct order. Not doing so + # leads to a missing symbol error: https://github.com/android/ndk/issues/201 + link_target.force_soname = True + else: + mlog.deprecation(f'target {self.name} links against shared module {link_target.name}, which is incorrect.' + '\n ' + f'This will be an error in the future, so please use shared_library() for {link_target.name} instead.' + '\n ' + f'If shared_module() was used for {link_target.name} because it has references to undefined symbols,' + '\n ' + 'use shared_library() with `override_options: [\'b_lundef=false\']` instead.') + link_target.force_soname = True + +class FileInTargetPrivateDir: + """Represents a file with the path '/path/to/build/target_private_dir/fname'. + target_private_dir is the return value of get_target_private_dir which is e.g. 'subdir/target.p'. + """ + + def __init__(self, fname: str): + self.fname = fname + + def __str__(self) -> str: + return self.fname + +class FileMaybeInTargetPrivateDir: + """Union between 'File' and 'FileInTargetPrivateDir'""" + + def __init__(self, inner: T.Union[File, FileInTargetPrivateDir]): + self.inner = inner + + @property + def fname(self) -> str: + return self.inner.fname + + def rel_to_builddir(self, build_to_src: str, target_private_dir: str) -> str: + if isinstance(self.inner, FileInTargetPrivateDir): + return os.path.join(target_private_dir, self.inner.fname) + return self.inner.rel_to_builddir(build_to_src) + + def absolute_path(self, srcdir: str, builddir: str) -> str: + if isinstance(self.inner, FileInTargetPrivateDir): + raise RuntimeError('Unreachable code') + return self.inner.absolute_path(srcdir, builddir) + + def __str__(self) -> str: + return self.fname + +class Generator(HoldableObject): + def __init__(self, exe: T.Union['Executable', programs.ExternalProgram], + arguments: T.List[str], + output: T.List[str], + # how2dataclass + *, + depfile: T.Optional[str] = None, + capture: bool = False, + depends: T.Optional[T.List[T.Union[BuildTarget, 'CustomTarget']]] = None, + name: str = 'Generator'): + self.exe = exe + self.depfile = depfile + self.capture = capture + self.depends: T.List[T.Union[BuildTarget, 'CustomTarget']] = depends or [] + self.arglist = arguments + self.outputs = output + self.name = name + + def __repr__(self) -> str: + repr_str = "<{0}: {1}>" + return repr_str.format(self.__class__.__name__, self.exe) + + def get_exe(self) -> T.Union['Executable', programs.ExternalProgram]: + return self.exe + + def get_base_outnames(self, inname: str) -> T.List[str]: + plainname = os.path.basename(inname) + basename = os.path.splitext(plainname)[0] + bases = [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs] + return bases + + def get_dep_outname(self, inname: str) -> T.List[str]: + if self.depfile is None: + raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.') + plainname = os.path.basename(inname) + basename = os.path.splitext(plainname)[0] + return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) + + def get_arglist(self, inname: str) -> T.List[str]: + plainname = os.path.basename(inname) + basename = os.path.splitext(plainname)[0] + return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist] + + @staticmethod + def is_parent_path(parent: str, trial: str) -> bool: + relpath = pathlib.PurePath(trial).relative_to(parent) + return relpath.parts[0] != '..' # For subdirs we can only go "down". + + def process_files(self, files: T.Iterable[T.Union[str, File, 'CustomTarget', 'CustomTargetIndex', 'GeneratedList']], + state: T.Union['Interpreter', 'ModuleState'], + preserve_path_from: T.Optional[str] = None, + extra_args: T.Optional[T.List[str]] = None) -> 'GeneratedList': + output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args if extra_args is not None else []) + + for e in files: + if isinstance(e, CustomTarget): + output.depends.add(e) + if isinstance(e, CustomTargetIndex): + output.depends.add(e.target) + if isinstance(e, (CustomTarget, CustomTargetIndex)): + output.depends.add(e) + fs = [File.from_built_file(state.subdir, f) for f in e.get_outputs()] + elif isinstance(e, GeneratedList): + if preserve_path_from: + raise InvalidArguments("generator.process: 'preserve_path_from' is not allowed if one input is a 'generated_list'.") + output.depends.add(e) + fs = [FileInTargetPrivateDir(f) for f in e.get_outputs()] + elif isinstance(e, str): + fs = [File.from_source_file(state.environment.source_dir, state.subdir, e)] + else: + fs = [e] + + for f in fs: + if preserve_path_from: + abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir) + if not self.is_parent_path(preserve_path_from, abs_f): + raise InvalidArguments('generator.process: When using preserve_path_from, all input files must be in a subdirectory of the given dir.') + f = FileMaybeInTargetPrivateDir(f) + output.add_file(f, state) + return output + + +@dataclass(eq=False) +class GeneratedList(HoldableObject): + + """The output of generator.process.""" + + generator: Generator + subdir: str + preserve_path_from: T.Optional[str] + extra_args: T.List[str] + + def __post_init__(self) -> None: + self.name = self.generator.exe + self.depends: T.Set[GeneratedTypes] = set() + self.infilelist: T.List[FileMaybeInTargetPrivateDir] = [] + self.outfilelist: T.List[str] = [] + self.outmap: T.Dict[FileMaybeInTargetPrivateDir, T.List[str]] = {} + self.extra_depends = [] # XXX: Doesn't seem to be used? + self.depend_files: T.List[File] = [] + + if self.extra_args is None: + self.extra_args: T.List[str] = [] + + if isinstance(self.generator.exe, programs.ExternalProgram): + if not self.generator.exe.found(): + raise InvalidArguments('Tried to use not-found external program as generator') + path = self.generator.exe.get_path() + if os.path.isabs(path): + # Can only add a dependency on an external program which we + # know the absolute path of + self.depend_files.append(File.from_absolute_file(path)) + + def add_preserved_path_segment(self, infile: FileMaybeInTargetPrivateDir, outfiles: T.List[str], state: T.Union['Interpreter', 'ModuleState']) -> T.List[str]: + result: T.List[str] = [] + in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir) + assert os.path.isabs(self.preserve_path_from) + rel = os.path.relpath(in_abs, self.preserve_path_from) + path_segment = os.path.dirname(rel) + for of in outfiles: + result.append(os.path.join(path_segment, of)) + return result + + def add_file(self, newfile: FileMaybeInTargetPrivateDir, state: T.Union['Interpreter', 'ModuleState']) -> None: + self.infilelist.append(newfile) + outfiles = self.generator.get_base_outnames(newfile.fname) + if self.preserve_path_from: + outfiles = self.add_preserved_path_segment(newfile, outfiles, state) + self.outfilelist += outfiles + self.outmap[newfile] = outfiles + + def get_inputs(self) -> T.List[FileMaybeInTargetPrivateDir]: + return self.infilelist + + def get_outputs(self) -> T.List[str]: + return self.outfilelist + + def get_outputs_for(self, filename: FileMaybeInTargetPrivateDir) -> T.List[str]: + return self.outmap[filename] + + def get_generator(self) -> 'Generator': + return self.generator + + def get_extra_args(self) -> T.List[str]: + return self.extra_args + + def get_subdir(self) -> str: + return self.subdir + + +class Executable(BuildTarget): + known_kwargs = known_exe_kwargs + + typename = 'executable' + + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): + key = OptionKey('b_pie') + if 'pie' not in kwargs and key in environment.coredata.options: + kwargs['pie'] = environment.coredata.options[key].value + super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, + environment, compilers, kwargs) + # Check for export_dynamic + self.export_dynamic = kwargs.get('export_dynamic', False) + if not isinstance(self.export_dynamic, bool): + raise InvalidArguments('"export_dynamic" keyword argument must be a boolean') + self.implib = kwargs.get('implib') + if not isinstance(self.implib, (bool, str, type(None))): + raise InvalidArguments('"export_dynamic" keyword argument must be a boolean or string') + if self.implib: + self.export_dynamic = True + if self.export_dynamic and self.implib is False: + raise InvalidArguments('"implib" keyword argument must not be false for if "export_dynamic" is true') + # Only linkwithable if using export_dynamic + self.is_linkwithable = self.export_dynamic + # Remember that this exe was returned by `find_program()` through an override + self.was_returned_by_find_program = False + + def post_init(self) -> None: + super().post_init() + machine = self.environment.machines[self.for_machine] + # Unless overridden, executables have no suffix or prefix. Except on + # Windows and with C#/Mono executables where the suffix is 'exe' + if not hasattr(self, 'prefix'): + self.prefix = '' + if not hasattr(self, 'suffix'): + # Executable for Windows or C#/Mono + if machine.is_windows() or machine.is_cygwin() or 'cs' in self.compilers: + self.suffix = 'exe' + elif machine.system.startswith('wasm') or machine.system == 'emscripten': + self.suffix = 'js' + elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('armclang') or + 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('armclang')): + self.suffix = 'axf' + elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('ccrx') or + 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('ccrx')): + self.suffix = 'abs' + elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('xc16')): + self.suffix = 'elf' + elif ('c' in self.compilers and self.compilers['c'].get_id() in {'ti', 'c2000'} or + 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'ti', 'c2000'}): + self.suffix = 'out' + elif ('c' in self.compilers and self.compilers['c'].get_id() in {'mwccarm', 'mwcceppc'} or + 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'mwccarm', 'mwcceppc'}): + self.suffix = 'nef' + else: + self.suffix = machine.get_exe_suffix() + self.filename = self.name + if self.suffix: + self.filename += '.' + self.suffix + self.outputs[0] = self.filename + + # The import library this target will generate + self.import_filename = None + # The import library that Visual Studio would generate (and accept) + self.vs_import_filename = None + # The import library that GCC would generate (and prefer) + self.gcc_import_filename = None + # The debugging information file this target will generate + self.debug_filename = None + + # If using export_dynamic, set the import library name + if self.export_dynamic: + implib_basename = self.name + '.exe' + if isinstance(self.implib, str): + implib_basename = self.implib + if machine.is_windows() or machine.is_cygwin(): + self.vs_import_filename = f'{implib_basename}.lib' + self.gcc_import_filename = f'lib{implib_basename}.a' + if self.get_using_msvc(): + self.import_filename = self.vs_import_filename + else: + self.import_filename = self.gcc_import_filename + + create_debug_file = ( + machine.is_windows() + and ('cs' in self.compilers or self.uses_rust() or self.get_using_msvc()) + # .pdb file is created only when debug symbols are enabled + # BEN: always generate PDBs actually. + #and self.environment.coredata.get_option(OptionKey("debug")) + ) + if create_debug_file: + self.debug_filename = self.name + '.pdb' + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return self.environment.get_bindir(), '{bindir}' + + def description(self): + '''Human friendly description of the executable''' + return self.name + + def type_suffix(self): + return "@exe" + + def get_import_filename(self) -> T.Optional[str]: + """ + The name of the import library that will be outputted by the compiler + + Returns None if there is no import library required for this platform + """ + return self.import_filename + + def get_import_filenameslist(self): + if self.import_filename: + return [self.vs_import_filename, self.gcc_import_filename] + return [] + + def get_debug_filename(self) -> T.Optional[str]: + """ + The name of debuginfo file that will be created by the compiler + + Returns None if the build won't create any debuginfo file + """ + return self.debug_filename + + def is_linkable_target(self): + return self.is_linkwithable + + def get_command(self) -> 'ImmutableListProtocol[str]': + """Provides compatibility with ExternalProgram. + + Since you can override ExternalProgram instances with Executables. + """ + return self.outputs + + def get_path(self) -> str: + """Provides compatibility with ExternalProgram.""" + return os.path.join(self.subdir, self.filename) + + def found(self) -> bool: + """Provides compatibility with ExternalProgram.""" + return True + + +class StaticLibrary(BuildTarget): + known_kwargs = known_stlib_kwargs + + typename = 'static library' + + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): + self.prelink = kwargs.get('prelink', False) + if not isinstance(self.prelink, bool): + raise InvalidArguments('Prelink keyword argument must be a boolean.') + super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, + environment, compilers, kwargs) + + def post_init(self) -> None: + super().post_init() + if 'cs' in self.compilers: + raise InvalidArguments('Static libraries not supported for C#.') + if 'rust' in self.compilers: + # If no crate type is specified, or it's the generic lib type, use rlib + if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': + mlog.debug('Defaulting Rust static library target crate type to rlib') + self.rust_crate_type = 'rlib' + # Don't let configuration proceed with a non-static crate type + elif self.rust_crate_type not in ['rlib', 'staticlib']: + raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib" or "staticlib"') + # See https://github.com/rust-lang/rust/issues/110460 + if self.rust_crate_type == 'rlib' and any(c in self.name for c in ['-', ' ', '.']): + raise InvalidArguments('Rust crate type "rlib" does not allow spaces, periods or dashes in the library name ' + 'due to a limitation of rustc. Replace them with underscores, for example') + if self.rust_crate_type == 'staticlib': + # FIXME: In the case of no-std we should not add those libraries, + # but we have no way to know currently. + rustc = self.compilers['rust'] + d = dependencies.InternalDependency('undefined', [], [], + rustc.native_static_libs, + [], [], [], [], [], {}, [], [], []) + self.external_deps.append(d) + # By default a static library is named libfoo.a even on Windows because + # MSVC does not have a consistent convention for what static libraries + # are called. The MSVC CRT uses libfoo.lib syntax but nothing else uses + # it and GCC only looks for static libraries called foo.lib and + # libfoo.a. However, we cannot use foo.lib because that's the same as + # the import library. Using libfoo.a is ok because people using MSVC + # always pass the library filename while linking anyway. + if not hasattr(self, 'prefix'): + self.prefix = 'lib' + if not hasattr(self, 'suffix'): + if 'rust' in self.compilers: + if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'rlib': + # default Rust static library suffix + self.suffix = 'rlib' + elif self.rust_crate_type == 'staticlib': + self.suffix = 'a' + else: + self.suffix = 'a' + self.filename = self.prefix + self.name + '.' + self.suffix + self.outputs[0] = self.filename + + def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: + return {} + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return self.environment.get_static_lib_dir(), '{libdir_static}' + + def type_suffix(self): + return "@sta" + + def process_kwargs(self, kwargs): + super().process_kwargs(kwargs) + if 'rust_crate_type' in kwargs: + rust_crate_type = kwargs['rust_crate_type'] + if isinstance(rust_crate_type, str): + self.rust_crate_type = rust_crate_type + else: + raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') + + def is_linkable_target(self): + return True + + def is_internal(self) -> bool: + return not self.install + +class SharedLibrary(BuildTarget): + known_kwargs = known_shlib_kwargs + + typename = 'shared library' + + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): + self.soversion = None + self.ltversion = None + # Max length 2, first element is compatibility_version, second is current_version + self.darwin_versions = [] + self.vs_module_defs = None + # The import library this target will generate + self.import_filename = None + # The import library that Visual Studio would generate (and accept) + self.vs_import_filename = None + # The import library that GCC would generate (and prefer) + self.gcc_import_filename = None + # The debugging information file this target will generate + self.debug_filename = None + # Use by the pkgconfig module + self.shared_library_only = False + super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, + environment, compilers, kwargs) + + def post_init(self) -> None: + super().post_init() + if 'rust' in self.compilers: + # If no crate type is specified, or it's the generic lib type, use dylib + if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': + mlog.debug('Defaulting Rust dynamic library target crate type to "dylib"') + self.rust_crate_type = 'dylib' + # Don't let configuration proceed with a non-dynamic crate type + elif self.rust_crate_type not in ['dylib', 'cdylib', 'proc-macro']: + raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for dynamic libraries; must be "dylib", "cdylib", or "proc-macro"') + # See https://github.com/rust-lang/rust/issues/110460 + if self.rust_crate_type != 'cdylib' and any(c in self.name for c in ['-', ' ', '.']): + raise InvalidArguments('Rust crate types "dylib" and "proc-macro" do not allow spaces, periods or dashes in the library name ' + 'due to a limitation of rustc. Replace them with underscores, for example') + + if not hasattr(self, 'prefix'): + self.prefix = None + if not hasattr(self, 'suffix'): + self.suffix = None + self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + self.determine_filenames() + + def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: + result: T.Dict[str, str] = {} + mappings = self.get_transitive_link_deps_mapping(prefix) + old = get_target_macos_dylib_install_name(self) + if old not in mappings: + fname = self.get_filename() + outdirs, _, _ = self.get_install_dir() + new = os.path.join(prefix, outdirs[0], fname) + result.update({old: new}) + mappings.update(result) + return mappings + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return self.environment.get_shared_lib_dir(), '{libdir_shared}' + + def determine_filenames(self): + """ + See https://github.com/mesonbuild/meson/pull/417 for details. + + First we determine the filename template (self.filename_tpl), then we + set the output filename (self.filename). + + The template is needed while creating aliases (self.get_aliases), + which are needed while generating .so shared libraries for Linux. + + Besides this, there's also the import library name, which is only used + on Windows since on that platform the linker uses a separate library + called the "import library" during linking instead of the shared + library (DLL). The toolchain will output an import library in one of + two formats: GCC or Visual Studio. + + When we're building with Visual Studio, the import library that will be + generated by the toolchain is self.vs_import_filename, and with + MinGW/GCC, it's self.gcc_import_filename. self.import_filename will + always contain the import library name this target will generate. + """ + prefix = '' + suffix = '' + create_debug_file = False + self.filename_tpl = self.basic_filename_tpl + # NOTE: manual prefix/suffix override is currently only tested for C/C++ + # C# and Mono + if 'cs' in self.compilers: + prefix = '' + suffix = 'dll' + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + create_debug_file = True + # C, C++, Swift, Vala + # Only Windows uses a separate import library for linking + # For all other targets/platforms import_filename stays None + elif self.environment.machines[self.for_machine].is_windows(): + suffix = 'dll' + self.vs_import_filename = '{}{}.lib'.format(self.prefix if self.prefix is not None else '', self.name) + self.gcc_import_filename = '{}{}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) + if self.uses_rust(): + # Shared library is of the form foo.dll + prefix = '' + # Import library is called foo.dll.lib + self.import_filename = f'{self.name}.dll.lib' + # .pdb file is only created when debug symbols are enabled + # BEN: always generate PDBs actually. + create_debug_file = True #self.environment.coredata.get_option(OptionKey("debug")) + elif self.get_using_msvc(): + # Shared library is of the form foo.dll + prefix = '' + # Import library is called foo.lib + self.import_filename = self.vs_import_filename + # .pdb file is only created when debug symbols are enabled + # BEN: always generate PDBs actually. + create_debug_file = True #self.environment.coredata.get_option(OptionKey("debug")) + # Assume GCC-compatible naming + else: + # Shared library is of the form libfoo.dll + prefix = 'lib' + # Import library is called libfoo.dll.a + self.import_filename = self.gcc_import_filename + # Shared library has the soversion if it is defined + if self.soversion: + self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' + else: + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + elif self.environment.machines[self.for_machine].is_cygwin(): + suffix = 'dll' + self.gcc_import_filename = '{}{}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) + # Shared library is of the form cygfoo.dll + # (ld --dll-search-prefix=cyg is the default) + prefix = 'cyg' + # Import library is called libfoo.dll.a + self.import_filename = self.gcc_import_filename + if self.soversion: + self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' + else: + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + elif self.environment.machines[self.for_machine].is_darwin(): + prefix = 'lib' + suffix = 'dylib' + # On macOS, the filename can only contain the major version + if self.soversion: + # libfoo.X.dylib + self.filename_tpl = '{0.prefix}{0.name}.{0.soversion}.{0.suffix}' + else: + # libfoo.dylib + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + elif self.environment.machines[self.for_machine].is_android(): + prefix = 'lib' + suffix = 'so' + # Android doesn't support shared_library versioning + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + else: + prefix = 'lib' + suffix = 'so' + if self.ltversion: + # libfoo.so.X[.Y[.Z]] (.Y and .Z are optional) + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.ltversion}' + elif self.soversion: + # libfoo.so.X + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}.{0.soversion}' + else: + # No versioning, libfoo.so + self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' + if self.prefix is None: + self.prefix = prefix + if self.suffix is None: + self.suffix = suffix + self.filename = self.filename_tpl.format(self) + # There may have been more outputs added by the time we get here, so + # only replace the first entry + self.outputs[0] = self.filename + if create_debug_file: + self.debug_filename = os.path.splitext(self.filename)[0] + '.pdb' + + @staticmethod + def _validate_darwin_versions(darwin_versions): + try: + if isinstance(darwin_versions, int): + darwin_versions = str(darwin_versions) + if isinstance(darwin_versions, str): + darwin_versions = 2 * [darwin_versions] + if not isinstance(darwin_versions, list): + raise InvalidArguments('Shared library darwin_versions: must be a string, integer,' + f'or a list, not {darwin_versions!r}') + if len(darwin_versions) > 2: + raise InvalidArguments('Shared library darwin_versions: list must contain 2 or fewer elements') + if len(darwin_versions) == 1: + darwin_versions = 2 * darwin_versions + for i, v in enumerate(darwin_versions[:]): + if isinstance(v, int): + v = str(v) + if not isinstance(v, str): + raise InvalidArguments('Shared library darwin_versions: list elements ' + f'must be strings or integers, not {v!r}') + if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', v): + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z where ' + 'X, Y, Z are numbers, and Y and Z are optional') + parts = v.split('.') + if len(parts) in {1, 2, 3} and int(parts[0]) > 65535: + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' + 'where X is [0, 65535] and Y, Z are optional') + if len(parts) in {2, 3} and int(parts[1]) > 255: + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' + 'where Y is [0, 255] and Y, Z are optional') + if len(parts) == 3 and int(parts[2]) > 255: + raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' + 'where Z is [0, 255] and Y, Z are optional') + darwin_versions[i] = v + except ValueError: + raise InvalidArguments('Shared library darwin_versions: value is invalid') + return darwin_versions + + def process_kwargs(self, kwargs): + super().process_kwargs(kwargs) + + if not self.environment.machines[self.for_machine].is_android(): + # Shared library version + if 'version' in kwargs: + self.ltversion = kwargs['version'] + if not isinstance(self.ltversion, str): + raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__) + if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion): + raise InvalidArguments(f'Invalid Shared library version "{self.ltversion}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.') + # Try to extract/deduce the soversion + if 'soversion' in kwargs: + self.soversion = kwargs['soversion'] + if isinstance(self.soversion, int): + self.soversion = str(self.soversion) + if not isinstance(self.soversion, str): + raise InvalidArguments('Shared library soversion is not a string or integer.') + elif self.ltversion: + # library version is defined, get the soversion from that + # We replicate what Autotools does here and take the first + # number of the version by default. + self.soversion = self.ltversion.split('.')[0] + # macOS, iOS and tvOS dylib compatibility_version and current_version + if 'darwin_versions' in kwargs: + self.darwin_versions = self._validate_darwin_versions(kwargs['darwin_versions']) + elif self.soversion: + # If unspecified, pick the soversion + self.darwin_versions = 2 * [self.soversion] + + # Visual Studio module-definitions file + if 'vs_module_defs' in kwargs: + path = kwargs['vs_module_defs'] + if isinstance(path, str): + if os.path.isabs(path): + self.vs_module_defs = File.from_absolute_file(path) + else: + self.vs_module_defs = File.from_source_file(self.environment.source_dir, self.subdir, path) + elif isinstance(path, File): + # When passing a generated file. + self.vs_module_defs = path + elif isinstance(path, CustomTarget): + # When passing output of a Custom Target + self.vs_module_defs = File.from_built_file(path.subdir, path.get_filename()) + else: + raise InvalidArguments( + 'Shared library vs_module_defs must be either a string, ' + 'a file object or a Custom Target') + self.process_link_depends(path) + + if 'rust_crate_type' in kwargs: + rust_crate_type = kwargs['rust_crate_type'] + if isinstance(rust_crate_type, str): + self.rust_crate_type = rust_crate_type + else: + raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') + if rust_crate_type == 'proc-macro': + FeatureNew.single_use('Rust crate type "proc-macro"', '0.62.0', self.subproject) + + def get_import_filename(self) -> T.Optional[str]: + """ + The name of the import library that will be outputted by the compiler + + Returns None if there is no import library required for this platform + """ + return self.import_filename + + def get_debug_filename(self) -> T.Optional[str]: + """ + The name of debuginfo file that will be created by the compiler + + Returns None if the build won't create any debuginfo file + """ + return self.debug_filename + + def get_import_filenameslist(self): + if self.import_filename: + return [self.vs_import_filename, self.gcc_import_filename] + return [] + + def get_all_link_deps(self): + return [self] + self.get_transitive_link_deps() + + def get_aliases(self) -> T.List[T.Tuple[str, str, str]]: + """ + If the versioned library name is libfoo.so.0.100.0, aliases are: + * libfoo.so.0 (soversion) -> libfoo.so.0.100.0 + * libfoo.so (unversioned; for linking) -> libfoo.so.0 + Same for dylib: + * libfoo.dylib (unversioned; for linking) -> libfoo.0.dylib + """ + aliases: T.List[T.Tuple[str, str, str]] = [] + # Aliases are only useful with .so and .dylib libraries. Also if + # there's no self.soversion (no versioning), we don't need aliases. + if self.suffix not in ('so', 'dylib') or not self.soversion: + return aliases + # With .so libraries, the minor and micro versions are also in the + # filename. If ltversion != soversion we create an soversion alias: + # libfoo.so.0 -> libfoo.so.0.100.0 + # Where libfoo.so.0.100.0 is the actual library + if self.suffix == 'so' and self.ltversion and self.ltversion != self.soversion: + alias_tpl = self.filename_tpl.replace('ltversion', 'soversion') + ltversion_filename = alias_tpl.format(self) + tag = self.install_tag[0] or 'runtime' + aliases.append((ltversion_filename, self.filename, tag)) + # libfoo.so.0/libfoo.0.dylib is the actual library + else: + ltversion_filename = self.filename + # Unversioned alias: + # libfoo.so -> libfoo.so.0 + # libfoo.dylib -> libfoo.0.dylib + tag = self.install_tag[0] or 'devel' + aliases.append((self.basic_filename_tpl.format(self), ltversion_filename, tag)) + return aliases + + def type_suffix(self): + return "@sha" + + def is_linkable_target(self): + return True + +# A shared library that is meant to be used with dlopen rather than linking +# into something else. +class SharedModule(SharedLibrary): + known_kwargs = known_shmod_kwargs + + typename = 'shared module' + + def __init__( + self, + name: str, + subdir: str, + subproject: SubProject, + for_machine: MachineChoice, + sources: T.List['SourceOutputs'], + structured_sources: T.Optional[StructuredSources], + objects: T.List[ObjectTypes], + environment: environment.Environment, + compilers: T.Dict[str, 'Compiler'], + kwargs): + if 'version' in kwargs: + raise MesonException('Shared modules must not specify the version kwarg.') + if 'soversion' in kwargs: + raise MesonException('Shared modules must not specify the soversion kwarg.') + super().__init__(name, subdir, subproject, for_machine, sources, + structured_sources, objects, environment, compilers, kwargs) + # We need to set the soname in cases where build files link the module + # to build targets, see: https://github.com/mesonbuild/meson/issues/9492 + self.force_soname = False + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return self.environment.get_shared_module_dir(), '{moduledir_shared}' + +class BothLibraries(SecondLevelHolder): + def __init__(self, shared: SharedLibrary, static: StaticLibrary) -> None: + self._preferred_library = 'shared' + self.shared = shared + self.static = static + self.subproject = self.shared.subproject + + def __repr__(self) -> str: + return f'' + + def get_default_object(self) -> BuildTarget: + if self._preferred_library == 'shared': + return self.shared + elif self._preferred_library == 'static': + return self.static + raise MesonBugException(f'self._preferred_library == "{self._preferred_library}" is neither "shared" nor "static".') + +class CommandBase: + + depend_files: T.List[File] + dependencies: T.List[T.Union[BuildTarget, 'CustomTarget']] + subproject: str + + def flatten_command(self, cmd: T.Sequence[T.Union[str, File, programs.ExternalProgram, BuildTargetTypes]]) -> \ + T.List[T.Union[str, File, BuildTarget, 'CustomTarget']]: + cmd = listify(cmd) + final_cmd: T.List[T.Union[str, File, BuildTarget, 'CustomTarget']] = [] + for c in cmd: + if isinstance(c, str): + final_cmd.append(c) + elif isinstance(c, File): + self.depend_files.append(c) + final_cmd.append(c) + elif isinstance(c, programs.ExternalProgram): + if not c.found(): + raise InvalidArguments('Tried to use not-found external program in "command"') + path = c.get_path() + if os.path.isabs(path): + # Can only add a dependency on an external program which we + # know the absolute path of + self.depend_files.append(File.from_absolute_file(path)) + final_cmd += c.get_command() + elif isinstance(c, (BuildTarget, CustomTarget)): + self.dependencies.append(c) + final_cmd.append(c) + elif isinstance(c, CustomTargetIndex): + FeatureNew.single_use('CustomTargetIndex for command argument', '0.60', self.subproject) + self.dependencies.append(c.target) + final_cmd += self.flatten_command(File.from_built_file(c.get_subdir(), c.get_filename())) + elif isinstance(c, list): + final_cmd += self.flatten_command(c) + else: + raise InvalidArguments(f'Argument {c!r} in "command" is invalid') + return final_cmd + +class CustomTarget(Target, CommandBase): + + typename = 'custom' + + def __init__(self, + name: T.Optional[str], + subdir: str, + subproject: str, + environment: environment.Environment, + command: T.Sequence[T.Union[ + str, BuildTargetTypes, GeneratedList, + programs.ExternalProgram, File]], + sources: T.Sequence[T.Union[ + str, File, BuildTargetTypes, ExtractedObjects, + GeneratedList, programs.ExternalProgram]], + outputs: T.List[str], + *, + build_always_stale: bool = False, + build_by_default: T.Optional[bool] = None, + capture: bool = False, + console: bool = False, + depend_files: T.Optional[T.Sequence[FileOrString]] = None, + extra_depends: T.Optional[T.Sequence[T.Union[str, SourceOutputs]]] = None, + depfile: T.Optional[str] = None, + env: T.Optional[EnvironmentVariables] = None, + feed: bool = False, + install: bool = False, + install_dir: T.Optional[T.List[T.Union[str, Literal[False]]]] = None, + install_mode: T.Optional[FileMode] = None, + install_tag: T.Optional[T.List[T.Optional[str]]] = None, + absolute_paths: bool = False, + backend: T.Optional['Backend'] = None, + ): + # TODO expose keyword arg to make MachineChoice.HOST configurable + super().__init__(name, subdir, subproject, False, MachineChoice.HOST, environment, + install, build_always_stale) + self.sources = list(sources) + self.outputs = substitute_values( + outputs, get_filenames_templates_dict( + get_sources_string_names(sources, backend), + [])) + self.build_by_default = build_by_default if build_by_default is not None else install + self.capture = capture + self.console = console + self.depend_files = list(depend_files or []) + self.dependencies: T.List[T.Union[CustomTarget, BuildTarget]] = [] + # must be after depend_files and dependencies + self.command = self.flatten_command(command) + self.depfile = depfile + self.env = env or EnvironmentVariables() + self.extra_depends = list(extra_depends or []) + self.feed = feed + self.install_dir = list(install_dir or []) + self.install_mode = install_mode + self.install_tag = _process_install_tag(install_tag, len(self.outputs)) + self.name = name if name else self.outputs[0] + + # Whether to use absolute paths for all files on the commandline + self.absolute_paths = absolute_paths + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return None, None + + def __repr__(self): + repr_str = "<{0} {1}: {2}>" + return repr_str.format(self.__class__.__name__, self.get_id(), self.command) + + def get_target_dependencies(self) -> T.List[T.Union[SourceOutputs, str]]: + deps: T.List[T.Union[SourceOutputs, str]] = [] + deps.extend(self.dependencies) + deps.extend(self.extra_depends) + for c in self.sources: + if isinstance(c, CustomTargetIndex): + deps.append(c.target) + elif not isinstance(c, programs.ExternalProgram): + deps.append(c) + return deps + + def get_transitive_build_target_deps(self) -> T.Set[T.Union[BuildTarget, 'CustomTarget']]: + ''' + Recursively fetch the build targets that this custom target depends on, + whether through `command:`, `depends:`, or `sources:` The recursion is + only performed on custom targets. + This is useful for setting PATH on Windows for finding required DLLs. + F.ex, if you have a python script that loads a C module that links to + other DLLs in your project. + ''' + bdeps: T.Set[T.Union[BuildTarget, 'CustomTarget']] = set() + deps = self.get_target_dependencies() + for d in deps: + if isinstance(d, BuildTarget): + bdeps.add(d) + elif isinstance(d, CustomTarget): + bdeps.update(d.get_transitive_build_target_deps()) + return bdeps + + def get_dependencies(self): + return self.dependencies + + def should_install(self) -> bool: + return self.install + + def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: + return self.install_dir + + def get_custom_install_mode(self) -> T.Optional['FileMode']: + return self.install_mode + + def get_outputs(self) -> T.List[str]: + return self.outputs + + def get_filename(self) -> str: + return self.outputs[0] + + def get_sources(self) -> T.List[T.Union[str, File, BuildTarget, GeneratedTypes, ExtractedObjects, programs.ExternalProgram]]: + return self.sources + + def get_generated_lists(self) -> T.List[GeneratedList]: + genlists: T.List[GeneratedList] = [] + for c in self.sources: + if isinstance(c, GeneratedList): + genlists.append(c) + return genlists + + def get_generated_sources(self) -> T.List[GeneratedList]: + return self.get_generated_lists() + + def get_dep_outname(self, infilenames): + if self.depfile is None: + raise InvalidArguments('Tried to get depfile name for custom_target that does not have depfile defined.') + if infilenames: + plainname = os.path.basename(infilenames[0]) + basename = os.path.splitext(plainname)[0] + return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) + else: + if '@BASENAME@' in self.depfile or '@PLAINNAME@' in self.depfile: + raise InvalidArguments('Substitution in depfile for custom_target that does not have an input file.') + return self.depfile + + def is_linkable_output(self, output: str) -> bool: + if output.endswith(('.a', '.dll', '.lib', '.so', '.dylib')): + return True + # libfoo.so.X soname + if re.search(r'\.so(\.\d+)*$', output): + return True + return False + + def is_linkable_target(self) -> bool: + if len(self.outputs) != 1: + return False + return self.is_linkable_output(self.outputs[0]) + + def links_dynamically(self) -> bool: + """Whether this target links dynamically or statically + + Does not assert the target is linkable, just that it is not shared + + :return: True if is dynamically linked, otherwise False + """ + suf = os.path.splitext(self.outputs[0])[-1] + return suf not in {'.a', '.lib'} + + def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: + return {} + + def get_link_dep_subdirs(self) -> T.AbstractSet[str]: + return OrderedSet() + + def get_all_link_deps(self): + return [] + + def is_internal(self) -> bool: + ''' + Returns True if this is a not installed static library. + ''' + if len(self.outputs) != 1: + return False + return CustomTargetIndex(self, self.outputs[0]).is_internal() + + def extract_all_objects(self) -> T.List[T.Union[str, 'ExtractedObjects']]: + return self.get_outputs() + + def type_suffix(self): + return "@cus" + + def __getitem__(self, index: int) -> 'CustomTargetIndex': + return CustomTargetIndex(self, self.outputs[index]) + + def __setitem__(self, index, value): + raise NotImplementedError + + def __delitem__(self, index): + raise NotImplementedError + + def __iter__(self): + for i in self.outputs: + yield CustomTargetIndex(self, i) + + def __len__(self) -> int: + return len(self.outputs) + +class CompileTarget(BuildTarget): + ''' + Target that only compile sources without linking them together. + It can be used as preprocessor, or transpiler. + ''' + + typename = 'compile' + + def __init__(self, + name: str, + subdir: str, + subproject: str, + environment: environment.Environment, + sources: T.List['SourceOutputs'], + output_templ: str, + compiler: Compiler, + backend: Backend, + compile_args: T.List[str], + include_directories: T.List[IncludeDirs], + dependencies: T.List[dependencies.Dependency]): + compilers = {compiler.get_language(): compiler} + kwargs = { + 'build_by_default': False, + f'{compiler.language}_args': compile_args, + 'include_directories': include_directories, + 'dependencies': dependencies, + } + super().__init__(name, subdir, subproject, compiler.for_machine, + sources, None, [], environment, compilers, kwargs) + self.filename = name + self.compiler = compiler + self.output_templ = output_templ + self.outputs = [] + self.sources_map: T.Dict[File, str] = {} + for f in self.sources: + self._add_output(f) + for gensrc in self.generated: + for s in gensrc.get_outputs(): + rel_src = backend.get_target_generated_dir(self, gensrc, s) + self._add_output(File.from_built_relative(rel_src)) + + def type_suffix(self) -> str: + return "@compile" + + @property + def is_unity(self) -> bool: + return False + + def _add_output(self, f: File) -> None: + plainname = os.path.basename(f.fname) + basename = os.path.splitext(plainname)[0] + o = self.output_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) + self.outputs.append(o) + self.sources_map[f] = o + + +class RunTarget(Target, CommandBase): + + typename = 'run' + + def __init__(self, name: str, + command: T.Sequence[T.Union[str, File, BuildTargetTypes, programs.ExternalProgram]], + dependencies: T.Sequence[Target], + subdir: str, + subproject: str, + environment: environment.Environment, + env: T.Optional['EnvironmentVariables'] = None, + default_env: bool = True): + # These don't produce output artifacts + super().__init__(name, subdir, subproject, False, MachineChoice.BUILD, environment) + self.dependencies = dependencies + self.depend_files = [] + self.command = self.flatten_command(command) + self.absolute_paths = False + self.env = env + self.default_env = default_env + + def __repr__(self) -> str: + repr_str = "<{0} {1}: {2}>" + return repr_str.format(self.__class__.__name__, self.get_id(), self.command[0]) + + def get_dependencies(self) -> T.List[T.Union[BuildTarget, 'CustomTarget']]: + return self.dependencies + + def get_generated_sources(self) -> T.List['GeneratedTypes']: + return [] + + def get_sources(self) -> T.List[File]: + return [] + + def should_install(self) -> bool: + return False + + def get_filename(self) -> str: + return self.name + + def get_outputs(self) -> T.List[str]: + if isinstance(self.name, str): + return [self.name] + elif isinstance(self.name, list): + return self.name + else: + raise RuntimeError('RunTarget: self.name is neither a list nor a string. This is a bug') + + def type_suffix(self) -> str: + return "@run" + +class AliasTarget(RunTarget): + + typename = 'alias' + + def __init__(self, name: str, dependencies: T.Sequence['Target'], + subdir: str, subproject: str, environment: environment.Environment): + super().__init__(name, [], dependencies, subdir, subproject, environment) + + def __repr__(self): + repr_str = "<{0} {1}>" + return repr_str.format(self.__class__.__name__, self.get_id()) + +class Jar(BuildTarget): + known_kwargs = known_jar_kwargs + + typename = 'jar' + + def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, + sources: T.List[SourceOutputs], structured_sources: T.Optional['StructuredSources'], + objects, environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], + kwargs): + super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, + environment, compilers, kwargs) + for s in self.sources: + if not s.endswith('.java'): + raise InvalidArguments(f'Jar source {s} is not a java file.') + for t in self.link_targets: + if not isinstance(t, Jar): + raise InvalidArguments(f'Link target {t} is not a jar target.') + if self.structured_sources: + raise InvalidArguments('structured sources are not supported in Java targets.') + self.filename = self.name + '.jar' + self.outputs = [self.filename] + self.java_args = kwargs.get('java_args', []) + self.java_resources: T.Optional[StructuredSources] = kwargs.get('java_resources', None) + + def get_main_class(self): + return self.main_class + + def type_suffix(self): + return "@jar" + + def get_java_args(self): + return self.java_args + + def get_java_resources(self) -> T.Optional[StructuredSources]: + return self.java_resources + + def validate_install(self): + # All jar targets are installable. + pass + + def is_linkable_target(self): + return True + + def get_classpath_args(self): + cp_paths = [os.path.join(l.get_subdir(), l.get_filename()) for l in self.link_targets] + cp_string = os.pathsep.join(cp_paths) + if cp_string: + return ['-cp', os.pathsep.join(cp_paths)] + return [] + + def get_default_install_dir(self) -> T.Tuple[str, str]: + return self.environment.get_jar_dir(), '{jardir}' + +@dataclass(eq=False) +class CustomTargetIndex(HoldableObject): + + """A special opaque object returned by indexing a CustomTarget. This object + exists in Meson, but acts as a proxy in the backends, making targets depend + on the CustomTarget it's derived from, but only adding one source file to + the sources. + """ + + typename: T.ClassVar[str] = 'custom' + + target: T.Union[CustomTarget, CompileTarget] + output: str + + def __post_init__(self) -> None: + self.for_machine = self.target.for_machine + + @property + def name(self) -> str: + return f'{self.target.name}[{self.output}]' + + def __repr__(self): + return ''.format(self.target, self.output) + + def get_outputs(self) -> T.List[str]: + return [self.output] + + def get_subdir(self) -> str: + return self.target.get_subdir() + + def get_filename(self) -> str: + return self.output + + def get_id(self) -> str: + return self.target.get_id() + + def get_all_link_deps(self): + return self.target.get_all_link_deps() + + def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: + return self.target.get_link_deps_mapping(prefix) + + def get_link_dep_subdirs(self) -> T.AbstractSet[str]: + return self.target.get_link_dep_subdirs() + + def is_linkable_target(self) -> bool: + return self.target.is_linkable_output(self.output) + + def links_dynamically(self) -> bool: + """Whether this target links dynamically or statically + + Does not assert the target is linkable, just that it is not shared + + :return: True if is dynamically linked, otherwise False + """ + suf = os.path.splitext(self.output)[-1] + return suf not in {'.a', '.lib'} + + def should_install(self) -> bool: + return self.target.should_install() + + def is_internal(self) -> bool: + ''' + Returns True if this is a not installed static library + ''' + suf = os.path.splitext(self.output)[-1] + return suf in {'.a', '.lib'} and not self.should_install() + + def extract_all_objects(self) -> T.List[T.Union[str, 'ExtractedObjects']]: + return self.target.extract_all_objects() + + def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: + return self.target.get_custom_install_dir() + +class ConfigurationData(HoldableObject): + def __init__(self, initial_values: T.Optional[T.Union[ + T.Dict[str, T.Tuple[T.Union[str, int, bool], T.Optional[str]]], + T.Dict[str, T.Union[str, int, bool]]] + ] = None): + super().__init__() + self.values: T.Dict[str, T.Tuple[T.Union[str, int, bool], T.Optional[str]]] = \ + {k: v if isinstance(v, tuple) else (v, None) for k, v in initial_values.items()} if initial_values else {} + self.used: bool = False + + def __repr__(self) -> str: + return repr(self.values) + + def __contains__(self, value: str) -> bool: + return value in self.values + + def __bool__(self) -> bool: + return bool(self.values) + + def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]: + return self.values[name] # (val, desc) + + def keys(self) -> T.Iterator[str]: + return self.values.keys() + +# A bit poorly named, but this represents plain data files to copy +# during install. +@dataclass(eq=False) +class Data(HoldableObject): + sources: T.List[File] + install_dir: str + install_dir_name: str + install_mode: 'FileMode' + subproject: str + rename: T.List[str] = None + install_tag: T.Optional[str] = None + data_type: str = None + + def __post_init__(self) -> None: + if self.rename is None: + self.rename = [os.path.basename(f.fname) for f in self.sources] + +@dataclass(eq=False) +class SymlinkData(HoldableObject): + target: str + name: str + install_dir: str + subproject: str + install_tag: T.Optional[str] = None + + def __post_init__(self) -> None: + if self.name != os.path.basename(self.name): + raise InvalidArguments(f'Link name is "{self.name}", but link names cannot contain path separators. ' + 'The dir part should be in install_dir.') + +@dataclass(eq=False) +class TestSetup: + exe_wrapper: T.List[str] + gdb: bool + timeout_multiplier: int + env: EnvironmentVariables + exclude_suites: T.List[str] + +def get_sources_string_names(sources, backend): + ''' + For the specified list of @sources which can be strings, Files, or targets, + get all the output basenames. + ''' + names = [] + for s in sources: + if isinstance(s, str): + names.append(s) + elif isinstance(s, (BuildTarget, CustomTarget, CustomTargetIndex, GeneratedList)): + names += s.get_outputs() + elif isinstance(s, ExtractedObjects): + names += backend.determine_ext_objs(s) + elif isinstance(s, File): + names.append(s.fname) + else: + raise AssertionError(f'Unknown source type: {s!r}') + return names + +def load(build_dir: str) -> Build: + filename = os.path.join(build_dir, 'meson-private', 'build.dat') + try: + b = pickle_load(filename, 'Build data', Build) + # We excluded coredata when saving Build object, load it separately + b.environment.coredata = coredata.load(build_dir) + return b + except FileNotFoundError: + raise MesonException(f'No such build data file as {filename!r}.') + + +def save(obj: Build, filename: str) -> None: + # Exclude coredata because we pickle it separately already + cdata = obj.environment.coredata + obj.environment.coredata = None + try: + with open(filename, 'wb') as f: + pickle.dump(obj, f) + finally: + obj.environment.coredata = cdata diff --git a/devtools/meson/mesonbuild/cargo/__init__.py b/devtools/meson/mesonbuild/cargo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/cargo/builder.py b/devtools/meson/mesonbuild/cargo/builder.py new file mode 100644 index 0000000..49bc65d --- /dev/null +++ b/devtools/meson/mesonbuild/cargo/builder.py @@ -0,0 +1,284 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Provides helpers for building AST + +This is meant to make building Meson AST from foreign (largely declarative) +build descriptions easier. +""" + +from __future__ import annotations +import builtins +import dataclasses +import typing as T + +from .. import mparser + + +def _token(tid: str, filename: str, value: mparser.TV_TokenTypes) -> mparser.Token[mparser.TV_TokenTypes]: + """Create a Token object, but with the line numbers stubbed out. + + :param tid: the token id (such as string, number, etc) + :param filename: the filename that the token was generated from + :param value: the value of the token + :return: A Token object + """ + return mparser.Token(tid, filename, -1, -1, -1, (-1, -1), value) + + +def string(value: str, filename: str) -> mparser.StringNode: + """Build A StringNode + + :param value: the value of the string + :param filename: the file that the value came from + :return: A StringNode + """ + return mparser.StringNode(_token('string', filename, value)) + + +def number(value: int, filename: str) -> mparser.NumberNode: + """Build A NumberNode + + :param value: the value of the number + :param filename: the file that the value came from + :return: A NumberNode + """ + return mparser.NumberNode(_token('number', filename, value)) + + +def bool(value: builtins.bool, filename: str) -> mparser.BooleanNode: + """Build A BooleanNode + + :param value: the value of the boolean + :param filename: the file that the value came from + :return: A BooleanNode + """ + return mparser.BooleanNode(_token('bool', filename, value)) + + +def array(value: T.List[mparser.BaseNode], filename: str) -> mparser.ArrayNode: + """Build an Array Node + + :param value: A list of nodes to insert into the array + :param filename: The file the array is from + :return: An ArrayNode built from the arguments + """ + args = mparser.ArgumentNode(_token('array', filename, 'unused')) + args.arguments = value + return mparser.ArrayNode(args, -1, -1, -1, -1) + + +def identifier(value: str, filename: str) -> mparser.IdNode: + """Build A IdNode + + :param value: the value of the boolean + :param filename: the file that the value came from + :return: A BooleanNode + """ + return mparser.IdNode(_token('id', filename, value)) + + +def method(name: str, id_: mparser.IdNode, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.MethodNode: + """Create a method call. + + :param name: the name of the method + :param id_: the object to call the method of + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + args = mparser.ArgumentNode(_token('array', id_.filename, 'unused')) + if pos is not None: + args.arguments = pos + if kw is not None: + args.kwargs = {identifier(k, id_.filename): v for k, v in kw.items()} + return mparser.MethodNode(id_.filename, -1, -1, id_, name, args) + + +def function(name: str, filename: str, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.FunctionNode: + """Create a function call. + + :param name: the name of the function + :param filename: The name of the current file being evaluated + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + args = mparser.ArgumentNode(_token('array', filename, 'unused')) + if pos is not None: + args.arguments = pos + if kw is not None: + args.kwargs = {identifier(k, filename): v for k, v in kw.items()} + return mparser.FunctionNode(filename, -1, -1, -1, -1, name, args) + + +def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an equality operation + + :param lhs: The left hand side of the equal + :param rhs: the right hand side of the equal + :return: A compraison node + """ + return mparser.ComparisonNode('==', lhs, rhs) + + +def or_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: + """Create and OrNode + + :param lhs: The Left of the Node + :param rhs: The Right of the Node + :return: The OrNode + """ + return mparser.OrNode(lhs, rhs) + + +def and_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: + """Create an AndNode + + :param lhs: The left of the And + :param rhs: The right of the And + :return: The AndNode + """ + return mparser.AndNode(lhs, rhs) + + +def not_(value: mparser.BaseNode, filename: str) -> mparser.NotNode: + """Create a not node + + :param value: The value to negate + :param filename: the string filename + :return: The NotNode + """ + return mparser.NotNode(_token('not', filename, ''), value) + + +def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.AssignmentNode: + """Create an AssignmentNode + + :param value: The rvalue + :param varname: The lvalue + :param filename: The filename + :return: An AssignmentNode + """ + return mparser.AssignmentNode(filename, -1, -1, varname, value) + + +def block(filename: str) -> mparser.CodeBlockNode: + return mparser.CodeBlockNode(_token('node', filename, '')) + + +@dataclasses.dataclass +class Builder: + + filename: str + + def assign(self, value: mparser.BaseNode, varname: str) -> mparser.AssignmentNode: + return assign(value, varname, self.filename) + + def string(self, value: str) -> mparser.StringNode: + """Build A StringNode + + :param value: the value of the string + :return: A StringNode + """ + return string(value, self.filename) + + def number(self, value: int) -> mparser.NumberNode: + """Build A NumberNode + + :param value: the value of the number + :return: A NumberNode + """ + return number(value, self.filename) + + def bool(self, value: builtins.bool) -> mparser.BooleanNode: + """Build A BooleanNode + + :param value: the value of the boolean + :return: A BooleanNode + """ + return bool(value, self.filename) + + def array(self, value: T.List[mparser.BaseNode]) -> mparser.ArrayNode: + """Build an Array Node + + :param value: A list of nodes to insert into the array + :return: An ArrayNode built from the arguments + """ + return array(value, self.filename) + + def identifier(self, value: str) -> mparser.IdNode: + """Build A IdNode + + :param value: the value of the boolean + :return: A BooleanNode + """ + return identifier(value, self.filename) + + def method(self, name: str, id_: mparser.IdNode, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.MethodNode: + """Create a method call. + + :param name: the name of the method + :param id_: the object to call the method of + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + return method(name, id_, pos or [], kw or {}) + + def function(self, name: str, + pos: T.Optional[T.List[mparser.BaseNode]] = None, + kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, + ) -> mparser.FunctionNode: + """Create a function call. + + :param name: the name of the function + :param pos: a list of positional arguments, defaults to None + :param kw: a dictionary of keyword arguments, defaults to None + :return: a method call object + """ + return function(name, self.filename, pos or [], kw or {}) + + def equal(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an equality operation + + :param lhs: The left hand side of the equal + :param rhs: the right hand side of the equal + :return: A compraison node + """ + return equal(lhs, rhs) + + def or_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: + """Create and OrNode + + :param lhs: The Left of the Node + :param rhs: The Right of the Node + :return: The OrNode + """ + return or_(lhs, rhs) + + def and_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: + """Create an AndNode + + :param lhs: The left of the And + :param rhs: The right of the And + :return: The AndNode + """ + return and_(lhs, rhs) + + def not_(self, value: mparser.BaseNode, filename: str) -> mparser.NotNode: + """Create a not node + + :param value: The value to negate + :return: The NotNode + """ + return not_(value, self.filename) diff --git a/devtools/meson/mesonbuild/cargo/cfg.py b/devtools/meson/mesonbuild/cargo/cfg.py new file mode 100644 index 0000000..ed6fd53 --- /dev/null +++ b/devtools/meson/mesonbuild/cargo/cfg.py @@ -0,0 +1,276 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Rust CFG parser. + +Rust uses its `cfg()` format in cargo. + +This may have the following functions: + - all() + - any() + - not() + +And additionally is made up of `identifier [ = str]`. Where the str is optional, +so you could have examples like: +``` +[target.`cfg(unix)`.dependencies] +[target.'cfg(target_arch = "x86_64")'.dependencies] +[target.'cfg(all(target_arch = "x86_64", target_arch = "x86"))'.dependencies] +``` +""" + +from __future__ import annotations +import dataclasses +import enum +import functools +import typing as T + + +from . import builder +from .. import mparser +from ..mesonlib import MesonBugException + +if T.TYPE_CHECKING: + _T = T.TypeVar('_T') + _LEX_TOKEN = T.Tuple['TokenType', T.Optional[str]] + _LEX_STREAM = T.Iterable[_LEX_TOKEN] + _LEX_STREAM_AH = T.Iterator[T.Tuple[_LEX_TOKEN, T.Optional[_LEX_TOKEN]]] + + +class TokenType(enum.Enum): + + LPAREN = enum.auto() + RPAREN = enum.auto() + STRING = enum.auto() + IDENTIFIER = enum.auto() + ALL = enum.auto() + ANY = enum.auto() + NOT = enum.auto() + COMMA = enum.auto() + EQUAL = enum.auto() + + +def lexer(raw: str) -> _LEX_STREAM: + """Lex a cfg() expression. + + :param raw: The raw cfg() expression + :return: An iterable of tokens + """ + buffer: T.List[str] = [] + is_string: bool = False + for s in raw: + if s.isspace() or s in {')', '(', ',', '='} or (s == '"' and buffer): + val = ''.join(buffer) + buffer.clear() + if is_string: + yield (TokenType.STRING, val) + elif val == 'any': + yield (TokenType.ANY, None) + elif val == 'all': + yield (TokenType.ALL, None) + elif val == 'not': + yield (TokenType.NOT, None) + elif val: + yield (TokenType.IDENTIFIER, val) + + if s == '(': + yield (TokenType.LPAREN, None) + continue + elif s == ')': + yield (TokenType.RPAREN, None) + continue + elif s == ',': + yield (TokenType.COMMA, None) + continue + elif s == '=': + yield (TokenType.EQUAL, None) + continue + elif s.isspace(): + continue + + if s == '"': + is_string = not is_string + else: + buffer.append(s) + if buffer: + # This should always be an identifier + yield (TokenType.IDENTIFIER, ''.join(buffer)) + + +def lookahead(iter: T.Iterator[_T]) -> T.Iterator[T.Tuple[_T, T.Optional[_T]]]: + """Get the current value of the iterable, and the next if possible. + + :param iter: The iterable to look into + :yield: A tuple of the current value, and, if possible, the next + :return: nothing + """ + current: _T + next_: T.Optional[_T] + try: + next_ = next(iter) + except StopIteration: + # This is an empty iterator, there's nothing to look ahead to + return + + while True: + current = next_ + try: + next_ = next(iter) + except StopIteration: + next_ = None + + yield current, next_ + + if next_ is None: + break + + +@dataclasses.dataclass +class IR: + + """Base IR node for Cargo CFG.""" + + filename: str + +@dataclasses.dataclass +class String(IR): + + value: str + + +@dataclasses.dataclass +class Identifier(IR): + + value: str + + +@dataclasses.dataclass +class Equal(IR): + + lhs: IR + rhs: IR + + +@dataclasses.dataclass +class Any(IR): + + args: T.List[IR] + + +@dataclasses.dataclass +class All(IR): + + args: T.List[IR] + + +@dataclasses.dataclass +class Not(IR): + + value: IR + + +def _parse(ast: _LEX_STREAM_AH, filename: str) -> IR: + (token, value), n_stream = next(ast) + if n_stream is not None: + ntoken, _ = n_stream + else: + ntoken, _ = (None, None) + + stream: T.List[_LEX_TOKEN] + if token is TokenType.IDENTIFIER: + if ntoken is TokenType.EQUAL: + return Equal(filename, Identifier(filename, value), _parse(ast, filename)) + if token is TokenType.STRING: + return String(filename, value) + if token is TokenType.EQUAL: + # In this case the previous caller already has handled the equal + return _parse(ast, filename) + if token in {TokenType.ANY, TokenType.ALL}: + type_ = All if token is TokenType.ALL else Any + assert ntoken is TokenType.LPAREN + next(ast) # advance the iterator to get rid of the LPAREN + stream = [] + args: T.List[IR] = [] + while token is not TokenType.RPAREN: + (token, value), _ = next(ast) + if token is TokenType.COMMA: + args.append(_parse(lookahead(iter(stream)), filename)) + stream.clear() + else: + stream.append((token, value)) + if stream: + args.append(_parse(lookahead(iter(stream)), filename)) + return type_(filename, args) + if token is TokenType.NOT: + next(ast) # advance the iterator to get rid of the LPAREN + stream = [] + # Mypy can't figure out that token is overridden inside the while loop + while token is not TokenType.RPAREN: # type: ignore + (token, value), _ = next(ast) + stream.append((token, value)) + return Not(filename, _parse(lookahead(iter(stream)), filename)) + + raise MesonBugException(f'Unhandled Cargo token: {token}') + + +def parse(ast: _LEX_STREAM, filename: str) -> IR: + """Parse the tokenized list into Meson AST. + + :param ast: An iterable of Tokens + :param filename: The name of the file being parsed + :return: An mparser Node to be used as a conditional + """ + ast_i: _LEX_STREAM_AH = lookahead(iter(ast)) + return _parse(ast_i, filename) + + +@functools.singledispatch +def ir_to_meson(ir: T.Any) -> mparser.BaseNode: + raise NotImplementedError + + +@ir_to_meson.register +def _(ir: String) -> mparser.BaseNode: + return builder.string(ir.value, ir.filename) + + +@ir_to_meson.register +def _(ir: Identifier) -> mparser.BaseNode: + host_machine = builder.identifier('host_machine', ir.filename) + if ir.value == "target_arch": + return builder.method('cpu_family', host_machine) + elif ir.value in {"target_os", "target_family"}: + return builder.method('system', host_machine) + elif ir.value == "target_endian": + return builder.method('endian', host_machine) + raise MesonBugException(f"Unhandled Cargo identifier: {ir.value}") + + +@ir_to_meson.register +def _(ir: Equal) -> mparser.BaseNode: + return builder.equal(ir_to_meson(ir.lhs), ir_to_meson(ir.rhs)) + + +@ir_to_meson.register +def _(ir: Not) -> mparser.BaseNode: + return builder.not_(ir_to_meson(ir.value), ir.filename) + + +@ir_to_meson.register +def _(ir: Any) -> mparser.BaseNode: + args = iter(reversed(ir.args)) + last = next(args) + cur = builder.or_(ir_to_meson(next(args)), ir_to_meson(last)) + for a in args: + cur = builder.or_(ir_to_meson(a), cur) + return cur + + +@ir_to_meson.register +def _(ir: All) -> mparser.BaseNode: + args = iter(reversed(ir.args)) + last = next(args) + cur = builder.and_(ir_to_meson(next(args)), ir_to_meson(last)) + for a in args: + cur = builder.and_(ir_to_meson(a), cur) + return cur diff --git a/devtools/meson/mesonbuild/cargo/interpreter.py b/devtools/meson/mesonbuild/cargo/interpreter.py new file mode 100644 index 0000000..59e1a1f --- /dev/null +++ b/devtools/meson/mesonbuild/cargo/interpreter.py @@ -0,0 +1,451 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Interpreter for converting Cargo Toml definitions to Meson AST + +There are some notable limits here. We don't even try to convert something with +a build.rs: there's so few limits on what Cargo allows a build.rs (basically +none), and no good way for us to convert them. In that case, an actual meson +port will be required. +""" + +from __future__ import annotations +import dataclasses +import glob +import importlib +import itertools +import json +import os +import shutil +import typing as T + +from . import builder +from . import version +from .. import mparser +from .._pathlib import Path +from ..mesonlib import MesonException, Popen_safe + +if T.TYPE_CHECKING: + from types import ModuleType + + from . import manifest + from ..environment import Environment + +# tomllib is present in python 3.11, before that it is a pypi module called tomli, +# we try to import tomllib, then tomli, +# TODO: add a fallback to toml2json? +tomllib: T.Optional[ModuleType] = None +toml2json: T.Optional[str] = None +for t in ['tomllib', 'tomli']: + try: + tomllib = importlib.import_module(t) + break + except ImportError: + pass +else: + # TODO: it would be better to use an Executable here, which could be looked + # up in the cross file or provided by a wrap. However, that will have to be + # passed in externally, since we don't have (and I don't think we should), + # have access to the `Environment` for that in this module. + toml2json = shutil.which('toml2json') + + +def load_toml(filename: str) -> T.Dict[object, object]: + if tomllib: + with open(filename, 'rb') as f: + raw = tomllib.load(f) + else: + if toml2json is None: + raise MesonException('Could not find an implementation of tomllib, nor toml2json') + + p, out, err = Popen_safe([toml2json, filename]) + if p.returncode != 0: + raise MesonException('toml2json failed to decode output\n', err) + + raw = json.loads(out) + + if not isinstance(raw, dict): + raise MesonException("Cargo.toml isn't a dictionary? How did that happen?") + + return raw + + +def fixup_meson_varname(name: str) -> str: + """Fixup a meson variable name + + :param name: The name to fix + :return: the fixed name + """ + return name.replace('-', '_') + +# Pylance can figure out that these do not, in fact, overlap, but mypy can't +@T.overload +def _fixup_raw_mappings(d: manifest.BuildTarget) -> manifest.FixedBuildTarget: ... # type: ignore + +@T.overload +def _fixup_raw_mappings(d: manifest.LibTarget) -> manifest.FixedLibTarget: ... # type: ignore + +@T.overload +def _fixup_raw_mappings(d: manifest.Dependency) -> manifest.FixedDependency: ... + +def _fixup_raw_mappings(d: T.Union[manifest.BuildTarget, manifest.LibTarget, manifest.Dependency] + ) -> T.Union[manifest.FixedBuildTarget, manifest.FixedLibTarget, + manifest.FixedDependency]: + """Fixup raw cargo mappings to ones more suitable for python to consume. + + This does the following: + * replaces any `-` with `_`, cargo likes the former, but python dicts make + keys with `-` in them awkward to work with + * Convert Dependndency versions from the cargo format to something meson + understands + + :param d: The mapping to fix + :return: the fixed string + """ + raw = {fixup_meson_varname(k): v for k, v in d.items()} + if 'version' in raw: + assert isinstance(raw['version'], str), 'for mypy' + raw['version'] = version.convert(raw['version']) + return T.cast('T.Union[manifest.FixedBuildTarget, manifest.FixedLibTarget, manifest.FixedDependency]', raw) + + +@dataclasses.dataclass +class Package: + + """Representation of a Cargo Package entry, with defaults filled in.""" + + name: str + version: str + description: str + resolver: T.Optional[str] = None + authors: T.List[str] = dataclasses.field(default_factory=list) + edition: manifest.EDITION = '2015' + rust_version: T.Optional[str] = None + documentation: T.Optional[str] = None + readme: T.Optional[str] = None + homepage: T.Optional[str] = None + repository: T.Optional[str] = None + license: T.Optional[str] = None + license_file: T.Optional[str] = None + keywords: T.List[str] = dataclasses.field(default_factory=list) + categories: T.List[str] = dataclasses.field(default_factory=list) + workspace: T.Optional[str] = None + build: T.Optional[str] = None + links: T.Optional[str] = None + exclude: T.List[str] = dataclasses.field(default_factory=list) + include: T.List[str] = dataclasses.field(default_factory=list) + publish: bool = True + metadata: T.Dict[str, T.Dict[str, str]] = dataclasses.field(default_factory=dict) + default_run: T.Optional[str] = None + autobins: bool = True + autoexamples: bool = True + autotests: bool = True + autobenches: bool = True + + +@dataclasses.dataclass +class Dependency: + + """Representation of a Cargo Dependency Entry.""" + + version: T.List[str] + registry: T.Optional[str] = None + git: T.Optional[str] = None + branch: T.Optional[str] = None + rev: T.Optional[str] = None + path: T.Optional[str] = None + optional: bool = False + package: T.Optional[str] = None + default_features: bool = False + features: T.List[str] = dataclasses.field(default_factory=list) + + @classmethod + def from_raw(cls, raw: manifest.DependencyV) -> Dependency: + """Create a dependency from a raw cargo dictionary""" + if isinstance(raw, str): + return cls(version.convert(raw)) + return cls(**_fixup_raw_mappings(raw)) + + +@dataclasses.dataclass +class BuildTarget: + + name: str + crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['lib']) + path: dataclasses.InitVar[T.Optional[str]] = None + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-test-field + # True for lib, bin, test + test: bool = True + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-doctest-field + # True for lib + doctest: bool = False + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-bench-field + # True for lib, bin, benchmark + bench: bool = True + + # https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-doc-field + # True for libraries and binaries + doc: bool = False + + harness: bool = True + edition: manifest.EDITION = '2015' + required_features: T.List[str] = dataclasses.field(default_factory=list) + plugin: bool = False + + +@dataclasses.dataclass +class Library(BuildTarget): + + """Representation of a Cargo Library Entry.""" + + doctest: bool = True + doc: bool = True + proc_macro: bool = False + crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['lib']) + doc_scrape_examples: bool = True + + +@dataclasses.dataclass +class Binary(BuildTarget): + + """Representation of a Cargo Bin Entry.""" + + doc: bool = True + + +@dataclasses.dataclass +class Test(BuildTarget): + + """Representation of a Cargo Test Entry.""" + + bench: bool = True + + +@dataclasses.dataclass +class Benchmark(BuildTarget): + + """Representation of a Cargo Benchmark Entry.""" + + test: bool = True + + +@dataclasses.dataclass +class Example(BuildTarget): + + """Representation of a Cargo Example Entry.""" + + crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['bin']) + + +@dataclasses.dataclass +class Manifest: + + """Cargo Manifest definition. + + Most of these values map up to the Cargo Manifest, but with default values + if not provided. + + Cargo subprojects can contain what Meson wants to treat as multiple, + interdependent, subprojects. + + :param subdir: the subdirectory that this cargo project is in + :param path: the path within the cargo subproject. + """ + + package: Package + dependencies: T.Dict[str, Dependency] + dev_dependencies: T.Dict[str, Dependency] + build_dependencies: T.Dict[str, Dependency] + lib: Library + bin: T.List[Binary] + test: T.List[Test] + bench: T.List[Benchmark] + example: T.List[Example] + features: T.Dict[str, T.List[str]] + target: T.Dict[str, T.Dict[str, Dependency]] + subdir: str + path: str = '' + + +def _create_project(package: Package, build: builder.Builder, env: Environment) -> mparser.FunctionNode: + """Create a function call + + :param package: The Cargo package to generate from + :param filename: The full path to the file + :param meson_version: The generating meson version + :return: a FunctionNode + """ + args: T.List[mparser.BaseNode] = [] + args.extend([ + build.string(package.name), + build.string('rust'), + ]) + kwargs: T.Dict[str, mparser.BaseNode] = { + 'version': build.string(package.version), + # Always assume that the generated meson is using the latest features + # This will warn when when we generate deprecated code, which is helpful + # for the upkeep of the module + 'meson_version': build.string(f'>= {env.coredata.version}'), + 'default_options': build.array([build.string(f'rust_std={package.edition}')]), + } + if package.license: + kwargs['license'] = build.string(package.license) + elif package.license_file: + kwargs['license_files'] = build.string(package.license_file) + + return build.function('project', args, kwargs) + + +def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = '') -> Manifest: + # This cast is a bit of a hack to deal with proc-macro + lib = _fixup_raw_mappings(raw_manifest.get('lib', {})) + + # We need to set the name field if it's not set manually, + # including if other fields are set in the lib section + lib.setdefault('name', raw_manifest['package']['name']) + + pkg = T.cast('manifest.FixedPackage', + {fixup_meson_varname(k): v for k, v in raw_manifest['package'].items()}) + + return Manifest( + Package(**pkg), + {k: Dependency.from_raw(v) for k, v in raw_manifest.get('dependencies', {}).items()}, + {k: Dependency.from_raw(v) for k, v in raw_manifest.get('dev-dependencies', {}).items()}, + {k: Dependency.from_raw(v) for k, v in raw_manifest.get('build-dependencies', {}).items()}, + Library(**lib), + [Binary(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bin', {})], + [Test(**_fixup_raw_mappings(b)) for b in raw_manifest.get('test', {})], + [Benchmark(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bench', {})], + [Example(**_fixup_raw_mappings(b)) for b in raw_manifest.get('example', {})], + raw_manifest.get('features', {}), + {k: {k2: Dependency.from_raw(v2) for k2, v2 in v['dependencies'].items()} + for k, v in raw_manifest.get('target', {}).items()}, + subdir, + path, + ) + + +def _load_manifests(subdir: str) -> T.Dict[str, Manifest]: + filename = os.path.join(subdir, 'Cargo.toml') + raw = load_toml(filename) + + manifests: T.Dict[str, Manifest] = {} + + raw_manifest: T.Union[manifest.Manifest, manifest.VirtualManifest] + if 'package' in raw: + raw_manifest = T.cast('manifest.Manifest', raw) + manifest_ = _convert_manifest(raw_manifest, subdir) + manifests[manifest_.package.name] = manifest_ + else: + raw_manifest = T.cast('manifest.VirtualManifest', raw) + + if 'workspace' in raw_manifest: + # XXX: need to verify that python glob and cargo globbing are the + # same and probably write a glob implementation. Blarg + + # We need to chdir here to make the glob work correctly + pwd = os.getcwd() + os.chdir(subdir) + members: T.Iterable[str] + try: + members = itertools.chain.from_iterable( + glob.glob(m) for m in raw_manifest['workspace']['members']) + finally: + os.chdir(pwd) + if 'exclude' in raw_manifest['workspace']: + members = (x for x in members if x not in raw_manifest['workspace']['exclude']) + + for m in members: + filename = os.path.join(subdir, m, 'Cargo.toml') + raw = load_toml(filename) + + raw_manifest = T.cast('manifest.Manifest', raw) + man = _convert_manifest(raw_manifest, subdir, m) + manifests[man.package.name] = man + + return manifests + + +def load_all_manifests(subproject_dir: str) -> T.Dict[str, Manifest]: + """Find all cargo subprojects, and load them + + :param subproject_dir: Directory to look for subprojects in + :return: A dictionary of rust project names to Manifests + """ + manifests: T.Dict[str, Manifest] = {} + for p in Path(subproject_dir).iterdir(): + if p.is_dir() and (p / 'Cargo.toml').exists(): + manifests.update(_load_manifests(str(p))) + return manifests + + +def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: + kw: T.Dict[str, mparser.BaseNode] = {} + if cargo.dependencies: + ids = [build.identifier(f'dep_{n}') for n in cargo.dependencies] + kw['dependencies'] = build.array( + [build.method('get_variable', i, [build.string('dep')]) for i in ids]) + + # FIXME: currently assuming that an rlib is being generated, which is + # the most common. + return [ + build.assign( + build.function( + 'static_library', + [ + build.string(fixup_meson_varname(cargo.package.name)), + build.string(os.path.join('src', 'lib.rs')), + ], + kw, + ), + 'lib' + ), + + build.assign( + build.function( + 'declare_dependency', + kw={'link_with': build.identifier('lib'), **kw}, + ), + 'dep' + ) + ] + + +def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode: + filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml') + build = builder.Builder(filename) + + ast: T.List[mparser.BaseNode] = [ + _create_project(cargo.package, build, env), + build.assign(build.function('import', [build.string('rust')]), 'rust'), + ] + + if cargo.dependencies: + for name, dep in cargo.dependencies.items(): + kw = { + 'version': build.array([build.string(s) for s in dep.version]), + } + ast.extend([ + build.assign( + build.method( + 'cargo', + build.identifier('rust'), + [build.string(name)], + kw, + ), + f'dep_{fixup_meson_varname(name)}', + ), + ]) + + # Libs are always auto-discovered and there's no other way to handle them, + # which is unfortunate for reproducability + if os.path.exists(os.path.join(env.source_dir, cargo.subdir, cargo.path, 'src', 'lib.rs')): + ast.extend(_create_lib(cargo, build)) + + # XXX: make this not awful + block = builder.block(filename) + block.lines = ast + return block diff --git a/devtools/meson/mesonbuild/cargo/manifest.py b/devtools/meson/mesonbuild/cargo/manifest.py new file mode 100644 index 0000000..e6192d0 --- /dev/null +++ b/devtools/meson/mesonbuild/cargo/manifest.py @@ -0,0 +1,227 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Type definitions for cargo manifest files.""" + +from __future__ import annotations +import typing as T + +from typing_extensions import Literal, TypedDict, Required + +EDITION = Literal['2015', '2018', '2021'] +CRATE_TYPE = Literal['bin', 'lib', 'dylib', 'staticlib', 'cdylib', 'rlib', 'proc-macro'] + +Package = TypedDict( + 'Package', + { + 'name': Required[str], + 'version': Required[str], + 'authors': T.List[str], + 'edition': EDITION, + 'rust-version': str, + 'description': str, + 'readme': str, + 'license': str, + 'license-file': str, + 'keywords': T.List[str], + 'categories': T.List[str], + 'workspace': str, + 'build': str, + 'links': str, + 'include': T.List[str], + 'exclude': T.List[str], + 'publish': bool, + 'metadata': T.Dict[str, T.Dict[str, str]], + 'default-run': str, + 'autobins': bool, + 'autoexamples': bool, + 'autotests': bool, + 'autobenches': bool, + }, + total=False, +) +"""A description of the Package Dictionary.""" + +class FixedPackage(TypedDict, total=False): + + """A description of the Package Dictionary, fixed up.""" + + name: Required[str] + version: Required[str] + authors: T.List[str] + edition: EDITION + rust_version: str + description: str + readme: str + license: str + license_file: str + keywords: T.List[str] + categories: T.List[str] + workspace: str + build: str + links: str + include: T.List[str] + exclude: T.List[str] + publish: bool + metadata: T.Dict[str, T.Dict[str, str]] + default_run: str + autobins: bool + autoexamples: bool + autotests: bool + autobenches: bool + + +class Badge(TypedDict): + + """An entry in the badge section.""" + + status: Literal['actively-developed', 'passively-developed', 'as-is', 'experimental', 'deprecated', 'none'] + + +Dependency = TypedDict( + 'Dependency', + { + 'version': str, + 'registry': str, + 'git': str, + 'branch': str, + 'rev': str, + 'path': str, + 'optional': bool, + 'package': str, + 'default-features': bool, + 'features': T.List[str], + }, + total=False, +) +"""An entry in the *dependencies sections.""" + + +class FixedDependency(TypedDict, total=False): + + """An entry in the *dependencies sections, fixed up.""" + + version: T.List[str] + registry: str + git: str + branch: str + rev: str + path: str + optional: bool + package: str + default_features: bool + features: T.List[str] + + +DependencyV = T.Union[Dependency, str] +"""A Dependency entry, either a string or a Dependency Dict.""" + + +_BaseBuildTarget = TypedDict( + '_BaseBuildTarget', + { + 'path': str, + 'test': bool, + 'doctest': bool, + 'bench': bool, + 'doc': bool, + 'plugin': bool, + 'proc-macro': bool, + 'harness': bool, + 'edition': EDITION, + 'crate-type': T.List[CRATE_TYPE], + 'required-features': T.List[str], + }, + total=False, +) + + +class BuildTarget(_BaseBuildTarget, total=False): + + name: Required[str] + +class LibTarget(_BaseBuildTarget, total=False): + + name: str + + +class _BaseFixedBuildTarget(TypedDict, total=False): + path: str + test: bool + doctest: bool + bench: bool + doc: bool + plugin: bool + harness: bool + edition: EDITION + crate_type: T.List[CRATE_TYPE] + required_features: T.List[str] + + +class FixedBuildTarget(_BaseFixedBuildTarget, total=False): + + name: str + +class FixedLibTarget(_BaseFixedBuildTarget, total=False): + + name: Required[str] + proc_macro: bool + + +class Target(TypedDict): + + """Target entry in the Manifest File.""" + + dependencies: T.Dict[str, DependencyV] + + +class Workspace(TypedDict): + + """The representation of a workspace. + + In a vritual manifest the :attribute:`members` is always present, but in a + project manifest, an empty workspace may be provided, in which case the + workspace is implicitly filled in by values from the path based dependencies. + + the :attribute:`exclude` is always optional + """ + + members: T.List[str] + exclude: T.List[str] + + +Manifest = TypedDict( + 'Manifest', + { + 'package': Package, + 'badges': T.Dict[str, Badge], + 'dependencies': T.Dict[str, DependencyV], + 'dev-dependencies': T.Dict[str, DependencyV], + 'build-dependencies': T.Dict[str, DependencyV], + 'lib': LibTarget, + 'bin': T.List[BuildTarget], + 'test': T.List[BuildTarget], + 'bench': T.List[BuildTarget], + 'example': T.List[BuildTarget], + 'features': T.Dict[str, T.List[str]], + 'target': T.Dict[str, Target], + 'workspace': Workspace, + + # TODO: patch? + # TODO: replace? + }, + total=False, +) +"""The Cargo Manifest format.""" + + +class VirtualManifest(TypedDict): + + """The Representation of a virtual manifest. + + Cargo allows a root manifest that contains only a workspace, this is called + a virtual manifest. This doesn't really map 1:1 with any meson concept, + except perhaps the proposed "meta project". + """ + + workspace: Workspace diff --git a/devtools/meson/mesonbuild/cargo/version.py b/devtools/meson/mesonbuild/cargo/version.py new file mode 100644 index 0000000..cb09a00 --- /dev/null +++ b/devtools/meson/mesonbuild/cargo/version.py @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +"""Convert Cargo versions into Meson compatible ones.""" + +from __future__ import annotations +import typing as T + + +def convert(cargo_ver: str) -> T.List[str]: + """Convert a Cargo compatible version into a Meson compatible one. + + :param cargo_ver: The version, as Cargo specifies + :return: A list of version constraints, as Meson understands them + """ + # Cleanup, just for safety + cargo_ver = cargo_ver.strip() + cargo_vers = [c.strip() for c in cargo_ver.split(',')] + + out: T.List[str] = [] + + for ver in cargo_vers: + # This covers >= and =< as well + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#comparison-requirements + if ver.startswith(('>', '<', '=')): + out.append(ver) + + elif ver.startswith('~'): + # Rust has these tilde requirements, which means that it is >= to + # the version, but less than the next version + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#tilde-requirements + # we convert those into a pair of constraints + v = ver[1:].split('.') + out.append(f'>= {".".join(v)}') + if len(v) == 3: + out.append(f'< {v[0]}.{int(v[1]) + 1}.0') + elif len(v) == 2: + out.append(f'< {v[0]}.{int(v[1]) + 1}') + else: + out.append(f'< {int(v[0]) + 1}') + + elif '*' in ver: + # Rust has astrisk requirements,, which are like 1.* == ~1 + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#wildcard-requirements + v = ver.split('.')[:-1] + if v: + out.append(f'>= {".".join(v)}') + if len(v) == 2: + out.append(f'< {v[0]}.{int(v[1]) + 1}') + elif len(v) == 1: + out.append(f'< {int(v[0]) + 1}') + + else: + # a Caret version is equivalent to the default strategy + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements + if ver.startswith('^'): + ver = ver[1:] + + # If there is no qualifier, then it means this or the next non-zero version + # That means that if this is `1.1.0``, then we need `>= 1.1.0` && `< 2.0.0` + # Or if we have `0.1.0`, then we need `>= 0.1.0` && `< 0.2.0` + # Or if we have `0.1`, then we need `>= 0.1.0` && `< 0.2.0` + # Or if we have `0.0.0`, then we need `< 1.0.0` + # Or if we have `0.0`, then we need `< 1.0.0` + # Or if we have `0`, then we need `< 1.0.0` + # Or if we have `0.0.3`, then we need `>= 0.0.3` && `< 0.0.4` + # https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio + # + # this works much like the ~ versions, but in reverse. Tilde starts + # at the patch version and works up, to the major version, while + # bare numbers start at the major version and work down to the patch + # version + vers = ver.split('.') + min_: T.List[str] = [] + max_: T.List[str] = [] + bumped = False + for v_ in vers: + if v_ != '0' and not bumped: + min_.append(v_) + max_.append(str(int(v_) + 1)) + bumped = True + else: + if not (bumped and v_ == '0'): + min_.append(v_) + if not bumped: + max_.append('0') + + # If there is no minimum, don't emit one + if set(min_) != {'0'}: + out.append('>= {}'.format('.'.join(min_))) + if set(max_) != {'0'}: + out.append('< {}'.format('.'.join(max_))) + else: + out.append('< 1') + + return out diff --git a/devtools/meson/mesonbuild/cmake/__init__.py b/devtools/meson/mesonbuild/cmake/__init__.py new file mode 100644 index 0000000..e9d7f2a --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/__init__.py @@ -0,0 +1,39 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. + +__all__ = [ + 'CMakeExecutor', + 'CMakeExecScope', + 'CMakeException', + 'CMakeInterpreter', + 'CMakeTarget', + 'CMakeToolchain', + 'CMakeTraceParser', + 'TargetOptions', + 'language_map', + 'cmake_defines_to_args', + 'check_cmake_args', + 'cmake_is_debug', + 'resolve_cmake_trace_targets', +] + +from .common import CMakeException, TargetOptions, cmake_defines_to_args, language_map, check_cmake_args, cmake_is_debug +from .executor import CMakeExecutor +from .interpreter import CMakeInterpreter +from .toolchain import CMakeToolchain, CMakeExecScope +from .traceparser import CMakeTarget, CMakeTraceParser +from .tracetargets import resolve_cmake_trace_targets diff --git a/devtools/meson/mesonbuild/cmake/common.py b/devtools/meson/mesonbuild/cmake/common.py new file mode 100644 index 0000000..3de6c16 --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/common.py @@ -0,0 +1,344 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. +from __future__ import annotations + +from ..mesonlib import MesonException, OptionKey +from .. import mlog +from pathlib import Path +import typing as T + +if T.TYPE_CHECKING: + from ..environment import Environment + from ..interpreterbase import TYPE_var + +language_map = { + 'c': 'C', + 'cpp': 'CXX', + 'cuda': 'CUDA', + 'objc': 'OBJC', + 'objcpp': 'OBJCXX', + 'cs': 'CSharp', + 'java': 'Java', + 'fortran': 'Fortran', + 'swift': 'Swift', +} + +backend_generator_map = { + 'ninja': 'Ninja', + 'xcode': 'Xcode', + 'vs2010': 'Visual Studio 10 2010', + 'vs2012': 'Visual Studio 11 2012', + 'vs2013': 'Visual Studio 12 2013', + 'vs2015': 'Visual Studio 14 2015', + 'vs2017': 'Visual Studio 15 2017', + 'vs2019': 'Visual Studio 16 2019', + 'vs2022': 'Visual Studio 17 2022', +} + +blacklist_cmake_defs = [ + 'CMAKE_TOOLCHAIN_FILE', + 'CMAKE_PROJECT_INCLUDE', + 'MESON_PRELOAD_FILE', + 'MESON_PS_CMAKE_CURRENT_BINARY_DIR', + 'MESON_PS_CMAKE_CURRENT_SOURCE_DIR', + 'MESON_PS_DELAYED_CALLS', + 'MESON_PS_LOADED', + 'MESON_FIND_ROOT_PATH', + 'MESON_CMAKE_SYSROOT', + 'MESON_PATHS_LIST', + 'MESON_CMAKE_ROOT', +] + +def cmake_is_debug(env: 'Environment') -> bool: + if OptionKey('b_vscrt') in env.coredata.options: + is_debug = env.coredata.get_option(OptionKey('buildtype')) == 'debug' + if env.coredata.options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}: + is_debug = True + return is_debug + else: + # Don't directly assign to is_debug to make mypy happy + debug_opt = env.coredata.get_option(OptionKey('debug')) + assert isinstance(debug_opt, bool) + return debug_opt + +class CMakeException(MesonException): + pass + +class CMakeBuildFile: + def __init__(self, file: Path, is_cmake: bool, is_temp: bool) -> None: + self.file = file + self.is_cmake = is_cmake + self.is_temp = is_temp + + def __repr__(self) -> str: + return f'<{self.__class__.__name__}: {self.file}; cmake={self.is_cmake}; temp={self.is_temp}>' + +def _flags_to_list(raw: str) -> T.List[str]: + # Convert a raw commandline string into a list of strings + res = [] + curr = '' + escape = False + in_string = False + for i in raw: + if escape: + # If the current char is not a quote, the '\' is probably important + if i not in ['"', "'"]: + curr += '\\' + curr += i + escape = False + elif i == '\\': + escape = True + elif i in {'"', "'"}: + in_string = not in_string + elif i in {' ', '\n'}: + if in_string: + curr += i + else: + res += [curr] + curr = '' + else: + curr += i + res += [curr] + res = [r for r in res if len(r) > 0] + return res + +def cmake_get_generator_args(env: 'Environment') -> T.List[str]: + backend_name = env.coredata.get_option(OptionKey('backend')) + assert isinstance(backend_name, str) + assert backend_name in backend_generator_map + return ['-G', backend_generator_map[backend_name]] + +def cmake_defines_to_args(raw: T.List[T.Dict[str, TYPE_var]], permissive: bool = False) -> T.List[str]: + res = [] # type: T.List[str] + + for i in raw: + for key, val in i.items(): + if key in blacklist_cmake_defs: + mlog.warning('Setting', mlog.bold(key), 'is not supported. See the meson docs for cross compilation support:') + mlog.warning(' - URL: https://mesonbuild.com/CMake-module.html#cross-compilation') + mlog.warning(' --> Ignoring this option') + continue + if isinstance(val, (str, int, float)): + res += [f'-D{key}={val}'] + elif isinstance(val, bool): + val_str = 'ON' if val else 'OFF' + res += [f'-D{key}={val_str}'] + else: + raise MesonException('Type "{}" of "{}" is not supported as for a CMake define value'.format(type(val).__name__, key)) + + return res + +# TODO: this function will become obsolete once the `cmake_args` kwarg is dropped +def check_cmake_args(args: T.List[str]) -> T.List[str]: + res = [] # type: T.List[str] + dis = ['-D' + x for x in blacklist_cmake_defs] + assert dis # Ensure that dis is not empty. + for i in args: + if any(i.startswith(x) for x in dis): + mlog.warning('Setting', mlog.bold(i), 'is not supported. See the meson docs for cross compilation support:') + mlog.warning(' - URL: https://mesonbuild.com/CMake-module.html#cross-compilation') + mlog.warning(' --> Ignoring this option') + continue + res += [i] + return res + +class CMakeInclude: + def __init__(self, path: Path, isSystem: bool = False): + self.path = path + self.isSystem = isSystem + + def __repr__(self) -> str: + return f'' + +class CMakeFileGroup: + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.defines = data.get('defines', '') # type: str + self.flags = _flags_to_list(data.get('compileFlags', '')) # type: T.List[str] + self.is_generated = data.get('isGenerated', False) # type: bool + self.language = data.get('language', 'C') # type: str + self.sources = [Path(x) for x in data.get('sources', [])] # type: T.List[Path] + + # Fix the include directories + self.includes = [] # type: T.List[CMakeInclude] + for i in data.get('includePath', []): + if isinstance(i, dict) and 'path' in i: + isSystem = i.get('isSystem', False) + assert isinstance(isSystem, bool) + assert isinstance(i['path'], str) + self.includes += [CMakeInclude(Path(i['path']), isSystem)] + elif isinstance(i, str): + self.includes += [CMakeInclude(Path(i))] + + def log(self) -> None: + mlog.log('flags =', mlog.bold(', '.join(self.flags))) + mlog.log('defines =', mlog.bold(', '.join(self.defines))) + mlog.log('includes =', mlog.bold(', '.join([str(x) for x in self.includes]))) + mlog.log('is_generated =', mlog.bold('true' if self.is_generated else 'false')) + mlog.log('language =', mlog.bold(self.language)) + mlog.log('sources:') + for i in self.sources: + with mlog.nested(): + mlog.log(i.as_posix()) + +class CMakeTarget: + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.artifacts = [Path(x) for x in data.get('artifacts', [])] # type: T.List[Path] + self.src_dir = Path(data.get('sourceDirectory', '')) # type: Path + self.build_dir = Path(data.get('buildDirectory', '')) # type: Path + self.name = data.get('name', '') # type: str + self.full_name = data.get('fullName', '') # type: str + self.install = data.get('hasInstallRule', False) # type: bool + self.install_paths = [Path(x) for x in set(data.get('installPaths', []))] # type: T.List[Path] + self.link_lang = data.get('linkerLanguage', '') # type: str + self.link_libraries = _flags_to_list(data.get('linkLibraries', '')) # type: T.List[str] + self.link_flags = _flags_to_list(data.get('linkFlags', '')) # type: T.List[str] + self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) # type: T.List[str] + # self.link_path = Path(data.get('linkPath', '')) # type: Path + self.type = data.get('type', 'EXECUTABLE') # type: str + # self.is_generator_provided = data.get('isGeneratorProvided', False) # type: bool + self.files = [] # type: T.List[CMakeFileGroup] + + for i in data.get('fileGroups', []): + self.files += [CMakeFileGroup(i)] + + def log(self) -> None: + mlog.log('artifacts =', mlog.bold(', '.join([x.as_posix() for x in self.artifacts]))) + mlog.log('src_dir =', mlog.bold(self.src_dir.as_posix())) + mlog.log('build_dir =', mlog.bold(self.build_dir.as_posix())) + mlog.log('name =', mlog.bold(self.name)) + mlog.log('full_name =', mlog.bold(self.full_name)) + mlog.log('install =', mlog.bold('true' if self.install else 'false')) + mlog.log('install_paths =', mlog.bold(', '.join([x.as_posix() for x in self.install_paths]))) + mlog.log('link_lang =', mlog.bold(self.link_lang)) + mlog.log('link_libraries =', mlog.bold(', '.join(self.link_libraries))) + mlog.log('link_flags =', mlog.bold(', '.join(self.link_flags))) + mlog.log('link_lang_flags =', mlog.bold(', '.join(self.link_lang_flags))) + # mlog.log('link_path =', mlog.bold(self.link_path)) + mlog.log('type =', mlog.bold(self.type)) + # mlog.log('is_generator_provided =', mlog.bold('true' if self.is_generator_provided else 'false')) + for idx, i in enumerate(self.files): + mlog.log(f'Files {idx}:') + with mlog.nested(): + i.log() + +class CMakeProject: + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.src_dir = Path(data.get('sourceDirectory', '')) # type: Path + self.build_dir = Path(data.get('buildDirectory', '')) # type: Path + self.name = data.get('name', '') # type: str + self.targets = [] # type: T.List[CMakeTarget] + + for i in data.get('targets', []): + self.targets += [CMakeTarget(i)] + + def log(self) -> None: + mlog.log('src_dir =', mlog.bold(self.src_dir.as_posix())) + mlog.log('build_dir =', mlog.bold(self.build_dir.as_posix())) + mlog.log('name =', mlog.bold(self.name)) + for idx, i in enumerate(self.targets): + mlog.log(f'Target {idx}:') + with mlog.nested(): + i.log() + +class CMakeConfiguration: + def __init__(self, data: T.Dict[str, T.Any]) -> None: + self.name = data.get('name', '') # type: str + self.projects = [] # type: T.List[CMakeProject] + for i in data.get('projects', []): + self.projects += [CMakeProject(i)] + + def log(self) -> None: + mlog.log('name =', mlog.bold(self.name)) + for idx, i in enumerate(self.projects): + mlog.log(f'Project {idx}:') + with mlog.nested(): + i.log() + +class SingleTargetOptions: + def __init__(self) -> None: + self.opts = {} # type: T.Dict[str, str] + self.lang_args = {} # type: T.Dict[str, T.List[str]] + self.link_args = [] # type: T.List[str] + self.install = 'preserve' + + def set_opt(self, opt: str, val: str) -> None: + self.opts[opt] = val + + def append_args(self, lang: str, args: T.List[str]) -> None: + if lang not in self.lang_args: + self.lang_args[lang] = [] + self.lang_args[lang] += args + + def append_link_args(self, args: T.List[str]) -> None: + self.link_args += args + + def set_install(self, install: bool) -> None: + self.install = 'true' if install else 'false' + + def get_override_options(self, initial: T.List[str]) -> T.List[str]: + res = [] # type: T.List[str] + for i in initial: + opt = i[:i.find('=')] + if opt not in self.opts: + res += [i] + res += [f'{k}={v}' for k, v in self.opts.items()] + return res + + def get_compile_args(self, lang: str, initial: T.List[str]) -> T.List[str]: + if lang in self.lang_args: + return initial + self.lang_args[lang] + return initial + + def get_link_args(self, initial: T.List[str]) -> T.List[str]: + return initial + self.link_args + + def get_install(self, initial: bool) -> bool: + return {'preserve': initial, 'true': True, 'false': False}[self.install] + +class TargetOptions: + def __init__(self) -> None: + self.global_options = SingleTargetOptions() + self.target_options = {} # type: T.Dict[str, SingleTargetOptions] + + def __getitem__(self, tgt: str) -> SingleTargetOptions: + if tgt not in self.target_options: + self.target_options[tgt] = SingleTargetOptions() + return self.target_options[tgt] + + def get_override_options(self, tgt: str, initial: T.List[str]) -> T.List[str]: + initial = self.global_options.get_override_options(initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_override_options(initial) + return initial + + def get_compile_args(self, tgt: str, lang: str, initial: T.List[str]) -> T.List[str]: + initial = self.global_options.get_compile_args(lang, initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_compile_args(lang, initial) + return initial + + def get_link_args(self, tgt: str, initial: T.List[str]) -> T.List[str]: + initial = self.global_options.get_link_args(initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_link_args(initial) + return initial + + def get_install(self, tgt: str, initial: bool) -> bool: + initial = self.global_options.get_install(initial) + if tgt in self.target_options: + initial = self.target_options[tgt].get_install(initial) + return initial diff --git a/devtools/meson/mesonbuild/cmake/data/__init__.py b/devtools/meson/mesonbuild/cmake/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/cmake/data/preload.cmake b/devtools/meson/mesonbuild/cmake/data/preload.cmake new file mode 100644 index 0000000..234860b --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/data/preload.cmake @@ -0,0 +1,82 @@ +if(MESON_PS_LOADED) + return() +endif() + +set(MESON_PS_LOADED ON) + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # https://cmake.org/cmake/help/latest/policy/CMP0054.html + +# Dummy macros that have a special meaning in the meson code +macro(meson_ps_execute_delayed_calls) +endmacro() + +macro(meson_ps_reload_vars) +endmacro() + +macro(meson_ps_disabled_function) + message(WARNING "The function '${ARGV0}' is disabled in the context of CMake subprojects.\n" + "This should not be an issue but may lead to compilation errors.") +endmacro() + +# Helper macro to inspect the current CMake state +macro(meson_ps_inspect_vars) + set(MESON_PS_CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") + set(MESON_PS_CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + meson_ps_execute_delayed_calls() +endmacro() + + +# Override some system functions with custom code and forward the args +# to the original function +macro(add_custom_command) + meson_ps_inspect_vars() + _add_custom_command(${ARGV}) +endmacro() + +macro(add_custom_target) + meson_ps_inspect_vars() + _add_custom_target(${ARGV}) +endmacro() + +macro(set_property) + meson_ps_inspect_vars() + _set_property(${ARGV}) +endmacro() + +function(set_source_files_properties) + set(FILES) + set(I 0) + set(PROPERTIES OFF) + + while(I LESS ARGC) + if(NOT PROPERTIES) + if("${ARGV${I}}" STREQUAL "PROPERTIES") + set(PROPERTIES ON) + else() + list(APPEND FILES "${ARGV${I}}") + endif() + + math(EXPR I "${I} + 1") + else() + set(ID_IDX ${I}) + math(EXPR PROP_IDX "${ID_IDX} + 1") + + set(ID "${ARGV${ID_IDX}}") + set(PROP "${ARGV${PROP_IDX}}") + + set_property(SOURCE ${FILES} PROPERTY "${ID}" "${PROP}") + math(EXPR I "${I} + 2") + endif() + endwhile() +endfunction() + +# Disable some functions that would mess up the CMake meson integration +macro(target_precompile_headers) + meson_ps_disabled_function(target_precompile_headers) +endmacro() + +set(MESON_PS_DELAYED_CALLS add_custom_command;add_custom_target;set_property) +meson_ps_reload_vars() + +cmake_policy(POP) diff --git a/devtools/meson/mesonbuild/cmake/executor.py b/devtools/meson/mesonbuild/cmake/executor.py new file mode 100644 index 0000000..c22c0ca --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/executor.py @@ -0,0 +1,254 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. +from __future__ import annotations + +import subprocess as S +from threading import Thread +import typing as T +import re +import os + +from .. import mlog +from ..mesonlib import PerMachine, Popen_safe, version_compare, is_windows, OptionKey +from ..programs import find_external_program, NonExistingExternalProgram + +if T.TYPE_CHECKING: + from pathlib import Path + + from ..environment import Environment + from ..mesonlib import MachineChoice + from ..programs import ExternalProgram + + TYPE_result = T.Tuple[int, T.Optional[str], T.Optional[str]] + TYPE_cache_key = T.Tuple[str, T.Tuple[str, ...], str, T.FrozenSet[T.Tuple[str, str]]] + +class CMakeExecutor: + # The class's copy of the CMake path. Avoids having to search for it + # multiple times in the same Meson invocation. + class_cmakebin = PerMachine(None, None) # type: PerMachine[T.Optional[ExternalProgram]] + class_cmakevers = PerMachine(None, None) # type: PerMachine[T.Optional[str]] + class_cmake_cache = {} # type: T.Dict[T.Any, TYPE_result] + + def __init__(self, environment: 'Environment', version: str, for_machine: MachineChoice, silent: bool = False): + self.min_version = version + self.environment = environment + self.for_machine = for_machine + self.cmakebin, self.cmakevers = self.find_cmake_binary(self.environment, silent=silent) + self.always_capture_stderr = True + self.print_cmout = False + self.prefix_paths = [] # type: T.List[str] + self.extra_cmake_args = [] # type: T.List[str] + + if self.cmakebin is None: + return + + if not version_compare(self.cmakevers, self.min_version): + mlog.warning( + 'The version of CMake', mlog.bold(self.cmakebin.get_path()), + 'is', mlog.bold(self.cmakevers), 'but version', mlog.bold(self.min_version), + 'is required') + self.cmakebin = None + return + + self.prefix_paths = self.environment.coredata.options[OptionKey('cmake_prefix_path', machine=self.for_machine)].value + if self.prefix_paths: + self.extra_cmake_args += ['-DCMAKE_PREFIX_PATH={}'.format(';'.join(self.prefix_paths))] + + def find_cmake_binary(self, environment: 'Environment', silent: bool = False) -> T.Tuple[T.Optional['ExternalProgram'], T.Optional[str]]: + # Only search for CMake the first time and store the result in the class + # definition + if isinstance(CMakeExecutor.class_cmakebin[self.for_machine], NonExistingExternalProgram): + mlog.debug(f'CMake binary for {self.for_machine} is cached as not found') + return None, None + elif CMakeExecutor.class_cmakebin[self.for_machine] is not None: + mlog.debug(f'CMake binary for {self.for_machine} is cached.') + else: + assert CMakeExecutor.class_cmakebin[self.for_machine] is None + + mlog.debug(f'CMake binary for {self.for_machine} is not cached') + for potential_cmakebin in find_external_program( + environment, self.for_machine, 'cmake', 'CMake', + environment.default_cmake, allow_default_for_cross=False): + version_if_ok = self.check_cmake(potential_cmakebin) + if not version_if_ok: + continue + if not silent: + mlog.log('Found CMake:', mlog.bold(potential_cmakebin.get_path()), + f'({version_if_ok})') + CMakeExecutor.class_cmakebin[self.for_machine] = potential_cmakebin + CMakeExecutor.class_cmakevers[self.for_machine] = version_if_ok + break + else: + if not silent: + mlog.log('Found CMake:', mlog.red('NO')) + # Set to False instead of None to signify that we've already + # searched for it and not found it + CMakeExecutor.class_cmakebin[self.for_machine] = NonExistingExternalProgram() + CMakeExecutor.class_cmakevers[self.for_machine] = None + return None, None + + return CMakeExecutor.class_cmakebin[self.for_machine], CMakeExecutor.class_cmakevers[self.for_machine] + + def check_cmake(self, cmakebin: 'ExternalProgram') -> T.Optional[str]: + if not cmakebin.found(): + mlog.log(f'Did not find CMake {cmakebin.name!r}') + return None + try: + cmd = cmakebin.get_command() + p, out = Popen_safe(cmd + ['--version'])[0:2] + if p.returncode != 0: + mlog.warning('Found CMake {!r} but couldn\'t run it' + ''.format(' '.join(cmd))) + return None + except FileNotFoundError: + mlog.warning('We thought we found CMake {!r} but now it\'s not there. How odd!' + ''.format(' '.join(cmd))) + return None + except PermissionError: + msg = 'Found CMake {!r} but didn\'t have permissions to run it.'.format(' '.join(cmd)) + if not is_windows(): + msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.' + mlog.warning(msg) + return None + + cmvers = re.search(r'(cmake|cmake3)\s*version\s*([\d.]+)', out) + if cmvers is not None: + return cmvers.group(2) + mlog.warning(f'We thought we found CMake {cmd!r}, but it was missing the expected ' + 'version string in its output.') + return None + + def set_exec_mode(self, print_cmout: T.Optional[bool] = None, always_capture_stderr: T.Optional[bool] = None) -> None: + if print_cmout is not None: + self.print_cmout = print_cmout + if always_capture_stderr is not None: + self.always_capture_stderr = always_capture_stderr + + def _cache_key(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_cache_key: + fenv = frozenset(env.items()) if env is not None else frozenset() + targs = tuple(args) + return (self.cmakebin.get_path(), targs, build_dir.as_posix(), fenv) + + def _call_cmout_stderr(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + cmd = self.cmakebin.get_command() + args + proc = S.Popen(cmd, stdout=S.PIPE, stderr=S.PIPE, cwd=str(build_dir), env=env) # TODO [PYTHON_37]: drop Path conversion + + # stdout and stderr MUST be read at the same time to avoid pipe + # blocking issues. The easiest way to do this is with a separate + # thread for one of the pipes. + def print_stdout() -> None: + while True: + line = proc.stdout.readline() + if not line: + break + mlog.log(line.decode(errors='ignore').strip('\n')) + proc.stdout.close() + + t = Thread(target=print_stdout) + t.start() + + try: + # Read stderr line by line and log non trace lines + raw_trace = '' + tline_start_reg = re.compile(r'^\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(.*$') + inside_multiline_trace = False + while True: + line_raw = proc.stderr.readline() + if not line_raw: + break + line = line_raw.decode(errors='ignore') + if tline_start_reg.match(line): + raw_trace += line + inside_multiline_trace = not line.endswith(' )\n') + elif inside_multiline_trace: + raw_trace += line + else: + mlog.warning(line.strip('\n')) + + finally: + proc.stderr.close() + t.join() + proc.wait() + + return proc.returncode, None, raw_trace + + def _call_cmout(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + cmd = self.cmakebin.get_command() + args + proc = S.Popen(cmd, stdout=S.PIPE, stderr=S.STDOUT, cwd=str(build_dir), env=env) # TODO [PYTHON_37]: drop Path conversion + while True: + line = proc.stdout.readline() + if not line: + break + mlog.log(line.decode(errors='ignore').strip('\n')) + proc.stdout.close() + proc.wait() + return proc.returncode, None, None + + def _call_quiet(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + build_dir.mkdir(parents=True, exist_ok=True) + cmd = self.cmakebin.get_command() + args + ret = S.run(cmd, env=env, cwd=str(build_dir), close_fds=False, + stdout=S.PIPE, stderr=S.PIPE, universal_newlines=False) # TODO [PYTHON_37]: drop Path conversion + rc = ret.returncode + out = ret.stdout.decode(errors='ignore') + err = ret.stderr.decode(errors='ignore') + return rc, out, err + + def _call_impl(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]]) -> TYPE_result: + mlog.debug(f'Calling CMake ({self.cmakebin.get_command()}) in {build_dir} with:') + for i in args: + mlog.debug(f' - "{i}"') + if not self.print_cmout: + return self._call_quiet(args, build_dir, env) + else: + if self.always_capture_stderr: + return self._call_cmout_stderr(args, build_dir, env) + else: + return self._call_cmout(args, build_dir, env) + + def call(self, args: T.List[str], build_dir: Path, env: T.Optional[T.Dict[str, str]] = None, disable_cache: bool = False) -> TYPE_result: + if env is None: + env = os.environ.copy() + + args = args + self.extra_cmake_args + if disable_cache: + return self._call_impl(args, build_dir, env) + + # First check if cached, if not call the real cmake function + cache = CMakeExecutor.class_cmake_cache + key = self._cache_key(args, build_dir, env) + if key not in cache: + cache[key] = self._call_impl(args, build_dir, env) + return cache[key] + + def found(self) -> bool: + return self.cmakebin is not None + + def version(self) -> str: + return self.cmakevers + + def executable_path(self) -> str: + return self.cmakebin.get_path() + + def get_command(self) -> T.List[str]: + return self.cmakebin.get_command() + + def get_cmake_prefix_paths(self) -> T.List[str]: + return self.prefix_paths + + def machine_choice(self) -> MachineChoice: + return self.for_machine diff --git a/devtools/meson/mesonbuild/cmake/fileapi.py b/devtools/meson/mesonbuild/cmake/fileapi.py new file mode 100644 index 0000000..9605f92 --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/fileapi.py @@ -0,0 +1,321 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .common import CMakeException, CMakeBuildFile, CMakeConfiguration +import typing as T +from .. import mlog +from pathlib import Path +import json +import re + +STRIP_KEYS = ['cmake', 'reply', 'backtrace', 'backtraceGraph', 'version'] + +class CMakeFileAPI: + def __init__(self, build_dir: Path): + self.build_dir = build_dir + self.api_base_dir = self.build_dir / '.cmake' / 'api' / 'v1' + self.request_dir = self.api_base_dir / 'query' / 'client-meson' + self.reply_dir = self.api_base_dir / 'reply' + self.cmake_sources = [] # type: T.List[CMakeBuildFile] + self.cmake_configurations = [] # type: T.List[CMakeConfiguration] + self.kind_resolver_map = { + 'codemodel': self._parse_codemodel, + 'cmakeFiles': self._parse_cmakeFiles, + } + + def get_cmake_sources(self) -> T.List[CMakeBuildFile]: + return self.cmake_sources + + def get_cmake_configurations(self) -> T.List[CMakeConfiguration]: + return self.cmake_configurations + + def setup_request(self) -> None: + self.request_dir.mkdir(parents=True, exist_ok=True) + + query = { + 'requests': [ + {'kind': 'codemodel', 'version': {'major': 2, 'minor': 0}}, + {'kind': 'cmakeFiles', 'version': {'major': 1, 'minor': 0}}, + ] + } + + query_file = self.request_dir / 'query.json' + query_file.write_text(json.dumps(query, indent=2), encoding='utf-8') + + def load_reply(self) -> None: + if not self.reply_dir.is_dir(): + raise CMakeException('No response from the CMake file API') + + root = None + reg_index = re.compile(r'^index-.*\.json$') + for i in self.reply_dir.iterdir(): + if reg_index.match(i.name): + root = i + break + + if not root: + raise CMakeException('Failed to find the CMake file API index') + + index = self._reply_file_content(root) # Load the root index + index = self._strip_data(index) # Avoid loading duplicate files + index = self._resolve_references(index) # Load everything + index = self._strip_data(index) # Strip unused data (again for loaded files) + + # Debug output + debug_json = self.build_dir / '..' / 'fileAPI.json' + debug_json = debug_json.resolve() + debug_json.write_text(json.dumps(index, indent=2), encoding='utf-8') + mlog.cmd_ci_include(debug_json.as_posix()) + + # parse the JSON + for i in index['objects']: + assert isinstance(i, dict) + assert 'kind' in i + assert i['kind'] in self.kind_resolver_map + + self.kind_resolver_map[i['kind']](i) + + def _parse_codemodel(self, data: T.Dict[str, T.Any]) -> None: + assert 'configurations' in data + assert 'paths' in data + + source_dir = data['paths']['source'] + build_dir = data['paths']['build'] + + # The file API output differs quite a bit from the server + # output. It is more flat than the server output and makes + # heavy use of references. Here these references are + # resolved and the resulting data structure is identical + # to the CMake serve output. + + def helper_parse_dir(dir_entry: T.Dict[str, T.Any]) -> T.Tuple[Path, Path]: + src_dir = Path(dir_entry.get('source', '.')) + bld_dir = Path(dir_entry.get('build', '.')) + src_dir = src_dir if src_dir.is_absolute() else source_dir / src_dir + bld_dir = bld_dir if bld_dir.is_absolute() else build_dir / bld_dir + src_dir = src_dir.resolve() + bld_dir = bld_dir.resolve() + + return src_dir, bld_dir + + def parse_sources(comp_group: T.Dict[str, T.Any], tgt: T.Dict[str, T.Any]) -> T.Tuple[T.List[Path], T.List[Path], T.List[int]]: + gen = [] + src = [] + idx = [] + + src_list_raw = tgt.get('sources', []) + for i in comp_group.get('sourceIndexes', []): + if i >= len(src_list_raw) or 'path' not in src_list_raw[i]: + continue + if src_list_raw[i].get('isGenerated', False): + gen += [Path(src_list_raw[i]['path'])] + else: + src += [Path(src_list_raw[i]['path'])] + idx += [i] + + return src, gen, idx + + def parse_target(tgt: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]: + src_dir, bld_dir = helper_parse_dir(cnf.get('paths', {})) + + # Parse install paths (if present) + install_paths = [] + if 'install' in tgt: + prefix = Path(tgt['install']['prefix']['path']) + install_paths = [prefix / x['path'] for x in tgt['install']['destinations']] + install_paths = list(set(install_paths)) + + # On the first look, it looks really nice that the CMake devs have + # decided to use arrays for the linker flags. However, this feeling + # soon turns into despair when you realize that there only one entry + # per type in most cases, and we still have to do manual string splitting. + link_flags = [] + link_libs = [] + for i in tgt.get('link', {}).get('commandFragments', []): + if i['role'] == 'flags': + link_flags += [i['fragment']] + elif i['role'] == 'libraries': + link_libs += [i['fragment']] + elif i['role'] == 'libraryPath': + link_flags += ['-L{}'.format(i['fragment'])] + elif i['role'] == 'frameworkPath': + link_flags += ['-F{}'.format(i['fragment'])] + for i in tgt.get('archive', {}).get('commandFragments', []): + if i['role'] == 'flags': + link_flags += [i['fragment']] + + # TODO The `dependencies` entry is new in the file API. + # maybe we can make use of that in addition to the + # implicit dependency detection + tgt_data = { + 'artifacts': [Path(x.get('path', '')) for x in tgt.get('artifacts', [])], + 'sourceDirectory': src_dir, + 'buildDirectory': bld_dir, + 'name': tgt.get('name', ''), + 'fullName': tgt.get('nameOnDisk', ''), + 'hasInstallRule': 'install' in tgt, + 'installPaths': install_paths, + 'linkerLanguage': tgt.get('link', {}).get('language', 'CXX'), + 'linkLibraries': ' '.join(link_libs), # See previous comment block why we join the array + 'linkFlags': ' '.join(link_flags), # See previous comment block why we join the array + 'type': tgt.get('type', 'EXECUTABLE'), + 'fileGroups': [], + } + + processed_src_idx = [] + for cg in tgt.get('compileGroups', []): + # Again, why an array, when there is usually only one element + # and arguments are separated with spaces... + flags = [] + for i in cg.get('compileCommandFragments', []): + flags += [i['fragment']] + + cg_data = { + 'defines': [x.get('define', '') for x in cg.get('defines', [])], + 'compileFlags': ' '.join(flags), + 'language': cg.get('language', 'C'), + 'isGenerated': None, # Set later, flag is stored per source file + 'sources': [], + 'includePath': cg.get('includes', []), + } + + normal_src, generated_src, src_idx = parse_sources(cg, tgt) + if normal_src: + cg_data = dict(cg_data) + cg_data['isGenerated'] = False + cg_data['sources'] = normal_src + tgt_data['fileGroups'] += [cg_data] + if generated_src: + cg_data = dict(cg_data) + cg_data['isGenerated'] = True + cg_data['sources'] = generated_src + tgt_data['fileGroups'] += [cg_data] + processed_src_idx += src_idx + + # Object libraries have no compile groups, only source groups. + # So we add all the source files to a dummy source group that were + # not found in the previous loop + normal_src = [] + generated_src = [] + for idx, src in enumerate(tgt.get('sources', [])): + if idx in processed_src_idx: + continue + + if src.get('isGenerated', False): + generated_src += [src['path']] + else: + normal_src += [src['path']] + + if normal_src: + tgt_data['fileGroups'] += [{ + 'isGenerated': False, + 'sources': normal_src, + }] + if generated_src: + tgt_data['fileGroups'] += [{ + 'isGenerated': True, + 'sources': generated_src, + }] + return tgt_data + + def parse_project(pro: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]: + # Only look at the first directory specified in directoryIndexes + # TODO Figure out what the other indexes are there for + p_src_dir = source_dir + p_bld_dir = build_dir + try: + p_src_dir, p_bld_dir = helper_parse_dir(cnf['directories'][pro['directoryIndexes'][0]]) + except (IndexError, KeyError): + pass + + pro_data = { + 'name': pro.get('name', ''), + 'sourceDirectory': p_src_dir, + 'buildDirectory': p_bld_dir, + 'targets': [], + } + + for ref in pro.get('targetIndexes', []): + tgt = {} + try: + tgt = cnf['targets'][ref] + except (IndexError, KeyError): + pass + pro_data['targets'] += [parse_target(tgt)] + + return pro_data + + for cnf in data.get('configurations', []): + cnf_data = { + 'name': cnf.get('name', ''), + 'projects': [], + } + + for pro in cnf.get('projects', []): + cnf_data['projects'] += [parse_project(pro)] + + self.cmake_configurations += [CMakeConfiguration(cnf_data)] + + def _parse_cmakeFiles(self, data: T.Dict[str, T.Any]) -> None: + assert 'inputs' in data + assert 'paths' in data + + src_dir = Path(data['paths']['source']) + + for i in data['inputs']: + path = Path(i['path']) + path = path if path.is_absolute() else src_dir / path + self.cmake_sources += [CMakeBuildFile(path, i.get('isCMake', False), i.get('isGenerated', False))] + + def _strip_data(self, data: T.Any) -> T.Any: + if isinstance(data, list): + for idx, i in enumerate(data): + data[idx] = self._strip_data(i) + + elif isinstance(data, dict): + new = {} + for key, val in data.items(): + if key not in STRIP_KEYS: + new[key] = self._strip_data(val) + data = new + + return data + + def _resolve_references(self, data: T.Any) -> T.Any: + if isinstance(data, list): + for idx, i in enumerate(data): + data[idx] = self._resolve_references(i) + + elif isinstance(data, dict): + # Check for the "magic" reference entry and insert + # it into the root data dict + if 'jsonFile' in data: + data.update(self._reply_file_content(data['jsonFile'])) + + for key, val in data.items(): + data[key] = self._resolve_references(val) + + return data + + def _reply_file_content(self, filename: Path) -> T.Dict[str, T.Any]: + real_path = self.reply_dir / filename + if not real_path.exists(): + raise CMakeException(f'File "{real_path}" does not exist') + + data = json.loads(real_path.read_text(encoding='utf-8')) + assert isinstance(data, dict) + for i in data.keys(): + assert isinstance(i, str) + return data diff --git a/devtools/meson/mesonbuild/cmake/generator.py b/devtools/meson/mesonbuild/cmake/generator.py new file mode 100644 index 0000000..7903dd4 --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/generator.py @@ -0,0 +1,196 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mesonlib +from .. import mlog +from .common import cmake_is_debug +import typing as T + +if T.TYPE_CHECKING: + from .traceparser import CMakeTraceParser, CMakeTarget + +def parse_generator_expressions( + raw: str, + trace: 'CMakeTraceParser', + *, + context_tgt: T.Optional['CMakeTarget'] = None, + ) -> str: + '''Parse CMake generator expressions + + Most generator expressions are simply ignored for + simplicety, however some are required for some common + use cases. + ''' + + # Early abort if no generator expression present + if '$<' not in raw: + return raw + + out = '' # type: str + i = 0 # type: int + + def equal(arg: str) -> str: + col_pos = arg.find(',') + if col_pos < 0: + return '0' + else: + return '1' if arg[:col_pos] == arg[col_pos + 1:] else '0' + + def vers_comp(op: str, arg: str) -> str: + col_pos = arg.find(',') + if col_pos < 0: + return '0' + else: + return '1' if mesonlib.version_compare(arg[:col_pos], '{}{}'.format(op, arg[col_pos + 1:])) else '0' + + def target_property(arg: str) -> str: + # We can't really support this since we don't have any context + if ',' not in arg: + if context_tgt is None: + return '' + return ';'.join(context_tgt.properties.get(arg, [])) + + args = arg.split(',') + props = trace.targets[args[0]].properties.get(args[1], []) if args[0] in trace.targets else [] + return ';'.join(props) + + def target_file(arg: str) -> str: + if arg not in trace.targets: + mlog.warning(f"Unable to evaluate the cmake variable '$'.") + return '' + tgt = trace.targets[arg] + + cfgs = [] + cfg = '' + + if 'IMPORTED_CONFIGURATIONS' in tgt.properties: + cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x] + cfg = cfgs[0] + + if cmake_is_debug(trace.env): + if 'DEBUG' in cfgs: + cfg = 'DEBUG' + elif 'RELEASE' in cfgs: + cfg = 'RELEASE' + else: + if 'RELEASE' in cfgs: + cfg = 'RELEASE' + + if f'IMPORTED_IMPLIB_{cfg}' in tgt.properties: + return ';'.join([x for x in tgt.properties[f'IMPORTED_IMPLIB_{cfg}'] if x]) + elif 'IMPORTED_IMPLIB' in tgt.properties: + return ';'.join([x for x in tgt.properties['IMPORTED_IMPLIB'] if x]) + elif f'IMPORTED_LOCATION_{cfg}' in tgt.properties: + return ';'.join([x for x in tgt.properties[f'IMPORTED_LOCATION_{cfg}'] if x]) + elif 'IMPORTED_LOCATION' in tgt.properties: + return ';'.join([x for x in tgt.properties['IMPORTED_LOCATION'] if x]) + return '' + + supported = { + # Boolean functions + 'BOOL': lambda x: '0' if x.upper() in {'0', 'FALSE', 'OFF', 'N', 'NO', 'IGNORE', 'NOTFOUND'} or x.endswith('-NOTFOUND') else '1', + 'AND': lambda x: '1' if all(y == '1' for y in x.split(',')) else '0', + 'OR': lambda x: '1' if any(y == '1' for y in x.split(',')) else '0', + 'NOT': lambda x: '0' if x == '1' else '1', + + 'IF': lambda x: x.split(',')[1] if x.split(',')[0] == '1' else x.split(',')[2], + + '0': lambda x: '', + '1': lambda x: x, + + # String operations + 'STREQUAL': equal, + 'EQUAL': equal, + 'VERSION_LESS': lambda x: vers_comp('<', x), + 'VERSION_GREATER': lambda x: vers_comp('>', x), + 'VERSION_EQUAL': lambda x: vers_comp('=', x), + 'VERSION_LESS_EQUAL': lambda x: vers_comp('<=', x), + 'VERSION_GREATER_EQUAL': lambda x: vers_comp('>=', x), + + # String modification + 'LOWER_CASE': lambda x: x.lower(), + 'UPPER_CASE': lambda x: x.upper(), + + # Always assume the BUILD_INTERFACE is valid. + # INSTALL_INTERFACE is always invalid for subprojects and + # it should also never appear in CMake config files, used + # for dependencies + 'INSTALL_INTERFACE': lambda x: '', + 'BUILD_INTERFACE': lambda x: x, + + # Constants + 'ANGLE-R': lambda x: '>', + 'COMMA': lambda x: ',', + 'SEMICOLON': lambda x: ';', + + # Target related expressions + 'TARGET_EXISTS': lambda x: '1' if x in trace.targets else '0', + 'TARGET_NAME_IF_EXISTS': lambda x: x if x in trace.targets else '', + 'TARGET_PROPERTY': target_property, + 'TARGET_FILE': target_file, + } # type: T.Dict[str, T.Callable[[str], str]] + + # Recursively evaluate generator expressions + def eval_generator_expressions() -> str: + nonlocal i + i += 2 + + func = '' # type: str + args = '' # type: str + res = '' # type: str + exp = '' # type: str + + # Determine the body of the expression + while i < len(raw): + if raw[i] == '>': + # End of the generator expression + break + elif i < len(raw) - 1 and raw[i] == '$' and raw[i + 1] == '<': + # Nested generator expression + exp += eval_generator_expressions() + else: + # Generator expression body + exp += raw[i] + + i += 1 + + # Split the expression into a function and arguments part + col_pos = exp.find(':') + if col_pos < 0: + func = exp + else: + func = exp[:col_pos] + args = exp[col_pos + 1:] + + func = func.strip() + args = args.strip() + + # Evaluate the function + if func in supported: + res = supported[func](args) + + return res + + while i < len(raw): + if i < len(raw) - 1 and raw[i] == '$' and raw[i + 1] == '<': + # Generator expression detected --> try resolving it + out += eval_generator_expressions() + else: + # Normal string, leave unchanged + out += raw[i] + + i += 1 + + return out diff --git a/devtools/meson/mesonbuild/cmake/interpreter.py b/devtools/meson/mesonbuild/cmake/interpreter.py new file mode 100644 index 0000000..f88d091 --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/interpreter.py @@ -0,0 +1,1266 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. +from __future__ import annotations + +from functools import lru_cache +from os import environ +from pathlib import Path +import re +import typing as T + +from .common import CMakeException, CMakeTarget, language_map, cmake_get_generator_args, check_cmake_args +from .fileapi import CMakeFileAPI +from .executor import CMakeExecutor +from .toolchain import CMakeToolchain, CMakeExecScope +from .traceparser import CMakeTraceParser +from .tracetargets import resolve_cmake_trace_targets +from .. import mlog, mesonlib +from ..mesonlib import MachineChoice, OrderedSet, path_is_in_root, relative_to_if_possible, OptionKey +from ..mesondata import DataFile +from ..compilers.compilers import assembler_suffixes, lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header +from ..programs import ExternalProgram +from ..coredata import FORBIDDEN_TARGET_NAMES +from ..mparser import ( + Token, + BaseNode, + CodeBlockNode, + FunctionNode, + ArrayNode, + ArgumentNode, + AssignmentNode, + BooleanNode, + StringNode, + IdNode, + IndexNode, + MethodNode, + NumberNode, +) + + +if T.TYPE_CHECKING: + from .common import CMakeConfiguration, TargetOptions + from .traceparser import CMakeGeneratorTarget + from .._typing import ImmutableListProtocol + from ..build import Build + from ..backend.backends import Backend + from ..environment import Environment + + TYPE_mixed = T.Union[str, int, bool, Path, BaseNode] + TYPE_mixed_list = T.Union[TYPE_mixed, T.Sequence[TYPE_mixed]] + TYPE_mixed_kwargs = T.Dict[str, TYPE_mixed_list] + +# Disable all warnings automatically enabled with --trace and friends +# See https://cmake.org/cmake/help/latest/variable/CMAKE_POLICY_WARNING_CMPNNNN.html +disable_policy_warnings = [ + 'CMP0025', + 'CMP0047', + 'CMP0056', + 'CMP0060', + 'CMP0065', + 'CMP0066', + 'CMP0067', + 'CMP0082', + 'CMP0089', + 'CMP0102', +] + +target_type_map = { + 'STATIC_LIBRARY': 'static_library', + 'MODULE_LIBRARY': 'shared_module', + 'SHARED_LIBRARY': 'shared_library', + 'EXECUTABLE': 'executable', + 'OBJECT_LIBRARY': 'static_library', + 'INTERFACE_LIBRARY': 'header_only' +} + +skip_targets = ['UTILITY'] + +blacklist_compiler_flags = [ + '-Wall', '-Wextra', '-Weverything', '-Werror', '-Wpedantic', '-pedantic', '-w', + '/W1', '/W2', '/W3', '/W4', '/Wall', '/WX', '/w', + '/O1', '/O2', '/Ob', '/Od', '/Og', '/Oi', '/Os', '/Ot', '/Ox', '/Oy', '/Ob0', + '/RTC1', '/RTCc', '/RTCs', '/RTCu', + '/Z7', '/Zi', '/ZI', +] + +blacklist_link_flags = [ + '/machine:x64', '/machine:x86', '/machine:arm', '/machine:ebc', + '/debug', '/debug:fastlink', '/debug:full', '/debug:none', + '/incremental', +] + +blacklist_clang_cl_link_flags = ['/GR', '/EHsc', '/MDd', '/Zi', '/RTC1'] + +blacklist_link_libs = [ + 'kernel32.lib', + 'user32.lib', + 'gdi32.lib', + 'winspool.lib', + 'shell32.lib', + 'ole32.lib', + 'oleaut32.lib', + 'uuid.lib', + 'comdlg32.lib', + 'advapi32.lib' +] + +transfer_dependencies_from = ['header_only'] + +_cmake_name_regex = re.compile(r'[^_a-zA-Z0-9]') +def _sanitize_cmake_name(name: str) -> str: + name = _cmake_name_regex.sub('_', name) + if name in FORBIDDEN_TARGET_NAMES or name.startswith('meson'): + name = 'cm_' + name + return name + +class OutputTargetMap: + rm_so_version = re.compile(r'(\.[0-9]+)+$') + + def __init__(self, build_dir: Path): + self.tgt_map: T.Dict[str, T.Union['ConverterTarget', 'ConverterCustomTarget']] = {} + self.build_dir = build_dir + + def add(self, tgt: T.Union['ConverterTarget', 'ConverterCustomTarget']) -> None: + def assign_keys(keys: T.List[str]) -> None: + for i in [x for x in keys if x]: + self.tgt_map[i] = tgt + keys = [self._target_key(tgt.cmake_name)] + if isinstance(tgt, ConverterTarget): + keys += [tgt.full_name] + keys += [self._rel_artifact_key(x) for x in tgt.artifacts] + keys += [self._base_artifact_key(x) for x in tgt.artifacts] + if isinstance(tgt, ConverterCustomTarget): + keys += [self._rel_generated_file_key(x) for x in tgt.original_outputs] + keys += [self._base_generated_file_key(x) for x in tgt.original_outputs] + assign_keys(keys) + + def _return_first_valid_key(self, keys: T.List[str]) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]: + for i in keys: + if i and i in self.tgt_map: + return self.tgt_map[i] + return None + + def target(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]: + return self._return_first_valid_key([self._target_key(name)]) + + def executable(self, name: str) -> T.Optional['ConverterTarget']: + tgt = self.target(name) + if tgt is None or not isinstance(tgt, ConverterTarget): + return None + if tgt.meson_func() != 'executable': + return None + return tgt + + def artifact(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]: + keys = [] + candidates = [name, OutputTargetMap.rm_so_version.sub('', name)] + for i in lib_suffixes: + if not name.endswith('.' + i): + continue + new_name = name[:-len(i) - 1] + new_name = OutputTargetMap.rm_so_version.sub('', new_name) + candidates += [f'{new_name}.{i}'] + for i in candidates: + keys += [self._rel_artifact_key(Path(i)), Path(i).name, self._base_artifact_key(Path(i))] + return self._return_first_valid_key(keys) + + def generated(self, name: Path) -> T.Optional['ConverterCustomTarget']: + res = self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)]) + assert res is None or isinstance(res, ConverterCustomTarget) + return res + + # Utility functions to generate local keys + def _rel_path(self, fname: Path) -> T.Optional[Path]: + try: + return fname.resolve().relative_to(self.build_dir) + except ValueError: + pass + return None + + def _target_key(self, tgt_name: str) -> str: + return f'__tgt_{tgt_name}__' + + def _rel_generated_file_key(self, fname: Path) -> T.Optional[str]: + path = self._rel_path(fname) + return f'__relgen_{path.as_posix()}__' if path else None + + def _base_generated_file_key(self, fname: Path) -> str: + return f'__gen_{fname.name}__' + + def _rel_artifact_key(self, fname: Path) -> T.Optional[str]: + path = self._rel_path(fname) + return f'__relart_{path.as_posix()}__' if path else None + + def _base_artifact_key(self, fname: Path) -> str: + return f'__art_{fname.name}__' + +class ConverterTarget: + def __init__(self, target: CMakeTarget, env: 'Environment', for_machine: MachineChoice) -> None: + self.env = env + self.for_machine = for_machine + self.artifacts = target.artifacts + self.src_dir = target.src_dir + self.build_dir = target.build_dir + self.name = target.name + self.cmake_name = target.name + self.full_name = target.full_name + self.type = target.type + self.install = target.install + self.install_dir: T.Optional[Path] = None + self.link_libraries = target.link_libraries + self.link_flags = target.link_flags + target.link_lang_flags + self.depends_raw: T.List[str] = [] + self.depends: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] = [] + + if target.install_paths: + self.install_dir = target.install_paths[0] + + self.languages: T.Set[str] = set() + self.sources: T.List[Path] = [] + self.generated: T.List[Path] = [] + self.generated_ctgt: T.List[CustomTargetReference] = [] + self.includes: T.List[Path] = [] + self.sys_includes: T.List[Path] = [] + self.link_with: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] = [] + self.object_libs: T.List[ConverterTarget] = [] + self.compile_opts: T.Dict[str, T.List[str]] = {} + self.public_compile_opts: T.List[str] = [] + self.pie = False + + # Project default override options (c_std, cpp_std, etc.) + self.override_options: T.List[str] = [] + + # Convert the target name to a valid meson target name + self.name = _sanitize_cmake_name(self.name) + + self.generated_raw: T.List[Path] = [] + + for i in target.files: + languages: T.Set[str] = set() + src_suffixes: T.Set[str] = set() + + # Insert suffixes + for j in i.sources: + if not j.suffix: + continue + src_suffixes.add(j.suffix[1:]) + + # Determine the meson language(s) + # Extract the default language from the explicit CMake field + lang_cmake_to_meson = {val.lower(): key for key, val in language_map.items()} + languages.add(lang_cmake_to_meson.get(i.language.lower(), 'c')) + + # Determine missing languages from the source suffixes + for sfx in src_suffixes: + for key, val in lang_suffixes.items(): + if sfx in val: + languages.add(key) + break + + # Register the new languages and initialize the compile opts array + for lang in languages: + self.languages.add(lang) + if lang not in self.compile_opts: + self.compile_opts[lang] = [] + + # Add arguments, but avoid duplicates + args = i.flags + args += [f'-D{x}' for x in i.defines] + for lang in languages: + self.compile_opts[lang] += [x for x in args if x not in self.compile_opts[lang]] + + # Handle include directories + self.includes += [x.path for x in i.includes if x.path not in self.includes and not x.isSystem] + self.sys_includes += [x.path for x in i.includes if x.path not in self.sys_includes and x.isSystem] + + # Add sources to the right array + if i.is_generated: + self.generated_raw += i.sources + else: + self.sources += i.sources + + def __repr__(self) -> str: + return f'<{self.__class__.__name__}: {self.name}>' + + std_regex = re.compile(r'([-]{1,2}std=|/std:v?|[-]{1,2}std:)(.*)') + + def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, subdir: Path, install_prefix: Path, trace: CMakeTraceParser) -> None: + # Detect setting the C and C++ standard and do additional compiler args manipulation + for i in ['c', 'cpp']: + if i not in self.compile_opts: + continue + + temp = [] + for j in self.compile_opts[i]: + m = ConverterTarget.std_regex.match(j) + ctgt = output_target_map.generated(Path(j)) + if m: + std = m.group(2) + supported = self._all_lang_stds(i) + if std not in supported: + mlog.warning( + 'Unknown {0}_std "{1}" -> Ignoring. Try setting the project-' + 'level {0}_std if build errors occur. Known ' + '{0}_stds are: {2}'.format(i, std, ' '.join(supported)), + once=True + ) + continue + self.override_options += [f'{i}_std={std}'] + elif j in {'-fPIC', '-fpic', '-fPIE', '-fpie'}: + self.pie = True + elif isinstance(ctgt, ConverterCustomTarget): + # Sometimes projects pass generated source files as compiler + # flags. Add these as generated sources to ensure that the + # corresponding custom target is run.2 + self.generated_raw += [Path(j)] + temp += [j] + elif j in blacklist_compiler_flags: + pass + else: + temp += [j] + + self.compile_opts[i] = temp + + # Make sure to force enable -fPIC for OBJECT libraries + if self.type.upper() == 'OBJECT_LIBRARY': + self.pie = True + + # Use the CMake trace, if required + tgt = trace.targets.get(self.cmake_name) + if tgt: + self.depends_raw = trace.targets[self.cmake_name].depends + + rtgt = resolve_cmake_trace_targets(self.cmake_name, trace, self.env) + self.includes += [Path(x) for x in rtgt.include_directories] + self.link_flags += rtgt.link_flags + self.public_compile_opts += rtgt.public_compile_opts + self.link_libraries += rtgt.libraries + + elif self.type.upper() not in ['EXECUTABLE', 'OBJECT_LIBRARY']: + mlog.warning('CMake: Target', mlog.bold(self.cmake_name), 'not found in CMake trace. This can lead to build errors') + + temp = [] + for i in self.link_libraries: + # Let meson handle this arcane magic + if ',-rpath,' in i: + continue + if not Path(i).is_absolute(): + link_with = output_target_map.artifact(i) + if link_with: + self.link_with += [link_with] + continue + + temp += [i] + self.link_libraries = temp + + # Filter out files that are not supported by the language + supported = list(assembler_suffixes) + list(header_suffixes) + list(obj_suffixes) + for i in self.languages: + supported += list(lang_suffixes[i]) + supported = [f'.{x}' for x in supported] + self.sources = [x for x in self.sources if any(x.name.endswith(y) for y in supported)] + self.generated_raw = [x for x in self.generated_raw if any(x.name.endswith(y) for y in supported)] + + # Make paths relative + def rel_path(x: Path, is_header: bool, is_generated: bool) -> T.Optional[Path]: + if not x.is_absolute(): + x = self.src_dir / x + x = x.resolve() + assert x.is_absolute() + if not x.exists() and not any(x.name.endswith(y) for y in obj_suffixes) and not is_generated: + if path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True): + x.mkdir(parents=True, exist_ok=True) + return x.relative_to(Path(self.env.get_build_dir()) / subdir) + else: + mlog.warning('CMake: path', mlog.bold(x.as_posix()), 'does not exist.') + mlog.warning(' --> Ignoring. This can lead to build errors.') + return None + if x in trace.explicit_headers: + return None + if ( + path_is_in_root(x, Path(self.env.get_source_dir())) + and not ( + path_is_in_root(x, root_src_dir) or + path_is_in_root(x, Path(self.env.get_build_dir())) + ) + ): + mlog.warning('CMake: path', mlog.bold(x.as_posix()), 'is inside the root project but', mlog.bold('not'), 'inside the subproject.') + mlog.warning(' --> Ignoring. This can lead to build errors.') + return None + if path_is_in_root(x, Path(self.env.get_build_dir())) and is_header: + return x.relative_to(Path(self.env.get_build_dir()) / subdir) + if path_is_in_root(x, root_src_dir): + return x.relative_to(root_src_dir) + return x + + build_dir_rel = self.build_dir.relative_to(Path(self.env.get_build_dir()) / subdir) + self.generated_raw = [rel_path(x, False, True) for x in self.generated_raw] + self.includes = list(OrderedSet([rel_path(x, True, False) for x in OrderedSet(self.includes)] + [build_dir_rel])) + self.sys_includes = list(OrderedSet([rel_path(x, True, False) for x in OrderedSet(self.sys_includes)])) + self.sources = [rel_path(x, False, False) for x in self.sources] + + # Resolve custom targets + for gen_file in self.generated_raw: + ctgt = output_target_map.generated(gen_file) + if ctgt: + assert isinstance(ctgt, ConverterCustomTarget) + ref = ctgt.get_ref(gen_file) + assert isinstance(ref, CustomTargetReference) and ref.valid() + self.generated_ctgt += [ref] + elif gen_file is not None: + self.generated += [gen_file] + + # Remove delete entries + self.includes = [x for x in self.includes if x is not None] + self.sys_includes = [x for x in self.sys_includes if x is not None] + self.sources = [x for x in self.sources if x is not None] + + # Make sure '.' is always in the include directories + if Path('.') not in self.includes: + self.includes += [Path('.')] + + # make install dir relative to the install prefix + if self.install_dir and self.install_dir.is_absolute(): + if path_is_in_root(self.install_dir, install_prefix): + self.install_dir = self.install_dir.relative_to(install_prefix) + + # Remove blacklisted options and libs + def check_flag(flag: str) -> bool: + if flag.lower() in blacklist_link_flags or flag in blacklist_compiler_flags + blacklist_clang_cl_link_flags: + return False + if flag.startswith('/D'): + return False + return True + + self.link_libraries = [x for x in self.link_libraries if x.lower() not in blacklist_link_libs] + self.link_flags = [x for x in self.link_flags if check_flag(x)] + + # Handle OSX frameworks + def handle_frameworks(flags: T.List[str]) -> T.List[str]: + res: T.List[str] = [] + for i in flags: + p = Path(i) + if not p.exists() or not p.name.endswith('.framework'): + res += [i] + continue + res += ['-framework', p.stem] + return res + + self.link_libraries = handle_frameworks(self.link_libraries) + self.link_flags = handle_frameworks(self.link_flags) + + # Handle explicit CMake add_dependency() calls + for i in self.depends_raw: + dep_tgt = output_target_map.target(i) + if dep_tgt: + self.depends.append(dep_tgt) + + def process_object_libs(self, obj_target_list: T.List['ConverterTarget'], linker_workaround: bool) -> None: + # Try to detect the object library(s) from the generated input sources + temp = [x for x in self.generated if any(x.name.endswith('.' + y) for y in obj_suffixes)] + stem = [x.stem for x in temp] + exts = self._all_source_suffixes() + # Temp now stores the source filenames of the object files + for i in obj_target_list: + source_files = [x.name for x in i.sources + i.generated] + for j in stem: + # On some platforms (specifically looking at you Windows with vs20xy backend) CMake does + # not produce object files with the format `foo.cpp.obj`, instead it skipps the language + # suffix and just produces object files like `foo.obj`. Thus we have to do our best to + # undo this step and guess the correct language suffix of the object file. This is done + # by trying all language suffixes meson knows and checking if one of them fits. + candidates = [j] + if not any(j.endswith('.' + x) for x in exts): + mlog.warning('Object files do not contain source file extensions, thus falling back to guessing them.', once=True) + candidates += [f'{j}.{x}' for x in exts] + if any(x in source_files for x in candidates): + if linker_workaround: + self._append_objlib_sources(i) + else: + self.includes += i.includes + self.includes = list(OrderedSet(self.includes)) + self.object_libs += [i] + break + + # Filter out object files from the sources + self.generated = [x for x in self.generated if not any(x.name.endswith('.' + y) for y in obj_suffixes)] + + def _append_objlib_sources(self, tgt: 'ConverterTarget') -> None: + self.includes += tgt.includes + self.sources += tgt.sources + self.generated += tgt.generated + self.generated_ctgt += tgt.generated_ctgt + self.includes = list(OrderedSet(self.includes)) + self.sources = list(OrderedSet(self.sources)) + self.generated = list(OrderedSet(self.generated)) + self.generated_ctgt = list(OrderedSet(self.generated_ctgt)) + + # Inherit compiler arguments since they may be required for building + for lang, opts in tgt.compile_opts.items(): + if lang not in self.compile_opts: + self.compile_opts[lang] = [] + self.compile_opts[lang] += [x for x in opts if x not in self.compile_opts[lang]] + + @lru_cache(maxsize=None) + def _all_source_suffixes(self) -> 'ImmutableListProtocol[str]': + suffixes: T.List[str] = [] + for exts in lang_suffixes.values(): + suffixes.extend(exts) + return suffixes + + @lru_cache(maxsize=None) + def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]': + try: + res = self.env.coredata.options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices + except KeyError: + return [] + + # TODO: Get rid of this once we have proper typing for options + assert isinstance(res, list) + for i in res: + assert isinstance(i, str) + + return res + + def process_inter_target_dependencies(self) -> None: + # Move the dependencies from all transfer_dependencies_from to the target + to_process = list(self.depends) + processed = [] + new_deps = [] + for i in to_process: + processed += [i] + if isinstance(i, ConverterTarget) and i.meson_func() in transfer_dependencies_from: + to_process += [x for x in i.depends if x not in processed] + else: + new_deps += [i] + self.depends = list(OrderedSet(new_deps)) + + def cleanup_dependencies(self) -> None: + # Clear the dependencies from targets that where moved from + if self.meson_func() in transfer_dependencies_from: + self.depends = [] + + def meson_func(self) -> str: + return target_type_map.get(self.type.upper()) + + def log(self) -> None: + mlog.log('Target', mlog.bold(self.name), f'({self.cmake_name})') + mlog.log(' -- artifacts: ', mlog.bold(str(self.artifacts))) + mlog.log(' -- full_name: ', mlog.bold(self.full_name)) + mlog.log(' -- type: ', mlog.bold(self.type)) + mlog.log(' -- install: ', mlog.bold('true' if self.install else 'false')) + mlog.log(' -- install_dir: ', mlog.bold(self.install_dir.as_posix() if self.install_dir else '')) + mlog.log(' -- link_libraries: ', mlog.bold(str(self.link_libraries))) + mlog.log(' -- link_with: ', mlog.bold(str(self.link_with))) + mlog.log(' -- object_libs: ', mlog.bold(str(self.object_libs))) + mlog.log(' -- link_flags: ', mlog.bold(str(self.link_flags))) + mlog.log(' -- languages: ', mlog.bold(str(self.languages))) + mlog.log(' -- includes: ', mlog.bold(str(self.includes))) + mlog.log(' -- sys_includes: ', mlog.bold(str(self.sys_includes))) + mlog.log(' -- sources: ', mlog.bold(str(self.sources))) + mlog.log(' -- generated: ', mlog.bold(str(self.generated))) + mlog.log(' -- generated_ctgt: ', mlog.bold(str(self.generated_ctgt))) + mlog.log(' -- pie: ', mlog.bold('true' if self.pie else 'false')) + mlog.log(' -- override_opts: ', mlog.bold(str(self.override_options))) + mlog.log(' -- depends: ', mlog.bold(str(self.depends))) + mlog.log(' -- options:') + for key, val in self.compile_opts.items(): + mlog.log(' -', key, '=', mlog.bold(str(val))) + +class CustomTargetReference: + def __init__(self, ctgt: 'ConverterCustomTarget', index: int) -> None: + self.ctgt = ctgt + self.index = index + + def __repr__(self) -> str: + if self.valid(): + return '<{}: {} [{}]>'.format(self.__class__.__name__, self.ctgt.name, self.ctgt.outputs[self.index]) + else: + return f'<{self.__class__.__name__}: INVALID REFERENCE>' + + def valid(self) -> bool: + return self.ctgt is not None and self.index >= 0 + + def filename(self) -> str: + return self.ctgt.outputs[self.index] + +class ConverterCustomTarget: + tgt_counter = 0 + out_counter = 0 + + def __init__(self, target: CMakeGeneratorTarget, env: 'Environment', for_machine: MachineChoice) -> None: + assert target.current_bin_dir is not None + assert target.current_src_dir is not None + self.name = target.name + if not self.name: + self.name = f'custom_tgt_{ConverterCustomTarget.tgt_counter}' + ConverterCustomTarget.tgt_counter += 1 + self.cmake_name = str(self.name) + self.original_outputs = list(target.outputs) + self.outputs = [x.name for x in self.original_outputs] + self.conflict_map: T.Dict[str, str] = {} + self.command: T.List[T.List[T.Union[str, ConverterTarget]]] = [] + self.working_dir = target.working_dir + self.depends_raw = target.depends + self.inputs: T.List[T.Union[str, CustomTargetReference]] = [] + self.depends: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] = [] + self.current_bin_dir = target.current_bin_dir + self.current_src_dir = target.current_src_dir + self.env = env + self.for_machine = for_machine + self._raw_target = target + + # Convert the target name to a valid meson target name + self.name = _sanitize_cmake_name(self.name) + + def __repr__(self) -> str: + return f'<{self.__class__.__name__}: {self.name} {self.outputs}>' + + def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, all_outputs: T.List[str], trace: CMakeTraceParser) -> None: + # Default the working directory to ${CMAKE_CURRENT_BINARY_DIR} + if self.working_dir is None: + self.working_dir = self.current_bin_dir + + # relative paths in the working directory are always relative + # to ${CMAKE_CURRENT_BINARY_DIR} + if not self.working_dir.is_absolute(): + self.working_dir = self.current_bin_dir / self.working_dir + + # Modify the original outputs if they are relative. Again, + # relative paths are relative to ${CMAKE_CURRENT_BINARY_DIR} + def ensure_absolute(x: Path) -> Path: + if x.is_absolute(): + return x + else: + return self.current_bin_dir / x + self.original_outputs = [ensure_absolute(x) for x in self.original_outputs] + + # Ensure that there is no duplicate output in the project so + # that meson can handle cases where the same filename is + # generated in multiple directories + temp_outputs: T.List[str] = [] + for i in self.outputs: + if i in all_outputs: + old = str(i) + i = f'c{ConverterCustomTarget.out_counter}_{i}' + ConverterCustomTarget.out_counter += 1 + self.conflict_map[old] = i + all_outputs += [i] + temp_outputs += [i] + self.outputs = temp_outputs + + # Check if the command is a build target + commands: T.List[T.List[T.Union[str, ConverterTarget]]] = [] + for curr_cmd in self._raw_target.command: + assert isinstance(curr_cmd, list) + assert curr_cmd[0] != '', "An empty string is not a valid executable" + cmd: T.List[T.Union[str, ConverterTarget]] = [] + + for j in curr_cmd: + if not j: + continue + target = output_target_map.executable(j) + if target: + # When cross compiling, binaries have to be executed with an exe_wrapper (for instance wine for mingw-w64) + if self.env.exe_wrapper is not None and self.env.properties[self.for_machine].get_cmake_use_exe_wrapper(): + assert isinstance(self.env.exe_wrapper, ExternalProgram) + cmd += self.env.exe_wrapper.get_command() + cmd += [target] + continue + elif j in trace.targets: + trace_tgt = trace.targets[j] + if trace_tgt.type == 'EXECUTABLE' and 'IMPORTED_LOCATION' in trace_tgt.properties: + cmd += trace_tgt.properties['IMPORTED_LOCATION'] + continue + mlog.debug(f'CMake: Found invalid CMake target "{j}" --> ignoring \n{trace_tgt}') + + # Fallthrough on error + cmd += [j] + + commands += [cmd] + self.command = commands + + # If the custom target does not declare any output, create a dummy + # one that can be used as dependency. + if not self.outputs: + self.outputs = [self.name + '.h'] + + # Check dependencies and input files + for i in self.depends_raw: + if not i: + continue + raw = Path(i) + art = output_target_map.artifact(i) + tgt = output_target_map.target(i) + gen = output_target_map.generated(raw) + + rel_to_root = None + try: + rel_to_root = raw.relative_to(root_src_dir) + except ValueError: + rel_to_root = None + + # First check for existing files. Only then check for existing + # targets, etc. This reduces the chance of misdetecting input files + # as outputs from other targets. + # See https://github.com/mesonbuild/meson/issues/6632 + if not raw.is_absolute() and (self.current_src_dir / raw).is_file(): + self.inputs += [(self.current_src_dir / raw).relative_to(root_src_dir).as_posix()] + elif raw.is_absolute() and raw.exists() and rel_to_root is not None: + self.inputs += [rel_to_root.as_posix()] + elif art: + self.depends += [art] + elif tgt: + self.depends += [tgt] + elif gen: + ctgt_ref = gen.get_ref(raw) + assert ctgt_ref is not None + self.inputs += [ctgt_ref] + + def process_inter_target_dependencies(self) -> None: + # Move the dependencies from all transfer_dependencies_from to the target + to_process = list(self.depends) + processed = [] + new_deps = [] + for i in to_process: + processed += [i] + if isinstance(i, ConverterTarget) and i.meson_func() in transfer_dependencies_from: + to_process += [x for x in i.depends if x not in processed] + else: + new_deps += [i] + self.depends = list(OrderedSet(new_deps)) + + def get_ref(self, fname: Path) -> T.Optional[CustomTargetReference]: + name = fname.name + try: + if name in self.conflict_map: + name = self.conflict_map[name] + idx = self.outputs.index(name) + return CustomTargetReference(self, idx) + except ValueError: + return None + + def log(self) -> None: + mlog.log('Custom Target', mlog.bold(self.name), f'({self.cmake_name})') + mlog.log(' -- command: ', mlog.bold(str(self.command))) + mlog.log(' -- outputs: ', mlog.bold(str(self.outputs))) + mlog.log(' -- conflict_map: ', mlog.bold(str(self.conflict_map))) + mlog.log(' -- working_dir: ', mlog.bold(str(self.working_dir))) + mlog.log(' -- depends_raw: ', mlog.bold(str(self.depends_raw))) + mlog.log(' -- inputs: ', mlog.bold(str(self.inputs))) + mlog.log(' -- depends: ', mlog.bold(str(self.depends))) + +class CMakeInterpreter: + def __init__(self, build: 'Build', subdir: Path, src_dir: Path, install_prefix: Path, env: 'Environment', backend: 'Backend'): + self.build = build + self.subdir = subdir + self.src_dir = src_dir + self.build_dir_rel = subdir / '__CMake_build' + self.build_dir = Path(env.get_build_dir()) / self.build_dir_rel + self.install_prefix = install_prefix + self.env = env + self.for_machine = MachineChoice.HOST # TODO make parameter + self.backend_name = backend.name + self.linkers: T.Set[str] = set() + self.fileapi = CMakeFileAPI(self.build_dir) + + # Raw CMake results + self.bs_files: T.List[Path] = [] + self.codemodel_configs: T.Optional[T.List[CMakeConfiguration]] = None + self.cmake_stderr: T.Optional[str] = None + + # Analysed data + self.project_name = '' + self.languages: T.List[str] = [] + self.targets: T.List[ConverterTarget] = [] + self.custom_targets: T.List[ConverterCustomTarget] = [] + self.trace: CMakeTraceParser + self.output_target_map = OutputTargetMap(self.build_dir) + + # Generated meson data + self.generated_targets: T.Dict[str, T.Dict[str, T.Optional[str]]] = {} + self.internal_name_map: T.Dict[str, str] = {} + + # Do some special handling for object libraries for certain configurations + self._object_lib_workaround = False + if self.backend_name.startswith('vs'): + for comp in self.env.coredata.compilers[self.for_machine].values(): + if comp.get_linker_id() == 'link': + self._object_lib_workaround = True + break + + def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor: + # Find CMake + # TODO: Using MachineChoice.BUILD should always be correct here, but also evaluate the use of self.for_machine + cmake_exe = CMakeExecutor(self.env, '>=3.14', MachineChoice.BUILD) + if not cmake_exe.found(): + raise CMakeException('Unable to find CMake') + self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, self.env, permissive=True) + + preload_file = DataFile('cmake/data/preload.cmake').write_to_private(self.env) + toolchain = CMakeToolchain(cmake_exe, self.env, self.for_machine, CMakeExecScope.SUBPROJECT, self.build_dir, preload_file) + toolchain_file = toolchain.write() + + # TODO: drop this check once the deprecated `cmake_args` kwarg is removed + extra_cmake_options = check_cmake_args(extra_cmake_options) + + cmake_args = [] + cmake_args += cmake_get_generator_args(self.env) + cmake_args += [f'-DCMAKE_INSTALL_PREFIX={self.install_prefix}'] + cmake_args += extra_cmake_options + trace_args = self.trace.trace_args() + cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in disable_policy_warnings] + + self.fileapi.setup_request() + + # Run CMake + mlog.log() + with mlog.nested(): + mlog.log('Configuring the build directory with', mlog.bold('CMake'), 'version', mlog.cyan(cmake_exe.version())) + mlog.log(mlog.bold('Running CMake with:'), ' '.join(cmake_args)) + mlog.log(mlog.bold(' - build directory: '), self.build_dir.as_posix()) + mlog.log(mlog.bold(' - source directory: '), self.src_dir.as_posix()) + mlog.log(mlog.bold(' - toolchain file: '), toolchain_file.as_posix()) + mlog.log(mlog.bold(' - preload file: '), preload_file.as_posix()) + mlog.log(mlog.bold(' - trace args: '), ' '.join(trace_args)) + mlog.log(mlog.bold(' - disabled policy warnings:'), '[{}]'.format(', '.join(disable_policy_warnings))) + mlog.log() + self.build_dir.mkdir(parents=True, exist_ok=True) + os_env = environ.copy() + os_env['LC_ALL'] = 'C' + final_args = cmake_args + trace_args + cmcmp_args + toolchain.get_cmake_args() + [self.src_dir.as_posix()] + + cmake_exe.set_exec_mode(print_cmout=True, always_capture_stderr=self.trace.requires_stderr()) + rc, _, self.cmake_stderr = cmake_exe.call(final_args, self.build_dir, env=os_env, disable_cache=True) + + mlog.log() + h = mlog.green('SUCCEEDED') if rc == 0 else mlog.red('FAILED') + mlog.log('CMake configuration:', h) + if rc != 0: + # get the last CMake error - We only need the message function for this: + self.trace.functions = {'message': self.trace.functions['message']} + self.trace.parse(self.cmake_stderr) + error = f': {self.trace.errors[-1]}' if self.trace.errors else '' + raise CMakeException(f'Failed to configure the CMake subproject{error}') + + return cmake_exe + + def initialise(self, extra_cmake_options: T.List[str]) -> None: + # Configure the CMake project to generate the file API data + self.configure(extra_cmake_options) + + # Parse the result + self.fileapi.load_reply() + + # Load the buildsystem file list + cmake_files = self.fileapi.get_cmake_sources() + self.bs_files = [x.file for x in cmake_files if not x.is_cmake and not x.is_temp] + self.bs_files = [relative_to_if_possible(x, Path(self.env.get_source_dir())) for x in self.bs_files] + 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)] + self.bs_files = list(OrderedSet(self.bs_files)) + + # Load the codemodel configurations + self.codemodel_configs = self.fileapi.get_cmake_configurations() + + def analyse(self) -> None: + if self.codemodel_configs is None: + raise CMakeException('CMakeInterpreter was not initialized') + + # Clear analyser data + self.project_name = '' + self.languages = [] + self.targets = [] + self.custom_targets = [] + + # Parse the trace + self.trace.parse(self.cmake_stderr) + + # Find all targets + added_target_names: T.List[str] = [] + for i_0 in self.codemodel_configs: + for j_0 in i_0.projects: + if not self.project_name: + self.project_name = j_0.name + for k_0 in j_0.targets: + # Avoid duplicate targets from different configurations and known + # dummy CMake internal target types + if k_0.type not in skip_targets and k_0.name not in added_target_names: + added_target_names += [k_0.name] + self.targets += [ConverterTarget(k_0, self.env, self.for_machine)] + + # Add interface targets from trace, if not already present. + # This step is required because interface targets were removed from + # the CMake file API output. + api_target_name_list = [x.name for x in self.targets] + for i_1 in self.trace.targets.values(): + if i_1.type != 'INTERFACE' or i_1.name in api_target_name_list or i_1.imported: + continue + dummy = CMakeTarget({ + 'name': i_1.name, + 'type': 'INTERFACE_LIBRARY', + 'sourceDirectory': self.src_dir, + 'buildDirectory': self.build_dir, + }) + self.targets += [ConverterTarget(dummy, self.env, self.for_machine)] + + for i_2 in self.trace.custom_targets: + self.custom_targets += [ConverterCustomTarget(i_2, self.env, self.for_machine)] + + # generate the output_target_map + for i_3 in [*self.targets, *self.custom_targets]: + assert isinstance(i_3, (ConverterTarget, ConverterCustomTarget)) + self.output_target_map.add(i_3) + + # First pass: Basic target cleanup + object_libs = [] + custom_target_outputs: T.List[str] = [] + for ctgt in self.custom_targets: + ctgt.postprocess(self.output_target_map, self.src_dir, custom_target_outputs, self.trace) + for tgt in self.targets: + tgt.postprocess(self.output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace) + if tgt.type == 'OBJECT_LIBRARY': + object_libs += [tgt] + self.languages += [x for x in tgt.languages if x not in self.languages] + + # Second pass: Detect object library dependencies + for tgt in self.targets: + tgt.process_object_libs(object_libs, self._object_lib_workaround) + + # Third pass: Reassign dependencies to avoid some loops + for tgt in self.targets: + tgt.process_inter_target_dependencies() + for ctgt in self.custom_targets: + ctgt.process_inter_target_dependencies() + + # Fourth pass: Remove rassigned dependencies + for tgt in self.targets: + tgt.cleanup_dependencies() + + mlog.log('CMake project', mlog.bold(self.project_name), 'has', mlog.bold(str(len(self.targets) + len(self.custom_targets))), 'build targets.') + + def pretend_to_be_meson(self, options: TargetOptions) -> CodeBlockNode: + if not self.project_name: + raise CMakeException('CMakeInterpreter was not analysed') + + def token(tid: str = 'string', val: TYPE_mixed = '') -> Token: + return Token(tid, self.subdir.as_posix(), 0, 0, 0, None, val) + + def string(value: str) -> StringNode: + return StringNode(token(val=value)) + + def id_node(value: str) -> IdNode: + return IdNode(token(val=value)) + + def number(value: int) -> NumberNode: + return NumberNode(token(val=value)) + + def nodeify(value: TYPE_mixed_list) -> BaseNode: + if isinstance(value, str): + return string(value) + if isinstance(value, Path): + return string(value.as_posix()) + elif isinstance(value, bool): + return BooleanNode(token(val=value)) + elif isinstance(value, int): + return number(value) + elif isinstance(value, list): + return array(value) + elif isinstance(value, BaseNode): + return value + raise RuntimeError('invalid type of value: {} ({})'.format(type(value).__name__, str(value))) + + def indexed(node: BaseNode, index: int) -> IndexNode: + return IndexNode(node, nodeify(index)) + + def array(elements: TYPE_mixed_list) -> ArrayNode: + args = ArgumentNode(token()) + if not isinstance(elements, list): + elements = [args] + args.arguments += [nodeify(x) for x in elements if x is not None] + return ArrayNode(args, 0, 0, 0, 0) + + def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> FunctionNode: + args = [] if args is None else args + kwargs = {} if kwargs is None else kwargs + args_n = ArgumentNode(token()) + if not isinstance(args, list): + assert isinstance(args, (str, int, bool, Path, BaseNode)) + args = [args] + args_n.arguments = [nodeify(x) for x in args if x is not None] + args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} + func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, name, args_n) + return func_n + + def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> MethodNode: + args = [] if args is None else args + kwargs = {} if kwargs is None else kwargs + args_n = ArgumentNode(token()) + if not isinstance(args, list): + assert isinstance(args, (str, int, bool, Path, BaseNode)) + args = [args] + args_n.arguments = [nodeify(x) for x in args if x is not None] + args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} + return MethodNode(self.subdir.as_posix(), 0, 0, obj, name, args_n) + + def assign(var_name: str, value: BaseNode) -> AssignmentNode: + return AssignmentNode(self.subdir.as_posix(), 0, 0, var_name, value) + + # Generate the root code block and the project function call + root_cb = CodeBlockNode(token()) + root_cb.lines += [function('project', [self.project_name] + self.languages)] + + # Add the run script for custom commands + + # Add the targets + processing: T.List[str] = [] + processed: T.Dict[str, T.Dict[str, T.Optional[str]]] = {} + name_map: T.Dict[str, str] = {} + + def extract_tgt(tgt: T.Union[ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> IdNode: + tgt_name = None + if isinstance(tgt, (ConverterTarget, ConverterCustomTarget)): + tgt_name = tgt.name + elif isinstance(tgt, CustomTargetReference): + tgt_name = tgt.ctgt.name + assert tgt_name is not None and tgt_name in processed + res_var = processed[tgt_name]['tgt'] + return id_node(res_var) if res_var else None + + def detect_cycle(tgt: T.Union[ConverterTarget, ConverterCustomTarget]) -> None: + if tgt.name in processing: + raise CMakeException('Cycle in CMake inputs/dependencies detected') + processing.append(tgt.name) + + def resolve_ctgt_ref(ref: CustomTargetReference) -> T.Union[IdNode, IndexNode]: + tgt_var = extract_tgt(ref) + if len(ref.ctgt.outputs) == 1: + return tgt_var + else: + return indexed(tgt_var, ref.index) + + def process_target(tgt: ConverterTarget) -> None: + detect_cycle(tgt) + + # First handle inter target dependencies + link_with: T.List[IdNode] = [] + objec_libs: T.List[IdNode] = [] + sources: T.List[Path] = [] + generated: T.List[T.Union[IdNode, IndexNode]] = [] + generated_filenames: T.List[str] = [] + custom_targets: T.List[ConverterCustomTarget] = [] + dependencies: T.List[IdNode] = [] + for i in tgt.link_with: + assert isinstance(i, ConverterTarget) + if i.name not in processed: + process_target(i) + link_with += [extract_tgt(i)] + for i in tgt.object_libs: + assert isinstance(i, ConverterTarget) + if i.name not in processed: + process_target(i) + objec_libs += [extract_tgt(i)] + for i in tgt.depends: + if not isinstance(i, ConverterCustomTarget): + continue + if i.name not in processed: + process_custom_target(i) + dependencies += [extract_tgt(i)] + + # Generate the source list and handle generated sources + sources += tgt.sources + sources += tgt.generated + + for ctgt_ref in tgt.generated_ctgt: + ctgt = ctgt_ref.ctgt + if ctgt.name not in processed: + process_custom_target(ctgt) + generated += [resolve_ctgt_ref(ctgt_ref)] + generated_filenames += [ctgt_ref.filename()] + if ctgt not in custom_targets: + custom_targets += [ctgt] + + # Add all header files from all used custom targets. This + # ensures that all custom targets are built before any + # sources of the current target are compiled and thus all + # header files are present. This step is necessary because + # CMake always ensures that a custom target is executed + # before another target if at least one output is used. + for ctgt in custom_targets: + for j in ctgt.outputs: + if not is_header(j) or j in generated_filenames: + continue + + generated += [resolve_ctgt_ref(ctgt.get_ref(Path(j)))] + generated_filenames += [j] + + # Determine the meson function to use for the build target + tgt_func = tgt.meson_func() + if not tgt_func: + raise CMakeException(f'Unknown target type "{tgt.type}"') + + # Determine the variable names + inc_var = f'{tgt.name}_inc' + dir_var = f'{tgt.name}_dir' + sys_var = f'{tgt.name}_sys' + src_var = f'{tgt.name}_src' + dep_var = f'{tgt.name}_dep' + tgt_var = tgt.name + + install_tgt = options.get_install(tgt.cmake_name, tgt.install) + + # Generate target kwargs + tgt_kwargs: TYPE_mixed_kwargs = { + 'build_by_default': install_tgt, + 'link_args': options.get_link_args(tgt.cmake_name, tgt.link_flags + tgt.link_libraries), + 'link_with': link_with, + 'include_directories': id_node(inc_var), + 'install': install_tgt, + 'override_options': options.get_override_options(tgt.cmake_name, tgt.override_options), + 'objects': [method(x, 'extract_all_objects') for x in objec_libs], + } + + # Only set if installed and only override if it is set + if install_tgt and tgt.install_dir: + tgt_kwargs['install_dir'] = tgt.install_dir + + # Handle compiler args + for key, val in tgt.compile_opts.items(): + tgt_kwargs[f'{key}_args'] = options.get_compile_args(tgt.cmake_name, key, val) + + # Handle -fPCI, etc + if tgt_func == 'executable': + tgt_kwargs['pie'] = tgt.pie + elif tgt_func == 'static_library': + tgt_kwargs['pic'] = tgt.pie + + # declare_dependency kwargs + dep_kwargs: TYPE_mixed_kwargs = { + 'link_args': tgt.link_flags + tgt.link_libraries, + 'link_with': id_node(tgt_var), + 'compile_args': tgt.public_compile_opts, + 'include_directories': id_node(inc_var), + } + + if dependencies: + generated += dependencies + + # Generate the function nodes + dir_node = assign(dir_var, function('include_directories', tgt.includes)) + sys_node = assign(sys_var, function('include_directories', tgt.sys_includes, {'is_system': True})) + inc_node = assign(inc_var, array([id_node(dir_var), id_node(sys_var)])) + node_list = [dir_node, sys_node, inc_node] + if tgt_func == 'header_only': + del dep_kwargs['link_with'] + dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs)) + node_list += [dep_node] + src_var = None + tgt_var = None + else: + src_node = assign(src_var, function('files', sources)) + tgt_node = assign(tgt_var, function(tgt_func, [tgt_var, id_node(src_var), *generated], tgt_kwargs)) + node_list += [src_node, tgt_node] + if tgt_func in {'static_library', 'shared_library'}: + dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs)) + node_list += [dep_node] + elif tgt_func == 'shared_module': + del dep_kwargs['link_with'] + dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs)) + node_list += [dep_node] + else: + dep_var = None + + # Add the nodes to the ast + root_cb.lines += node_list + processed[tgt.name] = {'inc': inc_var, 'src': src_var, 'dep': dep_var, 'tgt': tgt_var, 'func': tgt_func} + name_map[tgt.cmake_name] = tgt.name + + def process_custom_target(tgt: ConverterCustomTarget) -> None: + # CMake allows to specify multiple commands in a custom target. + # To map this to meson, a helper script is used to execute all + # commands in order. This additionally allows setting the working + # directory. + + detect_cycle(tgt) + tgt_var = tgt.name + + def resolve_source(x: T.Union[str, ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> T.Union[str, IdNode, IndexNode]: + if isinstance(x, ConverterTarget): + if x.name not in processed: + process_target(x) + return extract_tgt(x) + if isinstance(x, ConverterCustomTarget): + if x.name not in processed: + process_custom_target(x) + return extract_tgt(x) + elif isinstance(x, CustomTargetReference): + if x.ctgt.name not in processed: + process_custom_target(x.ctgt) + return resolve_ctgt_ref(x) + else: + return x + + # Generate the command list + command: T.List[T.Union[str, IdNode, IndexNode]] = [] + command += mesonlib.get_meson_command() + command += ['--internal', 'cmake_run_ctgt'] + command += ['-o', '@OUTPUT@'] + if tgt.original_outputs: + command += ['-O'] + [x.as_posix() for x in tgt.original_outputs] + command += ['-d', tgt.working_dir.as_posix()] + + # Generate the commands. Subcommands are separated by ';;;' + for cmd in tgt.command: + command += [resolve_source(x) for x in cmd] + [';;;'] + + tgt_kwargs: TYPE_mixed_kwargs = { + 'input': [resolve_source(x) for x in tgt.inputs], + 'output': tgt.outputs, + 'command': command, + 'depends': [resolve_source(x) for x in tgt.depends], + } + + root_cb.lines += [assign(tgt_var, function('custom_target', [tgt.name], tgt_kwargs))] + processed[tgt.name] = {'inc': None, 'src': None, 'dep': None, 'tgt': tgt_var, 'func': 'custom_target'} + name_map[tgt.cmake_name] = tgt.name + + # Now generate the target function calls + for ctgt in self.custom_targets: + if ctgt.name not in processed: + process_custom_target(ctgt) + for tgt in self.targets: + if tgt.name not in processed: + process_target(tgt) + + self.generated_targets = processed + self.internal_name_map = name_map + return root_cb + + def target_info(self, target: str) -> T.Optional[T.Dict[str, str]]: + # Try resolving the target name + # start by checking if there is a 100% match (excluding the name prefix) + prx_tgt = _sanitize_cmake_name(target) + if prx_tgt in self.generated_targets: + return self.generated_targets[prx_tgt] + # check if there exists a name mapping + if target in self.internal_name_map: + target = self.internal_name_map[target] + assert target in self.generated_targets + return self.generated_targets[target] + return None + + def target_list(self) -> T.List[str]: + return list(self.internal_name_map.keys()) diff --git a/devtools/meson/mesonbuild/cmake/toolchain.py b/devtools/meson/mesonbuild/cmake/toolchain.py new file mode 100644 index 0000000..477629e --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/toolchain.py @@ -0,0 +1,258 @@ +# Copyright 2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from pathlib import Path +from .traceparser import CMakeTraceParser +from ..envconfig import CMakeSkipCompilerTest +from .common import language_map, cmake_get_generator_args +from .. import mlog + +import shutil +import typing as T +from enum import Enum +from textwrap import dedent + +if T.TYPE_CHECKING: + from .executor import CMakeExecutor + from ..environment import Environment + from ..compilers import Compiler + from ..mesonlib import MachineChoice + +class CMakeExecScope(Enum): + SUBPROJECT = 'subproject' + DEPENDENCY = 'dependency' + +class CMakeToolchain: + def __init__(self, cmakebin: 'CMakeExecutor', env: 'Environment', for_machine: MachineChoice, exec_scope: CMakeExecScope, build_dir: Path, preload_file: T.Optional[Path] = None) -> None: + self.env = env + self.cmakebin = cmakebin + self.for_machine = for_machine + self.exec_scope = exec_scope + self.preload_file = preload_file + self.build_dir = build_dir + self.build_dir = self.build_dir.resolve() + self.toolchain_file = build_dir / 'CMakeMesonToolchainFile.cmake' + self.cmcache_file = build_dir / 'CMakeCache.txt' + self.minfo = self.env.machines[self.for_machine] + self.properties = self.env.properties[self.for_machine] + self.compilers = self.env.coredata.compilers[self.for_machine] + self.cmakevars = self.env.cmakevars[self.for_machine] + self.cmakestate = self.env.coredata.cmake_cache[self.for_machine] + + self.variables = self.get_defaults() + self.variables.update(self.cmakevars.get_variables()) + + # Determine whether CMake the compiler test should be skipped + skip_status = self.properties.get_cmake_skip_compiler_test() + self.skip_check = skip_status == CMakeSkipCompilerTest.ALWAYS + if skip_status == CMakeSkipCompilerTest.DEP_ONLY and self.exec_scope == CMakeExecScope.DEPENDENCY: + self.skip_check = True + if not self.properties.get_cmake_defaults(): + self.skip_check = False + + assert self.toolchain_file.is_absolute() + + def write(self) -> Path: + if not self.toolchain_file.parent.exists(): + self.toolchain_file.parent.mkdir(parents=True) + self.toolchain_file.write_text(self.generate(), encoding='utf-8') + self.cmcache_file.write_text(self.generate_cache(), encoding='utf-8') + mlog.cmd_ci_include(self.toolchain_file.as_posix()) + return self.toolchain_file + + def get_cmake_args(self) -> T.List[str]: + args = ['-DCMAKE_TOOLCHAIN_FILE=' + self.toolchain_file.as_posix()] + if self.preload_file is not None: + args += ['-DMESON_PRELOAD_FILE=' + self.preload_file.as_posix()] + return args + + @staticmethod + def _print_vars(vars: T.Dict[str, T.List[str]]) -> str: + res = '' + for key, value in vars.items(): + res += 'set(' + key + for i in value: + res += f' "{i}"' + res += ')\n' + return res + + def generate(self) -> str: + res = dedent('''\ + ###################################### + ### AUTOMATICALLY GENERATED FILE ### + ###################################### + + # This file was generated from the configuration in the + # relevant meson machine file. See the meson documentation + # https://mesonbuild.com/Machine-files.html for more information + + if(DEFINED MESON_PRELOAD_FILE) + include("${MESON_PRELOAD_FILE}") + endif() + + ''') + + # Escape all \ in the values + for key, value in self.variables.items(): + self.variables[key] = [x.replace('\\', '/') for x in value] + + # Set compiler + if self.skip_check: + self.update_cmake_compiler_state() + res += '# CMake compiler state variables\n' + for lang, vars in self.cmakestate: + res += f'# -- Variables for language {lang}\n' + res += self._print_vars(vars) + res += '\n' + res += '\n' + + # Set variables from the current machine config + res += '# Variables from meson\n' + res += self._print_vars(self.variables) + res += '\n' + + # Add the user provided toolchain file + user_file = self.properties.get_cmake_toolchain_file() + if user_file is not None: + res += dedent(''' + # Load the CMake toolchain file specified by the user + include("{}") + + '''.format(user_file.as_posix())) + + return res + + def generate_cache(self) -> str: + if not self.skip_check: + return '' + + res = '' + for name, v in self.cmakestate.cmake_cache.items(): + res += f'{name}:{v.type}={";".join(v.value)}\n' + return res + + def get_defaults(self) -> T.Dict[str, T.List[str]]: + defaults = {} # type: T.Dict[str, T.List[str]] + + # Do nothing if the user does not want automatic defaults + if not self.properties.get_cmake_defaults(): + return defaults + + # Best effort to map the meson system name to CMAKE_SYSTEM_NAME, which + # is not trivial since CMake lacks a list of all supported + # CMAKE_SYSTEM_NAME values. + SYSTEM_MAP = { + 'android': 'Android', + 'linux': 'Linux', + 'windows': 'Windows', + 'freebsd': 'FreeBSD', + 'darwin': 'Darwin', + } # type: T.Dict[str, str] + + # Only set these in a cross build. Otherwise CMake will trip up in native + # builds and thing they are cross (which causes TRY_RUN() to break) + if self.env.is_cross_build(when_building_for=self.for_machine): + defaults['CMAKE_SYSTEM_NAME'] = [SYSTEM_MAP.get(self.minfo.system, self.minfo.system)] + defaults['CMAKE_SYSTEM_PROCESSOR'] = [self.minfo.cpu_family] + + defaults['CMAKE_SIZEOF_VOID_P'] = ['8' if self.minfo.is_64_bit else '4'] + + sys_root = self.properties.get_sys_root() + if sys_root: + defaults['CMAKE_SYSROOT'] = [sys_root] + + def make_abs(exe: str) -> str: + if Path(exe).is_absolute(): + return exe + + p = shutil.which(exe) + if p is None: + return exe + return p + + # Set the compiler variables + for lang, comp_obj in self.compilers.items(): + prefix = 'CMAKE_{}_'.format(language_map.get(lang, lang.upper())) + + exe_list = comp_obj.get_exelist() + if not exe_list: + continue + + if len(exe_list) >= 2 and not self.is_cmdline_option(comp_obj, exe_list[1]): + defaults[prefix + 'COMPILER_LAUNCHER'] = [make_abs(exe_list[0])] + exe_list = exe_list[1:] + + exe_list[0] = make_abs(exe_list[0]) + defaults[prefix + 'COMPILER'] = exe_list + if comp_obj.get_id() == 'clang-cl': + defaults['CMAKE_LINKER'] = comp_obj.get_linker_exelist() + + return defaults + + @staticmethod + def is_cmdline_option(compiler: 'Compiler', arg: str) -> bool: + if compiler.get_argument_syntax() == 'msvc': + return arg.startswith('/') + else: + return arg.startswith('-') + + def update_cmake_compiler_state(self) -> None: + # Check if all variables are already cached + if self.cmakestate.languages.issuperset(self.compilers.keys()): + return + + # Generate the CMakeLists.txt + mlog.debug('CMake Toolchain: Calling CMake once to generate the compiler state') + languages = list(self.compilers.keys()) + lang_ids = [language_map.get(x, x.upper()) for x in languages] + cmake_content = dedent(f''' + cmake_minimum_required(VERSION 3.7) + project(CompInfo {' '.join(lang_ids)}) + ''') + + build_dir = Path(self.env.scratch_dir) / '__CMake_compiler_info__' + build_dir.mkdir(parents=True, exist_ok=True) + cmake_file = build_dir / 'CMakeLists.txt' + cmake_file.write_text(cmake_content, encoding='utf-8') + + # Generate the temporary toolchain file + temp_toolchain_file = build_dir / 'CMakeMesonTempToolchainFile.cmake' + temp_toolchain_file.write_text(CMakeToolchain._print_vars(self.variables), encoding='utf-8') + + # Configure + trace = CMakeTraceParser(self.cmakebin.version(), build_dir, self.env) + self.cmakebin.set_exec_mode(print_cmout=False, always_capture_stderr=trace.requires_stderr()) + cmake_args = [] + cmake_args += trace.trace_args() + cmake_args += cmake_get_generator_args(self.env) + cmake_args += [f'-DCMAKE_TOOLCHAIN_FILE={temp_toolchain_file.as_posix()}', '.'] + rc, _, raw_trace = self.cmakebin.call(cmake_args, build_dir=build_dir, disable_cache=True) + + if rc != 0: + mlog.warning('CMake Toolchain: Failed to determine CMake compilers state') + return + + # Parse output + trace.parse(raw_trace) + self.cmakestate.cmake_cache = {**trace.cache} + + vars_by_file = {k.name: v for (k, v) in trace.vars_by_file.items()} + + for lang in languages: + lang_cmake = language_map.get(lang, lang.upper()) + file_name = f'CMake{lang_cmake}Compiler.cmake' + vars = vars_by_file.setdefault(file_name, {}) + vars[f'CMAKE_{lang_cmake}_COMPILER_FORCED'] = ['1'] + self.cmakestate.update(lang, vars) diff --git a/devtools/meson/mesonbuild/cmake/traceparser.py b/devtools/meson/mesonbuild/cmake/traceparser.py new file mode 100644 index 0000000..7f31f13 --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/traceparser.py @@ -0,0 +1,825 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. +from __future__ import annotations + +from .common import CMakeException +from .generator import parse_generator_expressions +from .. import mlog +from ..mesonlib import version_compare + +import typing as T +from pathlib import Path +from functools import lru_cache +import re +import json +import textwrap + +if T.TYPE_CHECKING: + from ..environment import Environment + +class CMakeTraceLine: + def __init__(self, file_str: str, line: int, func: str, args: T.List[str]) -> None: + self.file = CMakeTraceLine._to_path(file_str) + self.line = line + self.func = func.lower() + self.args = args + + @staticmethod + @lru_cache(maxsize=None) + def _to_path(file_str: str) -> Path: + return Path(file_str) + + def __repr__(self) -> str: + s = 'CMake TRACE: {0}:{1} {2}({3})' + return s.format(self.file, self.line, self.func, self.args) + +class CMakeCacheEntry(T.NamedTuple): + value: T.List[str] + type: str + +class CMakeTarget: + def __init__( + self, + name: str, + target_type: str, + properties: T.Optional[T.Dict[str, T.List[str]]] = None, + imported: bool = False, + tline: T.Optional[CMakeTraceLine] = None + ): + if properties is None: + properties = {} + self.name = name + self.type = target_type + self.properties = properties + self.imported = imported + self.tline = tline + self.depends = [] # type: T.List[str] + self.current_bin_dir = None # type: T.Optional[Path] + self.current_src_dir = None # type: T.Optional[Path] + + def __repr__(self) -> str: + s = 'CMake TARGET:\n -- name: {}\n -- type: {}\n -- imported: {}\n -- properties: {{\n{} }}\n -- tline: {}' + propSTR = '' + for i in self.properties: + propSTR += " '{}': {}\n".format(i, self.properties[i]) + return s.format(self.name, self.type, self.imported, propSTR, self.tline) + + def strip_properties(self) -> None: + # Strip the strings in the properties + if not self.properties: + return + for key, val in self.properties.items(): + self.properties[key] = [x.strip() for x in val] + assert all(';' not in x for x in self.properties[key]) + +class CMakeGeneratorTarget(CMakeTarget): + def __init__(self, name: str) -> None: + super().__init__(name, 'CUSTOM', {}) + self.outputs = [] # type: T.List[Path] + self._outputs_str = [] # type: T.List[str] + self.command = [] # type: T.List[T.List[str]] + self.working_dir = None # type: T.Optional[Path] + +class CMakeTraceParser: + def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', permissive: bool = True) -> None: + self.vars: T.Dict[str, T.List[str]] = {} + self.vars_by_file: T.Dict[Path, T.Dict[str, T.List[str]]] = {} + self.targets: T.Dict[str, CMakeTarget] = {} + self.cache: T.Dict[str, CMakeCacheEntry] = {} + + self.explicit_headers = set() # type: T.Set[Path] + + # T.List of targes that were added with add_custom_command to generate files + self.custom_targets = [] # type: T.List[CMakeGeneratorTarget] + + self.env = env + self.permissive = permissive # type: bool + self.cmake_version = cmake_version # type: str + self.trace_file = 'cmake_trace.txt' + self.trace_file_path = build_dir / self.trace_file + self.trace_format = 'json-v1' if version_compare(cmake_version, '>=3.17') else 'human' + + self.errors: T.List[str] = [] + + # State for delayed command execution. Delayed command execution is realised + # with a custom CMake file that overrides some functions and adds some + # introspection information to the trace. + self.delayed_commands = [] # type: T.List[str] + self.stored_commands = [] # type: T.List[CMakeTraceLine] + + # All supported functions + self.functions = { + 'set': self._cmake_set, + 'unset': self._cmake_unset, + 'add_executable': self._cmake_add_executable, + 'add_library': self._cmake_add_library, + 'add_custom_command': self._cmake_add_custom_command, + 'add_custom_target': self._cmake_add_custom_target, + 'set_property': self._cmake_set_property, + 'set_target_properties': self._cmake_set_target_properties, + 'target_compile_definitions': self._cmake_target_compile_definitions, + 'target_compile_options': self._cmake_target_compile_options, + 'target_include_directories': self._cmake_target_include_directories, + 'target_link_libraries': self._cmake_target_link_libraries, + 'target_link_options': self._cmake_target_link_options, + 'add_dependencies': self._cmake_add_dependencies, + 'message': self._cmake_message, + + # Special functions defined in the preload script. + # These functions do nothing in the CMake code, but have special + # meaning here in the trace parser. + 'meson_ps_execute_delayed_calls': self._meson_ps_execute_delayed_calls, + 'meson_ps_reload_vars': self._meson_ps_reload_vars, + 'meson_ps_disabled_function': self._meson_ps_disabled_function, + } # type: T.Dict[str, T.Callable[[CMakeTraceLine], None]] + + if version_compare(self.cmake_version, '<3.17.0'): + mlog.deprecation(textwrap.dedent(f'''\ + CMake support for versions <3.17 is deprecated since Meson 0.62.0. + | + | However, Meson was only able to find CMake {self.cmake_version}. + | + | Support for all CMake versions below 3.17.0 will be removed once + | newer CMake versions are more widely adopted. If you encounter + | any errors please try upgrading CMake to a newer version first. + '''), once=True) + + def trace_args(self) -> T.List[str]: + arg_map = { + 'human': ['--trace', '--trace-expand'], + 'json-v1': ['--trace-expand', '--trace-format=json-v1'], + } + + base_args = ['--no-warn-unused-cli'] + if not self.requires_stderr(): + base_args += [f'--trace-redirect={self.trace_file}'] + + return arg_map[self.trace_format] + base_args + + def requires_stderr(self) -> bool: + return version_compare(self.cmake_version, '<3.16') + + def parse(self, trace: T.Optional[str] = None) -> None: + # First load the trace (if required) + if not self.requires_stderr(): + if not self.trace_file_path.exists and not self.trace_file_path.is_file(): + raise CMakeException(f'CMake: Trace file "{self.trace_file_path!s}" not found') + trace = self.trace_file_path.read_text(errors='ignore', encoding='utf-8') + if not trace: + raise CMakeException('CMake: The CMake trace was not provided or is empty') + + # Second parse the trace + lexer1 = None + if self.trace_format == 'human': + lexer1 = self._lex_trace_human(trace) + elif self.trace_format == 'json-v1': + lexer1 = self._lex_trace_json(trace) + else: + raise CMakeException(f'CMake: Internal error: Invalid trace format {self.trace_format}. Expected [human, json-v1]') + + # Primary pass -- parse everything + for l in lexer1: + # store the function if its execution should be delayed + if l.func in self.delayed_commands: + self.stored_commands += [l] + continue + + # "Execute" the CMake function if supported + fn = self.functions.get(l.func, None) + if fn: + fn(l) + + # Evaluate generator expressions + strlist_gen: T.Callable[[T.List[str]], T.List[str]] = lambda strlist: parse_generator_expressions(';'.join(strlist), self).split(';') if strlist else [] + pathlist_gen: T.Callable[[T.List[str]], T.List[Path]] = lambda strlist: [Path(x) for x in parse_generator_expressions(';'.join(strlist), self).split(';')] if strlist else [] + + self.vars = {k: strlist_gen(v) for k, v in self.vars.items()} + self.vars_by_file = { + p: {k: strlist_gen(v) for k, v in d.items()} + for p, d in self.vars_by_file.items() + } + self.explicit_headers = {Path(parse_generator_expressions(str(x), self)) for x in self.explicit_headers} + self.cache = { + k: CMakeCacheEntry( + strlist_gen(v.value), + v.type + ) + for k, v in self.cache.items() + } + + for tgt in self.targets.values(): + tgtlist_gen: T.Callable[[T.List[str], CMakeTarget], T.List[str]] = lambda strlist, t: parse_generator_expressions(';'.join(strlist), self, context_tgt=t).split(';') if strlist else [] + tgt.name = parse_generator_expressions(tgt.name, self, context_tgt=tgt) + tgt.type = parse_generator_expressions(tgt.type, self, context_tgt=tgt) + tgt.properties = { + k: tgtlist_gen(v, tgt) for k, v in tgt.properties.items() + } if tgt.properties is not None else None + tgt.depends = tgtlist_gen(tgt.depends, tgt) + + for ctgt in self.custom_targets: + ctgt.outputs = pathlist_gen(ctgt._outputs_str) + temp = ctgt.command + ctgt.command = [strlist_gen(x) for x in ctgt.command] + for command, src in zip(ctgt.command, temp): + if command[0] == "": + raise CMakeException( + "We evaluated the cmake variable '{}' to an empty string, which is not a valid path to an executable.".format(src[0]) + ) + ctgt.working_dir = Path(parse_generator_expressions(str(ctgt.working_dir), self)) if ctgt.working_dir is not None else None + + # Postprocess + for tgt in self.targets.values(): + tgt.strip_properties() + + def get_first_cmake_var_of(self, var_list: T.List[str]) -> T.List[str]: + # Return the first found CMake variable in list var_list + for i in var_list: + if i in self.vars: + return self.vars[i] + + return [] + + def get_cmake_var(self, var: str) -> T.List[str]: + # Return the value of the CMake variable var or an empty list if var does not exist + if var in self.vars: + return self.vars[var] + + return [] + + def var_to_str(self, var: str) -> T.Optional[str]: + if var in self.vars and self.vars[var]: + return self.vars[var][0] + + return None + + def _str_to_bool(self, expr: T.Union[str, T.List[str]]) -> bool: + if not expr: + return False + if isinstance(expr, list): + expr_str = expr[0] + else: + expr_str = expr + expr_str = expr_str.upper() + return expr_str not in ['0', 'OFF', 'NO', 'FALSE', 'N', 'IGNORE'] and not expr_str.endswith('NOTFOUND') + + def var_to_bool(self, var: str) -> bool: + return self._str_to_bool(self.vars.get(var, [])) + + def _gen_exception(self, function: str, error: str, tline: CMakeTraceLine) -> None: + # Generate an exception if the parser is not in permissive mode + + if self.permissive: + mlog.debug(f'CMake trace warning: {function}() {error}\n{tline}') + return None + raise CMakeException(f'CMake: {function}() {error}\n{tline}') + + def _cmake_set(self, tline: CMakeTraceLine) -> None: + """Handler for the CMake set() function in all varieties. + + comes in three flavors: + set( [PARENT_SCOPE]) + set( CACHE [FORCE]) + set(ENV{} ) + + We don't support the ENV variant, and any uses of it will be ignored + silently. the other two variates are supported, with some caveats: + - we don't properly handle scoping, so calls to set() inside a + function without PARENT_SCOPE set could incorrectly shadow the + outer scope. + - We don't honor the type of CACHE arguments + """ + # DOC: https://cmake.org/cmake/help/latest/command/set.html + + cache_type = None + cache_force = 'FORCE' in tline.args + try: + cache_idx = tline.args.index('CACHE') + cache_type = tline.args[cache_idx + 1] + except (ValueError, IndexError): + pass + + # 1st remove PARENT_SCOPE and CACHE from args + args = [] + for i in tline.args: + if not i or i == 'PARENT_SCOPE': + continue + + # Discard everything after the CACHE keyword + if i == 'CACHE': + break + + args.append(i) + + if len(args) < 1: + return self._gen_exception('set', 'requires at least one argument', tline) + + # Now that we've removed extra arguments all that should be left is the + # variable identifier and the value, join the value back together to + # ensure spaces in the value are correctly handled. This assumes that + # variable names don't have spaces. Please don't do that... + identifier = args.pop(0) + value = ' '.join(args) + + # Write to the CMake cache instead + if cache_type: + # Honor how the CMake FORCE parameter works + if identifier not in self.cache or cache_force: + self.cache[identifier] = CMakeCacheEntry(value.split(';'), cache_type) + + if not value: + # Same as unset + if identifier in self.vars: + del self.vars[identifier] + else: + self.vars[identifier] = value.split(';') + self.vars_by_file.setdefault(tline.file, {})[identifier] = value.split(';') + + def _cmake_unset(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/unset.html + if len(tline.args) < 1: + return self._gen_exception('unset', 'requires at least one argument', tline) + + if tline.args[0] in self.vars: + del self.vars[tline.args[0]] + + def _cmake_add_executable(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/add_executable.html + args = list(tline.args) # Make a working copy + + # Make sure the exe is imported + is_imported = True + if 'IMPORTED' not in args: + return self._gen_exception('add_executable', 'non imported executables are not supported', tline) + + args.remove('IMPORTED') + + if len(args) < 1: + return self._gen_exception('add_executable', 'requires at least 1 argument', tline) + + self.targets[args[0]] = CMakeTarget(args[0], 'EXECUTABLE', {}, tline=tline, imported=is_imported) + + def _cmake_add_library(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/add_library.html + args = list(tline.args) # Make a working copy + + # Make sure the lib is imported + if 'INTERFACE' in args: + args.remove('INTERFACE') + + if len(args) < 1: + return self._gen_exception('add_library', 'interface library name not specified', tline) + + self.targets[args[0]] = CMakeTarget(args[0], 'INTERFACE', {}, tline=tline, imported='IMPORTED' in args) + elif 'IMPORTED' in args: + args.remove('IMPORTED') + + # Now, only look at the first two arguments (target_name and target_type) and ignore the rest + if len(args) < 2: + return self._gen_exception('add_library', 'requires at least 2 arguments', tline) + + self.targets[args[0]] = CMakeTarget(args[0], args[1], {}, tline=tline, imported=True) + elif 'ALIAS' in args: + args.remove('ALIAS') + + # Now, only look at the first two arguments (target_name and target_ref) and ignore the rest + if len(args) < 2: + return self._gen_exception('add_library', 'requires at least 2 arguments', tline) + + # Simulate the ALIAS with INTERFACE_LINK_LIBRARIES + self.targets[args[0]] = CMakeTarget(args[0], 'ALIAS', {'INTERFACE_LINK_LIBRARIES': [args[1]]}, tline=tline) + elif 'OBJECT' in args: + return self._gen_exception('add_library', 'OBJECT libraries are not supported', tline) + else: + self.targets[args[0]] = CMakeTarget(args[0], 'NORMAL', {}, tline=tline) + + def _cmake_add_custom_command(self, tline: CMakeTraceLine, name: T.Optional[str] = None) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/add_custom_command.html + args = self._flatten_args(list(tline.args)) # Commands can be passed as ';' separated lists + + if not args: + return self._gen_exception('add_custom_command', 'requires at least 1 argument', tline) + + # Skip the second function signature + if args[0] == 'TARGET': + return self._gen_exception('add_custom_command', 'TARGET syntax is currently not supported', tline) + + magic_keys = ['OUTPUT', 'COMMAND', 'MAIN_DEPENDENCY', 'DEPENDS', 'BYPRODUCTS', + 'IMPLICIT_DEPENDS', 'WORKING_DIRECTORY', 'COMMENT', 'DEPFILE', + 'JOB_POOL', 'VERBATIM', 'APPEND', 'USES_TERMINAL', 'COMMAND_EXPAND_LISTS'] + + target = CMakeGeneratorTarget(name) + + def handle_output(key: str, target: CMakeGeneratorTarget) -> None: + target._outputs_str += [key] + + def handle_command(key: str, target: CMakeGeneratorTarget) -> None: + if key == 'ARGS': + return + target.command[-1] += [key] + + def handle_depends(key: str, target: CMakeGeneratorTarget) -> None: + target.depends += [key] + + working_dir = None + + def handle_working_dir(key: str, target: CMakeGeneratorTarget) -> None: + nonlocal working_dir + if working_dir is None: + working_dir = key + else: + working_dir += ' ' + working_dir += key + + fn = None + + for i in args: + if i in magic_keys: + if i == 'OUTPUT': + fn = handle_output + elif i == 'DEPENDS': + fn = handle_depends + elif i == 'WORKING_DIRECTORY': + fn = handle_working_dir + elif i == 'COMMAND': + fn = handle_command + target.command += [[]] + else: + fn = None + continue + + if fn is not None: + fn(i, target) + + cbinary_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_BINARY_DIR') + csource_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR') + + target.working_dir = Path(working_dir) if working_dir else None + target.current_bin_dir = Path(cbinary_dir) if cbinary_dir else None + target.current_src_dir = Path(csource_dir) if csource_dir else None + target._outputs_str = self._guess_files(target._outputs_str) + target.depends = self._guess_files(target.depends) + target.command = [self._guess_files(x) for x in target.command] + + self.custom_targets += [target] + if name: + self.targets[name] = target + + def _cmake_add_custom_target(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/add_custom_target.html + # We only the first parameter (the target name) is interesting + if len(tline.args) < 1: + return self._gen_exception('add_custom_target', 'requires at least one argument', tline) + + # It's pretty much the same as a custom command + self._cmake_add_custom_command(tline, tline.args[0]) + + def _cmake_set_property(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/set_property.html + args = list(tline.args) + + scope = args.pop(0) + + append = False + targets = [] + while args: + curr = args.pop(0) + # XXX: APPEND_STRING is specifically *not* supposed to create a + # list, is treating them as aliases really okay? + if curr in {'APPEND', 'APPEND_STRING'}: + append = True + continue + + if curr == 'PROPERTY': + break + + targets += curr.split(';') + + if not args: + return self._gen_exception('set_property', 'failed to parse argument list', tline) + + if len(args) == 1: + # Tries to set property to nothing so nothing has to be done + return + + identifier = args.pop(0) + if self.trace_format == 'human': + value = ' '.join(args).split(';') + else: + value = [y for x in args for y in x.split(';')] + if not value: + return + + def do_target(t: str) -> None: + if t not in self.targets: + return self._gen_exception('set_property', f'TARGET {t} not found', tline) + + tgt = self.targets[t] + if identifier not in tgt.properties: + tgt.properties[identifier] = [] + + if append: + tgt.properties[identifier] += value + else: + tgt.properties[identifier] = value + + def do_source(src: str) -> None: + if identifier != 'HEADER_FILE_ONLY' or not self._str_to_bool(value): + return + + current_src_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR') + if not current_src_dir: + mlog.warning(textwrap.dedent('''\ + CMake trace: set_property(SOURCE) called before the preload script was loaded. + Unable to determine CMAKE_CURRENT_SOURCE_DIR. This can lead to build errors. + ''')) + current_src_dir = '.' + + cur_p = Path(current_src_dir) + src_p = Path(src) + + if not src_p.is_absolute(): + src_p = cur_p / src_p + self.explicit_headers.add(src_p) + + if scope == 'TARGET': + for i in targets: + do_target(i) + elif scope == 'SOURCE': + files = self._guess_files(targets) + for i in files: + do_source(i) + + def _cmake_set_target_properties(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/set_target_properties.html + args = list(tline.args) + + targets = [] + while args: + curr = args.pop(0) + if curr == 'PROPERTIES': + break + + targets.append(curr) + + # Now we need to try to reconstitute the original quoted format of the + # arguments, as a property value could have spaces in it. Unlike + # set_property() this is not context free. There are two approaches I + # can think of, both have drawbacks: + # + # 1. Assume that the property will be capitalized ([A-Z_]), this is + # convention but cmake doesn't require it. + # 2. Maintain a copy of the list here: https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#target-properties + # + # Neither of these is awesome for obvious reasons. I'm going to try + # option 1 first and fall back to 2, as 1 requires less code and less + # synchronization for cmake changes. + # + # With the JSON output format, introduced in CMake 3.17, spaces are + # handled properly and we don't have to do either options + + arglist = [] # type: T.List[T.Tuple[str, T.List[str]]] + if self.trace_format == 'human': + name = args.pop(0) + values = [] # type: T.List[str] + prop_regex = re.compile(r'^[A-Z_]+$') + for a in args: + if prop_regex.match(a): + if values: + arglist.append((name, ' '.join(values).split(';'))) + name = a + values = [] + else: + values.append(a) + if values: + arglist.append((name, ' '.join(values).split(';'))) + else: + arglist = [(x[0], x[1].split(';')) for x in zip(args[::2], args[1::2])] + + for name, value in arglist: + for i in targets: + if i not in self.targets: + return self._gen_exception('set_target_properties', f'TARGET {i} not found', tline) + + self.targets[i].properties[name] = value + + def _cmake_add_dependencies(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/add_dependencies.html + args = list(tline.args) + + if len(args) < 2: + return self._gen_exception('add_dependencies', 'takes at least 2 arguments', tline) + + target = self.targets.get(args[0]) + if not target: + return self._gen_exception('add_dependencies', 'target not found', tline) + + for i in args[1:]: + target.depends += i.split(';') + + def _cmake_target_compile_definitions(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/target_compile_definitions.html + self._parse_common_target_options('target_compile_definitions', 'COMPILE_DEFINITIONS', 'INTERFACE_COMPILE_DEFINITIONS', tline) + + def _cmake_target_compile_options(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/target_compile_options.html + self._parse_common_target_options('target_compile_options', 'COMPILE_OPTIONS', 'INTERFACE_COMPILE_OPTIONS', tline) + + def _cmake_target_include_directories(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/target_include_directories.html + self._parse_common_target_options('target_include_directories', 'INCLUDE_DIRECTORIES', 'INTERFACE_INCLUDE_DIRECTORIES', tline, ignore=['SYSTEM', 'BEFORE'], paths=True) + + def _cmake_target_link_options(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/target_link_options.html + self._parse_common_target_options('target_link_options', 'LINK_OPTIONS', 'INTERFACE_LINK_OPTIONS', tline) + + def _cmake_target_link_libraries(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/target_link_libraries.html + self._parse_common_target_options('target_link_options', 'LINK_LIBRARIES', 'INTERFACE_LINK_LIBRARIES', tline) + + def _cmake_message(self, tline: CMakeTraceLine) -> None: + # DOC: https://cmake.org/cmake/help/latest/command/message.html + args = list(tline.args) + + if len(args) < 1: + return self._gen_exception('message', 'takes at least 1 argument', tline) + + if args[0].upper().strip() not in ['FATAL_ERROR', 'SEND_ERROR']: + return + + self.errors += [' '.join(args[1:])] + + def _parse_common_target_options(self, func: str, private_prop: str, interface_prop: str, tline: CMakeTraceLine, ignore: T.Optional[T.List[str]] = None, paths: bool = False) -> None: + if ignore is None: + ignore = ['BEFORE'] + + args = list(tline.args) + + if len(args) < 1: + return self._gen_exception(func, 'requires at least one argument', tline) + + target = args[0] + if target not in self.targets: + return self._gen_exception(func, f'TARGET {target} not found', tline) + + interface = [] + private = [] + + mode = 'PUBLIC' + for i in args[1:]: + if i in ignore: + continue + + if i in {'INTERFACE', 'LINK_INTERFACE_LIBRARIES', 'PUBLIC', 'PRIVATE', 'LINK_PUBLIC', 'LINK_PRIVATE'}: + mode = i + continue + + if mode in {'INTERFACE', 'LINK_INTERFACE_LIBRARIES', 'PUBLIC', 'LINK_PUBLIC'}: + interface += i.split(';') + + if mode in {'PUBLIC', 'PRIVATE', 'LINK_PRIVATE'}: + private += i.split(';') + + if paths: + interface = self._guess_files(interface) + private = self._guess_files(private) + + interface = [x for x in interface if x] + private = [x for x in private if x] + + for j in [(private_prop, private), (interface_prop, interface)]: + if not j[0] in self.targets[target].properties: + self.targets[target].properties[j[0]] = [] + + self.targets[target].properties[j[0]] += j[1] + + def _meson_ps_execute_delayed_calls(self, tline: CMakeTraceLine) -> None: + for l in self.stored_commands: + fn = self.functions.get(l.func, None) + if fn: + fn(l) + + # clear the stored commands + self.stored_commands = [] + + def _meson_ps_reload_vars(self, tline: CMakeTraceLine) -> None: + self.delayed_commands = self.get_cmake_var('MESON_PS_DELAYED_CALLS') + + def _meson_ps_disabled_function(self, tline: CMakeTraceLine) -> None: + args = list(tline.args) + if not args: + mlog.error('Invalid preload.cmake script! At least one argument to `meson_ps_disabled_function` is expected') + return + mlog.warning(f'The CMake function "{args[0]}" was disabled to avoid compatibility issues with Meson.') + + def _lex_trace_human(self, trace: str) -> T.Generator[CMakeTraceLine, None, None]: + # The trace format is: '(): ( )\n' + reg_tline = re.compile(r'\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(([\s\S]*?) ?\)\s*\n', re.MULTILINE) + reg_other = re.compile(r'[^\n]*\n') + loc = 0 + while loc < len(trace): + mo_file_line = reg_tline.match(trace, loc) + if not mo_file_line: + skip_match = reg_other.match(trace, loc) + if not skip_match: + print(trace[loc:]) + raise CMakeException('Failed to parse CMake trace') + + loc = skip_match.end() + continue + + loc = mo_file_line.end() + + file = mo_file_line.group(1) + line = mo_file_line.group(3) + func = mo_file_line.group(4) + args = mo_file_line.group(5) + argl = args.split(' ') + argl = [a.strip() for a in argl] + + yield CMakeTraceLine(file, int(line), func, argl) + + def _lex_trace_json(self, trace: str) -> T.Generator[CMakeTraceLine, None, None]: + lines = trace.splitlines(keepends=False) + lines.pop(0) # The first line is the version + for i in lines: + data = json.loads(i) + assert isinstance(data['file'], str) + assert isinstance(data['line'], int) + assert isinstance(data['cmd'], str) + assert isinstance(data['args'], list) + args = data['args'] + for j in args: + assert isinstance(j, str) + yield CMakeTraceLine(data['file'], data['line'], data['cmd'], args) + + def _flatten_args(self, args: T.List[str]) -> T.List[str]: + # Split lists in arguments + res = [] # type: T.List[str] + for i in args: + res += i.split(';') + return res + + def _guess_files(self, broken_list: T.List[str]) -> T.List[str]: + # Nothing has to be done for newer formats + if self.trace_format != 'human': + return broken_list + + # Try joining file paths that contain spaces + + reg_start = re.compile(r'^([A-Za-z]:)?/(.*/)*[^./]+$') + reg_end = re.compile(r'^.*\.[a-zA-Z]+$') + + fixed_list = [] # type: T.List[str] + curr_str = None # type: T.Optional[str] + path_found = False # type: bool + + for i in broken_list: + if curr_str is None: + curr_str = i + path_found = False + elif Path(curr_str).is_file(): + # Abort concatenation if curr_str is an existing file + fixed_list += [curr_str] + curr_str = i + path_found = False + elif not reg_start.match(curr_str): + # Abort concatenation if curr_str no longer matches the regex + fixed_list += [curr_str] + curr_str = i + path_found = False + elif reg_end.match(i): + # File detected + curr_str = f'{curr_str} {i}' + fixed_list += [curr_str] + curr_str = None + path_found = False + elif Path(f'{curr_str} {i}').exists(): + # Path detected + curr_str = f'{curr_str} {i}' + path_found = True + elif path_found: + # Add path to fixed_list after ensuring the whole path is in curr_str + fixed_list += [curr_str] + curr_str = i + path_found = False + else: + curr_str = f'{curr_str} {i}' + path_found = False + + if curr_str: + fixed_list += [curr_str] + return fixed_list diff --git a/devtools/meson/mesonbuild/cmake/tracetargets.py b/devtools/meson/mesonbuild/cmake/tracetargets.py new file mode 100644 index 0000000..338364d --- /dev/null +++ b/devtools/meson/mesonbuild/cmake/tracetargets.py @@ -0,0 +1,119 @@ +# SPDX-License-Identifer: Apache-2.0 +# Copyright 2021 The Meson development team +from __future__ import annotations + +from .common import cmake_is_debug +from .. import mlog + +from pathlib import Path +import re +import typing as T + +if T.TYPE_CHECKING: + from .traceparser import CMakeTraceParser + from ..environment import Environment + from ..compilers import Compiler + from ..dependencies import MissingCompiler + +class ResolvedTarget: + def __init__(self) -> None: + self.include_directories: T.List[str] = [] + self.link_flags: T.List[str] = [] + self.public_compile_opts: T.List[str] = [] + self.libraries: T.List[str] = [] + +def resolve_cmake_trace_targets(target_name: str, + trace: 'CMakeTraceParser', + env: 'Environment', + *, + clib_compiler: T.Union['MissingCompiler', 'Compiler'] = None, + not_found_warning: T.Callable[[str], None] = lambda x: None) -> ResolvedTarget: + res = ResolvedTarget() + targets = [target_name] + + # recognise arguments we should pass directly to the linker + reg_is_lib = re.compile(r'^(-l[a-zA-Z0-9_]+|-l?pthread)$') + reg_is_maybe_bare_lib = re.compile(r'^[a-zA-Z0-9_]+$') + + is_debug = cmake_is_debug(env) + + processed_targets: T.List[str] = [] + while len(targets) > 0: + curr = targets.pop(0) + + # Skip already processed targets + if curr in processed_targets: + continue + + if curr not in trace.targets: + if reg_is_lib.match(curr): + res.libraries += [curr] + elif Path(curr).is_absolute() and Path(curr).exists(): + res.libraries += [curr] + elif env.machines.build.is_windows() and reg_is_maybe_bare_lib.match(curr) and clib_compiler: + # On Windows, CMake library dependencies can be passed as bare library names, + # CMake brute-forces a combination of prefix/suffix combinations to find the + # right library. Assume any bare argument passed which is not also a CMake + # target must be a system library we should try to link against. + res.libraries += clib_compiler.find_library(curr, env, []) + else: + not_found_warning(curr) + continue + + tgt = trace.targets[curr] + cfgs = [] + cfg = '' + mlog.debug(tgt) + + if 'INTERFACE_INCLUDE_DIRECTORIES' in tgt.properties: + res.include_directories += [x for x in tgt.properties['INTERFACE_INCLUDE_DIRECTORIES'] if x] + + if 'INTERFACE_LINK_OPTIONS' in tgt.properties: + res.link_flags += [x for x in tgt.properties['INTERFACE_LINK_OPTIONS'] if x] + + if 'INTERFACE_COMPILE_DEFINITIONS' in tgt.properties: + res.public_compile_opts += ['-D' + re.sub('^-D', '', x) for x in tgt.properties['INTERFACE_COMPILE_DEFINITIONS'] if x] + + if 'INTERFACE_COMPILE_OPTIONS' in tgt.properties: + res.public_compile_opts += [x for x in tgt.properties['INTERFACE_COMPILE_OPTIONS'] if x] + + if 'IMPORTED_CONFIGURATIONS' in tgt.properties: + cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x] + cfg = cfgs[0] + + if is_debug: + if 'DEBUG' in cfgs: + cfg = 'DEBUG' + elif 'RELEASE' in cfgs: + cfg = 'RELEASE' + else: + if 'RELEASE' in cfgs: + cfg = 'RELEASE' + + if f'IMPORTED_IMPLIB_{cfg}' in tgt.properties: + res.libraries += [x for x in tgt.properties[f'IMPORTED_IMPLIB_{cfg}'] if x] + elif 'IMPORTED_IMPLIB' in tgt.properties: + res.libraries += [x for x in tgt.properties['IMPORTED_IMPLIB'] if x] + elif f'IMPORTED_LOCATION_{cfg}' in tgt.properties: + res.libraries += [x for x in tgt.properties[f'IMPORTED_LOCATION_{cfg}'] if x] + elif 'IMPORTED_LOCATION' in tgt.properties: + res.libraries += [x for x in tgt.properties['IMPORTED_LOCATION'] if x] + + if 'LINK_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['LINK_LIBRARIES'] if x] + if 'INTERFACE_LINK_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['INTERFACE_LINK_LIBRARIES'] if x] + + if f'IMPORTED_LINK_DEPENDENT_LIBRARIES_{cfg}' in tgt.properties: + targets += [x for x in tgt.properties[f'IMPORTED_LINK_DEPENDENT_LIBRARIES_{cfg}'] if x] + elif 'IMPORTED_LINK_DEPENDENT_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES'] if x] + + processed_targets += [curr] + + res.include_directories = sorted(set(res.include_directories)) + res.link_flags = sorted(set(res.link_flags)) + res.public_compile_opts = sorted(set(res.public_compile_opts)) + res.libraries = sorted(set(res.libraries)) + + return res diff --git a/devtools/meson/mesonbuild/compilers/__init__.py b/devtools/meson/mesonbuild/compilers/__init__.py new file mode 100644 index 0000000..c516aab --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/__init__.py @@ -0,0 +1,97 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Public symbols for compilers sub-package when using 'from . import compilers' +__all__ = [ + 'Compiler', + 'RunResult', + + 'all_languages', + 'base_options', + 'clib_langs', + 'clink_langs', + 'c_suffixes', + 'cpp_suffixes', + 'get_base_compile_args', + 'get_base_link_args', + 'is_assembly', + 'is_header', + 'is_library', + 'is_llvm_ir', + 'is_object', + 'is_source', + 'is_known_suffix', + 'lang_suffixes', + 'LANGUAGES_USING_LDFLAGS', + 'sort_clink', + 'SUFFIX_TO_LANG', + + 'compiler_from_language', + 'detect_compiler_for', + 'detect_static_linker', + 'detect_c_compiler', + 'detect_cpp_compiler', + 'detect_cuda_compiler', + 'detect_fortran_compiler', + 'detect_objc_compiler', + 'detect_objcpp_compiler', + 'detect_java_compiler', + 'detect_cs_compiler', + 'detect_vala_compiler', + 'detect_rust_compiler', + 'detect_d_compiler', + 'detect_swift_compiler', +] + +# Bring symbols from each module into compilers sub-package namespace +from .compilers import ( + Compiler, + RunResult, + all_languages, + base_options, + clib_langs, + clink_langs, + c_suffixes, + cpp_suffixes, + get_base_compile_args, + get_base_link_args, + is_header, + is_source, + is_assembly, + is_llvm_ir, + is_object, + is_library, + is_known_suffix, + lang_suffixes, + LANGUAGES_USING_LDFLAGS, + sort_clink, + SUFFIX_TO_LANG, +) +from .detect import ( + compiler_from_language, + detect_compiler_for, + detect_static_linker, + detect_c_compiler, + detect_cpp_compiler, + detect_cuda_compiler, + detect_objc_compiler, + detect_objcpp_compiler, + detect_fortran_compiler, + detect_java_compiler, + detect_cs_compiler, + detect_vala_compiler, + detect_rust_compiler, + detect_d_compiler, + detect_swift_compiler, +) diff --git a/devtools/meson/mesonbuild/compilers/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7542438286a8f8336bc9b4b886676ecae63b5ce2 GIT binary patch literal 1492 zcmchXOK;Oa5XX}=&HK^3`+laSy&!Q#2vHubKvj_lmCz{C%JDdMX1J82SgKyX3W^3SvXot>Q-YyGrbE+owL>HFv5mwY1el?St{Ym6u6QQr+P zfk{l^0;X{hGnmC3=COc9EMXZdSj8o*VI3RT#1^)(gUh&rtGI^ixPhCvh1m;!5Xc@I&HuPZNesP!4_@9HtoO;?ZPhY z!5(#?OZ%`-2XJ6w-0LNd4t4HXKx5Z)q|U#I{5Ot@yik`d&l8^Ik0NX2C|w#@$`Qdh zbOT@Mg6+A3$*j^vWBXUrLBSR(8V=nLyu==l<56qmgkloJzS~V$a-?*9E>EINw4$qo zrIbSh?^fr{;L@?sWLGez*;iWf_RjXMNw_9!qX&ccjvY=+6-3f@bk(R=esJSYbI@h3 zCQhhxc6@$%aeVrsCoXy~&rikK^OLjV)1EGWl`X$!HlIRb`v)4r7_I z!dPXjF*X>RjCIBqW1F$V*k$Z7_*Zd$bWdl6;PWALe)hf8e=7zucRl@wC4EfDLoSc; zJ2a)Sxf8K|_5U%frLfjwU>f9p= aF!G$o{AJWDgH$q=GSA=dKYC@-{mxHOBbe0y literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/__pycache__/c.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/__pycache__/c.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c49ba23abb785a386558338b1dcf76642c0249f GIT binary patch literal 33888 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 A>i_@% literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/__pycache__/c_function_attributes.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/__pycache__/c_function_attributes.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d20cf5a3283531af2ef6a25c193afd8017acb3d5 GIT binary patch literal 4288 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/__pycache__/d.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/__pycache__/d.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2dfb197d37437b18b0050598387ecb8731cada8c GIT binary patch literal 30152 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%0AG>Fo$QU{SiNKDyVtwz=aF#NgwUtTK>Xn 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 R?-9&Be`6E#8&6UlIu{gL#0} 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 aW+*e7*^tR*7BUUQ9?6WSH>8Ktk^cin#1WJL literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/asm.py b/devtools/meson/mesonbuild/compilers/asm.py new file mode 100644 index 0000000..e34b4a6 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/asm.py @@ -0,0 +1,330 @@ +import os +import typing as T + +from ..mesonlib import EnvironmentException, OptionKey, get_meson_command +from .compilers import Compiler +from .mixins.metrowerks import MetrowerksCompiler, mwasmarm_instruction_set_args, mwasmeppc_instruction_set_args + +if T.TYPE_CHECKING: + from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..envconfig import MachineInfo + +nasm_optimization_args = { + 'plain': [], + '0': ['-O0'], + 'g': ['-O0'], + '1': ['-O1'], + '2': ['-Ox'], + '3': ['-Ox'], + 's': ['-Ox'], +} # type: T.Dict[str, T.List[str]] + + +class NasmCompiler(Compiler): + language = 'nasm' + id = 'nasm' + + # https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features + crt_args: T.Dict[str, T.List[str]] = { + 'none': [], + 'md': ['/DEFAULTLIB:ucrt.lib', '/DEFAULTLIB:vcruntime.lib', '/DEFAULTLIB:msvcrt.lib'], + 'mdd': ['/DEFAULTLIB:ucrtd.lib', '/DEFAULTLIB:vcruntimed.lib', '/DEFAULTLIB:msvcrtd.lib'], + 'mt': ['/DEFAULTLIB:libucrt.lib', '/DEFAULTLIB:libvcruntime.lib', '/DEFAULTLIB:libcmt.lib'], + 'mtd': ['/DEFAULTLIB:libucrtd.lib', '/DEFAULTLIB:libvcruntimed.lib', '/DEFAULTLIB:libcmtd.lib'], + } + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, + for_machine: 'MachineChoice', info: 'MachineInfo', + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, is_cross: bool = False): + super().__init__(ccache, exelist, version, for_machine, info, linker, full_version, is_cross) + if 'link' in self.linker.id: + self.base_options.add(OptionKey('b_vscrt')) + + def needs_static_linker(self) -> bool: + return True + + def get_always_args(self) -> T.List[str]: + cpu = '64' if self.info.is_64_bit else '32' + if self.info.is_windows() or self.info.is_cygwin(): + plat = 'win' + define = f'WIN{cpu}' + elif self.info.is_darwin(): + plat = 'macho' + define = 'MACHO' + else: + plat = 'elf' + define = 'ELF' + args = ['-f', f'{plat}{cpu}', f'-D{define}'] + if self.info.is_64_bit: + args.append('-D__x86_64__') + return args + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-o', outputname] + + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: + outargs = [] + for arg in args: + if arg == '-pthread': + continue + outargs.append(arg) + return outargs + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return nasm_optimization_args[optimization_level] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + if self.info.is_windows(): + return [] + return ['-g', '-F', 'dwarf'] + return [] + + def get_depfile_suffix(self) -> str: + return 'd' + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['-MD', outfile, '-MQ', outtarget] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'x86', 'x86_64'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # FIXME: Not implemented + return [] + + def get_pic_args(self) -> T.List[str]: + return [] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if not path: + path = '.' + return ['-I' + path] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + return parameter_list + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + # Linking ASM-only objects into an executable or DLL + # require this, otherwise it'll fail to find + # _WinMain or _DllMainCRTStartup. + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + if not self.info.is_windows(): + return [] + if crt_val in self.crt_args: + return self.crt_args[crt_val] + assert crt_val in {'from_buildtype', 'static_from_buildtype'} + dbg = 'mdd' + rel = 'md' + if crt_val == 'static_from_buildtype': + dbg = 'mtd' + rel = 'mt' + # Match what build type flags used to do. + if buildtype == 'plain': + return [] + elif buildtype == 'debug': + return self.crt_args[dbg] + elif buildtype == 'debugoptimized': + return self.crt_args[rel] + elif buildtype == 'release': + return self.crt_args[rel] + elif buildtype == 'minsize': + return self.crt_args[rel] + else: + assert buildtype == 'custom' + raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + +class YasmCompiler(NasmCompiler): + id = 'yasm' + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + # Yasm is incompatible with Nasm optimization flags. + return [] + + def get_exelist(self, ccache: bool = True) -> T.List[str]: + # Wrap yasm executable with an internal script that will write depfile. + exelist = super().get_exelist(ccache) + return get_meson_command() + ['--internal', 'yasm'] + exelist + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + if self.info.is_windows(): + return ['-g', 'null'] + return ['-g', 'dwarf2'] + return [] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['--depfile', outfile] + +# https://learn.microsoft.com/en-us/cpp/assembler/masm/ml-and-ml64-command-line-reference +class MasmCompiler(Compiler): + language = 'masm' + id = 'ml' + + def get_compile_only_args(self) -> T.List[str]: + return ['/c'] + + def get_argument_syntax(self) -> str: + return 'msvc' + + def needs_static_linker(self) -> bool: + return True + + def get_always_args(self) -> T.List[str]: + return ['/nologo'] + + def get_werror_args(self) -> T.List[str]: + return ['/WX'] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['/Fo', outputname] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return [] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + return ['/Zi'] + return [] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'x86', 'x86_64'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # FIXME: Not implemented + return [] + + def get_pic_args(self) -> T.List[str]: + return [] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if not path: + path = '.' + return ['-I' + path] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I' or i[:2] == '/I': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + return parameter_list + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + def depfile_for_object(self, objfile: str) -> T.Optional[str]: + return None + + +# https://learn.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-command-line-reference +class MasmARMCompiler(Compiler): + language = 'masm' + id = 'armasm' + + def needs_static_linker(self) -> bool: + return True + + def get_always_args(self) -> T.List[str]: + return ['-nologo'] + + def get_werror_args(self) -> T.List[str]: + return [] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-o', outputname] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return [] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + return ['-g'] + return [] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'arm', 'aarch64'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # FIXME: Not implemented + return [] + + def get_pic_args(self) -> T.List[str]: + return [] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if not path: + path = '.' + return ['-i' + path] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + return parameter_list + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + def depfile_for_object(self, objfile: str) -> T.Optional[str]: + return None + + +class MetrowerksAsmCompiler(MetrowerksCompiler, Compiler): + language = 'nasm' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, + for_machine: 'MachineChoice', info: 'MachineInfo', + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, is_cross: bool = False): + Compiler.__init__(self, ccache, exelist, version, for_machine, info, linker, full_version, is_cross) + MetrowerksCompiler.__init__(self) + + self.warn_args = {'0': [], '1': [], '2': [], '3': [], 'everything': []} # type: T.Dict[str, T.List[str]] + self.can_compile_suffixes.add('s') + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + def get_pic_args(self) -> T.List[str]: + return [] + + def needs_static_linker(self) -> bool: + return True + + +class MetrowerksAsmCompilerARM(MetrowerksAsmCompiler): + id = 'mwasmarm' + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwasmarm_instruction_set_args.get(instruction_set, None) + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'arm'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') + + +class MetrowerksAsmCompilerEmbeddedPowerPC(MetrowerksAsmCompiler): + id = 'mwasmeppc' + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwasmeppc_instruction_set_args.get(instruction_set, None) + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + if self.info.cpu_family not in {'ppc'}: + raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') diff --git a/devtools/meson/mesonbuild/compilers/c.py b/devtools/meson/mesonbuild/compilers/c.py new file mode 100644 index 0000000..d514650 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/c.py @@ -0,0 +1,799 @@ +# Copyright 2012-2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os.path +import typing as T + +from .. import coredata +from .. import mlog +from ..mesonlib import MesonException, version_compare, OptionKey +from .c_function_attributes import C_FUNC_ATTRIBUTES +from .mixins.clike import CLikeCompiler +from .mixins.ccrx import CcrxCompiler +from .mixins.xc16 import Xc16Compiler +from .mixins.compcert import CompCertCompiler +from .mixins.ti import TICompiler +from .mixins.arm import ArmCompiler, ArmclangCompiler +from .mixins.visualstudio import MSVCCompiler, ClangClCompiler +from .mixins.gnu import GnuCompiler +from .mixins.gnu import gnu_common_warning_args, gnu_c_warning_args +from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler +from .mixins.clang import ClangCompiler +from .mixins.elbrus import ElbrusCompiler +from .mixins.pgi import PGICompiler +from .mixins.emscripten import EmscriptenMixin +from .mixins.metrowerks import MetrowerksCompiler +from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args +from .compilers import ( + gnu_winlibs, + msvc_winlibs, + Compiler, +) + +if T.TYPE_CHECKING: + from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType + from ..dependencies import Dependency + from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..programs import ExternalProgram + from .compilers import CompileCheckMode + + CompilerMixinBase = Compiler +else: + CompilerMixinBase = object + + +class CCompiler(CLikeCompiler, Compiler): + def attribute_check_func(self, name: str) -> str: + try: + return C_FUNC_ATTRIBUTES[name] + except KeyError: + raise MesonException(f'Unknown function attribute "{name}"') + + language = 'c' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + # If a child ObjC or CPP class has already set it, don't set it ourselves + Compiler.__init__(self, ccache, exelist, version, for_machine, info, + is_cross=is_cross, full_version=full_version, linker=linker) + CLikeCompiler.__init__(self, exe_wrapper) + + def get_no_stdinc_args(self) -> T.List[str]: + return ['-nostdinc'] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + code = 'int main(void) { int class=0; return class; }\n' + return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) + + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} + t = '''{prefix} + #include <{header}> + int main(void) {{ + /* If it's not defined as a macro, try to use as a symbol */ + #ifndef {symbol} + {symbol}; + #endif + return 0; + }}''' + return self.compiles(t.format(**fargs), env, extra_args=extra_args, + dependencies=dependencies) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + opts.update({ + OptionKey('std', machine=self.for_machine, lang=self.language): coredata.UserComboOption( + 'C language standard to use', + ['none'], + 'none', + ) + }) + return opts + + +class _ClangCStds(CompilerMixinBase): + + """Mixin class for clang based compilers for setting C standards. + + This is used by both ClangCCompiler and ClangClCompiler, as they share + the same versions + """ + + _C17_VERSION = '>=6.0.0' + _C18_VERSION = '>=8.0.0' + _C2X_VERSION = '>=9.0.0' + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + c_stds = ['c89', 'c99', 'c11'] + g_stds = ['gnu89', 'gnu99', 'gnu11'] + # https://releases.llvm.org/6.0.0/tools/clang/docs/ReleaseNotes.html + # https://en.wikipedia.org/wiki/Xcode#Latest_versions + if version_compare(self.version, self._C17_VERSION): + c_stds += ['c17'] + g_stds += ['gnu17'] + if version_compare(self.version, self._C18_VERSION): + c_stds += ['c18'] + g_stds += ['gnu18'] + if version_compare(self.version, self._C2X_VERSION): + c_stds += ['c2x'] + g_stds += ['gnu2x'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds + return opts + + +class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler): + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version) + ClangCompiler.__init__(self, defines) + default_warn_args = ['-Wall', '-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': ['-Weverything']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + if self.info.is_windows() or self.info.is_cygwin(): + opts.update({ + OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-std=' + std.value) + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + if self.info.is_windows() or self.info.is_cygwin(): + # without a typedict mypy can't understand this. + libs = options[OptionKey('winlibs', machine=self.for_machine, lang=self.language)].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs + return [] + + +class ArmLtdClangCCompiler(ClangCCompiler): + + id = 'armltdclang' + + +class AppleClangCCompiler(ClangCCompiler): + + """Handle the differences between Apple Clang and Vanilla Clang. + + Right now this just handles the differences between the versions that new + C standards were added. + """ + + _C17_VERSION = '>=10.0.0' + _C18_VERSION = '>=11.0.0' + _C2X_VERSION = '>=11.0.0' + + +class EmscriptenCCompiler(EmscriptenMixin, ClangCCompiler): + + id = 'emscripten' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + if not is_cross: + raise MesonException('Emscripten compiler can only be used for cross compilation.') + if not version_compare(version, '>=1.39.19'): + raise MesonException('Meson requires Emscripten >= 1.39.19') + ClangCCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper=exe_wrapper, linker=linker, + defines=defines, full_version=full_version) + + +class ArmclangCCompiler(ArmclangCompiler, CCompiler): + ''' + Keil armclang + ''' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ArmclangCompiler.__init__(self) + default_warn_args = ['-Wall', '-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': ['-Weverything']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-std=' + std.value) + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + +class GnuCCompiler(GnuCompiler, CCompiler): + + _C18_VERSION = '>=8.0.0' + _C2X_VERSION = '>=9.0.0' + _INVALID_PCH_VERSION = ">=3.4.0" + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version) + GnuCompiler.__init__(self, defines) + default_warn_args = ['-Wall'] + if version_compare(self.version, self._INVALID_PCH_VERSION): + default_warn_args += ['-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': (default_warn_args + ['-Wextra', '-Wpedantic'] + + self.supported_warn_args(gnu_common_warning_args) + + self.supported_warn_args(gnu_c_warning_args))} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c89', 'c99', 'c11'] + g_stds = ['gnu89', 'gnu99', 'gnu11'] + if version_compare(self.version, self._C18_VERSION): + c_stds += ['c17', 'c18'] + g_stds += ['gnu17', 'gnu18'] + if version_compare(self.version, self._C2X_VERSION): + c_stds += ['c2x'] + g_stds += ['gnu2x'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + c_stds + g_stds + if self.info.is_windows() or self.info.is_cygwin(): + opts.update({ + key.evolve('winlibs'): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', lang=self.language, machine=self.for_machine)] + if std.value != 'none': + args.append('-std=' + std.value) + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + if self.info.is_windows() or self.info.is_cygwin(): + # without a typeddict mypy can't figure this out + libs: T.List[str] = options[OptionKey('winlibs', lang=self.language, machine=self.for_machine)].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs + return [] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return ['-fpch-preprocess', '-include', os.path.basename(header)] + + +class PGICCompiler(PGICompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + PGICompiler.__init__(self) + + +class NvidiaHPC_CCompiler(PGICompiler, CCompiler): + + id = 'nvidia_hpc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + PGICompiler.__init__(self) + + +class ElbrusCCompiler(ElbrusCompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ElbrusCompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + stds = ['c89', 'c9x', 'c99', 'gnu89', 'gnu9x', 'gnu99'] + stds += ['iso9899:1990', 'iso9899:199409', 'iso9899:1999'] + if version_compare(self.version, '>=1.20.00'): + stds += ['c11', 'gnu11'] + if version_compare(self.version, '>=1.21.00') and version_compare(self.version, '<1.22.00'): + stds += ['c90', 'c1x', 'gnu90', 'gnu1x', 'iso9899:2011'] + if version_compare(self.version, '>=1.23.00'): + stds += ['c90', 'c1x', 'gnu90', 'gnu1x', 'iso9899:2011'] + if version_compare(self.version, '>=1.26.00'): + stds += ['c17', 'c18', 'iso9899:2017', 'iso9899:2018', 'gnu17', 'gnu18'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + stds + return opts + + # Elbrus C compiler does not have lchmod, but there is only linker warning, not compiler error. + # So we should explicitly fail at this case. + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + if funcname == 'lchmod': + return False, False + else: + return super().has_function(funcname, prefix, env, + extra_args=extra_args, + dependencies=dependencies) + + +class IntelCCompiler(IntelGnuLikeCompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + IntelGnuLikeCompiler.__init__(self) + self.lang_header = 'c-header' + default_warn_args = ['-Wall', '-w3'] + self.warn_args = {'0': [], + '1': default_warn_args + ['-diag-disable:remark'], + '2': default_warn_args + ['-Wextra', '-diag-disable:remark'], + '3': default_warn_args + ['-Wextra', '-diag-disable:remark'], + 'everything': default_warn_args + ['-Wextra']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c89', 'c99'] + g_stds = ['gnu89', 'gnu99'] + if version_compare(self.version, '>=16.0.0'): + c_stds += ['c11'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-std=' + std.value) + return args + + +class IntelLLVMCCompiler(ClangCCompiler): + + id = 'intel-llvm' + + +class VisualStudioLikeCCompilerMixin(CompilerMixinBase): + + """Shared methods that apply to MSVC-like C compilers.""" + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + opts.update({ + OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption( + 'Windows libs to link against.', + msvc_winlibs, + ), + }) + return opts + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + # need a TypeDict to make this work + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + libs = options[key].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs + + +class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + + _C11_VERSION = '>=19.28' + _C17_VERSION = '>=19.28' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, + full_version=full_version) + MSVCCompiler.__init__(self, target) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + c_stds = ['c89', 'c99'] + # Need to have these to be compatible with projects + # that set c_std to e.g. gnu99. + # https://github.com/mesonbuild/meson/issues/7611 + g_stds = ['gnu89', 'gnu90', 'gnu9x', 'gnu99'] + if version_compare(self.version, self._C11_VERSION): + c_stds += ['c11'] + g_stds += ['gnu1x', 'gnu11'] + if version_compare(self.version, self._C17_VERSION): + c_stds += ['c17', 'c18'] + g_stds += ['gnu17', 'gnu18'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + c_stds + g_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value.startswith('gnu'): + mlog.log( + 'cl.exe does not actually support gnu standards, and meson ' + 'will instead demote to the nearest ISO C standard. This ' + 'may cause compilation to fail.', once=True) + # As of MVSC 16.8, /std:c11 and /std:c17 are the only valid C standard options. + if std.value in {'c11', 'gnu1x', 'gnu11'}: + args.append('/std:c11') + elif std.value in {'c17', 'c18', 'gnu17', 'gnu18'}: + args.append('/std:c17') + return args + + +class ClangClCCompiler(_ClangCStds, ClangClCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, [], exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, + full_version=full_version) + ClangClCompiler.__init__(self, target) + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key].value + if std != "none": + return [f'/clang:-std={std}'] + return [] + + +class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + + """Intel "ICL" compiler abstraction.""" + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, [], exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, + full_version=full_version) + IntelVisualStudioLikeCompiler.__init__(self, target) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'c11'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value == 'c89': + mlog.log("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True) + elif std.value != 'none': + args.append('/Qstd:' + std.value) + return args + + +class IntelLLVMClCCompiler(IntelClCCompiler): + + id = 'intel-llvm-cl' + + +class ArmCCompiler(ArmCompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, + full_version=full_version) + ArmCompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'c11'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('--' + std.value) + return args + + +class CcrxCCompiler(CcrxCompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + CcrxCompiler.__init__(self) + + # Override CCompiler.get_always_args + def get_always_args(self) -> T.List[str]: + return ['-nologo'] + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99'] + return opts + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value == 'c89': + args.append('-lang=c') + elif std.value == 'c99': + args.append('-lang=c99') + return args + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-optimize=0'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-output=obj={target}'] + + def get_werror_args(self) -> T.List[str]: + return ['-change_message=error'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['-include=' + path] + + +class Xc16CCompiler(Xc16Compiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + Xc16Compiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'gnu89', 'gnu99'] + return opts + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('-ansi') + args.append('-std=' + std.value) + return args + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-O0'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-o{target}'] + + def get_werror_args(self) -> T.List[str]: + return ['-change_message=error'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['-I' + path] + +class CompCertCCompiler(CompCertCompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + CompCertCompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-O0'] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-o{target}'] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['-I' + path] + +class TICCompiler(TICompiler, CCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + TICompiler.__init__(self) + + # Override CCompiler.get_always_args + def get_always_args(self) -> T.List[str]: + return [] + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c89', 'c99', 'c11'] + return opts + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('--' + std.value) + return args + +class C2000CCompiler(TICCompiler): + # Required for backwards compat with projects created before ti-cgt support existed + id = 'c2000' + +class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler): + id = 'mwccarm' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwccarm_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c99'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang') + args.append(std.value) + return args + +class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler): + id = 'mwcceppc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwcceppc_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c99'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang ' + std.value) + return args diff --git a/devtools/meson/mesonbuild/compilers/c_function_attributes.py b/devtools/meson/mesonbuild/compilers/c_function_attributes.py new file mode 100644 index 0000000..71ee9b2 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/c_function_attributes.py @@ -0,0 +1,143 @@ +# These functions are based on the following code: +# https://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_gcc_func_attribute.m4, +# which is licensed under the following terms: +# +# Copyright (c) 2013 Gabriele Svelto +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. +# + +C_FUNC_ATTRIBUTES = { + 'alias': ''' + int foo(void) { return 0; } + int bar(void) __attribute__((alias("foo")));''', + 'aligned': + 'int foo(void) __attribute__((aligned(32)));', + 'alloc_size': + 'void *foo(int a) __attribute__((alloc_size(1)));', + 'always_inline': + 'inline __attribute__((always_inline)) int foo(void) { return 0; }', + 'artificial': + 'inline __attribute__((artificial)) int foo(void) { return 0; }', + 'cold': + 'int foo(void) __attribute__((cold));', + 'const': + 'int foo(void) __attribute__((const));', + 'constructor': + 'int foo(void) __attribute__((constructor));', + 'constructor_priority': + 'int foo( void ) __attribute__((__constructor__(65535/2)));', + 'deprecated': + 'int foo(void) __attribute__((deprecated("")));', + 'destructor': + 'int foo(void) __attribute__((destructor));', + 'dllexport': + '__declspec(dllexport) int foo(void) { return 0; }', + 'dllimport': + '__declspec(dllimport) int foo(void);', + 'error': + 'int foo(void) __attribute__((error("")));', + 'externally_visible': + 'int foo(void) __attribute__((externally_visible));', + 'fallthrough': ''' + int foo( void ) { + switch (0) { + case 1: __attribute__((fallthrough)); + case 2: break; + } + return 0; + };''', + 'flatten': + 'int foo(void) __attribute__((flatten));', + 'format': + 'int foo(const char * p, ...) __attribute__((format(printf, 1, 2)));', + 'format_arg': + 'char * foo(const char * p) __attribute__((format_arg(1)));', + 'force_align_arg_pointer': + '__attribute__((force_align_arg_pointer)) int foo(void) { return 0; }', + 'gnu_inline': + 'inline __attribute__((gnu_inline)) int foo(void) { return 0; }', + 'hot': + 'int foo(void) __attribute__((hot));', + 'ifunc': + ('int my_foo(void) { return 0; }' + 'static int (*resolve_foo(void))(void) { return my_foo; }' + 'int foo(void) __attribute__((ifunc("resolve_foo")));'), + 'leaf': + '__attribute__((leaf)) int foo(void) { return 0; }', + 'malloc': + 'int *foo(void) __attribute__((malloc));', + 'noclone': + 'int foo(void) __attribute__((noclone));', + 'noinline': + '__attribute__((noinline)) int foo(void) { return 0; }', + 'nonnull': + 'int foo(char * p) __attribute__((nonnull(1)));', + 'noreturn': + 'int foo(void) __attribute__((noreturn));', + 'nothrow': + 'int foo(void) __attribute__((nothrow));', + 'optimize': + '__attribute__((optimize(3))) int foo(void) { return 0; }', + 'packed': + 'struct __attribute__((packed)) foo { int bar; };', + 'pure': + 'int foo(void) __attribute__((pure));', + 'returns_nonnull': + 'int *foo(void) __attribute__((returns_nonnull));', + 'section': ''' + #if defined(__APPLE__) && defined(__MACH__) + extern int foo __attribute__((section("__BAR,__bar"))); + #else + extern int foo __attribute__((section(".bar"))); + #endif''', + 'sentinel': + 'int foo(const char *bar, ...) __attribute__((sentinel));', + 'unused': + 'int foo(void) __attribute__((unused));', + 'used': + 'int foo(void) __attribute__((used));', + 'vector_size': + '__attribute__((vector_size(32))); int foo(void) { return 0; }', + 'visibility': ''' + int foo_def(void) __attribute__((visibility("default"))); + int foo_hid(void) __attribute__((visibility("hidden"))); + int foo_int(void) __attribute__((visibility("internal")));''', + 'visibility:default': + 'int foo(void) __attribute__((visibility("default")));', + 'visibility:hidden': + 'int foo(void) __attribute__((visibility("hidden")));', + 'visibility:internal': + 'int foo(void) __attribute__((visibility("internal")));', + 'visibility:protected': + 'int foo(void) __attribute__((visibility("protected")));', + 'warning': + 'int foo(void) __attribute__((warning("")));', + 'warn_unused_result': + 'int foo(void) __attribute__((warn_unused_result));', + 'weak': + 'int foo(void) __attribute__((weak));', + 'weakref': ''' + static int foo(void) { return 0; } + static int var(void) __attribute__((weakref("foo")));''', + 'retain': '__attribute__((retain)) int x;', +} + +CXX_FUNC_ATTRIBUTES = { + # Alias must be applied to the mangled name in C++ + 'alias': + ('extern "C" {' + 'int foo(void) { return 0; }' + '}' + 'int bar(void) __attribute__((alias("foo")));' + ), + 'ifunc': + ('extern "C" {' + 'int my_foo(void) { return 0; }' + 'static int (*resolve_foo(void))(void) { return my_foo; }' + '}' + 'int foo(void) __attribute__((ifunc("resolve_foo")));'), +} diff --git a/devtools/meson/mesonbuild/compilers/compilers.py b/devtools/meson/mesonbuild/compilers/compilers.py new file mode 100644 index 0000000..dda0f38 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/compilers.py @@ -0,0 +1,1390 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import abc +import contextlib, os.path, re +import enum +import itertools +import typing as T +from functools import lru_cache + +from .. import coredata +from .. import mlog +from .. import mesonlib +from ..mesonlib import ( + HoldableObject, + EnvironmentException, MesonException, + Popen_safe_logged, LibType, TemporaryDirectoryWinProof, OptionKey, +) + +from ..arglist import CompilerArgs + +if T.TYPE_CHECKING: + from ..build import BuildTarget + from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType + from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers import RSPFileSyntax + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..dependencies import Dependency + + CompilerType = T.TypeVar('CompilerType', bound='Compiler') + _T = T.TypeVar('_T') + +"""This file contains the data files of all compilers Meson knows +about. To support a new compiler, add its information below. +Also add corresponding autodetection code in detect.py.""" + +header_suffixes = {'h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di'} +obj_suffixes = {'o', 'obj', 'res'} +# To the emscripten compiler, .js files are libraries +lib_suffixes = {'a', 'lib', 'dll', 'dll.a', 'dylib', 'so', 'js'} +# Mapping of language to suffixes of files that should always be in that language +# This means we can't include .h headers here since they could be C, C++, ObjC, etc. +# First suffix is the language's default. +lang_suffixes = { + 'c': ('c',), + 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino', 'ixx', 'C'), + 'cuda': ('cu',), + # f90, f95, f03, f08 are for free-form fortran ('f90' recommended) + # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended) + 'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'), + 'd': ('d', 'di'), + 'objc': ('m',), + 'objcpp': ('mm',), + 'rust': ('rs',), + 'vala': ('vala', 'vapi', 'gs'), + 'cs': ('cs',), + 'swift': ('swift',), + 'java': ('java',), + 'cython': ('pyx', ), + 'nasm': ('asm',), + 'masm': ('masm',), +} +all_languages = lang_suffixes.keys() +c_cpp_suffixes = {'h'} +cpp_suffixes = set(lang_suffixes['cpp']) | c_cpp_suffixes +c_suffixes = set(lang_suffixes['c']) | c_cpp_suffixes +assembler_suffixes = {'s', 'S', 'sx', 'asm', 'masm'} +llvm_ir_suffixes = {'ll'} +all_suffixes = set(itertools.chain(*lang_suffixes.values(), assembler_suffixes, llvm_ir_suffixes, c_cpp_suffixes)) +source_suffixes = all_suffixes - header_suffixes +# List of languages that by default consume and output libraries following the +# C ABI; these can generally be used interchangeably +# This must be sorted, see sort_clink(). +clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'nasm', 'fortran') +# List of languages that can be linked with C code directly by the linker +# used in build.py:process_compilers() and build.py:get_dynamic_linker() +# This must be sorted, see sort_clink(). +clink_langs = ('d', 'cuda') + clib_langs + +SUFFIX_TO_LANG = dict(itertools.chain(*( + [(suffix, lang) for suffix in v] for lang, v in lang_suffixes.items()))) # type: T.Dict[str, str] + +# Languages that should use LDFLAGS arguments when linking. +LANGUAGES_USING_LDFLAGS = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'} # type: T.Set[str] +# Languages that should use CPPFLAGS arguments when linking. +LANGUAGES_USING_CPPFLAGS = {'c', 'cpp', 'objc', 'objcpp'} # type: T.Set[str] +soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') + +# Environment variables that each lang uses. +CFLAGS_MAPPING: T.Mapping[str, str] = { + 'c': 'CFLAGS', + 'cpp': 'CXXFLAGS', + 'cuda': 'CUFLAGS', + 'objc': 'OBJCFLAGS', + 'objcpp': 'OBJCXXFLAGS', + 'fortran': 'FFLAGS', + 'd': 'DFLAGS', + 'vala': 'VALAFLAGS', + 'rust': 'RUSTFLAGS', + 'cython': 'CYTHONFLAGS', + 'cs': 'CSFLAGS', # This one might not be standard. +} + +# All these are only for C-linkable languages; see `clink_langs` above. + +def sort_clink(lang: str) -> int: + ''' + Sorting function to sort the list of languages according to + reversed(compilers.clink_langs) and append the unknown langs in the end. + The purpose is to prefer C over C++ for files that can be compiled by + both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc. + ''' + if lang not in clink_langs: + return 1 + return -clink_langs.index(lang) + +def is_header(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + suffix = fname.split('.')[-1] + return suffix in header_suffixes + +def is_source_suffix(suffix: str) -> bool: + return suffix in source_suffixes + +def is_source(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + suffix = fname.split('.')[-1].lower() + return is_source_suffix(suffix) + +def is_assembly(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + suffix = fname.split('.')[-1] + return suffix in assembler_suffixes + +def is_llvm_ir(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + suffix = fname.split('.')[-1] + return suffix in llvm_ir_suffixes + +@lru_cache(maxsize=None) +def cached_by_name(fname: 'mesonlib.FileOrString') -> bool: + suffix = fname.split('.')[-1] + return suffix in obj_suffixes + +def is_object(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + return cached_by_name(fname) + +def is_library(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + + if soregex.match(fname): + return True + + suffix = fname.split('.')[-1] + return suffix in lib_suffixes + +def is_known_suffix(fname: 'mesonlib.FileOrString') -> bool: + if isinstance(fname, mesonlib.File): + fname = fname.fname + suffix = fname.split('.')[-1] + + return suffix in all_suffixes + + +class CompileCheckMode(enum.Enum): + + PREPROCESS = 'preprocess' + COMPILE = 'compile' + LINK = 'link' + + +cuda_buildtype_args = {'plain': [], + 'debug': ['-g', '-G'], + 'debugoptimized': ['-g', '-lineinfo'], + 'release': [], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] +java_buildtype_args = {'plain': [], + 'debug': ['-g'], + 'debugoptimized': ['-g'], + 'release': [], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +rust_buildtype_args = {'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +d_gdc_buildtype_args = {'plain': [], + 'debug': [], + 'debugoptimized': ['-finline-functions'], + 'release': ['-finline-functions'], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +d_ldc_buildtype_args = {'plain': [], + 'debug': [], + 'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'], + 'release': ['-enable-inlining', '-Hkeep-all-bodies'], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +d_dmd_buildtype_args = {'plain': [], + 'debug': [], + 'debugoptimized': ['-inline'], + 'release': ['-inline'], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +mono_buildtype_args = {'plain': [], + 'debug': [], + 'debugoptimized': ['-optimize+'], + 'release': ['-optimize+'], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +swift_buildtype_args = {'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + +gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32', + '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] # type: T.List[str] + +msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib', + 'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib', + 'uuid.lib', 'comdlg32.lib', 'advapi32.lib'] # type: T.List[str] + +clike_optimization_args = {'plain': [], + '0': [], + 'g': [], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Os'], + } # type: T.Dict[str, T.List[str]] + +cuda_optimization_args = {'plain': [], + '0': [], + 'g': ['-O0'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-O3'] + } # type: T.Dict[str, T.List[str]] + +cuda_debug_args = {False: [], + True: ['-g']} # type: T.Dict[bool, T.List[str]] + +clike_debug_args = {False: [], + True: ['-g']} # type: T.Dict[bool, T.List[str]] + +base_options: 'KeyedOptionDictType' = { + OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True), + OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), + OptionKey('b_lto_threads'): coredata.UserIntegerOption('Use multiple threads for Link Time Optimization', (None, None, 0)), + OptionKey('b_lto_mode'): coredata.UserComboOption('Select between different LTO modes.', + ['default', 'thin'], + 'default'), + OptionKey('b_thinlto_cache'): coredata.UserBooleanOption('Use LLVM ThinLTO caching for faster incremental builds', False), + OptionKey('b_thinlto_cache_dir'): coredata.UserStringOption('Directory to store ThinLTO cache objects', ''), + OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use', + ['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined'], + 'none'), + OptionKey('b_lundef'): coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True), + OptionKey('b_asneeded'): coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True), + OptionKey('b_pgo'): coredata.UserComboOption('Use profile guided optimization', + ['off', 'generate', 'use'], + 'off'), + OptionKey('b_coverage'): coredata.UserBooleanOption('Enable coverage tracking.', False), + OptionKey('b_colorout'): coredata.UserComboOption('Use colored output', + ['auto', 'always', 'never'], + 'always'), + OptionKey('b_ndebug'): coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'), + OptionKey('b_staticpic'): coredata.UserBooleanOption('Build static libraries as position independent', True), + OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False), + OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False), + OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.', + ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype', 'static_from_buildtype'], + 'from_buildtype'), +} + +def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType', + option: OptionKey) -> bool: + try: + if option not in boptions: + return False + ret = options[option].value + assert isinstance(ret, bool), 'must return bool' # could also be str + return ret + except KeyError: + return False + + +def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '_T') -> '_T': + """Get the value of an option, or the fallback value.""" + try: + v: '_T' = options[opt].value + except KeyError: + return fallback + + assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}' + # Mypy doesn't understand that the above assert ensures that v is type _T + return v + + +def are_asserts_disabled(options: KeyedOptionDictType) -> bool: + """Should debug assertions be disabled + + :param options: OptionDictionary + :return: whether to disable assertions or not + """ + return (options[OptionKey('b_ndebug')].value == 'true' or + (options[OptionKey('b_ndebug')].value == 'if-release' and + options[OptionKey('buildtype')].value in {'release', 'plain'})) + + +def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]: + args = [] # type T.List[str] + try: + if options[OptionKey('b_lto')].value: + args.extend(compiler.get_lto_compile_args( + threads=get_option_value(options, OptionKey('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'))) + except KeyError: + pass + try: + args += compiler.get_colorout_args(options[OptionKey('b_colorout')].value) + except KeyError: + pass + try: + args += compiler.sanitizer_compile_args(options[OptionKey('b_sanitize')].value) + except KeyError: + pass + try: + pgo_val = options[OptionKey('b_pgo')].value + if pgo_val == 'generate': + args.extend(compiler.get_profile_generate_args()) + elif pgo_val == 'use': + args.extend(compiler.get_profile_use_args()) + except KeyError: + pass + try: + if options[OptionKey('b_coverage')].value: + args += compiler.get_coverage_args() + except KeyError: + pass + try: + args += compiler.get_assert_args(are_asserts_disabled(options)) + except KeyError: + pass + # This does not need a try...except + if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')): + args.append('-fembed-bitcode') + try: + crt_val = options[OptionKey('b_vscrt')].value + buildtype = options[OptionKey('buildtype')].value + try: + args += compiler.get_crt_compile_args(crt_val, buildtype) + except AttributeError: + pass + except KeyError: + pass + return args + +def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', + is_shared_module: bool, build_dir: str) -> T.List[str]: + args = [] # type: T.List[str] + try: + if options[OptionKey('b_lto')].value: + thinlto_cache_dir = None + if get_option_value(options, OptionKey('b_thinlto_cache'), False): + thinlto_cache_dir = get_option_value(options, OptionKey('b_thinlto_cache_dir'), '') + if thinlto_cache_dir == '': + thinlto_cache_dir = os.path.join(build_dir, 'meson-private', 'thinlto-cache') + args.extend(linker.get_lto_link_args( + threads=get_option_value(options, OptionKey('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'), + thinlto_cache_dir=thinlto_cache_dir)) + except KeyError: + pass + try: + args += linker.sanitizer_link_args(options[OptionKey('b_sanitize')].value) + except KeyError: + pass + try: + pgo_val = options[OptionKey('b_pgo')].value + if pgo_val == 'generate': + args.extend(linker.get_profile_generate_args()) + elif pgo_val == 'use': + args.extend(linker.get_profile_use_args()) + except KeyError: + pass + try: + if options[OptionKey('b_coverage')].value: + args += linker.get_coverage_link_args() + except KeyError: + pass + + as_needed = option_enabled(linker.base_options, options, OptionKey('b_asneeded')) + bitcode = option_enabled(linker.base_options, options, OptionKey('b_bitcode')) + # Shared modules cannot be built with bitcode_bundle because + # -bitcode_bundle is incompatible with -undefined and -bundle + if bitcode and not is_shared_module: + args.extend(linker.bitcode_args()) + elif as_needed: + # -Wl,-dead_strip_dylibs is incompatible with bitcode + args.extend(linker.get_asneeded_args()) + + # Apple's ld (the only one that supports bitcode) does not like -undefined + # arguments or -headerpad_max_install_names when bitcode is enabled + if not bitcode: + args.extend(linker.headerpad_args()) + if (not is_shared_module and + option_enabled(linker.base_options, options, OptionKey('b_lundef'))): + args.extend(linker.no_undefined_link_args()) + else: + args.extend(linker.get_allow_undefined_link_args()) + + try: + crt_val = options[OptionKey('b_vscrt')].value + buildtype = options[OptionKey('buildtype')].value + try: + args += linker.get_crt_link_args(crt_val, buildtype) + except AttributeError: + pass + except KeyError: + pass + return args + + +class CrossNoRunException(MesonException): + pass + +class RunResult(HoldableObject): + def __init__(self, compiled: bool, returncode: int = 999, + stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED', + cached: bool = False): + self.compiled = compiled + self.returncode = returncode + self.stdout = stdout + self.stderr = stderr + self.cached = cached + + +class CompileResult(HoldableObject): + + """The result of Compiler.compiles (and friends).""" + + def __init__(self, stdo: T.Optional[str] = None, stde: T.Optional[str] = None, + command: T.Optional[T.List[str]] = None, + returncode: int = 999, + input_name: T.Optional[str] = None, + output_name: T.Optional[str] = None, + cached: bool = False): + self.stdout = stdo + self.stderr = stde + self.input_name = input_name + self.output_name = output_name + self.command = command or [] + self.cached = cached + self.returncode = returncode + + +class Compiler(HoldableObject, metaclass=abc.ABCMeta): + # Libraries to ignore in find_library() since they are provided by the + # compiler or the C library. Currently only used for MSVC. + ignore_libs = [] # type: T.List[str] + # Libraries that are internal compiler implementations, and must not be + # manually searched. + internal_libs = [] # type: T.List[str] + + LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]] + INVOKES_LINKER = True + + language: str + id: str + warn_args: T.Dict[str, T.List[str]] + mode: str = 'COMPILER' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, + for_machine: MachineChoice, info: 'MachineInfo', + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, is_cross: bool = False): + self.exelist = ccache + exelist + self.exelist_no_ccache = exelist + # In case it's been overridden by a child class already + if not hasattr(self, 'file_suffixes'): + self.file_suffixes = lang_suffixes[self.language] + if not hasattr(self, 'can_compile_suffixes'): + self.can_compile_suffixes = set(self.file_suffixes) + self.default_suffix = self.file_suffixes[0] + self.version = version + self.full_version = full_version + self.for_machine = for_machine + self.base_options: T.Set[OptionKey] = set() + self.linker = linker + self.info = info + self.is_cross = is_cross + self.modes: T.List[Compiler] = [] + + def __repr__(self) -> str: + repr_str = "<{0}: v{1} `{2}`>" + return repr_str.format(self.__class__.__name__, self.version, + ' '.join(self.exelist)) + + @lru_cache(maxsize=None) + def can_compile(self, src: 'mesonlib.FileOrString') -> bool: + if isinstance(src, mesonlib.File): + src = src.fname + suffix = os.path.splitext(src)[1] + if suffix != '.C': + suffix = suffix.lower() + return bool(suffix) and suffix[1:] in self.can_compile_suffixes + + def get_id(self) -> str: + return self.id + + def get_modes(self) -> T.List[Compiler]: + return self.modes + + def get_linker_id(self) -> str: + # There is not guarantee that we have a dynamic linker instance, as + # some languages don't have separate linkers and compilers. In those + # cases return the compiler id + try: + return self.linker.id + except AttributeError: + return self.id + + def get_version_string(self) -> str: + details = [self.id, self.version] + if self.full_version: + details += ['"%s"' % (self.full_version)] + return '(%s)' % (' '.join(details)) + + def get_language(self) -> str: + return self.language + + @classmethod + def get_display_language(cls) -> str: + return cls.language.capitalize() + + def get_default_suffix(self) -> str: + return self.default_suffix + + def get_define(self, dname: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.List['Dependency'], + disable_cache: bool = False) -> T.Tuple[str, bool]: + raise EnvironmentException('%s does not support get_define ' % self.get_id()) + + def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], + guess: T.Optional[int], prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']]) -> int: + raise EnvironmentException('%s does not support compute_int ' % self.get_id()) + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) + + def has_members(self, typename: str, membernames: T.List[str], + prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) + + def has_type(self, typename: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + raise EnvironmentException('%s does not support has_type ' % self.get_id()) + + def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: + raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id()) + + def get_exelist(self, ccache: bool = True) -> T.List[str]: + return self.exelist.copy() if ccache else self.exelist_no_ccache.copy() + + def get_linker_exelist(self) -> T.List[str]: + return self.linker.get_exelist() if self.linker else self.get_exelist() + + @abc.abstractmethod + def get_output_args(self, outputname: str) -> T.List[str]: + pass + + def get_linker_output_args(self, outputname: str) -> T.List[str]: + return self.linker.get_output_args(outputname) + + def get_linker_search_args(self, dirname: str) -> T.List[str]: + return self.linker.get_search_args(dirname) + + def get_builtin_define(self, define: str) -> T.Optional[str]: + raise EnvironmentException('%s does not support get_builtin_define.' % self.id) + + def has_builtin_define(self, define: str) -> bool: + raise EnvironmentException('%s does not support has_builtin_define.' % self.id) + + def get_always_args(self) -> T.List[str]: + return [] + + def can_linker_accept_rsp(self) -> bool: + """ + Determines whether the linker can accept arguments using the @rsp syntax. + """ + return self.linker.get_accepts_rsp() + + def get_linker_always_args(self) -> T.List[str]: + return self.linker.get_always_args() + + def get_linker_lib_prefix(self) -> str: + return self.linker.get_lib_prefix() + + def gen_import_library_args(self, implibname: str) -> T.List[str]: + """ + Used only on Windows for libraries that need an import library. + This currently means C, C++, Fortran. + """ + return [] + + def get_options(self) -> 'MutableKeyedOptionDictType': + return {} + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return self.linker.get_option_args(options) + + def check_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + """Check that header is usable. + + Returns a two item tuple of bools. The first bool is whether the + check succeeded, the second is whether the result was cached (True) + or run fresh (False). + """ + raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) + + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + """Check that header is exists. + + This check will return true if the file exists, even if it contains: + + ```c + # error "You thought you could use this, LOLZ!" + ``` + + Use check_header if your header only works in some cases. + + Returns a two item tuple of bools. The first bool is whether the + check succeeded, the second is whether the result was cached (True) + or run fresh (False). + """ + raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) + + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) + + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: + raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) + + # Caching run() in general seems too risky (no way to know what the program + # depends on), but some callers know more about the programs they intend to + # run. + # For now we just accept code as a string, as that's what internal callers + # need anyway. If we wanted to accept files, the cache key would need to + # include mtime. + def cached_run(self, code: str, env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: + run_check_cache = env.coredata.run_check_cache + args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode('link')) + key = (code, tuple(args)) + if key in run_check_cache: + p = run_check_cache[key] + p.cached = True + mlog.debug('Using cached run result:') + mlog.debug('Code:\n', code) + mlog.debug('Args:\n', extra_args) + mlog.debug('Cached run returncode:\n', p.returncode) + mlog.debug('Cached run stdout:\n', p.stdout) + mlog.debug('Cached run stderr:\n', p.stderr) + else: + p = self.run(code, env, extra_args=extra_args, dependencies=dependencies) + run_check_cache[key] = p + return p + + def sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: + raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language()) + + def alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: + raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) + + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + """See if a function exists. + + Returns a two item tuple of bools. The first bool is whether the + check succeeded, the second is whether the result was cached (True) + or run fresh (False). + """ + raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) + + @classmethod + def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]: + "Always returns a copy that can be independently mutated" + return args.copy() + + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: + return self._unix_args_to_native(args, self.info) + + @classmethod + def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: + "Always returns a copy that can be independently mutated" + return args.copy() + + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: + raise EnvironmentException(f'Language {self.get_display_language()} does not support library finding.') + + def get_library_naming(self, env: 'Environment', libtype: LibType, + strict: bool = False) -> T.Optional[T.Tuple[str, ...]]: + raise EnvironmentException( + 'Language {} does not support get_library_naming.'.format( + self.get_display_language())) + + def get_program_dirs(self, env: 'Environment') -> T.List[str]: + return [] + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + raise EnvironmentException( + 'Language {} does not support has_multi_arguments.'.format( + self.get_display_language())) + + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self.linker.has_multi_arguments(args, env) + + def _get_compile_output(self, dirname: str, mode: str) -> str: + # TODO: mode should really be an enum + # In pre-processor mode, the output is sent to stdout and discarded + if mode == 'preprocess': + return None + # Extension only matters if running results; '.exe' is + # guaranteed to be executable on every platform. + if mode == 'link': + suffix = 'exe' + else: + suffix = 'obj' + return os.path.join(dirname, 'output.' + suffix) + + def get_compiler_args_for_mode(self, mode: CompileCheckMode) -> T.List[str]: + # TODO: mode should really be an enum + args = [] # type: T.List[str] + args += self.get_always_args() + if mode is CompileCheckMode.COMPILE: + args += self.get_compile_only_args() + elif mode is CompileCheckMode.PREPROCESS: + args += self.get_preprocess_only_args() + else: + assert mode is CompileCheckMode.LINK + return args + + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs: + """Return an appropriate CompilerArgs instance for this class.""" + return CompilerArgs(self, args) + + @contextlib.contextmanager + def compile(self, code: 'mesonlib.FileOrString', + extra_args: T.Union[None, CompilerArgs, T.List[str]] = None, + *, mode: str = 'link', want_output: bool = False, + temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: + # TODO: there isn't really any reason for this to be a contextmanager + if extra_args is None: + extra_args = [] + + with TemporaryDirectoryWinProof(dir=temp_dir) as tmpdirname: + no_ccache = False + if isinstance(code, str): + srcname = os.path.join(tmpdirname, + 'testfile.' + self.default_suffix) + with open(srcname, 'w', encoding='utf-8') as ofile: + ofile.write(code) + # ccache would result in a cache miss + no_ccache = True + contents = code + else: + srcname = code.fname + if not is_object(code.fname): + with open(code.fname, encoding='utf-8') as f: + contents = f.read() + else: + contents = '' + + # Construct the compiler command-line + commands = self.compiler_args() + commands.append(srcname) + + # Preprocess mode outputs to stdout, so no output args + output = self._get_compile_output(tmpdirname, mode) + if mode != 'preprocess': + commands += self.get_output_args(output) + commands.extend(self.get_compiler_args_for_mode(CompileCheckMode(mode))) + + # extra_args must be last because it could contain '/link' to + # pass args to VisualStudio's linker. In that case everything + # in the command line after '/link' is given to the linker. + if extra_args: + commands += extra_args + # Generate full command-line with the exelist + command_list = self.get_exelist(ccache=not no_ccache) + commands.to_native() + mlog.debug('Running compile:') + mlog.debug('Working directory: ', tmpdirname) + mlog.debug('Code:\n', contents) + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + if no_ccache: + os_env['CCACHE_DISABLE'] = '1' + p, stdo, stde = Popen_safe_logged(command_list, msg='Command line', cwd=tmpdirname, env=os_env) + + result = CompileResult(stdo, stde, command_list, p.returncode, input_name=srcname) + if want_output: + result.output_name = output + yield result + + @contextlib.contextmanager + def cached_compile(self, code: 'mesonlib.FileOrString', cdata: coredata.CoreData, *, + extra_args: T.Union[None, T.List[str], CompilerArgs] = None, + mode: str = 'link', + temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: + # TODO: There's isn't really any reason for this to be a context manager + + # Calculate the key + textra_args = tuple(extra_args) if extra_args is not None else tuple() # type: T.Tuple[str, ...] + key = (tuple(self.exelist), self.version, code, textra_args, mode) # type: coredata.CompilerCheckCacheKey + + # Check if not cached, and generate, otherwise get from the cache + if key in cdata.compiler_check_cache: + p = cdata.compiler_check_cache[key] + p.cached = True + mlog.debug('Using cached compile:') + mlog.debug('Cached command line: ', ' '.join(p.command), '\n') + mlog.debug('Code:\n', code) + mlog.debug('Cached compiler stdout:\n', p.stdout) + mlog.debug('Cached compiler stderr:\n', p.stderr) + yield p + else: + with self.compile(code, extra_args=extra_args, mode=mode, want_output=False, temp_dir=temp_dir) as p: + cdata.compiler_check_cache[key] = p + yield p + + def get_colorout_args(self, colortype: str) -> T.List[str]: + # TODO: colortype can probably be an emum + return [] + + # Some compilers (msvc) write debug info to a separate file. + # These args specify where it should be written. + def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: + return [] + + def get_link_debugfile_name(self, targetfile: str) -> str: + return self.linker.get_debugfile_name(targetfile) + + def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: + return self.linker.get_debugfile_args(targetfile) + + def get_std_shared_lib_link_args(self) -> T.List[str]: + return self.linker.get_std_shared_lib_args() + + def get_std_shared_module_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return self.linker.get_std_shared_module_args(options) + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + return self.linker.get_link_whole_for(args) + + def get_allow_undefined_link_args(self) -> T.List[str]: + return self.linker.get_allow_undefined_args() + + def no_undefined_link_args(self) -> T.List[str]: + return self.linker.no_undefined_args() + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + """Compiler arguments needed to enable the given instruction set. + + Return type ay be an empty list meaning nothing needed or None + meaning the given set is not supported. + """ + return None + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return self.linker.build_rpath_args( + env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + + def get_archive_name(self, filename: str) -> str: + return self.linker.get_archive_name(filename) + + def get_command_to_archive_shlib(self) -> T.List[str]: + return self.linker.get_command_to_archive_shlib() + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def thread_link_flags(self, env: 'Environment') -> T.List[str]: + return self.linker.thread_flags(env) + + def openmp_flags(self) -> T.List[str]: + raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language()) + + def openmp_link_flags(self) -> T.List[str]: + return self.openmp_flags() + + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]: + return [] + + def get_gui_app_args(self, value: bool) -> T.List[str]: + # Only used on Windows + return self.linker.get_gui_app_args(value) + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + # By default the dynamic linker is going to return an empty + # array in case it either doesn't support Windows subsystems + # or does not target Windows + return self.linker.get_win_subsystem_args(value) + + def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: + raise EnvironmentException( + f'Language {self.get_display_language()} does not support function attributes.') + + def get_pic_args(self) -> T.List[str]: + m = 'Language {} does not support position-independent code' + raise EnvironmentException(m.format(self.get_display_language())) + + def get_pie_args(self) -> T.List[str]: + m = 'Language {} does not support position-independent executable' + raise EnvironmentException(m.format(self.get_display_language())) + + def get_pie_link_args(self) -> T.List[str]: + return self.linker.get_pie_args() + + def get_argument_syntax(self) -> str: + """Returns the argument family type. + + Compilers fall into families if they try to emulate the command line + interface of another compiler. For example, clang is in the GCC family + since it accepts most of the same arguments as GCC. ICL (ICC on + windows) is in the MSVC family since it accepts most of the same + arguments as MSVC. + """ + return 'other' + + def get_profile_generate_args(self) -> T.List[str]: + raise EnvironmentException( + '%s does not support get_profile_generate_args ' % self.get_id()) + + def get_profile_use_args(self) -> T.List[str]: + raise EnvironmentException( + '%s does not support get_profile_use_args ' % self.get_id()) + + def remove_linkerlike_args(self, args: T.List[str]) -> T.List[str]: + rm_exact = ('-headerpad_max_install_names',) + rm_prefixes = ('-Wl,', '-L',) + rm_next = ('-L', '-framework',) + ret = [] # T.List[str] + iargs = iter(args) + for arg in iargs: + # Remove this argument + if arg in rm_exact: + continue + # If the argument starts with this, but is not *exactly* this + # f.ex., '-L' should match ['-Lfoo'] but not ['-L', 'foo'] + if arg.startswith(rm_prefixes) and arg not in rm_prefixes: + continue + # Ignore this argument and the one after it + if arg in rm_next: + next(iargs) + continue + ret.append(arg) + return ret + + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + return [] + + def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default', + thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]: + return self.linker.get_lto_args() + + def sanitizer_compile_args(self, value: str) -> T.List[str]: + return [] + + def sanitizer_link_args(self, value: str) -> T.List[str]: + return self.linker.sanitizer_args(value) + + def get_asneeded_args(self) -> T.List[str]: + return self.linker.get_asneeded_args() + + def headerpad_args(self) -> T.List[str]: + return self.linker.headerpad_args() + + def bitcode_args(self) -> T.List[str]: + return self.linker.bitcode_args() + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not implement get_buildtype_args') + + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + return self.linker.get_buildtype_args(buildtype) + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, + darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return self.linker.get_soname_args( + env, prefix, shlib_name, suffix, soversion, + darwin_versions) + + def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]: + return target.link_args + + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: + return dep.get_compile_args() + + def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]: + return dep.get_link_args() + + @classmethod + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: + """Get a list of arguments to pass to the compiler to set the linker. + """ + return [] + + def get_coverage_args(self) -> T.List[str]: + return [] + + def get_coverage_link_args(self) -> T.List[str]: + return self.linker.get_coverage_args() + + def get_assert_args(self, disable: bool) -> T.List[str]: + """Get arguments to enable or disable assertion. + + :param disable: Whether to disable assertions + :return: A list of string arguments for this compiler + """ + return [] + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + raise EnvironmentException('This compiler does not support Windows CRT selection') + + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + raise EnvironmentException('This compiler does not support Windows CRT selection') + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_preprocess_only_args(self) -> T.List[str]: + raise EnvironmentException('This compiler does not have a preprocessor') + + def get_preprocess_to_file_args(self) -> T.List[str]: + return self.get_preprocess_only_args() + + def get_default_include_dirs(self) -> T.List[str]: + # TODO: This is a candidate for returning an immutable list + return [] + + def get_largefile_args(self) -> T.List[str]: + '''Enable transparent large-file-support for 32-bit UNIX systems''' + if not (self.get_argument_syntax() == 'msvc' or self.info.is_darwin()): + # Enable large-file support unconditionally on all platforms other + # than macOS and MSVC. macOS is now 64-bit-only so it doesn't + # need anything special, and MSVC doesn't have automatic LFS. + # You must use the 64-bit counterparts explicitly. + # glibc, musl, and uclibc, and all BSD libcs support this. On Android, + # support for transparent LFS is available depending on the version of + # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs + # https://code.google.com/p/android/issues/detail?id=64613 + # + # If this breaks your code, fix it! It's been 20+ years! + return ['-D_FILE_OFFSET_BITS=64'] + # We don't enable -D_LARGEFILE64_SOURCE since that enables + # transitionary features and must be enabled by programs that use + # those features explicitly. + return [] + + def get_library_dirs(self, env: 'Environment', + elf_class: T.Optional[int] = None) -> T.List[str]: + return [] + + def get_return_value(self, + fname: str, + rtype: str, + prefix: str, + env: 'Environment', + extra_args: T.Optional[T.List[str]], + dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]: + raise EnvironmentException(f'{self.id} does not support get_return_value') + + def find_framework(self, + name: str, + env: 'Environment', + extra_dirs: T.List[str], + allow_system: bool = True) -> T.Optional[T.List[str]]: + raise EnvironmentException(f'{self.id} does not support find_framework') + + def find_framework_paths(self, env: 'Environment') -> T.List[str]: + raise EnvironmentException(f'{self.id} does not support find_framework_paths') + + def attribute_check_func(self, name: str) -> str: + raise EnvironmentException(f'{self.id} does not support attribute checks') + + def get_pch_suffix(self) -> str: + raise EnvironmentException(f'{self.id} does not support pre compiled headers') + + def get_pch_name(self, name: str) -> str: + raise EnvironmentException(f'{self.id} does not support pre compiled headers') + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not support pre compiled headers') + + def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not support function attributes') + + def name_string(self) -> str: + return ' '.join(self.exelist) + + @abc.abstractmethod + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + """Check that this compiler actually works. + + This should provide a simple compile/link test. Something as simple as: + ```python + main(): return 0 + ``` + is good enough here. + """ + + def split_shlib_to_parts(self, fname: str) -> T.Tuple[T.Optional[str], str]: + return None, fname + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return [] + + def get_std_exe_link_args(self) -> T.List[str]: + # TODO: is this a linker property? + return [] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + return [] + + def depfile_for_object(self, objfile: str) -> T.Optional[str]: + return objfile + '.' + self.get_depfile_suffix() + + def get_depfile_suffix(self) -> str: + raise EnvironmentException(f'{self.id} does not implement get_depfile_suffix') + + def get_no_stdinc_args(self) -> T.List[str]: + """Arguments to turn off default inclusion of standard libraries.""" + return [] + + def get_warn_args(self, level: str) -> T.List[str]: + return [] + + def get_werror_args(self) -> T.List[str]: + return [] + + @abc.abstractmethod + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + pass + + def get_module_incdir_args(self) -> T.Tuple[str, ...]: + raise EnvironmentException(f'{self.id} does not implement get_module_incdir_args') + + def get_module_outdir_args(self, path: str) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not implement get_module_outdir_args') + + def module_name_to_filename(self, module_name: str) -> str: + raise EnvironmentException(f'{self.id} does not implement module_name_to_filename') + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + """Arguments to pass the compiler and/or linker for checks. + + The default implementation turns off optimizations. + + Examples of things that go here: + - extra arguments for error checking + - Arguments required to make the compiler exit with a non-zero status + when something is wrong. + """ + return self.get_no_optimization_args() + + def get_no_optimization_args(self) -> T.List[str]: + """Arguments to the compiler to turn off all optimizations.""" + return [] + + def build_wrapper_args(self, env: 'Environment', + extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + mode: CompileCheckMode = CompileCheckMode.COMPILE) -> CompilerArgs: + """Arguments to pass the build_wrapper helper. + + This generally needs to be set on a per-language basis. It provides + a hook for languages to handle dependencies and extra args. The base + implementation handles the most common cases, namely adding the + check_arguments, unwrapping dependencies, and appending extra args. + """ + if callable(extra_args): + extra_args = extra_args(mode) + if extra_args is None: + extra_args = [] + if dependencies is None: + dependencies = [] + + # Collect compiler arguments + args = self.compiler_args(self.get_compiler_check_args(mode)) + for d in dependencies: + # Add compile flags needed by dependencies + args += d.get_compile_args() + if mode is CompileCheckMode.LINK: + # Add link flags needed to find dependencies + args += d.get_link_args() + + if mode is CompileCheckMode.COMPILE: + # Add DFLAGS from the env + args += env.coredata.get_external_args(self.for_machine, self.language) + elif mode is CompileCheckMode.LINK: + # Add LDFLAGS from the env + args += env.coredata.get_external_link_args(self.for_machine, self.language) + # extra_args must override all other arguments, so we add them last + args += extra_args + return args + + @contextlib.contextmanager + def _build_wrapper(self, code: 'mesonlib.FileOrString', env: 'Environment', + extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + mode: str = 'compile', want_output: bool = False, + disable_cache: bool = False, + temp_dir: str = None) -> T.Iterator[T.Optional[CompileResult]]: + """Helper for getting a cached value when possible. + + This method isn't meant to be called externally, it's mean to be + wrapped by other methods like compiles() and links(). + """ + args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode(mode)) + if disable_cache or want_output: + with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r: + yield r + else: + with self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) as r: + yield r + + def compiles(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + mode: str = 'compile', + disable_cache: bool = False) -> T.Tuple[bool, bool]: + with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: + return p.returncode == 0, p.cached + + def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + compiler: T.Optional['Compiler'] = None, + extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + mode: str = 'compile', + disable_cache: bool = False) -> T.Tuple[bool, bool]: + if compiler: + with compiler._build_wrapper(code, env, dependencies=dependencies, want_output=True) as r: + objfile = mesonlib.File.from_absolute_file(r.output_name) + return self.compiles(objfile, env, extra_args=extra_args, + dependencies=dependencies, mode='link', disable_cache=True) + + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode='link', disable_cache=disable_cache) + + def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + """Used by D for extra language features.""" + # TODO: using a TypeDict here would improve this + raise EnvironmentException(f'{self.id} does not implement get_feature_args') + + def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]: + raise EnvironmentException(f'{self.id} does not know how to do prelinking.') + + def rsp_file_syntax(self) -> 'RSPFileSyntax': + """The format of the RSP file that this compiler supports. + + If `self.can_linker_accept_rsp()` returns True, then this needs to + be implemented + """ + return self.linker.rsp_file_syntax() + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + """Arguments required for a debug build.""" + return [] + + def get_no_warn_args(self) -> T.List[str]: + """Arguments to completely disable warnings.""" + return [] + + def needs_static_linker(self) -> bool: + raise NotImplementedError(f'There is no static linker for {self.language}') + + def get_preprocessor(self) -> Compiler: + """Get compiler's preprocessor. + """ + raise EnvironmentException(f'{self.get_id()} does not support preprocessor') + +def get_global_options(lang: str, + comp: T.Type[Compiler], + for_machine: MachineChoice, + env: 'Environment') -> 'KeyedOptionDictType': + """Retrieve options that apply to all compilers for a given language.""" + description = f'Extra arguments passed to the {lang}' + argkey = OptionKey('args', lang=lang, machine=for_machine) + largkey = argkey.evolve('link_args') + envkey = argkey.evolve('env_args') + + comp_key = argkey if argkey in env.options else envkey + + comp_options = env.options.get(comp_key, []) + link_options = env.options.get(largkey, []) + + cargs = coredata.UserArrayOption( + description + ' compiler', + comp_options, split_args=True, user_input=True, allow_dups=True) + + largs = coredata.UserArrayOption( + description + ' linker', + link_options, split_args=True, user_input=True, allow_dups=True) + + if comp.INVOKES_LINKER and comp_key == envkey: + # If the compiler acts as a linker driver, and we're using the + # environment variable flags for both the compiler and linker + # arguments, then put the compiler flags in the linker flags as well. + # This is how autotools works, and the env vars feature is for + # autotools compatibility. + largs.extend_value(comp_options) + + opts: 'KeyedOptionDictType' = {argkey: cargs, largkey: largs} + + return opts diff --git a/devtools/meson/mesonbuild/compilers/cpp.py b/devtools/meson/mesonbuild/compilers/cpp.py new file mode 100644 index 0000000..0c68923 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/cpp.py @@ -0,0 +1,964 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import copy +import functools +import os.path +import typing as T + +from .. import coredata +from .. import mlog +from ..mesonlib import MesonException, version_compare, OptionKey + +from .compilers import ( + gnu_winlibs, + msvc_winlibs, + Compiler, +) +from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES +from .mixins.clike import CLikeCompiler +from .mixins.ccrx import CcrxCompiler +from .mixins.ti import TICompiler +from .mixins.arm import ArmCompiler, ArmclangCompiler +from .mixins.visualstudio import MSVCCompiler, ClangClCompiler +from .mixins.gnu import GnuCompiler, gnu_common_warning_args, gnu_cpp_warning_args +from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler +from .mixins.clang import ClangCompiler +from .mixins.elbrus import ElbrusCompiler +from .mixins.pgi import PGICompiler +from .mixins.emscripten import EmscriptenMixin +from .mixins.metrowerks import MetrowerksCompiler +from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args + +if T.TYPE_CHECKING: + from .compilers import CompileCheckMode + from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType + from ..dependencies import Dependency + from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..programs import ExternalProgram + CompilerMixinBase = CLikeCompiler +else: + CompilerMixinBase = object + + +def non_msvc_eh_options(eh: str, args: T.List[str]) -> None: + if eh == 'none': + args.append('-fno-exceptions') + elif eh in {'s', 'c'}: + mlog.warning(f'non-MSVC compilers do not support {eh} exception handling. ' + 'You may want to set eh to \'default\'.', fatal=False) + +class CPPCompiler(CLikeCompiler, Compiler): + def attribute_check_func(self, name: str) -> str: + try: + return CXX_FUNC_ATTRIBUTES.get(name, C_FUNC_ATTRIBUTES[name]) + except KeyError: + raise MesonException(f'Unknown function attribute "{name}"') + + language = 'cpp' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + # If a child ObjCPP class has already set it, don't set it ourselves + Compiler.__init__(self, ccache, exelist, version, for_machine, info, + is_cross=is_cross, linker=linker, + full_version=full_version) + CLikeCompiler.__init__(self, exe_wrapper) + + @staticmethod + def get_display_language() -> str: + return 'C++' + + def get_no_stdinc_args(self) -> T.List[str]: + return ['-nostdinc++'] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + code = 'class breakCCompiler;int main(void) { return 0; }\n' + return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # -fpermissive allows non-conforming code to compile which is necessary + # for many C++ checks. Particularly, the has_header_symbol check is + # too strict without this and always fails. + return super().get_compiler_check_args(mode) + ['-fpermissive'] + + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + # Check if it's a C-like symbol + found, cached = super().has_header_symbol(hname, symbol, prefix, env, + extra_args=extra_args, + dependencies=dependencies) + if found: + return True, cached + # Check if it's a class or a template + if extra_args is None: + extra_args = [] + t = f'''{prefix} + #include <{hname}> + using {symbol}; + int main(void) {{ return 0; }}''' + return self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies) + + def _test_cpp_std_arg(self, cpp_std_value: str) -> bool: + # Test whether the compiler understands a -std=XY argument + assert cpp_std_value.startswith('-std=') + + # This test does not use has_multi_arguments() for two reasons: + # 1. has_multi_arguments() requires an env argument, which the compiler + # object does not have at this point. + # 2. even if it did have an env object, that might contain another more + # recent -std= argument, which might lead to a cascaded failure. + CPP_TEST = 'int i = static_cast(0);' + with self.compile(CPP_TEST, extra_args=[cpp_std_value], mode='compile') as p: + if p.returncode == 0: + mlog.debug(f'Compiler accepts {cpp_std_value}:', 'YES') + return True + else: + mlog.debug(f'Compiler accepts {cpp_std_value}:', 'NO') + return False + + @functools.lru_cache() + def _find_best_cpp_std(self, cpp_std: str) -> str: + # The initial version mapping approach to make falling back + # from '-std=c++14' to '-std=c++1y' was too brittle. For instance, + # Apple's Clang uses a different versioning scheme to upstream LLVM, + # making the whole detection logic awfully brittle. Instead, let's + # just see if feeding GCC or Clang our '-std=' setting works, and + # if not, try the fallback argument. + CPP_FALLBACKS = { + 'c++11': 'c++0x', + 'gnu++11': 'gnu++0x', + 'c++14': 'c++1y', + 'gnu++14': 'gnu++1y', + 'c++17': 'c++1z', + 'gnu++17': 'gnu++1z', + 'c++20': 'c++2a', + 'gnu++20': 'gnu++2a', + } + + # Currently, remapping is only supported for Clang, Elbrus and GCC + assert self.id in frozenset(['clang', 'lcc', 'gcc', 'emscripten', 'armltdclang', 'intel-llvm']) + + if cpp_std not in CPP_FALLBACKS: + # 'c++03' and 'c++98' don't have fallback types + return '-std=' + cpp_std + + for i in (cpp_std, CPP_FALLBACKS[cpp_std]): + cpp_std_value = '-std=' + i + if self._test_cpp_std_arg(cpp_std_value): + return cpp_std_value + + raise MesonException(f'C++ Compiler does not support -std={cpp_std}') + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key: coredata.UserComboOption( + 'C++ language standard to use', + ['none'], + 'none', + ), + }) + return opts + + +class _StdCPPLibMixin(CompilerMixinBase): + + """Detect whether to use libc++ or libstdc++.""" + + @functools.lru_cache(None) + def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: + """Detect the C++ stdlib and default search dirs + + As an optimization, this method will cache the value, to avoid building the same values over and over + + :param env: An Environment object + :raises MesonException: If a stdlib cannot be determined + """ + + # We need to apply the search prefix here, as these link arguments may + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran. + search_dirs = [f'-L{d}' for d in self.get_compiler_dirs(env, 'libraries')] + + machine = env.machines[self.for_machine] + assert machine is not None, 'for mypy' + + # We need to determine whether to use libc++ or libstdc++. We can't + # really know the answer in most cases, only the most likely answer, + # because a user can install things themselves or build custom images. + search_order: T.List[str] = [] + if machine.system in {'android', 'darwin', 'dragonfly', 'freebsd', 'netbsd', 'openbsd'}: + search_order = ['c++', 'stdc++'] + else: + search_order = ['stdc++', 'c++'] + for lib in search_order: + if self.find_library(lib, env, []) is not None: + return search_dirs + [f'-l{lib}'] + # TODO: maybe a bug exception? + raise MesonException('Could not detect either libc++ or libstdc++ as your C++ stdlib implementation.') + + +class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ClangCompiler.__init__(self, defines) + default_warn_args = ['-Wall', '-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': ['-Weverything']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('key', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + }) + opts[key.evolve('std')].choices = [ + 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', + 'c++2a', 'c++20', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', + 'gnu++2a', 'gnu++20', + ] + if self.info.is_windows() or self.info.is_cygwin(): + opts.update({ + key.evolve('winlibs'): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append(self._find_best_cpp_std(std.value)) + + non_msvc_eh_options(options[key.evolve('eh')].value, args) + + if not options[key.evolve('rtti')].value: + args.append('-fno-rtti') + + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + if self.info.is_windows() or self.info.is_cygwin(): + # without a typedict mypy can't understand this. + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + libs = options[key].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs + return [] + + +class ArmLtdClangCPPCompiler(ClangCPPCompiler): + + id = 'armltdclang' + + +class AppleClangCPPCompiler(ClangCPPCompiler): + pass + + +class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): + + id = 'emscripten' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + if not is_cross: + raise MesonException('Emscripten compiler can only be used for cross compilation.') + if not version_compare(version, '>=1.39.19'): + raise MesonException('Meson requires Emscripten >= 1.39.19') + ClangCPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper=exe_wrapper, linker=linker, + defines=defines, full_version=full_version) + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append(self._find_best_cpp_std(std.value)) + return args + + +class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): + ''' + Keil armclang + ''' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ArmclangCompiler.__init__(self) + default_warn_args = ['-Wall', '-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': ['-Weverything']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + }) + opts[key].choices = [ + 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98', + 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', + ] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('-std=' + std.value) + + non_msvc_eh_options(options[key.evolve('eh')].value, args) + + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + +class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + GnuCompiler.__init__(self, defines) + default_warn_args = ['-Wall', '-Winvalid-pch'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': (default_warn_args + ['-Wextra', '-Wpedantic'] + + self.supported_warn_args(gnu_common_warning_args) + + self.supported_warn_args(gnu_cpp_warning_args))} + + def get_options(self) -> 'MutableKeyedOptionDictType': + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts = CPPCompiler.get_options(self) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + key.evolve('debugstl'): coredata.UserBooleanOption( + 'STL debug mode', + False, + ) + }) + cppstd_choices = [ + 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', + 'c++2a', 'c++20', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', + 'gnu++1z', 'gnu++2a', 'gnu++20', + ] + if version_compare(self.version, '>=12.2.0'): + cppstd_choices.append('c++23') + cppstd_choices.append('gnu++23') + opts[key].choices = cppstd_choices + if self.info.is_windows() or self.info.is_cygwin(): + opts.update({ + key.evolve('winlibs'): coredata.UserArrayOption( + 'Standard Win libraries to link against', + gnu_winlibs, + ), + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append(self._find_best_cpp_std(std.value)) + + non_msvc_eh_options(options[key.evolve('eh')].value, args) + + if not options[key.evolve('rtti')].value: + args.append('-fno-rtti') + + if options[key.evolve('debugstl')].value: + args.append('-D_GLIBCXX_DEBUG=1') + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + if self.info.is_windows() or self.info.is_cygwin(): + # without a typedict mypy can't understand this. + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + libs = options[key].value.copy() + assert isinstance(libs, list) + for l in libs: + assert isinstance(l, str) + return libs + return [] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return ['-fpch-preprocess', '-include', os.path.basename(header)] + + +class PGICPPCompiler(PGICompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + PGICompiler.__init__(self) + + +class NvidiaHPC_CPPCompiler(PGICompiler, CPPCompiler): + + id = 'nvidia_hpc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + PGICompiler.__init__(self) + + +class ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ElbrusCompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + + cpp_stds = ['none', 'c++98', 'gnu++98'] + if version_compare(self.version, '>=1.20.00'): + cpp_stds += ['c++03', 'c++0x', 'c++11', 'gnu++03', 'gnu++0x', 'gnu++11'] + if version_compare(self.version, '>=1.21.00') and version_compare(self.version, '<1.22.00'): + cpp_stds += ['c++14', 'gnu++14', 'c++1y', 'gnu++1y'] + if version_compare(self.version, '>=1.22.00'): + cpp_stds += ['c++14', 'gnu++14'] + if version_compare(self.version, '>=1.23.00'): + cpp_stds += ['c++1y', 'gnu++1y'] + if version_compare(self.version, '>=1.24.00'): + cpp_stds += ['c++1z', 'c++17', 'gnu++1z', 'gnu++17'] + if version_compare(self.version, '>=1.25.00'): + cpp_stds += ['c++2a', 'gnu++2a'] + if version_compare(self.version, '>=1.26.00'): + cpp_stds += ['c++20', 'gnu++20'] + + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('debugstl'): coredata.UserBooleanOption( + 'STL debug mode', + False, + ), + }) + opts[key].choices = cpp_stds + return opts + + # Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error. + # So we should explicitly fail at this case. + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + if funcname == 'lchmod': + return False, False + else: + return super().has_function(funcname, prefix, env, + extra_args=extra_args, + dependencies=dependencies) + + # Elbrus C++ compiler does not support RTTI, so don't check for it. + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append(self._find_best_cpp_std(std.value)) + + non_msvc_eh_options(options[key.evolve('eh')].value, args) + + if options[key.evolve('debugstl')].value: + args.append('-D_GLIBCXX_DEBUG=1') + return args + + +class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + IntelGnuLikeCompiler.__init__(self) + self.lang_header = 'c++-header' + default_warn_args = ['-Wall', '-w3', '-Wpch-messages'] + self.warn_args = {'0': [], + '1': default_warn_args + ['-diag-disable:remark'], + '2': default_warn_args + ['-Wextra', '-diag-disable:remark'], + '3': default_warn_args + ['-Wextra', '-diag-disable:remark'], + 'everything': default_warn_args + ['-Wextra']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + # Every Unix compiler under the sun seems to accept -std=c++03, + # with the exception of ICC. Instead of preventing the user from + # globally requesting C++03, we transparently remap it to C++98 + c_stds = ['c++98', 'c++03'] + g_stds = ['gnu++98', 'gnu++03'] + if version_compare(self.version, '>=15.0.0'): + c_stds += ['c++11', 'c++14'] + g_stds += ['gnu++11'] + if version_compare(self.version, '>=16.0.0'): + c_stds += ['c++17'] + if version_compare(self.version, '>=17.0.0'): + g_stds += ['gnu++14'] + if version_compare(self.version, '>=19.1.0'): + c_stds += ['c++2a'] + g_stds += ['gnu++2a'] + + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + key.evolve('debugstl'): coredata.UserBooleanOption('STL debug mode', False), + }) + opts[key].choices = ['none'] + c_stds + g_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + remap_cpp03 = { + 'c++03': 'c++98', + 'gnu++03': 'gnu++98' + } + args.append('-std=' + remap_cpp03.get(std.value, std.value)) + if options[key.evolve('eh')].value == 'none': + args.append('-fno-exceptions') + if not options[key.evolve('rtti')].value: + args.append('-fno-rtti') + if options[key.evolve('debugstl')].value: + args.append('-D_GLIBCXX_DEBUG=1') + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + +class IntelLLVMCPPCompiler(ClangCPPCompiler): + + id = 'intel-llvm' + + +class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase): + + """Mixin for C++ specific method overrides in MSVC-like compilers.""" + + VC_VERSION_MAP = { + 'none': (True, None), + 'vc++11': (True, 11), + 'vc++14': (True, 14), + 'vc++17': (True, 17), + 'vc++20': (True, 20), + 'vc++latest': (True, "latest"), + 'c++11': (False, 11), + 'c++14': (False, 14), + 'c++17': (False, 17), + 'c++20': (False, 20), + 'c++latest': (False, "latest"), + } + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + # need a typeddict for this + key = OptionKey('winlibs', machine=self.for_machine, lang=self.language) + return T.cast('T.List[str]', options[key].value[:]) + + def _get_options_impl(self, opts: 'MutableKeyedOptionDictType', cpp_stds: T.List[str]) -> 'MutableKeyedOptionDictType': + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key.evolve('eh'): coredata.UserComboOption( + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default', + ), + key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), + key.evolve('winlibs'): coredata.UserArrayOption( + 'Windows libs to link against.', + msvc_winlibs, + ), + }) + opts[key.evolve('std')].choices = cpp_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + + eh = options[key.evolve('eh')] + if eh.value == 'default': + args.append('/EHsc') + elif eh.value == 'none': + args.append('/EHs-c-') + else: + args.append('/EH' + eh.value) + + if not options[key.evolve('rtti')].value: + args.append('/GR-') + + permissive, ver = self.VC_VERSION_MAP[options[key].value] + + if ver is not None: + args.append(f'/std:c++{ver}') + + if not permissive: + args.append('/permissive-') + + return args + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class. + return Compiler.get_compiler_check_args(self, mode) + + +class CPP11AsCPP14Mixin(CompilerMixinBase): + + """Mixin class for VisualStudio and ClangCl to replace C++11 std with C++14. + + This is a limitation of Clang and MSVC that ICL doesn't share. + """ + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + # Note: there is no explicit flag for supporting C++11; we attempt to do the best we can + # which means setting the C++ standard version to C++14, in compilers that support it + # (i.e., after VS2015U3) + # if one is using anything before that point, one cannot set the standard. + key = OptionKey('std', machine=self.for_machine, lang=self.language) + if options[key].value in {'vc++11', 'c++11'}: + mlog.warning(self.id, 'does not support C++11;', + 'attempting best effort; setting the standard to C++14', + once=True, fatal=False) + # Don't mutate anything we're going to change, we need to use + # deepcopy since we're messing with members, and we can't simply + # copy the members because the option proxy doesn't support it. + options = copy.deepcopy(options) + if options[key].value == 'vc++11': + options[key].value = 'vc++14' + else: + options[key].value = 'c++14' + return super().get_option_compile_args(options) + + +class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, MSVCCompiler, CPPCompiler): + + id = 'msvc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MSVCCompiler.__init__(self, target) + + # By default, MSVC has a broken __cplusplus define that pretends to be c++98: + # https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-160 + # Pass the flag to enable a truthful define, if possible. + if version_compare(self.version, '>= 19.14.26428'): + self.always_args = self.always_args + ['/Zc:__cplusplus'] + + def get_options(self) -> 'MutableKeyedOptionDictType': + cpp_stds = ['none', 'c++11', 'vc++11'] + # Visual Studio 2015 and later + if version_compare(self.version, '>=19'): + cpp_stds.extend(['c++14', 'c++latest', 'vc++latest']) + # Visual Studio 2017 and later + if version_compare(self.version, '>=19.11'): + cpp_stds.extend(['vc++14', 'c++17', 'vc++17']) + if version_compare(self.version, '>=19.29'): + cpp_stds.extend(['c++20', 'vc++20']) + return self._get_options_impl(super().get_options(), cpp_stds) + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + key = OptionKey('std', machine=self.for_machine, lang=self.language) + if options[key].value != 'none' and version_compare(self.version, '<19.00.24210'): + mlog.warning('This version of MSVC does not support cpp_std arguments', fatal=False) + options = copy.copy(options) + options[key].value = 'none' + + args = super().get_option_compile_args(options) + + if version_compare(self.version, '<19.11'): + try: + i = args.index('/permissive-') + except ValueError: + return args + del args[i] + return args + +class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, ClangClCompiler, CPPCompiler): + + id = 'clang-cl' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, [], exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ClangClCompiler.__init__(self, target) + + def get_options(self) -> 'MutableKeyedOptionDictType': + cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++20', 'vc++20', 'c++latest'] + return self._get_options_impl(super().get_options(), cpp_stds) + + +class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, [], exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + IntelVisualStudioLikeCompiler.__init__(self, target) + + def get_options(self) -> 'MutableKeyedOptionDictType': + # This has only been tested with version 19.0, + cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest'] + return self._get_options_impl(super().get_options(), cpp_stds) + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class. + return IntelVisualStudioLikeCompiler.get_compiler_check_args(self, mode) + + +class IntelLLVMClCPPCompiler(IntelClCPPCompiler): + + id = 'intel-llvm-cl' + + +class ArmCPPCompiler(ArmCompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ArmCompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c++03', 'c++11'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value == 'c++11': + args.append('--cpp11') + elif std.value == 'c++03': + args.append('--cpp') + return args + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + return [] + + +class CcrxCPPCompiler(CcrxCompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + CcrxCompiler.__init__(self) + + # Override CCompiler.get_always_args + def get_always_args(self) -> T.List[str]: + return ['-nologo', '-lang=cpp'] + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def get_compile_only_args(self) -> T.List[str]: + return [] + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-output=obj={target}'] + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + return [] + +class TICPPCompiler(TICompiler, CPPCompiler): + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + TICompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'c++03'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('--' + std.value) + return args + + def get_always_args(self) -> T.List[str]: + return [] + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + +class C2000CPPCompiler(TICPPCompiler): + # Required for backwards compat with projects created before ti-cgt support existed + id = 'c2000' + +class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler): + id = 'mwccarm' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwccarm_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang') + args.append(std.value) + return args + +class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler): + id = 'mwcceppc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwcceppc_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang ' + std.value) + return args diff --git a/devtools/meson/mesonbuild/compilers/cs.py b/devtools/meson/mesonbuild/compilers/cs.py new file mode 100644 index 0000000..f0bed5f --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/cs.py @@ -0,0 +1,154 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os.path, subprocess +import textwrap +import typing as T + +from ..mesonlib import EnvironmentException +from ..linkers import RSPFileSyntax + +from .compilers import Compiler, mono_buildtype_args +from .mixins.islinker import BasicLinkerIsCompilerMixin + +if T.TYPE_CHECKING: + from ..envconfig import MachineInfo + from ..environment import Environment + from ..mesonlib import MachineChoice + +cs_optimization_args = { + 'plain': [], + '0': [], + 'g': [], + '1': ['-optimize+'], + '2': ['-optimize+'], + '3': ['-optimize+'], + 's': ['-optimize+'], + } # type: T.Dict[str, T.List[str]] + + +class CsCompiler(BasicLinkerIsCompilerMixin, Compiler): + + language = 'cs' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', runner: T.Optional[str] = None): + super().__init__([], exelist, version, for_machine, info) + self.runner = runner + + @classmethod + def get_display_language(cls) -> str: + return 'C sharp' + + def get_always_args(self) -> T.List[str]: + return ['/nologo'] + + def get_linker_always_args(self) -> T.List[str]: + return ['/nologo'] + + def get_output_args(self, fname: str) -> T.List[str]: + return ['-out:' + fname] + + def get_link_args(self, fname: str) -> T.List[str]: + return ['-r:' + fname] + + def get_werror_args(self) -> T.List[str]: + return ['-warnaserror'] + + def get_pic_args(self) -> T.List[str]: + return [] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-L': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + if i[:5] == '-lib:': + parameter_list[idx] = i[:5] + os.path.normpath(os.path.join(build_dir, i[5:])) + + return parameter_list + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return [] + + def get_pch_name(self, header_name: str) -> str: + return '' + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + src = 'sanity.cs' + obj = 'sanity.exe' + source_name = os.path.join(work_dir, src) + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent(''' + public class Sanity { + static public void Main () { + } + } + ''')) + pc = subprocess.Popen(self.exelist + self.get_always_args() + [src], cwd=work_dir) + pc.wait() + if pc.returncode != 0: + raise EnvironmentException('C# compiler %s cannot compile programs.' % self.name_string()) + if self.runner: + cmdlist = [self.runner, obj] + else: + cmdlist = [os.path.join(work_dir, obj)] + pe = subprocess.Popen(cmdlist, cwd=work_dir) + pe.wait() + if pe.returncode != 0: + raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string()) + + def needs_static_linker(self) -> bool: + return False + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return mono_buildtype_args[buildtype] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return ['-debug'] if is_debug else [] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return cs_optimization_args[optimization_level] + + +class MonoCompiler(CsCompiler): + + id = 'mono' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo'): + super().__init__(exelist, version, for_machine, info, runner='mono') + + def rsp_file_syntax(self) -> 'RSPFileSyntax': + return RSPFileSyntax.GCC + + +class VisualStudioCsCompiler(CsCompiler): + + id = 'csc' + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + res = mono_buildtype_args[buildtype] + if not self.info.is_windows(): + tmp = [] + for flag in res: + if flag == '-debug': + flag = '-debug:portable' + tmp.append(flag) + res = tmp + return res + + def rsp_file_syntax(self) -> 'RSPFileSyntax': + return RSPFileSyntax.MSVC diff --git a/devtools/meson/mesonbuild/compilers/cuda.py b/devtools/meson/mesonbuild/compilers/cuda.py new file mode 100644 index 0000000..8ed7fa4 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/cuda.py @@ -0,0 +1,791 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import enum +import os.path +import string +import typing as T + +from .. import coredata +from .. import mlog +from ..mesonlib import ( + EnvironmentException, Popen_safe, OptionOverrideProxy, + is_windows, LibType, OptionKey, version_compare, +) +from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, + cuda_debug_args) + +if T.TYPE_CHECKING: + from .compilers import CompileCheckMode + from ..build import BuildTarget + from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType + from ..dependencies import Dependency + from ..environment import Environment # noqa: F401 + from ..envconfig import MachineInfo + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..programs import ExternalProgram + + +class _Phase(enum.Enum): + + COMPILER = 'compiler' + LINKER = 'linker' + + +class CudaCompiler(Compiler): + + LINKER_PREFIX = '-Xlinker=' + language = 'cuda' + + # NVCC flags taking no arguments. + _FLAG_PASSTHRU_NOARGS = { + # NVCC --long-option, NVCC -short-option CUDA Toolkit 11.2.1 Reference + '--objdir-as-tempdir', '-objtemp', # 4.2.1.2 + '--generate-dependency-targets', '-MP', # 4.2.1.12 + '--allow-unsupported-compiler', '-allow-unsupported-compiler', # 4.2.1.14 + '--link', # 4.2.2.1 + '--lib', '-lib', # 4.2.2.2 + '--device-link', '-dlink', # 4.2.2.3 + '--device-c', '-dc', # 4.2.2.4 + '--device-w', '-dw', # 4.2.2.5 + '--cuda', '-cuda', # 4.2.2.6 + '--compile', '-c', # 4.2.2.7 + '--fatbin', '-fatbin', # 4.2.2.8 + '--cubin', '-cubin', # 4.2.2.9 + '--ptx', '-ptx', # 4.2.2.10 + '--preprocess', '-E', # 4.2.2.11 + '--generate-dependencies', '-M', # 4.2.2.12 + '--generate-nonsystem-dependencies', '-MM', # 4.2.2.13 + '--generate-dependencies-with-compile', '-MD', # 4.2.2.14 + '--generate-nonsystem-dependencies-with-compile', '-MMD', # 4.2.2.15 + '--run', # 4.2.2.16 + '--profile', '-pg', # 4.2.3.1 + '--debug', '-g', # 4.2.3.2 + '--device-debug', '-G', # 4.2.3.3 + '--extensible-whole-program', '-ewp', # 4.2.3.4 + '--generate-line-info', '-lineinfo', # 4.2.3.5 + '--dlink-time-opt', '-dlto', # 4.2.3.8 + '--no-exceptions', '-noeh', # 4.2.3.11 + '--shared', '-shared', # 4.2.3.12 + '--no-host-device-initializer-list', '-nohdinitlist', # 4.2.3.15 + '--expt-relaxed-constexpr', '-expt-relaxed-constexpr', # 4.2.3.16 + '--extended-lambda', '-extended-lambda', # 4.2.3.17 + '--expt-extended-lambda', '-expt-extended-lambda', # 4.2.3.18 + '--m32', '-m32', # 4.2.3.20 + '--m64', '-m64', # 4.2.3.21 + '--forward-unknown-to-host-compiler', '-forward-unknown-to-host-compiler', # 4.2.5.1 + '--forward-unknown-to-host-linker', '-forward-unknown-to-host-linker', # 4.2.5.2 + '--dont-use-profile', '-noprof', # 4.2.5.3 + '--dryrun', '-dryrun', # 4.2.5.5 + '--verbose', '-v', # 4.2.5.6 + '--keep', '-keep', # 4.2.5.7 + '--save-temps', '-save-temps', # 4.2.5.9 + '--clean-targets', '-clean', # 4.2.5.10 + '--no-align-double', # 4.2.5.16 + '--no-device-link', '-nodlink', # 4.2.5.17 + '--allow-unsupported-compiler', '-allow-unsupported-compiler', # 4.2.5.18 + '--use_fast_math', '-use_fast_math', # 4.2.7.7 + '--extra-device-vectorization', '-extra-device-vectorization', # 4.2.7.12 + '--compile-as-tools-patch', '-astoolspatch', # 4.2.7.13 + '--keep-device-functions', '-keep-device-functions', # 4.2.7.14 + '--disable-warnings', '-w', # 4.2.8.1 + '--source-in-ptx', '-src-in-ptx', # 4.2.8.2 + '--restrict', '-restrict', # 4.2.8.3 + '--Wno-deprecated-gpu-targets', '-Wno-deprecated-gpu-targets', # 4.2.8.4 + '--Wno-deprecated-declarations', '-Wno-deprecated-declarations', # 4.2.8.5 + '--Wreorder', '-Wreorder', # 4.2.8.6 + '--Wdefault-stream-launch', '-Wdefault-stream-launch', # 4.2.8.7 + '--Wext-lambda-captures-this', '-Wext-lambda-captures-this', # 4.2.8.8 + '--display-error-number', '-err-no', # 4.2.8.10 + '--resource-usage', '-res-usage', # 4.2.8.14 + '--help', '-h', # 4.2.8.15 + '--version', '-V', # 4.2.8.16 + '--list-gpu-code', '-code-ls', # 4.2.8.20 + '--list-gpu-arch', '-arch-ls', # 4.2.8.21 + } + # Dictionary of NVCC flags taking either one argument or a comma-separated list. + # Maps --long to -short options, because the short options are more GCC-like. + _FLAG_LONG2SHORT_WITHARGS = { + '--output-file': '-o', # 4.2.1.1 + '--pre-include': '-include', # 4.2.1.3 + '--library': '-l', # 4.2.1.4 + '--define-macro': '-D', # 4.2.1.5 + '--undefine-macro': '-U', # 4.2.1.6 + '--include-path': '-I', # 4.2.1.7 + '--system-include': '-isystem', # 4.2.1.8 + '--library-path': '-L', # 4.2.1.9 + '--output-directory': '-odir', # 4.2.1.10 + '--dependency-output': '-MF', # 4.2.1.11 + '--compiler-bindir': '-ccbin', # 4.2.1.13 + '--archiver-binary': '-arbin', # 4.2.1.15 + '--cudart': '-cudart', # 4.2.1.16 + '--cudadevrt': '-cudadevrt', # 4.2.1.17 + '--libdevice-directory': '-ldir', # 4.2.1.18 + '--target-directory': '-target-dir', # 4.2.1.19 + '--optimization-info': '-opt-info', # 4.2.3.6 + '--optimize': '-O', # 4.2.3.7 + '--ftemplate-backtrace-limit': '-ftemplate-backtrace-limit', # 4.2.3.9 + '--ftemplate-depth': '-ftemplate-depth', # 4.2.3.10 + '--x': '-x', # 4.2.3.13 + '--std': '-std', # 4.2.3.14 + '--machine': '-m', # 4.2.3.19 + '--compiler-options': '-Xcompiler', # 4.2.4.1 + '--linker-options': '-Xlinker', # 4.2.4.2 + '--archive-options': '-Xarchive', # 4.2.4.3 + '--ptxas-options': '-Xptxas', # 4.2.4.4 + '--nvlink-options': '-Xnvlink', # 4.2.4.5 + '--threads': '-t', # 4.2.5.4 + '--keep-dir': '-keep-dir', # 4.2.5.8 + '--run-args': '-run-args', # 4.2.5.11 + '--input-drive-prefix': '-idp', # 4.2.5.12 + '--dependency-drive-prefix': '-ddp', # 4.2.5.13 + '--drive-prefix': '-dp', # 4.2.5.14 + '--dependency-target-name': '-MT', # 4.2.5.15 + '--default-stream': '-default-stream', # 4.2.6.1 + '--gpu-architecture': '-arch', # 4.2.7.1 + '--gpu-code': '-code', # 4.2.7.2 + '--generate-code': '-gencode', # 4.2.7.3 + '--relocatable-device-code': '-rdc', # 4.2.7.4 + '--entries': '-e', # 4.2.7.5 + '--maxrregcount': '-maxrregcount', # 4.2.7.6 + '--ftz': '-ftz', # 4.2.7.8 + '--prec-div': '-prec-div', # 4.2.7.9 + '--prec-sqrt': '-prec-sqrt', # 4.2.7.10 + '--fmad': '-fmad', # 4.2.7.11 + '--Werror': '-Werror', # 4.2.8.9 + '--diag-error': '-diag-error', # 4.2.8.11 + '--diag-suppress': '-diag-suppress', # 4.2.8.12 + '--diag-warn': '-diag-warn', # 4.2.8.13 + '--options-file': '-optf', # 4.2.8.17 + '--time': '-time', # 4.2.8.18 + '--qpp-config': '-qpp-config', # 4.2.8.19 + } + # Reverse map -short to --long options. + _FLAG_SHORT2LONG_WITHARGS = {v: k for k, v in _FLAG_LONG2SHORT_WITHARGS.items()} + + id = 'nvcc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, exe_wrapper: T.Optional['ExternalProgram'], + host_compiler: Compiler, info: 'MachineInfo', + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + super().__init__(ccache, exelist, version, for_machine, info, linker=linker, full_version=full_version, is_cross=is_cross) + self.exe_wrapper = exe_wrapper + self.host_compiler = host_compiler + self.base_options = host_compiler.base_options + self.warn_args = {level: self._to_host_flags(flags) for level, flags in host_compiler.warn_args.items()} + + @classmethod + def _shield_nvcc_list_arg(cls, arg: str, listmode: bool = True) -> str: + r""" + Shield an argument against both splitting by NVCC's list-argument + parse logic, and interpretation by any shell. + + NVCC seems to consider every comma , that is neither escaped by \ nor inside + a double-quoted string a split-point. Single-quotes do not provide protection + against splitting; In fact, after splitting they are \-escaped. Unfortunately, + double-quotes don't protect against shell expansion. What follows is a + complex dance to accommodate everybody. + """ + + SQ = "'" + DQ = '"' + CM = "," + BS = "\\" + DQSQ = DQ+SQ+DQ + quotable = set(string.whitespace+'"$`\\') + + if CM not in arg or not listmode: + if SQ not in arg: + # If any of the special characters "$`\ or whitespace are present, single-quote. + # Otherwise return bare. + if set(arg).intersection(quotable): + return SQ+arg+SQ + else: + return arg # Easy case: no splits, no quoting. + else: + # There are single quotes. Double-quote them, and single-quote the + # strings between them. + l = [cls._shield_nvcc_list_arg(s) for s in arg.split(SQ)] + l = sum([[s, DQSQ] for s in l][:-1], []) # Interleave l with DQSQs + return ''.join(l) + else: + # A comma is present, and list mode was active. + # We apply (what we guess is) the (primitive) NVCC splitting rule: + l = [''] + instring = False + argit = iter(arg) + for c in argit: + if c == CM and not instring: + l.append('') + elif c == DQ: + l[-1] += c + instring = not instring + elif c == BS: + try: + l[-1] += next(argit) + except StopIteration: + break + else: + l[-1] += c + + # Shield individual strings, without listmode, then return them with + # escaped commas between them. + l = [cls._shield_nvcc_list_arg(s, listmode=False) for s in l] + return r'\,'.join(l) + + @classmethod + def _merge_flags(cls, flags: T.List[str]) -> T.List[str]: + r""" + The flags to NVCC gets exceedingly verbose and unreadable when too many of them + are shielded with -Xcompiler. Merge consecutive -Xcompiler-wrapped arguments + into one. + """ + if len(flags) <= 1: + return flags + flagit = iter(flags) + xflags = [] + + def is_xcompiler_flag_isolated(flag: str) -> bool: + return flag == '-Xcompiler' + + def is_xcompiler_flag_glued(flag: str) -> bool: + return flag.startswith('-Xcompiler=') + + def is_xcompiler_flag(flag: str) -> bool: + return is_xcompiler_flag_isolated(flag) or is_xcompiler_flag_glued(flag) + + def get_xcompiler_val(flag: str, flagit: T.Iterator[str]) -> str: + if is_xcompiler_flag_glued(flag): + return flag[len('-Xcompiler='):] + else: + try: + return next(flagit) + except StopIteration: + return "" + + ingroup = False + for flag in flagit: + if not is_xcompiler_flag(flag): + ingroup = False + xflags.append(flag) + elif ingroup: + xflags[-1] += ',' + xflags[-1] += get_xcompiler_val(flag, flagit) + elif is_xcompiler_flag_isolated(flag): + ingroup = True + xflags.append(flag) + xflags.append(get_xcompiler_val(flag, flagit)) + elif is_xcompiler_flag_glued(flag): + ingroup = True + xflags.append(flag) + else: + raise ValueError("-Xcompiler flag merging failed, unknown argument form!") + return xflags + + def _to_host_flags(self, flags: T.List[str], phase: _Phase = _Phase.COMPILER) -> T.List[str]: + """ + Translate generic "GCC-speak" plus particular "NVCC-speak" flags to NVCC flags. + + NVCC's "short" flags have broad similarities to the GCC standard, but have + gratuitous, irritating differences. + """ + + xflags = [] + flagit = iter(flags) + + for flag in flagit: + # The CUDA Toolkit Documentation, in 4.1. Command Option Types and Notation, + # specifies that NVCC does not parse the standard flags as GCC does. It has + # its own strategy, to wit: + # + # nvcc recognizes three types of command options: boolean options, single + # value options, and list options. + # + # Boolean options do not have an argument; they are either specified on a + # command line or not. Single value options must be specified at most once, + # and list options may be repeated. Examples of each of these option types + # are, respectively: --verbose (switch to verbose mode), --output-file + # (specify output file), and --include-path (specify include path). + # + # Single value options and list options must have arguments, which must + # follow the name of the option itself by either one of more spaces or an + # equals character. When a one-character short name such as -I, -l, and -L + # is used, the value of the option may also immediately follow the option + # itself without being separated by spaces or an equal character. The + # individual values of list options may be separated by commas in a single + # instance of the option, or the option may be repeated, or any + # combination of these two cases. + # + # One strange consequence of this choice is that directory and filenames that + # contain commas (',') cannot be passed to NVCC (at least, not as easily as + # in GCC). Another strange consequence is that it is legal to supply flags + # such as + # + # -lpthread,rt,dl,util + # -l pthread,rt,dl,util + # -l=pthread,rt,dl,util + # + # and each of the above alternatives is equivalent to GCC-speak + # + # -lpthread -lrt -ldl -lutil + # -l pthread -l rt -l dl -l util + # -l=pthread -l=rt -l=dl -l=util + # + # *With the exception of commas in the name*, GCC-speak for these list flags + # is a strict subset of NVCC-speak, so we passthrough those flags. + # + # The -D macro-define flag is documented as somehow shielding commas from + # splitting a definition. Balanced parentheses, braces and single-quotes + # around the comma are not sufficient, but balanced double-quotes are. The + # shielding appears to work with -l, -I, -L flags as well, for instance. + # + # Since our goal is to replicate GCC-speak as much as possible, we check for + # commas in all list-arguments and shield them with double-quotes. We make + # an exception for -D (where this would be value-changing) and -U (because + # it isn't possible to define a macro with a comma in the name). + + if flag in self._FLAG_PASSTHRU_NOARGS: + xflags.append(flag) + continue + + # Handle breakup of flag-values into a flag-part and value-part. + if flag[:1] not in '-/': + # This is not a flag. It's probably a file input. Pass it through. + xflags.append(flag) + continue + elif flag[:1] == '/': + # This is ambiguously either an MVSC-style /switch or an absolute path + # to a file. For some magical reason the following works acceptably in + # both cases. + wrap = '"' if ',' in flag else '' + xflags.append(f'-X{phase.value}={wrap}{flag}{wrap}') + continue + elif len(flag) >= 2 and flag[0] == '-' and flag[1] in 'IDULlmOxmte': + # This is a single-letter short option. These options (with the + # exception of -o) are allowed to receive their argument with neither + # space nor = sign before them. Detect and separate them in that event. + if flag[2:3] == '': # -I something + try: + val = next(flagit) + except StopIteration: + pass + elif flag[2:3] == '=': # -I=something + val = flag[3:] + else: # -Isomething + val = flag[2:] + flag = flag[:2] # -I + elif flag in self._FLAG_LONG2SHORT_WITHARGS or \ + flag in self._FLAG_SHORT2LONG_WITHARGS: + # This is either -o or a multi-letter flag, and it is receiving its + # value isolated. + try: + val = next(flagit) # -o something + except StopIteration: + pass + elif flag.split('=', 1)[0] in self._FLAG_LONG2SHORT_WITHARGS or \ + flag.split('=', 1)[0] in self._FLAG_SHORT2LONG_WITHARGS: + # This is either -o or a multi-letter flag, and it is receiving its + # value after an = sign. + flag, val = flag.split('=', 1) # -o=something + # Some dependencies (e.g., BoostDependency) add unspaced "-isystem/usr/include" arguments + elif flag.startswith('-isystem'): + val = flag[8:].strip() + flag = flag[:8] + else: + # This is a flag, and it's foreign to NVCC. + # + # We do not know whether this GCC-speak flag takes an isolated + # argument. Assuming it does not (the vast majority indeed don't), + # wrap this argument in an -Xcompiler flag and send it down to NVCC. + if flag == '-ffast-math': + xflags.append('-use_fast_math') + xflags.append('-Xcompiler='+flag) + elif flag == '-fno-fast-math': + xflags.append('-ftz=false') + xflags.append('-prec-div=true') + xflags.append('-prec-sqrt=true') + xflags.append('-Xcompiler='+flag) + elif flag == '-freciprocal-math': + xflags.append('-prec-div=false') + xflags.append('-Xcompiler='+flag) + elif flag == '-fno-reciprocal-math': + xflags.append('-prec-div=true') + xflags.append('-Xcompiler='+flag) + else: + xflags.append('-Xcompiler='+self._shield_nvcc_list_arg(flag)) + # The above should securely handle GCC's -Wl, -Wa, -Wp, arguments. + continue + + assert val is not None # Should only trip if there is a missing argument. + + # Take care of the various NVCC-supported flags that need special handling. + flag = self._FLAG_LONG2SHORT_WITHARGS.get(flag, flag) + + if flag in {'-include', '-isystem', '-I', '-L', '-l'}: + # These flags are known to GCC, but list-valued in NVCC. They potentially + # require double-quoting to prevent NVCC interpreting the flags as lists + # when GCC would not have done so. + # + # We avoid doing this quoting for -D to avoid redefining macros and for + # -U because it isn't possible to define a macro with a comma in the name. + # -U with comma arguments is impossible in GCC-speak (and thus unambiguous + #in NVCC-speak, albeit unportable). + if len(flag) == 2: + xflags.append(flag+self._shield_nvcc_list_arg(val)) + elif flag == '-isystem' and val in self.host_compiler.get_default_include_dirs(): + # like GnuLikeCompiler, we have to filter out include directories specified + # with -isystem that overlap with the host compiler's search path + pass + else: + xflags.append(flag) + xflags.append(self._shield_nvcc_list_arg(val)) + elif flag == '-O': + # Handle optimization levels GCC knows about that NVCC does not. + if val == 'fast': + xflags.append('-O3') + xflags.append('-use_fast_math') + xflags.append('-Xcompiler') + xflags.append(flag+val) + elif val in {'s', 'g', 'z'}: + xflags.append('-Xcompiler') + xflags.append(flag+val) + else: + xflags.append(flag+val) + elif flag in {'-D', '-U', '-m', '-t'}: + xflags.append(flag+val) # For style, keep glued. + elif flag in {'-std'}: + xflags.append(flag+'='+val) # For style, keep glued. + else: + xflags.append(flag) + xflags.append(val) + + return self._merge_flags(xflags) + + def needs_static_linker(self) -> bool: + return False + + def thread_link_flags(self, environment: 'Environment') -> T.List[str]: + return self._to_host_flags(self.host_compiler.thread_link_flags(environment), _Phase.LINKER) + + def sanity_check(self, work_dir: str, env: 'Environment') -> None: + mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist)) + mlog.debug('Is cross compiler: %s.' % str(self.is_cross)) + + sname = 'sanitycheckcuda.cu' + code = r''' + #include + #include + + __global__ void kernel (void) {} + + int main(void){ + struct cudaDeviceProp prop; + int count, i; + cudaError_t ret = cudaGetDeviceCount(&count); + if(ret != cudaSuccess){ + fprintf(stderr, "%d\n", (int)ret); + }else{ + for(i=0;i T.Tuple[bool, bool]: + if extra_args is None: + extra_args = [] + fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} + # Check if it's a C-like symbol + t = '''{prefix} + #include <{header}> + int main(void) {{ + /* If it's not defined as a macro, try to use as a symbol */ + #ifndef {symbol} + {symbol}; + #endif + return 0; + }}''' + found, cached = self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies) + if found: + return True, cached + # Check if it's a class or a template + t = '''{prefix} + #include <{header}> + using {symbol}; + int main(void) {{ + return 0; + }}''' + return self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies) + + _CPP14_VERSION = '>=9.0' + _CPP17_VERSION = '>=11.0' + _CPP20_VERSION = '>=12.0' + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + std_key = OptionKey('std', machine=self.for_machine, lang=self.language) + ccbindir_key = OptionKey('ccbindir', machine=self.for_machine, lang=self.language) + + cpp_stds = ['none', 'c++03', 'c++11'] + if version_compare(self.version, self._CPP14_VERSION): + cpp_stds += ['c++14'] + if version_compare(self.version, self._CPP17_VERSION): + cpp_stds += ['c++17'] + if version_compare(self.version, self._CPP20_VERSION): + cpp_stds += ['c++20'] + + opts.update({ + std_key: coredata.UserComboOption('C++ language standard to use with CUDA', + cpp_stds, 'none'), + ccbindir_key: coredata.UserStringOption('CUDA non-default toolchain directory to use (-ccbin)', + ''), + }) + return opts + + def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOptionDictType': + """ + Convert an NVCC Option set to a host compiler's option set. + """ + + # We must strip the -std option from the host compiler option set, as NVCC has + # its own -std flag that may not agree with the host compiler's. + host_options = {key: options.get(key, opt) for key, opt in self.host_compiler.get_options().items()} + std_key = OptionKey('std', machine=self.for_machine, lang=self.host_compiler.language) + overrides = {std_key: 'none'} + return OptionOverrideProxy(overrides, host_options) + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = self.get_ccbin_args(options) + # On Windows, the version of the C++ standard used by nvcc is dictated by + # the combination of CUDA version and MSVC version; the --std= is thus ignored + # and attempting to use it will result in a warning: https://stackoverflow.com/a/51272091/741027 + if not is_windows(): + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('--std=' + std.value) + + return args + self._to_host_flags(self.host_compiler.get_option_compile_args(self._to_host_compiler_options(options))) + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = self.get_ccbin_args(options) + return args + self._to_host_flags(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)), _Phase.LINKER) + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, + darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_soname_args( + env, prefix, shlib_name, suffix, soversion, darwin_versions), _Phase.LINKER) + + def get_compile_only_args(self) -> T.List[str]: + return ['-c'] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-O0'] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + # alternatively, consider simply redirecting this to the host compiler, which would + # give us more control over options like "optimize for space" (which nvcc doesn't support): + # return self._to_host_flags(self.host_compiler.get_optimization_args(optimization_level)) + return cuda_optimization_args[optimization_level] + + def sanitizer_compile_args(self, value: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.sanitizer_compile_args(value)) + + def sanitizer_link_args(self, value: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.sanitizer_link_args(value)) + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return cuda_debug_args[is_debug] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror=cross-execution-space-call,deprecated-declarations,reorder'] + + def get_warn_args(self, level: str) -> T.List[str]: + return self.warn_args[level] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # nvcc doesn't support msvc's "Edit and Continue" PDB format; "downgrade" to + # a regular PDB to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi') + host_args = ['/Zi' if arg == '/ZI' else arg for arg in self.host_compiler.get_buildtype_args(buildtype)] + return cuda_buildtype_args[buildtype] + self._to_host_flags(host_args) + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + return ['-isystem=' + path] if is_system else ['-I' + path] + + def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_compile_debugfile_args(rel_obj, pch)) + + def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_link_debugfile_args(targetfile), _Phase.LINKER) + + def get_depfile_suffix(self) -> str: + return 'd' + + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_buildtype_linker_args(buildtype), _Phase.LINKER) + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + (rpath_args, rpath_dirs_to_remove) = self.host_compiler.build_rpath_args( + env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + return (self._to_host_flags(rpath_args, _Phase.LINKER), rpath_dirs_to_remove) + + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + return args + + def get_pic_args(self) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_pic_args()) + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + return [] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def get_std_exe_link_args(self) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_std_exe_link_args(), _Phase.LINKER) + + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: + return ['-l' + libname] # FIXME + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_crt_compile_args(crt_val, buildtype)) + + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + # nvcc defaults to static, release version of msvc runtime and provides no + # native option to override it; override it with /NODEFAULTLIB + host_link_arg_overrides = [] + host_crt_compile_args = self.host_compiler.get_crt_compile_args(crt_val, buildtype) + if any(arg in {'/MDd', '/MD', '/MTd'} for arg in host_crt_compile_args): + host_link_arg_overrides += ['/NODEFAULTLIB:LIBCMT.lib'] + return self._to_host_flags(host_link_arg_overrides + self.host_compiler.get_crt_link_args(crt_val, buildtype), _Phase.LINKER) + + def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]: + return self._to_host_flags(super().get_target_link_args(target), _Phase.LINKER) + + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: + return self._to_host_flags(super().get_dependency_compile_args(dep)) + + def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]: + return self._to_host_flags(super().get_dependency_link_args(dep), _Phase.LINKER) + + def get_ccbin_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + key = OptionKey('ccbindir', machine=self.for_machine, lang=self.language) + ccbindir = options[key].value + if isinstance(ccbindir, str) and ccbindir != '': + return [self._shield_nvcc_list_arg('-ccbin='+ccbindir, False)] + else: + return [] + + def get_profile_generate_args(self) -> T.List[str]: + return ['-Xcompiler=' + x for x in self.host_compiler.get_profile_generate_args()] + + def get_profile_use_args(self) -> T.List[str]: + return ['-Xcompiler=' + x for x in self.host_compiler.get_profile_use_args()] + + def get_assert_args(self, disable: bool) -> T.List[str]: + return self.host_compiler.get_assert_args(disable) diff --git a/devtools/meson/mesonbuild/compilers/cython.py b/devtools/meson/mesonbuild/compilers/cython.py new file mode 100644 index 0000000..9bbfebe --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/cython.py @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation +from __future__ import annotations + +"""Abstraction for Cython language compilers.""" + +import typing as T + +from .. import coredata +from ..mesonlib import EnvironmentException, OptionKey, version_compare +from .compilers import Compiler + +if T.TYPE_CHECKING: + from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType + from ..environment import Environment + + +class CythonCompiler(Compiler): + + """Cython Compiler.""" + + language = 'cython' + id = 'cython' + + def needs_static_linker(self) -> bool: + # We transpile into C, so we don't need any linker + return False + + def get_always_args(self) -> T.List[str]: + return ['--fast-fail'] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-o', outputname] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + # Cython doesn't have optimization levels itself, the underlying + # compiler might though + return [] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + if version_compare(self.version, '>=0.29.33'): + return ['-M'] + return [] + + def get_depfile_suffix(self) -> str: + return 'dep' + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + code = 'print("hello world")' + with self.cached_compile(code, environment.coredata) as p: + if p.returncode != 0: + raise EnvironmentException(f'Cython compiler {self.id!r} cannot compile programs') + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # Cython doesn't implement this, but Meson requires an implementation + return [] + + def get_pic_args(self) -> T.List[str]: + # We can lie here, it's fine + return [] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + new: T.List[str] = [] + for i in parameter_list: + new.append(i) + + return new + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + opts.update({ + OptionKey('version', machine=self.for_machine, lang=self.language): coredata.UserComboOption( + 'Python version to target', + ['2', '3'], + '3', + ), + OptionKey('language', machine=self.for_machine, lang=self.language): coredata.UserComboOption( + 'Output C or C++ files', + ['c', 'cpp'], + 'c', + ) + }) + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args: T.List[str] = [] + key = options[OptionKey('version', machine=self.for_machine, lang=self.language)] + args.append(f'-{key.value}') + lang = options[OptionKey('language', machine=self.for_machine, lang=self.language)] + if lang.value == 'cpp': + args.append('--cplus') + return args diff --git a/devtools/meson/mesonbuild/compilers/d.py b/devtools/meson/mesonbuild/compilers/d.py new file mode 100644 index 0000000..c6e70b2 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/d.py @@ -0,0 +1,1028 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os.path +import re +import subprocess +import typing as T + +from .. import mesonlib +from .. import mlog +from ..arglist import CompilerArgs +from ..linkers import RSPFileSyntax +from ..mesonlib import ( + EnvironmentException, version_compare, OptionKey, is_windows +) + +from . import compilers +from .compilers import ( + d_dmd_buildtype_args, + d_gdc_buildtype_args, + d_ldc_buildtype_args, + clike_debug_args, + Compiler, + CompileCheckMode, +) +from .mixins.gnu import GnuCompiler +from .mixins.gnu import gnu_common_warning_args + +if T.TYPE_CHECKING: + from ..dependencies import Dependency + from ..programs import ExternalProgram + from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + + CompilerMixinBase = Compiler +else: + CompilerMixinBase = object + +d_feature_args = {'gcc': {'unittest': '-funittest', + 'debug': '-fdebug', + 'version': '-fversion', + 'import_dir': '-J' + }, + 'llvm': {'unittest': '-unittest', + 'debug': '-d-debug', + 'version': '-d-version', + 'import_dir': '-J' + }, + 'dmd': {'unittest': '-unittest', + 'debug': '-debug', + 'version': '-version', + 'import_dir': '-J' + } + } # type: T.Dict[str, T.Dict[str, str]] + +ldc_optimization_args = {'plain': [], + '0': [], + 'g': [], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Oz'], + } # type: T.Dict[str, T.List[str]] + +dmd_optimization_args = {'plain': [], + '0': [], + 'g': [], + '1': ['-O'], + '2': ['-O'], + '3': ['-O'], + 's': ['-O'], + } # type: T.Dict[str, T.List[str]] + + +class DmdLikeCompilerMixin(CompilerMixinBase): + + """Mixin class for DMD and LDC. + + LDC has a number of DMD like arguments, and this class allows for code + sharing between them as makes sense. + """ + + def __init__(self, dmd_frontend_version: T.Optional[str]): + if dmd_frontend_version is None: + self._dmd_has_depfile = False + else: + # -makedeps switch introduced in 2.095 frontend + self._dmd_has_depfile = version_compare(dmd_frontend_version, ">=2.095.0") + + if T.TYPE_CHECKING: + mscrt_args = {} # type: T.Dict[str, T.List[str]] + + def _get_target_arch_args(self) -> T.List[str]: ... + + LINKER_PREFIX = '-L=' + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-of=' + outputname] + + def get_linker_output_args(self, outputname: str) -> T.List[str]: + return ['-of=' + outputname] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == "": + path = "." + return ['-I=' + path] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:3] == '-I=': + parameter_list[idx] = i[:3] + os.path.normpath(os.path.join(build_dir, i[3:])) + if i[:4] == '-L-L': + parameter_list[idx] = i[:4] + os.path.normpath(os.path.join(build_dir, i[4:])) + if i[:5] == '-L=-L': + parameter_list[idx] = i[:5] + os.path.normpath(os.path.join(build_dir, i[5:])) + if i[:6] == '-Wl,-L': + parameter_list[idx] = i[:6] + os.path.normpath(os.path.join(build_dir, i[6:])) + + return parameter_list + + def get_warn_args(self, level: str) -> T.List[str]: + return ['-wi'] + + def get_werror_args(self) -> T.List[str]: + return ['-w'] + + def get_coverage_args(self) -> T.List[str]: + return ['-cov'] + + def get_coverage_link_args(self) -> T.List[str]: + return [] + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-E'] + + def get_compile_only_args(self) -> T.List[str]: + return ['-c'] + + def get_depfile_suffix(self) -> str: + return 'deps' + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + if self._dmd_has_depfile: + return [f'-makedeps={outfile}'] + return [] + + def get_pic_args(self) -> T.List[str]: + if self.info.is_windows(): + return [] + return ['-fPIC'] + + def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + # TODO: using a TypeDict here would improve this + res = [] + # get_feature_args can be called multiple times for the same target when there is generated source + # so we have to copy the kwargs (target.d_features) dict before popping from it + kwargs = kwargs.copy() + if 'unittest' in kwargs: + unittest = kwargs.pop('unittest') + unittest_arg = d_feature_args[self.id]['unittest'] + if not unittest_arg: + raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) + if unittest: + res.append(unittest_arg) + + if 'debug' in kwargs: + debug_level = -1 + debugs = kwargs.pop('debug') + if not isinstance(debugs, list): + debugs = [debugs] + + debug_arg = d_feature_args[self.id]['debug'] + if not debug_arg: + raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string()) + + # Parse all debug identifiers and the largest debug level identifier + for d in debugs: + if isinstance(d, int): + if d > debug_level: + debug_level = d + elif isinstance(d, str) and d.isdigit(): + if int(d) > debug_level: + debug_level = int(d) + else: + res.append(f'{debug_arg}={d}') + + if debug_level >= 0: + res.append(f'{debug_arg}={debug_level}') + + if 'versions' in kwargs: + version_level = -1 + versions = kwargs.pop('versions') + if not isinstance(versions, list): + versions = [versions] + + version_arg = d_feature_args[self.id]['version'] + if not version_arg: + raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string()) + + # Parse all version identifiers and the largest version level identifier + for v in versions: + if isinstance(v, int): + if v > version_level: + version_level = v + elif isinstance(v, str) and v.isdigit(): + if int(v) > version_level: + version_level = int(v) + else: + res.append(f'{version_arg}={v}') + + if version_level >= 0: + res.append(f'{version_arg}={version_level}') + + if 'import_dirs' in kwargs: + import_dirs = kwargs.pop('import_dirs') + if not isinstance(import_dirs, list): + import_dirs = [import_dirs] + + import_dir_arg = d_feature_args[self.id]['import_dir'] + if not import_dir_arg: + raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) + for idir_obj in import_dirs: + basedir = idir_obj.get_curdir() + for idir in idir_obj.get_incdirs(): + bldtreedir = os.path.join(basedir, idir) + # Avoid superfluous '/.' at the end of paths when d is '.' + if idir not in ('', '.'): + expdir = bldtreedir + else: + expdir = basedir + srctreedir = os.path.join(build_to_src, expdir) + res.append(f'{import_dir_arg}{srctreedir}') + res.append(f'{import_dir_arg}{bldtreedir}') + + if kwargs: + raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) + + return res + + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + if buildtype != 'plain': + return self._get_target_arch_args() + return [] + + def gen_import_library_args(self, implibname: str) -> T.List[str]: + return self.linker.import_library_args(implibname) + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + if self.info.is_windows(): + return ([], set()) + + # GNU ld, solaris ld, and lld acting like GNU ld + if self.linker.id.startswith('ld'): + # The way that dmd and ldc pass rpath to gcc is different than we would + # do directly, each argument -rpath and the value to rpath, need to be + # split into two separate arguments both prefaced with the -L=. + args = [] + (rpath_args, rpath_dirs_to_remove) = super().build_rpath_args( + env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + for r in rpath_args: + if ',' in r: + a, b = r.split(',', maxsplit=1) + args.append(a) + args.append(self.LINKER_PREFIX + b) + else: + args.append(r) + return (args, rpath_dirs_to_remove) + + return super().build_rpath_args( + env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) + + @classmethod + def _translate_args_to_nongnu(cls, args: T.List[str], info: MachineInfo, link_id: str) -> T.List[str]: + # Translate common arguments to flags the LDC/DMD compilers + # can understand. + # The flags might have been added by pkg-config files, + # and are therefore out of the user's control. + dcargs = [] + # whether we hit a linker argument that expect another arg + # see the comment in the "-L" section + link_expect_arg = False + link_flags_with_arg = [ + '-rpath', '-rpath-link', '-soname', '-compatibility_version', '-current_version', + ] + for arg in args: + # Translate OS specific arguments first. + osargs = [] # type: T.List[str] + if info.is_windows(): + osargs = cls.translate_arg_to_windows(arg) + elif info.is_darwin(): + osargs = cls._translate_arg_to_osx(arg) + if osargs: + dcargs.extend(osargs) + continue + + # Translate common D arguments here. + if arg == '-pthread': + continue + if arg.startswith('-fstack-protector'): + continue + if arg.startswith('-D') and not (arg == '-D' or arg.startswith(('-Dd', '-Df'))): + # ignore all '-D*' flags (like '-D_THREAD_SAFE') + # unless they are related to documentation + continue + if arg.startswith('-Wl,'): + # Translate linker arguments here. + linkargs = arg[arg.index(',') + 1:].split(',') + for la in linkargs: + dcargs.append('-L=' + la.strip()) + continue + elif arg.startswith(('-link-defaultlib', '-linker', '-link-internally', '-linkonce-templates', '-lib')): + # these are special arguments to the LDC linker call, + # arguments like "-link-defaultlib-shared" do *not* + # denote a library to be linked, but change the default + # Phobos/DRuntime linking behavior, while "-linker" sets the + # default linker. + dcargs.append(arg) + continue + elif arg.startswith('-l'): + # translate library link flag + dcargs.append('-L=' + arg) + continue + elif arg.startswith('-isystem'): + # translate -isystem system include path + # this flag might sometimes be added by C library Cflags via + # pkg-config. + # NOTE: -isystem and -I are not 100% equivalent, so this is just + # a workaround for the most common cases. + if arg.startswith('-isystem='): + dcargs.append('-I=' + arg[9:]) + else: + dcargs.append('-I' + arg[8:]) + continue + elif arg.startswith('-idirafter'): + # same as -isystem, but appends the path instead + if arg.startswith('-idirafter='): + dcargs.append('-I=' + arg[11:]) + else: + dcargs.append('-I' + arg[10:]) + continue + elif arg.startswith('-L'): + # The D linker expect library search paths in the form of -L=-L/path (the '=' is optional). + # + # This function receives a mix of arguments already prepended + # with -L for the D linker driver and other linker arguments. + # The arguments starting with -L can be: + # - library search path (with or without a second -L) + # - it can come from pkg-config (a single -L) + # - or from the user passing linker flags (-L-L would be expected) + # - arguments like "-L=-rpath" that expect a second argument (also prepended with -L) + # - arguments like "-L=@rpath/xxx" without a second argument (on Apple platform) + # - arguments like "-L=/SUBSYSTEM:CONSOLE (for Windows linker) + # + # The logic that follows tries to detect all these cases (some may be missing) + # in order to prepend a -L only for the library search paths with a single -L + + if arg.startswith('-L='): + suffix = arg[3:] + else: + suffix = arg[2:] + + if link_expect_arg: + # flags like rpath and soname expect a path or filename respectively, + # we must not alter it (i.e. prefixing with -L for a lib search path) + dcargs.append(arg) + link_expect_arg = False + continue + + if suffix in link_flags_with_arg: + link_expect_arg = True + + if suffix.startswith('-') or suffix.startswith('@'): + # this is not search path + dcargs.append(arg) + continue + + # linker flag such as -L=/DEBUG must pass through + if info.is_windows() and link_id == 'link' and suffix.startswith('/'): + dcargs.append(arg) + continue + + # Make sure static library files are passed properly to the linker. + if arg.endswith('.a') or arg.endswith('.lib'): + if len(suffix) > 0 and not suffix.startswith('-'): + dcargs.append('-L=' + suffix) + continue + + dcargs.append('-L=' + arg) + continue + elif not arg.startswith('-') and arg.endswith(('.a', '.lib')): + # ensure static libraries are passed through to the linker + dcargs.append('-L=' + arg) + continue + else: + dcargs.append(arg) + + return dcargs + + @classmethod + def translate_arg_to_windows(cls, arg: str) -> T.List[str]: + args = [] + if arg.startswith('-Wl,'): + # Translate linker arguments here. + linkargs = arg[arg.index(',') + 1:].split(',') + for la in linkargs: + if la.startswith('--out-implib='): + # Import library name + args.append('-L=/IMPLIB:' + la[13:].strip()) + elif arg.startswith('-mscrtlib='): + args.append(arg) + mscrtlib = arg[10:].lower() + if cls is LLVMDCompiler: + # Default crt libraries for LDC2 must be excluded for other + # selected crt options. + if mscrtlib != 'libcmt': + args.append('-L=/NODEFAULTLIB:libcmt') + args.append('-L=/NODEFAULTLIB:libvcruntime') + + # Fixes missing definitions for printf-functions in VS2017 + if mscrtlib.startswith('msvcrt'): + args.append('-L=/DEFAULTLIB:legacy_stdio_definitions.lib') + + return args + + @classmethod + def _translate_arg_to_osx(cls, arg: str) -> T.List[str]: + args = [] + if arg.startswith('-install_name'): + args.append('-L=' + arg) + return args + + @classmethod + def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo, link_id: str = '') -> T.List[str]: + return cls._translate_args_to_nongnu(args, info, link_id) + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + ddebug_args = [] + if is_debug: + ddebug_args = [d_feature_args[self.id]['debug']] + + return clike_debug_args[is_debug] + ddebug_args + + def _get_crt_args(self, crt_val: str, buildtype: str) -> T.List[str]: + if not self.info.is_windows(): + return [] + + if crt_val in self.mscrt_args: + return self.mscrt_args[crt_val] + assert crt_val in {'from_buildtype', 'static_from_buildtype'} + + dbg = 'mdd' + rel = 'md' + if crt_val == 'static_from_buildtype': + dbg = 'mtd' + rel = 'mt' + + # Match what build type flags used to do. + if buildtype == 'plain': + return [] + elif buildtype == 'debug': + return self.mscrt_args[dbg] + elif buildtype == 'debugoptimized': + return self.mscrt_args[rel] + elif buildtype == 'release': + return self.mscrt_args[rel] + elif buildtype == 'minsize': + return self.mscrt_args[rel] + else: + assert buildtype == 'custom' + raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, + darwin_versions: T.Tuple[str, str]) -> T.List[str]: + sargs = super().get_soname_args(env, prefix, shlib_name, suffix, + soversion, darwin_versions) + + # LDC and DMD actually do use a linker, but they proxy all of that with + # their own arguments + if self.linker.id.startswith('ld.'): + soargs = [] + for arg in sargs: + a, b = arg.split(',', maxsplit=1) + soargs.append(a) + soargs.append(self.LINKER_PREFIX + b) + return soargs + elif self.linker.id.startswith('ld64'): + soargs = [] + for arg in sargs: + if not arg.startswith(self.LINKER_PREFIX): + soargs.append(self.LINKER_PREFIX + arg) + else: + soargs.append(arg) + return soargs + else: + return sargs + + def get_allow_undefined_link_args(self) -> T.List[str]: + args = self.linker.get_allow_undefined_args() + if self.info.is_darwin(): + # On macOS we're passing these options to the C compiler, but + # they're linker options and need -Wl, so clang/gcc knows what to + # do with them. I'm assuming, but don't know for certain, that + # ldc/dmd do some kind of mapping internally for arguments they + # understand, but pass arguments they don't understand directly. + args = [a.replace('-L=', '-Xcc=-Wl,') for a in args] + return args + + +class DCompilerArgs(CompilerArgs): + prepend_prefixes = ('-I', '-L') + dedup2_prefixes = ('-I', ) + + +class DCompiler(Compiler): + mscrt_args = { + 'none': ['-mscrtlib='], + 'md': ['-mscrtlib=msvcrt'], + 'mdd': ['-mscrtlib=msvcrtd'], + 'mt': ['-mscrtlib=libcmt'], + 'mtd': ['-mscrtlib=libcmtd'], + } + + language = 'd' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False): + super().__init__([], exelist, version, for_machine, info, linker=linker, + full_version=full_version, is_cross=is_cross) + self.arch = arch + self.exe_wrapper = exe_wrapper + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + source_name = os.path.join(work_dir, 'sanity.d') + output_name = os.path.join(work_dir, 'dtest') + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write('''void main() { }''') + pc = subprocess.Popen(self.exelist + self.get_output_args(output_name) + self._get_target_arch_args() + [source_name], cwd=work_dir) + pc.wait() + if pc.returncode != 0: + raise EnvironmentException('D compiler %s cannot compile programs.' % self.name_string()) + if self.is_cross: + if self.exe_wrapper is None: + # Can't check if the binaries run so we have to assume they do + return + cmdlist = self.exe_wrapper.get_command() + [output_name] + else: + cmdlist = [output_name] + if subprocess.call(cmdlist) != 0: + raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string()) + + def needs_static_linker(self) -> bool: + return True + + def get_depfile_suffix(self) -> str: + return 'deps' + + def get_pic_args(self) -> T.List[str]: + if self.info.is_windows(): + return [] + return ['-fPIC'] + + def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + # TODO: using a TypeDict here would improve this + res = [] + # get_feature_args can be called multiple times for the same target when there is generated source + # so we have to copy the kwargs (target.d_features) dict before popping from it + kwargs = kwargs.copy() + if 'unittest' in kwargs: + unittest = kwargs.pop('unittest') + unittest_arg = d_feature_args[self.id]['unittest'] + if not unittest_arg: + raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) + if unittest: + res.append(unittest_arg) + + if 'debug' in kwargs: + debug_level = -1 + debugs = kwargs.pop('debug') + if not isinstance(debugs, list): + debugs = [debugs] + + debug_arg = d_feature_args[self.id]['debug'] + if not debug_arg: + raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string()) + + # Parse all debug identifiers and the largest debug level identifier + for d in debugs: + if isinstance(d, int): + if d > debug_level: + debug_level = d + elif isinstance(d, str) and d.isdigit(): + if int(d) > debug_level: + debug_level = int(d) + else: + res.append(f'{debug_arg}={d}') + + if debug_level >= 0: + res.append(f'{debug_arg}={debug_level}') + + if 'versions' in kwargs: + version_level = -1 + versions = kwargs.pop('versions') + if not isinstance(versions, list): + versions = [versions] + + version_arg = d_feature_args[self.id]['version'] + if not version_arg: + raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string()) + + # Parse all version identifiers and the largest version level identifier + for v in versions: + if isinstance(v, int): + if v > version_level: + version_level = v + elif isinstance(v, str) and v.isdigit(): + if int(v) > version_level: + version_level = int(v) + else: + res.append(f'{version_arg}={v}') + + if version_level >= 0: + res.append(f'{version_arg}={version_level}') + + if 'import_dirs' in kwargs: + import_dirs = kwargs.pop('import_dirs') + if not isinstance(import_dirs, list): + import_dirs = [import_dirs] + + import_dir_arg = d_feature_args[self.id]['import_dir'] + if not import_dir_arg: + raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) + for idir_obj in import_dirs: + basedir = idir_obj.get_curdir() + for idir in idir_obj.get_incdirs(): + bldtreedir = os.path.join(basedir, idir) + # Avoid superfluous '/.' at the end of paths when d is '.' + if idir not in ('', '.'): + expdir = bldtreedir + else: + expdir = basedir + srctreedir = os.path.join(build_to_src, expdir) + res.append(f'{import_dir_arg}{srctreedir}') + res.append(f'{import_dir_arg}{bldtreedir}') + + if kwargs: + raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) + + return res + + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + if buildtype != 'plain': + return self._get_target_arch_args() + return [] + + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> DCompilerArgs: + return DCompilerArgs(self, args) + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self.compiles('int i;\n', env, extra_args=args) + + def _get_target_arch_args(self) -> T.List[str]: + # LDC2 on Windows targets to current OS architecture, but + # it should follow the target specified by the MSVC toolchain. + if self.info.is_windows(): + if self.arch == 'x86_64': + return ['-m64'] + return ['-m32'] + return [] + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return [] + + def _get_compile_extra_args(self, extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None) -> T.List[str]: + args = self._get_target_arch_args() + if extra_args: + if callable(extra_args): + extra_args = extra_args(CompileCheckMode.COMPILE) + if isinstance(extra_args, list): + args.extend(extra_args) + elif isinstance(extra_args, str): + args.append(extra_args) + return args + + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: + need_exe_wrapper = env.need_exe_wrapper(self.for_machine) + if need_exe_wrapper and self.exe_wrapper is None: + raise compilers.CrossNoRunException('Can not run test applications in this cross environment.') + extra_args = self._get_compile_extra_args(extra_args) + with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p: + if p.returncode != 0: + mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') + return compilers.RunResult(False) + if need_exe_wrapper: + cmdlist = self.exe_wrapper.get_command() + [p.output_name] + else: + cmdlist = [p.output_name] + try: + pe, so, se = mesonlib.Popen_safe(cmdlist) + except Exception as e: + mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') + return compilers.RunResult(False) + + mlog.debug('Program stdout:\n') + mlog.debug(so) + mlog.debug('Program stderr:\n') + mlog.debug(se) + return compilers.RunResult(True, pe.returncode, so, se) + + def sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: + if extra_args is None: + extra_args = [] + t = f''' + import std.stdio : writeln; + {prefix} + void main() {{ + writeln(({typename}).sizeof); + }} + ''' + res = self.cached_run(t, env, extra_args=extra_args, + dependencies=dependencies) + if not res.compiled: + return -1, False + if res.returncode != 0: + raise mesonlib.EnvironmentException('Could not run sizeof test binary.') + return int(res.stdout), res.cached + + def alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: + if extra_args is None: + extra_args = [] + t = f''' + import std.stdio : writeln; + {prefix} + void main() {{ + writeln(({typename}).alignof); + }} + ''' + res = self.run(t, env, extra_args=extra_args, + dependencies=dependencies) + if not res.compiled: + raise mesonlib.EnvironmentException('Could not compile alignment test.') + if res.returncode != 0: + raise mesonlib.EnvironmentException('Could not run alignment test binary.') + align = int(res.stdout) + if align == 0: + raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.') + return align, res.cached + + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + + extra_args = self._get_compile_extra_args(extra_args) + code = f'''{prefix} + import {hname}; + ''' + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode='compile', disable_cache=disable_cache) + +class GnuDCompiler(GnuCompiler, DCompiler): + + # we mostly want DCompiler, but that gives us the Compiler.LINKER_PREFIX instead + LINKER_PREFIX = GnuCompiler.LINKER_PREFIX + id = 'gcc' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False): + DCompiler.__init__(self, exelist, version, for_machine, info, arch, + exe_wrapper=exe_wrapper, linker=linker, + full_version=full_version, is_cross=is_cross) + GnuCompiler.__init__(self, {}) + default_warn_args = ['-Wall', '-Wdeprecated'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic'], + 'everything': (default_warn_args + ['-Wextra', '-Wpedantic'] + + self.supported_warn_args(gnu_common_warning_args))} + + self.base_options = { + OptionKey(o) for o in [ + 'b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt', + 'b_coverage', 'b_pgo', 'b_ndebug']} + + self._has_color_support = version_compare(self.version, '>=4.9') + # dependencies were implemented before, but broken - support was fixed in GCC 7.1+ + # (and some backported versions) + self._has_deps_support = version_compare(self.version, '>=7.1') + + def get_colorout_args(self, colortype: str) -> T.List[str]: + if self._has_color_support: + super().get_colorout_args(colortype) + return [] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + if self._has_deps_support: + return super().get_dependency_gen_args(outtarget, outfile) + return [] + + def get_warn_args(self, level: str) -> T.List[str]: + return self.warn_args[level] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return d_gdc_buildtype_args[buildtype] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I' or i[:2] == '-L': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + + return parameter_list + + def get_allow_undefined_link_args(self) -> T.List[str]: + return self.linker.get_allow_undefined_args() + + def get_linker_always_args(self) -> T.List[str]: + args = super().get_linker_always_args() + if self.info.is_windows(): + return args + return args + ['-shared-libphobos'] + + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['-frelease'] + return [] + +# LDC uses the DMD frontend code to parse and analyse the code. +# It then uses LLVM for the binary code generation and optimizations. +# This function retrieves the dmd frontend version, which determines +# the common features between LDC and DMD. +# We need the complete version text because the match is not on first line +# of version_output +def find_ldc_dmd_frontend_version(version_output: T.Optional[str]) -> T.Optional[str]: + if version_output is None: + return None + version_regex = re.search(r'DMD v(\d+\.\d+\.\d+)', version_output) + if version_regex: + return version_regex.group(1) + return None + +class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler): + + id = 'llvm' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False, version_output: T.Optional[str] = None): + DCompiler.__init__(self, exelist, version, for_machine, info, arch, + exe_wrapper=exe_wrapper, linker=linker, + full_version=full_version, is_cross=is_cross) + DmdLikeCompilerMixin.__init__(self, dmd_frontend_version=find_ldc_dmd_frontend_version(version_output)) + self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} + + def get_colorout_args(self, colortype: str) -> T.List[str]: + if colortype == 'always': + return ['-enable-color'] + return [] + + def get_warn_args(self, level: str) -> T.List[str]: + if level in {'2', '3'}: + return ['-wi', '-dw'] + elif level == '1': + return ['-wi'] + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + if buildtype != 'plain': + return self._get_target_arch_args() + d_ldc_buildtype_args[buildtype] + return d_ldc_buildtype_args[buildtype] + + def get_pic_args(self) -> T.List[str]: + return ['-relocation-model=pic'] + + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return self._get_crt_args(crt_val, buildtype) + + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: + return self._unix_args_to_native(args, self.info, self.linker.id) + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return ldc_optimization_args[optimization_level] + + @classmethod + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: + return [f'-linker={linker}'] + + def get_linker_always_args(self) -> T.List[str]: + args = super().get_linker_always_args() + if self.info.is_windows(): + return args + return args + ['-link-defaultlib-shared'] + + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['--release'] + return [] + + def rsp_file_syntax(self) -> RSPFileSyntax: + # We use `mesonlib.is_windows` here because we want to know what the + # build machine is, not the host machine. This really means we would + # have the Environment not the MachineInfo in the compiler. + return RSPFileSyntax.MSVC if is_windows() else RSPFileSyntax.GCC + + +class DmdDCompiler(DmdLikeCompilerMixin, DCompiler): + + id = 'dmd' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', arch: str, *, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None, + is_cross: bool = False): + DCompiler.__init__(self, exelist, version, for_machine, info, arch, + exe_wrapper=exe_wrapper, linker=linker, + full_version=full_version, is_cross=is_cross) + DmdLikeCompilerMixin.__init__(self, version) + self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} + + def get_colorout_args(self, colortype: str) -> T.List[str]: + if colortype == 'always': + return ['-color=on'] + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + if buildtype != 'plain': + return self._get_target_arch_args() + d_dmd_buildtype_args[buildtype] + return d_dmd_buildtype_args[buildtype] + + def get_std_exe_link_args(self) -> T.List[str]: + if self.info.is_windows(): + # DMD links against D runtime only when main symbol is found, + # so these needs to be inserted when linking static D libraries. + if self.arch == 'x86_64': + return ['phobos64.lib'] + elif self.arch == 'x86_mscoff': + return ['phobos32mscoff.lib'] + return ['phobos.lib'] + return [] + + def get_std_shared_lib_link_args(self) -> T.List[str]: + libname = 'libphobos2.so' + if self.info.is_windows(): + if self.arch == 'x86_64': + libname = 'phobos64.lib' + elif self.arch == 'x86_mscoff': + libname = 'phobos32mscoff.lib' + else: + libname = 'phobos.lib' + return ['-shared', '-defaultlib=' + libname] + + def _get_target_arch_args(self) -> T.List[str]: + # DMD32 and DMD64 on 64-bit Windows defaults to 32-bit (OMF). + # Force the target to 64-bit in order to stay consistent + # across the different platforms. + if self.info.is_windows(): + if self.arch == 'x86_64': + return ['-m64'] + elif self.arch == 'x86_mscoff': + return ['-m32mscoff'] + return ['-m32'] + return [] + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + return self._get_crt_args(crt_val, buildtype) + + def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: + return self._unix_args_to_native(args, self.info, self.linker.id) + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return dmd_optimization_args[optimization_level] + + def can_linker_accept_rsp(self) -> bool: + return False + + def get_linker_always_args(self) -> T.List[str]: + args = super().get_linker_always_args() + if self.info.is_windows(): + return args + return args + ['-defaultlib=phobos2', '-debuglib=phobos2'] + + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['-release'] + return [] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.MSVC diff --git a/devtools/meson/mesonbuild/compilers/detect.py b/devtools/meson/mesonbuild/compilers/detect.py new file mode 100644 index 0000000..58d6f4e --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/detect.py @@ -0,0 +1,1381 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from ..mesonlib import ( + MesonException, EnvironmentException, MachineChoice, join_args, + search_version, is_windows, Popen_safe, Popen_safe_logged, windows_proof_rm, +) +from ..envconfig import BinaryTable +from .. import mlog + +from ..linkers import guess_win_linker, guess_nix_linker + +import subprocess +import platform +import re +import shutil +import tempfile +import os +import typing as T + +if T.TYPE_CHECKING: + from .compilers import Compiler + from .c import CCompiler + from .cpp import CPPCompiler + from .fortran import FortranCompiler + from .rust import RustCompiler + from ..linkers.linkers import StaticLinker, DynamicLinker + from ..environment import Environment + from ..programs import ExternalProgram + + +# Default compilers and linkers +# ============================= + +defaults: T.Dict[str, T.List[str]] = {} + +# List of potential compilers. +if is_windows(): + # Intel C and C++ compiler is icl on Windows, but icc and icpc elsewhere. + # Search for icl before cl, since Intel "helpfully" provides a + # cl.exe that returns *exactly the same thing* that microsofts + # cl.exe does, and if icl is present, it's almost certainly what + # you want. + defaults['c'] = ['icl', 'cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc'] + # There is currently no pgc++ for Windows, only for Mac and Linux. + defaults['cpp'] = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl'] + defaults['fortran'] = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95'] + # Clang and clang++ are valid, but currently unsupported. + defaults['objc'] = ['cc', 'gcc'] + defaults['objcpp'] = ['c++', 'g++'] + defaults['cs'] = ['csc', 'mcs'] +else: + if platform.machine().lower() == 'e2k': + defaults['c'] = ['cc', 'gcc', 'lcc', 'clang'] + defaults['cpp'] = ['c++', 'g++', 'l++', 'clang++'] + defaults['objc'] = ['clang'] + defaults['objcpp'] = ['clang++'] + else: + defaults['c'] = ['cc', 'gcc', 'clang', 'nvc', 'pgcc', 'icc', 'icx'] + defaults['cpp'] = ['c++', 'g++', 'clang++', 'nvc++', 'pgc++', 'icpc', 'icpx'] + defaults['objc'] = ['cc', 'gcc', 'clang'] + defaults['objcpp'] = ['c++', 'g++', 'clang++'] + defaults['fortran'] = ['gfortran', 'flang', 'nvfortran', 'pgfortran', 'ifort', 'ifx', 'g95'] + defaults['cs'] = ['mcs', 'csc'] +defaults['d'] = ['ldc2', 'ldc', 'gdc', 'dmd'] +defaults['java'] = ['javac'] +defaults['cuda'] = ['nvcc'] +defaults['rust'] = ['rustc'] +defaults['swift'] = ['swiftc'] +defaults['vala'] = ['valac'] +defaults['cython'] = ['cython', 'cython3'] # Official name is cython, but Debian renamed it to cython3. +defaults['static_linker'] = ['ar', 'gar'] +defaults['strip'] = ['strip'] +defaults['vs_static_linker'] = ['lib'] +defaults['clang_cl_static_linker'] = ['llvm-lib'] +defaults['cuda_static_linker'] = ['nvlink'] +defaults['gcc_static_linker'] = ['gcc-ar'] +defaults['clang_static_linker'] = ['llvm-ar'] +defaults['nasm'] = ['nasm', 'yasm'] + + +def compiler_from_language(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Optional[Compiler]: + lang_map: T.Dict[str, T.Callable[['Environment', MachineChoice], Compiler]] = { + 'c': detect_c_compiler, + 'cpp': detect_cpp_compiler, + 'objc': detect_objc_compiler, + 'cuda': detect_cuda_compiler, + 'objcpp': detect_objcpp_compiler, + 'java': detect_java_compiler, + 'cs': detect_cs_compiler, + 'vala': detect_vala_compiler, + 'd': detect_d_compiler, + 'rust': detect_rust_compiler, + 'fortran': detect_fortran_compiler, + 'swift': detect_swift_compiler, + 'cython': detect_cython_compiler, + 'nasm': detect_nasm_compiler, + 'masm': detect_masm_compiler, + } + return lang_map[lang](env, for_machine) if lang in lang_map else None + +def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice, skip_sanity_check: bool) -> T.Optional[Compiler]: + comp = compiler_from_language(env, lang, for_machine) + if comp is None: + return comp + assert comp.for_machine == for_machine + env.coredata.process_new_compiler(lang, comp, env) + if not skip_sanity_check: + comp.sanity_check(env.get_scratch_dir(), env) + env.coredata.compilers[comp.for_machine][lang] = comp + return comp + + +# Helpers +# ======= + +def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str], T.Optional['ExternalProgram']]: + ''' + The list of compilers is detected in the exact same way for + C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. + ''' + value = env.lookup_binary_entry(for_machine, lang) + if value is not None: + comp, ccache = BinaryTable.parse_entry(value) + # Return value has to be a list of compiler 'choices' + compilers = [comp] + else: + if not env.machines.matches_build_machine(for_machine): + raise EnvironmentException(f'{lang!r} compiler binary not defined in cross or native file') + compilers = [[x] for x in defaults[lang]] + ccache = BinaryTable.detect_compiler_cache() + + if env.machines.matches_build_machine(for_machine): + exe_wrap: T.Optional[ExternalProgram] = None + else: + exe_wrap = env.get_exe_wrapper() + + return compilers, ccache, exe_wrap + +def _handle_exceptions( + exceptions: T.Mapping[str, T.Union[Exception, str]], + binaries: T.List[T.List[str]], + bintype: str = 'compiler') -> T.NoReturn: + errmsg = f'Unknown {bintype}(s): {binaries}' + if exceptions: + errmsg += '\nThe following exception(s) were encountered:' + for c, e in exceptions.items(): + errmsg += f'\nRunning `{c}` gave "{e}"' + raise EnvironmentException(errmsg) + + +# Linker specific +# =============== + +def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker: + from . import d + from ..linkers import linkers + linker = env.lookup_binary_entry(compiler.for_machine, 'ar') + if linker is not None: + trials = [linker] + else: + default_linkers = [[l] for l in defaults['static_linker']] + if compiler.language == 'cuda': + trials = [defaults['cuda_static_linker']] + default_linkers + elif compiler.get_argument_syntax() == 'msvc': + trials = [defaults['vs_static_linker'], defaults['clang_cl_static_linker']] + elif compiler.id == 'gcc': + # Use gcc-ar if available; needed for LTO + trials = [defaults['gcc_static_linker']] + default_linkers + elif compiler.id == 'clang': + # Use llvm-ar if available; needed for LTO + trials = [defaults['clang_static_linker']] + default_linkers + elif compiler.language == 'd': + # Prefer static linkers over linkers used by D compilers + if is_windows(): + trials = [defaults['vs_static_linker'], defaults['clang_cl_static_linker'], compiler.get_linker_exelist()] + else: + trials = default_linkers + elif compiler.id == 'intel-cl' and compiler.language == 'c': # why not cpp? Is this a bug? + # Intel has it's own linker that acts like microsoft's lib + trials = [['xilib']] + elif is_windows() and compiler.id == 'pgi': # this handles cpp / nvidia HPC, in addition to just c/fortran + trials = [['ar']] # For PGI on Windows, "ar" is just a wrapper calling link/lib. + elif is_windows() and compiler.id == 'nasm': + # This may well be LINK.EXE if it's under a MSVC environment + trials = [defaults['vs_static_linker'], defaults['clang_cl_static_linker']] + default_linkers + else: + trials = default_linkers + popen_exceptions = {} + for linker in trials: + linker_name = os.path.basename(linker[0]) + + if any(os.path.basename(x) in {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'} for x in linker): + arg = '/?' + elif linker_name in {'ar2000', 'ar2000.exe', 'ar430', 'ar430.exe', 'armar', 'armar.exe'}: + arg = '?' + else: + arg = '--version' + try: + p, out, err = Popen_safe_logged(linker + [arg], msg='Detecting linker via') + except OSError as e: + popen_exceptions[join_args(linker + [arg])] = e + continue + if "xilib: executing 'lib'" in err: + return linkers.IntelVisualStudioLinker(linker, getattr(compiler, 'machine', None)) + if '/OUT:' in out.upper() or '/OUT:' in err.upper(): + return linkers.VisualStudioLinker(linker, getattr(compiler, 'machine', None)) + if 'ar-Error-Unknown switch: --version' in err: + return linkers.PGIStaticLinker(linker) + if p.returncode == 0 and 'armar' in linker_name: + return linkers.ArmarLinker(linker) + if 'DMD32 D Compiler' in out or 'DMD64 D Compiler' in out: + assert isinstance(compiler, d.DCompiler) + return linkers.DLinker(linker, compiler.arch) + if 'LDC - the LLVM D compiler' in out: + assert isinstance(compiler, d.DCompiler) + return linkers.DLinker(linker, compiler.arch, rsp_syntax=compiler.rsp_file_syntax()) + if 'GDC' in out and ' based on D ' in out: + assert isinstance(compiler, d.DCompiler) + return linkers.DLinker(linker, compiler.arch) + if err.startswith('Renesas') and 'rlink' in linker_name: + return linkers.CcrxLinker(linker) + if out.startswith('GNU ar') and 'xc16-ar' in linker_name: + return linkers.Xc16Linker(linker) + if 'Texas Instruments Incorporated' in out: + if 'ar2000' in linker_name: + return linkers.C2000Linker(linker) + else: + return linkers.TILinker(linker) + if out.startswith('The CompCert'): + return linkers.CompCertLinker(linker) + if out.strip().startswith('Metrowerks') or out.strip().startswith('Freescale'): + if 'ARM' in out: + return linkers.MetrowerksStaticLinkerARM(linker) + else: + return linkers.MetrowerksStaticLinkerEmbeddedPowerPC(linker) + if p.returncode == 0: + return linkers.ArLinker(compiler.for_machine, linker) + if p.returncode == 1 and err.startswith('usage'): # OSX + return linkers.AppleArLinker(compiler.for_machine, linker) + if p.returncode == 1 and err.startswith('Usage'): # AIX + return linkers.AIXArLinker(linker) + if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris + return linkers.ArLinker(compiler.for_machine, linker) + _handle_exceptions(popen_exceptions, trials, 'linker') + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + + +# Compilers +# ========= + + +def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: MachineChoice, *, override_compiler: T.Optional[T.List[str]] = None) -> Compiler: + """Shared implementation for finding the C or C++ compiler to use. + + the override_compiler option is provided to allow compilers which use + the compiler (GCC or Clang usually) as their shared linker, to find + the linker they need. + """ + from . import c, cpp + from ..linkers import linkers + popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} + compilers, ccache, exe_wrap = _get_compilers(env, lang, for_machine) + if override_compiler is not None: + compilers = [override_compiler] + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + cls: T.Union[T.Type[CCompiler], T.Type[CPPCompiler]] + lnk: T.Union[T.Type[StaticLinker], T.Type[DynamicLinker]] + + for compiler in compilers: + if isinstance(compiler, str): + compiler = [compiler] + compiler_name = os.path.basename(compiler[0]) + + if any(os.path.basename(x) in {'cl', 'cl.exe', 'clang-cl', 'clang-cl.exe'} for x in compiler): + # Watcom C provides it's own cl.exe clone that mimics an older + # version of Microsoft's compiler. Since Watcom's cl.exe is + # just a wrapper, we skip using it if we detect its presence + # so as not to confuse Meson when configuring for MSVC. + # + # Additionally the help text of Watcom's cl.exe is paged, and + # the binary will not exit without human intervention. In + # practice, Meson will block waiting for Watcom's cl.exe to + # exit, which requires user input and thus will never exit. + if 'WATCOM' in os.environ: + def sanitize(p: str) -> str: + return os.path.normcase(os.path.abspath(p)) + + watcom_cls = [sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl')), + sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl.exe')), + sanitize(os.path.join(os.environ['WATCOM'], 'BINNT64', 'cl')), + sanitize(os.path.join(os.environ['WATCOM'], 'BINNT64', 'cl.exe'))] + found_cl = sanitize(shutil.which('cl')) + if found_cl in watcom_cls: + mlog.debug('Skipping unsupported cl.exe clone at:', found_cl) + continue + arg = '/?' + elif 'armcc' in compiler_name: + arg = '--vsn' + elif 'ccrx' in compiler_name: + arg = '-v' + elif 'xc16' in compiler_name: + arg = '--version' + elif 'ccomp' in compiler_name: + arg = '-version' + elif compiler_name in {'cl2000', 'cl2000.exe', 'cl430', 'cl430.exe', 'armcl', 'armcl.exe'}: + # TI compiler + arg = '-version' + elif compiler_name in {'icl', 'icl.exe'}: + # if you pass anything to icl you get stuck in a pager + arg = '' + else: + arg = '--version' + + cmd = compiler + [arg] + try: + p, out, err = Popen_safe_logged(cmd, msg='Detecting compiler via') + except OSError as e: + popen_exceptions[join_args(cmd)] = e + continue + + if 'ccrx' in compiler_name: + out = err + + full_version = out.split('\n', 1)[0] + version = search_version(out) + + guess_gcc_or_lcc: T.Optional[str] = None + if 'Free Software Foundation' in out or out.startswith('xt-'): + guess_gcc_or_lcc = 'gcc' + if 'e2k' in out and 'lcc' in out: + guess_gcc_or_lcc = 'lcc' + if 'Microchip Technology' in out: + # this output has "Free Software Foundation" in its version + guess_gcc_or_lcc = None + + if guess_gcc_or_lcc: + defines = _get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[join_args(compiler)] = 'no pre-processor defines' + continue + + if guess_gcc_or_lcc == 'lcc': + version = _get_lcc_version_from_defines(defines) + cls = c.ElbrusCCompiler if lang == 'c' else cpp.ElbrusCPPCompiler + else: + version = _get_gnu_version_from_defines(defines) + cls = c.GnuCCompiler if lang == 'c' else cpp.GnuCPPCompiler + + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + + return cls( + ccache, compiler, version, for_machine, is_cross, + info, exe_wrap, defines=defines, full_version=full_version, + linker=linker) + + if 'Emscripten' in out: + cls = c.EmscriptenCCompiler if lang == 'c' else cpp.EmscriptenCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + + # emcc requires a file input in order to pass arguments to the + # linker. It'll exit with an error code, but still print the + # linker version. + with tempfile.NamedTemporaryFile(suffix='.c') as f: + cmd = compiler + [cls.LINKER_PREFIX + "--version", f.name] + _, o, _ = Popen_safe(cmd) + + linker = linkers.WASMDynamicLinker( + compiler, for_machine, cls.LINKER_PREFIX, + [], version=search_version(o)) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, linker=linker, full_version=full_version) + + if 'Arm C/C++/Fortran Compiler' in out: + arm_ver_match = re.search(r'version (\d+)\.(\d+)\.?(\d+)? \(build number (\d+)\)', out) + assert arm_ver_match is not None, 'for mypy' # because mypy *should* be complaining that this could be None + version = '.'.join([x for x in arm_ver_match.groups() if x is not None]) + if lang == 'c': + cls = c.ArmLtdClangCCompiler + elif lang == 'cpp': + cls = cpp.ArmLtdClangCPPCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, linker=linker) + if 'armclang' in out: + # The compiler version is not present in the first line of output, + # instead it is present in second line, startswith 'Component:'. + # So, searching for the 'Component' in out although we know it is + # present in second line, as we are not sure about the + # output format in future versions + arm_ver_match = re.search('.*Component.*', out) + if arm_ver_match is None: + popen_exceptions[join_args(compiler)] = 'version string not found' + continue + arm_ver_str = arm_ver_match.group(0) + # Override previous values + version = search_version(arm_ver_str) + full_version = arm_ver_str + cls = c.ArmclangCCompiler if lang == 'c' else cpp.ArmclangCPPCompiler + linker = linkers.ArmClangDynamicLinker(for_machine, version=version) + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + if 'CL.EXE COMPATIBILITY' in out: + # if this is clang-cl masquerading as cl, detect it as cl, not + # clang + arg = '--version' + try: + p, out, err = Popen_safe(compiler + [arg]) + except OSError as e: + popen_exceptions[join_args(compiler + [arg])] = e + version = search_version(out) + match = re.search('^Target: (.*?)-', out, re.MULTILINE) + if match: + target = match.group(1) + else: + target = 'unknown target' + cls = c.ClangClCCompiler if lang == 'c' else cpp.ClangClCPPCompiler + linker = guess_win_linker(env, ['lld-link'], cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, target, + exe_wrap, linker=linker) + if 'clang' in out or 'Clang' in out: + linker = None + + defines = _get_clang_compiler_defines(compiler) + + # Even if the for_machine is darwin, we could be using vanilla + # clang. + if 'Apple' in out: + cls = c.AppleClangCCompiler if lang == 'c' else cpp.AppleClangCPPCompiler + else: + cls = c.ClangCCompiler if lang == 'c' else cpp.ClangCPPCompiler + + if 'windows' in out or env.machines[for_machine].is_windows(): + # If we're in a MINGW context this actually will use a gnu + # style ld, but for clang on "real" windows we'll use + # either link.exe or lld-link.exe + try: + linker = guess_win_linker(env, compiler, cls, version, for_machine, invoked_directly=False) + except MesonException: + pass + if linker is None: + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, defines=defines, full_version=full_version, linker=linker) + + if 'Intel(R) C++ Intel(R)' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = c.IntelClCCompiler if lang == 'c' else cpp.IntelClCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, target, + exe_wrap, linker=linker) + if 'Intel(R) oneAPI DPC++/C++ Compiler for applications' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = c.IntelLLVMClCCompiler if lang == 'c' else cpp.IntelLLVMClCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, target, + exe_wrap, linker=linker) + if 'Microsoft' in out or 'Microsoft' in err: + # Latest versions of Visual Studio print version + # number to stderr but earlier ones print version + # on stdout. Why? Lord only knows. + # Check both outputs to figure out version. + for lookat in [err, out]: + version = search_version(lookat) + if version != 'unknown version': + break + else: + raise EnvironmentException(f'Failed to detect MSVC compiler version: stderr was\n{err!r}') + cl_signature = lookat.split('\n', maxsplit=1)[0] + match = re.search(r'.*(x86|x64|ARM|ARM64)([^_A-Za-z0-9]|$)', cl_signature) + if match: + target = match.group(1) + else: + m = f'Failed to detect MSVC compiler target architecture: \'cl /?\' output is\n{cl_signature}' + raise EnvironmentException(m) + cls = c.VisualStudioCCompiler if lang == 'c' else cpp.VisualStudioCPPCompiler + linker = guess_win_linker(env, ['link'], cls, version, for_machine) + # As of this writing, CCache does not support MSVC but sccache does. + if 'sccache' not in ccache: + ccache = [] + return cls( + ccache, compiler, version, for_machine, is_cross, info, target, + exe_wrap, full_version=cl_signature, linker=linker) + if 'PGI Compilers' in out: + cls = c.PGICCompiler if lang == 'c' else cpp.PGICPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, + info, exe_wrap, linker=linker) + if 'NVIDIA Compilers and Tools' in out: + cls = c.NvidiaHPC_CCompiler if lang == 'c' else cpp.NvidiaHPC_CPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.NvidiaHPC_DynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, + info, exe_wrap, linker=linker) + if '(ICC)' in out: + cls = c.IntelCCompiler if lang == 'c' else cpp.IntelCPPCompiler + l = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=l) + if 'Intel(R) oneAPI' in out: + cls = c.IntelLLVMCCompiler if lang == 'c' else cpp.IntelLLVMCPPCompiler + l = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=l) + if 'TMS320C2000 C/C++' in out or 'MSP430 C/C++' in out or 'TI ARM C/C++ Compiler' in out: + if 'TMS320C2000 C/C++' in out: + cls = c.C2000CCompiler if lang == 'c' else cpp.C2000CPPCompiler + lnk = linkers.C2000DynamicLinker + else: + cls = c.TICCompiler if lang == 'c' else cpp.TICPPCompiler + lnk = linkers.TIDynamicLinker + + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = lnk(compiler, for_machine, version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + if 'ARM' in out and not ('Metrowerks' in out or 'Freescale' in out): + cls = c.ArmCCompiler if lang == 'c' else cpp.ArmCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.ArmDynamicLinker(for_machine, version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, + info, exe_wrap, full_version=full_version, linker=linker) + if 'RX Family' in out: + cls = c.CcrxCCompiler if lang == 'c' else cpp.CcrxCPPCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.CcrxDynamicLinker(for_machine, version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Microchip Technology' in out: + cls = c.Xc16CCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.Xc16DynamicLinker(for_machine, version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'CompCert' in out: + cls = c.CompCertCCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.CompCertDynamicLinker(for_machine, version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Metrowerks C/C++' in out or 'Freescale C/C++' in out: + if 'ARM' in out: + cls = c.MetrowerksCCompilerARM if lang == 'c' else cpp.MetrowerksCPPCompilerARM + lnk = linkers.MetrowerksLinkerARM + else: + cls = c.MetrowerksCCompilerEmbeddedPowerPC if lang == 'c' else cpp.MetrowerksCPPCompilerEmbeddedPowerPC + lnk = linkers.MetrowerksLinkerEmbeddedPowerPC + + mwcc_ver_match = re.search(r'Version (\d+)\.(\d+)\.?(\d+)? build (\d+)', out) + assert mwcc_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + compiler_version = '.'.join(x for x in mwcc_ver_match.groups() if x is not None) + + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + ld = env.lookup_binary_entry(for_machine, cls.language + '_ld') + + if ld is not None: + _, o_ld, _ = Popen_safe(ld + ['--version']) + + mwld_ver_match = re.search(r'Version (\d+)\.(\d+)\.?(\d+)? build (\d+)', o_ld) + assert mwld_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + linker_version = '.'.join(x for x in mwld_ver_match.groups() if x is not None) + + linker = lnk(ld, for_machine, version=linker_version) + else: + raise EnvironmentException(f'Failed to detect linker for {cls.id!r} compiler. Please update your cross file(s).') + + return cls( + ccache, compiler, compiler_version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException(f'Unknown compiler {compilers}') + +def detect_c_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + return _detect_c_or_cpp_compiler(env, 'c', for_machine) + +def detect_cpp_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + return _detect_c_or_cpp_compiler(env, 'cpp', for_machine) + +def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from .cuda import CudaCompiler + from ..linkers.linkers import CudaLinker + popen_exceptions = {} + is_cross = env.is_cross_build(for_machine) + compilers, ccache, exe_wrap = _get_compilers(env, 'cuda', for_machine) + info = env.machines[for_machine] + for compiler in compilers: + arg = '--version' + try: + p, out, err = Popen_safe_logged(compiler + [arg], msg='Detecting compiler via') + except OSError as e: + popen_exceptions[join_args(compiler + [arg])] = e + continue + # Example nvcc printout: + # + # nvcc: NVIDIA (R) Cuda compiler driver + # Copyright (c) 2005-2018 NVIDIA Corporation + # Built on Sat_Aug_25_21:08:01_CDT_2018 + # Cuda compilation tools, release 10.0, V10.0.130 + # + # search_version() first finds the "10.0" after "release", + # rather than the more precise "10.0.130" after "V". + # The patch version number is occasionally important; For + # instance, on Linux, + # - CUDA Toolkit 8.0.44 requires NVIDIA Driver 367.48 + # - CUDA Toolkit 8.0.61 requires NVIDIA Driver 375.26 + # Luckily, the "V" also makes it very simple to extract + # the full version: + version = out.strip().rsplit('V', maxsplit=1)[-1] + cpp_compiler = detect_cpp_compiler(env, for_machine) + cls = CudaCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = CudaLinker(compiler, for_machine, CudaCompiler.LINKER_PREFIX, [], version=CudaLinker.parse_version()) + return cls(ccache, compiler, version, for_machine, is_cross, exe_wrap, host_compiler=cpp_compiler, info=info, linker=linker) + raise EnvironmentException(f'Could not find suitable CUDA compiler: "{"; ".join([" ".join(c) for c in compilers])}"') + +def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from . import fortran + from ..linkers import linkers + popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} + compilers, ccache, exe_wrap = _get_compilers(env, 'fortran', for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + cls: T.Type[FortranCompiler] + for compiler in compilers: + for arg in ['--version', '-V']: + try: + p, out, err = Popen_safe_logged(compiler + [arg], msg='Detecting compiler via') + except OSError as e: + popen_exceptions[join_args(compiler + [arg])] = e + continue + + version = search_version(out) + full_version = out.split('\n', 1)[0] + + guess_gcc_or_lcc: T.Optional[str] = None + if 'GNU Fortran' in out: + guess_gcc_or_lcc = 'gcc' + if 'e2k' in out and 'lcc' in out: + guess_gcc_or_lcc = 'lcc' + + if guess_gcc_or_lcc: + defines = _get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[join_args(compiler)] = 'no pre-processor defines' + continue + if guess_gcc_or_lcc == 'lcc': + version = _get_lcc_version_from_defines(defines) + cls = fortran.ElbrusFortranCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, defines, full_version=full_version, linker=linker) + else: + version = _get_gnu_version_from_defines(defines) + cls = fortran.GnuFortranCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, defines, full_version=full_version, linker=linker) + + if 'Arm C/C++/Fortran Compiler' in out: + cls = fortran.ArmLtdFlangFortranCompiler + arm_ver_match = re.search(r'version (\d+)\.(\d+)\.?(\d+)? \(build number (\d+)\)', out) + assert arm_ver_match is not None, 'for mypy' # because mypy *should* be complaining that this could be None + version = '.'.join([x for x in arm_ver_match.groups() if x is not None]) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, linker=linker) + if 'G95' in out: + cls = fortran.G95FortranCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Sun Fortran' in err: + version = search_version(err) + cls = fortran.SunFortranCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Intel(R) Fortran Compiler for applications' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = fortran.IntelLLVMClFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, + target, exe_wrap, linker=linker) + + if 'Intel(R) Visual Fortran' in err or 'Intel(R) Fortran' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = fortran.IntelClFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, + target, exe_wrap, linker=linker) + + if 'ifort (IFORT)' in out: + cls = fortran.IntelFortranCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'ifx (IFORT)' in out or 'ifx (IFX)' in out: + cls = fortran.IntelLLVMFortranCompiler + linker = guess_nix_linker(env, compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'PathScale EKOPath(tm)' in err: + return fortran.PathScaleFortranCompiler( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version) + + if 'PGI Compilers' in out: + cls = fortran.PGIFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.PGIDynamicLinker(compiler, for_machine, + cls.LINKER_PREFIX, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + full_version=full_version, linker=linker) + + if 'NVIDIA Compilers and Tools' in out: + cls = fortran.NvidiaHPC_FortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.PGIDynamicLinker(compiler, for_machine, + cls.LINKER_PREFIX, [], version=version) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + full_version=full_version, linker=linker) + + if 'flang' in out or 'clang' in out: + cls = fortran.FlangFortranCompiler + linker = guess_nix_linker(env, + compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'Open64 Compiler Suite' in err: + cls = fortran.Open64FortranCompiler + linker = guess_nix_linker(env, + compiler, cls, version, for_machine) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + if 'NAG Fortran' in err: + full_version = err.split('\n', 1)[0] + version = full_version.split()[-1] + cls = fortran.NAGFortranCompiler + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = linkers.NAGDynamicLinker( + compiler, for_machine, cls.LINKER_PREFIX, [], + version=version) + return cls( + compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_objc_compiler(env: 'Environment', for_machine: MachineChoice) -> 'Compiler': + return _detect_objc_or_objcpp_compiler(env, 'objc', for_machine) + +def detect_objcpp_compiler(env: 'Environment', for_machine: MachineChoice) -> 'Compiler': + return _detect_objc_or_objcpp_compiler(env, 'objcpp', for_machine) + +def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine: MachineChoice) -> 'Compiler': + from . import objc, objcpp + popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} + compilers, ccache, exe_wrap = _get_compilers(env, lang, for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + comp: T.Union[T.Type[objc.ObjCCompiler], T.Type[objcpp.ObjCPPCompiler]] + + for compiler in compilers: + arg = ['--version'] + try: + p, out, err = Popen_safe_logged(compiler + arg, msg='Detecting compiler via') + except OSError as e: + popen_exceptions[join_args(compiler + arg)] = e + continue + version = search_version(out) + if 'Free Software Foundation' in out: + defines = _get_gnu_compiler_defines(compiler) + if not defines: + popen_exceptions[join_args(compiler)] = 'no pre-processor defines' + continue + version = _get_gnu_version_from_defines(defines) + comp = objc.GnuObjCCompiler if lang == 'objc' else objcpp.GnuObjCPPCompiler + linker = guess_nix_linker(env, compiler, comp, version, for_machine) + return comp( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, defines, linker=linker) + if 'clang' in out: + linker = None + defines = _get_clang_compiler_defines(compiler) + if not defines: + popen_exceptions[join_args(compiler)] = 'no pre-processor defines' + continue + if 'Apple' in out: + comp = objc.AppleClangObjCCompiler if lang == 'objc' else objcpp.AppleClangObjCPPCompiler + else: + comp = objc.ClangObjCCompiler if lang == 'objc' else objcpp.ClangObjCPPCompiler + if 'windows' in out or env.machines[for_machine].is_windows(): + # If we're in a MINGW context this actually will use a gnu style ld + try: + linker = guess_win_linker(env, compiler, comp, version, for_machine) + except MesonException: + pass + + if not linker: + linker = guess_nix_linker(env, compiler, comp, version, for_machine) + return comp( + ccache, compiler, version, for_machine, + is_cross, info, exe_wrap, linker=linker, defines=defines) + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_java_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from .java import JavaCompiler + exelist = env.lookup_binary_entry(for_machine, 'java') + info = env.machines[for_machine] + if exelist is None: + # TODO support fallback + exelist = [defaults['java'][0]] + + try: + p, out, err = Popen_safe_logged(exelist + ['-version'], msg='Detecting compiler via') + except OSError: + raise EnvironmentException('Could not execute Java compiler: {}'.format(join_args(exelist))) + if 'javac' in out or 'javac' in err: + version = search_version(err if 'javac' in err else out) + if not version or version == 'unknown version': + parts = (err if 'javac' in err else out).split() + if len(parts) > 1: + version = parts[1] + comp_class = JavaCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class(exelist, version, for_machine, info) + raise EnvironmentException('Unknown compiler: ' + join_args(exelist)) + +def detect_cs_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from . import cs + compilers, ccache, exe_wrap = _get_compilers(env, 'cs', for_machine) + popen_exceptions = {} + info = env.machines[for_machine] + for comp in compilers: + try: + p, out, err = Popen_safe_logged(comp + ['--version'], msg='Detecting compiler via') + except OSError as e: + popen_exceptions[join_args(comp + ['--version'])] = e + continue + + version = search_version(out) + cls: T.Type[cs.CsCompiler] + if 'Mono' in out: + cls = cs.MonoCompiler + elif "Visual C#" in out: + cls = cs.VisualStudioCsCompiler + else: + continue + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + return cls(comp, version, for_machine, info) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_cython_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + """Search for a cython compiler.""" + from .cython import CythonCompiler + compilers, _, _ = _get_compilers(env, 'cython', MachineChoice.BUILD) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + + popen_exceptions: T.Dict[str, Exception] = {} + for comp in compilers: + try: + _, out, err = Popen_safe_logged(comp + ['-V'], msg='Detecting compiler via') + except OSError as e: + popen_exceptions[join_args(comp + ['-V'])] = e + continue + + version: T.Optional[str] = None + # 3.0 + if 'Cython' in out: + version = search_version(out) + # older + elif 'Cython' in err: + version = search_version(err) + if version is not None: + comp_class = CythonCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class([], comp, version, for_machine, info, is_cross=is_cross) + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_vala_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from .vala import ValaCompiler + exelist = env.lookup_binary_entry(MachineChoice.BUILD, 'vala') + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + if exelist is None: + # TODO support fallback + exelist = [defaults['vala'][0]] + + try: + p, out = Popen_safe_logged(exelist + ['--version'], msg='Detecting compiler via')[0:2] + except OSError: + raise EnvironmentException('Could not execute Vala compiler: {}'.format(join_args(exelist))) + version = search_version(out) + if 'Vala' in out: + comp_class = ValaCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class(exelist, version, for_machine, is_cross, info) + raise EnvironmentException('Unknown compiler: ' + join_args(exelist)) + +def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> RustCompiler: + from . import rust + from ..linkers import linkers + popen_exceptions = {} # type: T.Dict[str, Exception] + compilers, _, exe_wrap = _get_compilers(env, 'rust', for_machine) + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + + cc = detect_c_compiler(env, for_machine) + is_link_exe = isinstance(cc.linker, linkers.VisualStudioLikeLinkerMixin) + override = env.lookup_binary_entry(for_machine, 'rust_ld') + + for compiler in compilers: + arg = ['--version'] + try: + out = Popen_safe_logged(compiler + arg, msg='Detecting compiler via')[1] + except OSError as e: + popen_exceptions[join_args(compiler + arg)] = e + continue + + version = search_version(out) + cls: T.Type[RustCompiler] = rust.RustCompiler + + # Clippy is a wrapper around rustc, but it doesn't have rustc in it's + # output. We can otherwise treat it as rustc. + if 'clippy' in out: + # clippy returns its own version and not the rustc version by + # default so try harder here to get the correct version. + # Also replace the whole output with the rustc output in + # case this is later used for other purposes. + arg = ['--rustc', '--version'] + try: + out = Popen_safe(compiler + arg)[1] + except OSError as e: + popen_exceptions[join_args(compiler + arg)] = e + continue + version = search_version(out) + + cls = rust.ClippyRustCompiler + + if 'rustc' in out: + # On Linux and mac rustc will invoke gcc (clang for mac + # presumably) and it can do this windows, for dynamic linking. + # this means the easiest way to C compiler for dynamic linking. + # figure out what linker to use is to just get the value of the + # C compiler and use that as the basis of the rust linker. + # However, there are two things we need to change, if CC is not + # the default use that, and second add the necessary arguments + # to rust to use -fuse-ld + + if any(a.startswith('linker=') for a in compiler): + mlog.warning( + 'Please do not put -C linker= in your compiler ' + 'command, set rust_ld=command in your cross file ' + 'or use the RUSTC_LD environment variable, otherwise meson ' + 'will override your selection.') + + compiler = compiler.copy() # avoid mutating the original list + + if override is None: + extra_args: T.Dict[str, T.Union[str, bool]] = {} + always_args: T.List[str] = [] + if is_link_exe: + compiler.extend(cls.use_linker_args(cc.linker.exelist[0], '')) + extra_args['direct'] = True + extra_args['machine'] = cc.linker.machine + else: + exelist = cc.linker.exelist + cc.linker.get_always_args() + if os.path.basename(exelist[0]) in {'ccache', 'sccache'}: + del exelist[0] + c = exelist.pop(0) + compiler.extend(cls.use_linker_args(c, '')) + + # Also ensure that we pass any extra arguments to the linker + for l in exelist: + compiler.extend(['-C', f'link-arg={l}']) + + # This trickery with type() gets us the class of the linker + # so we can initialize a new copy for the Rust Compiler + # TODO rewrite this without type: ignore + assert cc.linker is not None, 'for mypy' + if is_link_exe: + linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist, # type: ignore + version=cc.linker.version, **extra_args) # type: ignore + else: + linker = type(cc.linker)(compiler, for_machine, cc.LINKER_PREFIX, + always_args=always_args, version=cc.linker.version, + **extra_args) + elif 'link' in override[0]: + linker = guess_win_linker(env, + override, cls, version, for_machine, use_linker_prefix=False) + # rustc takes linker arguments without a prefix, and + # inserts the correct prefix itself. + assert isinstance(linker, linkers.VisualStudioLikeLinkerMixin) + linker.direct = True + compiler.extend(cls.use_linker_args(linker.exelist[0], '')) + else: + # On linux and macos rust will invoke the c compiler for + # linking, on windows it will use lld-link or link.exe. + # we will simply ask for the C compiler that corresponds to + # it, and use that. + cc = _detect_c_or_cpp_compiler(env, 'c', for_machine, override_compiler=override) + linker = cc.linker + + # Of course, we're not going to use any of that, we just + # need it to get the proper arguments to pass to rustc + c = linker.exelist[1] if linker.exelist[0].endswith('ccache') else linker.exelist[0] + compiler.extend(cls.use_linker_args(c, '')) + + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + return cls( + compiler, version, for_machine, is_cross, info, exe_wrap, + linker=linker) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from . import c, d + info = env.machines[for_machine] + + # Detect the target architecture, required for proper architecture handling on Windows. + # MSVC compiler is required for correct platform detection. + c_compiler = {'c': detect_c_compiler(env, for_machine)} + is_msvc = isinstance(c_compiler['c'], c.VisualStudioCCompiler) + if not is_msvc: + c_compiler = {} + + # Import here to avoid circular imports + from ..environment import detect_cpu_family + arch = detect_cpu_family(c_compiler) + if is_msvc and arch == 'x86': + arch = 'x86_mscoff' + + popen_exceptions = {} + is_cross = env.is_cross_build(for_machine) + compilers, ccache, exe_wrap = _get_compilers(env, 'd', for_machine) + cls: T.Type[d.DCompiler] + for exelist in compilers: + # Search for a D compiler. + # We prefer LDC over GDC unless overridden with the DC + # environment variable because LDC has a much more + # up to date language version at time (2016). + if os.path.basename(exelist[-1]).startswith(('ldmd', 'gdmd')): + raise EnvironmentException( + f'Meson does not support {exelist[-1]} as it is only a DMD frontend for another compiler.' + 'Please provide a valid value for DC or unset it so that Meson can resolve the compiler by itself.') + try: + p, out = Popen_safe(exelist + ['--version'])[0:2] + except OSError as e: + popen_exceptions[join_args(exelist + ['--version'])] = e + continue + version = search_version(out) + full_version = out.split('\n', 1)[0] + + if 'LLVM D compiler' in out: + cls = d.LLVMDCompiler + # LDC seems to require a file + # We cannot use NamedTemporaryFile on windows, its documented + # to not work for our uses. So, just use mkstemp and only have + # one path for simplicity. + o, f = tempfile.mkstemp('.d') + os.close(o) + + try: + if info.is_windows() or info.is_cygwin(): + objfile = os.path.basename(f)[:-1] + 'obj' + linker = guess_win_linker(env, + exelist, + cls, full_version, for_machine, + use_linker_prefix=True, invoked_directly=False, + extra_args=[f]) + else: + # LDC writes an object file to the current working directory. + # Clean it up. + objfile = os.path.basename(f)[:-1] + 'o' + linker = guess_nix_linker(env, + exelist, cls, full_version, for_machine, + extra_args=[f]) + finally: + windows_proof_rm(f) + windows_proof_rm(objfile) + + return cls( + exelist, version, for_machine, info, arch, + full_version=full_version, linker=linker, version_output=out) + elif 'gdc' in out: + cls = d.GnuDCompiler + linker = guess_nix_linker(env, exelist, cls, version, for_machine) + return cls( + exelist, version, for_machine, info, arch, + exe_wrapper=exe_wrap, is_cross=is_cross, + full_version=full_version, linker=linker) + elif 'The D Language Foundation' in out or 'Digital Mars' in out: + cls = d.DmdDCompiler + # DMD seems to require a file + # We cannot use NamedTemporaryFile on windows, its documented + # to not work for our uses. So, just use mkstemp and only have + # one path for simplicity. + o, f = tempfile.mkstemp('.d') + os.close(o) + + # DMD as different detection logic for x86 and x86_64 + arch_arg = '-m64' if arch == 'x86_64' else '-m32' + + try: + if info.is_windows() or info.is_cygwin(): + objfile = os.path.basename(f)[:-1] + 'obj' + linker = guess_win_linker(env, + exelist, cls, full_version, for_machine, + invoked_directly=False, extra_args=[f, arch_arg]) + else: + objfile = os.path.basename(f)[:-1] + 'o' + linker = guess_nix_linker(env, + exelist, cls, full_version, for_machine, + extra_args=[f, arch_arg]) + finally: + windows_proof_rm(f) + windows_proof_rm(objfile) + + return cls( + exelist, version, for_machine, info, arch, + full_version=full_version, linker=linker) + raise EnvironmentException('Unknown compiler: ' + join_args(exelist)) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_swift_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from .swift import SwiftCompiler + exelist = env.lookup_binary_entry(for_machine, 'swift') + is_cross = env.is_cross_build(for_machine) + info = env.machines[for_machine] + if exelist is None: + # TODO support fallback + exelist = [defaults['swift'][0]] + + try: + p, _, err = Popen_safe_logged(exelist + ['-v'], msg='Detecting compiler via') + except OSError: + raise EnvironmentException('Could not execute Swift compiler: {}'.format(join_args(exelist))) + version = search_version(err) + if 'Swift' in err: + # As for 5.0.1 swiftc *requires* a file to check the linker: + with tempfile.NamedTemporaryFile(suffix='.swift') as f: + cls = SwiftCompiler + linker = guess_nix_linker(env, + exelist, cls, version, for_machine, + extra_args=[f.name]) + return cls( + exelist, version, for_machine, is_cross, info, linker=linker) + + raise EnvironmentException('Unknown compiler: ' + join_args(exelist)) + +def detect_nasm_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + from .asm import NasmCompiler, YasmCompiler, MetrowerksAsmCompilerARM, MetrowerksAsmCompilerEmbeddedPowerPC + compilers, _, _ = _get_compilers(env, 'nasm', for_machine) + is_cross = env.is_cross_build(for_machine) + + # We need a C compiler to properly detect the machine info and linker + cc = detect_c_compiler(env, for_machine) + if not is_cross: + from ..environment import detect_machine_info + info = detect_machine_info({'c': cc}) + else: + info = env.machines[for_machine] + + popen_exceptions: T.Dict[str, Exception] = {} + for comp in compilers: + if comp == ['nasm'] and is_windows() and not shutil.which(comp[0]): + # nasm is not in PATH on Windows by default + default_path = os.path.join(os.environ['ProgramFiles'], 'NASM') + comp[0] = shutil.which(comp[0], path=default_path) or comp[0] + try: + output = Popen_safe_logged(comp + ['--version'], msg='Detecting compiler via')[1] + except OSError as e: + popen_exceptions[' '.join(comp + ['--version'])] = e + continue + + version = search_version(output) + if 'NASM' in output: + comp_class = NasmCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + elif 'yasm' in output: + comp_class = YasmCompiler + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + elif 'Metrowerks' in output or 'Freescale' in output: + if 'ARM' in output: + comp_class_mwasmarm = MetrowerksAsmCompilerARM + env.coredata.add_lang_args(comp_class_mwasmarm.language, comp_class_mwasmarm, for_machine, env) + return comp_class_mwasmarm([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + else: + comp_class_mwasmeppc = MetrowerksAsmCompilerEmbeddedPowerPC + env.coredata.add_lang_args(comp_class_mwasmeppc.language, comp_class_mwasmeppc, for_machine, env) + return comp_class_mwasmeppc([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + + _handle_exceptions(popen_exceptions, compilers) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +def detect_masm_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: + # We need a C compiler to properly detect the machine info and linker + is_cross = env.is_cross_build(for_machine) + cc = detect_c_compiler(env, for_machine) + if not is_cross: + from ..environment import detect_machine_info + info = detect_machine_info({'c': cc}) + else: + info = env.machines[for_machine] + + from .asm import MasmCompiler, MasmARMCompiler + comp_class: T.Type[Compiler] + if info.cpu_family == 'x86': + comp = ['ml'] + comp_class = MasmCompiler + arg = '/?' + elif info.cpu_family == 'x86_64': + comp = ['ml64'] + comp_class = MasmCompiler + arg = '/?' + elif info.cpu_family == 'arm': + comp = ['armasm'] + comp_class = MasmARMCompiler + arg = '-h' + elif info.cpu_family == 'aarch64': + comp = ['armasm64'] + comp_class = MasmARMCompiler + arg = '-h' + else: + raise EnvironmentException(f'Platform {info.cpu_family} not supported by MASM') + + popen_exceptions: T.Dict[str, Exception] = {} + try: + output = Popen_safe(comp + [arg])[2] + version = search_version(output) + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + return comp_class([], comp, version, for_machine, info, cc.linker, is_cross=is_cross) + except OSError as e: + popen_exceptions[' '.join(comp + [arg])] = e + _handle_exceptions(popen_exceptions, [comp]) + raise EnvironmentException('Unreachable code (exception to make mypy happy)') + +# GNU/Clang defines and version +# ============================= + +def _get_gnu_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]: + """ + Detect GNU compiler platform type (Apple, MinGW, Unix) + """ + # Arguments to output compiler pre-processor defines to stdout + # gcc, g++, and gfortran all support these arguments + args = compiler + ['-E', '-dM', '-'] + mlog.debug(f'Running command: {join_args(args)}') + p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE) + if p.returncode != 0: + raise EnvironmentException('Unable to detect GNU compiler type:\n' + f'Compiler stdout:\n{output}\n-----\n' + f'Compiler stderr:\n{error}\n-----\n') + # Parse several lines of the type: + # `#define ___SOME_DEF some_value` + # and extract `___SOME_DEF` + defines: T.Dict[str, str] = {} + for line in output.split('\n'): + if not line: + continue + d, *rest = line.split(' ', 2) + if d != '#define': + continue + if len(rest) == 1: + defines[rest[0]] = '' + if len(rest) == 2: + defines[rest[0]] = rest[1] + return defines + +def _get_clang_compiler_defines(compiler: T.List[str]) -> T.Dict[str, str]: + """ + Get the list of Clang pre-processor defines + """ + args = compiler + ['-E', '-dM', '-'] + mlog.debug(f'Running command: {join_args(args)}') + p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE) + if p.returncode != 0: + raise EnvironmentException('Unable to get clang pre-processor defines:\n' + f'Compiler stdout:\n{output}\n-----\n' + f'Compiler stderr:\n{error}\n-----\n') + defines: T.Dict[str, str] = {} + for line in output.split('\n'): + if not line: + continue + d, *rest = line.split(' ', 2) + if d != '#define': + continue + if len(rest) == 1: + defines[rest[0]] = '' + if len(rest) == 2: + defines[rest[0]] = rest[1] + return defines + +def _get_gnu_version_from_defines(defines: T.Dict[str, str]) -> str: + dot = '.' + major = defines.get('__GNUC__', '0') + minor = defines.get('__GNUC_MINOR__', '0') + patch = defines.get('__GNUC_PATCHLEVEL__', '0') + return dot.join((major, minor, patch)) + +def _get_lcc_version_from_defines(defines: T.Dict[str, str]) -> str: + dot = '.' + generation_and_major = defines.get('__LCC__', '100') + generation = generation_and_major[:1] + major = generation_and_major[1:] + minor = defines.get('__LCC_MINOR__', '0') + return dot.join((generation, major, minor)) diff --git a/devtools/meson/mesonbuild/compilers/fortran.py b/devtools/meson/mesonbuild/compilers/fortran.py new file mode 100644 index 0000000..7c836b7 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/fortran.py @@ -0,0 +1,546 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import typing as T +import os + +from .. import coredata +from .compilers import ( + clike_debug_args, + Compiler, +) +from .mixins.clike import CLikeCompiler +from .mixins.gnu import ( + GnuCompiler, gnulike_buildtype_args, gnu_optimization_args +) +from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler +from .mixins.clang import ClangCompiler +from .mixins.elbrus import ElbrusCompiler +from .mixins.pgi import PGICompiler + +from mesonbuild.mesonlib import ( + version_compare, MesonException, + LibType, OptionKey, +) + +if T.TYPE_CHECKING: + from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType + from ..dependencies import Dependency + from ..envconfig import MachineInfo + from ..environment import Environment + from ..linkers.linkers import DynamicLinker + from ..mesonlib import MachineChoice + from ..programs import ExternalProgram + from .compilers import CompileCheckMode + + +class FortranCompiler(CLikeCompiler, Compiler): + + language = 'fortran' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + Compiler.__init__(self, [], exelist, version, for_machine, info, + is_cross=is_cross, full_version=full_version, linker=linker) + CLikeCompiler.__init__(self, exe_wrapper) + + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + raise MesonException('Fortran does not have "has_function" capability.\n' + 'It is better to test if a Fortran capability is working like:\n\n' + "meson.get_compiler('fortran').links('block; end block; end program')\n\n" + 'that example is to see if the compiler has Fortran 2008 Block element.') + + def _get_basic_compiler_args(self, env: 'Environment', mode: CompileCheckMode) -> T.Tuple[T.List[str], T.List[str]]: + cargs = env.coredata.get_external_args(self.for_machine, self.language) + largs = env.coredata.get_external_link_args(self.for_machine, self.language) + return cargs, largs + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + source_name = 'sanitycheckf.f90' + code = 'program main; print *, "Fortran compilation is working."; end program\n' + return self._sanity_check_impl(work_dir, environment, source_name, code) + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return gnulike_buildtype_args[buildtype] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return gnu_optimization_args[optimization_level] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return clike_debug_args[is_debug] + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-cpp'] + super().get_preprocess_only_args() + + def get_module_incdir_args(self) -> T.Tuple[str, ...]: + return ('-I', ) + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-module', path] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I' or i[:2] == '-L': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + + return parameter_list + + def module_name_to_filename(self, module_name: str) -> str: + if '_' in module_name: # submodule + s = module_name.lower() + if self.id in {'gcc', 'intel', 'intel-cl'}: + filename = s.replace('_', '@') + '.smod' + elif self.id in {'pgi', 'flang'}: + filename = s.replace('_', '-') + '.mod' + else: + filename = s + '.mod' + else: # module + filename = module_name.lower() + '.mod' + + return filename + + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: + code = 'stop; end program' + return self._find_library_impl(libname, env, extra_dirs, code, libtype, lib_prefix_warning) + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_arguments(args, env, 'stop; end program') + + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_link_arguments(args, env, 'stop; end program') + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = super().get_options() + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts.update({ + key: coredata.UserComboOption( + 'Fortran language standard to use', + ['none'], + 'none', + ), + }) + return opts + + +class GnuFortranCompiler(GnuCompiler, FortranCompiler): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + GnuCompiler.__init__(self, defines) + default_warn_args = ['-Wall'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-Wpedantic', '-fimplicit-none'], + 'everything': default_warn_args + ['-Wextra', '-Wpedantic', '-fimplicit-none']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = FortranCompiler.get_options(self) + fortran_stds = ['legacy', 'f95', 'f2003'] + if version_compare(self.version, '>=4.4.0'): + fortran_stds += ['f2008'] + if version_compare(self.version, '>=8.0.0'): + fortran_stds += ['f2018'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + fortran_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + if std.value != 'none': + args.append('-std=' + std.value) + return args + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + # Disabled until this is fixed: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162 + # return ['-cpp', '-MD', '-MQ', outtarget] + return [] + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-J' + path] + + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + # We need to apply the search prefix here, as these link arguments may + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + search_dirs: T.List[str] = [] + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') + return search_dirs + ['-lgfortran', '-lm'] + + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + ''' + Derived from mixins/clike.py:has_header, but without C-style usage of + __has_include which breaks with GCC-Fortran 10: + https://github.com/mesonbuild/meson/issues/7017 + ''' + code = f'{prefix}\n#include <{hname}>' + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode='preprocess', disable_cache=disable_cache) + + +class ElbrusFortranCompiler(ElbrusCompiler, FortranCompiler): + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + defines: T.Optional[T.Dict[str, str]] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + ElbrusCompiler.__init__(self) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = FortranCompiler.get_options(self) + fortran_stds = ['f95', 'f2003', 'f2008', 'gnu', 'legacy', 'f2008ts'] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + fortran_stds + return opts + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-J' + path] + + +class G95FortranCompiler(FortranCompiler): + + LINKER_PREFIX = '-Wl,' + id = 'g95' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + default_warn_args = ['-Wall'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-Wextra'], + '3': default_warn_args + ['-Wextra', '-pedantic'], + 'everything': default_warn_args + ['-Wextra', '-pedantic']} + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-fmod=' + path] + + def get_no_warn_args(self) -> T.List[str]: + # FIXME: Confirm that there's no compiler option to disable all warnings + return [] + + +class SunFortranCompiler(FortranCompiler): + + LINKER_PREFIX = '-Wl,' + id = 'sun' + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['-fpp'] + + def get_always_args(self) -> T.List[str]: + return [] + + def get_warn_args(self, level: str) -> T.List[str]: + return [] + + def get_module_incdir_args(self) -> T.Tuple[str, ...]: + return ('-M', ) + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-moddir=' + path] + + def openmp_flags(self) -> T.List[str]: + return ['-xopenmp'] + + +class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): + + file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp', ) + id = 'intel' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + # FIXME: Add support for OS X and Windows in detect_fortran_compiler so + # we are sent the type of compiler + IntelGnuLikeCompiler.__init__(self) + default_warn_args = ['-warn', 'general', '-warn', 'truncated_source'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['-warn', 'unused'], + '3': ['-warn', 'all'], + 'everything': ['-warn', 'all']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = FortranCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'} + if std.value != 'none': + args.append('-stand=' + stds[std.value]) + return args + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-cpp', '-EP'] + + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + # TODO: needs default search path added + return ['-lifcore', '-limf'] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['-gen-dep=' + outtarget, '-gen-depformat=make'] + + +class IntelLLVMFortranCompiler(IntelFortranCompiler): + + id = 'intel-llvm' + + +class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): + + file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp', ) + always_args = ['/nologo'] + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', target: str, + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + IntelVisualStudioLikeCompiler.__init__(self, target) + + default_warn_args = ['/warn:general', '/warn:truncated_source'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['/warn:unused'], + '3': ['/warn:all'], + 'everything': ['/warn:all']} + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = FortranCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + key = OptionKey('std', machine=self.for_machine, lang=self.language) + std = options[key] + stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'} + if std.value != 'none': + args.append('/stand:' + stds[std.value]) + return args + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['/module:' + path] + + +class IntelLLVMClFortranCompiler(IntelClFortranCompiler): + + id = 'intel-llvm-cl' + +class PathScaleFortranCompiler(FortranCompiler): + + id = 'pathscale' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + default_warn_args = ['-fullwarn'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args, + 'everything': default_warn_args} + + def openmp_flags(self) -> T.List[str]: + return ['-mp'] + + +class PGIFortranCompiler(PGICompiler, FortranCompiler): + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + PGICompiler.__init__(self) + + default_warn_args = ['-Minform=inform'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args + ['-Mdclchk'], + 'everything': default_warn_args + ['-Mdclchk']} + + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + # TODO: needs default search path added + return ['-lpgf90rtl', '-lpgf90', '-lpgf90_rpm1', '-lpgf902', + '-lpgf90rtl', '-lpgftnrtl', '-lrt'] + + +class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler): + + id = 'nvidia_hpc' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + PGICompiler.__init__(self) + + default_warn_args = ['-Minform=inform'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args + ['-Mdclchk'], + 'everything': default_warn_args + ['-Mdclchk']} + + +class FlangFortranCompiler(ClangCompiler, FortranCompiler): + + id = 'flang' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + ClangCompiler.__init__(self, {}) + default_warn_args = ['-Minform=inform'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args, + 'everything': default_warn_args} + + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: + # We need to apply the search prefix here, as these link arguments may + # be passed to a different compiler with a different set of default + # search paths, such as when using Clang for C/C++ and gfortran for + # fortran, + # XXX: Untested.... + search_dirs: T.List[str] = [] + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') + return search_dirs + ['-lflang', '-lpgmath'] + +class ArmLtdFlangFortranCompiler(FlangFortranCompiler): + + id = 'armltdflang' + +class Open64FortranCompiler(FortranCompiler): + + id = 'open64' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + default_warn_args = ['-fullwarn'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args, + '3': default_warn_args, + 'everything': default_warn_args} + + def openmp_flags(self) -> T.List[str]: + return ['-mp'] + + +class NAGFortranCompiler(FortranCompiler): + + id = 'nagfor' + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, + info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + FortranCompiler.__init__(self, exelist, version, for_machine, + is_cross, info, exe_wrapper, linker=linker, + full_version=full_version) + # Warnings are on by default; -w disables (by category): + self.warn_args = { + '0': ['-w=all'], + '1': [], + '2': [], + '3': [], + 'everything': [], + } + + def get_always_args(self) -> T.List[str]: + return self.get_nagfor_quiet(self.version) + + def get_module_outdir_args(self, path: str) -> T.List[str]: + return ['-mdir', path] + + @staticmethod + def get_nagfor_quiet(version: str) -> T.List[str]: + return ['-quiet'] if version_compare(version, '>=7100') else [] + + def get_pic_args(self) -> T.List[str]: + return ['-PIC'] + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-fpp'] + + def get_std_exe_link_args(self) -> T.List[str]: + return self.get_always_args() + + def openmp_flags(self) -> T.List[str]: + return ['-openmp'] diff --git a/devtools/meson/mesonbuild/compilers/java.py b/devtools/meson/mesonbuild/compilers/java.py new file mode 100644 index 0000000..9f508d6 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/java.py @@ -0,0 +1,125 @@ +# Copyright 2012-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import os.path +import shutil +import subprocess +import textwrap +import typing as T + +from ..mesonlib import EnvironmentException +from .compilers import Compiler, java_buildtype_args +from .mixins.islinker import BasicLinkerIsCompilerMixin + +if T.TYPE_CHECKING: + from ..envconfig import MachineInfo + from ..environment import Environment + from ..mesonlib import MachineChoice + +class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler): + + language = 'java' + id = 'unknown' + + _WARNING_LEVELS: T.Dict[str, T.List[str]] = { + '0': ['-nowarn'], + '1': ['-Xlint:all'], + '2': ['-Xlint:all', '-Xdoclint:all'], + '3': ['-Xlint:all', '-Xdoclint:all'], + } + + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, + info: 'MachineInfo', full_version: T.Optional[str] = None): + super().__init__([], exelist, version, for_machine, info, full_version=full_version) + self.javarunner = 'java' + + def get_warn_args(self, level: str) -> T.List[str]: + return self._WARNING_LEVELS[level] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_no_warn_args(self) -> T.List[str]: + return ['-nowarn'] + + def get_output_args(self, outputname: str) -> T.List[str]: + if outputname == '': + outputname = './' + return ['-d', outputname, '-s', outputname] + + def get_pic_args(self) -> T.List[str]: + return [] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return [] + + def get_pch_name(self, name: str) -> str: + return '' + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return java_buildtype_args[buildtype] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], + build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i in {'-cp', '-classpath', '-sourcepath'} and idx + 1 < len(parameter_list): + path_list = parameter_list[idx + 1].split(os.pathsep) + path_list = [os.path.normpath(os.path.join(build_dir, x)) for x in path_list] + parameter_list[idx + 1] = os.pathsep.join(path_list) + + return parameter_list + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + src = 'SanityCheck.java' + obj = 'SanityCheck' + source_name = os.path.join(work_dir, src) + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent( + '''class SanityCheck { + public static void main(String[] args) { + int i; + } + } + ''')) + pc = subprocess.Popen(self.exelist + [src], cwd=work_dir) + pc.wait() + if pc.returncode != 0: + raise EnvironmentException(f'Java compiler {self.name_string()} cannot compile programs.') + runner = shutil.which(self.javarunner) + if runner: + cmdlist = [runner, '-cp', '.', obj] + pe = subprocess.Popen(cmdlist, cwd=work_dir) + pe.wait() + if pe.returncode != 0: + raise EnvironmentException(f'Executables created by Java compiler {self.name_string()} are not runnable.') + else: + m = "Java Virtual Machine wasn't found, but it's needed by Meson. " \ + "Please install a JRE.\nIf you have specific needs where this " \ + "requirement doesn't make sense, please open a bug at " \ + "https://github.com/mesonbuild/meson/issues/new and tell us " \ + "all about it." + raise EnvironmentException(m) + + def needs_static_linker(self) -> bool: + return False + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return [] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + return ['-g'] + return ['-g:none'] diff --git a/devtools/meson/mesonbuild/compilers/mixins/__init__.py b/devtools/meson/mesonbuild/compilers/mixins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d22dfd6519da1fece1f66db664e5b332ea4b6f3a GIT binary patch literal 168 zcmZ?b<>g`kf;}G&r-A6lAOZ#$feZ&AE@lA|DGb33nv8xc8Hzx{2;x_ui&acYYFSKr zeojhpQF2U1j$ur3N_ISm4HPfQ&(A52$xSWJ&x4RjrI|S?G0FM41(`XiML?;{ip;#? gnE3e2yv&mLc)fzkTO2mI`6;D2sdgZ%J_9iW0K1AV%K!iX literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/arm.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/arm.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59e3066d1a439dc0b45943e68122e1da3d0bb7e0 GIT binary patch literal 6400 zcmd5=&5s;M74NV4o}Hat?|QwCKPI-ZGmu?kCn6*`CeE&t7~5;)7!boot)8jcnO^tD zrn<-3ZLL9y6Nwv$3kQs_PY4MK3Bd`3gy0Y0TvtxMan6a~tDdi&nN1wv!1VO%`gm3K z`qiuVey`t}nJH@c{rO*i+xp2#P5UQR`oBC1Z)#O7GIUL28q+<^*BiP{Wy3QXhI*O} zi61uCX}e zM<0ziN-ceUwg5ijUF`8My`!X5$#@$JjFJ%c{Q2jQ6zq@u#Gjx-Lsj z5QMQ4yI~M*JT=qCyw9UB@Z2UC7Ox6_&2xhG`d;ApZtJES+~Wcrh1)wc>IUC?YNW%e zEziBjZN{73w(W>^^c2dbMbLo>>{jT7LUqu>*Mj@52m_x7F{=5s(BE-A%$${(9nWzC znNbtTih6`t%y$#cWKM98I}w*T-wh%($!x0|#i5^=E4N=tjFmPOE)sb;$*$bSI9|_* z8HghFm!#g7`bDWz5 z$iNsZ)bgx=T9y@2FFi6?na!Y{>-ARHENXf5Qh)W4Nt=uo7>{Z>f|dogh!(2Te6)pD zqlB%?v1QD6oIQtnxi{Ylb`rH2HTD#GPqP~874|&(&!B#mokM*VHCpdWnEgDvfR-wI z0h?c!CEC=U!jsqD?glN|O2>2Ky;|IH;+h-PTA}ZUK`jnzj_1{`-nmuV!v1@E)S-4N zT9u|Fd}(cj0ml|*1&_NTXwjzAkE|k#dyUTB1`7MywiZ=m{V`PeME?l3{s8yBz7M*D z=a4evQD$GWO^mP}XPEf}C$(3$sLV9HMrI>9kM&!vTGZXy2}K;$V6>1=gi*ATN~sKc zwVn}2u)bI%a+Jsth%EB^Tiz};_g%2GO zC|i~bEhm6&E2Y>`cWcYtNlD=kJ&%Hx&HblrZU>&F!Z8LbsSUL?7AM?9Bjd+@9yFhY(fvKJ9{#3+iu{-wtWY4 zM++dDp4E%Gr5m`ixGF|jPZmbDf3-g(DcxPY=|=GnqFB5?*hJb)y45CT1~c0k zY?`%^%&x33zQY4%r!yt_enYa*FWC{!gU4;p4S2fCW~$1sVoLE65whHo{a&J%O6TQ4 zYtL@;^ki&)=gqa1exbZl>VPCMEk2&5l8rK3!TtKk`(!W?O!6~f~>?Nt3g z8d>w?xDpO<;>G8C06;l(+k@x!CiOsW;t&_H=)grBn1cXHy{Dhor|4&q1fCf2(TLE` zj|)A)Ev+UTIK-!zqHxR?5n7O^>x+10iipaphH&eX5!oiJYRHCTR@rfcg(G3-`zAGm=COd3(#5r#8?K9zGp<2M(XB0LllSg zSl>1tn~GZd2HJtDXxtOyiB92v-@L4SQ2ZWB%2|mV)&rcoj{9akBMUs}`mmmuOCyY= zwd2GcnGZtYtCF=Hx&Z>c3P^8asJIFuO_%LT-5qyX=P81AV{Q)=5!oNQamRL=QRt-| zaVPpQrif@4G<{yL>6eV;(&(N)+aw$HISR}`&)l|U(YF1Nb>U!bS+?yDx{lZD$=Nmw zTWB_1CSJgrqE2Lm$SRSGL|!5CH6mXp@*0uLM7~MnI+3A!9ymX-jEEa)E zc~{7S z$Sr>fRQr*R)*RaM%u+r1B^-z7j^fQwKg+Tla<}}t_D}~RE`Y1}xWo!QL`>!401=lq zl6qg@&jrQFk?#aO;LKSqP3vmO+>13I*;K8`Nfp2V_Y&icHizNqJ#{8OGd{51OU)J<&Y~Y4(^y5W z7LM35#qduHmm?n2vAgmsR28_$>dA{&$98uBYF96NVaxHNE31Qn^}Nh92?x-_i$hgw zhqBnTBM0D_GD?*D0Z8VXcA%W6EP;bkY(Rnd7@$`QF){N>vKs2;{ZB23c+*%~c@?$+|u{|w-ogIEx7v7^vqNdl|mjSt(#&9vXx3`kLX8F3foF0lu|Ps@ogmhi0;~Bb03lZiP5GHP{u}5UU7q# z*JXSKQ`arA27a+lq6&C-9Lb|C|LfC9lbMy{<^p7cr z8O_974BUE}NFj~V8RYLLQs&C7b$m9ub(hH7%HH}S4ksNGk;3<%1|sUo3sXg$mKPa9 z0n{&IeaD@?^-X}%z5z}Fy$VVEWkkmFQ)Qf(QoMmNm{)<+FCgaUAzTG&{yHMhbkiKg zw&G2&EA01w3uVPyB;wHAuThn3egeLVcc|-KB4frxK=1Fk52DjoC${TZA?mF77OirF z2;oF=iwJ$S8-b!NswzCH0H}hZ3Y1=^j?V_5x54sL+!48jyr}?awUQyo2?&~U(I}%IkRq>E2~zQL1DulfKoZSKc!4?T#+`dRIiP Ne^F1r&q7ai{omh>|DON= literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/ccrx.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/ccrx.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e0bb39ad44f5edbe5faec5fb36919b166d854e1 GIT binary patch literal 3890 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 G#(x1b{u}rJ literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/clike.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/clike.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb0ae83747c0128a4d6ad03f1511f65480bad11e GIT binary patch literal 41868 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/compcert.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/compcert.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf148307bc846de2e0f289ec084dbdcf34b1f16e GIT binary patch literal 4273 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/pgi.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/pgi.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..014e06906a529a09ebdd09dd96a0273ebe4d95f9 GIT binary patch literal 3641 zcmb7HOLH5?5#E_yyg?9zWXrN_nUZYDuuUeSQ$D0*M+vRSEGx7sW?l%Ltp#QPEVVDs zE+`U3o#b5e2clG2$NUH1@-OC^s#NKgb58ks761W|QYAp4cY3F1=9}(sdK$l2S*cq1 z{P6F8^w(A`>z|}dKP5EoT1_kc3mU=_EU-e>VT{^5;2qmMosNU29TdW1r-(jB6oOJ% z?v%qyrvkkwN zQ4{s=EK!%ur*`Lp;9pzql^2Av&2-I+qB!$1KaSE}=*~kg8@}Mw$#t_A_>ZJ3WOp=h zJvB)6rTk5tWPa$6%`nsP!p^6we1)Dk`cfX#-1nkGU&T=htSu=M~K^ou06cJGj*i4lYy_D-8ho)Z&Ar?q@o_1IEaE+#BZB8 z_&ypLIQWze*@@*c!3XRK8(1eS{{l+^@42wBinFT=T{r0s$EzE^@}qvN!cX%@yP(;R zHM_0ZmS!L8syvkHI2-!Wplz!%*3k7X0_RdJ!6;pM?5W5w1axvz8T9pCVs&2RoaNu~#W_!IPL0R)z0JK*639QMnfhktOY$lG zj4z3Jg27K5CuUsQ2xBn>2u}?cV9gw~7&?0+OkNeXdYs58Ox%9p4blg+@`OhVtIiu?Qx$V! zvg72OK+W7kr#M4ixSR(IiKT@T<<5pqPIDf;4`I9 z_F;n{p5D8^nZx$xGPYB*wyhh9r*IH6sX*K`n}pm&#>w%~Jxw11K&6X05koYNx)k)M z>~rgz-|q7#_7mrX3KRBcei`M;Bc5)}>GmV8s;7F!4*2)Bkh7oP*ep+J&5OA7iNc z352$Naip2Q?75qCAB-~T&K!}tkNs@udfhY*@{Vkn{vK1LM0Ja`*gD%{;;d#g)bIO8 z-fUq$K0~fkGmxu98mOd;L+J^*L@C-g(aKQjGc51g-!>r53=*wuC~NsyB_ulos9-=}-ym8g( za^OXSkvEX)UG%q|oHlpSRzIf!_E4y0&X_xp_BKN4Lb*V~GOa^cyv3?07^Q1WES`DXFHMZ@G1hqdx9ShisHmQrauTWoV zwx>QJy+lcYssa=L%B=iT#66Syb=ee&WJ4!huk8Kd;XQZzi+kH&?(E*zHN<85w?tK7 z(77<1WOLS1lpS?3?jFcqraq#%X*Y8_G#g$gtMZ+^w)>2#%#>c$oiZz<+-y?G$?B|8 MbnI#2$ywR?FUHb-4FCWD literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/__pycache__/ti.cpython-37.pyc b/devtools/meson/mesonbuild/compilers/mixins/__pycache__/ti.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b47b2d272a5d11589ae3c78e2d390738550d165c GIT binary patch literal 4899 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 Q^yFO|AIsz^Ldv`U1y#Vj7ytkO literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/compilers/mixins/arm.py b/devtools/meson/mesonbuild/compilers/mixins/arm.py new file mode 100644 index 0000000..7c53327 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/mixins/arm.py @@ -0,0 +1,201 @@ +# Copyright 2012-2020 Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Representations specific to the arm family of compilers.""" + +import os +import typing as T + +from ... import mesonlib +from ...linkers.linkers import ArmClangDynamicLinker +from ...mesonlib import OptionKey +from ..compilers import clike_debug_args +from .clang import clang_color_args + +if T.TYPE_CHECKING: + from ...environment import Environment + from ...compilers.compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + +arm_buildtype_args = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], +} # type: T.Dict[str, T.List[str]] + +arm_optimization_args = { + 'plain': [], + '0': ['-O0'], + 'g': ['-g'], + '1': ['-O1'], + '2': [], # Compiler defaults to -O2 + '3': ['-O3', '-Otime'], + 's': ['-O3'], # Compiler defaults to -Ospace +} # type: T.Dict[str, T.List[str]] + +armclang_buildtype_args = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], +} # type: T.Dict[str, T.List[str]] + +armclang_optimization_args = { + 'plain': [], + '0': [], # Compiler defaults to -O0 + 'g': ['-g'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Oz'] +} # type: T.Dict[str, T.List[str]] + + +class ArmCompiler(Compiler): + + """Functionality that is common to all ARM family compilers.""" + + id = 'arm' + + def __init__(self) -> None: + if not self.is_cross: + raise mesonlib.EnvironmentException('armcc supports only cross-compilation.') + default_warn_args = [] # type: T.List[str] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + [], + '3': default_warn_args + [], + 'everything': default_warn_args + []} # type: T.Dict[str, T.List[str]] + # Assembly + self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') + + def get_pic_args(self) -> T.List[str]: + # FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return arm_buildtype_args[buildtype] + + # Override CCompiler.get_always_args + def get_always_args(self) -> T.List[str]: + return [] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['--depend_target', outtarget, '--depend', outfile, '--depend_single_line'] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + # FIXME: Add required arguments + # NOTE from armcc user guide: + # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05 + # onwards on all platforms. Note that ARM Compiler on Windows 8 never supported + # PCH files." + return [] + + def get_pch_suffix(self) -> str: + # NOTE from armcc user guide: + # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05 + # onwards on all platforms. Note that ARM Compiler on Windows 8 never supported + # PCH files." + return 'pch' + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def get_coverage_args(self) -> T.List[str]: + return [] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return arm_optimization_args[optimization_level] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return clike_debug_args[is_debug] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I' or i[:2] == '-L': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + + return parameter_list + + +class ArmclangCompiler(Compiler): + ''' + This is the Keil armclang. + ''' + + id = 'armclang' + + def __init__(self) -> None: + if not self.is_cross: + raise mesonlib.EnvironmentException('armclang supports only cross-compilation.') + # Check whether 'armlink' is available in path + if not isinstance(self.linker, ArmClangDynamicLinker): + raise mesonlib.EnvironmentException(f'Unsupported Linker {self.linker.exelist}, must be armlink') + if not mesonlib.version_compare(self.version, '==' + self.linker.version): + raise mesonlib.EnvironmentException('armlink version does not match with compiler version') + self.base_options = { + OptionKey(o) for o in + ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', + 'b_ndebug', 'b_staticpic', 'b_colorout']} + # Assembly + self.can_compile_suffixes.add('s') + self.can_compile_suffixes.add('sx') + + def get_pic_args(self) -> T.List[str]: + # PIC support is not enabled by default for ARM, + # if users want to use it, they need to add the required arguments explicitly + return [] + + def get_colorout_args(self, colortype: str) -> T.List[str]: + return clang_color_args[colortype][:] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return armclang_buildtype_args[buildtype] + + def get_pch_suffix(self) -> str: + return 'gch' + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136 + # This flag is internal to Clang (or at least not documented on the man page) + # so it might change semantics at any time. + return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + return ['-MD', '-MT', outtarget, '-MF', outfile] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return armclang_optimization_args[optimization_level] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return clike_debug_args[is_debug] + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I' or i[:2] == '-L': + parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) + + return parameter_list diff --git a/devtools/meson/mesonbuild/compilers/mixins/ccrx.py b/devtools/meson/mesonbuild/compilers/mixins/ccrx.py new file mode 100644 index 0000000..1c22214 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/mixins/ccrx.py @@ -0,0 +1,134 @@ +# Copyright 2012-2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Representations specific to the Renesas CC-RX compiler family.""" + +import os +import typing as T + +from ...mesonlib import EnvironmentException + +if T.TYPE_CHECKING: + from ...envconfig import MachineInfo + from ...environment import Environment + from ...compilers.compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + +ccrx_buildtype_args = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], +} # type: T.Dict[str, T.List[str]] + +ccrx_optimization_args = { + '0': ['-optimize=0'], + 'g': ['-optimize=0'], + '1': ['-optimize=1'], + '2': ['-optimize=2'], + '3': ['-optimize=max'], + 's': ['-optimize=2', '-size'] +} # type: T.Dict[str, T.List[str]] + +ccrx_debug_args = { + False: [], + True: ['-debug'] +} # type: T.Dict[bool, T.List[str]] + + +class CcrxCompiler(Compiler): + + if T.TYPE_CHECKING: + is_cross = True + can_compile_suffixes = set() # type: T.Set[str] + + id = 'ccrx' + + def __init__(self) -> None: + if not self.is_cross: + raise EnvironmentException('ccrx supports only cross-compilation.') + # Assembly + self.can_compile_suffixes.add('src') + default_warn_args = [] # type: T.List[str] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + [], + '3': default_warn_args + [], + 'everything': default_warn_args + []} # type: T.Dict[str, T.List[str]] + + def get_pic_args(self) -> T.List[str]: + # PIC support is not enabled by default for CCRX, + # if users want to use it, they need to add the required arguments explicitly + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return ccrx_buildtype_args[buildtype] + + def get_pch_suffix(self) -> str: + return 'pch' + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return [] + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def get_coverage_args(self) -> T.List[str]: + return [] + + def get_no_stdinc_args(self) -> T.List[str]: + return [] + + def get_no_stdlib_link_args(self) -> T.List[str]: + return [] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return ccrx_optimization_args[optimization_level] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return ccrx_debug_args[is_debug] + + @classmethod + def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]: + result = [] + for i in args: + if i.startswith('-D'): + i = '-define=' + i[2:] + if i.startswith('-I'): + i = '-include=' + i[2:] + if i.startswith('-Wl,-rpath='): + continue + elif i == '--print-search-dirs': + continue + elif i.startswith('-L'): + continue + elif not i.startswith('-lib=') and i.endswith(('.a', '.lib')): + i = '-lib=' + i + result.append(i) + return result + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:9] == '-include=': + parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:])) + + return parameter_list diff --git a/devtools/meson/mesonbuild/compilers/mixins/clang.py b/devtools/meson/mesonbuild/compilers/mixins/clang.py new file mode 100644 index 0000000..b43b246 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/mixins/clang.py @@ -0,0 +1,180 @@ +# Copyright 2019-2022 The meson development team +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Abstractions for the LLVM/Clang compiler family.""" + +import os +import shutil +import typing as T + +from ... import mesonlib +from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ + MoldDynamicLinker +from ...mesonlib import OptionKey +from ..compilers import CompileCheckMode +from .gnu import GnuLikeCompiler + +if T.TYPE_CHECKING: + from ...environment import Environment + from ...dependencies import Dependency # noqa: F401 + +clang_color_args = { + 'auto': ['-fcolor-diagnostics'], + 'always': ['-fcolor-diagnostics'], + 'never': ['-fno-color-diagnostics'], +} # type: T.Dict[str, T.List[str]] + +clang_optimization_args = { + 'plain': [], + '0': ['-O0'], + 'g': ['-Og'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Oz'], +} # type: T.Dict[str, T.List[str]] + +class ClangCompiler(GnuLikeCompiler): + + id = 'clang' + + def __init__(self, defines: T.Optional[T.Dict[str, str]]): + super().__init__() + self.defines = defines or {} + self.base_options.update( + {OptionKey('b_colorout'), OptionKey('b_lto_threads'), OptionKey('b_lto_mode'), OptionKey('b_thinlto_cache'), + OptionKey('b_thinlto_cache_dir')}) + + # TODO: this really should be part of the linker base_options, but + # linkers don't have base_options. + if isinstance(self.linker, AppleDynamicLinker): + self.base_options.add(OptionKey('b_bitcode')) + # All Clang backends can also do LLVM IR + self.can_compile_suffixes.add('ll') + + def get_colorout_args(self, colortype: str) -> T.List[str]: + return clang_color_args[colortype][:] + + def has_builtin_define(self, define: str) -> bool: + return define in self.defines + + def get_builtin_define(self, define: str) -> T.Optional[str]: + return self.defines.get(define) + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return clang_optimization_args[optimization_level] + + def get_pch_suffix(self) -> str: + return 'pch' + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136 + # This flag is internal to Clang (or at least not documented on the man page) + # so it might change semantics at any time. + return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # Clang is different than GCC, it will return True when a symbol isn't + # defined in a header. Specifically this seems to have something to do + # with functions that may be in a header on some systems, but not all of + # them. `strlcat` specifically with can trigger this. + myargs: T.List[str] = ['-Werror=implicit-function-declaration'] + if mode is CompileCheckMode.COMPILE: + myargs.extend(['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument']) + if mesonlib.version_compare(self.version, '>=3.6.0'): + myargs.append('-Werror=ignored-optimization-argument') + return super().get_compiler_check_args(mode) + myargs + + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + if extra_args is None: + extra_args = [] + # Starting with XCode 8, we need to pass this to force linker + # visibility to obey OS X/iOS/tvOS minimum version targets with + # -mmacosx-version-min, -miphoneos-version-min, -mtvos-version-min etc. + # https://github.com/Homebrew/homebrew-core/issues/3727 + # TODO: this really should be communicated by the linker + if isinstance(self.linker, AppleDynamicLinker) and mesonlib.version_compare(self.version, '>=8.0'): + extra_args.append('-Wl,-no_weak_imports') + return super().has_function(funcname, prefix, env, extra_args=extra_args, + dependencies=dependencies) + + def openmp_flags(self) -> T.List[str]: + if mesonlib.version_compare(self.version, '>=3.8.0'): + return ['-fopenmp'] + elif mesonlib.version_compare(self.version, '>=3.7.0'): + return ['-fopenmp=libomp'] + else: + # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency. + return [] + + @classmethod + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: + # Clang additionally can use a linker specified as a path, which GCC + # (and other gcc-like compilers) cannot. This is because clang (being + # llvm based) is retargetable, while GCC is not. + # + + # qcld: Qualcomm Snapdragon linker, based on LLVM + if linker == 'qcld': + return ['-fuse-ld=qcld'] + if linker == 'mold': + return ['-fuse-ld=mold'] + + if shutil.which(linker): + if not shutil.which(linker): + raise mesonlib.MesonException( + f'Cannot find linker {linker}.') + return [f'-fuse-ld={linker}'] + return super().use_linker_args(linker, version) + + def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: + # Clang only warns about unknown or ignored attributes, so force an + # error. + return ['-Werror=attributes'] + + def get_coverage_link_args(self) -> T.List[str]: + return ['--coverage'] + + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + args: T.List[str] = [] + if mode == 'thin': + # ThinLTO requires the use of gold, lld, ld64, lld-link or mold 1.1+ + if isinstance(self.linker, (MoldDynamicLinker)): + # https://github.com/rui314/mold/commit/46995bcfc3e3113133620bf16445c5f13cd76a18 + if not mesonlib.version_compare(self.linker.version, '>=1.1'): + raise mesonlib.MesonException("LLVM's ThinLTO requires mold 1.1+") + elif not isinstance(self.linker, (AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker)): + raise mesonlib.MesonException(f"LLVM's ThinLTO only works with gold, lld, lld-link, ld64 or mold, not {self.linker.id}") + args.append(f'-flto={mode}') + else: + assert mode == 'default', 'someone forgot to wire something up' + args.extend(super().get_lto_compile_args(threads=threads)) + return args + + def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default', + thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]: + args = self.get_lto_compile_args(threads=threads, mode=mode) + if mode == 'thin' and thinlto_cache_dir is not None: + # We check for ThinLTO linker support above in get_lto_compile_args, and all of them support + # get_thinlto_cache_args as well + args.extend(self.linker.get_thinlto_cache_args(thinlto_cache_dir)) + # In clang -flto-jobs=0 means auto, and is the default if unspecified, just like in meson + if threads > 0: + if not mesonlib.version_compare(self.version, '>=4.0.0'): + raise mesonlib.MesonException('clang support for LTO threads requires clang >=4.0') + args.append(f'-flto-jobs={threads}') + return args diff --git a/devtools/meson/mesonbuild/compilers/mixins/clike.py b/devtools/meson/mesonbuild/compilers/mixins/clike.py new file mode 100644 index 0000000..db13e84 --- /dev/null +++ b/devtools/meson/mesonbuild/compilers/mixins/clike.py @@ -0,0 +1,1356 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +"""Mixin classes to be shared between C and C++ compilers. + +Without this we'll end up with awful diamond inheritance problems. The goal +of this is to have mixin's, which are classes that are designed *not* to be +standalone, they only work through inheritance. +""" + +import collections +import functools +import glob +import itertools +import os +import re +import subprocess +import copy +import typing as T +from pathlib import Path + +from ... import arglist +from ... import mesonlib +from ... import mlog +from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker +from ...mesonlib import LibType +from ...coredata import OptionKey +from .. import compilers +from ..compilers import CompileCheckMode +from .visualstudio import VisualStudioLikeCompiler + +if T.TYPE_CHECKING: + from ...dependencies import Dependency + from ..._typing import ImmutableListProtocol + from ...environment import Environment + from ...compilers.compilers import Compiler + from ...programs import ExternalProgram +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + +GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ | + ^(?:-Wl,)?-l | + \.a$''', re.X) + +class CLikeCompilerArgs(arglist.CompilerArgs): + prepend_prefixes = ('-I', '-L') + dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U') + + # NOTE: not thorough. A list of potential corner cases can be found in + # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 + dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic') + dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') + dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') + + def to_native(self, copy: bool = False) -> T.List[str]: + # This seems to be allowed, but could never work? + assert isinstance(self.compiler, compilers.Compiler), 'How did you get here' + + # Check if we need to add --start/end-group for circular dependencies + # between static libraries, and for recursively searching for symbols + # needed by static libraries that are provided by object files or + # shared libraries. + self.flush_pre_post() + if copy: + new = self.copy() + else: + new = self + # This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which + # all act like (or are) gnu ld + # TODO: this could probably be added to the DynamicLinker instead + if isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker)): + group_start = -1 + group_end = -1 + for i, each in enumerate(new): + if not GROUP_FLAGS.search(each): + continue + group_end = i + if group_start < 0: + # First occurrence of a library + group_start = i + if group_start >= 0: + # Last occurrence of a library + new.insert(group_end + 1, '-Wl,--end-group') + new.insert(group_start, '-Wl,--start-group') + # Remove system/default include paths added with -isystem + default_dirs = self.compiler.get_default_include_dirs() + if default_dirs: + real_default_dirs = [self._cached_realpath(i) for i in default_dirs] + bad_idx_list = [] # type: T.List[int] + for i, each in enumerate(new): + if not each.startswith('-isystem'): + continue + + # Remove the -isystem and the path if the path is a default path + if (each == '-isystem' and + i < (len(new) - 1) and + self._cached_realpath(new[i + 1]) in real_default_dirs): + bad_idx_list += [i, i + 1] + elif each.startswith('-isystem=') and self._cached_realpath(each[9:]) in real_default_dirs: + bad_idx_list += [i] + elif self._cached_realpath(each[8:]) in real_default_dirs: + bad_idx_list += [i] + for i in reversed(bad_idx_list): + new.pop(i) + return self.compiler.unix_args_to_native(new._container) + + @staticmethod + @functools.lru_cache(maxsize=None) + def _cached_realpath(arg: str) -> str: + return os.path.realpath(arg) + + def __repr__(self) -> str: + self.flush_pre_post() + return f'CLikeCompilerArgs({self.compiler!r}, {self._container!r})' + + +class CLikeCompiler(Compiler): + + """Shared bits for the C and CPP Compilers.""" + + if T.TYPE_CHECKING: + warn_args = {} # type: T.Dict[str, T.List[str]] + + # TODO: Replace this manual cache with functools.lru_cache + find_library_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], str, LibType], T.Optional[T.List[str]]] + find_framework_cache = {} # type: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], bool], T.Optional[T.List[str]]] + internal_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS + + def __init__(self, exe_wrapper: T.Optional['ExternalProgram'] = None): + # If a child ObjC or CPP class has already set it, don't set it ourselves + self.can_compile_suffixes.add('h') + # If the exe wrapper was not found, pretend it wasn't set so that the + # sanity check is skipped and compiler checks use fallbacks. + if not exe_wrapper or not exe_wrapper.found() or not exe_wrapper.get_command(): + self.exe_wrapper = None + else: + self.exe_wrapper = exe_wrapper + # Lazy initialized in get_preprocessor() + self.preprocessor: T.Optional[Compiler] = None + + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs: + # This is correct, mypy just doesn't understand co-operative inheritance + return CLikeCompilerArgs(self, args) + + def needs_static_linker(self) -> bool: + return True # When compiling static libraries, so yes. + + def get_always_args(self) -> T.List[str]: + ''' + Args that are always-on for all C compilers other than MSVC + ''' + return self.get_largefile_args() + + def get_no_stdinc_args(self) -> T.List[str]: + return ['-nostdinc'] + + def get_no_stdlib_link_args(self) -> T.List[str]: + return ['-nostdlib'] + + def get_warn_args(self, level: str) -> T.List[str]: + # TODO: this should be an enum + return self.warn_args[level] + + def get_no_warn_args(self) -> T.List[str]: + # Almost every compiler uses this for disabling warnings + return ['-w'] + + def get_depfile_suffix(self) -> str: + return 'd' + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-E', '-P'] + + def get_compile_only_args(self) -> T.List[str]: + return ['-c'] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-O0'] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-o', outputname] + + def get_werror_args(self) -> T.List[str]: + return ['-Werror'] + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if path == '': + path = '.' + if is_system: + return ['-isystem', path] + return ['-I' + path] + + def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]: + ''' + Get dirs from the compiler, either `libraries:` or `programs:` + ''' + return [] + + @functools.lru_cache() + def _get_library_dirs(self, env: 'Environment', + elf_class: T.Optional[int] = None) -> 'ImmutableListProtocol[str]': + # TODO: replace elf_class with enum + dirs = self.get_compiler_dirs(env, 'libraries') + if elf_class is None or elf_class == 0: + return dirs + + # if we do have an elf class for 32-bit or 64-bit, we want to check that + # the directory in question contains libraries of the appropriate class. Since + # system directories aren't mixed, we only need to check one file for each + # directory and go by that. If we can't check the file for some reason, assume + # the compiler knows what it's doing, and accept the directory anyway. + retval = [] + for d in dirs: + files = [f for f in os.listdir(d) if f.endswith('.so') and os.path.isfile(os.path.join(d, f))] + # if no files, accept directory and move on + if not files: + retval.append(d) + continue + + for f in files: + file_to_check = os.path.join(d, f) + try: + with open(file_to_check, 'rb') as fd: + header = fd.read(5) + # if file is not an ELF file, it's weird, but accept dir + # if it is elf, and the class matches, accept dir + if header[1:4] != b'ELF' or int(header[4]) == elf_class: + retval.append(d) + # at this point, it's an ELF file which doesn't match the + # appropriate elf_class, so skip this one + # stop scanning after the first successful read + break + except OSError: + # Skip the file if we can't read it + pass + + return retval + + def get_library_dirs(self, env: 'Environment', + elf_class: T.Optional[int] = None) -> T.List[str]: + """Wrap the lru_cache so that we return a new copy and don't allow + mutation of the cached value. + """ + return self._get_library_dirs(env, elf_class).copy() + + @functools.lru_cache() + def _get_program_dirs(self, env: 'Environment') -> 'ImmutableListProtocol[str]': + ''' + Programs used by the compiler. Also where toolchain DLLs such as + libstdc++-6.dll are found with MinGW. + ''' + return self.get_compiler_dirs(env, 'programs') + + def get_program_dirs(self, env: 'Environment') -> T.List[str]: + return self._get_program_dirs(env).copy() + + def get_pic_args(self) -> T.List[str]: + return ['-fPIC'] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return ['-include', os.path.basename(header)] + + def get_pch_name(self, name: str) -> str: + return os.path.basename(name) + '.' + self.get_pch_suffix() + + def get_default_include_dirs(self) -> T.List[str]: + return [] + + def gen_export_dynamic_link_args(self, env: 'Environment') -> T.List[str]: + return self.linker.export_dynamic_args(env) + + def gen_import_library_args(self, implibname: str) -> T.List[str]: + return self.linker.import_library_args(implibname) + + def _sanity_check_impl(self, work_dir: str, environment: 'Environment', + sname: str, code: str) -> None: + mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', mesonlib.join_args(self.exelist)) + mlog.debug(f'Is cross compiler: {self.is_cross!s}.') + + source_name = os.path.join(work_dir, sname) + binname = sname.rsplit('.', 1)[0] + mode = CompileCheckMode.LINK + if self.is_cross: + binname += '_cross' + if self.exe_wrapper is None: + # Linking cross built C/C++ apps is painful. You can't really + # tell if you should use -nostdlib or not and for example + # on OSX the compiler binary is the same but you need + # a ton of compiler flags to differentiate between + # arm and x86_64. So just compile. + mode = CompileCheckMode.COMPILE + cargs, largs = self._get_basic_compiler_args(environment, mode) + extra_flags = cargs + self.linker_to_compiler_args(largs) + + # Is a valid executable output for all toolchains and platforms + binname += '.exe' + # Write binary check source + binary_name = os.path.join(work_dir, binname) + with open(source_name, 'w', encoding='utf-8') as ofile: + ofile.write(code) + # Compile sanity check + # NOTE: extra_flags must be added at the end. On MSVC, it might contain a '/link' argument + # after which all further arguments will be passed directly to the linker + cmdlist = self.exelist + [sname] + self.get_output_args(binname) + extra_flags + pc, stdo, stde = mesonlib.Popen_safe(cmdlist, cwd=work_dir) + mlog.debug('Sanity check compiler command line:', mesonlib.join_args(cmdlist)) + mlog.debug('Sanity check compile stdout:') + mlog.debug(stdo) + mlog.debug('-----\nSanity check compile stderr:') + mlog.debug(stde) + mlog.debug('-----') + if pc.returncode != 0: + raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.') + # Run sanity check + if self.is_cross: + if self.exe_wrapper is None: + # Can't check if the binaries run so we have to assume they do + return + cmdlist = self.exe_wrapper.get_command() + [binary_name] + else: + cmdlist = [binary_name] + mlog.debug('Running test binary command: ', mesonlib.join_args(cmdlist)) + try: + # fortran code writes to stdout + pe = subprocess.run(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except Exception as e: + raise mesonlib.EnvironmentException(f'Could not invoke sanity test executable: {e!s}.') + if pe.returncode != 0: + raise mesonlib.EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.') + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + code = 'int main(void) { int class=0; return class; }\n' + return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) + + def check_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + code = f'''{prefix} + #include <{hname}>''' + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies) + + def has_header(self, hname: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + code = f'''{prefix} + #ifdef __has_include + #if !__has_include("{hname}") + #error "Header '{hname}' could not be found" + #endif + #else + #include <{hname}> + #endif''' + return self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode='preprocess', disable_cache=disable_cache) + + def has_header_symbol(self, hname: str, symbol: str, prefix: str, + env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + t = f'''{prefix} + #include <{hname}> + int main(void) {{ + /* If it's not defined as a macro, try to use as a symbol */ + #ifndef {symbol} + {symbol}; + #endif + return 0; + }}''' + return self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies) + + def _get_basic_compiler_args(self, env: 'Environment', mode: CompileCheckMode) -> T.Tuple[T.List[str], T.List[str]]: + cargs = [] # type: T.List[str] + largs = [] # type: T.List[str] + if mode is CompileCheckMode.LINK: + # Sometimes we need to manually select the CRT to use with MSVC. + # One example is when trying to do a compiler check that involves + # linking with static libraries since MSVC won't select a CRT for + # us in that case and will error out asking us to pick one. + try: + crt_val = env.coredata.options[OptionKey('b_vscrt')].value + buildtype = env.coredata.options[OptionKey('buildtype')].value + cargs += self.get_crt_compile_args(crt_val, buildtype) + except (KeyError, AttributeError): + pass + + # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env + sys_args = env.coredata.get_external_args(self.for_machine, self.language) + if isinstance(sys_args, str): + sys_args = [sys_args] + # Apparently it is a thing to inject linker flags both + # via CFLAGS _and_ LDFLAGS, even though the former are + # also used during linking. These flags can break + # argument checks. Thanks, Autotools. + cleaned_sys_args = self.remove_linkerlike_args(sys_args) + cargs += cleaned_sys_args + + if mode is CompileCheckMode.LINK: + ld_value = env.lookup_binary_entry(self.for_machine, self.language + '_ld') + if ld_value is not None: + largs += self.use_linker_args(ld_value[0], self.version) + + # Add LDFLAGS from the env + sys_ld_args = env.coredata.get_external_link_args(self.for_machine, self.language) + # CFLAGS and CXXFLAGS go to both linking and compiling, but we want them + # to only appear on the command line once. Remove dupes. + largs += [x for x in sys_ld_args if x not in sys_args] + + cargs += self.get_compiler_args_for_mode(mode) + return cargs, largs + + def build_wrapper_args(self, env: 'Environment', + extra_args: T.Union[None, arglist.CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + mode: CompileCheckMode = CompileCheckMode.COMPILE) -> arglist.CompilerArgs: + # TODO: the caller should handle the listing of these arguments + if extra_args is None: + extra_args = [] + else: + # TODO: we want to do this in the caller + extra_args = mesonlib.listify(extra_args) + extra_args = mesonlib.listify([e(mode.value) if callable(e) else e for e in extra_args]) + + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, collections.abc.Iterable): + # TODO: we want to ensure the front end does the listifing here + dependencies = [dependencies] + # Collect compiler arguments + cargs = self.compiler_args() # type: arglist.CompilerArgs + largs = [] # type: T.List[str] + for d in dependencies: + # Add compile flags needed by dependencies + cargs += d.get_compile_args() + if mode is CompileCheckMode.LINK: + # Add link flags needed to find dependencies + largs += d.get_link_args() + + ca, la = self._get_basic_compiler_args(env, mode) + cargs += ca + largs += la + + cargs += self.get_compiler_check_args(mode) + + # on MSVC compiler and linker flags must be separated by the "/link" argument + # at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here + if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and '/link' not in extra_args: + extra_args += ['/link'] + + args = cargs + extra_args + largs + return args + + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: + need_exe_wrapper = env.need_exe_wrapper(self.for_machine) + if need_exe_wrapper and self.exe_wrapper is None: + raise compilers.CrossNoRunException('Can not run test applications in this cross environment.') + with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p: + if p.returncode != 0: + mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') + return compilers.RunResult(False) + if need_exe_wrapper: + cmdlist = self.exe_wrapper.get_command() + [p.output_name] + else: + cmdlist = [p.output_name] + try: + pe, so, se = mesonlib.Popen_safe(cmdlist) + except Exception as e: + mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') + return compilers.RunResult(False) + + mlog.debug('Program stdout:\n') + mlog.debug(so) + mlog.debug('Program stderr:\n') + mlog.debug(se) + return compilers.RunResult(True, pe.returncode, so, se) + + def _compile_int(self, expression: str, prefix: str, env: 'Environment', + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']]) -> bool: + t = f'''{prefix} + #include + int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' + return self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies)[0] + + def cross_compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], + guess: T.Optional[int], prefix: str, env: 'Environment', + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: + # Try user's guess first + if isinstance(guess, int): + if self._compile_int(f'{expression} == {guess}', prefix, env, extra_args, dependencies): + return guess + + # If no bounds are given, compute them in the limit of int32 + maxint = 0x7fffffff + minint = -0x80000000 + if not isinstance(low, int) or not isinstance(high, int): + if self._compile_int(f'{expression} >= 0', prefix, env, extra_args, dependencies): + low = cur = 0 + while self._compile_int(f'{expression} > {cur}', prefix, env, extra_args, dependencies): + low = cur + 1 + if low > maxint: + raise mesonlib.EnvironmentException('Cross-compile check overflowed') + cur = min(cur * 2 + 1, maxint) + high = cur + else: + high = cur = -1 + while self._compile_int(f'{expression} < {cur}', prefix, env, extra_args, dependencies): + high = cur - 1 + if high < minint: + raise mesonlib.EnvironmentException('Cross-compile check overflowed') + cur = max(cur * 2, minint) + low = cur + else: + # Sanity check limits given by user + if high < low: + raise mesonlib.EnvironmentException('high limit smaller than low limit') + condition = f'{expression} <= {high} && {expression} >= {low}' + if not self._compile_int(condition, prefix, env, extra_args, dependencies): + raise mesonlib.EnvironmentException('Value out of given range') + + # Binary search + while low != high: + cur = low + int((high - low) / 2) + if self._compile_int(f'{expression} <= {cur}', prefix, env, extra_args, dependencies): + high = cur + else: + low = cur + 1 + + return low + + def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], + guess: T.Optional[int], prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']] = None) -> int: + if extra_args is None: + extra_args = [] + if self.is_cross: + return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies) + t = f'''{prefix} + #include + int main(void) {{ + printf("%ld\\n", (long)({expression})); + return 0; + }}''' + res = self.run(t, env, extra_args=extra_args, + dependencies=dependencies) + if not res.compiled: + return -1 + if res.returncode != 0: + raise mesonlib.EnvironmentException('Could not run compute_int test binary.') + return int(res.stdout) + + def cross_sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: + if extra_args is None: + extra_args = [] + t = f'''{prefix} + #include + int main(void) {{ + {typename} something; + return 0; + }}''' + if not self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies)[0]: + return -1 + return self.cross_compute_int(f'sizeof({typename})', None, None, None, prefix, env, extra_args, dependencies) + + def sizeof(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: + if extra_args is None: + extra_args = [] + if self.is_cross: + r = self.cross_sizeof(typename, prefix, env, extra_args=extra_args, + dependencies=dependencies) + return r, False + t = f'''{prefix} + #include + int main(void) {{ + printf("%ld\\n", (long)(sizeof({typename}))); + return 0; + }}''' + res = self.cached_run(t, env, extra_args=extra_args, + dependencies=dependencies) + if not res.compiled: + return -1, False + if res.returncode != 0: + raise mesonlib.EnvironmentException('Could not run sizeof test binary.') + return int(res.stdout), res.cached + + def cross_alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> int: + if extra_args is None: + extra_args = [] + t = f'''{prefix} + #include + int main(void) {{ + {typename} something; + return 0; + }}''' + if not self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies)[0]: + return -1 + t = f'''{prefix} + #include + struct tmp {{ + char c; + {typename} target; + }};''' + return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t, env, extra_args, dependencies) + + def alignment(self, typename: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]: + if extra_args is None: + extra_args = [] + if self.is_cross: + r = self.cross_alignment(typename, prefix, env, extra_args=extra_args, + dependencies=dependencies) + return r, False + t = f'''{prefix} + #include + #include + struct tmp {{ + char c; + {typename} target; + }}; + int main(void) {{ + printf("%d", (int)offsetof(struct tmp, target)); + return 0; + }}''' + res = self.cached_run(t, env, extra_args=extra_args, + dependencies=dependencies) + if not res.compiled: + raise mesonlib.EnvironmentException('Could not compile alignment test.') + if res.returncode != 0: + raise mesonlib.EnvironmentException('Could not run alignment test binary.') + align = int(res.stdout) + if align == 0: + raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.') + return align, res.cached + + def get_define(self, dname: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + disable_cache: bool = False) -> T.Tuple[str, bool]: + delim = '"MESON_GET_DEFINE_DELIMITER"' + code = f''' + {prefix} + #ifndef {dname} + # define {dname} + #endif + {delim}\n{dname}''' + args = self.build_wrapper_args(env, extra_args, dependencies, + mode=CompileCheckMode.PREPROCESS).to_native() + func = functools.partial(self.cached_compile, code, env.coredata, extra_args=args, mode='preprocess') + if disable_cache: + func = functools.partial(self.compile, code, extra_args=args, mode='preprocess', temp_dir=env.scratch_dir) + with func() as p: + cached = p.cached + if p.returncode != 0: + raise mesonlib.EnvironmentException(f'Could not get define {dname!r}') + # Get the preprocessed value after the delimiter, + # minus the extra newline at the end and + # merge string literals. + return self._concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]).strip(), cached + + def get_return_value(self, fname: str, rtype: str, prefix: str, + env: 'Environment', extra_args: T.Optional[T.List[str]], + dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]: + # TODO: rtype should be an enum. + # TODO: maybe we can use overload to tell mypy when this will return int vs str? + if rtype == 'string': + fmt = '%s' + cast = '(char*)' + elif rtype == 'int': + fmt = '%lli' + cast = '(long long int)' + else: + raise AssertionError(f'BUG: Unknown return type {rtype!r}') + code = f'''{prefix} + #include + int main(void) {{ + printf ("{fmt}", {cast} {fname}()); + return 0; + }}''' + res = self.run(code, env, extra_args=extra_args, dependencies=dependencies) + if not res.compiled: + raise mesonlib.EnvironmentException(f'Could not get return value of {fname}()') + if rtype == 'string': + return res.stdout + elif rtype == 'int': + try: + return int(res.stdout.strip()) + except ValueError: + raise mesonlib.EnvironmentException(f'Return value of {fname}() is not an int') + assert False, 'Unreachable' + + @staticmethod + def _no_prototype_templ() -> T.Tuple[str, str]: + """ + Try to find the function without a prototype from a header by defining + our own dummy prototype and trying to link with the C library (and + whatever else the compiler links in by default). This is very similar + to the check performed by Autoconf for AC_CHECK_FUNCS. + """ + # Define the symbol to something else since it is defined by the + # includes or defines listed by the user or by the compiler. This may + # include, for instance _GNU_SOURCE which must be defined before + # limits.h, which includes features.h + # Then, undef the symbol to get rid of it completely. + head = ''' + #define {func} meson_disable_define_of_{func} + {prefix} + #include + #undef {func} + ''' + # Override any GCC internal prototype and declare our own definition for + # the symbol. Use char because that's unlikely to be an actual return + # value for a function which ensures that we override the definition. + head += ''' + #ifdef __cplusplus + extern "C" + #endif + char {func} (void); + ''' + # The actual function call + main = ''' + int main(void) {{ + return {func} (); + }}''' + return head, main + + @staticmethod + def _have_prototype_templ() -> T.Tuple[str, str]: + """ + Returns a head-er and main() call that uses the headers listed by the + user for the function prototype while checking if a function exists. + """ + # Add the 'prefix', aka defines, includes, etc that the user provides + # This may include, for instance _GNU_SOURCE which must be defined + # before limits.h, which includes features.h + head = '{prefix}\n#include \n' + # We don't know what the function takes or returns, so return it as an int. + # Just taking the address or comparing it to void is not enough because + # compilers are smart enough to optimize it away. The resulting binary + # is not run so we don't care what the return value is. + main = '''\nint main(void) {{ + void *a = (void*) &{func}; + long long b = (long long) a; + return (int) b; + }}''' + return head, main + + def has_function(self, funcname: str, prefix: str, env: 'Environment', *, + extra_args: T.Optional[T.List[str]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + """Determine if a function exists. + + First, this function looks for the symbol in the default libraries + provided by the compiler (stdlib + a few others usually). If that + fails, it checks if any of the headers specified in the prefix provide + an implementation of the function, and if that fails, it checks if it's + implemented as a compiler-builtin. + """ + if extra_args is None: + extra_args = [] + + # Short-circuit if the check is already provided by the cross-info file + varname = 'has function ' + funcname + varname = varname.replace(' ', '_') + if self.is_cross: + val = env.properties.host.get(varname, None) + if val is not None: + if isinstance(val, bool): + return val, False + raise mesonlib.EnvironmentException(f'Cross variable {varname} is not a boolean.') + + # TODO: we really need a protocol for this, + # + # class StrProto(typing.Protocol): + # def __str__(self) -> str: ... + fargs = {'prefix': prefix, 'func': funcname} # type: T.Dict[str, T.Union[str, bool, int]] + + # glibc defines functions that are not available on Linux as stubs that + # fail with ENOSYS (such as e.g. lchmod). In this case we want to fail + # instead of detecting the stub as a valid symbol. + # We already included limits.h earlier to ensure that these are defined + # for stub functions. + stubs_fail = ''' + #if defined __stub_{func} || defined __stub___{func} + fail fail fail this function is not going to work + #endif + ''' + + # If we have any includes in the prefix supplied by the user, assume + # that the user wants us to use the symbol prototype defined in those + # includes. If not, then try to do the Autoconf-style check with + # a dummy prototype definition of our own. + # This is needed when the linker determines symbol availability from an + # SDK based on the prototype in the header provided by the SDK. + # Ignoring this prototype would result in the symbol always being + # marked as available. + if '#include' in prefix: + head, main = self._have_prototype_templ() + else: + head, main = self._no_prototype_templ() + templ = head + stubs_fail + main + + res, cached = self.links(templ.format(**fargs), env, extra_args=extra_args, + dependencies=dependencies) + if res: + return True, cached + + # MSVC does not have compiler __builtin_-s. + if self.get_id() in {'msvc', 'intel-cl'}: + return False, False + + # Detect function as a built-in + # + # Some functions like alloca() are defined as compiler built-ins which + # are inlined by the compiler and you can't take their address, so we + # need to look for them differently. On nice compilers like clang, we + # can just directly use the __has_builtin() macro. + fargs['no_includes'] = '#include' not in prefix + is_builtin = funcname.startswith('__builtin_') + fargs['is_builtin'] = is_builtin + fargs['__builtin_'] = '' if is_builtin else '__builtin_' + t = '''{prefix} + int main(void) {{ + + /* With some toolchains (MSYS2/mingw for example) the compiler + * provides various builtins which are not really implemented and + * fall back to the stdlib where they aren't provided and fail at + * build/link time. In case the user provides a header, including + * the header didn't lead to the function being defined, and the + * function we are checking isn't a builtin itself we assume the + * builtin is not functional and we just error out. */ + #if !{no_includes:d} && !defined({func}) && !{is_builtin:d} + #error "No definition for {__builtin_}{func} found in the prefix" + #endif + + #ifdef __has_builtin + #if !__has_builtin({__builtin_}{func}) + #error "{__builtin_}{func} not found" + #endif + #elif ! defined({func}) + {__builtin_}{func}; + #endif + return 0; + }}''' + return self.links(t.format(**fargs), env, extra_args=extra_args, + dependencies=dependencies) + + def has_members(self, typename: str, membernames: T.List[str], + prefix: str, env: 'Environment', *, + extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + if extra_args is None: + extra_args = [] + # Create code that accesses all members + members = ''.join(f'foo.{member};\n' for member in membernames) + t = f'''{prefix} + void bar(void) {{ + {typename} foo; + {members} + }}''' + return self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies) + + def has_type(self, typename: str, prefix: str, env: 'Environment', + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, + dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + t = f'''{prefix} + void bar(void) {{ + sizeof({typename}); + }}''' + return self.compiles(t, env, extra_args=extra_args, + dependencies=dependencies) + + def _symbols_have_underscore_prefix_searchbin(self, env: 'Environment') -> bool: + ''' + Check if symbols have underscore prefix by compiling a small test binary + and then searching the binary for the string, + ''' + symbol_name = b'meson_uscore_prefix' + code = '''#ifdef __cplusplus + extern "C" { + #endif + void ''' + symbol_name.decode() + ''' (void) {} + #ifdef __cplusplus + } + #endif + ''' + args = self.get_compiler_check_args(CompileCheckMode.COMPILE) + n = '_symbols_have_underscore_prefix_searchbin' + with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p: + if p.returncode != 0: + raise RuntimeError(f'BUG: Unable to compile {n!r} check: {p.stderr}') + if not os.path.isfile(p.output_name): + raise RuntimeError(f'BUG: Can\'t find compiled test code for {n!r} check') + with open(p.output_name, 'rb') as o: + for line in o: + # Check if the underscore form of the symbol is somewhere + # in the output file. + if b'_' + symbol_name in line: + mlog.debug("Underscore prefix check found prefixed function in binary") + return True + # Else, check if the non-underscored form is present + elif symbol_name in line: + mlog.debug("Underscore prefix check found non-prefixed function in binary") + return False + raise RuntimeError(f'BUG: {n!r} check did not find symbol string in binary') + + def _symbols_have_underscore_prefix_define(self, env: 'Environment') -> T.Optional[bool]: + ''' + Check if symbols have underscore prefix by querying the + __USER_LABEL_PREFIX__ define that most compilers provide + for this. Return if functions have underscore prefix or None + if it was not possible to determine, like when the compiler + does not set the define or the define has an unexpected value. + ''' + delim = '"MESON_HAVE_UNDERSCORE_DELIMITER" ' + code = f''' + #ifndef __USER_LABEL_PREFIX__ + #define MESON_UNDERSCORE_PREFIX unsupported + #else + #define MESON_UNDERSCORE_PREFIX __USER_LABEL_PREFIX__ + #endif + {delim}MESON_UNDERSCORE_PREFIX + ''' + with self._build_wrapper(code, env, mode='preprocess', want_output=False, temp_dir=env.scratch_dir) as p: + if p.returncode != 0: + raise RuntimeError(f'BUG: Unable to preprocess _symbols_have_underscore_prefix_define check: {p.stdout}') + symbol_prefix = p.stdout.partition(delim)[-1].rstrip() + + mlog.debug(f'Queried compiler for function prefix: __USER_LABEL_PREFIX__ is "{symbol_prefix!s}"') + if symbol_prefix == '_': + return True + elif symbol_prefix == '': + return False + else: + return None + + def _symbols_have_underscore_prefix_list(self, env: 'Environment') -> T.Optional[bool]: + ''' + Check if symbols have underscore prefix by consulting a hardcoded + list of cases where we know the results. + Return if functions have underscore prefix or None if unknown. + ''' + m = env.machines[self.for_machine] + # Darwin always uses the underscore prefix, not matter what + if m.is_darwin(): + return True + # Windows uses the underscore prefix on x86 (32bit) only + if m.is_windows() or m.is_cygwin(): + return m.cpu_family == 'x86' + return None + + def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: + ''' + Check if the compiler prefixes an underscore to global C symbols + ''' + # First, try to query the compiler directly + result = self._symbols_have_underscore_prefix_define(env) + if result is not None: + return result + + # Else, try to consult a hardcoded list of cases we know + # absolutely have an underscore prefix + result = self._symbols_have_underscore_prefix_list(env) + if result is not None: + return result + + # As a last resort, try search in a compiled binary, which is the + # most unreliable way of checking this, see #5482 + return self._symbols_have_underscore_prefix_searchbin(env) + + def _get_patterns(self, env: 'Environment', prefixes: T.List[str], suffixes: T.List[str], shared: bool = False) -> T.List[str]: + patterns = [] # type: T.List[str] + for p in prefixes: + for s in suffixes: + patterns.append(p + '{}.' + s) + if shared and env.machines[self.for_machine].is_openbsd(): + # Shared libraries on OpenBSD can be named libfoo.so.X.Y: + # https://www.openbsd.org/faq/ports/specialtopics.html#SharedLibs + # + # This globbing is probably the best matching we can do since regex + # is expensive. It's wrong in many edge cases, but it will match + # correctly-named libraries and hopefully no one on OpenBSD names + # their files libfoo.so.9a.7b.1.0 + for p in prefixes: + patterns.append(p + '{}.so.[0-9]*.[0-9]*') + return patterns + + def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool = False) -> T.Tuple[str, ...]: + ''' + Get library prefixes and suffixes for the target platform ordered by + priority + ''' + stlibext = ['a'] + # We've always allowed libname to be both `foo` and `libfoo`, and now + # people depend on it. Also, some people use prebuilt `foo.so` instead + # of `libfoo.so` for unknown reasons, and may also want to create + # `foo.so` by setting name_prefix to '' + if strict and not isinstance(self, VisualStudioLikeCompiler): # lib prefix is not usually used with msvc + prefixes = ['lib'] + else: + prefixes = ['lib', ''] + # Library suffixes and prefixes + if env.machines[self.for_machine].is_darwin(): + shlibext = ['dylib', 'so'] + elif env.machines[self.for_machine].is_windows(): + # FIXME: .lib files can be import or static so we should read the + # file, figure out which one it is, and reject the wrong kind. + if isinstance(self, VisualStudioLikeCompiler): + shlibext = ['lib'] + else: + shlibext = ['dll.a', 'lib', 'dll'] + # Yep, static libraries can also be foo.lib + stlibext += ['lib'] + elif env.machines[self.for_machine].is_cygwin(): + shlibext = ['dll', 'dll.a'] + prefixes = ['cyg'] + prefixes + else: + # Linux/BSDs + shlibext = ['so'] + # Search priority + if libtype is LibType.PREFER_SHARED: + patterns = self._get_patterns(env, prefixes, shlibext, True) + patterns.extend([x for x in self._get_patterns(env, prefixes, stlibext, False) if x not in patterns]) + elif libtype is LibType.PREFER_STATIC: + patterns = self._get_patterns(env, prefixes, stlibext, False) + patterns.extend([x for x in self._get_patterns(env, prefixes, shlibext, True) if x not in patterns]) + elif libtype is LibType.SHARED: + patterns = self._get_patterns(env, prefixes, shlibext, True) + else: + assert libtype is LibType.STATIC + patterns = self._get_patterns(env, prefixes, stlibext, False) + return tuple(patterns) + + @staticmethod + def _sort_shlibs_openbsd(libs: T.List[str]) -> T.List[str]: + def tuple_key(x: str) -> T.Tuple[int, ...]: + ver = x.rsplit('.so.', maxsplit=1)[1] + return tuple(int(i) for i in ver.split('.')) + + filtered = [] # type: T.List[str] + for lib in libs: + # Validate file as a shared library of type libfoo.so.X.Y + ret = lib.rsplit('.so.', maxsplit=1) + if len(ret) != 2: + continue + try: + tuple(int(i) for i in ret[1].split('.')) + except ValueError: + continue + filtered.append(lib) + return sorted(filtered, key=tuple_key, reverse=True) + + @classmethod + def _get_trials_from_pattern(cls, pattern: str, directory: str, libname: str) -> T.List[Path]: + f = Path(directory) / pattern.format(libname) + # Globbing for OpenBSD + if '*' in pattern: + # NOTE: globbing matches directories and broken symlinks + # so we have to do an isfile test on it later + return [Path(x) for x in cls._sort_shlibs_openbsd(glob.glob(str(f)))] + return [f] + + @staticmethod + def _get_file_from_list(env: 'Environment', paths: T.List[Path]) -> Path: + ''' + We just check whether the library exists. We can't do a link check + because the library might have unresolved symbols that require other + libraries. On macOS we check if the library matches our target + architecture. + ''' + # If not building on macOS for Darwin, do a simple file check + if not env.machines.host.is_darwin() or not env.machines.build.is_darwin(): + for p in paths: + if p.is_file(): + return p + # Run `lipo` and check if the library supports the arch we want + for p in paths: + if not p.is_file(): + continue + archs = mesonlib.darwin_get_object_archs(str(p)) + if archs and env.machines.host.cpu_family in archs: + return p + else: + mlog.debug(f'Rejected {p}, supports {archs} but need {env.machines.host.cpu_family}') + return None + + @functools.lru_cache() + def output_is_64bit(self, env: 'Environment') -> bool: + ''' + returns true if the output produced is 64-bit, false if 32-bit + ''' + return self.sizeof('void *', '', env)[0] == 8 + + def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.List[str], code: str, libtype: LibType, lib_prefix_warning: bool) -> T.Optional[T.List[str]]: + # First try if we can just add the library as -l. + # Gcc + co seem to prefer builtin lib dirs to -L dirs. + # Only try to find std libs if no extra dirs specified. + # The built-in search procedure will always favour .so and then always + # search for .a. This is only allowed if libtype is LibType.PREFER_SHARED + if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or + libname in self.internal_libs): + cargs = ['-l' + libname] + largs = self.get_linker_always_args() + self.get_allow_undefined_link_args() + extra_args = cargs + self.linker_to_compiler_args(largs) + + if self.links(code, env, extra_args=extra_args, disable_cache=True)[0]: + return cargs + # Don't do a manual search for internal libs + if libname in self.internal_libs: + return None + # Not found or we want to use a specific libtype? Try to find the + # library file itself. + patterns = self.get_library_naming(env, libtype) + # try to detect if we are 64-bit or 32-bit. If we can't + # detect, we will just skip path validity checks done in + # get_library_dirs() call + try: + if self.output_is_64bit(env): + elf_class = 2 + else: + elf_class = 1 + except (mesonlib.MesonException, KeyError): # TODO evaluate if catching KeyError is wanted here + elf_class = 0 + # Search in the specified dirs, and then in the system libraries + for d in itertools.chain(extra_dirs, self.get_library_dirs(env, elf_class)): + for p in patterns: + trials = self._get_trials_from_pattern(p, d, libname) + if not trials: + continue + trial = self._get_file_from_list(env, trials) + if not trial: + continue + if libname.startswith('lib') and trial.name.startswith(libname) and lib_prefix_warning: + mlog.warning(f'find_library({libname!r}) starting in "lib" only works by accident and is not portable') + return [trial.as_posix()] + return None + + def _find_library_impl(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + code: str, libtype: LibType, lib_prefix_warning: bool) -> T.Optional[T.List[str]]: + # These libraries are either built-in or invalid + if libname in self.ignore_libs: + return [] + if isinstance(extra_dirs, str): + extra_dirs = [extra_dirs] + key = (tuple(self.exelist), libname, tuple(extra_dirs), code, libtype) + if key not in self.find_library_cache: + value = self._find_library_real(libname, env, extra_dirs, code, libtype, lib_prefix_warning) + self.find_library_cache[key] = value + else: + value = self.find_library_cache[key] + if value is None: + return None + return value.copy() + + def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], + libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: + code = 'int main(void) { return 0; }\n' + return self._find_library_impl(libname, env, extra_dirs, code, libtype, lib_prefix_warning) + + def find_framework_paths(self, env: 'Environment') -> T.List[str]: + ''' + These are usually /Library/Frameworks and /System/Library/Frameworks, + unless you select a particular macOS SDK with the -isysroot flag. + You can also add to this by setting -F in CFLAGS. + ''' + # TODO: this really needs to be *AppleClang*, not just any clang. + if self.id != 'clang': + raise mesonlib.MesonException('Cannot find framework path with non-clang compiler') + # Construct the compiler command-line + commands = self.get_exelist(ccache=False) + ['-v', '-E', '-'] + commands += self.get_always_args() + # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env + commands += env.coredata.get_external_args(self.for_machine, self.language) + mlog.debug('Finding framework path by running: ', ' '.join(commands), '\n') + os_env = os.environ.copy() + os_env['LC_ALL'] = 'C' + _, _, stde = mesonlib.Popen_safe(commands, env=os_env, stdin=subprocess.PIPE) + paths = [] # T.List[str] + for line in stde.split('\n'): + if '(framework directory)' not in line: + continue + # line is of the form: + # ` /path/to/framework (framework directory)` + paths.append(line[:-21].strip()) + return paths + + def _find_framework_real(self, name: str, env: 'Environment', extra_dirs: T.List[str], allow_system: bool) -> T.Optional[T.List[str]]: + code = 'int main(void) { return 0; }' + link_args = [] + for d in extra_dirs: + link_args += ['-F' + d] + # We can pass -Z to disable searching in the system frameworks, but + # then we must also pass -L/usr/lib to pick up libSystem.dylib + extra_args = [] if allow_system else ['-Z', '-L/usr/lib'] + link_args += ['-framework', name] + if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]: + return link_args + return None + + def _find_framework_impl(self, name: str, env: 'Environment', extra_dirs: T.List[str], + allow_system: bool) -> T.Optional[T.List[str]]: + if isinstance(extra_dirs, str): + extra_dirs = [extra_dirs] + key = (tuple(self.exelist), name, tuple(extra_dirs), allow_system) + if key in self.find_framework_cache: + value = self.find_framework_cache[key] + else: + value = self._find_framework_real(name, env, extra_dirs, allow_system) + self.find_framework_cache[key] = value + if value is None: + return None + return value.copy() + + def find_framework(self, name: str, env: 'Environment', extra_dirs: T.List[str], + allow_system: bool = True) -> T.Optional[T.List[str]]: + ''' + Finds the framework with the specified name, and returns link args for + the same or returns None when the framework is not found. + ''' + # TODO: should probably check for macOS? + return self._find_framework_impl(name, env, extra_dirs, allow_system) + + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: + # TODO: does this belong here or in GnuLike or maybe PosixLike? + return [] + + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + # TODO: does this belong here or in GnuLike or maybe PosixLike? + return [] + + def thread_flags(self, env: 'Environment') -> T.List[str]: + # TODO: does this belong here or in GnuLike or maybe PosixLike? + host_m = env.machines[self.for_machine] + if host_m.is_haiku() or host_m.is_darwin(): + return [] + return ['-pthread'] + + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + return args.copy() + + def has_arguments(self, args: T.List[str], env: 'Environment', code: str, + mode: str) -> T.Tuple[bool, bool]: + return self.compiles(code, env, extra_args=args, mode=mode) + + def _has_multi_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]: + new_args = [] # type: T.List[str] + for arg in args: + # some compilers, e.g. GCC, don't warn for unsupported warning-disable + # flags, so when we are testing a flag like "-Wno-forgotten-towel", also + # check the equivalent enable flag too "-Wforgotten-towel" + if arg.startswith('-Wno-'): + new_args.append('-W' + arg[5:]) + if arg.startswith('-Wl,'): + mlog.warning(f'{arg} looks like a linker argument, ' + 'but has_argument and other similar methods only ' + 'support checking compiler arguments. Using them ' + 'to check linker arguments are never supported, ' + 'and results are likely to be wrong regardless of ' + 'the compiler you are using. has_link_argument or ' + 'other similar method can be used instead.') + new_args.append(arg) + return self.has_arguments(new_args, env, code, mode='compile') + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_arguments(args, env, 'extern int i;\nint i;\n') + + def _has_multi_link_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]: + # First time we check for link flags we need to first check if we have + # --fatal-warnings, otherwise some linker checks could give some + # false positive. + args = self.linker.fatal_warnings() + args + args = self.linker_to_compiler_args(args) + return self.has_arguments(args, env, code, mode='link') + + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + return self._has_multi_link_arguments(args, env, 'int main(void) { return 0; }\n') + + @staticmethod + def _concatenate_string_literals(s: str) -> str: + pattern = re.compile(r'(?P
.*([^\\]")|^")(?P([^\\"]|\\.)*)"\s+"(?P([^\\"]|\\.)*)(?P".*)')
+        ret = s
+        m = pattern.match(ret)
+        while m:
+            ret = ''.join(m.group('pre', 'str1', 'str2', 'post'))
+            m = pattern.match(ret)
+        return ret
+
+    def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+        # Most compilers (such as GCC and Clang) only warn about unknown or
+        # ignored attributes, so force an error. Overridden in GCC and Clang
+        # mixins.
+        return ['-Werror']
+
+    def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
+        # Just assume that if we're not on windows that dllimport and dllexport
+        # don't work
+        m = env.machines[self.for_machine]
+        if not (m.is_windows() or m.is_cygwin()):
+            if name in {'dllimport', 'dllexport'}:
+                return False, False
+
+        return self.compiles(self.attribute_check_func(name), env,
+                             extra_args=self.get_has_func_attribute_extra_args(name))
+
+    def get_assert_args(self, disable: bool) -> T.List[str]:
+        if disable:
+            return ['-DNDEBUG']
+        return []
+
+    @functools.lru_cache(maxsize=None)
+    def can_compile(self, src: 'mesonlib.FileOrString') -> bool:
+        # Files we preprocess can be anything, e.g. .in
+        if self.mode == 'PREPROCESSOR':
+            return True
+        return super().can_compile(src)
+
+    def get_preprocessor(self) -> Compiler:
+        if not self.preprocessor:
+            self.preprocessor = copy.copy(self)
+            self.preprocessor.exelist = self.exelist + self.get_preprocess_to_file_args()
+            self.preprocessor.mode = 'PREPROCESSOR'
+            self.modes.append(self.preprocessor)
+        return self.preprocessor
diff --git a/devtools/meson/mesonbuild/compilers/mixins/compcert.py b/devtools/meson/mesonbuild/compilers/mixins/compcert.py
new file mode 100644
index 0000000..d9c21a8
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/compcert.py
@@ -0,0 +1,138 @@
+# Copyright 2012-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Representations specific to the CompCert C compiler family."""
+
+import os
+import re
+import typing as T
+
+if T.TYPE_CHECKING:
+    from envconfig import MachineInfo
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+ccomp_buildtype_args = {
+    'plain': [''],
+    'debug': ['-O0', '-g'],
+    'debugoptimized': ['-O0', '-g'],
+    'release': ['-O3'],
+    'minsize': ['-Os'],
+    'custom': ['-Obranchless'],
+}  # type: T.Dict[str, T.List[str]]
+
+ccomp_optimization_args = {
+    'plain': [],
+    '0': ['-O0'],
+    'g': ['-O0'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-Os']
+}  # type: T.Dict[str, T.List[str]]
+
+ccomp_debug_args = {
+    False: [],
+    True: ['-g']
+}  # type: T.Dict[bool, T.List[str]]
+
+# As of CompCert 20.04, these arguments should be passed to the underlying gcc linker (via -WUl,)
+# There are probably (many) more, but these are those used by picolibc
+ccomp_args_to_wul = [
+        r"^-ffreestanding$",
+        r"^-r$"
+] # type: T.List[str]
+
+class CompCertCompiler(Compiler):
+
+    id = 'ccomp'
+
+    def __init__(self) -> None:
+        # Assembly
+        self.can_compile_suffixes.add('s')
+        self.can_compile_suffixes.add('sx')
+        default_warn_args = []  # type: T.List[str]
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + [],
+                          '3': default_warn_args + [],
+                          'everything': default_warn_args + []}  # type: T.Dict[str, T.List[str]]
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+    def get_pic_args(self) -> T.List[str]:
+        # As of now, CompCert does not support PIC
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return ccomp_buildtype_args[buildtype]
+
+    def get_pch_suffix(self) -> str:
+        return 'pch'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return []
+
+    @classmethod
+    def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]:
+        "Always returns a copy that can be independently mutated"
+        patched_args = []  # type: T.List[str]
+        for arg in args:
+            added = 0
+            for ptrn in ccomp_args_to_wul:
+                if re.match(ptrn, arg):
+                    patched_args.append('-WUl,' + arg)
+                    added = 1
+            if not added:
+                patched_args.append(arg)
+        return patched_args
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def get_preprocess_only_args(self) -> T.List[str]:
+        return ['-E']
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return ['-c']
+
+    def get_coverage_args(self) -> T.List[str]:
+        return []
+
+    def get_no_stdinc_args(self) -> T.List[str]:
+        return ['-nostdinc']
+
+    def get_no_stdlib_link_args(self) -> T.List[str]:
+        return ['-nostdlib']
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return ccomp_optimization_args[optimization_level]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return ccomp_debug_args[is_debug]
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:9] == '-I':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+        return parameter_list
diff --git a/devtools/meson/mesonbuild/compilers/mixins/elbrus.py b/devtools/meson/mesonbuild/compilers/mixins/elbrus.py
new file mode 100644
index 0000000..872649b
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/elbrus.py
@@ -0,0 +1,101 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Abstractions for the Elbrus family of compilers."""
+
+import os
+import typing as T
+import subprocess
+import re
+
+from .gnu import GnuLikeCompiler
+from .gnu import gnu_optimization_args
+from ...mesonlib import Popen_safe, OptionKey
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...coredata import KeyedOptionDictType
+
+
+class ElbrusCompiler(GnuLikeCompiler):
+    # Elbrus compiler is nearly like GCC, but does not support
+    # PCH, LTO, sanitizers and color output as of version 1.21.x.
+
+    id = 'lcc'
+
+    def __init__(self) -> None:
+        super().__init__()
+        self.base_options = {OptionKey(o) for o in ['b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']}
+        default_warn_args = ['-Wall']
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-Wextra'],
+                          '3': default_warn_args + ['-Wextra', '-Wpedantic'],
+                          'everything': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+    # FIXME: use _build_wrapper to call this so that linker flags from the env
+    # get applied
+    def get_library_dirs(self, env: 'Environment', elf_class: T.Optional[int] = None) -> T.List[str]:
+        os_env = os.environ.copy()
+        os_env['LC_ALL'] = 'C'
+        stdo = Popen_safe(self.get_exelist(ccache=False) + ['--print-search-dirs'], env=os_env)[1]
+        for line in stdo.split('\n'):
+            if line.startswith('libraries:'):
+                # lcc does not include '=' in --print-search-dirs output. Also it could show nonexistent dirs.
+                libstr = line.split(' ', 1)[1]
+                return [os.path.realpath(p) for p in libstr.split(':') if os.path.exists(p)]
+        return []
+
+    def get_program_dirs(self, env: 'Environment') -> T.List[str]:
+        os_env = os.environ.copy()
+        os_env['LC_ALL'] = 'C'
+        stdo = Popen_safe(self.get_exelist(ccache=False) + ['--print-search-dirs'], env=os_env)[1]
+        for line in stdo.split('\n'):
+            if line.startswith('programs:'):
+                # lcc does not include '=' in --print-search-dirs output.
+                libstr = line.split(' ', 1)[1]
+                return [os.path.realpath(p) for p in libstr.split(':')]
+        return []
+
+    def get_default_include_dirs(self) -> T.List[str]:
+        os_env = os.environ.copy()
+        os_env['LC_ALL'] = 'C'
+        p = subprocess.Popen(self.get_exelist(ccache=False) + ['-xc', '-E', '-v', '-'], env=os_env, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        stderr = p.stderr.read().decode('utf-8', errors='replace')
+        includes = []
+        for line in stderr.split('\n'):
+            if line.lstrip().startswith('--sys_include'):
+                includes.append(re.sub(r'\s*\\$', '', re.sub(r'^\s*--sys_include\s*', '', line)))
+        return includes
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return gnu_optimization_args[optimization_level]
+
+    def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]:
+        return ['-r', '-nodefaultlibs', '-nostartfiles', '-o', prelink_name] + obj_list
+
+    def get_pch_suffix(self) -> str:
+        # Actually it's not supported for now, but probably will be supported in future
+        return 'pch'
+
+    def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        args = []
+        std = options[OptionKey('std', lang=self.language, machine=self.for_machine)]
+        if std.value != 'none':
+            args.append('-std=' + std.value)
+        return args
+
+    def openmp_flags(self) -> T.List[str]:
+        return ['-fopenmp']
diff --git a/devtools/meson/mesonbuild/compilers/mixins/emscripten.py b/devtools/meson/mesonbuild/compilers/mixins/emscripten.py
new file mode 100644
index 0000000..22b7655
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/emscripten.py
@@ -0,0 +1,101 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Provides a mixin for shared code between C and C++ Emscripten compilers."""
+
+import os.path
+import typing as T
+
+from ... import coredata
+from ... import mesonlib
+from ...mesonlib import OptionKey
+from ...mesonlib import LibType
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+    from ...dependencies import Dependency
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+
+def wrap_js_includes(args: T.List[str]) -> T.List[str]:
+    final_args = []
+    for i in args:
+        if i.endswith('.js') and not i.startswith('-'):
+            final_args += ['--js-library', i]
+        else:
+            final_args += [i]
+    return final_args
+
+class EmscriptenMixin(Compiler):
+
+    def _get_compile_output(self, dirname: str, mode: str) -> str:
+        # In pre-processor mode, the output is sent to stdout and discarded
+        if mode == 'preprocess':
+            return None
+        # Unlike sane toolchains, emcc infers the kind of output from its name.
+        # This is the only reason why this method is overridden; compiler tests
+        # do not work well with the default exe/obj suffices.
+        if mode == 'link':
+            suffix = 'js'
+        else:
+            suffix = 'o'
+        return os.path.join(dirname, 'output.' + suffix)
+
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
+        args = ['-pthread']
+        count: int = env.coredata.options[OptionKey('thread_count', lang=self.language, machine=self.for_machine)].value
+        if count:
+            args.append(f'-sPTHREAD_POOL_SIZE={count}')
+        return args
+
+    def get_options(self) -> 'coredata.MutableKeyedOptionDictType':
+        opts = super().get_options()
+        key = OptionKey('thread_count', machine=self.for_machine, lang=self.language)
+        opts.update({
+            key: coredata.UserIntegerOption(
+                'Number of threads to use in web assembly, set to 0 to disable',
+                (0, None, 4),  # Default was picked at random
+            ),
+        })
+
+        return opts
+
+    @classmethod
+    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
+        return wrap_js_includes(super().native_args_to_unix(args))
+
+    def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]:
+        return wrap_js_includes(super().get_dependency_link_args(dep))
+
+    def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+                     libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]:
+        if not libname.endswith('.js'):
+            return super().find_library(libname, env, extra_dirs, libtype, lib_prefix_warning)
+        if os.path.isabs(libname):
+            if os.path.exists(libname):
+                return [libname]
+        if len(extra_dirs) == 0:
+            raise mesonlib.EnvironmentException('Looking up Emscripten JS libraries requires either an absolute path or specifying extra_dirs.')
+        for d in extra_dirs:
+            abs_path = os.path.join(d, libname)
+            if os.path.exists(abs_path):
+                return [abs_path]
+        return None
diff --git a/devtools/meson/mesonbuild/compilers/mixins/gnu.py b/devtools/meson/mesonbuild/compilers/mixins/gnu.py
new file mode 100644
index 0000000..93b367b
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/gnu.py
@@ -0,0 +1,653 @@
+# Copyright 2019-2022 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Provides mixins for GNU compilers and GNU-like compilers."""
+
+import abc
+import functools
+import os
+import multiprocessing
+import pathlib
+import re
+import subprocess
+import typing as T
+
+from ... import mesonlib
+from ... import mlog
+from ...mesonlib import OptionKey
+
+if T.TYPE_CHECKING:
+    from ..._typing import ImmutableListProtocol
+    from ...environment import Environment
+    from ..compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+# XXX: prevent circular references.
+# FIXME: this really is a posix interface not a c-like interface
+clike_debug_args = {
+    False: [],
+    True: ['-g'],
+}  # type: T.Dict[bool, T.List[str]]
+
+gnulike_buildtype_args = {
+    'plain': [],
+    'debug': [],
+    'debugoptimized': [],
+    'release': [],
+    'minsize': [],
+    'custom': [],
+}  # type: T.Dict[str, T.List[str]]
+
+gnu_optimization_args = {
+    'plain': [],
+    '0': ['-O0'],
+    'g': ['-Og'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-Os'],
+}  # type: T.Dict[str, T.List[str]]
+
+gnulike_instruction_set_args = {
+    'mmx': ['-mmmx'],
+    'sse': ['-msse'],
+    'sse2': ['-msse2'],
+    'sse3': ['-msse3'],
+    'ssse3': ['-mssse3'],
+    'sse41': ['-msse4.1'],
+    'sse42': ['-msse4.2'],
+    'avx': ['-mavx'],
+    'avx2': ['-mavx2'],
+    'neon': ['-mfpu=neon'],
+}  # type: T.Dict[str, T.List[str]]
+
+gnu_symbol_visibility_args = {
+    '': [],
+    'default': ['-fvisibility=default'],
+    'internal': ['-fvisibility=internal'],
+    'hidden': ['-fvisibility=hidden'],
+    'protected': ['-fvisibility=protected'],
+    'inlineshidden': ['-fvisibility=hidden', '-fvisibility-inlines-hidden'],
+}  # type: T.Dict[str, T.List[str]]
+
+gnu_color_args = {
+    'auto': ['-fdiagnostics-color=auto'],
+    'always': ['-fdiagnostics-color=always'],
+    'never': ['-fdiagnostics-color=never'],
+}  # type: T.Dict[str, T.List[str]]
+
+# Warnings collected from the GCC source and documentation.  This is an
+# objective set of all the warnings flags that apply to general projects: the
+# only ones omitted are those that require a project-specific value, or are
+# related to non-standard or legacy language support.  This behaves roughly
+# like -Weverything in clang.  Warnings implied by -Wall, -Wextra, or
+# higher-level warnings already enabled here are not included in these lists to
+# keep them as short as possible.  History goes back to GCC 3.0.0, everything
+# earlier is considered historical and listed under version 0.0.0.
+
+# GCC warnings for all C-family languages
+# Omitted non-general warnings:
+#   -Wabi=
+#   -Waggregate-return
+#   -Walloc-size-larger-than=BYTES
+#   -Walloca-larger-than=BYTES
+#   -Wframe-larger-than=BYTES
+#   -Wlarger-than=BYTES
+#   -Wstack-usage=BYTES
+#   -Wsystem-headers
+#   -Wtrampolines
+#   -Wvla-larger-than=BYTES
+#
+# Omitted warnings enabled elsewhere in meson:
+#   -Winvalid-pch (GCC 3.4.0)
+gnu_common_warning_args = {
+    "0.0.0": [
+        "-Wcast-qual",
+        "-Wconversion",
+        "-Wfloat-equal",
+        "-Wformat=2",
+        "-Winline",
+        "-Wmissing-declarations",
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wundef",
+        "-Wuninitialized",
+        "-Wwrite-strings",
+    ],
+    "3.0.0": [
+        "-Wdisabled-optimization",
+        "-Wpacked",
+        "-Wpadded",
+    ],
+    "3.3.0": [
+        "-Wmultichar",
+        "-Wswitch-default",
+        "-Wswitch-enum",
+        "-Wunused-macros",
+    ],
+    "4.0.0": [
+        "-Wmissing-include-dirs",
+    ],
+    "4.1.0": [
+        "-Wunsafe-loop-optimizations",
+        "-Wstack-protector",
+    ],
+    "4.2.0": [
+        "-Wstrict-overflow=5",
+    ],
+    "4.3.0": [
+        "-Warray-bounds=2",
+        "-Wlogical-op",
+        "-Wstrict-aliasing=3",
+        "-Wvla",
+    ],
+    "4.6.0": [
+        "-Wdouble-promotion",
+        "-Wsuggest-attribute=const",
+        "-Wsuggest-attribute=noreturn",
+        "-Wsuggest-attribute=pure",
+        "-Wtrampolines",
+    ],
+    "4.7.0": [
+        "-Wvector-operation-performance",
+    ],
+    "4.8.0": [
+        "-Wsuggest-attribute=format",
+    ],
+    "4.9.0": [
+        "-Wdate-time",
+    ],
+    "5.1.0": [
+        "-Wformat-signedness",
+        "-Wnormalized=nfc",
+    ],
+    "6.1.0": [
+        "-Wduplicated-cond",
+        "-Wnull-dereference",
+        "-Wshift-negative-value",
+        "-Wshift-overflow=2",
+        "-Wunused-const-variable=2",
+    ],
+    "7.1.0": [
+        "-Walloca",
+        "-Walloc-zero",
+        "-Wformat-overflow=2",
+        "-Wformat-truncation=2",
+        "-Wstringop-overflow=3",
+    ],
+    "7.2.0": [
+        "-Wduplicated-branches",
+    ],
+    "8.1.0": [
+        "-Wcast-align=strict",
+        "-Wsuggest-attribute=cold",
+        "-Wsuggest-attribute=malloc",
+    ],
+    "9.1.0": [
+        "-Wattribute-alias=2",
+    ],
+    "10.1.0": [
+        "-Wanalyzer-too-complex",
+        "-Warith-conversion",
+    ],
+    "12.1.0": [
+        "-Wbidi-chars=ucn",
+        "-Wopenacc-parallelism",
+        "-Wtrivial-auto-var-init",
+    ],
+}  # type: T.Dict[str, T.List[str]]
+
+# GCC warnings for C
+# Omitted non-general or legacy warnings:
+#   -Wc11-c2x-compat
+#   -Wc90-c99-compat
+#   -Wc99-c11-compat
+#   -Wdeclaration-after-statement
+#   -Wtraditional
+#   -Wtraditional-conversion
+gnu_c_warning_args = {
+    "0.0.0": [
+        "-Wbad-function-cast",
+        "-Wmissing-prototypes",
+        "-Wnested-externs",
+        "-Wstrict-prototypes",
+    ],
+    "3.4.0": [
+        "-Wold-style-definition",
+        "-Winit-self",
+    ],
+    "4.1.0": [
+        "-Wc++-compat",
+    ],
+    "4.5.0": [
+        "-Wunsuffixed-float-constants",
+    ],
+}  # type: T.Dict[str, T.List[str]]
+
+# GCC warnings for C++
+# Omitted non-general or legacy warnings:
+#   -Wc++0x-compat
+#   -Wc++1z-compat
+#   -Wc++2a-compat
+#   -Wctad-maybe-unsupported
+#   -Wnamespaces
+#   -Wtemplates
+gnu_cpp_warning_args = {
+    "0.0.0": [
+        "-Wctor-dtor-privacy",
+        "-Weffc++",
+        "-Wnon-virtual-dtor",
+        "-Wold-style-cast",
+        "-Woverloaded-virtual",
+        "-Wsign-promo",
+    ],
+    "4.0.1": [
+        "-Wstrict-null-sentinel",
+    ],
+    "4.6.0": [
+        "-Wnoexcept",
+    ],
+    "4.7.0": [
+        "-Wzero-as-null-pointer-constant",
+    ],
+    "4.8.0": [
+        "-Wabi-tag",
+        "-Wuseless-cast",
+    ],
+    "4.9.0": [
+        "-Wconditionally-supported",
+    ],
+    "5.1.0": [
+        "-Wsuggest-final-methods",
+        "-Wsuggest-final-types",
+        "-Wsuggest-override",
+    ],
+    "6.1.0": [
+        "-Wmultiple-inheritance",
+        "-Wplacement-new=2",
+        "-Wvirtual-inheritance",
+    ],
+    "7.1.0": [
+        "-Waligned-new=all",
+        "-Wnoexcept-type",
+        "-Wregister",
+    ],
+    "8.1.0": [
+        "-Wcatch-value=3",
+        "-Wextra-semi",
+    ],
+    "9.1.0": [
+        "-Wdeprecated-copy-dtor",
+        "-Wredundant-move",
+    ],
+    "10.1.0": [
+        "-Wcomma-subscript",
+        "-Wmismatched-tags",
+        "-Wredundant-tags",
+        "-Wvolatile",
+    ],
+    "11.1.0": [
+        "-Wdeprecated-enum-enum-conversion",
+        "-Wdeprecated-enum-float-conversion",
+        "-Winvalid-imported-macros",
+    ],
+}  # type: T.Dict[str, T.List[str]]
+
+# GCC warnings for Objective C and Objective C++
+# Omitted non-general or legacy warnings:
+#   -Wtraditional
+#   -Wtraditional-conversion
+gnu_objc_warning_args = {
+    "0.0.0": [
+        "-Wselector",
+    ],
+    "3.3": [
+        "-Wundeclared-selector",
+    ],
+    "4.1.0": [
+        "-Wassign-intercept",
+        "-Wstrict-selector-match",
+    ],
+}  # type: T.Dict[str, T.List[str]]
+
+_LANG_MAP = {
+    'c': 'c',
+    'cpp': 'c++',
+    'objc': 'objective-c',
+    'objcpp': 'objective-c++'
+}
+
+@functools.lru_cache(maxsize=None)
+def gnulike_default_include_dirs(compiler: T.Tuple[str, ...], lang: str) -> 'ImmutableListProtocol[str]':
+    if lang not in _LANG_MAP:
+        return []
+    lang = _LANG_MAP[lang]
+    env = os.environ.copy()
+    env["LC_ALL"] = 'C'
+    cmd = list(compiler) + [f'-x{lang}', '-E', '-v', '-']
+    _, stdout, _ = mesonlib.Popen_safe(cmd, stderr=subprocess.STDOUT, env=env)
+    parse_state = 0
+    paths = []  # type: T.List[str]
+    for line in stdout.split('\n'):
+        line = line.strip(' \n\r\t')
+        if parse_state == 0:
+            if line == '#include "..." search starts here:':
+                parse_state = 1
+        elif parse_state == 1:
+            if line == '#include <...> search starts here:':
+                parse_state = 2
+            else:
+                paths.append(line)
+        elif parse_state == 2:
+            if line == 'End of search list.':
+                break
+            else:
+                paths.append(line)
+    if not paths:
+        mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd)))
+    # Append a normalized copy of paths to make path lookup easier
+    paths += [os.path.normpath(x) for x in paths]
+    return paths
+
+
+class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
+    """
+    GnuLikeCompiler is a common interface to all compilers implementing
+    the GNU-style commandline interface. This includes GCC, Clang
+    and ICC. Certain functionality between them is different and requires
+    that the actual concrete subclass define their own implementation.
+    """
+
+    LINKER_PREFIX = '-Wl,'
+
+    def __init__(self) -> None:
+        self.base_options = {
+            OptionKey(o) for o in ['b_pch', 'b_lto', 'b_pgo', 'b_coverage',
+                                   'b_ndebug', 'b_staticpic', 'b_pie']}
+        if not (self.info.is_windows() or self.info.is_cygwin() or self.info.is_openbsd()):
+            self.base_options.add(OptionKey('b_lundef'))
+        if not self.info.is_windows() or self.info.is_cygwin():
+            self.base_options.add(OptionKey('b_asneeded'))
+        if not self.info.is_hurd():
+            self.base_options.add(OptionKey('b_sanitize'))
+        # All GCC-like backends can do assembly
+        self.can_compile_suffixes.add('s')
+        self.can_compile_suffixes.add('sx')
+
+    def get_pic_args(self) -> T.List[str]:
+        if self.info.is_windows() or self.info.is_cygwin() or self.info.is_darwin():
+            return [] # On Window and OS X, pic is always on.
+        return ['-fPIC']
+
+    def get_pie_args(self) -> T.List[str]:
+        return ['-fPIE']
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return gnulike_buildtype_args[buildtype]
+
+    @abc.abstractmethod
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        pass
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return clike_debug_args[is_debug]
+
+    @abc.abstractmethod
+    def get_pch_suffix(self) -> str:
+        pass
+
+    def split_shlib_to_parts(self, fname: str) -> T.Tuple[str, str]:
+        return os.path.dirname(fname), fname
+
+    def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
+        return gnulike_instruction_set_args.get(instruction_set, None)
+
+    def get_default_include_dirs(self) -> T.List[str]:
+        return gnulike_default_include_dirs(tuple(self.get_exelist(ccache=False)), self.language).copy()
+
+    @abc.abstractmethod
+    def openmp_flags(self) -> T.List[str]:
+        pass
+
+    def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]:
+        if vistype == 'inlineshidden' and self.language not in {'cpp', 'objcpp'}:
+            vistype = 'hidden'
+        return gnu_symbol_visibility_args[vistype]
+
+    def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]:
+        if not isinstance(defsfile, str):
+            raise RuntimeError('Module definitions file should be str')
+        # On Windows targets, .def files may be specified on the linker command
+        # line like an object file.
+        if self.info.is_windows() or self.info.is_cygwin():
+            return [defsfile]
+        # For other targets, discard the .def file.
+        return []
+
+    def get_argument_syntax(self) -> str:
+        return 'gcc'
+
+    def get_profile_generate_args(self) -> T.List[str]:
+        return ['-fprofile-generate']
+
+    def get_profile_use_args(self) -> T.List[str]:
+        return ['-fprofile-use']
+
+    def get_gui_app_args(self, value: bool) -> T.List[str]:
+        return ['-mwindows' if value else '-mconsole']
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:2] == '-I' or i[:2] == '-L':
+                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+
+        return parameter_list
+
+    @functools.lru_cache()
+    def _get_search_dirs(self, env: 'Environment') -> str:
+        extra_args = ['--print-search-dirs']
+        with self._build_wrapper('', env, extra_args=extra_args,
+                                 dependencies=None, mode='compile',
+                                 want_output=True) as p:
+            return p.stdout
+
+    def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]:
+        # We need to use the path separator used by the compiler for printing
+        # lists of paths ("gcc --print-search-dirs"). By default
+        # we assume it uses the platform native separator.
+        pathsep = os.pathsep
+
+        # clang uses ':' instead of ';' on Windows https://reviews.llvm.org/D61121
+        # so we need to repair things like 'C:\foo:C:\bar'
+        if pathsep == ';':
+            pathstr = re.sub(r':([^/\\])', r';\1', pathstr)
+
+        # pathlib treats empty paths as '.', so filter those out
+        paths = [p for p in pathstr.split(pathsep) if p]
+
+        result = []
+        for p in paths:
+            # GCC returns paths like this:
+            # /usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/lib
+            # It would make sense to normalize them to get rid of the .. parts
+            # Sadly when you are on a merged /usr fs it also kills these:
+            # /lib/x86_64-linux-gnu
+            # since /lib is a symlink to /usr/lib. This would mean
+            # paths under /lib would be considered not a "system path",
+            # which is wrong and breaks things. Store everything, just to be sure.
+            pobj = pathlib.Path(p)
+            unresolved = pobj.as_posix()
+            if pobj.exists():
+                if unresolved not in result:
+                    result.append(unresolved)
+                try:
+                    resolved = pathlib.Path(p).resolve().as_posix()
+                    if resolved not in result:
+                        result.append(resolved)
+                except FileNotFoundError:
+                    pass
+        return result
+
+    def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]:
+        '''
+        Get dirs from the compiler, either `libraries:` or `programs:`
+        '''
+        stdo = self._get_search_dirs(env)
+        for line in stdo.split('\n'):
+            if line.startswith(name + ':'):
+                return self._split_fetch_real_dirs(line.split('=', 1)[1])
+        return []
+
+    def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
+        # This provides a base for many compilers, GCC and Clang override this
+        # for their specific arguments
+        return ['-flto']
+
+    def sanitizer_compile_args(self, value: str) -> T.List[str]:
+        if value == 'none':
+            return []
+        args = ['-fsanitize=' + value]
+        if 'address' in value:  # for -fsanitize=address,undefined
+            args.append('-fno-omit-frame-pointer')
+        return args
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return ['-o', target]
+
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
+        return ['-MD', '-MQ', outtarget, '-MF', outfile]
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return ['-c']
+
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        if not path:
+            path = '.'
+        if is_system:
+            return ['-isystem' + path]
+        return ['-I' + path]
+
+    @classmethod
+    def use_linker_args(cls, linker: str, version: str) -> T.List[str]:
+        if linker not in {'gold', 'bfd', 'lld'}:
+            raise mesonlib.MesonException(
+                f'Unsupported linker, only bfd, gold, and lld are supported, not {linker}.')
+        return [f'-fuse-ld={linker}']
+
+    def get_coverage_args(self) -> T.List[str]:
+        return ['--coverage']
+
+    def get_preprocess_to_file_args(self) -> T.List[str]:
+        # We want to allow preprocessing files with any extension, such as
+        # foo.c.in. In that case we need to tell GCC/CLANG to treat them as
+        # assembly file.
+        lang = _LANG_MAP.get(self.language, 'assembler-with-cpp')
+        return self.get_preprocess_only_args() + [f'-x{lang}']
+
+
+class GnuCompiler(GnuLikeCompiler):
+    """
+    GnuCompiler represents an actual GCC in its many incarnations.
+    Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
+    """
+    id = 'gcc'
+
+    def __init__(self, defines: T.Optional[T.Dict[str, str]]):
+        super().__init__()
+        self.defines = defines or {}
+        self.base_options.update({OptionKey('b_colorout'), OptionKey('b_lto_threads')})
+
+    def get_colorout_args(self, colortype: str) -> T.List[str]:
+        if mesonlib.version_compare(self.version, '>=4.9.0'):
+            return gnu_color_args[colortype][:]
+        return []
+
+    def get_warn_args(self, level: str) -> T.List[str]:
+        # Mypy doesn't understand cooperative inheritance
+        args = super().get_warn_args(level)
+        if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
+            # -Wpedantic was added in 4.8.0
+            # https://gcc.gnu.org/gcc-4.8/changes.html
+            args[args.index('-Wpedantic')] = '-pedantic'
+        return args
+
+    def supported_warn_args(self, warn_args_by_version: T.Dict[str, T.List[str]]) -> T.List[str]:
+        result = []
+        for version, warn_args in warn_args_by_version.items():
+            if mesonlib.version_compare(self.version, '>=' + version):
+                result += warn_args
+        return result
+
+    def has_builtin_define(self, define: str) -> bool:
+        return define in self.defines
+
+    def get_builtin_define(self, define: str) -> T.Optional[str]:
+        if define in self.defines:
+            return self.defines[define]
+        return None
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return gnu_optimization_args[optimization_level]
+
+    def get_pch_suffix(self) -> str:
+        return 'gch'
+
+    def openmp_flags(self) -> T.List[str]:
+        return ['-fopenmp']
+
+    def has_arguments(self, args: T.List[str], env: 'Environment', code: str,
+                      mode: str) -> T.Tuple[bool, bool]:
+        # For some compiler command line arguments, the GNU compilers will
+        # emit a warning on stderr indicating that an option is valid for a
+        # another language, but still complete with exit_success
+        with self._build_wrapper(code, env, args, None, mode) as p:
+            result = p.returncode == 0
+            if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stderr:
+                result = False
+            if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stderr:
+                result = False
+        return result, p.cached
+
+    def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+        # GCC only warns about unknown or ignored attributes, so force an
+        # error.
+        return ['-Werror=attributes']
+
+    def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]:
+        return ['-r', '-o', prelink_name] + obj_list
+
+    def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
+        if threads == 0:
+            if mesonlib.version_compare(self.version, '>= 10.0'):
+                return ['-flto=auto']
+            # This matches clang's behavior of using the number of cpus
+            return [f'-flto={multiprocessing.cpu_count()}']
+        elif threads > 0:
+            return [f'-flto={threads}']
+        return super().get_lto_compile_args(threads=threads)
+
+    @classmethod
+    def use_linker_args(cls, linker: str, version: str) -> T.List[str]:
+        if linker == 'mold' and mesonlib.version_compare(version, '>=12.0.1'):
+            return ['-fuse-ld=mold']
+        return super().use_linker_args(linker, version)
+
+    def get_profile_use_args(self) -> T.List[str]:
+        return super().get_profile_use_args() + ['-fprofile-correction']
diff --git a/devtools/meson/mesonbuild/compilers/mixins/intel.py b/devtools/meson/mesonbuild/compilers/mixins/intel.py
new file mode 100644
index 0000000..b793fa8
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/intel.py
@@ -0,0 +1,185 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Abstractions for the Intel Compiler families.
+
+Intel provides both a posix/gcc-like compiler (ICC) for MacOS and Linux,
+with Meson mixin IntelGnuLikeCompiler.
+For Windows, the Intel msvc-like compiler (ICL) Meson mixin
+is IntelVisualStudioLikeCompiler.
+"""
+
+import os
+import typing as T
+
+from ... import mesonlib
+from ..compilers import CompileCheckMode
+from .gnu import GnuLikeCompiler
+from .visualstudio import VisualStudioLikeCompiler
+
+# XXX: avoid circular dependencies
+# TODO: this belongs in a posix compiler class
+# NOTE: the default Intel optimization is -O2, unlike GNU which defaults to -O0.
+# this can be surprising, particularly for debug builds, so we specify the
+# default as -O0.
+# https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-o
+# https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-g
+# https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-o
+# https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-g
+# https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-traceback
+# https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
+
+
+class IntelGnuLikeCompiler(GnuLikeCompiler):
+    """
+    Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1, 19.0
+    debugoptimized: -g -O2
+    release: -O3
+    minsize: -O2
+    """
+
+    BUILD_ARGS = {
+        'plain': [],
+        'debug': ["-g", "-traceback"],
+        'debugoptimized': ["-g", "-traceback"],
+        'release': [],
+        'minsize': [],
+        'custom': [],
+    }  # type: T.Dict[str, T.List[str]]
+
+    OPTIM_ARGS: T.Dict[str, T.List[str]] = {
+        'plain': [],
+        '0': ['-O0'],
+        'g': ['-O0'],
+        '1': ['-O1'],
+        '2': ['-O2'],
+        '3': ['-O3'],
+        's': ['-Os'],
+    }
+    id = 'intel'
+
+    def __init__(self) -> None:
+        super().__init__()
+        # As of 19.0.0 ICC doesn't have sanitizer, color, or lto support.
+        #
+        # It does have IPO, which serves much the same purpose as LOT, but
+        # there is an unfortunate rule for using IPO (you can't control the
+        # name of the output file) which break assumptions meson makes
+        self.base_options = {mesonlib.OptionKey(o) for o in [
+            'b_pch', 'b_lundef', 'b_asneeded', 'b_pgo', 'b_coverage',
+            'b_ndebug', 'b_staticpic', 'b_pie']}
+        self.lang_header = 'none'
+
+    def get_pch_suffix(self) -> str:
+        return 'pchi'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x',
+                self.lang_header, '-include', header, '-x', 'none']
+
+    def get_pch_name(self, header_name: str) -> str:
+        return os.path.basename(header_name) + '.' + self.get_pch_suffix()
+
+    def openmp_flags(self) -> T.List[str]:
+        if mesonlib.version_compare(self.version, '>=15.0.0'):
+            return ['-qopenmp']
+        else:
+            return ['-openmp']
+
+    def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
+        extra_args = [
+            '-diag-error', '10006',  # ignoring unknown option
+            '-diag-error', '10148',  # Option not supported
+            '-diag-error', '10155',  # ignoring argument required
+            '-diag-error', '10156',  # ignoring not argument allowed
+            '-diag-error', '10157',  # Ignoring argument of the wrong type
+            '-diag-error', '10158',  # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't
+        ]
+        return super().get_compiler_check_args(mode) + extra_args
+
+    def get_profile_generate_args(self) -> T.List[str]:
+        return ['-prof-gen=threadsafe']
+
+    def get_profile_use_args(self) -> T.List[str]:
+        return ['-prof-use']
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return self.BUILD_ARGS[buildtype]
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return self.OPTIM_ARGS[optimization_level]
+
+    def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
+        return ['-diag-error', '1292']
+
+
+class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
+
+    """Abstractions for ICL, the Intel compiler on Windows."""
+
+    BUILD_ARGS = {
+        'plain': [],
+        'debug': ["/Zi", "/traceback"],
+        'debugoptimized': ["/Zi", "/traceback"],
+        'release': [],
+        'minsize': [],
+        'custom': [],
+    }  # type: T.Dict[str, T.List[str]]
+
+    OPTIM_ARGS: T.Dict[str, T.List[str]] = {
+        'plain': [],
+        '0': ['/Od'],
+        'g': ['/Od'],
+        '1': ['/O1'],
+        '2': ['/O2'],
+        '3': ['/O3'],
+        's': ['/Os'],
+    }
+
+    id = 'intel-cl'
+
+    def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
+        args = super().get_compiler_check_args(mode)
+        if mode is not CompileCheckMode.LINK:
+            args.extend([
+                '/Qdiag-error:10006',  # ignoring unknown option
+                '/Qdiag-error:10148',  # Option not supported
+                '/Qdiag-error:10155',  # ignoring argument required
+                '/Qdiag-error:10156',  # ignoring not argument allowed
+                '/Qdiag-error:10157',  # Ignoring argument of the wrong type
+                '/Qdiag-error:10158',  # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't
+            ])
+        return args
+
+    def get_toolset_version(self) -> T.Optional[str]:
+        # ICL provides a cl.exe that returns the version of MSVC it tries to
+        # emulate, so we'll get the version from that and pass it to the same
+        # function the real MSVC uses to calculate the toolset version.
+        _, _, err = mesonlib.Popen_safe(['cl.exe'])
+        v1, v2, *_ = mesonlib.search_version(err).split('.')
+        version = int(v1 + v2)
+        return self._calculate_toolset_version(version)
+
+    def openmp_flags(self) -> T.List[str]:
+        return ['/Qopenmp']
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return self.BUILD_ARGS[buildtype]
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return self.OPTIM_ARGS[optimization_level]
+
+    def get_pch_base_name(self, header: str) -> str:
+        return os.path.basename(header)
diff --git a/devtools/meson/mesonbuild/compilers/mixins/islinker.py b/devtools/meson/mesonbuild/compilers/mixins/islinker.py
new file mode 100644
index 0000000..711e3e3
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/islinker.py
@@ -0,0 +1,130 @@
+# Copyright 2019 The Meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Mixins for compilers that *are* linkers.
+
+While many compilers (such as gcc and clang) are used by meson to dispatch
+linker commands and other (like MSVC) are not, a few (such as DMD) actually
+are both the linker and compiler in one binary. This module provides mixin
+classes for those cases.
+"""
+
+import typing as T
+
+from ...mesonlib import EnvironmentException, MesonException, is_windows
+
+if T.TYPE_CHECKING:
+    from ...coredata import KeyedOptionDictType
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+
+class BasicLinkerIsCompilerMixin(Compiler):
+
+    """Provides a baseline of methods that a linker would implement.
+
+    In every case this provides a "no" or "empty" answer. If a compiler
+    implements any of these it needs a different mixin or to override that
+    functionality itself.
+    """
+
+    def sanitizer_link_args(self, value: str) -> T.List[str]:
+        return []
+
+    def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default',
+                          thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]:
+        return []
+
+    def can_linker_accept_rsp(self) -> bool:
+        return is_windows()
+
+    def get_linker_exelist(self) -> T.List[str]:
+        return self.exelist.copy()
+
+    def get_linker_output_args(self, outputname: str) -> T.List[str]:
+        return []
+
+    def get_linker_always_args(self) -> T.List[str]:
+        return []
+
+    def get_linker_lib_prefix(self) -> str:
+        return ''
+
+    def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        return []
+
+    def has_multi_link_args(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
+        return False, False
+
+    def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
+        return []
+
+    def get_std_shared_lib_link_args(self) -> T.List[str]:
+        return []
+
+    def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        return self.get_std_shared_lib_link_args()
+
+    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
+        raise EnvironmentException(f'Linker {self.id} does not support link_whole')
+
+    def get_allow_undefined_link_args(self) -> T.List[str]:
+        raise EnvironmentException(f'Linker {self.id} does not support allow undefined')
+
+    def get_pie_link_args(self) -> T.List[str]:
+        raise EnvironmentException(f'Linker {self.id} does not support position-independent executable')
+
+    def get_undefined_link_args(self) -> T.List[str]:
+        return []
+
+    def get_coverage_link_args(self) -> T.List[str]:
+        return []
+
+    def no_undefined_link_args(self) -> T.List[str]:
+        return []
+
+    def bitcode_args(self) -> T.List[str]:
+        raise MesonException("This linker doesn't support bitcode bundles")
+
+    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
+                        suffix: str, soversion: str,
+                        darwin_versions: T.Tuple[str, str]) -> T.List[str]:
+        raise MesonException("This linker doesn't support soname args")
+
+    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
+                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
+                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+        return ([], set())
+
+    def get_asneeded_args(self) -> T.List[str]:
+        return []
+
+    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
+        return []
+
+    def get_link_debugfile_name(self, targetfile: str) -> str:
+        return ''
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
+        return []
diff --git a/devtools/meson/mesonbuild/compilers/mixins/metrowerks.py b/devtools/meson/mesonbuild/compilers/mixins/metrowerks.py
new file mode 100644
index 0000000..4390145
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/metrowerks.py
@@ -0,0 +1,300 @@
+# Copyright 2012-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Representations specific to the Metrowerks/Freescale Embedded C/C++ compiler family."""
+
+import os
+import typing as T
+
+from ...mesonlib import EnvironmentException, OptionKey
+
+if T.TYPE_CHECKING:
+    from ...envconfig import MachineInfo
+    from ...compilers.compilers import Compiler, CompileCheckMode
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+mwcc_buildtype_args = {
+    'plain': [],
+    'debug': ['-g'],
+    'debugoptimized': ['-g', '-O4'],
+    'release': ['-O4,p'],
+    'minsize': ['-Os'],
+    'custom': [],
+}  # type: T.Dict[str, T.List[str]]
+
+mwccarm_instruction_set_args = {
+    'generic': ['-proc', 'generic'],
+    'v4': ['-proc', 'v4'],
+    'v4t': ['-proc', 'v4t'],
+    'v5t': ['-proc', 'v5t'],
+    'v5te': ['-proc', 'v5te'],
+    'v6': ['-proc', 'v6'],
+    'arm7tdmi': ['-proc', 'arm7tdmi'],
+    'arm710t': ['-proc', 'arm710t'],
+    'arm720t': ['-proc', 'arm720t'],
+    'arm740t': ['-proc', 'arm740t'],
+    'arm7ej': ['-proc', 'arm7ej'],
+    'arm9tdmi': ['-proc', 'arm9tdmi'],
+    'arm920t': ['-proc', 'arm920t'],
+    'arm922t': ['-proc', 'arm922t'],
+    'arm940t': ['-proc', 'arm940t'],
+    'arm9ej': ['-proc', 'arm9ej'],
+    'arm926ej': ['-proc', 'arm926ej'],
+    'arm946e': ['-proc', 'arm946e'],
+    'arm966e': ['-proc', 'arm966e'],
+    'arm1020e': ['-proc', 'arm1020e'],
+    'arm1022e': ['-proc', 'arm1022e'],
+    'arm1026ej': ['-proc', 'arm1026ej'],
+    'dbmx1': ['-proc', 'dbmx1'],
+    'dbmxl': ['-proc', 'dbmxl'],
+    'XScale': ['-proc', 'XScale'],
+    'pxa255': ['-proc', 'pxa255'],
+    'pxa261': ['-proc', 'pxa261'],
+    'pxa262': ['-proc', 'pxa262'],
+    'pxa263': ['-proc', 'pxa263']
+}  # type: T.Dict[str, T.List[str]]
+
+mwcceppc_instruction_set_args = {
+    'generic': ['-proc', 'generic'],
+    '401': ['-proc', '401'],
+    '403': ['-proc', '403'],
+    '505': ['-proc', '505'],
+    '509': ['-proc', '509'],
+    '555': ['-proc', '555'],
+    '601': ['-proc', '601'],
+    '602': ['-proc', '602'],
+    '603': ['-proc', '603'],
+    '603e': ['-proc', '603e'],
+    '604': ['-proc', '604'],
+    '604e': ['-proc', '604e'],
+    '740': ['-proc', '740'],
+    '750': ['-proc', '750'],
+    '801': ['-proc', '801'],
+    '821': ['-proc', '821'],
+    '823': ['-proc', '823'],
+    '850': ['-proc', '850'],
+    '860': ['-proc', '860'],
+    '7400': ['-proc', '7400'],
+    '7450': ['-proc', '7450'],
+    '8240': ['-proc', '8240'],
+    '8260': ['-proc', '8260'],
+    'e500': ['-proc', 'e500'],
+    'gekko': ['-proc', 'gekko'],
+}  # type: T.Dict[str, T.List[str]]
+
+mwasmarm_instruction_set_args = {
+    'arm4': ['-proc', 'arm4'],
+    'arm4t': ['-proc', 'arm4t'],
+    'arm4xm': ['-proc', 'arm4xm'],
+    'arm4txm': ['-proc', 'arm4txm'],
+    'arm5': ['-proc', 'arm5'],
+    'arm5T': ['-proc', 'arm5T'],
+    'arm5xM': ['-proc', 'arm5xM'],
+    'arm5TxM': ['-proc', 'arm5TxM'],
+    'arm5TE': ['-proc', 'arm5TE'],
+    'arm5TExP': ['-proc', 'arm5TExP'],
+    'arm6': ['-proc', 'arm6'],
+    'xscale': ['-proc', 'xscale']
+}  # type: T.Dict[str, T.List[str]]
+
+mwasmeppc_instruction_set_args = {
+    '401': ['-proc', '401'],
+    '403': ['-proc', '403'],
+    '505': ['-proc', '505'],
+    '509': ['-proc', '509'],
+    '555': ['-proc', '555'],
+    '56X': ['-proc', '56X'],
+    '601': ['-proc', '601'],
+    '602': ['-proc', '602'],
+    '603': ['-proc', '603'],
+    '603e': ['-proc', '603e'],
+    '604': ['-proc', '604'],
+    '604e': ['-proc', '604e'],
+    '740': ['-proc', '740'],
+    '74X': ['-proc', '74X'],
+    '750': ['-proc', '750'],
+    '75X': ['-proc', '75X'],
+    '801': ['-proc', '801'],
+    '821': ['-proc', '821'],
+    '823': ['-proc', '823'],
+    '850': ['-proc', '850'],
+    '85X': ['-proc', '85X'],
+    '860': ['-proc', '860'],
+    '86X': ['-proc', '86X'],
+    '87X': ['-proc', '87X'],
+    '88X': ['-proc', '88X'],
+    '5100': ['-proc', '5100'],
+    '5200': ['-proc', '5200'],
+    '7400': ['-proc', '7400'],
+    '744X': ['-proc', '744X'],
+    '7450': ['-proc', '7450'],
+    '745X': ['-proc', '745X'],
+    '82XX': ['-proc', '82XX'],
+    '8240': ['-proc', '8240'],
+    '824X': ['-proc', '824X'],
+    '8260': ['-proc', '8260'],
+    '827X': ['-proc', '827X'],
+    '8280': ['-proc', '8280'],
+    'e300': ['-proc', 'e300'],
+    'e300c2': ['-proc', 'e300c2'],
+    'e300c3': ['-proc', 'e300c3'],
+    'e300c4': ['-proc', 'e300c4'],
+    'e600': ['-proc', 'e600'],
+    '85xx': ['-proc', '85xx'],
+    'e500': ['-proc', 'e500'],
+    'e500v2': ['-proc', 'e500v2'],
+    'Zen': ['-proc', 'Zen'],
+    '5565': ['-proc', '5565'],
+    '5674': ['-proc', '5674'],
+    'gekko': ['-proc', 'gekko'],
+    'generic': ['-proc', 'generic'],
+}  # type: T.Dict[str, T.List[str]]
+
+mwcc_optimization_args = {
+    'plain': [],
+    '0': ['-O0'],
+    'g': ['-Op'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-Os']
+}  # type: T.Dict[str, T.List[str]]
+
+mwcc_debug_args = {
+    False: [],
+    True: ['-g']
+}  # type: T.Dict[bool, T.List[str]]
+
+
+class MetrowerksCompiler(Compiler):
+    id = 'mwcc'
+
+    # These compilers can actually invoke the linker, but they choke on
+    # linker-specific flags. So it's best to invoke the linker directly
+    INVOKES_LINKER = False
+
+    def __init__(self) -> None:
+        if not self.is_cross:
+            raise EnvironmentException(f'{id} supports only cross-compilation.')
+
+        self.base_options = {
+            OptionKey(o) for o in ['b_pch', 'b_ndebug']}
+
+        default_warn_args = []  # type: T.List[str]
+        self.warn_args = {'0': ['-w', 'off'],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-w', 'most'],
+                          '3': default_warn_args + ['-w', 'all'],
+                          'everything': default_warn_args + ['-w', 'full']}  # type: T.Dict[str, T.List[str]]
+
+    def depfile_for_object(self, objfile: str) -> T.Optional[str]:
+        # Earlier versions of these compilers do not support specifying
+        # a custom name for a depfile, and can only generate '.d'
+        return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix()
+
+    def get_always_args(self) -> T.List[str]:
+        return ['-gccinc']
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return mwcc_buildtype_args[buildtype]
+
+    def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
+        return []
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return ['-c']
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return mwcc_debug_args[is_debug]
+
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
+        # Check comment in depfile_for_object()
+        return ['-gccdep', '-MD']
+
+    def get_depfile_suffix(self) -> str:
+        return 'd'
+
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        if not path:
+            path = '.'
+        return ['-I' + path]
+
+    def get_no_optimization_args(self) -> T.List[str]:
+        return ['-opt', 'off']
+
+    def get_no_stdinc_args(self) -> T.List[str]:
+        return ['-nostdinc']
+
+    def get_no_stdlib_link_args(self) -> T.List[str]:
+        return ['-nostdlib']
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return mwcc_optimization_args[optimization_level]
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return ['-o', target]
+
+    def get_pic_args(self) -> T.List[str]:
+        return ['-pic']
+
+    def get_preprocess_only_args(self) -> T.List[str]:
+        return ['-E']
+
+    def get_preprocess_to_file_args(self) -> T.List[str]:
+        return ['-P']
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return ['-prefix', self.get_pch_name(header)]
+
+    def get_pch_name(self, name: str) -> str:
+        return os.path.basename(name) + '.' + self.get_pch_suffix()
+
+    def get_pch_suffix(self) -> str:
+        return 'mch'
+
+    def get_warn_args(self, level: str) -> T.List[str]:
+        return self.warn_args[level]
+
+    def get_werror_args(self) -> T.List[str]:
+        return ['-w', 'error']
+
+    @classmethod
+    def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]:
+        result = []
+        for i in args:
+            if i.startswith('-D'):
+                i = '-D' + i[2:]
+            if i.startswith('-I'):
+                i = '-I' + i[2:]
+            if i.startswith('-Wl,-rpath='):
+                continue
+            elif i == '--print-search-dirs':
+                continue
+            elif i.startswith('-L'):
+                continue
+            result.append(i)
+        return result
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:2] == '-I':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+        return parameter_list
diff --git a/devtools/meson/mesonbuild/compilers/mixins/pgi.py b/devtools/meson/mesonbuild/compilers/mixins/pgi.py
new file mode 100644
index 0000000..2fa736c
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/pgi.py
@@ -0,0 +1,113 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Abstractions for the PGI family of compilers."""
+
+import typing as T
+import os
+from pathlib import Path
+
+from ..compilers import clike_debug_args, clike_optimization_args
+from ...mesonlib import OptionKey
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+pgi_buildtype_args = {
+    'plain': [],
+    'debug': [],
+    'debugoptimized': [],
+    'release': [],
+    'minsize': [],
+    'custom': [],
+}  # type: T.Dict[str, T.List[str]]
+
+
+class PGICompiler(Compiler):
+
+    id = 'pgi'
+
+    def __init__(self) -> None:
+        self.base_options = {OptionKey('b_pch')}
+
+        default_warn_args = ['-Minform=inform']
+        self.warn_args: T.Dict[str, T.List[str]] = {
+            '0': [],
+            '1': default_warn_args,
+            '2': default_warn_args,
+            '3': default_warn_args,
+            'everything': default_warn_args
+        }
+
+    def get_module_incdir_args(self) -> T.Tuple[str]:
+        return ('-module', )
+
+    def get_no_warn_args(self) -> T.List[str]:
+        return ['-silent']
+
+    def gen_import_library_args(self, implibname: str) -> T.List[str]:
+        return []
+
+    def get_pic_args(self) -> T.List[str]:
+        # PGI -fPIC is Linux only.
+        if self.info.is_linux():
+            return ['-fPIC']
+        return []
+
+    def openmp_flags(self) -> T.List[str]:
+        return ['-mp']
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return pgi_buildtype_args[buildtype]
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return clike_optimization_args[optimization_level]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return clike_debug_args[is_debug]
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:2] == '-I' or i[:2] == '-L':
+                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+        return parameter_list
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+    def get_pch_suffix(self) -> str:
+        # PGI defaults to .pch suffix for PCH on Linux and Windows with --pch option
+        return 'pch'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        # PGI supports PCH for C++ only.
+        hdr = Path(pch_dir).resolve().parent / header
+        if self.language == 'cpp':
+            return ['--pch',
+                    '--pch_dir', str(hdr.parent),
+                    f'-I{hdr.parent}']
+        else:
+            return []
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        # PGI cannot accept -pthread, it's already threaded
+        return []
diff --git a/devtools/meson/mesonbuild/compilers/mixins/ti.py b/devtools/meson/mesonbuild/compilers/mixins/ti.py
new file mode 100644
index 0000000..950c97f
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/ti.py
@@ -0,0 +1,151 @@
+# Copyright 2012-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Representations specific to the Texas Instruments compiler family."""
+
+import os
+import typing as T
+
+from ...mesonlib import EnvironmentException
+
+if T.TYPE_CHECKING:
+    from ...envconfig import MachineInfo
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+ti_buildtype_args = {
+    'plain': [],
+    'debug': [],
+    'debugoptimized': [],
+    'release': [],
+    'minsize': [],
+    'custom': [],
+}  # type: T.Dict[str, T.List[str]]
+
+ti_optimization_args = {
+    'plain': [],
+    '0': ['-O0'],
+    'g': ['-Ooff'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-O4']
+}  # type: T.Dict[str, T.List[str]]
+
+ti_debug_args = {
+    False: [],
+    True: ['-g']
+}  # type: T.Dict[bool, T.List[str]]
+
+
+class TICompiler(Compiler):
+
+    id = 'ti'
+
+    def __init__(self) -> None:
+        if not self.is_cross:
+            raise EnvironmentException('TI compilers only support cross-compilation.')
+
+        self.can_compile_suffixes.add('asm')    # Assembly
+        self.can_compile_suffixes.add('cla')    # Control Law Accelerator (CLA) used in C2000
+
+        default_warn_args = []  # type: T.List[str]
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + [],
+                          '3': default_warn_args + [],
+                          'everything': default_warn_args + []}  # type: T.Dict[str, T.List[str]]
+
+    def get_pic_args(self) -> T.List[str]:
+        # PIC support is not enabled by default for TI compilers,
+        # if users want to use it, they need to add the required arguments explicitly
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return ti_buildtype_args[buildtype]
+
+    def get_pch_suffix(self) -> str:
+        return 'pch'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return []
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def get_coverage_args(self) -> T.List[str]:
+        return []
+
+    def get_no_stdinc_args(self) -> T.List[str]:
+        return []
+
+    def get_no_stdlib_link_args(self) -> T.List[str]:
+        return []
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return ti_optimization_args[optimization_level]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return ti_debug_args[is_debug]
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return []
+
+    def get_no_optimization_args(self) -> T.List[str]:
+        return ['-Ooff']
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [f'--output_file={target}']
+
+    def get_werror_args(self) -> T.List[str]:
+        return ['--emit_warnings_as_errors']
+
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        if path == '':
+            path = '.'
+        return ['-I=' + path]
+
+    @classmethod
+    def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]:
+        result = []
+        for i in args:
+            if i.startswith('-D'):
+                i = '--define=' + i[2:]
+            if i.startswith('-Wl,-rpath='):
+                continue
+            elif i == '--print-search-dirs':
+                continue
+            elif i.startswith('-L'):
+                continue
+            result.append(i)
+        return result
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:15] == '--include_path=':
+                parameter_list[idx] = i[:15] + os.path.normpath(os.path.join(build_dir, i[15:]))
+            if i[:2] == '-I':
+                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+
+        return parameter_list
+
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
+        return ['--preproc_with_compile', f'--preproc_dependency={outfile}']
diff --git a/devtools/meson/mesonbuild/compilers/mixins/visualstudio.py b/devtools/meson/mesonbuild/compilers/mixins/visualstudio.py
new file mode 100644
index 0000000..8b8cea6
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/visualstudio.py
@@ -0,0 +1,503 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Abstractions to simplify compilers that implement an MSVC compatible
+interface.
+"""
+
+import abc
+import os
+import typing as T
+
+from ... import arglist
+from ... import mesonlib
+from ... import mlog
+
+if T.TYPE_CHECKING:
+    from ...environment import Environment
+    from ...dependencies import Dependency
+    from .clike import CLikeCompiler as Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+vs32_instruction_set_args = {
+    'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX
+    'sse': ['/arch:SSE'],
+    'sse2': ['/arch:SSE2'],
+    'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX.
+    'sse41': ['/arch:AVX'],
+    'sse42': ['/arch:AVX'],
+    'avx': ['/arch:AVX'],
+    'avx2': ['/arch:AVX2'],
+    'neon': None,
+}  # T.Dicst[str, T.Optional[T.List[str]]]
+
+# The 64 bit compiler defaults to /arch:avx.
+vs64_instruction_set_args = {
+    'mmx': ['/arch:AVX'],
+    'sse': ['/arch:AVX'],
+    'sse2': ['/arch:AVX'],
+    'sse3': ['/arch:AVX'],
+    'ssse3': ['/arch:AVX'],
+    'sse41': ['/arch:AVX'],
+    'sse42': ['/arch:AVX'],
+    'avx': ['/arch:AVX'],
+    'avx2': ['/arch:AVX2'],
+    'neon': None,
+}  # T.Dicst[str, T.Optional[T.List[str]]]
+
+msvc_optimization_args = {
+    'plain': [],
+    '0': ['/Od'],
+    'g': [], # No specific flag to optimize debugging, /Zi or /ZI will create debug information
+    '1': ['/O1'],
+    '2': ['/O2'],
+    '3': ['/O2', '/Gw'],
+    's': ['/O1', '/Gw'],
+}  # type: T.Dict[str, T.List[str]]
+
+msvc_debug_args = {
+    # BEN: always generate PDBs actually.
+    False: ['/Zi'],
+    True: ['/Zi']
+}  # type: T.Dict[bool, T.List[str]]
+
+
+class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta):
+
+    """A common interface for all compilers implementing an MSVC-style
+    interface.
+
+    A number of compilers attempt to mimic MSVC, with varying levels of
+    success, such as Clang-CL and ICL (the Intel C/C++ Compiler for Windows).
+    This class implements as much common logic as possible.
+    """
+
+    std_warn_args = ['/W3']
+    std_opt_args = ['/O2']
+    ignore_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS + ['execinfo']
+    internal_libs = []  # type: T.List[str]
+
+    crt_args = {
+        'none': [],
+        'md': ['/MD'],
+        'mdd': ['/MDd'],
+        'mt': ['/MT'],
+        'mtd': ['/MTd'],
+    }  # type: T.Dict[str, T.List[str]]
+
+    # /showIncludes is needed for build dependency tracking in Ninja
+    # See: https://ninja-build.org/manual.html#_deps
+    # Assume UTF-8 sources by default, but self.unix_args_to_native() removes it
+    # if `/source-charset` is set too.
+    # It is also dropped if Visual Studio 2013 or earlier is used, since it would
+    # not be supported in that case.
+    always_args = ['/nologo', '/showIncludes', '/utf-8']
+    warn_args = {
+        '0': [],
+        '1': ['/W2'],
+        '2': ['/W3'],
+        '3': ['/W4'],
+        'everything': ['/Wall'],
+    }  # type: T.Dict[str, T.List[str]]
+
+    INVOKES_LINKER = False
+
+    def __init__(self, target: str):
+        self.base_options = {mesonlib.OptionKey(o) for o in ['b_pch', 'b_ndebug', 'b_vscrt']} # FIXME add lto, pgo and the like
+        self.target = target
+        self.is_64 = ('x64' in target) or ('x86_64' in target)
+        # do some canonicalization of target machine
+        if 'x86_64' in target:
+            self.machine = 'x64'
+        elif '86' in target:
+            self.machine = 'x86'
+        elif 'aarch64' in target:
+            self.machine = 'arm64'
+        elif 'arm' in target:
+            self.machine = 'arm'
+        else:
+            self.machine = target
+        if mesonlib.version_compare(self.version, '>=19.28.29910'): # VS 16.9.0 includes cl 19.28.29910
+            self.base_options.add(mesonlib.OptionKey('b_sanitize'))
+        assert self.linker is not None
+        self.linker.machine = self.machine
+
+    # Override CCompiler.get_always_args
+    def get_always_args(self) -> T.List[str]:
+        # TODO: use ImmutableListProtocol[str] here instead
+        return self.always_args.copy()
+
+    def get_pch_suffix(self) -> str:
+        return 'pch'
+
+    def get_pch_name(self, header: str) -> str:
+        chopped = os.path.basename(header).split('.')[:-1]
+        chopped.append(self.get_pch_suffix())
+        pchname = '.'.join(chopped)
+        return pchname
+
+    def get_pch_base_name(self, header: str) -> str:
+        # This needs to be implemented by inheriting classes
+        raise NotImplementedError
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        base = self.get_pch_base_name(header)
+        pchname = self.get_pch_name(header)
+        return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)]
+
+    def get_preprocess_only_args(self) -> T.List[str]:
+        return ['/EP']
+
+    def get_preprocess_to_file_args(self) -> T.List[str]:
+        return ['/EP', '/P']
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return ['/c']
+
+    def get_no_optimization_args(self) -> T.List[str]:
+        return ['/Od', '/Oi-']
+
+    def sanitizer_compile_args(self, value: str) -> T.List[str]:
+        if value == 'none':
+            return []
+        if value != 'address':
+            raise mesonlib.MesonException('VS only supports address sanitizer at the moment.')
+        return ['/fsanitize=address']
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        if self.mode == 'PREPROCESSOR':
+            return ['/Fi' + target]
+        if target.endswith('.exe'):
+            return ['/Fe' + target]
+        return ['/Fo' + target]
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return []
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return msvc_debug_args[is_debug]
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        args = msvc_optimization_args[optimization_level]
+        if mesonlib.version_compare(self.version, '<18.0'):
+            args = [arg for arg in args if arg != '/Gw']
+        return args
+
+    def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]:
+        return ['/link'] + args
+
+    def get_pic_args(self) -> T.List[str]:
+        return [] # PIC is handled by the loader on Windows
+
+    def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]:
+        if not isinstance(defsfile, str):
+            raise RuntimeError('Module definitions file should be str')
+        # With MSVC, DLLs only export symbols that are explicitly exported,
+        # so if a module defs file is specified, we use that to export symbols
+        return ['/DEF:' + defsfile]
+
+    def gen_pch_args(self, header: str, source: str, pchname: str) -> T.Tuple[str, T.List[str]]:
+        objname = os.path.splitext(source)[0] + '.obj'
+        return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname]
+
+    def openmp_flags(self) -> T.List[str]:
+        return ['/openmp']
+
+    def openmp_link_flags(self) -> T.List[str]:
+        return []
+
+    # FIXME, no idea what these should be.
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    @classmethod
+    def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]:
+        result: T.List[str] = []
+        for i in args:
+            # -mms-bitfields is specific to MinGW-GCC
+            # -pthread is only valid for GCC
+            if i in {'-mms-bitfields', '-pthread'}:
+                continue
+            if i.startswith('-LIBPATH:'):
+                i = '/LIBPATH:' + i[9:]
+            elif i.startswith('-L'):
+                i = '/LIBPATH:' + i[2:]
+            # Translate GNU-style -lfoo library name to the import library
+            elif i.startswith('-l'):
+                name = i[2:]
+                if name in cls.ignore_libs:
+                    # With MSVC, these are provided by the C runtime which is
+                    # linked in by default
+                    continue
+                else:
+                    i = name + '.lib'
+            elif i.startswith('-isystem'):
+                # just use /I for -isystem system include path s
+                if i.startswith('-isystem='):
+                    i = '/I' + i[9:]
+                else:
+                    i = '/I' + i[8:]
+            elif i.startswith('-idirafter'):
+                # same as -isystem, but appends the path instead
+                if i.startswith('-idirafter='):
+                    i = '/I' + i[11:]
+                else:
+                    i = '/I' + i[10:]
+            # -pthread in link flags is only used on Linux
+            elif i == '-pthread':
+                continue
+            # cl.exe does not allow specifying both, so remove /utf-8 that we
+            # added automatically in the case the user overrides it manually.
+            elif (i.startswith('/source-charset:')
+                    or i.startswith('/execution-charset:')
+                    or i == '/validate-charset-'):
+                try:
+                    result.remove('/utf-8')
+                except ValueError:
+                    pass
+            result.append(i)
+        return result
+
+    @classmethod
+    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
+        result = []
+        for arg in args:
+            if arg.startswith(('/LIBPATH:', '-LIBPATH:')):
+                result.append('-L' + arg[9:])
+            elif arg.endswith(('.a', '.lib')) and not os.path.isabs(arg):
+                result.append('-l' + arg)
+            else:
+                result.append(arg)
+        return result
+
+    def get_werror_args(self) -> T.List[str]:
+        return ['/WX']
+
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        if path == '':
+            path = '.'
+        # msvc does not have a concept of system header dirs.
+        return ['-I' + path]
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:2] == '-I' or i[:2] == '/I':
+                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+            elif i[:9] == '/LIBPATH:':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+        return parameter_list
+
+    # Visual Studio is special. It ignores some arguments it does not
+    # understand and you can't tell it to error out on those.
+    # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t
+    def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]:
+        warning_text = '4044' if mode == 'link' else '9002'
+        with self._build_wrapper(code, env, extra_args=args, mode=mode) as p:
+            if p.returncode != 0:
+                return False, p.cached
+            return not (warning_text in p.stderr or warning_text in p.stdout), p.cached
+
+    def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
+        # BEN: always give pdb file a reasonable name
+        pdbarr = target.get_basename() #rel_obj.split('.')[:-1]
+        pdbarr += ['pdb']
+        args = ['/Fd' + '.'.join(pdbarr)]
+        return args
+
+    def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
+        if self.is_64:
+            return vs64_instruction_set_args.get(instruction_set, None)
+        return vs32_instruction_set_args.get(instruction_set, None)
+
+    def _calculate_toolset_version(self, version: int) -> T.Optional[str]:
+        if version < 1310:
+            return '7.0'
+        elif version < 1400:
+            return '7.1' # (Visual Studio 2003)
+        elif version < 1500:
+            return '8.0' # (Visual Studio 2005)
+        elif version < 1600:
+            return '9.0' # (Visual Studio 2008)
+        elif version < 1700:
+            return '10.0' # (Visual Studio 2010)
+        elif version < 1800:
+            return '11.0' # (Visual Studio 2012)
+        elif version < 1900:
+            return '12.0' # (Visual Studio 2013)
+        elif version < 1910:
+            return '14.0' # (Visual Studio 2015)
+        elif version < 1920:
+            return '14.1' # (Visual Studio 2017)
+        elif version < 1930:
+            return '14.2' # (Visual Studio 2019)
+        elif version < 1940:
+            return '14.3' # (Visual Studio 2022)
+        mlog.warning(f'Could not find toolset for version {self.version!r}')
+        return None
+
+    def get_toolset_version(self) -> T.Optional[str]:
+        # See boost/config/compiler/visualc.cpp for up to date mapping
+        try:
+            version = int(''.join(self.version.split('.')[0:2]))
+        except ValueError:
+            return None
+        return self._calculate_toolset_version(version)
+
+    def get_default_include_dirs(self) -> T.List[str]:
+        if 'INCLUDE' not in os.environ:
+            return []
+        return os.environ['INCLUDE'].split(os.pathsep)
+
+    def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+        if crt_val in self.crt_args:
+            return self.crt_args[crt_val]
+        assert crt_val in {'from_buildtype', 'static_from_buildtype'}
+        dbg = 'mdd'
+        rel = 'md'
+        if crt_val == 'static_from_buildtype':
+            dbg = 'mtd'
+            rel = 'mt'
+        # Match what build type flags used to do.
+        if buildtype == 'plain':
+            return []
+        elif buildtype == 'debug':
+            return self.crt_args[dbg]
+        elif buildtype == 'debugoptimized':
+            return self.crt_args[rel]
+        elif buildtype == 'release':
+            return self.crt_args[rel]
+        elif buildtype == 'minsize':
+            return self.crt_args[rel]
+        else:
+            assert buildtype == 'custom'
+            raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
+
+    def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
+        # MSVC doesn't have __attribute__ like Clang and GCC do, so just return
+        # false without compiling anything
+        return name in {'dllimport', 'dllexport'}, False
+
+    def get_argument_syntax(self) -> str:
+        return 'msvc'
+
+    def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
+        '''
+        Check if the compiler prefixes an underscore to global C symbols.
+
+        This overrides the Clike method, as for MSVC checking the
+        underscore prefix based on the compiler define never works,
+        so do not even try.
+        '''
+        # Try to consult a hardcoded list of cases we know
+        # absolutely have an underscore prefix
+        result = self._symbols_have_underscore_prefix_list(env)
+        if result is not None:
+            return result
+
+        # As a last resort, try search in a compiled binary
+        return self._symbols_have_underscore_prefix_searchbin(env)
+
+
+class MSVCCompiler(VisualStudioLikeCompiler):
+
+    """Specific to the Microsoft Compilers."""
+
+    id = 'msvc'
+
+    def __init__(self, target: str):
+        super().__init__(target)
+
+        # Visual Studio 2013 and earlier don't support the /utf-8 argument.
+        # We want to remove it. We also want to make an explicit copy so we
+        # don't mutate class constant state
+        if mesonlib.version_compare(self.version, '<19.00') and '/utf-8' in self.always_args:
+            self.always_args = [r for r in self.always_args if r != '/utf-8']
+
+    def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
+        args = super().get_compile_debugfile_args(rel_obj, pch)
+        # When generating a PDB file with PCH, all compile commands write
+        # to the same PDB file. Hence, we need to serialize the PDB
+        # writes using /FS since we do parallel builds. This slows down the
+        # build obviously, which is why we only do this when PCH is on.
+        # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was
+        # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx
+        if pch and mesonlib.version_compare(self.version, '>=18.0'):
+            args = ['/FS'] + args
+        return args
+
+    # Override CCompiler.get_always_args
+    # We want to drop '/utf-8' for Visual Studio 2013 and earlier
+    def get_always_args(self) -> T.List[str]:
+        return self.always_args
+
+    def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]:
+        if self.version.split('.')[0] == '16' and instruction_set == 'avx':
+            # VS documentation says that this exists and should work, but
+            # it does not. The headers do not contain AVX intrinsics
+            # and they cannot be called.
+            return None
+        return super().get_instruction_set_args(instruction_set)
+
+    def get_pch_base_name(self, header: str) -> str:
+        return os.path.basename(header)
+
+
+class ClangClCompiler(VisualStudioLikeCompiler):
+
+    """Specific to Clang-CL."""
+
+    id = 'clang-cl'
+
+    def __init__(self, target: str):
+        super().__init__(target)
+
+        # Assembly
+        self.can_compile_suffixes.add('s')
+        self.can_compile_suffixes.add('sx')
+
+    def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: str) -> T.Tuple[bool, bool]:
+        if mode != 'link':
+            args = args + ['-Werror=unknown-argument', '-Werror=unknown-warning-option']
+        return super().has_arguments(args, env, code, mode)
+
+    def get_toolset_version(self) -> T.Optional[str]:
+        # XXX: what is the right thing to do here?
+        return '14.1'
+
+    def get_pch_base_name(self, header: str) -> str:
+        return header
+
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        if path == '':
+            path = '.'
+        return ['/clang:-isystem' + path] if is_system else ['-I' + path]
+
+    def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]:
+        if dep.get_include_type() == 'system':
+            converted = []
+            for i in dep.get_compile_args():
+                if i.startswith('-isystem'):
+                    converted += ['/clang:' + i]
+                else:
+                    converted += [i]
+            return converted
+        else:
+            return dep.get_compile_args()
diff --git a/devtools/meson/mesonbuild/compilers/mixins/xc16.py b/devtools/meson/mesonbuild/compilers/mixins/xc16.py
new file mode 100644
index 0000000..36c2c10
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/mixins/xc16.py
@@ -0,0 +1,133 @@
+# Copyright 2012-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Representations specific to the Microchip XC16 C compiler family."""
+
+import os
+import typing as T
+
+from ...mesonlib import EnvironmentException
+
+if T.TYPE_CHECKING:
+    from ...envconfig import MachineInfo
+    from ...environment import Environment
+    from ...compilers.compilers import Compiler
+else:
+    # This is a bit clever, for mypy we pretend that these mixins descend from
+    # Compiler, so we get all of the methods and attributes defined for us, but
+    # for runtime we make them descend from object (which all classes normally
+    # do). This gives up DRYer type checking, with no runtime impact
+    Compiler = object
+
+xc16_buildtype_args = {
+    'plain': [],
+    'debug': [],
+    'debugoptimized': [],
+    'release': [],
+    'minsize': [],
+    'custom': [],
+}  # type: T.Dict[str, T.List[str]]
+
+xc16_optimization_args = {
+    'plain': [],
+    '0': ['-O0'],
+    'g': ['-O0'],
+    '1': ['-O1'],
+    '2': ['-O2'],
+    '3': ['-O3'],
+    's': ['-Os']
+}  # type: T.Dict[str, T.List[str]]
+
+xc16_debug_args = {
+    False: [],
+    True: []
+}  # type: T.Dict[bool, T.List[str]]
+
+
+class Xc16Compiler(Compiler):
+
+    id = 'xc16'
+
+    def __init__(self) -> None:
+        if not self.is_cross:
+            raise EnvironmentException('xc16 supports only cross-compilation.')
+        # Assembly
+        self.can_compile_suffixes.add('s')
+        self.can_compile_suffixes.add('sx')
+        default_warn_args = []  # type: T.List[str]
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + [],
+                          '3': default_warn_args + [],
+                          'everything': default_warn_args + []}  # type: T.Dict[str, T.List[str]]
+
+    def get_always_args(self) -> T.List[str]:
+        return []
+
+    def get_pic_args(self) -> T.List[str]:
+        # PIC support is not enabled by default for xc16,
+        # if users want to use it, they need to add the required arguments explicitly
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return xc16_buildtype_args[buildtype]
+
+    def get_pch_suffix(self) -> str:
+        return 'pch'
+
+    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
+        return []
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def get_coverage_args(self) -> T.List[str]:
+        return []
+
+    def get_no_stdinc_args(self) -> T.List[str]:
+        return ['-nostdinc']
+
+    def get_no_stdlib_link_args(self) -> T.List[str]:
+        return ['--nostdlib']
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return xc16_optimization_args[optimization_level]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return xc16_debug_args[is_debug]
+
+    @classmethod
+    def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]:
+        result = []
+        for i in args:
+            if i.startswith('-D'):
+                i = '-D' + i[2:]
+            if i.startswith('-I'):
+                i = '-I' + i[2:]
+            if i.startswith('-Wl,-rpath='):
+                continue
+            elif i == '--print-search-dirs':
+                continue
+            elif i.startswith('-L'):
+                continue
+            result.append(i)
+        return result
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:9] == '-I':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+        return parameter_list
diff --git a/devtools/meson/mesonbuild/compilers/objc.py b/devtools/meson/mesonbuild/compilers/objc.py
new file mode 100644
index 0000000..cb8eb9e
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/objc.py
@@ -0,0 +1,114 @@
+# Copyright 2012-2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import typing as T
+
+from .. import coredata
+from ..mesonlib import OptionKey
+
+from .compilers import Compiler
+from .mixins.clike import CLikeCompiler
+from .mixins.gnu import GnuCompiler, gnu_common_warning_args, gnu_objc_warning_args
+from .mixins.clang import ClangCompiler
+
+if T.TYPE_CHECKING:
+    from ..programs import ExternalProgram
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..linkers.linkers import DynamicLinker
+    from ..mesonlib import MachineChoice
+
+
+class ObjCCompiler(CLikeCompiler, Compiler):
+
+    language = 'objc'
+
+    def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrap: T.Optional['ExternalProgram'],
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        Compiler.__init__(self, ccache, exelist, version, for_machine, info,
+                          is_cross=is_cross, full_version=full_version,
+                          linker=linker)
+        CLikeCompiler.__init__(self, exe_wrap)
+
+    @staticmethod
+    def get_display_language() -> str:
+        return 'Objective-C'
+
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        code = '#import\nint main(void) { return 0; }\n'
+        return self._sanity_check_impl(work_dir, environment, 'sanitycheckobjc.m', code)
+
+
+class GnuObjCCompiler(GnuCompiler, ObjCCompiler):
+    def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        ObjCCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross,
+                              info, exe_wrapper, linker=linker, full_version=full_version)
+        GnuCompiler.__init__(self, defines)
+        default_warn_args = ['-Wall', '-Winvalid-pch']
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-Wextra'],
+                          '3': default_warn_args + ['-Wextra', '-Wpedantic'],
+                          'everything': (default_warn_args + ['-Wextra', '-Wpedantic'] +
+                                         self.supported_warn_args(gnu_common_warning_args) +
+                                         self.supported_warn_args(gnu_objc_warning_args))}
+
+
+class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
+    def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        ObjCCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross,
+                              info, exe_wrapper, linker=linker, full_version=full_version)
+        ClangCompiler.__init__(self, defines)
+        default_warn_args = ['-Wall', '-Winvalid-pch']
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-Wextra'],
+                          '3': default_warn_args + ['-Wextra', '-Wpedantic'],
+                          'everything': ['-Weverything']}
+
+    def get_options(self) -> 'coredata.MutableKeyedOptionDictType':
+        opts = super().get_options()
+        opts.update({
+            OptionKey('std', machine=self.for_machine, lang='c'): coredata.UserComboOption(
+                'C language standard to use',
+                ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'],
+                'none',
+            )
+        })
+        return opts
+
+    def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
+        args = []
+        std = options[OptionKey('std', machine=self.for_machine, lang='c')]
+        if std.value != 'none':
+            args.append('-std=' + std.value)
+        return args
+
+class AppleClangObjCCompiler(ClangObjCCompiler):
+
+    """Handle the differences between Apple's clang and vanilla clang."""
diff --git a/devtools/meson/mesonbuild/compilers/objcpp.py b/devtools/meson/mesonbuild/compilers/objcpp.py
new file mode 100644
index 0000000..530bc7c
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/objcpp.py
@@ -0,0 +1,115 @@
+# Copyright 2012-2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import typing as T
+
+from .. import coredata
+from ..mesonlib import OptionKey
+
+from .mixins.clike import CLikeCompiler
+from .compilers import Compiler
+from .mixins.gnu import GnuCompiler, gnu_common_warning_args, gnu_objc_warning_args
+from .mixins.clang import ClangCompiler
+
+if T.TYPE_CHECKING:
+    from ..programs import ExternalProgram
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..linkers.linkers import DynamicLinker
+    from ..mesonlib import MachineChoice
+
+class ObjCPPCompiler(CLikeCompiler, Compiler):
+
+    language = 'objcpp'
+
+    def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrap: T.Optional['ExternalProgram'],
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        Compiler.__init__(self, ccache, exelist, version, for_machine, info,
+                          is_cross=is_cross, full_version=full_version,
+                          linker=linker)
+        CLikeCompiler.__init__(self, exe_wrap)
+
+    @staticmethod
+    def get_display_language() -> str:
+        return 'Objective-C++'
+
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        code = '#import\nclass MyClass;int main(void) { return 0; }\n'
+        return self._sanity_check_impl(work_dir, environment, 'sanitycheckobjcpp.mm', code)
+
+
+class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
+    def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        ObjCPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross,
+                                info, exe_wrapper, linker=linker, full_version=full_version)
+        GnuCompiler.__init__(self, defines)
+        default_warn_args = ['-Wall', '-Winvalid-pch']
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-Wextra'],
+                          '3': default_warn_args + ['-Wextra', '-Wpedantic'],
+                          'everything': (default_warn_args + ['-Wextra', '-Wpedantic'] +
+                                         self.supported_warn_args(gnu_common_warning_args) +
+                                         self.supported_warn_args(gnu_objc_warning_args))}
+
+
+class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
+
+    def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 defines: T.Optional[T.Dict[str, str]] = None,
+                 linker: T.Optional['DynamicLinker'] = None,
+                 full_version: T.Optional[str] = None):
+        ObjCPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross,
+                                info, exe_wrapper, linker=linker, full_version=full_version)
+        ClangCompiler.__init__(self, defines)
+        default_warn_args = ['-Wall', '-Winvalid-pch']
+        self.warn_args = {'0': [],
+                          '1': default_warn_args,
+                          '2': default_warn_args + ['-Wextra'],
+                          '3': default_warn_args + ['-Wextra', '-Wpedantic'],
+                          'everything': ['-Weverything']}
+
+    def get_options(self) -> 'coredata.MutableKeyedOptionDictType':
+        opts = super().get_options()
+        opts.update({
+            OptionKey('std', machine=self.for_machine, lang='cpp'): coredata.UserComboOption(
+                'C++ language standard to use',
+                ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17'],
+                'none',
+            )
+        })
+        return opts
+
+    def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
+        args = []
+        std = options[OptionKey('std', machine=self.for_machine, lang='cpp')]
+        if std.value != 'none':
+            args.append('-std=' + std.value)
+        return args
+
+
+class AppleClangObjCPPCompiler(ClangObjCPPCompiler):
+
+    """Handle the differences between Apple's clang and vanilla clang."""
diff --git a/devtools/meson/mesonbuild/compilers/rust.py b/devtools/meson/mesonbuild/compilers/rust.py
new file mode 100644
index 0000000..ef0390e
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/rust.py
@@ -0,0 +1,230 @@
+# Copyright 2012-2022 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import subprocess, os.path
+import textwrap
+import re
+import typing as T
+
+from .. import coredata, mlog
+from ..mesonlib import EnvironmentException, MesonException, Popen_safe, OptionKey, join_args
+from .compilers import Compiler, rust_buildtype_args, clike_debug_args
+
+if T.TYPE_CHECKING:
+    from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType
+    from ..envconfig import MachineInfo
+    from ..environment import Environment  # noqa: F401
+    from ..linkers.linkers import DynamicLinker
+    from ..mesonlib import MachineChoice
+    from ..programs import ExternalProgram
+    from ..dependencies import Dependency
+
+
+rust_optimization_args = {
+    'plain': [],
+    '0': [],
+    'g': ['-C', 'opt-level=0'],
+    '1': ['-C', 'opt-level=1'],
+    '2': ['-C', 'opt-level=2'],
+    '3': ['-C', 'opt-level=3'],
+    's': ['-C', 'opt-level=s'],
+}  # type: T.Dict[str, T.List[str]]
+
+class RustCompiler(Compiler):
+
+    # rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX
+    language = 'rust'
+    id = 'rustc'
+
+    _WARNING_LEVELS: T.Dict[str, T.List[str]] = {
+        '0': ['-A', 'warnings'],
+        '1': [],
+        '2': [],
+        '3': ['-W', 'warnings'],
+    }
+
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo',
+                 exe_wrapper: T.Optional['ExternalProgram'] = None,
+                 full_version: T.Optional[str] = None,
+                 linker: T.Optional['DynamicLinker'] = None):
+        super().__init__([], exelist, version, for_machine, info,
+                         is_cross=is_cross, full_version=full_version,
+                         linker=linker)
+        self.exe_wrapper = exe_wrapper
+        self.base_options.update({OptionKey(o) for o in ['b_colorout', 'b_ndebug']})
+        if 'link' in self.linker.id:
+            self.base_options.add(OptionKey('b_vscrt'))
+        self.native_static_libs: T.List[str] = []
+
+    def needs_static_linker(self) -> bool:
+        return False
+
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        source_name = os.path.join(work_dir, 'sanity.rs')
+        output_name = os.path.join(work_dir, 'rusttest')
+        with open(source_name, 'w', encoding='utf-8') as ofile:
+            ofile.write(textwrap.dedent(
+                '''fn main() {
+                }
+                '''))
+
+        cmdlist = self.exelist + ['-o', output_name, source_name]
+        pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir)
+        mlog.debug('Sanity check compiler command line:', join_args(cmdlist))
+        mlog.debug('Sanity check compile stdout:')
+        mlog.debug(stdo)
+        mlog.debug('-----\nSanity check compile stderr:')
+        mlog.debug(stde)
+        mlog.debug('-----')
+        if pc.returncode != 0:
+            raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.')
+        if self.is_cross:
+            if self.exe_wrapper is None:
+                # Can't check if the binaries run so we have to assume they do
+                return
+            cmdlist = self.exe_wrapper.get_command() + [output_name]
+        else:
+            cmdlist = [output_name]
+        pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+        pe.wait()
+        if pe.returncode != 0:
+            raise EnvironmentException(f'Executables created by Rust compiler {self.name_string()} are not runnable.')
+        # Get libraries needed to link with a Rust staticlib
+        cmdlist = self.exelist + ['--crate-type', 'staticlib', '--print', 'native-static-libs', source_name]
+        p, stdo, stde = Popen_safe(cmdlist, cwd=work_dir)
+        if p.returncode == 0:
+            match = re.search('native-static-libs: (.*)$', stde, re.MULTILINE)
+            if match:
+                # Exclude some well known libraries that we don't need because they
+                # are always part of C/C++ linkers. Rustc probably should not print
+                # them, pkg-config for example never specify them.
+                # FIXME: https://github.com/rust-lang/rust/issues/55120
+                exclude = {'-lc', '-lgcc_s', '-lkernel32', '-ladvapi32'}
+                self.native_static_libs = [i for i in match.group(1).split() if i not in exclude]
+
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
+        return ['--dep-info', outfile]
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return rust_buildtype_args[buildtype]
+
+    def get_sysroot(self) -> str:
+        cmd = self.get_exelist(ccache=False) + ['--print', 'sysroot']
+        p, stdo, stde = Popen_safe(cmd)
+        return stdo.split('\n', maxsplit=1)[0]
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return clike_debug_args[is_debug]
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return rust_optimization_args[optimization_level]
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+                                               build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:2] == '-L':
+                for j in ['dependency', 'crate', 'native', 'framework', 'all']:
+                    combined_len = len(j) + 3
+                    if i[:combined_len] == f'-L{j}=':
+                        parameter_list[idx] = i[:combined_len] + os.path.normpath(os.path.join(build_dir, i[combined_len:]))
+                        break
+
+        return parameter_list
+
+    def get_output_args(self, outputname: str) -> T.List[str]:
+        return ['-o', outputname]
+
+    @classmethod
+    def use_linker_args(cls, linker: str, version: str) -> T.List[str]:
+        return ['-C', f'linker={linker}']
+
+    # Rust does not have a use_linker_args because it dispatches to a gcc-like
+    # C compiler for dynamic linking, as such we invoke the C compiler's
+    # use_linker_args method instead.
+
+    def get_options(self) -> 'MutableKeyedOptionDictType':
+        key = OptionKey('std', machine=self.for_machine, lang=self.language)
+        return {
+            key: coredata.UserComboOption(
+                'Rust edition to use',
+                ['none', '2015', '2018', '2021'],
+                'none',
+            ),
+        }
+
+    def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]:
+        # Rust doesn't have dependency compile arguments so simply return
+        # nothing here. Dependencies are linked and all required metadata is
+        # provided by the linker flags.
+        return []
+
+    def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+        args = []
+        key = OptionKey('std', machine=self.for_machine, lang=self.language)
+        std = options[key]
+        if std.value != 'none':
+            args.append('--edition=' + std.value)
+        return args
+
+    def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+        # Rust handles this for us, we don't need to do anything
+        return []
+
+    def get_colorout_args(self, colortype: str) -> T.List[str]:
+        if colortype in {'always', 'never', 'auto'}:
+            return [f'--color={colortype}']
+        raise MesonException(f'Invalid color type for rust {colortype}')
+
+    def get_linker_always_args(self) -> T.List[str]:
+        args: T.List[str] = []
+        for a in super().get_linker_always_args():
+            args.extend(['-C', f'link-arg={a}'])
+        return args
+
+    def get_werror_args(self) -> T.List[str]:
+        # Use -D warnings, which makes every warning not explicitly allowed an
+        # error
+        return ['-D', 'warnings']
+
+    def get_warn_args(self, level: str) -> T.List[str]:
+        # TODO: I'm not really sure what to put here, Rustc doesn't have warning
+        return self._WARNING_LEVELS[level]
+
+    def get_no_warn_args(self) -> T.List[str]:
+        return self._WARNING_LEVELS["0"]
+
+    def get_pic_args(self) -> T.List[str]:
+        # relocation-model=pic is rustc's default already.
+        return []
+
+    def get_pie_args(self) -> T.List[str]:
+        # Rustc currently has no way to toggle this, it's controlled by whether
+        # pic is on by rustc
+        return []
+
+    def get_assert_args(self, disable: bool) -> T.List[str]:
+        action = "no" if disable else "yes"
+        return ['-C', f'debug-assertions={action}', '-C', 'overflow-checks=no']
+
+
+class ClippyRustCompiler(RustCompiler):
+
+    """Clippy is a linter that wraps Rustc.
+
+    This just provides us a different id
+    """
+
+    id = 'clippy-driver rustc'
diff --git a/devtools/meson/mesonbuild/compilers/swift.py b/devtools/meson/mesonbuild/compilers/swift.py
new file mode 100644
index 0000000..19866e2
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/swift.py
@@ -0,0 +1,130 @@
+# Copyright 2012-2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import subprocess, os.path
+import typing as T
+
+from ..mesonlib import EnvironmentException
+
+from .compilers import Compiler, swift_buildtype_args, clike_debug_args
+
+if T.TYPE_CHECKING:
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..linkers.linkers import DynamicLinker
+    from ..mesonlib import MachineChoice
+
+swift_optimization_args = {
+    'plain': [],
+    '0': [],
+    'g': [],
+    '1': ['-O'],
+    '2': ['-O'],
+    '3': ['-O'],
+    's': ['-O'],
+}  # type: T.Dict[str, T.List[str]]
+
+class SwiftCompiler(Compiler):
+
+    LINKER_PREFIX = ['-Xlinker']
+    language = 'swift'
+    id = 'llvm'
+
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo', full_version: T.Optional[str] = None,
+                 linker: T.Optional['DynamicLinker'] = None):
+        super().__init__([], exelist, version, for_machine, info,
+                         is_cross=is_cross, full_version=full_version,
+                         linker=linker)
+        self.version = version
+
+    def needs_static_linker(self) -> bool:
+        return True
+
+    def get_werror_args(self) -> T.List[str]:
+        return ['--fatal-warnings']
+
+    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
+        return ['-emit-dependencies']
+
+    def depfile_for_object(self, objfile: str) -> T.Optional[str]:
+        return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix()
+
+    def get_depfile_suffix(self) -> str:
+        return 'd'
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return ['-o', target]
+
+    def get_header_import_args(self, headername: str) -> T.List[str]:
+        return ['-import-objc-header', headername]
+
+    def get_warn_args(self, level: str) -> T.List[str]:
+        return []
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        return swift_buildtype_args[buildtype]
+
+    def get_std_exe_link_args(self) -> T.List[str]:
+        return ['-emit-executable']
+
+    def get_module_args(self, modname: str) -> T.List[str]:
+        return ['-module-name', modname]
+
+    def get_mod_gen_args(self) -> T.List[str]:
+        return ['-emit-module']
+
+    def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+        return ['-I' + path]
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return ['-c']
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+                                               build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:2] == '-I' or i[:2] == '-L':
+                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+
+        return parameter_list
+
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        src = 'swifttest.swift'
+        source_name = os.path.join(work_dir, src)
+        output_name = os.path.join(work_dir, 'swifttest')
+        extra_flags: T.List[str] = []
+        extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
+        if self.is_cross:
+            extra_flags += self.get_compile_only_args()
+        else:
+            extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
+        with open(source_name, 'w', encoding='utf-8') as ofile:
+            ofile.write('''print("Swift compilation is working.")
+''')
+        pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
+        pc.wait()
+        if pc.returncode != 0:
+            raise EnvironmentException('Swift compiler %s cannot compile programs.' % self.name_string())
+        if self.is_cross:
+            # Can't check if the binaries run so we have to assume they do
+            return
+        if subprocess.call(output_name) != 0:
+            raise EnvironmentException('Executables created by Swift compiler %s are not runnable.' % self.name_string())
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return clike_debug_args[is_debug]
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return swift_optimization_args[optimization_level]
diff --git a/devtools/meson/mesonbuild/compilers/vala.py b/devtools/meson/mesonbuild/compilers/vala.py
new file mode 100644
index 0000000..40cfc14
--- /dev/null
+++ b/devtools/meson/mesonbuild/compilers/vala.py
@@ -0,0 +1,140 @@
+# Copyright 2012-2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import os.path
+import typing as T
+
+from .. import mlog
+from ..mesonlib import EnvironmentException, version_compare, OptionKey
+
+from .compilers import Compiler, LibType
+
+if T.TYPE_CHECKING:
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+
+class ValaCompiler(Compiler):
+
+    language = 'vala'
+    id = 'valac'
+
+    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
+                 is_cross: bool, info: 'MachineInfo'):
+        super().__init__([], exelist, version, for_machine, info, is_cross=is_cross)
+        self.version = version
+        self.base_options = {OptionKey('b_colorout')}
+
+    def needs_static_linker(self) -> bool:
+        return False # Because compiles into C.
+
+    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
+        return []
+
+    def get_debug_args(self, is_debug: bool) -> T.List[str]:
+        return ['--debug'] if is_debug else []
+
+    def get_output_args(self, target: str) -> T.List[str]:
+        return [] # Because compiles into C.
+
+    def get_compile_only_args(self) -> T.List[str]:
+        return [] # Because compiles into C.
+
+    def get_pic_args(self) -> T.List[str]:
+        return []
+
+    def get_pie_args(self) -> T.List[str]:
+        return []
+
+    def get_pie_link_args(self) -> T.List[str]:
+        return []
+
+    def get_always_args(self) -> T.List[str]:
+        return ['-C']
+
+    def get_warn_args(self, warning_level: str) -> T.List[str]:
+        return []
+
+    def get_no_warn_args(self) -> T.List[str]:
+        return ['--disable-warnings']
+
+    def get_werror_args(self) -> T.List[str]:
+        return ['--fatal-warnings']
+
+    def get_colorout_args(self, colortype: str) -> T.List[str]:
+        if version_compare(self.version, '>=0.37.1'):
+            return ['--color=' + colortype]
+        return []
+
+    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
+                                               build_dir: str) -> T.List[str]:
+        for idx, i in enumerate(parameter_list):
+            if i[:9] == '--girdir=':
+                parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+            if i[:10] == '--vapidir=':
+                parameter_list[idx] = i[:10] + os.path.normpath(os.path.join(build_dir, i[10:]))
+            if i[:13] == '--includedir=':
+                parameter_list[idx] = i[:13] + os.path.normpath(os.path.join(build_dir, i[13:]))
+            if i[:14] == '--metadatadir=':
+                parameter_list[idx] = i[:14] + os.path.normpath(os.path.join(build_dir, i[14:]))
+
+        return parameter_list
+
+    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
+        code = 'class MesonSanityCheck : Object { }'
+        extra_flags: T.List[str] = []
+        extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
+        if self.is_cross:
+            extra_flags += self.get_compile_only_args()
+        else:
+            extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
+        with self.cached_compile(code, environment.coredata, extra_args=extra_flags, mode='compile') as p:
+            if p.returncode != 0:
+                msg = f'Vala compiler {self.name_string()!r} cannot compile programs'
+                raise EnvironmentException(msg)
+
+    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
+        if buildtype in {'debug', 'debugoptimized', 'minsize'}:
+            return ['--debug']
+        return []
+
+    def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
+                     libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]:
+        if extra_dirs and isinstance(extra_dirs, str):
+            extra_dirs = [extra_dirs]
+        # Valac always looks in the default vapi dir, so only search there if
+        # no extra dirs are specified.
+        if not extra_dirs:
+            code = 'class MesonFindLibrary : Object { }'
+            args: T.List[str] = []
+            args += env.coredata.get_external_args(self.for_machine, self.language)
+            vapi_args = ['--pkg', libname]
+            args += vapi_args
+            with self.cached_compile(code, env.coredata, extra_args=args, mode='compile') as p:
+                if p.returncode == 0:
+                    return vapi_args
+        # Not found? Try to find the vapi file itself.
+        for d in extra_dirs:
+            vapi = os.path.join(d, libname + '.vapi')
+            if os.path.isfile(vapi):
+                return [vapi]
+        mlog.debug(f'Searched {extra_dirs!r} and {libname!r} wasn\'t found')
+        return None
+
+    def thread_flags(self, env: 'Environment') -> T.List[str]:
+        return []
+
+    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
+        return []
diff --git a/devtools/meson/mesonbuild/coredata.py b/devtools/meson/mesonbuild/coredata.py
new file mode 100644
index 0000000..17ad701
--- /dev/null
+++ b/devtools/meson/mesonbuild/coredata.py
@@ -0,0 +1,1343 @@
+# Copyright 2013-2023 The Meson development team
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import copy
+
+from . import mlog, mparser
+import pickle, os, uuid
+import sys
+from itertools import chain
+from pathlib import PurePath
+from collections import OrderedDict
+from .mesonlib import (
+    HoldableObject,
+    MesonException, EnvironmentException, MachineChoice, PerMachine,
+    PerMachineDefaultable, default_libdir, default_libexecdir,
+    default_prefix, default_datadir, default_includedir, default_infodir,
+    default_localedir, default_mandir, default_sbindir, default_sysconfdir,
+    split_args, OptionKey, OptionType, stringlistify,
+    pickle_load
+)
+from .wrap import WrapMode
+import ast
+import argparse
+import configparser
+import enum
+import shlex
+import typing as T
+
+if T.TYPE_CHECKING:
+    from . import dependencies
+    from .compilers.compilers import Compiler, CompileResult, RunResult
+    from .dependencies.detect import TV_DepID
+    from .environment import Environment
+    from .mesonlib import OptionOverrideProxy, FileOrString
+    from .cmake.traceparser import CMakeCacheEntry
+
+    OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], OptionOverrideProxy]
+    MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]']
+    KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, OptionOverrideProxy]
+    CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], str]
+    # code, args
+    RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]]
+
+    # typeshed
+    StrOrBytesPath = T.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]
+
+# Check major_versions_differ() if changing versioning scheme.
+#
+# Pip requires that RCs are named like this: '0.1.0.rc1'
+# But the corresponding Git tag needs to be '0.1.0rc1'
+version = '1.2.2'
+
+# The next stable version when we are in dev. This is used to allow projects to
+# require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when
+# using a feature introduced in 1.2.0 when using Meson 1.1.99.
+stable_version = version
+if stable_version.endswith('.99'):
+    stable_version_array = stable_version.split('.')
+    stable_version_array[-1] = '0'
+    stable_version_array[-2] = str(int(stable_version_array[-2]) + 1)
+    stable_version = '.'.join(stable_version_array)
+
+backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode', 'none']
+genvslitelist = ['vs2022']
+buildtypelist = ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom']
+
+DEFAULT_YIELDING = False
+
+# Can't bind this near the class method it seems, sadly.
+_T = T.TypeVar('_T')
+
+
+def get_genvs_default_buildtype_list() -> list:
+    # just debug, debugoptimized, and release for now
+    # but this should probably be configurable through some extra option, alongside --genvslite.
+    return buildtypelist[1:-2]
+
+
+class MesonVersionMismatchException(MesonException):
+    '''Build directory generated with Meson version is incompatible with current version'''
+    def __init__(self, old_version: str, current_version: str, extra_msg: str = '') -> None:
+        super().__init__(f'Build directory has been generated with Meson version {old_version}, '
+                         f'which is incompatible with the current version {current_version}.'
+                         + extra_msg)
+        self.old_version = old_version
+        self.current_version = current_version
+
+
+class UserOption(T.Generic[_T], HoldableObject):
+    def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]],
+                 yielding: bool,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__()
+        self.choices = choices
+        self.description = description
+        if not isinstance(yielding, bool):
+            raise MesonException('Value of "yielding" must be a boolean.')
+        self.yielding = yielding
+        self.deprecated = deprecated
+        self.readonly = False
+
+    def listify(self, value: T.Any) -> T.List[T.Any]:
+        return [value]
+
+    def printable_value(self) -> T.Union[str, int, bool, T.List[T.Union[str, int, bool]]]:
+        assert isinstance(self.value, (str, int, bool, list))
+        return self.value
+
+    # Check that the input is a valid value and return the
+    # "cleaned" or "native" version. For example the Boolean
+    # option could take the string "true" and return True.
+    def validate_value(self, value: T.Any) -> _T:
+        raise RuntimeError('Derived option class did not override validate_value.')
+
+    def set_value(self, newvalue: T.Any) -> bool:
+        oldvalue = getattr(self, 'value', None)
+        self.value = self.validate_value(newvalue)
+        return self.value != oldvalue
+
+class UserStringOption(UserOption[str]):
+    def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__(description, None, yielding, deprecated)
+        self.set_value(value)
+
+    def validate_value(self, value: T.Any) -> str:
+        if not isinstance(value, str):
+            raise MesonException('Value "%s" for string option is not a string.' % str(value))
+        return value
+
+class UserBooleanOption(UserOption[bool]):
+    def __init__(self, description: str, value, yielding: bool = DEFAULT_YIELDING,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__(description, [True, False], yielding, deprecated)
+        self.set_value(value)
+
+    def __bool__(self) -> bool:
+        return self.value
+
+    def validate_value(self, value: T.Any) -> bool:
+        if isinstance(value, bool):
+            return value
+        if not isinstance(value, str):
+            raise MesonException(f'Value {value} cannot be converted to a boolean')
+        if value.lower() == 'true':
+            return True
+        if value.lower() == 'false':
+            return False
+        raise MesonException('Value %s is not boolean (true or false).' % value)
+
+class UserIntegerOption(UserOption[int]):
+    def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        min_value, max_value, default_value = value
+        self.min_value = min_value
+        self.max_value = max_value
+        c = []
+        if min_value is not None:
+            c.append('>=' + str(min_value))
+        if max_value is not None:
+            c.append('<=' + str(max_value))
+        choices = ', '.join(c)
+        super().__init__(description, choices, yielding, deprecated)
+        self.set_value(default_value)
+
+    def validate_value(self, value: T.Any) -> int:
+        if isinstance(value, str):
+            value = self.toint(value)
+        if not isinstance(value, int):
+            raise MesonException('New value for integer option is not an integer.')
+        if self.min_value is not None and value < self.min_value:
+            raise MesonException('New value %d is less than minimum value %d.' % (value, self.min_value))
+        if self.max_value is not None and value > self.max_value:
+            raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value))
+        return value
+
+    def toint(self, valuestring: str) -> int:
+        try:
+            return int(valuestring)
+        except ValueError:
+            raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring)
+
+class OctalInt(int):
+    # NinjaBackend.get_user_option_args uses str() to converts it to a command line option
+    # UserUmaskOption.toint() uses int(str, 8) to convert it to an integer
+    # So we need to use oct instead of dec here if we do not want values to be misinterpreted.
+    def __str__(self):
+        return oct(int(self))
+
+class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]):
+    def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__(description, (0, 0o777, value), yielding, deprecated)
+        self.choices = ['preserve', '0000-0777']
+
+    def printable_value(self) -> str:
+        if self.value == 'preserve':
+            return self.value
+        return format(self.value, '04o')
+
+    def validate_value(self, value: T.Any) -> T.Union[str, OctalInt]:
+        if value == 'preserve':
+            return 'preserve'
+        return OctalInt(super().validate_value(value))
+
+    def toint(self, valuestring: T.Union[str, OctalInt]) -> int:
+        try:
+            return int(valuestring, 8)
+        except ValueError as e:
+            raise MesonException(f'Invalid mode: {e}')
+
+class UserComboOption(UserOption[str]):
+    def __init__(self, description: str, choices: T.List[str], value: T.Any,
+                 yielding: bool = DEFAULT_YIELDING,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__(description, choices, yielding, deprecated)
+        if not isinstance(self.choices, list):
+            raise MesonException('Combo choices must be an array.')
+        for i in self.choices:
+            if not isinstance(i, str):
+                raise MesonException('Combo choice elements must be strings.')
+        self.set_value(value)
+
+    def validate_value(self, value: T.Any) -> str:
+        if value not in self.choices:
+            if isinstance(value, bool):
+                _type = 'boolean'
+            elif isinstance(value, (int, float)):
+                _type = 'number'
+            else:
+                _type = 'string'
+            optionsstring = ', '.join([f'"{item}"' for item in self.choices])
+            raise MesonException('Value "{}" (of type "{}") for combo option "{}" is not one of the choices.'
+                                 ' Possible choices are (as string): {}.'.format(
+                                     value, _type, self.description, optionsstring))
+        return value
+
+class UserArrayOption(UserOption[T.List[str]]):
+    def __init__(self, description: str, value: T.Union[str, T.List[str]],
+                 split_args: bool = False, user_input: bool = False,
+                 allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING,
+                 choices: T.Optional[T.List[str]] = None,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__(description, choices if choices is not None else [], yielding, deprecated)
+        self.split_args = split_args
+        self.allow_dups = allow_dups
+        self.value = self.validate_value(value, user_input=user_input)
+
+    def listify(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]:
+        # User input is for options defined on the command line (via -D
+        # options). Users can put their input in as a comma separated
+        # string, but for defining options in meson_options.txt the format
+        # should match that of a combo
+        if not user_input and isinstance(value, str) and not value.startswith('['):
+            raise MesonException('Value does not define an array: ' + value)
+
+        if isinstance(value, str):
+            if value.startswith('['):
+                try:
+                    newvalue = ast.literal_eval(value)
+                except ValueError:
+                    raise MesonException(f'malformed option {value}')
+            elif value == '':
+                newvalue = []
+            else:
+                if self.split_args:
+                    newvalue = split_args(value)
+                else:
+                    newvalue = [v.strip() for v in value.split(',')]
+        elif isinstance(value, list):
+            newvalue = value
+        else:
+            raise MesonException(f'"{value}" should be a string array, but it is not')
+        return newvalue
+
+    def validate_value(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]:
+        newvalue = self.listify(value, user_input)
+
+        if not self.allow_dups and len(set(newvalue)) != len(newvalue):
+            msg = 'Duplicated values in array option is deprecated. ' \
+                  'This will become a hard error in the future.'
+            mlog.deprecation(msg)
+        for i in newvalue:
+            if not isinstance(i, str):
+                raise MesonException(f'String array element "{newvalue!s}" is not a string.')
+        if self.choices:
+            bad = [x for x in newvalue if x not in self.choices]
+            if bad:
+                raise MesonException('Options "{}" are not in allowed choices: "{}"'.format(
+                    ', '.join(bad), ', '.join(self.choices)))
+        return newvalue
+
+    def extend_value(self, value: T.Union[str, T.List[str]]) -> None:
+        """Extend the value with an additional value."""
+        new = self.validate_value(value)
+        self.set_value(self.value + new)
+
+
+class UserFeatureOption(UserComboOption):
+    static_choices = ['enabled', 'disabled', 'auto']
+
+    def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+                 deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
+        super().__init__(description, self.static_choices, value, yielding, deprecated)
+        self.name: T.Optional[str] = None  # TODO: Refactor options to all store their name
+
+    def is_enabled(self) -> bool:
+        return self.value == 'enabled'
+
+    def is_disabled(self) -> bool:
+        return self.value == 'disabled'
+
+    def is_auto(self) -> bool:
+        return self.value == 'auto'
+
+
+class DependencyCacheType(enum.Enum):
+
+    OTHER = 0
+    PKG_CONFIG = 1
+    CMAKE = 2
+
+    @classmethod
+    def from_type(cls, dep: 'dependencies.Dependency') -> 'DependencyCacheType':
+        # As more types gain search overrides they'll need to be added here
+        if dep.type_name == 'pkgconfig':
+            return cls.PKG_CONFIG
+        if dep.type_name == 'cmake':
+            return cls.CMAKE
+        return cls.OTHER
+
+
+class DependencySubCache:
+
+    def __init__(self, type_: DependencyCacheType):
+        self.types = [type_]
+        self.__cache: T.Dict[T.Tuple[str, ...], 'dependencies.Dependency'] = {}
+
+    def __getitem__(self, key: T.Tuple[str, ...]) -> 'dependencies.Dependency':
+        return self.__cache[key]
+
+    def __setitem__(self, key: T.Tuple[str, ...], value: 'dependencies.Dependency') -> None:
+        self.__cache[key] = value
+
+    def __contains__(self, key: T.Tuple[str, ...]) -> bool:
+        return key in self.__cache
+
+    def values(self) -> T.Iterable['dependencies.Dependency']:
+        return self.__cache.values()
+
+
+class DependencyCache:
+
+    """Class that stores a cache of dependencies.
+
+    This class is meant to encapsulate the fact that we need multiple keys to
+    successfully lookup by providing a simple get/put interface.
+    """
+
+    def __init__(self, builtins: 'KeyedOptionDictType', for_machine: MachineChoice):
+        self.__cache = OrderedDict()  # type: T.MutableMapping[TV_DepID, DependencySubCache]
+        self.__builtins = builtins
+        self.__pkg_conf_key = OptionKey('pkg_config_path', machine=for_machine)
+        self.__cmake_key = OptionKey('cmake_prefix_path', machine=for_machine)
+
+    def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]:
+        data: T.Dict[str, T.List[str]] = {
+            DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins[self.__pkg_conf_key].value),
+            DependencyCacheType.CMAKE: stringlistify(self.__builtins[self.__cmake_key].value),
+            DependencyCacheType.OTHER: [],
+        }
+        assert type_ in data, 'Someone forgot to update subkey calculations for a new type'
+        return tuple(data[type_])
+
+    def __iter__(self) -> T.Iterator['TV_DepID']:
+        return self.keys()
+
+    def put(self, key: 'TV_DepID', dep: 'dependencies.Dependency') -> None:
+        t = DependencyCacheType.from_type(dep)
+        if key not in self.__cache:
+            self.__cache[key] = DependencySubCache(t)
+        subkey = self.__calculate_subkey(t)
+        self.__cache[key][subkey] = dep
+
+    def get(self, key: 'TV_DepID') -> T.Optional['dependencies.Dependency']:
+        """Get a value from the cache.
+
+        If there is no cache entry then None will be returned.
+        """
+        try:
+            val = self.__cache[key]
+        except KeyError:
+            return None
+
+        for t in val.types:
+            subkey = self.__calculate_subkey(t)
+            try:
+                return val[subkey]
+            except KeyError:
+                pass
+        return None
+
+    def values(self) -> T.Iterator['dependencies.Dependency']:
+        for c in self.__cache.values():
+            yield from c.values()
+
+    def keys(self) -> T.Iterator['TV_DepID']:
+        return iter(self.__cache.keys())
+
+    def items(self) -> T.Iterator[T.Tuple['TV_DepID', T.List['dependencies.Dependency']]]:
+        for k, v in self.__cache.items():
+            vs = []
+            for t in v.types:
+                subkey = self.__calculate_subkey(t)
+                if subkey in v:
+                    vs.append(v[subkey])
+            yield k, vs
+
+    def clear(self) -> None:
+        self.__cache.clear()
+
+
+class CMakeStateCache:
+    """Class that stores internal CMake compiler states.
+
+    This cache is used to reduce the startup overhead of CMake by caching
+    all internal CMake compiler variables.
+    """
+
+    def __init__(self) -> None:
+        self.__cache: T.Dict[str, T.Dict[str, T.List[str]]] = {}
+        self.cmake_cache: T.Dict[str, 'CMakeCacheEntry'] = {}
+
+    def __iter__(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
+        return iter(self.__cache.items())
+
+    def items(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
+        return iter(self.__cache.items())
+
+    def update(self, language: str, variables: T.Dict[str, T.List[str]]):
+        if language not in self.__cache:
+            self.__cache[language] = {}
+        self.__cache[language].update(variables)
+
+    @property
+    def languages(self) -> T.Set[str]:
+        return set(self.__cache.keys())
+
+
+# Can't bind this near the class method it seems, sadly.
+_V = T.TypeVar('_V')
+
+# This class contains all data that must persist over multiple
+# invocations of Meson. It is roughly the same thing as
+# cmakecache.
+
+class CoreData:
+
+    def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command: T.List[str]):
+        self.lang_guids = {
+            'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
+            'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
+            'cpp': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
+            'test': '3AC096D0-A1C2-E12C-1390-A8335801FDAB',
+            'directory': '2150E333-8FDC-42A3-9474-1A3956D46DE8',
+        }
+        self.test_guid = str(uuid.uuid4()).upper()
+        self.regen_guid = str(uuid.uuid4()).upper()
+        self.install_guid = str(uuid.uuid4()).upper()
+        self.meson_command = meson_command
+        self.target_guids = {}
+        self.version = version
+        self.options: 'MutableKeyedOptionDictType' = {}
+        self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
+        self.compilers = PerMachine(OrderedDict(), OrderedDict())  # type: PerMachine[T.Dict[str, Compiler]]
+
+        # Set of subprojects that have already been initialized once, this is
+        # required to be stored and reloaded with the coredata, as we don't
+        # want to overwrite options for such subprojects.
+        self.initialized_subprojects: T.Set[str] = set()
+
+        # For host == build configurations these caches should be the same.
+        self.deps: PerMachine[DependencyCache] = PerMachineDefaultable.default(
+            self.is_cross_build(),
+            DependencyCache(self.options, MachineChoice.BUILD),
+            DependencyCache(self.options, MachineChoice.HOST))
+
+        self.compiler_check_cache: T.Dict['CompilerCheckCacheKey', 'CompileResult'] = OrderedDict()
+        self.run_check_cache: T.Dict['RunCheckCacheKey', 'RunResult'] = OrderedDict()
+
+        # CMake cache
+        self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache())
+
+        # Only to print a warning if it changes between Meson invocations.
+        self.config_files = self.__load_config_files(options, scratch_dir, 'native')
+        self.builtin_options_libdir_cross_fixup()
+        self.init_builtins('')
+
+    @staticmethod
+    def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> T.List[str]:
+        # Need to try and make the passed filenames absolute because when the
+        # files are parsed later we'll have chdir()d.
+        if ftype == 'cross':
+            filenames = options.cross_file
+        else:
+            filenames = options.native_file
+
+        if not filenames:
+            return []
+
+        found_invalid = []  # type: T.List[str]
+        missing = []        # type: T.List[str]
+        real = []           # type: T.List[str]
+        for i, f in enumerate(filenames):
+            f = os.path.expanduser(os.path.expandvars(f))
+            if os.path.exists(f):
+                if os.path.isfile(f):
+                    real.append(os.path.abspath(f))
+                    continue
+                elif os.path.isdir(f):
+                    found_invalid.append(os.path.abspath(f))
+                else:
+                    # in this case we've been passed some kind of pipe, copy
+                    # the contents of that file into the meson private (scratch)
+                    # directory so that it can be re-read when wiping/reconfiguring
+                    copy = os.path.join(scratch_dir, f'{uuid.uuid4()}.{ftype}.ini')
+                    with open(f, encoding='utf-8') as rf:
+                        with open(copy, 'w', encoding='utf-8') as wf:
+                            wf.write(rf.read())
+                    real.append(copy)
+
+                    # Also replace the command line argument, as the pipe
+                    # probably won't exist on reconfigure
+                    filenames[i] = copy
+                    continue
+            if sys.platform != 'win32':
+                paths = [
+                    os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')),
+                ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')
+                for path in paths:
+                    path_to_try = os.path.join(path, 'meson', ftype, f)
+                    if os.path.isfile(path_to_try):
+                        real.append(path_to_try)
+                        break
+                else:
+                    missing.append(f)
+            else:
+                missing.append(f)
+
+        if missing:
+            if found_invalid:
+                mlog.log('Found invalid candidates for', ftype, 'file:', *found_invalid)
+            mlog.log('Could not find any valid candidate for', ftype, 'files:', *missing)
+            raise MesonException(f'Cannot find specified {ftype} file: {f}')
+        return real
+
+    def builtin_options_libdir_cross_fixup(self):
+        # By default set libdir to "lib" when cross compiling since
+        # getting the "system default" is always wrong on multiarch
+        # platforms as it gets a value like lib/x86_64-linux-gnu.
+        if self.cross_files:
+            BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib'
+
+    def sanitize_prefix(self, prefix):
+        prefix = os.path.expanduser(prefix)
+        if not os.path.isabs(prefix):
+            raise MesonException(f'prefix value {prefix!r} must be an absolute path')
+        if prefix.endswith('/') or prefix.endswith('\\'):
+            # On Windows we need to preserve the trailing slash if the
+            # string is of type 'C:\' because 'C:' is not an absolute path.
+            if len(prefix) == 3 and prefix[1] == ':':
+                pass
+            # If prefix is a single character, preserve it since it is
+            # the root directory.
+            elif len(prefix) == 1:
+                pass
+            else:
+                prefix = prefix[:-1]
+        return prefix
+
+    def sanitize_dir_option_value(self, prefix: str, option: OptionKey, value: T.Any) -> T.Any:
+        '''
+        If the option is an installation directory option, the value is an
+        absolute path and resides within prefix, return the value
+        as a path relative to the prefix. Otherwise, return it as is.
+
+        This way everyone can do f.ex, get_option('libdir') and usually get
+        the library directory relative to prefix, even though it really
+        should not be relied upon.
+        '''
+        try:
+            value = PurePath(value)
+        except TypeError:
+            return value
+        if option.name.endswith('dir') and value.is_absolute() and \
+           option not in BUILTIN_DIR_NOPREFIX_OPTIONS:
+            try:
+                # Try to relativize the path.
+                value = value.relative_to(prefix)
+            except ValueError:
+                # Path is not relative, let’s keep it as is.
+                pass
+            if '..' in value.parts:
+                raise MesonException(
+                    f'The value of the \'{option}\' option is \'{value}\' but '
+                    'directory options are not allowed to contain \'..\'.\n'
+                    f'If you need a path outside of the {prefix!r} prefix, '
+                    'please use an absolute path.'
+                )
+        # .as_posix() keeps the posix-like file separators Meson uses.
+        return value.as_posix()
+
+    def init_builtins(self, subproject: str) -> None:
+        # Create builtin options with default values
+        for key, opt in BUILTIN_OPTIONS.items():
+            self.add_builtin_option(self.options, key.evolve(subproject=subproject), opt)
+        for for_machine in iter(MachineChoice):
+            for key, opt in BUILTIN_OPTIONS_PER_MACHINE.items():
+                self.add_builtin_option(self.options, key.evolve(subproject=subproject, machine=for_machine), opt)
+
+    @staticmethod
+    def add_builtin_option(opts_map: 'MutableKeyedOptionDictType', key: OptionKey,
+                           opt: 'BuiltinOption') -> None:
+        if key.subproject:
+            if opt.yielding:
+                # This option is global and not per-subproject
+                return
+            value = opts_map[key.as_root()].value
+        else:
+            value = None
+        opts_map[key] = opt.init_option(key, value, default_prefix())
+
+    def init_backend_options(self, backend_name: str) -> None:
+        if backend_name == 'ninja':
+            self.options[OptionKey('backend_max_links')] = UserIntegerOption(
+                'Maximum number of linker processes to run or 0 for no '
+                'limit',
+                (0, None, 0))
+        elif backend_name.startswith('vs'):
+            self.options[OptionKey('backend_startup_project')] = UserStringOption(
+                'Default project to execute in Visual Studio',
+                '')
+
+    def get_option(self, key: OptionKey) -> T.Union[T.List[str], str, int, bool, WrapMode]:
+        try:
+            v = self.options[key].value
+            if key.name == 'wrap_mode':
+                return WrapMode[v]
+            return v
+        except KeyError:
+            pass
+
+        try:
+            v = self.options[key.as_root()]
+            if v.yielding:
+                if key.name == 'wrap_mode':
+                    return WrapMode[v.value]
+                return v.value
+        except KeyError:
+            pass
+
+        raise MesonException(f'Tried to get unknown builtin option {str(key)}')
+
+    def set_option(self, key: OptionKey, value, first_invocation: bool = False) -> bool:
+        dirty = False
+        if key.is_builtin():
+            if key.name == 'prefix':
+                value = self.sanitize_prefix(value)
+            else:
+                prefix = self.options[OptionKey('prefix')].value
+                value = self.sanitize_dir_option_value(prefix, key, value)
+
+        try:
+            opt = self.options[key]
+        except KeyError:
+            raise MesonException(f'Tried to set unknown builtin option {str(key)}')
+
+        if opt.deprecated is True:
+            mlog.deprecation(f'Option {key.name!r} is deprecated')
+        elif isinstance(opt.deprecated, list):
+            for v in opt.listify(value):
+                if v in opt.deprecated:
+                    mlog.deprecation(f'Option {key.name!r} value {v!r} is deprecated')
+        elif isinstance(opt.deprecated, dict):
+            def replace(v):
+                newvalue = opt.deprecated.get(v)
+                if newvalue is not None:
+                    mlog.deprecation(f'Option {key.name!r} value {v!r} is replaced by {newvalue!r}')
+                    return newvalue
+                return v
+            newvalue = [replace(v) for v in opt.listify(value)]
+            value = ','.join(newvalue)
+        elif isinstance(opt.deprecated, str):
+            # Option is deprecated and replaced by another. Note that a project
+            # option could be replaced by a built-in or module option, which is
+            # why we use OptionKey.from_string(newname) instead of
+            # key.evolve(newname). We set the value on both the old and new names,
+            # assuming they accept the same value. That could for example be
+            # achieved by adding the values from old option as deprecated on the
+            # new option, for example in the case of boolean option is replaced
+            # by a feature option with a different name.
+            newname = opt.deprecated
+            newkey = OptionKey.from_string(newname).evolve(subproject=key.subproject)
+            mlog.deprecation(f'Option {key.name!r} is replaced by {newname!r}')
+            dirty |= self.set_option(newkey, value, first_invocation)
+
+        changed = opt.set_value(value)
+        if changed and opt.readonly and not first_invocation:
+            raise MesonException(f'Tried modify read only option {str(key)!r}')
+        dirty |= changed
+
+        if key.name == 'buildtype':
+            dirty |= self._set_others_from_buildtype(value)
+
+        return dirty
+
+    def clear_cache(self) -> None:
+        self.deps.host.clear()
+        self.deps.build.clear()
+        self.compiler_check_cache.clear()
+        self.run_check_cache.clear()
+
+    def get_nondefault_buildtype_args(self) -> T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]]:
+        result = []
+        value = self.options[OptionKey('buildtype')].value
+        if value == 'plain':
+            opt = 'plain'
+            debug = False
+        elif value == 'debug':
+            opt = '0'
+            debug = True
+        elif value == 'debugoptimized':
+            opt = '2'
+            debug = True
+        elif value == 'release':
+            opt = '3'
+            debug = False
+        elif value == 'minsize':
+            opt = 's'
+            debug = True
+        else:
+            assert value == 'custom'
+            return []
+        actual_opt = self.options[OptionKey('optimization')].value
+        actual_debug = self.options[OptionKey('debug')].value
+        if actual_opt != opt:
+            result.append(('optimization', actual_opt, opt))
+        if actual_debug != debug:
+            result.append(('debug', actual_debug, debug))
+        return result
+
+    def _set_others_from_buildtype(self, value: str) -> bool:
+        dirty = False
+
+        if value == 'plain':
+            opt = 'plain'
+            debug = False
+        elif value == 'debug':
+            opt = '0'
+            debug = True
+        elif value == 'debugoptimized':
+            opt = '2'
+            debug = True
+        elif value == 'release':
+            opt = '3'
+            debug = False
+        elif value == 'minsize':
+            opt = 's'
+            debug = True
+        else:
+            assert value == 'custom'
+            return False
+
+        dirty |= self.options[OptionKey('optimization')].set_value(opt)
+        dirty |= self.options[OptionKey('debug')].set_value(debug)
+
+        return dirty
+
+    @staticmethod
+    def is_per_machine_option(optname: OptionKey) -> bool:
+        if optname.name in BUILTIN_OPTIONS_PER_MACHINE:
+            return True
+        return optname.lang is not None
+
+    def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
+        return self.options[OptionKey('args', machine=for_machine, lang=lang)].value
+
+    def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
+        return self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value
+
+    def update_project_options(self, options: 'MutableKeyedOptionDictType') -> None:
+        for key, value in options.items():
+            if not key.is_project():
+                continue
+            if key not in self.options:
+                self.options[key] = value
+                continue
+
+            oldval = self.options[key]
+            if type(oldval) is not type(value):
+                self.options[key] = value
+            elif oldval.choices != value.choices:
+                # If the choices have changed, use the new value, but attempt
+                # to keep the old options. If they are not valid keep the new
+                # defaults but warn.
+                self.options[key] = value
+                try:
+                    value.set_value(oldval.value)
+                except MesonException:
+                    mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).',
+                                 fatal=False)
+
+    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
+        if when_building_for == MachineChoice.BUILD:
+            return False
+        return len(self.cross_files) > 0
+
+    def copy_build_options_from_regular_ones(self) -> bool:
+        dirty = False
+        assert not self.is_cross_build()
+        for k in BUILTIN_OPTIONS_PER_MACHINE:
+            o = self.options[k]
+            dirty |= self.options[k.as_build()].set_value(o.value)
+        for bk, bv in self.options.items():
+            if bk.machine is MachineChoice.BUILD:
+                hk = bk.as_host()
+                try:
+                    hv = self.options[hk]
+                    dirty |= bv.set_value(hv.value)
+                except KeyError:
+                    continue
+
+        return dirty
+
+    def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', first_invocation: bool = False) -> bool:
+        dirty = False
+        if not self.is_cross_build():
+            options = {k: v for k, v in options.items() if k.machine is not MachineChoice.BUILD}
+        # Set prefix first because it's needed to sanitize other options
+        pfk = OptionKey('prefix')
+        if pfk in options:
+            prefix = self.sanitize_prefix(options[pfk])
+            dirty |= self.options[OptionKey('prefix')].set_value(prefix)
+            for key in BUILTIN_DIR_NOPREFIX_OPTIONS:
+                if key not in options:
+                    dirty |= self.options[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
+
+        unknown_options: T.List[OptionKey] = []
+        for k, v in options.items():
+            if k == pfk:
+                continue
+            elif k in self.options:
+                dirty |= self.set_option(k, v, first_invocation)
+            elif k.machine != MachineChoice.BUILD and k.type != OptionType.COMPILER:
+                unknown_options.append(k)
+        if unknown_options:
+            unknown_options_str = ', '.join(sorted(str(s) for s in unknown_options))
+            sub = f'In subproject {subproject}: ' if subproject else ''
+            raise MesonException(f'{sub}Unknown options: "{unknown_options_str}"')
+
+        if not self.is_cross_build():
+            dirty |= self.copy_build_options_from_regular_ones()
+
+        return dirty
+
+    def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None:
+        # Main project can set default options on subprojects, but subprojects
+        # can only set default options on themselves.
+        # Preserve order: if env.options has 'buildtype' it must come after
+        # 'optimization' if it is in default_options.
+        options: T.MutableMapping[OptionKey, T.Any] = OrderedDict()
+        for k, v in default_options.items():
+            if not subproject or k.subproject == subproject:
+                options[k] = v
+        options.update(env.options)
+        env.options = options
+
+        # Create a subset of options, keeping only project and builtin
+        # options for this subproject.
+        # Language and backend specific options will be set later when adding
+        # languages and setting the backend (builtin options must be set first
+        # to know which backend we'll use).
+        options = OrderedDict()
+
+        for k, v in env.options.items():
+            # If this is a subproject, don't use other subproject options
+            if k.subproject and k.subproject != subproject:
+                continue
+            # If the option is a builtin and is yielding then it's not allowed per subproject.
+            #
+            # Always test this using the HOST machine, as many builtin options
+            # are not valid for the BUILD machine, but the yielding value does
+            # not differ between them even when they are valid for both.
+            if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding:
+                continue
+            # Skip base, compiler, and backend options, they are handled when
+            # adding languages and setting backend.
+            if k.type in {OptionType.COMPILER, OptionType.BACKEND, OptionType.BASE}:
+                continue
+            options[k] = v
+
+        self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)
+
+    def add_compiler_options(self, options: 'MutableKeyedOptionDictType', lang: str, for_machine: MachineChoice,
+                             env: 'Environment') -> None:
+        for k, o in options.items():
+            value = env.options.get(k)
+            if value is not None:
+                o.set_value(value)
+            self.options.setdefault(k, o)
+
+    def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
+                      for_machine: MachineChoice, env: 'Environment') -> None:
+        """Add global language arguments that are needed before compiler/linker detection."""
+        from .compilers import compilers
+        # These options are all new at this point, because the compiler is
+        # responsible for adding its own options, thus calling
+        # `self.options.update()`` is perfectly safe.
+        self.options.update(compilers.get_global_options(lang, comp, for_machine, env))
+
+    def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None:
+        from . import compilers
+
+        self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env)
+
+        enabled_opts: T.List[OptionKey] = []
+        for key in comp.base_options:
+            if key in self.options:
+                continue
+            oobj = copy.deepcopy(compilers.base_options[key])
+            if key in env.options:
+                oobj.set_value(env.options[key])
+                enabled_opts.append(key)
+            self.options[key] = oobj
+        self.emit_base_options_warnings(enabled_opts)
+
+    def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
+        if OptionKey('b_bitcode') in enabled_opts:
+            mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as \'b_asneeded\' have been disabled.', fatal=False)
+            mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.', fatal=False)
+
+class CmdLineFileParser(configparser.ConfigParser):
+    def __init__(self) -> None:
+        # We don't want ':' as key delimiter, otherwise it would break when
+        # storing subproject options like "subproject:option=value"
+        super().__init__(delimiters=['='], interpolation=None)
+
+    def read(self, filenames: T.Union['StrOrBytesPath', T.Iterable['StrOrBytesPath']], encoding: str = 'utf-8') -> T.List[str]:
+        return super().read(filenames, encoding)
+
+    def optionxform(self, option: str) -> str:
+        # Don't call str.lower() on keys
+        return option
+
+class MachineFileParser():
+    def __init__(self, filenames: T.List[str]) -> None:
+        self.parser = CmdLineFileParser()
+        self.constants = {'True': True, 'False': False}
+        self.sections = {}
+
+        try:
+            self.parser.read(filenames)
+        except configparser.Error as e:
+            raise EnvironmentException(f'Malformed cross or native file: {e}')
+
+        # Parse [constants] first so they can be used in other sections
+        if self.parser.has_section('constants'):
+            self.constants.update(self._parse_section('constants'))
+
+        for s in self.parser.sections():
+            if s == 'constants':
+                continue
+            self.sections[s] = self._parse_section(s)
+
+    def _parse_section(self, s):
+        self.scope = self.constants.copy()
+        section = {}
+        for entry, value in self.parser.items(s):
+            if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
+                raise EnvironmentException(f'Malformed variable name {entry!r} in machine file.')
+            # Windows paths...
+            value = value.replace('\\', '\\\\')
+            try:
+                ast = mparser.Parser(value, 'machinefile').parse()
+                if not ast.lines:
+                    raise EnvironmentException('value cannot be empty')
+                res = self._evaluate_statement(ast.lines[0])
+            except MesonException as e:
+                raise EnvironmentException(f'Malformed value in machine file variable {entry!r}: {str(e)}.')
+            except KeyError as e:
+                raise EnvironmentException(f'Undefined constant {e.args[0]!r} in machine file variable {entry!r}.')
+            section[entry] = res
+            self.scope[entry] = res
+        return section
+
+    def _evaluate_statement(self, node):
+        if isinstance(node, (mparser.StringNode)):
+            return node.value
+        elif isinstance(node, mparser.BooleanNode):
+            return node.value
+        elif isinstance(node, mparser.NumberNode):
+            return node.value
+        elif isinstance(node, mparser.ArrayNode):
+            return [self._evaluate_statement(arg) for arg in node.args.arguments]
+        elif isinstance(node, mparser.IdNode):
+            return self.scope[node.value]
+        elif isinstance(node, mparser.ArithmeticNode):
+            l = self._evaluate_statement(node.left)
+            r = self._evaluate_statement(node.right)
+            if node.operation == 'add':
+                if (isinstance(l, str) and isinstance(r, str)) or \
+                   (isinstance(l, list) and isinstance(r, list)):
+                    return l + r
+            elif node.operation == 'div':
+                if isinstance(l, str) and isinstance(r, str):
+                    return os.path.join(l, r)
+        raise EnvironmentException('Unsupported node type')
+
+def parse_machine_files(filenames):
+    parser = MachineFileParser(filenames)
+    return parser.sections
+
+def get_cmd_line_file(build_dir: str) -> str:
+    return os.path.join(build_dir, 'meson-private', 'cmd_line.txt')
+
+def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
+    filename = get_cmd_line_file(build_dir)
+    if not os.path.isfile(filename):
+        return
+
+    config = CmdLineFileParser()
+    config.read(filename)
+
+    # Do a copy because config is not really a dict. options.cmd_line_options
+    # overrides values from the file.
+    d = {OptionKey.from_string(k): v for k, v in config['options'].items()}
+    d.update(options.cmd_line_options)
+    options.cmd_line_options = d
+
+    properties = config['properties']
+    if not options.cross_file:
+        options.cross_file = ast.literal_eval(properties.get('cross_file', '[]'))
+    if not options.native_file:
+        # This will be a string in the form: "['first', 'second', ...]", use
+        # literal_eval to get it into the list of strings.
+        options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
+
+def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
+    filename = get_cmd_line_file(build_dir)
+    config = CmdLineFileParser()
+
+    properties = OrderedDict()
+    if options.cross_file:
+        properties['cross_file'] = options.cross_file
+    if options.native_file:
+        properties['native_file'] = options.native_file
+
+    config['options'] = {str(k): str(v) for k, v in options.cmd_line_options.items()}
+    config['properties'] = properties
+    with open(filename, 'w', encoding='utf-8') as f:
+        config.write(f)
+
+def update_cmd_line_file(build_dir: str, options: argparse.Namespace):
+    filename = get_cmd_line_file(build_dir)
+    config = CmdLineFileParser()
+    config.read(filename)
+    config['options'].update({str(k): str(v) for k, v in options.cmd_line_options.items()})
+    with open(filename, 'w', encoding='utf-8') as f:
+        config.write(f)
+
+def format_cmd_line_options(options: argparse.Namespace) -> str:
+    cmdline = ['-D{}={}'.format(str(k), v) for k, v in options.cmd_line_options.items()]
+    if options.cross_file:
+        cmdline += [f'--cross-file={f}' for f in options.cross_file]
+    if options.native_file:
+        cmdline += [f'--native-file={f}' for f in options.native_file]
+    return ' '.join([shlex.quote(x) for x in cmdline])
+
+def major_versions_differ(v1: str, v2: str) -> bool:
+    v1_major, v1_minor = v1.rsplit('.', 1)
+    v2_major, v2_minor = v2.rsplit('.', 1)
+    # Major version differ, or one is development version but not the other.
+    return v1_major != v2_major or ('99' in {v1_minor, v2_minor} and v1_minor != v2_minor)
+
+def load(build_dir: str, suggest_reconfigure: bool = True) -> CoreData:
+    filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
+    return pickle_load(filename, 'Coredata', CoreData, suggest_reconfigure)
+
+
+def save(obj: CoreData, build_dir: str) -> str:
+    filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
+    prev_filename = filename + '.prev'
+    tempfilename = filename + '~'
+    if major_versions_differ(obj.version, version):
+        raise MesonException('Fatal version mismatch corruption.')
+    if os.path.exists(filename):
+        import shutil
+        shutil.copyfile(filename, prev_filename)
+    with open(tempfilename, 'wb') as f:
+        pickle.dump(obj, f)
+        f.flush()
+        os.fsync(f.fileno())
+    os.replace(tempfilename, filename)
+    return filename
+
+
+def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
+    for n, b in BUILTIN_OPTIONS.items():
+        b.add_to_argparse(str(n), parser, '')
+    for n, b in BUILTIN_OPTIONS_PER_MACHINE.items():
+        b.add_to_argparse(str(n), parser, ' (just for host machine)')
+        b.add_to_argparse(str(n.as_build()), parser, ' (just for build machine)')
+    parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
+                        help='Set the value of an option, can be used several times to set multiple options.')
+
+def create_options_dict(options: T.List[str], subproject: str = '') -> T.Dict[OptionKey, str]:
+    result: T.OrderedDict[OptionKey, str] = OrderedDict()
+    for o in options:
+        try:
+            (key, value) = o.split('=', 1)
+        except ValueError:
+            raise MesonException(f'Option {o!r} must have a value separated by equals sign.')
+        k = OptionKey.from_string(key)
+        if subproject:
+            k = k.evolve(subproject=subproject)
+        result[k] = value
+    return result
+
+def parse_cmd_line_options(args: argparse.Namespace) -> None:
+    args.cmd_line_options = create_options_dict(args.projectoptions)
+
+    # Merge builtin options set with --option into the dict.
+    for key in chain(
+            BUILTIN_OPTIONS.keys(),
+            (k.as_build() for k in BUILTIN_OPTIONS_PER_MACHINE.keys()),
+            BUILTIN_OPTIONS_PER_MACHINE.keys(),
+    ):
+        name = str(key)
+        value = getattr(args, name, None)
+        if value is not None:
+            if key in args.cmd_line_options:
+                cmdline_name = BuiltinOption.argparse_name_to_arg(name)
+                raise MesonException(
+                    f'Got argument {name} as both -D{name} and {cmdline_name}. Pick one.')
+            args.cmd_line_options[key] = value
+            delattr(args, name)
+
+
+_U = T.TypeVar('_U', bound=UserOption[_T])
+
+class BuiltinOption(T.Generic[_T, _U]):
+
+    """Class for a builtin option type.
+
+    There are some cases that are not fully supported yet.
+    """
+
+    def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: bool = True, *,
+                 choices: T.Any = None, readonly: bool = False):
+        self.opt_type = opt_type
+        self.description = description
+        self.default = default
+        self.choices = choices
+        self.yielding = yielding
+        self.readonly = readonly
+
+    def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) -> _U:
+        """Create an instance of opt_type and return it."""
+        if value is None:
+            value = self.prefixed_default(name, prefix)
+        keywords = {'yielding': self.yielding, 'value': value}
+        if self.choices:
+            keywords['choices'] = self.choices
+        o = self.opt_type(self.description, **keywords)
+        o.readonly = self.readonly
+        return o
+
+    def _argparse_action(self) -> T.Optional[str]:
+        # If the type is a boolean, the presence of the argument in --foo form
+        # is to enable it. Disabling happens by using -Dfoo=false, which is
+        # parsed under `args.projectoptions` and does not hit this codepath.
+        if isinstance(self.default, bool):
+            return 'store_true'
+        return None
+
+    def _argparse_choices(self) -> T.Any:
+        if self.opt_type is UserBooleanOption:
+            return [True, False]
+        elif self.opt_type is UserFeatureOption:
+            return UserFeatureOption.static_choices
+        return self.choices
+
+    @staticmethod
+    def argparse_name_to_arg(name: str) -> str:
+        if name == 'warning_level':
+            return '--warnlevel'
+        else:
+            return '--' + name.replace('_', '-')
+
+    def prefixed_default(self, name: 'OptionKey', prefix: str = '') -> T.Any:
+        if self.opt_type in [UserComboOption, UserIntegerOption]:
+            return self.default
+        try:
+            return BUILTIN_DIR_NOPREFIX_OPTIONS[name][prefix]
+        except KeyError:
+            pass
+        return self.default
+
+    def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffix: str) -> None:
+        kwargs = OrderedDict()
+
+        c = self._argparse_choices()
+        b = self._argparse_action()
+        h = self.description
+        if not b:
+            h = '{} (default: {}).'.format(h.rstrip('.'), self.prefixed_default(name))
+        else:
+            kwargs['action'] = b
+        if c and not b:
+            kwargs['choices'] = c
+        kwargs['default'] = argparse.SUPPRESS
+        kwargs['dest'] = name
+
+        cmdline_name = self.argparse_name_to_arg(name)
+        parser.add_argument(cmdline_name, help=h + help_suffix, **kwargs)
+
+
+# Update `docs/markdown/Builtin-options.md` after changing the options below
+# Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required.
+BUILTIN_DIR_OPTIONS: 'MutableKeyedOptionDictType' = OrderedDict([
+    (OptionKey('prefix'),          BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())),
+    (OptionKey('bindir'),          BuiltinOption(UserStringOption, 'Executable directory', 'bin')),
+    (OptionKey('datadir'),         BuiltinOption(UserStringOption, 'Data file directory', default_datadir())),
+    (OptionKey('includedir'),      BuiltinOption(UserStringOption, 'Header file directory', default_includedir())),
+    (OptionKey('infodir'),         BuiltinOption(UserStringOption, 'Info page directory', default_infodir())),
+    (OptionKey('libdir'),          BuiltinOption(UserStringOption, 'Library directory', default_libdir())),
+    (OptionKey('licensedir'),      BuiltinOption(UserStringOption, 'Licenses directory', '')),
+    (OptionKey('libexecdir'),      BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())),
+    (OptionKey('localedir'),       BuiltinOption(UserStringOption, 'Locale data directory', default_localedir())),
+    (OptionKey('localstatedir'),   BuiltinOption(UserStringOption, 'Localstate data directory', 'var')),
+    (OptionKey('mandir'),          BuiltinOption(UserStringOption, 'Manual page directory', default_mandir())),
+    (OptionKey('sbindir'),         BuiltinOption(UserStringOption, 'System executable directory', default_sbindir())),
+    (OptionKey('sharedstatedir'),  BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')),
+    (OptionKey('sysconfdir'),      BuiltinOption(UserStringOption, 'Sysconf data directory', default_sysconfdir())),
+])
+
+BUILTIN_CORE_OPTIONS: 'MutableKeyedOptionDictType' = OrderedDict([
+    (OptionKey('auto_features'),   BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')),
+    (OptionKey('backend'),         BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist,
+                                                 readonly=True)),
+    (OptionKey('genvslite'),
+     BuiltinOption(
+         UserComboOption,
+         'Setup multiple buildtype-suffixed ninja-backend build directories, '
+         'and a [builddir]_vs containing a Visual Studio meta-backend with multiple configurations that calls into them',
+         'vs2022',
+         choices=genvslitelist)
+     ),
+    (OptionKey('buildtype'),       BuiltinOption(UserComboOption, 'Build type to use', 'debug',
+                                                 choices=buildtypelist)),
+    (OptionKey('debug'),           BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)),
+    (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'],
+                                                 yielding=False)),
+    (OptionKey('errorlogs'),       BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)),
+    (OptionKey('install_umask'),   BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')),
+    (OptionKey('layout'),          BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])),
+    (OptionKey('optimization'),    BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['plain', '0', 'g', '1', '2', '3', 's'])),
+    (OptionKey('prefer_static'),   BuiltinOption(UserBooleanOption, 'Whether to try static linking before shared linking', False)),
+    (OptionKey('stdsplit'),        BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)),
+    (OptionKey('strip'),           BuiltinOption(UserBooleanOption, 'Strip targets on install', False)),
+    (OptionKey('unity'),           BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])),
+    (OptionKey('unity_size'),      BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))),
+    (OptionKey('warning_level'),   BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3', 'everything'], yielding=False)),
+    (OptionKey('werror'),          BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)),
+    (OptionKey('wrap_mode'),       BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])),
+    (OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])),
+    (OptionKey('vsenv'),           BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)),
+
+    # Pkgconfig module
+    (OptionKey('relocatable', module='pkgconfig'),
+     BuiltinOption(UserBooleanOption, 'Generate pkgconfig files as relocatable', False)),
+
+    # Python module
+    (OptionKey('bytecompile', module='python'),
+     BuiltinOption(UserIntegerOption, 'Whether to compile bytecode', (-1, 2, 0))),
+    (OptionKey('install_env', module='python'),
+     BuiltinOption(UserComboOption, 'Which python environment to install to', 'prefix', choices=['auto', 'prefix', 'system', 'venv'])),
+    (OptionKey('platlibdir', module='python'),
+     BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')),
+    (OptionKey('purelibdir', module='python'),
+     BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')),
+])
+
+BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items()))
+
+BUILTIN_OPTIONS_PER_MACHINE: 'MutableKeyedOptionDictType' = OrderedDict([
+    (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])),
+    (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])),
+])
+
+# Special prefix-dependent defaults for installation directories that reside in
+# a path outside of the prefix in FHS and common usage.
+BUILTIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = {
+    OptionKey('sysconfdir'):     {'/usr': '/etc'},
+    OptionKey('localstatedir'):  {'/usr': '/var',     '/usr/local': '/var/local'},
+    OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
+    OptionKey('platlibdir', module='python'): {},
+    OptionKey('purelibdir', module='python'): {},
+}
+
+FORBIDDEN_TARGET_NAMES = frozenset({
+    'clean',
+    'clean-ctlist',
+    'clean-gcno',
+    'clean-gcda',
+    'coverage',
+    'coverage-text',
+    'coverage-xml',
+    'coverage-html',
+    'phony',
+    'PHONY',
+    'all',
+    'test',
+    'benchmark',
+    'install',
+    'uninstall',
+    'build.ninja',
+    'scan-build',
+    'reconfigure',
+    'dist',
+    'distcheck',
+})
diff --git a/devtools/meson/mesonbuild/dependencies/__init__.py b/devtools/meson/mesonbuild/dependencies/__init__.py
new file mode 100644
index 0000000..c6dabc5
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/__init__.py
@@ -0,0 +1,261 @@
+# Copyright 2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .base import Dependency, InternalDependency, ExternalDependency, NotFoundDependency, MissingCompiler
+from .base import (
+        ExternalLibrary, DependencyException, DependencyMethods,
+        BuiltinDependency, SystemDependency, get_leaf_external_dependencies)
+from .detect import find_external_dependency, get_dep_identifier, packages, _packages_accept_language
+
+__all__ = [
+    'Dependency',
+    'InternalDependency',
+    'ExternalDependency',
+    'SystemDependency',
+    'BuiltinDependency',
+    'NotFoundDependency',
+    'ExternalLibrary',
+    'DependencyException',
+    'DependencyMethods',
+    'MissingCompiler',
+
+    'find_external_dependency',
+    'get_dep_identifier',
+    'get_leaf_external_dependencies',
+]
+
+"""Dependency representations and discovery logic.
+
+Meson attempts to largely abstract away dependency discovery information, and
+to encapsulate that logic itself so that the DSL doesn't have too much direct
+information. There are some cases where this is impossible/undesirable, such
+as the `get_variable()` method.
+
+Meson has four primary dependency types:
+  1. pkg-config
+  2. apple frameworks
+  3. CMake
+  4. system
+
+Plus a few more niche ones.
+
+When a user calls `dependency('foo')` Meson creates a list of candidates, and
+tries those candidates in order to find one that matches the criteria
+provided by the user (such as version requirements, or optional components
+that are required.)
+
+Except to work around bugs or handle odd corner cases, pkg-config and CMake
+generally just workâ„¢, though there are exceptions. Most of this package is
+concerned with dependencies that don't (always) provide CMake and/or
+pkg-config files.
+
+For these cases one needs to write a `system` dependency. These dependencies
+descend directly from `ExternalDependency`, in their constructor they
+manually set up the necessary link and compile args (and additional
+dependencies as necessary).
+
+For example, imagine a dependency called Foo, it uses an environment variable
+called `$FOO_ROOT` to point to its install root, which looks like this:
+```txt
+$FOOROOT
+→ include/
+→ lib/
+```
+To use Foo, you need its include directory, and you need to link to
+`lib/libfoo.ext`.
+
+You could write code that looks like:
+
+```python
+class FooSystemDependency(ExternalDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        root = os.environ.get('FOO_ROOT')
+        if root is None:
+            mlog.debug('$FOO_ROOT is unset.')
+            self.is_found = False
+            return
+
+        lib = self.clib_compiler.find_library('foo', environment, [os.path.join(root, 'lib')])
+        if lib is None:
+            mlog.debug('Could not find lib.')
+            self.is_found = False
+            return
+
+        self.compile_args.append(f'-I{os.path.join(root, "include")}')
+        self.link_args.append(lib)
+        self.is_found = True
+```
+
+This code will look for `FOO_ROOT` in the environment, handle `FOO_ROOT` being
+undefined gracefully, then set its `compile_args` and `link_args` gracefully.
+It will also gracefully handle not finding the required lib (hopefully that
+doesn't happen, but it could if, for example, the lib is only static and
+shared linking is requested).
+
+There are a couple of things about this that still aren't ideal. For one, we
+don't want to be reading random environment variables at this point. Those
+should actually be added to `envconfig.Properties` and read in
+`environment.Environment._set_default_properties_from_env` (see how
+`BOOST_ROOT` is handled). We can also handle the `static` keyword and the
+`prefer_static` built-in option. So now that becomes:
+
+```python
+class FooSystemDependency(ExternalDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        root = environment.properties[self.for_machine].foo_root
+        if root is None:
+            mlog.debug('foo_root is unset.')
+            self.is_found = False
+            return
+
+        get_option = environment.coredata.get_option
+        static_opt = kwargs.get('static', get_option(Mesonlib.OptionKey('prefer_static'))
+        static = Mesonlib.LibType.STATIC if static_opt else Mesonlib.LibType.SHARED
+        lib = self.clib_compiler.find_library(
+            'foo', environment, [os.path.join(root, 'lib')], libtype=static)
+        if lib is None:
+            mlog.debug('Could not find lib.')
+            self.is_found = False
+            return
+
+        self.compile_args.append(f'-I{os.path.join(root, "include")}')
+        self.link_args.append(lib)
+        self.is_found = True
+```
+
+This is nicer in a couple of ways. First we can properly cross compile as we
+are allowed to set `FOO_ROOT` for both the build and host machines, it also
+means that users can override this in their machine files, and if that
+environment variables changes during a Meson reconfigure Meson won't re-read
+it, this is important for reproducibility. Finally, Meson will figure out
+whether it should be finding `libfoo.so` or `libfoo.a` (or the platform
+specific names). Things are looking pretty good now, so it can be added to
+the `packages` dict below:
+
+```python
+packages.update({
+    'foo': FooSystemDependency,
+})
+```
+
+Now, what if foo also provides pkg-config, but it's only shipped on Unices,
+or only included in very recent versions of the dependency? We can use the
+`DependencyFactory` class:
+
+```python
+foo_factory = DependencyFactory(
+    'foo',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    system_class=FooSystemDependency,
+)
+```
+
+This is a helper function that will generate a default pkg-config based
+dependency, and use the `FooSystemDependency` as well. It can also handle
+custom finders for pkg-config and cmake based dependencies that need some
+extra help. You would then add the `foo_factory` to packages instead of
+`FooSystemDependency`:
+
+```python
+packages.update({
+    'foo': foo_factory,
+})
+```
+
+If you have a dependency that is very complicated, (such as having multiple
+implementations) you may need to write your own factory function. There are a
+number of examples in this package.
+
+_Note_ before we moved to factory functions it was common to use an
+`ExternalDependency` class that would instantiate different types of
+dependencies and hold the one it found. There are a number of drawbacks to
+this approach, and no new dependencies should do this.
+"""
+
+# This is a dict where the keys should be strings, and the values must be one
+# of:
+# - An ExternalDependency subclass
+# - A DependencyFactory object
+# - A callable with a signature of (Environment, MachineChoice, Dict[str, Any]) -> List[Callable[[], ExternalDependency]]
+#
+# The internal "defaults" attribute contains a separate dictionary mapping
+# for lazy imports. The values must be:
+# - a string naming the submodule that should be imported from `mesonbuild.dependencies` to populate the dependency
+packages.defaults.update({
+    # From dev:
+    'gtest': 'dev',
+    'gmock': 'dev',
+    'llvm': 'dev',
+    'valgrind': 'dev',
+    'zlib': 'dev',
+    'jni': 'dev',
+    'jdk': 'dev',
+
+    'boost': 'boost',
+    'cuda': 'cuda',
+
+    # per-file
+    'coarray': 'coarrays',
+    'hdf5': 'hdf5',
+    'mpi': 'mpi',
+    'scalapack': 'scalapack',
+
+    # From misc:
+    'blocks': 'misc',
+    'curses': 'misc',
+    'netcdf': 'misc',
+    'openmp': 'misc',
+    'threads': 'misc',
+    'pcap': 'misc',
+    'cups': 'misc',
+    'libwmf': 'misc',
+    'libgcrypt': 'misc',
+    'gpgme': 'misc',
+    'shaderc': 'misc',
+    'iconv': 'misc',
+    'intl': 'misc',
+    'dl': 'misc',
+    'openssl': 'misc',
+    'libcrypto': 'misc',
+    'libssl': 'misc',
+
+    # From platform:
+    'appleframeworks': 'platform',
+
+    # from python:
+    'python3': 'python',
+    'pybind11': 'python',
+
+    # From ui:
+    'gl': 'ui',
+    'gnustep': 'ui',
+    'sdl2': 'ui',
+    'wxwidgets': 'ui',
+    'vulkan': 'ui',
+
+    # from qt
+    'qt4': 'qt',
+    'qt5': 'qt',
+    'qt6': 'qt',
+})
+_packages_accept_language.update({
+    'hdf5',
+    'mpi',
+    'netcdf',
+    'openmp',
+})
diff --git a/devtools/meson/mesonbuild/dependencies/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/dependencies/__pycache__/__init__.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1176319cd2865be3d6ece7b60e2fa6c9b47ffbc5
GIT binary patch
literal 1401
zcmah|&5zqe6i;l&cCwpIvb!zY4@wd0AreAbpd1iFsI*8(Y%jfyB3To^u`|tlxHIGI
zh6DT~9N@_Rz>WW6u3X^8nGhLMC!brpPBSfD|&wVF)AGgMApo0Zd?8kI9TpULO8<1haq0AsoRm+=AQi
z7M%RA+=06&_uj~T2=ew1^Pl?t9-E@~;OPOpvq}O34`1}=@BY!pbms#?8OX*v1c*T3hFnvIR==Qd48-*7{@x)ngxH{ru3DRL~FxP9L`=MklDNw2?k-
zwpb-aqL!2Bm7CAWpmxkUT%->6LTn_-H&oOH^Y_WOf-gz@QgH-Wo5K*x5dz6B|7?x}
zbt}N_z^6-rjx0&b)>y1Zs+cRG@~Os2k&VyX$}kF+Buz;hf@w5pjDI8X!u^iiu8Cj-N8|HpFH>NSmF`-LC&Bj=!DmH5g(wQ21FL8&9G048a;g6t
D)-{Kn

literal 0
HcmV?d00001

diff --git a/devtools/meson/mesonbuild/dependencies/__pycache__/base.cpython-37.pyc b/devtools/meson/mesonbuild/dependencies/__pycache__/base.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9474b6efc47df02506c0140c05562fbe60bfe8bb
GIT binary patch
literal 26036
zcmdUYdvILWdEef<@5N%V1R=gfT~d@lPyi%LvK|yoi!V@+NKg?WOInH9Ecaf33+@9t
zcR>>Cg_K@
zn7hY}#q5}E)ME{!WEhN_b+cs3Z@d(j-$W@PzsXWkep971e&h8_BU{R%PQp&sbB&SG
zNF!g$OFC5_Z4^ociKpxN##m{rQ7jc3+e+IS~d
z^&O3!rJeFLSKrmxUD_@2k@}v--qK!)=j;0#_m}RM_-K89hf5C|v9mFI%r3qgvy0BQoAJ^l(%bBDq{nZXrNc;VwC3580tT6AH?Uu+opZUe(2pq=?VK``Apu9
z+lTEbDvi=#-2sq$HTlwk@uMWG2}gEKW;x^KWTp)HJ`GdM$XgrGg9tZ
z`>6fg?WBFo{seNL!3d7qpTr10DI<6m>F4beNS~1OQQN#2n>zVDLd=xmjZ~V=R=d)!
zwVLh%(up(8wZ``VJh3U$OEl`OWiQik+*Y$*yNt)VDt^oLN^{wrN_y#Ywabg^tByB%
zzEZtXYdWW{v}#qyE1YMIGdHTvDjW6+FSP1*<#OG*aCyb4w!Q2H$$!aNN0SrR9Oa@^
zx!P*1R+Lk2RGQ4cZ@$r3YqQq5n%jO^wc4#}tBwbmQz%%gI|}iUGtFx?)oM1JW*f=k
zoKtD9DU8FZUOicHovE~!KegtzTaCqvT6Wsr$b7R}U$dRlHRXESqL1dAwsXVF_)~Jd
z(TiM`D$=T=*1c^P+iI=K#_fx(HC1(7uXyH0TUDxU$JX<5F@pRYMs`7=aILvqrZb;nQe%e`eFotGzJzTlY6JgY~RHf!Rwsrjqda&AR9UWNh
zmbFxC0_1|aH3!?6@G|9cv(j+NWiMAQH(K^uo$-9R{PtRnfFR#_=HlFxHNB3`C#=6h0
zuB$z0bQ)im(3CMG-M1ofJW-o3Bvs2FTXOY1R}P9(VGi%(k)6KM&95M0FrF0Tz(c01twxfXV>Pwb)ki+
zl-kQyxM=Er2KyOIF?fVQ2(vn7G4B9^$MBWuWz2+GOiErAdEp;NE?{>Wk$$iPsKo(b
ziBif=f)=Jq89QCd+L=<$&Xz{(Tq$pllt%4*sbG(m#_U3=Xpdp$MQ>XVK+ZeuD=pjg
z5|y=ftCL&3x;#^DHJ573Ub5P#Ty?xO&rG}4^iuA+3!o_#9O98Bg#&xNrLLB;$k$am
zBl>rSV2gaa9_FvDx_-Nzk=1HtHAsvCL0@kyg?+xwK7nM`E-y@N8(2~=apKj*3#IJK
zFP%MgVPS6mtd~4>{=`dXy!6Re=g%$9FO*Uj-?+GV=6tDe=Jmx_PRzY>;{2J{F1+$m
zDT{o+%833gFJ8EC&dXjrea_F%oqF}Yz$*&
zYRW!>RMAg8VoxKr4V(m@&DxJ5HSRytoWyo;5)<|lm@T*oJe|PPr!Xqhej41yGxoE{
zyALVTK8iBW*~gIH0WK)`d;+{iA^d>XxSbLXBURdIpG5vC)H-dSK`n4nk&3|iP^MfCovjD
zMAgYPTg@4b2Rf(wT4+?(EwEkdtWRRrTC(1p40@cLwkCBg#(Hf`ULvKafi8ktG^>s*
zP(U8y)w-*Am?9_5Lekq+UR5n{G;TRMg7VetZ{n$2KoB!CIAsMRW90GeJlNZo*{$lT
z=h$?DgcxJWa>axv(IXIg!rkE?f5V+>BVilZpV&>~Yq9suZmbOIh!C<1La<8+6I}yg
za+x_P2_d;4o{@M~!dy3YXQXT1Wy!qcjJ6AR#@a>6*(N#TQfqraedD&XIyW`pnKj!>
zkWKQ^K6mP6$n>sNma*+Mw=6_ik$`x4@~vRW%7j2KTdy^*>gcGdTrc;MY1d~PM+DuM
zmr%!5C((o=aC#YJm(joL0qNK4;FHOddn2~9R9UOHZGgU)sDl;ua&~!1^SN$m)Q?rk
z@%EBsKtPp{CX|@t9J=wK$+c#!T`oH);gZ0{j3Rh~@DtauJaYK$M3_{t3A*ku?jVhp
zggdYh!MTgA#8$AI+`APMzj6G=@tb%*jgysJ_`o>!fnjybqt*w;aqzF%a=BWs03gen
zWSvDb>O}-wGZ$dsz}(zGnSi;g@k{4i@t*AoktgEUu|L+HOite
z1!mE$op!1%RcW_?#=^Ws?Ea;`afM4r=m03k?#A5lwsFTK`*;yKD{&w$<4(c`hy$S+
zcalNMjw6<0iMz(#I2Jeo#&Y3;7k}f-MfDn*gIJW*Ae=mF5^Bf{bMj>|F#;^cC)mEY4D__f7w`c6tu-U9HN)1(|7I36
zN;hZbJLaSFoy<&4qiB`DRHB&vdl_WlaB^qWOAH>?89c3}EOQA
zDF+zm^QhvV+#FDJ-k30UnFYjjD(9y}4VQDG`mq
z<5RX&OUPC)BN%>k)G{9Z8GK!WMhyGadEi63UzqEREzWAiNu@651`srl+Bm+I>zeh6
z5>!r0_K|XU*Hja7m||D6IwpsJyN3ld)p?Xr=MV%WgAJ<&gPxpaA?b~BsY9yvKC*mS
zvOxL}J@9=6!+oXn^@D)eTmWM1`~Nk3Z42NloH*9(3TC2e4EmQytsw8`@C_jA(IHzK
zHncTZsjFa%Y%xFG^3#Jq$N|4`k7+^Qc((QmLn0vW{k
zVx%{rE1fwXzXufX@MKgmMy55Ydt>_Ipnh#~>Qaw1aFjzw+F91>IOxH^PXW_Z+E&wn
zo(!rna^AMBLs#!%rs`IDMKntlZY(3C1jv~T={-toRW@pd9U?aso8px1M+hTz-?3XO{FNGcU
zvy;K|;XO^D7J*acHHcE3N4@X~9|tIgJRvMFR@witlykk8HkGRHu8j{#|=%uT!G
z7Ylc3a=xcEp4?)Wh{>1r;Sq$e#V~|`2V#~DE%diI7XKU#66t8U;p;MZXvtE1l%6S$
zefuNy%yOOFWS~i%1X0cSL|$zcx5E>C=
zbhPF|XFpZPu$ovE3)(%ck?V0WPzH;@t>iEy^t{*6oa!*3&@i|HJGcU2Q{g!OE{X{=L242iCm1pqql!AB-+5tjxJ+cIvxL~ktuz0QoV^y148B!J+u3&etLl$>7CsqYg
z8R~|XAknw3lbE!`^yOMrP#(~yTJwsdz&_eX!}6>n6Sih%EKnm!l*J4YvekWsgJlWI
zN3aG+Lrbj-X_%RRG!RJ8dA;uTwc(R4X`;Dq>EyI^#i`g1Fwoyw$ovE)nL(b;?XB7g+pbXqf|0Jv5)bUf^%_>@O63};I@Z@m*xUz@7;xj<
z7)lu7ApIRWTwB6wtWU|3u%>d}UITf@v_y(^SrG+#TM4NIHXw9%*$ErdTtx*B9B>O^
zc4y|*CO`)w0B{dvA)EUva8j$(soM$UAFjV+Q*z0_vesxZ!XTB!q6o8<|Qy?z1owPE&=xgbFNYc
z)sOm#Ir)_{HH*lN!(Gbh7Uk)iv5j~)4$4i11k@K@$m+1(gMPoAdJP&O3XqlkIG)&X
ztUQ?-M`7E0I{;>fLSzL80qRuj&uR;nKQ3{&q!b-{u(L>U6JP*44AB}}gke=!LRv!r
z7?x9UYk(3kiP%eieP9dsGTO8h1H#8q?RB{xjH8Hi0D=)!Yv@R0hp?@6>pFnO
zU8_>ry0k{n7EqeDmLOU7;7hu?4s&l0wif3gn!Sj%6*<65RaOa2Q$BrphYv&+Im6fh
zoNOv7?X#}iOqS{(r_cFHQ
ztTNWqPX~$tcIKslj0sDFfVL+f5@oIVioo0dKs}%3&OyiAc_;#DTi2pdd1~*V*>Xg5
z!}@^h5x$DnRf)ly45|#47%VerGN6nsf~#6(>}>{cpNc6O9Ml?vYYeDCR$T@g3_i!;
zT?T)g!Iv2H_Dy0I^Nt~S17G(U1Q~N8H@>|P$0uFbUPw+P3rWP2g#^MB^NaC`WHD}H
zXRTtfn82@TSV?JxgAe}-5`zlt14IIYr8Za6M}i&_G*i+@2@~3goxeT$9yN8NcH!MT
z%)T&C+S_1O)27J;41f3CHpJzLo)o(zwcFkUlN$}5d*R+>*!RN>NT((mHmUQoP+yxP
zGcZT?K8Ik?+ZFl5?1x~`d)S_YK`)EZuqW;0l!K#E@AC-i?F&EC=wSx+XsS%X82Xsh
z`@yFfNS(LZ9%)=Y8bT0~~b_i?W4~)~8|a6nz{Mc=ufDd~!fR(dX?mZAG;c
z{VDMix^$^?a&h(|c?Z~8KsL3WKdR&CuQhFL(r=)R-H|r>H377Cih{g1+e@59&jL!#
zIUA5t!2pmsO}d1(_xO({&kT4e!A3Z$wf$*uiWEV63k;)F7jC@86?o)QT)>v&R*tFXPcop&cwjBn&oJ+287v~0Dro8KBE1gvv>2M
z3+;ZL13owc-oPquE;)IrGchb1d}N~GG+O;kB!#mKzQRNjCu3`bYOM&}YJ-(*$6>7B
z*G|AtZ+49~0N|!^EOuiKB~y3OcVl2VpLxsNh;JmiaOt?3Qm?l&C>d{O?_|3$>fDUO
zZ17~5mjfUfcTJrOQ;w#D$4&Iz+peh*Swj!rawK|X^*kSc83DYoTo-zO2r1$zrskLl
zlPXQM@U~0RBMgx5YR4<}Cs^^P5J0vS=HNEV!(+^adDkv4<7j=>OL5KB+Sm@s$2cCdNvu}i(0o$=7l7}_2I8;8(TpH_)%gDigz5wZ;0)JXQ=
z5^}(5aFf(eFh11DO9=0S948ks7VlU?M%HHt+-#2x2XO=~5C+_FgocEs+Cjmg4WwYl
zdzL7%LM0X!!^yCBw)0VpN5U~+YFAKxOLhJu!JJ?ynjJEyz~nnzn=dCdJh)yQ^5wm>
z`D9@ZvqQ4DF=KqIgBWyrZ++Nivr$4TihAlO0R$pr{_&UVCxFnWAfa*->aVlf!_7K4
zTx)fB>Yx_7AWzpcV?A7|3s~ikq9PN9Y$n(Q0M^uyO&C6&E%jpeoa779N%lmXP@VOC
z&vI*(nedrUgmW`GN4A*TkYUW-OYcS6070ZjI|lS(LOVhvKwulgmxNh}^4~<{R!kK%
z9=;oEnlP59Z<)$Mj(NxMb27K$>T%@6!<;N~XsS
zGE@gS=`aVJ?0d$0=6mt?5=%*NiRQZ*JkQYfyisU_yszXy*wft%NPP~3J>TV6N0y<6
zUyj`**BD>uLkU^TXgm203laMNT-rs8@(QMT%e)o8W!%Djh%Y98+I%~K%0^TNIiOPn
z?0ybyMA1f2`m@LvQ>v~aXFn7ZKFA%T5`&tt<0peHhXLXfTWmRXjQz@;2!;t;n#$`<
z77BBY{fEdV!f1Sr4_;ZLgs@*PuSAEI?4oRr2PwnK>()$^6cbY7^=>t*;nWa&O#
zVt|u`*OD~mD-uiFbTVRYDiw5ApxX3uIt`iA6(V`B)wVc2ZqL(PVT$9i#5mAsh}Zt$YYdXmz+P5(+)VRo;R)QpS8S*mPJ;AKYToBa9@R`L)VrOC`dONRvX&
zi2{x^UMbi%z{tzft6qr&?=uTg)QB!+napKu!>y
zD}39BDqo;qATWAy)YdAL%tuh6cyUmf0j@~|_48b3PAZn5*CJTiVN4P!Mld=pdvkC3
zM{LNitj9Zu5dZKp)rQe9H_S$SBW}dni96syp;bxTc)puhNrC@-Y9raEXacuVb-bO?
zZl!NOEP3EWmrUe8+)due-i@h;@f^;^?-*}C4DK_L06uGv+{xQXwsqHh8f3Vf1DZ-u
zX`n@^2;Nx7J!{sLDfT%H~a
zt`X$(d`e!|+s1`)%l0}f)HQ17*F{$Ij74a~DsDT_%n!8pMb|FKU8S-);ppK
z`xIf5E=@5wYvsVmL+mnl82LmVaiFA+4aE!E`l4NLG(H6~^bHCS826&N$YlwUP=Ahj
zRR&}!2bEexM_Q@%R}k|?eV5BBOd1e#LLC>7nFx^(Gscm<#Sv(=k`t+7
zg1W2(v{{8Xe@(+mNojT;{*fma_j~g8QEe79MbKtJ;}gd@gH8(?Cup^h#>GKEehyd2
zD((XAV_kDzqO12XXK)Pk6KHn0?UQm7ohTvjQBR=n+Zb?t^7ax5K>dq*XL5(FOk)Fl
zpJ|TrMj{VD>_u#2C%xrS7L#1=D-qPbvwygu%&f?Qpdo2PSTAy+{NrzkfOjFGZwkT3
z(Nu8zT!CL0vW1+az*|ddL{c=#DPkYf^T2xq=tQ95^ZO5ehCx(Tihs#Q{T`%(%4r
zq&&~qL3W(?b$n$Ez*T>P`QKtb+*>f3O1t9acoMX|UQrNMzsi8{>ZL9&o>-he<&D1l
z%9*({uaqyoaN?CSr@b^N7(Hf0tD(I>cmn8w(uOHM;GUKG>&zXM%d|d6tpXB5=uqEe
zAV@-n{%cHz7`caXT0B~u4OK#c8jtjZaVm-Sfx^JBXXc^G+YH4aTA~eDYp@Sb4&2BS
zS3Up2Ej;poWDlXckH!oC21*X+g|*X9F!h@eZ1lj8VR9dWvU36FFLKU+L`$+FP;f7?
zI2=FE8qXN1lAN=nh~S)oP=KdPbq#j{+*hg$ZKJziVrDn#9+p_Vn{cO*ddg3wfGI#u
z5}L*6iQE+b0%Kq=w}04P9GbG)etuH+joE=SCV(Z4K2rcc>!8(Vsz-PAr+ve&TYq6
z(p}?A5JHicQEi(zn~rMf_v0HTG$Z1!*8F7{L(mJK-8A2#=>)DA(2Zj(UpCz7!T$Ps
z%b;JHN^r%(&T?FK4w4BeFK|0GFrW*@a#F^aP=A2Yk4lMxl#u%Ycn%q612c$@7IQyr
zkLgj~fmvonj5_Eiw9yNFD1ts5!wPm%;!k{3y~V^H-_tYj_nEeEPg~r5k9PLFs=Yur
zKeIezRxH1rY_GTpJ3c{!f8@QmWf!R%BJYJm9lKQA;Jq{6T8h0N4|GBw7?T=QwZhml
zoCpM2sH(n!;F|&1q+*?q4*{F9T-Pf56lj=Ar;~fmYE;@NXCM7R#;N`>$3l<}bX5N&
z$j}3}nB-W0H8R#m=9^k;>yK<&yHbDpfZDJmkj;?jEM$%s*~YIiASoB)056Q!ZB2U1
z$n@ekOPab;5u-+#H_~jW29-&;TjV8HTD%JlMjP`5azBg`rL1&RZn(>y(eSeHz45Qy
z{Wu%xr-WXie>uO-2|bB&bnZ=<8I!~?VeG&shj_urC3Zk1Fb*{(PLmdDbM?G8+nl!ftJKDUuW(p3KOmxwpcQF3dCn0d*G
z#)X%~T{gtw!y{r&hxMY_PZ%b3FvV9;_>%HbqT<5!??~Vdy?*qk2;(6YOWqP%YLMK446#W?kEcZTrlApjb`LZ3}Sa7I)joF-rMOoSLpNT7BF{FzmU{FR7
zKtbAuyNBc#Djxp{u1@nd2j9{H778K&_Kpq$@rsQBhi;<5;C$UBorSfm2cJTH
zd#Dmzid0%+4es=>$;*83HkYt1ia5~g1ir(w)|}k&0Re%J(X{ocN}VpSzG=leJbSIO
zTGQ8_rsz%%WEu5Q4%@d*i7WE7uYQMa9?s0K@XZ81WLOkgLyvT-EHQZcn};JiHB+y_
zZ&u(WcHIO^KA)g!NhMy8(8J5Z#l_4A4DfO*51=eM!>Pk|Yn@hslrX@1sx;IcxR6=aBbb
z!g(jP{MdPTVDMW}0%J}*FVjN_0+&>?IrpFnzl}owoc)uoWz7ABU1LHQm_N+9jZQ&g
z-IH^Rit1jgz?a4))dwjO}4?6M>gvBTZYofh5$w;e($?P|D(FvVIT5
zFlQ8+7I6L6sVwmhpMYV{uz*qgAy=HB6(i>hNGBRC0_J%ozlc!%4xaV-M#7ww0U`kA
zxq>S;(6~uVlQv-?P=Qd(Z4lB%*18Ro`As5D+$(NFhNTCN&vlwTt`kxoHUy|MEvPfo
z`PM}^1X?hG>+X(Ql`6Dtw!9goWgQDTKdxQ*=i7tc`#>&&)?mqU+0x88YpGsY#=FtP
z>mF$9@;dKi`L5a;m%JRN{bIP3E|qXMLjn8XY5~RoRHPlgLrjX&b*KRF@)g~VB2a3^
zVcX*D;u`LZzFDK|8v?l-;ZLhyLB>O$#aH|eZXhCW9C+atozT%4}v)KLQ>KJQ9w#NUAX#p|>QB;fW2QCT21_gbtCH5J?;;K&A;hME9s
z-{dX0!SBYFbQ8N`KrP8`YKfE!UR>Wn|5F*yY~l4(+-7?3HyW*`j)TCg>5C{DM&r=N
zdhtf(23*T@p>`Gaga29N%LP7uk4uk}%mMTCbGb*dA2^}8rE$T)Jd
zp$8OBk!oJ;3vvjtDvuHW`i|4X$N)2I(wz;eN9-)sD_@AoF#>B0rx%ks*uiAy_g{hE
zB~XuOeFf(zc;AA569pLJnw+XDcp)AD)W5-m%Sl(EGQlhRaCHf{Ssbgv
z1Ep}03Rj^6&52xr3YY`o0nh;NN=3TV+yuU1L|sG9@e0*7csYbt*Sv3j#dqN8m^0_}rUu%Y
z!5a&B7X;ih$#@-qgu9C``1sBw{HSZI!6gPj7k!v}z!lcnG$c9Y#J_|Bh$WK#xwX%%d~StUQ5|K0-~Flj*RK>hm5J`4P+qhd3Cndn`R+sQ-rFD46%&jYSSh#t-n{_c=YK@-F3>LU2WCTC&q>X2=<9l0#wvo_Y2%&=}17{<{QlYH+`7NguCj1+52%MBkj$_YVQ;nmLcY
zaB>sud=zk=kAk!MJ#LstQ$3ODKO^s{2-rN*x0SwY(H|W+D~E7lD1oKksJ?;Rrz4}9
z{s^Or0yJ))_DnzlKu7(g`hfbs2kR0H#6pI*Ys)@Ez|H`$|0l|J?vLDw40*tH?Gx%=
z8fxebu3~I1P7W)$vN*)@&m%=9S$N#vLZoN;2LlDkvrVU=eSC)z%m<<_c^6JtqzS+*
z$KebO{Q;E!DSge2j`H9L=q_)rB(7%E%Mwc>mBKfTZ)Q0G=lCX{`{lAI_nAmK2gdFz
zZ5RO1QoMPbCS26`I>&(YEc#5}$#=~ad7~PxA0;@VmE5wS>+A$~Lmmar^?a)yy%w_Y
zTJV*iGniu^^b=1A^i%ICm@}vSG9x$>NHPg|aLxHJeK!5~13dmv@LoIJGrT$?NIZnE
zPFg>T4Km&QJ8&7q8AOld;PjCDHb5p;M
znFllb%ZLviYaXCWy_roFBj)UBmKV|DVNTp7@t2t%=1@A`(5@3l(%iu;y%j(9zmU$I5nlrampO=Tnd_Yyh$z>
zPbGN6Bm?G2dkY;h)&FK^2N7)2=6oMU>7-WCeVc6w&o$4O@LWQ$kP7&4Ib{kN^!r`G
z>DnFRbrE$OcZ=k`kGvpx7aZBn7H-PoVbUO(S{?JBhJ%hXy
z^T4&Iz_l-FuKoJyH)3y}ejQ(M>FJwzK4o^EISUV_CRnZDZGxhdiMWF3*Ey5fB2xl?
z2qolawlgm`)!`^XM(xv&ZG_LY4U9SdTPb|zi<>EzrB#bB-41(nr!wkqVg4T8Gp2iR
zAqGH|)P}!)$I*Z!0Kz5nGA}vn`g+R&Bq0Kv#g7_T>HovLf63wrPHYf(e;rRMgbi{=
zv3Nd_01V^-9U0#bm$z9IOI2AQ_+$TK-8hM#P-DzDW*49n4(~qRP715cw?jiW>`-4E
zzNi&GJBZ#+uUrJyr9>^(C*#j9Xh`k1fDEMugYW9n
zW|AnJ_Pjd;PN`JoAAhMs5K)`wqECwq7t($$vTrJpH_w6E5$&!z)I+2Ujjs!=koK0DXjil$7P5vA*wIAVZ8mhA;;bSSX}u8T(`G
z5?@$kJ9{>D7#ihifXfVOruMUuR~h_k24ZNthk7cGAzo*9Tx+~nIKD5TnD<8vfZI;$
zcR%-_t~1+<_aM+O_Wu;%mWZu+sd~N^I8vok>Tyaq%rj?8Tfw3QBa20`Px5b|{hY8xN@A_H=EYCD4o2KO0^P0sVb&(UUxWa=lVBx8k
zIi~+p!f_7PeE|XAi4lDAW)W0spOFVALq~0X4khyOVxllw+>PJQ#ts#)7SiLd7e|Xn
TipBAr6S;|z@xwcI6bt_s7Hu5D

literal 0
HcmV?d00001

diff --git a/devtools/meson/mesonbuild/dependencies/__pycache__/detect.cpython-37.pyc b/devtools/meson/mesonbuild/dependencies/__pycache__/detect.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5618c3906353d52fcda87fda4f8997ac53f722d9
GIT binary patch
literal 6074
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 T.Any:
+        if item.startswith('__'):
+            raise AttributeError()
+        raise DependencyException('no toolchain found')
+
+    def __bool__(self) -> bool:
+        return False
+
+
+class DependencyMethods(Enum):
+    # Auto means to use whatever dependency checking mechanisms in whatever order meson thinks is best.
+    AUTO = 'auto'
+    PKGCONFIG = 'pkg-config'
+    CMAKE = 'cmake'
+    # The dependency is provided by the standard library and does not need to be linked
+    BUILTIN = 'builtin'
+    # Just specify the standard link arguments, assuming the operating system provides the library.
+    SYSTEM = 'system'
+    # This is only supported on OSX - search the frameworks directory by name.
+    EXTRAFRAMEWORK = 'extraframework'
+    # Detect using the sysconfig module.
+    SYSCONFIG = 'sysconfig'
+    # Specify using a "program"-config style tool
+    CONFIG_TOOL = 'config-tool'
+    # For backwards compatibility
+    SDLCONFIG = 'sdlconfig'
+    CUPSCONFIG = 'cups-config'
+    PCAPCONFIG = 'pcap-config'
+    LIBWMFCONFIG = 'libwmf-config'
+    QMAKE = 'qmake'
+    # Misc
+    DUB = 'dub'
+
+
+DependencyTypeName = T.NewType('DependencyTypeName', str)
+
+
+class Dependency(HoldableObject):
+
+    @classmethod
+    def _process_include_type_kw(cls, kwargs: T.Dict[str, T.Any]) -> str:
+        if 'include_type' not in kwargs:
+            return 'preserve'
+        if not isinstance(kwargs['include_type'], str):
+            raise DependencyException('The include_type kwarg must be a string type')
+        if kwargs['include_type'] not in ['preserve', 'system', 'non-system']:
+            raise DependencyException("include_type may only be one of ['preserve', 'system', 'non-system']")
+        return kwargs['include_type']
+
+    def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> None:
+        self.name = f'dep{id(self)}'
+        self.version:  T.Optional[str] = None
+        self.language: T.Optional[str] = None # None means C-like
+        self.is_found = False
+        self.type_name = type_name
+        self.compile_args: T.List[str] = []
+        self.link_args:    T.List[str] = []
+        # Raw -L and -l arguments without manual library searching
+        # If None, self.link_args will be used
+        self.raw_link_args: T.Optional[T.List[str]] = None
+        self.sources: T.List[T.Union['FileOrString', 'CustomTarget', 'StructuredSources']] = []
+        self.extra_files: T.List[mesonlib.File] = []
+        self.include_type = self._process_include_type_kw(kwargs)
+        self.ext_deps: T.List[Dependency] = []
+        self.d_features: T.DefaultDict[str, T.List[T.Any]] = collections.defaultdict(list)
+        self.featurechecks: T.List['FeatureCheckBase'] = []
+        self.feature_since: T.Optional[T.Tuple[str, str]] = None
+
+    def __repr__(self) -> str:
+        return f'<{self.__class__.__name__} {self.name}: {self.is_found}>'
+
+    def is_built(self) -> bool:
+        return False
+
+    def summary_value(self) -> T.Union[str, mlog.AnsiDecorator, mlog.AnsiText]:
+        if not self.found():
+            return mlog.red('NO')
+        if not self.version:
+            return mlog.green('YES')
+        return mlog.AnsiText(mlog.green('YES'), ' ', mlog.cyan(self.version))
+
+    def get_compile_args(self) -> T.List[str]:
+        if self.include_type == 'system':
+            converted = []
+            for i in self.compile_args:
+                if i.startswith('-I') or i.startswith('/I'):
+                    converted += ['-isystem' + i[2:]]
+                else:
+                    converted += [i]
+            return converted
+        if self.include_type == 'non-system':
+            converted = []
+            for i in self.compile_args:
+                if i.startswith('-isystem'):
+                    converted += ['-I' + i[8:]]
+                else:
+                    converted += [i]
+            return converted
+        return self.compile_args
+
+    def get_all_compile_args(self) -> T.List[str]:
+        """Get the compile arguments from this dependency and it's sub dependencies."""
+        return list(itertools.chain(self.get_compile_args(),
+                                    *(d.get_all_compile_args() for d in self.ext_deps)))
+
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
+        if raw and self.raw_link_args is not None:
+            return self.raw_link_args
+        return self.link_args
+
+    def get_all_link_args(self) -> T.List[str]:
+        """Get the link arguments from this dependency and it's sub dependencies."""
+        return list(itertools.chain(self.get_link_args(),
+                                    *(d.get_all_link_args() for d in self.ext_deps)))
+
+    def found(self) -> bool:
+        return self.is_found
+
+    def get_sources(self) -> T.List[T.Union['FileOrString', 'CustomTarget', 'StructuredSources']]:
+        """Source files that need to be added to the target.
+        As an example, gtest-all.cc when using GTest."""
+        return self.sources
+
+    def get_extra_files(self) -> T.List[mesonlib.File]:
+        """Mostly for introspection and IDEs"""
+        return self.extra_files
+
+    def get_name(self) -> str:
+        return self.name
+
+    def get_version(self) -> str:
+        if self.version:
+            return self.version
+        else:
+            return 'unknown'
+
+    def get_include_dirs(self) -> T.List['IncludeDirs']:
+        return []
+
+    def get_include_type(self) -> str:
+        return self.include_type
+
+    def get_exe_args(self, compiler: 'Compiler') -> T.List[str]:
+        return []
+
+    def get_pkgconfig_variable(self, variable_name: str,
+                               define_variable: 'ImmutableListProtocol[str]',
+                               default: T.Optional[str]) -> str:
+        raise DependencyException(f'{self.name!r} is not a pkgconfig dependency')
+
+    def get_configtool_variable(self, variable_name: str) -> str:
+        raise DependencyException(f'{self.name!r} is not a config-tool dependency')
+
+    def get_partial_dependency(self, *, compile_args: bool = False,
+                               link_args: bool = False, links: bool = False,
+                               includes: bool = False, sources: bool = False) -> 'Dependency':
+        """Create a new dependency that contains part of the parent dependency.
+
+        The following options can be inherited:
+            links -- all link_with arguments
+            includes -- all include_directory and -I/-isystem calls
+            sources -- any source, header, or generated sources
+            compile_args -- any compile args
+            link_args -- any link args
+
+        Additionally the new dependency will have the version parameter of it's
+        parent (if any) and the requested values of any dependencies will be
+        added as well.
+        """
+        raise RuntimeError('Unreachable code in partial_dependency called')
+
+    def _add_sub_dependency(self, deplist: T.Iterable[T.Callable[[], 'Dependency']]) -> bool:
+        """Add an internal dependency from a list of possible dependencies.
+
+        This method is intended to make it easier to add additional
+        dependencies to another dependency internally.
+
+        Returns true if the dependency was successfully added, false
+        otherwise.
+        """
+        for d in deplist:
+            dep = d()
+            if dep.is_found:
+                self.ext_deps.append(dep)
+                return True
+        return False
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> str:
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'No default provided for dependency {self!r}, which is not pkg-config, cmake, or config-tool based.')
+
+    def generate_system_dependency(self, include_type: str) -> 'Dependency':
+        new_dep = copy.deepcopy(self)
+        new_dep.include_type = self._process_include_type_kw({'include_type': include_type})
+        return new_dep
+
+class InternalDependency(Dependency):
+    def __init__(self, version: str, incdirs: T.List['IncludeDirs'], compile_args: T.List[str],
+                 link_args: T.List[str],
+                 libraries: T.List[LibTypes],
+                 whole_libraries: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]],
+                 sources: T.Sequence[T.Union[FileOrString, CustomTarget, StructuredSources]],
+                 extra_files: T.Sequence[mesonlib.File],
+                 ext_deps: T.List[Dependency], variables: T.Dict[str, str],
+                 d_module_versions: T.List[T.Union[str, int]], d_import_dirs: T.List['IncludeDirs'],
+                 objects: T.List['ExtractedObjects']):
+        super().__init__(DependencyTypeName('internal'), {})
+        self.version = version
+        self.is_found = True
+        self.include_directories = incdirs
+        self.compile_args = compile_args
+        self.link_args = link_args
+        self.libraries = libraries
+        self.whole_libraries = whole_libraries
+        self.sources = list(sources)
+        self.extra_files = list(extra_files)
+        self.ext_deps = ext_deps
+        self.variables = variables
+        self.objects = objects
+        if d_module_versions:
+            self.d_features['versions'] = d_module_versions
+        if d_import_dirs:
+            self.d_features['import_dirs'] = d_import_dirs
+
+    def __deepcopy__(self, memo: T.Dict[int, 'InternalDependency']) -> 'InternalDependency':
+        result = self.__class__.__new__(self.__class__)
+        assert isinstance(result, InternalDependency)
+        memo[id(self)] = result
+        for k, v in self.__dict__.items():
+            if k in {'libraries', 'whole_libraries'}:
+                setattr(result, k, copy.copy(v))
+            else:
+                setattr(result, k, copy.deepcopy(v, memo))
+        return result
+
+    def summary_value(self) -> mlog.AnsiDecorator:
+        # Omit the version.  Most of the time it will be just the project
+        # version, which is uninteresting in the summary.
+        return mlog.green('YES')
+
+    def is_built(self) -> bool:
+        if self.sources or self.libraries or self.whole_libraries:
+            return True
+        return any(d.is_built() for d in self.ext_deps)
+
+    def get_pkgconfig_variable(self, variable_name: str,
+                               define_variable: 'ImmutableListProtocol[str]',
+                               default: T.Optional[str]) -> str:
+        raise DependencyException('Method "get_pkgconfig_variable()" is '
+                                  'invalid for an internal dependency')
+
+    def get_configtool_variable(self, variable_name: str) -> str:
+        raise DependencyException('Method "get_configtool_variable()" is '
+                                  'invalid for an internal dependency')
+
+    def get_partial_dependency(self, *, compile_args: bool = False,
+                               link_args: bool = False, links: bool = False,
+                               includes: bool = False, sources: bool = False,
+                               extra_files: bool = False) -> InternalDependency:
+        final_compile_args = self.compile_args.copy() if compile_args else []
+        final_link_args = self.link_args.copy() if link_args else []
+        final_libraries = self.libraries.copy() if links else []
+        final_whole_libraries = self.whole_libraries.copy() if links else []
+        final_sources = self.sources.copy() if sources else []
+        final_extra_files = self.extra_files.copy() if extra_files else []
+        final_includes = self.include_directories.copy() if includes else []
+        final_deps = [d.get_partial_dependency(
+            compile_args=compile_args, link_args=link_args, links=links,
+            includes=includes, sources=sources) for d in self.ext_deps]
+        return InternalDependency(
+            self.version, final_includes, final_compile_args,
+            final_link_args, final_libraries, final_whole_libraries,
+            final_sources, final_extra_files, final_deps, self.variables, [], [], [])
+
+    def get_include_dirs(self) -> T.List['IncludeDirs']:
+        return self.include_directories
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> str:
+        val = self.variables.get(internal, default_value)
+        if val is not None:
+            return val
+        raise DependencyException(f'Could not get an internal variable and no default provided for {self!r}')
+
+    def generate_link_whole_dependency(self) -> Dependency:
+        from ..build import SharedLibrary, CustomTarget, CustomTargetIndex
+        new_dep = copy.deepcopy(self)
+        for x in new_dep.libraries:
+            if isinstance(x, SharedLibrary):
+                raise MesonException('Cannot convert a dependency to link_whole when it contains a '
+                                     'SharedLibrary')
+            elif isinstance(x, (CustomTarget, CustomTargetIndex)) and x.links_dynamically():
+                raise MesonException('Cannot convert a dependency to link_whole when it contains a '
+                                     'CustomTarget or CustomTargetIndex which is a shared library')
+
+        # Mypy doesn't understand that the above is a TypeGuard
+        new_dep.whole_libraries += T.cast('T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]]',
+                                          new_dep.libraries)
+        new_dep.libraries = []
+        return new_dep
+
+class HasNativeKwarg:
+    def __init__(self, kwargs: T.Dict[str, T.Any]):
+        self.for_machine = self.get_for_machine_from_kwargs(kwargs)
+
+    def get_for_machine_from_kwargs(self, kwargs: T.Dict[str, T.Any]) -> MachineChoice:
+        return MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST
+
+class ExternalDependency(Dependency, HasNativeKwarg):
+    def __init__(self, type_name: DependencyTypeName, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
+        Dependency.__init__(self, type_name, kwargs)
+        self.env = environment
+        self.name = type_name # default
+        self.is_found = False
+        self.language = language
+        version_reqs = kwargs.get('version', None)
+        if isinstance(version_reqs, str):
+            version_reqs = [version_reqs]
+        self.version_reqs: T.Optional[T.List[str]] = version_reqs
+        self.required = kwargs.get('required', True)
+        self.silent = kwargs.get('silent', False)
+        self.static = kwargs.get('static', self.env.coredata.get_option(OptionKey('prefer_static')))
+        self.libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED
+        if not isinstance(self.static, bool):
+            raise DependencyException('Static keyword must be boolean')
+        # Is this dependency to be run on the build platform?
+        HasNativeKwarg.__init__(self, kwargs)
+        self.clib_compiler = detect_compiler(self.name, environment, self.for_machine, self.language)
+
+    def get_compiler(self) -> T.Union['MissingCompiler', 'Compiler']:
+        return self.clib_compiler
+
+    def get_partial_dependency(self, *, compile_args: bool = False,
+                               link_args: bool = False, links: bool = False,
+                               includes: bool = False, sources: bool = False) -> Dependency:
+        new = copy.copy(self)
+        if not compile_args:
+            new.compile_args = []
+        if not link_args:
+            new.link_args = []
+        if not sources:
+            new.sources = []
+        if not includes:
+            pass # TODO maybe filter compile_args?
+        if not sources:
+            new.sources = []
+
+        return new
+
+    def log_details(self) -> str:
+        return ''
+
+    def log_info(self) -> str:
+        return ''
+
+    @staticmethod
+    def log_tried() -> str:
+        return ''
+
+    # Check if dependency version meets the requirements
+    def _check_version(self) -> None:
+        if not self.is_found:
+            return
+
+        if self.version_reqs:
+            # an unknown version can never satisfy any requirement
+            if not self.version:
+                self.is_found = False
+                found_msg: mlog.TV_LoggableList = []
+                found_msg += ['Dependency', mlog.bold(self.name), 'found:']
+                found_msg += [mlog.red('NO'), 'unknown version, but need:', self.version_reqs]
+                mlog.log(*found_msg)
+
+                if self.required:
+                    m = f'Unknown version, but need {self.version_reqs!r}.'
+                    raise DependencyException(m)
+
+            else:
+                (self.is_found, not_found, found) = \
+                    version_compare_many(self.version, self.version_reqs)
+                if not self.is_found:
+                    found_msg = ['Dependency', mlog.bold(self.name), 'found:']
+                    found_msg += [mlog.red('NO'),
+                                  'found', mlog.normal_cyan(self.version), 'but need:',
+                                  mlog.bold(', '.join([f"'{e}'" for e in not_found]))]
+                    if found:
+                        found_msg += ['; matched:',
+                                      ', '.join([f"'{e}'" for e in found])]
+                    mlog.log(*found_msg)
+
+                    if self.required:
+                        m = 'Invalid version, need {!r} {!r} found {!r}.'
+                        raise DependencyException(m.format(self.name, not_found, self.version))
+                    return
+
+
+class NotFoundDependency(Dependency):
+    def __init__(self, name: str, environment: 'Environment') -> None:
+        super().__init__(DependencyTypeName('not-found'), {})
+        self.env = environment
+        self.name = name
+        self.is_found = False
+
+    def get_partial_dependency(self, *, compile_args: bool = False,
+                               link_args: bool = False, links: bool = False,
+                               includes: bool = False, sources: bool = False) -> 'NotFoundDependency':
+        return copy.copy(self)
+
+
+class ExternalLibrary(ExternalDependency):
+    def __init__(self, name: str, link_args: T.List[str], environment: 'Environment',
+                 language: str, silent: bool = False) -> None:
+        super().__init__(DependencyTypeName('library'), environment, {}, language=language)
+        self.name = name
+        self.language = language
+        self.is_found = False
+        if link_args:
+            self.is_found = True
+            self.link_args = link_args
+        if not silent:
+            if self.is_found:
+                mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES'))
+            else:
+                mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO'))
+
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
+        '''
+        External libraries detected using a compiler must only be used with
+        compatible code. For instance, Vala libraries (.vapi files) cannot be
+        used with C code, and not all Rust library types can be linked with
+        C-like code. Note that C++ libraries *can* be linked with C code with
+        a C++ linker (and vice-versa).
+        '''
+        # Using a vala library in a non-vala target, or a non-vala library in a vala target
+        # XXX: This should be extended to other non-C linkers such as Rust
+        if (self.language == 'vala' and language != 'vala') or \
+           (language == 'vala' and self.language != 'vala'):
+            return []
+        return super().get_link_args(language=language, raw=raw)
+
+    def get_partial_dependency(self, *, compile_args: bool = False,
+                               link_args: bool = False, links: bool = False,
+                               includes: bool = False, sources: bool = False) -> 'ExternalLibrary':
+        # External library only has link_args, so ignore the rest of the
+        # interface.
+        new = copy.copy(self)
+        if not link_args:
+            new.link_args = []
+        return new
+
+
+def get_leaf_external_dependencies(deps: T.List[Dependency]) -> T.List[Dependency]:
+    if not deps:
+        # Ensure that we always return a new instance
+        return deps.copy()
+    final_deps = []
+    while deps:
+        next_deps = []
+        for d in mesonlib.listify(deps):
+            if not isinstance(d, Dependency) or d.is_built():
+                raise DependencyException('Dependencies must be external dependencies')
+            final_deps.append(d)
+            next_deps.extend(d.ext_deps)
+        deps = next_deps
+    return final_deps
+
+
+def sort_libpaths(libpaths: T.List[str], refpaths: T.List[str]) -> T.List[str]:
+    """Sort  according to 
+
+    It is intended to be used to sort -L flags returned by pkg-config.
+    Pkg-config returns flags in random order which cannot be relied on.
+    """
+    if len(refpaths) == 0:
+        return list(libpaths)
+
+    def key_func(libpath: str) -> T.Tuple[int, int]:
+        common_lengths: T.List[int] = []
+        for refpath in refpaths:
+            try:
+                common_path: str = os.path.commonpath([libpath, refpath])
+            except ValueError:
+                common_path = ''
+            common_lengths.append(len(common_path))
+        max_length = max(common_lengths)
+        max_index = common_lengths.index(max_length)
+        reversed_max_length = len(refpaths[max_index]) - max_length
+        return (max_index, reversed_max_length)
+    return sorted(libpaths, key=key_func)
+
+def strip_system_libdirs(environment: 'Environment', for_machine: MachineChoice, link_args: T.List[str]) -> T.List[str]:
+    """Remove -L arguments.
+
+    leaving these in will break builds where a user has a version of a library
+    in the system path, and a different version not in the system path if they
+    want to link against the non-system path version.
+    """
+    exclude = {f'-L{p}' for p in environment.get_compiler_system_lib_dirs(for_machine)}
+    return [l for l in link_args if l not in exclude]
+
+def strip_system_includedirs(environment: 'Environment', for_machine: MachineChoice, include_args: T.List[str]) -> T.List[str]:
+    """Remove -I arguments.
+
+    leaving these in will break builds where user want dependencies with system
+    include-type used in rust.bindgen targets as if will cause system headers
+    to not be found.
+    """
+
+    exclude = {f'-I{p}' for p in environment.get_compiler_system_include_dirs(for_machine)}
+    return [i for i in include_args if i not in exclude]
+
+def process_method_kw(possible: T.Iterable[DependencyMethods], kwargs: T.Dict[str, T.Any]) -> T.List[DependencyMethods]:
+    method = kwargs.get('method', 'auto')  # type: T.Union[DependencyMethods, str]
+    if isinstance(method, DependencyMethods):
+        return [method]
+    # TODO: try/except?
+    if method not in [e.value for e in DependencyMethods]:
+        raise DependencyException(f'method {method!r} is invalid')
+    method = DependencyMethods(method)
+
+    # Raise FeatureNew where appropriate
+    if method is DependencyMethods.CONFIG_TOOL:
+        # FIXME: needs to get a handle on the subproject
+        # FeatureNew.single_use('Configuration method "config-tool"', '0.44.0')
+        pass
+    # This sets per-tool config methods which are deprecated to to the new
+    # generic CONFIG_TOOL value.
+    if method in [DependencyMethods.SDLCONFIG, DependencyMethods.CUPSCONFIG,
+                  DependencyMethods.PCAPCONFIG, DependencyMethods.LIBWMFCONFIG]:
+        # FIXME: needs to get a handle on the subproject
+        #FeatureDeprecated.single_use(f'Configuration method {method.value}', '0.44', 'Use "config-tool" instead.')
+        method = DependencyMethods.CONFIG_TOOL
+    if method is DependencyMethods.QMAKE:
+        # FIXME: needs to get a handle on the subproject
+        # FeatureDeprecated.single_use('Configuration method "qmake"', '0.58', 'Use "config-tool" instead.')
+        method = DependencyMethods.CONFIG_TOOL
+
+    # Set the detection method. If the method is set to auto, use any available method.
+    # If method is set to a specific string, allow only that detection method.
+    if method == DependencyMethods.AUTO:
+        methods = list(possible)
+    elif method in possible:
+        methods = [method]
+    else:
+        raise DependencyException(
+            'Unsupported detection method: {}, allowed methods are {}'.format(
+                method.value,
+                mlog.format_list([x.value for x in [DependencyMethods.AUTO] + list(possible)])))
+
+    return methods
+
+def detect_compiler(name: str, env: 'Environment', for_machine: MachineChoice,
+                    language: T.Optional[str]) -> T.Union['MissingCompiler', 'Compiler']:
+    """Given a language and environment find the compiler used."""
+    compilers = env.coredata.compilers[for_machine]
+
+    # Set the compiler for this dependency if a language is specified,
+    # else try to pick something that looks usable.
+    if language:
+        if language not in compilers:
+            m = name.capitalize() + ' requires a {0} compiler, but ' \
+                '{0} is not in the list of project languages'
+            raise DependencyException(m.format(language.capitalize()))
+        return compilers[language]
+    else:
+        for lang in clib_langs:
+            try:
+                return compilers[lang]
+            except KeyError:
+                continue
+    return MissingCompiler()
+
+
+class SystemDependency(ExternalDependency):
+
+    """Dependency base for System type dependencies."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None) -> None:
+        super().__init__(DependencyTypeName('system'), env, kwargs, language=language)
+        self.name = name
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'system'
+
+
+class BuiltinDependency(ExternalDependency):
+
+    """Dependency base for Builtin type dependencies."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None) -> None:
+        super().__init__(DependencyTypeName('builtin'), env, kwargs, language=language)
+        self.name = name
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'builtin'
diff --git a/devtools/meson/mesonbuild/dependencies/boost.py b/devtools/meson/mesonbuild/dependencies/boost.py
new file mode 100644
index 0000000..0e4dab9
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/boost.py
@@ -0,0 +1,1092 @@
+# Copyright 2013-2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import re
+import dataclasses
+import functools
+import typing as T
+from pathlib import Path
+
+from .. import mlog
+from .. import mesonlib
+
+from .base import DependencyException, SystemDependency
+from .detect import packages
+from .pkgconfig import PkgConfigDependency
+from .misc import threads_factory
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment, Properties
+
+# On windows 3 directory layouts are supported:
+# * The default layout (versioned) installed:
+#   - $BOOST_ROOT/include/boost-x_x/boost/*.hpp
+#   - $BOOST_ROOT/lib/*.lib
+# * The non-default layout (system) installed:
+#   - $BOOST_ROOT/include/boost/*.hpp
+#   - $BOOST_ROOT/lib/*.lib
+# * The pre-built binaries from sf.net:
+#   - $BOOST_ROOT/boost/*.hpp
+#   - $BOOST_ROOT/lib-/*.lib where arch=32/64 and compiler=msvc-14.1
+#
+# Note that we should also try to support:
+# mingw-w64 / Windows : libboost_-mt.a            (location = /mingw64/lib/)
+#                       libboost_-mt.dll.a
+#
+# The `modules` argument accept library names. This is because every module that
+# has libraries to link against also has multiple options regarding how to
+# link. See for example:
+# * http://www.boost.org/doc/libs/1_65_1/libs/test/doc/html/boost_test/usage_variants.html
+# * http://www.boost.org/doc/libs/1_65_1/doc/html/stacktrace/configuration_and_build.html
+# * http://www.boost.org/doc/libs/1_65_1/libs/math/doc/html/math_toolkit/main_tr1.html
+
+# **On Unix**, official packaged versions of boost libraries follow the following schemes:
+#
+# Linux / Debian:   libboost_.so -> libboost_.so.1.66.0
+# Linux / Red Hat:  libboost_.so -> libboost_.so.1.66.0
+# Linux / OpenSuse: libboost_.so -> libboost_.so.1.66.0
+# Win   / Cygwin:   libboost_.dll.a                                 (location = /usr/lib)
+#                   libboost_.a
+#                   cygboost__1_64.dll                              (location = /usr/bin)
+# Win   / VS:       boost_-vc-mt[-gd]--1_67.dll          (location = C:/local/boost_1_67_0)
+# Mac   / homebrew: libboost_.dylib + libboost_-mt.dylib    (location = /usr/local/lib)
+# Mac   / macports: libboost_.dylib + libboost_-mt.dylib    (location = /opt/local/lib)
+#
+# Its not clear that any other abi tags (e.g. -gd) are used in official packages.
+#
+# On Linux systems, boost libs have multithreading support enabled, but without the -mt tag.
+#
+# Boost documentation recommends using complex abi tags like "-lboost_regex-gcc34-mt-d-1_36".
+# (See http://www.boost.org/doc/libs/1_66_0/more/getting_started/unix-variants.html#library-naming)
+# However, its not clear that any Unix distribution follows this scheme.
+# Furthermore, the boost documentation for unix above uses examples from windows like
+#   "libboost_regex-vc71-mt-d-x86-1_34.lib", so apparently the abi tags may be more aimed at windows.
+#
+# We follow the following strategy for finding modules:
+# A) Detect potential boost root directories (uses also BOOST_ROOT env var)
+# B) Foreach candidate
+#   1. Look for the boost headers (boost/version.pp)
+#   2. Find all boost libraries
+#     2.1 Add all libraries in lib*
+#     2.2 Filter out non boost libraries
+#     2.3 Filter the remaining libraries based on the meson requirements (static/shared, etc.)
+#     2.4 Ensure that all libraries have the same boost tag (and are thus compatible)
+#   3. Select the libraries matching the requested modules
+
+@dataclasses.dataclass(eq=False, order=False)
+class UnknownFileException(Exception):
+    path: Path
+
+@functools.total_ordering
+class BoostIncludeDir():
+    def __init__(self, path: Path, version_int: int):
+        self.path = path
+        self.version_int = version_int
+        major = int(self.version_int / 100000)
+        minor = int((self.version_int / 100) % 1000)
+        patch = int(self.version_int % 100)
+        self.version = f'{major}.{minor}.{patch}'
+        self.version_lib = f'{major}_{minor}'
+
+    def __repr__(self) -> str:
+        return f''
+
+    def __lt__(self, other: object) -> bool:
+        if isinstance(other, BoostIncludeDir):
+            return (self.version_int, self.path) < (other.version_int, other.path)
+        return NotImplemented
+
+@functools.total_ordering
+class BoostLibraryFile():
+    # Python libraries are special because of the included
+    # minor version in the module name.
+    boost_python_libs = ['boost_python', 'boost_numpy']
+    reg_python_mod_split = re.compile(r'(boost_[a-zA-Z]+)([0-9]*)')
+
+    reg_abi_tag = re.compile(r'^s?g?y?d?p?n?$')
+    reg_ver_tag = re.compile(r'^[0-9_]+$')
+
+    def __init__(self, path: Path):
+        self.path = path
+        self.name = self.path.name
+
+        # Initialize default properties
+        self.static = False
+        self.toolset = ''
+        self.arch = ''
+        self.version_lib = ''
+        self.mt = True
+
+        self.runtime_static = False
+        self.runtime_debug = False
+        self.python_debug = False
+        self.debug = False
+        self.stlport = False
+        self.deprecated_iostreams = False
+
+        # Post process the library name
+        name_parts = self.name.split('.')
+        self.basename = name_parts[0]
+        self.suffixes = name_parts[1:]
+        self.vers_raw = [x for x in self.suffixes if x.isdigit()]
+        self.suffixes = [x for x in self.suffixes if not x.isdigit()]
+        self.nvsuffix = '.'.join(self.suffixes)  # Used for detecting the library type
+        self.nametags = self.basename.split('-')
+        self.mod_name = self.nametags[0]
+        if self.mod_name.startswith('lib'):
+            self.mod_name = self.mod_name[3:]
+
+        # Set library version if possible
+        if len(self.vers_raw) >= 2:
+            self.version_lib = '{}_{}'.format(self.vers_raw[0], self.vers_raw[1])
+
+        # Detecting library type
+        if self.nvsuffix in {'so', 'dll', 'dll.a', 'dll.lib', 'dylib'}:
+            self.static = False
+        elif self.nvsuffix in {'a', 'lib'}:
+            self.static = True
+        else:
+            raise UnknownFileException(self.path)
+
+        # boost_.lib is the dll import library
+        if self.basename.startswith('boost_') and self.nvsuffix == 'lib':
+            self.static = False
+
+        # Process tags
+        tags = self.nametags[1:]
+        # Filter out the python version tag and fix modname
+        if self.is_python_lib():
+            tags = self.fix_python_name(tags)
+        if not tags:
+            return
+
+        # Without any tags mt is assumed, however, an absence of mt in the name
+        # with tags present indicates that the lib was built without mt support
+        self.mt = False
+        for i in tags:
+            if i == 'mt':
+                self.mt = True
+            elif len(i) == 3 and i[1:] in {'32', '64'}:
+                self.arch = i
+            elif BoostLibraryFile.reg_abi_tag.match(i):
+                self.runtime_static = 's' in i
+                self.runtime_debug = 'g' in i
+                self.python_debug = 'y' in i
+                self.debug = 'd' in i
+                self.stlport = 'p' in i
+                self.deprecated_iostreams = 'n' in i
+            elif BoostLibraryFile.reg_ver_tag.match(i):
+                self.version_lib = i
+            else:
+                self.toolset = i
+
+    def __repr__(self) -> str:
+        return f''
+
+    def __lt__(self, other: object) -> bool:
+        if isinstance(other, BoostLibraryFile):
+            return (
+                self.mod_name, self.static, self.version_lib, self.arch,
+                not self.mt, not self.runtime_static,
+                not self.debug, self.runtime_debug, self.python_debug,
+                self.stlport, self.deprecated_iostreams,
+                self.name,
+            ) < (
+                other.mod_name, other.static, other.version_lib, other.arch,
+                not other.mt, not other.runtime_static,
+                not other.debug, other.runtime_debug, other.python_debug,
+                other.stlport, other.deprecated_iostreams,
+                other.name,
+            )
+        return NotImplemented
+
+    def __eq__(self, other: object) -> bool:
+        if isinstance(other, BoostLibraryFile):
+            return self.name == other.name
+        return NotImplemented
+
+    def __hash__(self) -> int:
+        return hash(self.name)
+
+    @property
+    def abitag(self) -> str:
+        abitag = ''
+        abitag += 'S' if self.static else '-'
+        abitag += 'M' if self.mt else '-'
+        abitag += ' '
+        abitag += 's' if self.runtime_static else '-'
+        abitag += 'g' if self.runtime_debug else '-'
+        abitag += 'y' if self.python_debug else '-'
+        abitag += 'd' if self.debug else '-'
+        abitag += 'p' if self.stlport else '-'
+        abitag += 'n' if self.deprecated_iostreams else '-'
+        abitag += ' ' + (self.arch or '???')
+        abitag += ' ' + (self.toolset or '?')
+        abitag += ' ' + (self.version_lib or 'x_xx')
+        return abitag
+
+    def is_boost(self) -> bool:
+        return any(self.name.startswith(x) for x in ['libboost_', 'boost_'])
+
+    def is_python_lib(self) -> bool:
+        return any(self.mod_name.startswith(x) for x in BoostLibraryFile.boost_python_libs)
+
+    def fix_python_name(self, tags: T.List[str]) -> T.List[str]:
+        # Handle the boost_python naming madness.
+        # See https://github.com/mesonbuild/meson/issues/4788 for some distro
+        # specific naming variations.
+        other_tags = []  # type: T.List[str]
+
+        # Split the current modname into the base name and the version
+        m_cur = BoostLibraryFile.reg_python_mod_split.match(self.mod_name)
+        cur_name = m_cur.group(1)
+        cur_vers = m_cur.group(2)
+
+        # Update the current version string if the new version string is longer
+        def update_vers(new_vers: str) -> None:
+            nonlocal cur_vers
+            new_vers = new_vers.replace('_', '')
+            new_vers = new_vers.replace('.', '')
+            if not new_vers.isdigit():
+                return
+            if len(new_vers) > len(cur_vers):
+                cur_vers = new_vers
+
+        for i in tags:
+            if i.startswith('py'):
+                update_vers(i[2:])
+            elif i.isdigit():
+                update_vers(i)
+            elif len(i) >= 3 and i[0].isdigit and i[2].isdigit() and i[1] == '.':
+                update_vers(i)
+            else:
+                other_tags += [i]
+
+        self.mod_name = cur_name + cur_vers
+        return other_tags
+
+    def mod_name_matches(self, mod_name: str) -> bool:
+        if self.mod_name == mod_name:
+            return True
+        if not self.is_python_lib():
+            return False
+
+        m_cur = BoostLibraryFile.reg_python_mod_split.match(self.mod_name)
+        m_arg = BoostLibraryFile.reg_python_mod_split.match(mod_name)
+
+        if not m_cur or not m_arg:
+            return False
+
+        if m_cur.group(1) != m_arg.group(1):
+            return False
+
+        cur_vers = m_cur.group(2)
+        arg_vers = m_arg.group(2)
+
+        # Always assume python 2 if nothing is specified
+        if not arg_vers:
+            arg_vers = '2'
+
+        return cur_vers.startswith(arg_vers)
+
+    def version_matches(self, version_lib: str) -> bool:
+        # If no version tag is present, assume that it fits
+        if not self.version_lib or not version_lib:
+            return True
+        return self.version_lib == version_lib
+
+    def arch_matches(self, arch: str) -> bool:
+        # If no version tag is present, assume that it fits
+        if not self.arch or not arch:
+            return True
+        return self.arch == arch
+
+    def vscrt_matches(self, vscrt: str) -> bool:
+        # If no vscrt tag present, assume that it fits  ['/MD', '/MDd', '/MT', '/MTd']
+        if not vscrt:
+            return True
+        if vscrt in {'/MD', '-MD'}:
+            return not self.runtime_static and not self.runtime_debug
+        elif vscrt in {'/MDd', '-MDd'}:
+            return not self.runtime_static and self.runtime_debug
+        elif vscrt in {'/MT', '-MT'}:
+            return (self.runtime_static or not self.static) and not self.runtime_debug
+        elif vscrt in {'/MTd', '-MTd'}:
+            return (self.runtime_static or not self.static) and self.runtime_debug
+
+        mlog.warning(f'Boost: unknown vscrt tag {vscrt}. This may cause the compilation to fail. Please consider reporting this as a bug.', once=True)
+        return True
+
+    def get_compiler_args(self) -> T.List[str]:
+        args = []  # type: T.List[str]
+        if self.mod_name in boost_libraries:
+            libdef = boost_libraries[self.mod_name]  # type: BoostLibrary
+            if self.static:
+                args += libdef.static
+            else:
+                args += libdef.shared
+            if self.mt:
+                args += libdef.multi
+            else:
+                args += libdef.single
+        return args
+
+    def get_link_args(self) -> T.List[str]:
+        return [self.path.as_posix()]
+
+class BoostDependency(SystemDependency):
+    def __init__(self, environment: Environment, kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('boost', environment, kwargs, language='cpp')
+        buildtype = environment.coredata.get_option(mesonlib.OptionKey('buildtype'))
+        assert isinstance(buildtype, str)
+        self.debug = buildtype.startswith('debug')
+        self.multithreading = kwargs.get('threading', 'multi') == 'multi'
+
+        self.boost_root = None  # type: T.Optional[Path]
+        self.explicit_static = 'static' in kwargs
+
+        # Extract and validate modules
+        self.modules = mesonlib.extract_as_list(kwargs, 'modules')  # type: T.List[str]
+        for i in self.modules:
+            if not isinstance(i, str):
+                raise DependencyException('Boost module argument is not a string.')
+            if i.startswith('boost_'):
+                raise DependencyException('Boost modules must be passed without the boost_ prefix')
+
+        self.modules_found = []    # type: T.List[str]
+        self.modules_missing = []  # type: T.List[str]
+
+        # Do we need threads?
+        if 'thread' in self.modules:
+            if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+                self.is_found = False
+                return
+
+        # Try figuring out the architecture tag
+        self.arch = environment.machines[self.for_machine].cpu_family
+        self.arch = boost_arch_map.get(self.arch, None)
+
+        # First, look for paths specified in a machine file
+        props = self.env.properties[self.for_machine]
+        if any(x in self.env.properties[self.for_machine] for x in
+               ['boost_includedir', 'boost_librarydir', 'boost_root']):
+            self.detect_boost_machine_file(props)
+            return
+
+        # Finally, look for paths from .pc files and from searching the filesystem
+        self.detect_roots()
+
+    def check_and_set_roots(self, roots: T.List[Path], use_system: bool) -> None:
+        roots = list(mesonlib.OrderedSet(roots))
+        for j in roots:
+            #   1. Look for the boost headers (boost/version.hpp)
+            mlog.debug(f'Checking potential boost root {j.as_posix()}')
+            inc_dirs = self.detect_inc_dirs(j)
+            inc_dirs = sorted(inc_dirs, reverse=True)  # Prefer the newer versions
+
+            # Early abort when boost is not found
+            if not inc_dirs:
+                continue
+
+            lib_dirs = self.detect_lib_dirs(j, use_system)
+            self.is_found = self.run_check(inc_dirs, lib_dirs)
+            if self.is_found:
+                self.boost_root = j
+                break
+
+    def detect_boost_machine_file(self, props: 'Properties') -> None:
+        """Detect boost with values in the machine file or environment.
+
+        The machine file values are defaulted to the environment values.
+        """
+        # XXX: if we had a TypedDict we wouldn't need this
+        incdir = props.get('boost_includedir')
+        assert incdir is None or isinstance(incdir, str)
+        libdir = props.get('boost_librarydir')
+        assert libdir is None or isinstance(libdir, str)
+
+        if incdir and libdir:
+            inc_dir = Path(incdir)
+            lib_dir = Path(libdir)
+
+            if not inc_dir.is_absolute() or not lib_dir.is_absolute():
+                raise DependencyException('Paths given for boost_includedir and boost_librarydir in machine file must be absolute')
+
+            mlog.debug('Trying to find boost with:')
+            mlog.debug(f'  - boost_includedir = {inc_dir}')
+            mlog.debug(f'  - boost_librarydir = {lib_dir}')
+
+            return self.detect_split_root(inc_dir, lib_dir)
+
+        elif incdir or libdir:
+            raise DependencyException('Both boost_includedir *and* boost_librarydir have to be set in your machine file (one is not enough)')
+
+        rootdir = props.get('boost_root')
+        # It shouldn't be possible to get here without something in boost_root
+        assert rootdir
+
+        raw_paths = mesonlib.stringlistify(rootdir)
+        paths = [Path(x) for x in raw_paths]
+        if paths and any(not x.is_absolute() for x in paths):
+            raise DependencyException('boost_root path given in machine file must be absolute')
+
+        self.check_and_set_roots(paths, use_system=False)
+
+    def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) -> bool:
+        mlog.debug('  - potential library dirs: {}'.format([x.as_posix() for x in lib_dirs]))
+        mlog.debug('  - potential include dirs: {}'.format([x.path.as_posix() for x in inc_dirs]))
+
+        #   2. Find all boost libraries
+        libs = []  # type: T.List[BoostLibraryFile]
+        for i in lib_dirs:
+            libs = self.detect_libraries(i)
+            if libs:
+                mlog.debug(f'  - found boost library dir: {i}')
+                # mlog.debug('  - raw library list:')
+                # for j in libs:
+                #     mlog.debug('    - {}'.format(j))
+                break
+        libs = sorted(set(libs))
+
+        modules = ['boost_' + x for x in self.modules]
+        for inc in inc_dirs:
+            mlog.debug(f'  - found boost {inc.version} include dir: {inc.path}')
+            f_libs = self.filter_libraries(libs, inc.version_lib)
+
+            mlog.debug('  - filtered library list:')
+            for j in f_libs:
+                mlog.debug(f'    - {j}')
+
+            #   3. Select the libraries matching the requested modules
+            not_found = []  # type: T.List[str]
+            selected_modules = []  # type: T.List[BoostLibraryFile]
+            for mod in modules:
+                found = False
+                for l in f_libs:
+                    if l.mod_name_matches(mod):
+                        selected_modules += [l]
+                        found = True
+                        break
+                if not found:
+                    not_found += [mod]
+
+            # log the result
+            mlog.debug('  - found:')
+            comp_args = []  # type: T.List[str]
+            link_args = []  # type: T.List[str]
+            for j in selected_modules:
+                c_args = j.get_compiler_args()
+                l_args = j.get_link_args()
+                mlog.debug('    - {:<24} link={} comp={}'.format(j.mod_name, str(l_args), str(c_args)))
+                comp_args += c_args
+                link_args += l_args
+
+            comp_args = list(mesonlib.OrderedSet(comp_args))
+            link_args = list(mesonlib.OrderedSet(link_args))
+
+            self.modules_found = [x.mod_name for x in selected_modules]
+            self.modules_found = [x[6:] for x in self.modules_found]
+            self.modules_found = sorted(set(self.modules_found))
+            self.modules_missing = not_found
+            self.modules_missing = [x[6:] for x in self.modules_missing]
+            self.modules_missing = sorted(set(self.modules_missing))
+
+            # if we found all modules we are done
+            if not not_found:
+                self.version = inc.version
+                self.compile_args = ['-I' + inc.path.as_posix()]
+                self.compile_args += comp_args
+                self.compile_args += self._extra_compile_args()
+                self.compile_args = list(mesonlib.OrderedSet(self.compile_args))
+                self.link_args = link_args
+                mlog.debug(f'  - final compile args: {self.compile_args}')
+                mlog.debug(f'  - final link args:    {self.link_args}')
+                return True
+
+            # in case we missed something log it and try again
+            mlog.debug('  - NOT found:')
+            for mod in not_found:
+                mlog.debug(f'    - {mod}')
+
+        return False
+
+    def detect_inc_dirs(self, root: Path) -> T.List[BoostIncludeDir]:
+        candidates = []  # type: T.List[Path]
+        inc_root = root / 'include'
+
+        candidates += [root / 'boost']
+        candidates += [inc_root / 'boost']
+        if inc_root.is_dir():
+            for i in inc_root.iterdir():
+                if not i.is_dir() or not i.name.startswith('boost-'):
+                    continue
+                candidates += [i / 'boost']
+        candidates = [x for x in candidates if x.is_dir()]
+        candidates = [x / 'version.hpp' for x in candidates]
+        candidates = [x for x in candidates if x.exists()]
+        return [self._include_dir_from_version_header(x) for x in candidates]
+
+    def detect_lib_dirs(self, root: Path, use_system: bool) -> T.List[Path]:
+        # First check the system include paths. Only consider those within the
+        # given root path
+
+        if use_system:
+            system_dirs_t = self.clib_compiler.get_library_dirs(self.env)
+            system_dirs = [Path(x) for x in system_dirs_t]
+            system_dirs = [x.resolve() for x in system_dirs if x.exists()]
+            system_dirs = [x for x in system_dirs if mesonlib.path_is_in_root(x, root)]
+            system_dirs = list(mesonlib.OrderedSet(system_dirs))
+
+            if system_dirs:
+                return system_dirs
+
+        # No system include paths were found --> fall back to manually looking
+        # for library dirs in root
+        dirs = []     # type: T.List[Path]
+        subdirs = []  # type: T.List[Path]
+        for i in root.iterdir():
+            if i.is_dir() and i.name.startswith('lib'):
+                dirs += [i]
+
+        # Some distros put libraries not directly inside /usr/lib but in /usr/lib/x86_64-linux-gnu
+        for i in dirs:
+            for j in i.iterdir():
+                if j.is_dir() and j.name.endswith('-linux-gnu'):
+                    subdirs += [j]
+
+        # Filter out paths that don't match the target arch to avoid finding
+        # the wrong libraries. See https://github.com/mesonbuild/meson/issues/7110
+        if not self.arch:
+            return dirs + subdirs
+
+        arch_list_32 = ['32', 'i386']
+        arch_list_64 = ['64']
+
+        raw_list = dirs + subdirs
+        no_arch = [x for x in raw_list if not any(y in x.name for y in arch_list_32 + arch_list_64)]
+
+        matching_arch = []  # type: T.List[Path]
+        if '32' in self.arch:
+            matching_arch = [x for x in raw_list if any(y in x.name for y in arch_list_32)]
+        elif '64' in self.arch:
+            matching_arch = [x for x in raw_list if any(y in x.name for y in arch_list_64)]
+
+        return sorted(matching_arch) + sorted(no_arch)
+
+    def filter_libraries(self, libs: T.List[BoostLibraryFile], lib_vers: str) -> T.List[BoostLibraryFile]:
+        # MSVC is very picky with the library tags
+        vscrt = ''
+        try:
+            crt_val = self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value
+            buildtype = self.env.coredata.options[mesonlib.OptionKey('buildtype')].value
+            vscrt = self.clib_compiler.get_crt_compile_args(crt_val, buildtype)[0]
+        except (KeyError, IndexError, AttributeError):
+            pass
+
+        # mlog.debug('    - static: {}'.format(self.static))
+        # mlog.debug('    - not explicit static: {}'.format(not self.explicit_static))
+        # mlog.debug('    - mt: {}'.format(self.multithreading))
+        # mlog.debug('    - version: {}'.format(lib_vers))
+        # mlog.debug('    - arch: {}'.format(self.arch))
+        # mlog.debug('    - vscrt: {}'.format(vscrt))
+        libs = [x for x in libs if x.static == self.static or not self.explicit_static]
+        libs = [x for x in libs if x.mt == self.multithreading]
+        libs = [x for x in libs if x.version_matches(lib_vers)]
+        libs = [x for x in libs if x.arch_matches(self.arch)]
+        libs = [x for x in libs if x.vscrt_matches(vscrt)]
+        libs = [x for x in libs if x.nvsuffix != 'dll']  # Only link to import libraries
+
+        # Only filter by debug when we are building in release mode. Debug
+        # libraries are automatically preferred through sorting otherwise.
+        if not self.debug:
+            libs = [x for x in libs if not x.debug]
+
+        # Take the abitag from the first library and filter by it. This
+        # ensures that we have a set of libraries that are always compatible.
+        if not libs:
+            return []
+        abitag = libs[0].abitag
+        libs = [x for x in libs if x.abitag == abitag]
+
+        return libs
+
+    def detect_libraries(self, libdir: Path) -> T.List[BoostLibraryFile]:
+        libs = set()  # type: T.Set[BoostLibraryFile]
+        for i in libdir.iterdir():
+            if not i.is_file():
+                continue
+            if not any(i.name.startswith(x) for x in ['libboost_', 'boost_']):
+                continue
+            # Windows binaries from SourceForge ship with PDB files alongside
+            # DLLs (#8325).  Ignore them.
+            if i.name.endswith('.pdb'):
+                continue
+
+            try:
+                libs.add(BoostLibraryFile(i.resolve()))
+            except UnknownFileException as e:
+                mlog.warning('Boost: ignoring unknown file {} under lib directory'.format(e.path.name))
+
+        return [x for x in libs if x.is_boost()]  # Filter out no boost libraries
+
+    def detect_split_root(self, inc_dir: Path, lib_dir: Path) -> None:
+        boost_inc_dir = None
+        for j in [inc_dir / 'version.hpp', inc_dir / 'boost' / 'version.hpp']:
+            if j.is_file():
+                boost_inc_dir = self._include_dir_from_version_header(j)
+                break
+        if not boost_inc_dir:
+            self.is_found = False
+            return
+
+        self.is_found = self.run_check([boost_inc_dir], [lib_dir])
+
+    def detect_roots(self) -> None:
+        roots = []  # type: T.List[Path]
+
+        # Try getting the BOOST_ROOT from a boost.pc if it exists. This primarily
+        # allows BoostDependency to find boost from Conan. See #5438
+        try:
+            boost_pc = PkgConfigDependency('boost', self.env, {'required': False})
+            if boost_pc.found():
+                boost_root = boost_pc.get_pkgconfig_variable('prefix', [], None)
+                if boost_root:
+                    roots += [Path(boost_root)]
+        except DependencyException:
+            pass
+
+        # Add roots from system paths
+        inc_paths = [Path(x) for x in self.clib_compiler.get_default_include_dirs()]
+        inc_paths = [x.parent for x in inc_paths if x.exists()]
+        inc_paths = [x.resolve() for x in inc_paths]
+        roots += inc_paths
+
+        # Add system paths
+        if self.env.machines[self.for_machine].is_windows():
+            # Where boost built from source actually installs it
+            c_root = Path('C:/Boost')
+            if c_root.is_dir():
+                roots += [c_root]
+
+            # Where boost documentation says it should be
+            prog_files = Path('C:/Program Files/boost')
+            # Where boost prebuilt binaries are
+            local_boost = Path('C:/local')
+
+            candidates = []  # type: T.List[Path]
+            if prog_files.is_dir():
+                candidates += [*prog_files.iterdir()]
+            if local_boost.is_dir():
+                candidates += [*local_boost.iterdir()]
+
+            roots += [x for x in candidates if x.name.lower().startswith('boost') and x.is_dir()]
+        else:
+            tmp = []  # type: T.List[Path]
+
+            # Add some default system paths
+            tmp += [Path('/opt/local')]
+            tmp += [Path('/usr/local/opt/boost')]
+            tmp += [Path('/usr/local')]
+            tmp += [Path('/usr')]
+
+            # Cleanup paths
+            tmp = [x for x in tmp if x.is_dir()]
+            tmp = [x.resolve() for x in tmp]
+            roots += tmp
+
+        self.check_and_set_roots(roots, use_system=True)
+
+    def log_details(self) -> str:
+        res = ''
+        if self.modules_found:
+            res += 'found: ' + ', '.join(self.modules_found)
+        if self.modules_missing:
+            if res:
+                res += ' | '
+            res += 'missing: ' + ', '.join(self.modules_missing)
+        return res
+
+    def log_info(self) -> str:
+        if self.boost_root:
+            return self.boost_root.as_posix()
+        return ''
+
+    def _include_dir_from_version_header(self, hfile: Path) -> BoostIncludeDir:
+        # Extract the version with a regex. Using clib_compiler.get_define would
+        # also work, however, this is slower (since it the compiler has to be
+        # invoked) and overkill since the layout of the header is always the same.
+        assert hfile.exists()
+        raw = hfile.read_text(encoding='utf-8')
+        m = re.search(r'#define\s+BOOST_VERSION\s+([0-9]+)', raw)
+        if not m:
+            mlog.debug(f'Failed to extract version information from {hfile}')
+            return BoostIncludeDir(hfile.parents[1], 0)
+        return BoostIncludeDir(hfile.parents[1], int(m.group(1)))
+
+    def _extra_compile_args(self) -> T.List[str]:
+        # BOOST_ALL_DYN_LINK should not be required with the known defines below
+        return ['-DBOOST_ALL_NO_LIB']  # Disable automatic linking
+
+packages['boost'] = BoostDependency
+
+# See https://www.boost.org/doc/libs/1_72_0/more/getting_started/unix-variants.html#library-naming
+# See https://mesonbuild.com/Reference-tables.html#cpu-families
+boost_arch_map = {
+    'aarch64': 'a64',
+    'arc': 'a32',
+    'arm': 'a32',
+    'ia64': 'i64',
+    'mips': 'm32',
+    'mips64': 'm64',
+    'ppc': 'p32',
+    'ppc64': 'p64',
+    'sparc': 's32',
+    'sparc64': 's64',
+    'x86': 'x32',
+    'x86_64': 'x64',
+}
+
+
+####      ---- BEGIN GENERATED ----      ####
+#                                           #
+# Generated with tools/boost_names.py:
+#  - boost version:   1.73.0
+#  - modules found:   159
+#  - libraries found: 43
+#
+
+class BoostLibrary():
+    def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]):
+        self.name = name
+        self.shared = shared
+        self.static = static
+        self.single = single
+        self.multi = multi
+
+class BoostModule():
+    def __init__(self, name: str, key: str, desc: str, libs: T.List[str]):
+        self.name = name
+        self.key = key
+        self.desc = desc
+        self.libs = libs
+
+
+# dict of all know libraries with additional compile options
+boost_libraries = {
+    'boost_atomic': BoostLibrary(
+        name='boost_atomic',
+        shared=['-DBOOST_ATOMIC_DYN_LINK=1'],
+        static=['-DBOOST_ATOMIC_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_chrono': BoostLibrary(
+        name='boost_chrono',
+        shared=['-DBOOST_CHRONO_DYN_LINK=1'],
+        static=['-DBOOST_CHRONO_STATIC_LINK=1'],
+        single=['-DBOOST_CHRONO_THREAD_DISABLED'],
+        multi=[],
+    ),
+    'boost_container': BoostLibrary(
+        name='boost_container',
+        shared=['-DBOOST_CONTAINER_DYN_LINK=1'],
+        static=['-DBOOST_CONTAINER_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_context': BoostLibrary(
+        name='boost_context',
+        shared=['-DBOOST_CONTEXT_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_contract': BoostLibrary(
+        name='boost_contract',
+        shared=['-DBOOST_CONTRACT_DYN_LINK'],
+        static=['-DBOOST_CONTRACT_STATIC_LINK'],
+        single=['-DBOOST_CONTRACT_DISABLE_THREADS'],
+        multi=[],
+    ),
+    'boost_coroutine': BoostLibrary(
+        name='boost_coroutine',
+        shared=['-DBOOST_COROUTINES_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_date_time': BoostLibrary(
+        name='boost_date_time',
+        shared=['-DBOOST_DATE_TIME_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_exception': BoostLibrary(
+        name='boost_exception',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_fiber': BoostLibrary(
+        name='boost_fiber',
+        shared=['-DBOOST_FIBERS_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_fiber_numa': BoostLibrary(
+        name='boost_fiber_numa',
+        shared=['-DBOOST_FIBERS_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_filesystem': BoostLibrary(
+        name='boost_filesystem',
+        shared=['-DBOOST_FILESYSTEM_DYN_LINK=1'],
+        static=['-DBOOST_FILESYSTEM_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_graph': BoostLibrary(
+        name='boost_graph',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_iostreams': BoostLibrary(
+        name='boost_iostreams',
+        shared=['-DBOOST_IOSTREAMS_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_locale': BoostLibrary(
+        name='boost_locale',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_log': BoostLibrary(
+        name='boost_log',
+        shared=['-DBOOST_LOG_DYN_LINK=1'],
+        static=[],
+        single=['-DBOOST_LOG_NO_THREADS'],
+        multi=[],
+    ),
+    'boost_log_setup': BoostLibrary(
+        name='boost_log_setup',
+        shared=['-DBOOST_LOG_SETUP_DYN_LINK=1'],
+        static=[],
+        single=['-DBOOST_LOG_NO_THREADS'],
+        multi=[],
+    ),
+    'boost_math_c99': BoostLibrary(
+        name='boost_math_c99',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_c99f': BoostLibrary(
+        name='boost_math_c99f',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_c99l': BoostLibrary(
+        name='boost_math_c99l',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_tr1': BoostLibrary(
+        name='boost_math_tr1',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_tr1f': BoostLibrary(
+        name='boost_math_tr1f',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_math_tr1l': BoostLibrary(
+        name='boost_math_tr1l',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_mpi': BoostLibrary(
+        name='boost_mpi',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_nowide': BoostLibrary(
+        name='boost_nowide',
+        shared=['-DBOOST_NOWIDE_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_prg_exec_monitor': BoostLibrary(
+        name='boost_prg_exec_monitor',
+        shared=['-DBOOST_TEST_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_program_options': BoostLibrary(
+        name='boost_program_options',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_random': BoostLibrary(
+        name='boost_random',
+        shared=['-DBOOST_RANDOM_DYN_LINK'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_regex': BoostLibrary(
+        name='boost_regex',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_serialization': BoostLibrary(
+        name='boost_serialization',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_addr2line': BoostLibrary(
+        name='boost_stacktrace_addr2line',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_backtrace': BoostLibrary(
+        name='boost_stacktrace_backtrace',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_basic': BoostLibrary(
+        name='boost_stacktrace_basic',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_noop': BoostLibrary(
+        name='boost_stacktrace_noop',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_windbg': BoostLibrary(
+        name='boost_stacktrace_windbg',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_stacktrace_windbg_cached': BoostLibrary(
+        name='boost_stacktrace_windbg_cached',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_system': BoostLibrary(
+        name='boost_system',
+        shared=['-DBOOST_SYSTEM_DYN_LINK=1'],
+        static=['-DBOOST_SYSTEM_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_test_exec_monitor': BoostLibrary(
+        name='boost_test_exec_monitor',
+        shared=['-DBOOST_TEST_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_thread': BoostLibrary(
+        name='boost_thread',
+        shared=['-DBOOST_THREAD_BUILD_DLL=1', '-DBOOST_THREAD_USE_DLL=1'],
+        static=['-DBOOST_THREAD_BUILD_LIB=1', '-DBOOST_THREAD_USE_LIB=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_timer': BoostLibrary(
+        name='boost_timer',
+        shared=['-DBOOST_TIMER_DYN_LINK=1'],
+        static=['-DBOOST_TIMER_STATIC_LINK=1'],
+        single=[],
+        multi=[],
+    ),
+    'boost_type_erasure': BoostLibrary(
+        name='boost_type_erasure',
+        shared=['-DBOOST_TYPE_ERASURE_DYN_LINK'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_unit_test_framework': BoostLibrary(
+        name='boost_unit_test_framework',
+        shared=['-DBOOST_TEST_DYN_LINK=1'],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_wave': BoostLibrary(
+        name='boost_wave',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+    'boost_wserialization': BoostLibrary(
+        name='boost_wserialization',
+        shared=[],
+        static=[],
+        single=[],
+        multi=[],
+    ),
+}
+
+#                                           #
+####       ---- END GENERATED ----       ####
diff --git a/devtools/meson/mesonbuild/dependencies/cmake.py b/devtools/meson/mesonbuild/dependencies/cmake.py
new file mode 100644
index 0000000..0c6e773
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/cmake.py
@@ -0,0 +1,670 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from .base import ExternalDependency, DependencyException, DependencyTypeName
+from ..mesonlib import is_windows, MesonException, PerMachine, stringlistify, extract_as_list
+from ..cmake import CMakeExecutor, CMakeTraceParser, CMakeException, CMakeToolchain, CMakeExecScope, check_cmake_args, resolve_cmake_trace_targets, cmake_is_debug
+from .. import mlog
+import importlib.resources
+from pathlib import Path
+import functools
+import re
+import os
+import shutil
+import textwrap
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..cmake import CMakeTarget
+    from ..environment import Environment
+    from ..envconfig import MachineInfo
+
+class CMakeInfo(T.NamedTuple):
+    module_paths: T.List[str]
+    cmake_root: str
+    archs: T.List[str]
+    common_paths: T.List[str]
+
+class CMakeDependency(ExternalDependency):
+    # The class's copy of the CMake path. Avoids having to search for it
+    # multiple times in the same Meson invocation.
+    class_cmakeinfo: PerMachine[T.Optional[CMakeInfo]] = PerMachine(None, None)
+    # Version string for the minimum CMake version
+    class_cmake_version = '>=3.4'
+    # CMake generators to try (empty for no generator)
+    class_cmake_generators = ['', 'Ninja', 'Unix Makefiles', 'Visual Studio 10 2010']
+    class_working_generator: T.Optional[str] = None
+
+    def _gen_exception(self, msg: str) -> DependencyException:
+        return DependencyException(f'Dependency {self.name} not found: {msg}')
+
+    def _main_cmake_file(self) -> str:
+        return 'CMakeLists.txt'
+
+    def _extra_cmake_opts(self) -> T.List[str]:
+        return []
+
+    def _map_module_list(self, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
+        # Map the input module list to something else
+        # This function will only be executed AFTER the initial CMake
+        # interpreter pass has completed. Thus variables defined in the
+        # CMakeLists.txt can be accessed here.
+        #
+        # Both the modules and components inputs contain the original lists.
+        return modules
+
+    def _map_component_list(self, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
+        # Map the input components list to something else. This
+        # function will be executed BEFORE the initial CMake interpreter
+        # pass. Thus variables from the CMakeLists.txt can NOT be accessed.
+        #
+        # Both the modules and components inputs contain the original lists.
+        return components
+
+    def _original_module_name(self, module: str) -> str:
+        # Reverse the module mapping done by _map_module_list for
+        # one module
+        return module
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> None:
+        # Gather a list of all languages to support
+        self.language_list = []  # type: T.List[str]
+        if language is None or force_use_global_compilers:
+            compilers = None
+            if kwargs.get('native', False):
+                compilers = environment.coredata.compilers.build
+            else:
+                compilers = environment.coredata.compilers.host
+
+            candidates = ['c', 'cpp', 'fortran', 'objc', 'objcxx']
+            self.language_list += [x for x in candidates if x in compilers]
+        else:
+            self.language_list += [language]
+
+        # Add additional languages if required
+        if 'fortran' in self.language_list:
+            self.language_list += ['c']
+
+        # Ensure that the list is unique
+        self.language_list = list(set(self.language_list))
+
+        super().__init__(DependencyTypeName('cmake'), environment, kwargs, language=language)
+        self.name = name
+        self.is_libtool = False
+        # Store a copy of the CMake path on the object itself so it is
+        # stored in the pickled coredata and recovered.
+        self.cmakebin:  T.Optional[CMakeExecutor] = None
+        self.cmakeinfo: T.Optional[CMakeInfo] = None
+
+        # Where all CMake "build dirs" are located
+        self.cmake_root_dir = environment.scratch_dir
+
+        # T.List of successfully found modules
+        self.found_modules: T.List[str] = []
+
+        # Initialize with None before the first return to avoid
+        # AttributeError exceptions in derived classes
+        self.traceparser: T.Optional[CMakeTraceParser] = None
+
+        # TODO further evaluate always using MachineChoice.BUILD
+        self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent)
+        if not self.cmakebin.found():
+            self.cmakebin = None
+            msg = f'CMake binary for machine {self.for_machine} not found. Giving up.'
+            if self.required:
+                raise DependencyException(msg)
+            mlog.debug(msg)
+            return
+
+        # Setup the trace parser
+        self.traceparser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir(), self.env)
+
+        cm_args = stringlistify(extract_as_list(kwargs, 'cmake_args'))
+        cm_args = check_cmake_args(cm_args)
+        if CMakeDependency.class_cmakeinfo[self.for_machine] is None:
+            CMakeDependency.class_cmakeinfo[self.for_machine] = self._get_cmake_info(cm_args)
+        self.cmakeinfo = CMakeDependency.class_cmakeinfo[self.for_machine]
+        if self.cmakeinfo is None:
+            raise self._gen_exception('Unable to obtain CMake system information')
+
+        package_version = kwargs.get('cmake_package_version', '')
+        if not isinstance(package_version, str):
+            raise DependencyException('Keyword "cmake_package_version" must be a string.')
+        components = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'components'))]
+        modules = [(x, True) for x in stringlistify(extract_as_list(kwargs, 'modules'))]
+        modules += [(x, False) for x in stringlistify(extract_as_list(kwargs, 'optional_modules'))]
+        cm_path = stringlistify(extract_as_list(kwargs, 'cmake_module_path'))
+        cm_path = [x if os.path.isabs(x) else os.path.join(environment.get_source_dir(), x) for x in cm_path]
+        if cm_path:
+            cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path))
+        if not self._preliminary_find_check(name, cm_path, self.cmakebin.get_cmake_prefix_paths(), environment.machines[self.for_machine]):
+            mlog.debug('Preliminary CMake check failed. Aborting.')
+            return
+        self._detect_dep(name, package_version, modules, components, cm_args)
+
+    def __repr__(self) -> str:
+        return f'<{self.__class__.__name__} {self.name}: {self.is_found} {self.version_reqs}>'
+
+    def _get_cmake_info(self, cm_args: T.List[str]) -> T.Optional[CMakeInfo]:
+        mlog.debug("Extracting basic cmake information")
+
+        # Try different CMake generators since specifying no generator may fail
+        # in cygwin for some reason
+        gen_list = []
+        # First try the last working generator
+        if CMakeDependency.class_working_generator is not None:
+            gen_list += [CMakeDependency.class_working_generator]
+        gen_list += CMakeDependency.class_cmake_generators
+
+        temp_parser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir(), self.env)
+        toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
+        toolchain.write()
+
+        for i in gen_list:
+            mlog.debug('Try CMake generator: {}'.format(i if len(i) > 0 else 'auto'))
+
+            # Prepare options
+            cmake_opts = temp_parser.trace_args() + toolchain.get_cmake_args() + ['.']
+            cmake_opts += cm_args
+            if len(i) > 0:
+                cmake_opts = ['-G', i] + cmake_opts
+
+            # Run CMake
+            ret1, out1, err1 = self._call_cmake(cmake_opts, 'CMakePathInfo.txt')
+
+            # Current generator was successful
+            if ret1 == 0:
+                CMakeDependency.class_working_generator = i
+                break
+
+            mlog.debug(f'CMake failed to gather system information for generator {i} with error code {ret1}')
+            mlog.debug(f'OUT:\n{out1}\n\n\nERR:\n{err1}\n\n')
+
+        # Check if any generator succeeded
+        if ret1 != 0:
+            return None
+
+        try:
+            temp_parser.parse(err1)
+        except MesonException:
+            return None
+
+        def process_paths(l: T.List[str]) -> T.Set[str]:
+            if is_windows():
+                # Cannot split on ':' on Windows because its in the drive letter
+                tmp = [x.split(os.pathsep) for x in l]
+            else:
+                # https://github.com/mesonbuild/meson/issues/7294
+                tmp = [re.split(r':|;', x) for x in l]
+            flattened = [x for sublist in tmp for x in sublist]
+            return set(flattened)
+
+        # Extract the variables and sanity check them
+        root_paths_set = process_paths(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH'))
+        root_paths_set.update(process_paths(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT')))
+        root_paths = sorted(root_paths_set)
+        root_paths = [x for x in root_paths if os.path.isdir(x)]
+        module_paths_set = process_paths(temp_parser.get_cmake_var('MESON_PATHS_LIST'))
+        rooted_paths: T.List[str] = []
+        for j in [Path(x) for x in root_paths]:
+            for p in [Path(x) for x in module_paths_set]:
+                rooted_paths.append(str(j / p.relative_to(p.anchor)))
+        module_paths = sorted(module_paths_set.union(rooted_paths))
+        module_paths = [x for x in module_paths if os.path.isdir(x)]
+        archs = temp_parser.get_cmake_var('MESON_ARCH_LIST')
+
+        common_paths = ['lib', 'lib32', 'lib64', 'libx32', 'share']
+        for i in archs:
+            common_paths += [os.path.join('lib', i)]
+
+        res = CMakeInfo(
+            module_paths=module_paths,
+            cmake_root=temp_parser.get_cmake_var('MESON_CMAKE_ROOT')[0],
+            archs=archs,
+            common_paths=common_paths,
+        )
+
+        mlog.debug(f'  -- Module search paths:    {res.module_paths}')
+        mlog.debug(f'  -- CMake root:             {res.cmake_root}')
+        mlog.debug(f'  -- CMake architectures:    {res.archs}')
+        mlog.debug(f'  -- CMake lib search paths: {res.common_paths}')
+
+        return res
+
+    @staticmethod
+    @functools.lru_cache(maxsize=None)
+    def _cached_listdir(path: str) -> T.Tuple[T.Tuple[str, str], ...]:
+        try:
+            return tuple((x, str(x).lower()) for x in os.listdir(path))
+        except OSError:
+            return tuple()
+
+    @staticmethod
+    @functools.lru_cache(maxsize=None)
+    def _cached_isdir(path: str) -> bool:
+        try:
+            return os.path.isdir(path)
+        except OSError:
+            return False
+
+    def _preliminary_find_check(self, name: str, module_path: T.List[str], prefix_path: T.List[str], machine: 'MachineInfo') -> bool:
+        lname = str(name).lower()
+
+        # Checks , /cmake, /CMake
+        def find_module(path: str) -> bool:
+            for i in [path, os.path.join(path, 'cmake'), os.path.join(path, 'CMake')]:
+                if not self._cached_isdir(i):
+                    continue
+
+                # Check the directory case insensitive
+                content = self._cached_listdir(i)
+                candidates = ['Find{}.cmake', '{}Config.cmake', '{}-config.cmake']
+                candidates = [x.format(name).lower() for x in candidates]
+                if any(x[1] in candidates for x in content):
+                    return True
+            return False
+
+        # Search in /(lib/|lib*|share) for cmake files
+        def search_lib_dirs(path: str) -> bool:
+            for i in [os.path.join(path, x) for x in self.cmakeinfo.common_paths]:
+                if not self._cached_isdir(i):
+                    continue
+
+                # Check /(lib/|lib*|share)/cmake/*/
+                cm_dir = os.path.join(i, 'cmake')
+                if self._cached_isdir(cm_dir):
+                    content = self._cached_listdir(cm_dir)
+                    content = tuple(x for x in content if x[1].startswith(lname))
+                    for k in content:
+                        if find_module(os.path.join(cm_dir, k[0])):
+                            return True
+
+                # /(lib/|lib*|share)/*/
+                # /(lib/|lib*|share)/*/(cmake|CMake)/
+                content = self._cached_listdir(i)
+                content = tuple(x for x in content if x[1].startswith(lname))
+                for k in content:
+                    if find_module(os.path.join(i, k[0])):
+                        return True
+
+            return False
+
+        # Check the user provided and system module paths
+        for i in module_path + [os.path.join(self.cmakeinfo.cmake_root, 'Modules')]:
+            if find_module(i):
+                return True
+
+        # Check the user provided prefix paths
+        for i in prefix_path:
+            if search_lib_dirs(i):
+                return True
+
+        # Check PATH
+        system_env = []  # type: T.List[str]
+        for i in os.environ.get('PATH', '').split(os.pathsep):
+            if i.endswith('/bin') or i.endswith('\\bin'):
+                i = i[:-4]
+            if i.endswith('/sbin') or i.endswith('\\sbin'):
+                i = i[:-5]
+            system_env += [i]
+
+        # Check the system paths
+        for i in self.cmakeinfo.module_paths + system_env:
+            if find_module(i):
+                return True
+
+            if search_lib_dirs(i):
+                return True
+
+            content = self._cached_listdir(i)
+            content = tuple(x for x in content if x[1].startswith(lname))
+            for k in content:
+                if search_lib_dirs(os.path.join(i, k[0])):
+                    return True
+
+            # Mac framework support
+            if machine.is_darwin():
+                for j in [f'{lname}.framework', f'{lname}.app']:
+                    for k in content:
+                        if k[1] != j:
+                            continue
+                        if find_module(os.path.join(i, k[0], 'Resources')) or find_module(os.path.join(i, k[0], 'Version')):
+                            return True
+
+        # Check the environment path
+        env_path = os.environ.get(f'{name}_DIR')
+        if env_path and find_module(env_path):
+            return True
+
+        # Check the Linux CMake registry
+        linux_reg = Path.home() / '.cmake' / 'packages'
+        for p in [linux_reg / name, linux_reg / lname]:
+            if p.exists():
+                return True
+
+        return False
+
+    def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]) -> None:
+        # Detect a dependency with CMake using the '--find-package' mode
+        # and the trace output (stderr)
+        #
+        # When the trace output is enabled CMake prints all functions with
+        # parameters to stderr as they are executed. Since CMake 3.4.0
+        # variables ("${VAR}") are also replaced in the trace output.
+        mlog.debug('\nDetermining dependency {!r} with CMake executable '
+                   '{!r}'.format(name, self.cmakebin.executable_path()))
+
+        # Try different CMake generators since specifying no generator may fail
+        # in cygwin for some reason
+        gen_list = []
+        # First try the last working generator
+        if CMakeDependency.class_working_generator is not None:
+            gen_list += [CMakeDependency.class_working_generator]
+        gen_list += CMakeDependency.class_cmake_generators
+
+        # Map the components
+        comp_mapped = self._map_component_list(modules, components)
+        toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
+        toolchain.write()
+
+        for i in gen_list:
+            mlog.debug('Try CMake generator: {}'.format(i if len(i) > 0 else 'auto'))
+
+            # Prepare options
+            cmake_opts = []
+            cmake_opts += [f'-DNAME={name}']
+            cmake_opts += ['-DARCHS={}'.format(';'.join(self.cmakeinfo.archs))]
+            cmake_opts += [f'-DVERSION={package_version}']
+            cmake_opts += ['-DCOMPS={}'.format(';'.join([x[0] for x in comp_mapped]))]
+            cmake_opts += [f'-DSTATIC={self.static}']
+            cmake_opts += args
+            cmake_opts += self.traceparser.trace_args()
+            cmake_opts += toolchain.get_cmake_args()
+            cmake_opts += self._extra_cmake_opts()
+            cmake_opts += ['.']
+            if len(i) > 0:
+                cmake_opts = ['-G', i] + cmake_opts
+
+            # Run CMake
+            ret1, out1, err1 = self._call_cmake(cmake_opts, self._main_cmake_file())
+
+            # Current generator was successful
+            if ret1 == 0:
+                CMakeDependency.class_working_generator = i
+                break
+
+            mlog.debug(f'CMake failed for generator {i} and package {name} with error code {ret1}')
+            mlog.debug(f'OUT:\n{out1}\n\n\nERR:\n{err1}\n\n')
+
+        # Check if any generator succeeded
+        if ret1 != 0:
+            return
+
+        try:
+            self.traceparser.parse(err1)
+        except CMakeException as e:
+            e2 = self._gen_exception(str(e))
+            if self.required:
+                raise
+            else:
+                self.compile_args = []
+                self.link_args = []
+                self.is_found = False
+                self.reason = e2
+                return
+
+        # Whether the package is found or not is always stored in PACKAGE_FOUND
+        self.is_found = self.traceparser.var_to_bool('PACKAGE_FOUND')
+        if not self.is_found:
+            return
+
+        # Try to detect the version
+        vers_raw = self.traceparser.get_cmake_var('PACKAGE_VERSION')
+
+        if len(vers_raw) > 0:
+            self.version = vers_raw[0]
+            self.version.strip('"\' ')
+
+        # Post-process module list. Used in derived classes to modify the
+        # module list (append prepend a string, etc.).
+        modules = self._map_module_list(modules, components)
+        autodetected_module_list = False
+
+        # Try guessing a CMake target if none is provided
+        if len(modules) == 0:
+            for i in self.traceparser.targets:
+                tg = i.lower()
+                lname = name.lower()
+                if f'{lname}::{lname}' == tg or lname == tg.replace('::', ''):
+                    mlog.debug(f'Guessed CMake target \'{i}\'')
+                    modules = [(i, True)]
+                    autodetected_module_list = True
+                    break
+
+        # Failed to guess a target --> try the old-style method
+        if len(modules) == 0:
+            # Warn when there might be matching imported targets but no automatic match was used
+            partial_modules: T.List[CMakeTarget] = []
+            for k, v in self.traceparser.targets.items():
+                tg = k.lower()
+                lname = name.lower()
+                if tg.startswith(f'{lname}::'):
+                    partial_modules += [v]
+            if partial_modules:
+                mlog.warning(textwrap.dedent(f'''\
+                    Could not find and exact match for the CMake dependency {name}.
+
+                    However, Meson found the following partial matches:
+
+                        {[x.name for x in partial_modules]}
+
+                    Using imported is recommended, since this approach is less error prone
+                    and better supported by Meson. Consider explicitly specifying one of
+                    these in the dependency call with:
+
+                        dependency('{name}', modules: ['{name}::', ...])
+
+                    Meson will now continue to use the old-style {name}_LIBRARIES CMake
+                    variables to extract the dependency information since no explicit
+                    target is currently specified.
+
+                '''))
+                mlog.debug('More info for the partial match targets:')
+                for tgt in partial_modules:
+                    mlog.debug(tgt)
+
+            incDirs = [x for x in self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS') if x]
+            defs = [x for x in self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS') if x]
+            libs_raw = [x for x in self.traceparser.get_cmake_var('PACKAGE_LIBRARIES') if x]
+
+            # CMake has a "fun" API, where certain keywords describing
+            # configurations can be in the *_LIBRARIES variables. See:
+            # - https://github.com/mesonbuild/meson/issues/9197
+            # - https://gitlab.freedesktop.org/libnice/libnice/-/issues/140
+            # - https://cmake.org/cmake/help/latest/command/target_link_libraries.html#overview  (the last point in the section)
+            libs: T.List[str] = []
+            cfg_matches = True
+            is_debug = cmake_is_debug(self.env)
+            cm_tag_map = {'debug': is_debug, 'optimized': not is_debug, 'general': True}
+            for i in libs_raw:
+                if i.lower() in cm_tag_map:
+                    cfg_matches = cm_tag_map[i.lower()]
+                    continue
+                if cfg_matches:
+                    libs += [i]
+                # According to the CMake docs, a keyword only works for the
+                # directly the following item and all items without a keyword
+                # are implicitly `general`
+                cfg_matches = True
+
+            # Try to use old style variables if no module is specified
+            if len(libs) > 0:
+                self.compile_args = [f'-I{x}' for x in incDirs] + defs
+                self.link_args = []
+                for j in libs:
+                    rtgt = resolve_cmake_trace_targets(j, self.traceparser, self.env, clib_compiler=self.clib_compiler)
+                    self.link_args += rtgt.libraries
+                    self.compile_args += [f'-I{x}' for x in rtgt.include_directories]
+                    self.compile_args += rtgt.public_compile_opts
+                mlog.debug(f'using old-style CMake variables for dependency {name}')
+                mlog.debug(f'Include Dirs:         {incDirs}')
+                mlog.debug(f'Compiler Definitions: {defs}')
+                mlog.debug(f'Libraries:            {libs}')
+                return
+
+            # Even the old-style approach failed. Nothing else we can do here
+            self.is_found = False
+            raise self._gen_exception('CMake: failed to guess a CMake target for {}.\n'
+                                      'Try to explicitly specify one or more targets with the "modules" property.\n'
+                                      'Valid targets are:\n{}'.format(name, list(self.traceparser.targets.keys())))
+
+        # Set dependencies with CMake targets
+        # recognise arguments we should pass directly to the linker
+        incDirs = []
+        compileOptions = []
+        libraries = []
+
+        for i, required in modules:
+            if i not in self.traceparser.targets:
+                if not required:
+                    mlog.warning('CMake: T.Optional module', mlog.bold(self._original_module_name(i)), 'for', mlog.bold(name), 'was not found')
+                    continue
+                raise self._gen_exception('CMake: invalid module {} for {}.\n'
+                                          'Try to explicitly specify one or more targets with the "modules" property.\n'
+                                          'Valid targets are:\n{}'.format(self._original_module_name(i), name, list(self.traceparser.targets.keys())))
+
+            if not autodetected_module_list:
+                self.found_modules += [i]
+
+            rtgt = resolve_cmake_trace_targets(i, self.traceparser, self.env,
+                                               clib_compiler=self.clib_compiler,
+                                               not_found_warning=lambda x:
+                                                   mlog.warning('CMake: Dependency', mlog.bold(x), 'for', mlog.bold(name), 'was not found')
+                                               )
+            incDirs += rtgt.include_directories
+            compileOptions += rtgt.public_compile_opts
+            libraries += rtgt.libraries + rtgt.link_flags
+
+        # Make sure all elements in the lists are unique and sorted
+        incDirs = sorted(set(incDirs))
+        compileOptions = sorted(set(compileOptions))
+        libraries = sorted(set(libraries))
+
+        mlog.debug(f'Include Dirs:         {incDirs}')
+        mlog.debug(f'Compiler Options:     {compileOptions}')
+        mlog.debug(f'Libraries:            {libraries}')
+
+        self.compile_args = compileOptions + [f'-I{x}' for x in incDirs]
+        self.link_args = libraries
+
+    def _get_build_dir(self) -> Path:
+        build_dir = Path(self.cmake_root_dir) / f'cmake_{self.name}'
+        build_dir.mkdir(parents=True, exist_ok=True)
+        return build_dir
+
+    def _setup_cmake_dir(self, cmake_file: str) -> Path:
+        # Setup the CMake build environment and return the "build" directory
+        build_dir = self._get_build_dir()
+
+        # Remove old CMake cache so we can try out multiple generators
+        cmake_cache = build_dir / 'CMakeCache.txt'
+        cmake_files = build_dir / 'CMakeFiles'
+        if cmake_cache.exists():
+            cmake_cache.unlink()
+        shutil.rmtree(cmake_files.as_posix(), ignore_errors=True)
+
+        # Insert language parameters into the CMakeLists.txt and write new CMakeLists.txt
+        cmake_txt = importlib.resources.read_text('mesonbuild.dependencies.data', cmake_file, encoding = 'utf-8')
+
+        # In general, some Fortran CMake find_package() also require C language enabled,
+        # even if nothing from C is directly used. An easy Fortran example that fails
+        # without C language is
+        #   find_package(Threads)
+        # To make this general to
+        # any other language that might need this, we use a list for all
+        # languages and expand in the cmake Project(... LANGUAGES ...) statement.
+        from ..cmake import language_map
+        cmake_language = [language_map[x] for x in self.language_list if x in language_map]
+        if not cmake_language:
+            cmake_language += ['NONE']
+
+        cmake_txt = textwrap.dedent("""
+            cmake_minimum_required(VERSION ${{CMAKE_VERSION}})
+            project(MesonTemp LANGUAGES {})
+        """).format(' '.join(cmake_language)) + cmake_txt
+
+        cm_file = build_dir / 'CMakeLists.txt'
+        cm_file.write_text(cmake_txt, encoding='utf-8')
+        mlog.cmd_ci_include(cm_file.absolute().as_posix())
+
+        return build_dir
+
+    def _call_cmake(self,
+                    args: T.List[str],
+                    cmake_file: str,
+                    env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, T.Optional[str], T.Optional[str]]:
+        build_dir = self._setup_cmake_dir(cmake_file)
+        return self.cmakebin.call(args, build_dir, env=env)
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'cmake'
+
+    def log_details(self) -> str:
+        modules = [self._original_module_name(x) for x in self.found_modules]
+        modules = sorted(set(modules))
+        if modules:
+            return 'modules: ' + ', '.join(modules)
+        return ''
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> str:
+        if cmake and self.traceparser is not None:
+            try:
+                v = self.traceparser.vars[cmake]
+            except KeyError:
+                pass
+            else:
+                # CMake does NOT have a list datatype. We have no idea whether
+                # anything is a string or a string-separated-by-; Internally,
+                # we treat them as the latter and represent everything as a
+                # list, because it is convenient when we are mostly handling
+                # imported targets, which have various properties that are
+                # actually lists.
+                #
+                # As a result we need to convert them back to strings when grabbing
+                # raw variables the user requested.
+                return ';'.join(v)
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'Could not get cmake variable and no default provided for {self!r}')
+
+
+class CMakeDependencyFactory:
+
+    def __init__(self, name: T.Optional[str] = None, modules: T.Optional[T.List[str]] = None):
+        self.name = name
+        self.modules = modules
+
+    def __call__(self, name: str, env: Environment, kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> CMakeDependency:
+        if self.modules:
+            kwargs['modules'] = self.modules
+        return CMakeDependency(self.name or name, env, kwargs, language, force_use_global_compilers)
+
+    @staticmethod
+    def log_tried() -> str:
+        return CMakeDependency.log_tried()
diff --git a/devtools/meson/mesonbuild/dependencies/coarrays.py b/devtools/meson/mesonbuild/dependencies/coarrays.py
new file mode 100644
index 0000000..5cb8556
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/coarrays.py
@@ -0,0 +1,89 @@
+# Copyright 2013-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import functools
+import typing as T
+
+from .base import DependencyMethods, detect_compiler, SystemDependency
+from .cmake import CMakeDependency
+from .detect import packages
+from .pkgconfig import PkgConfigDependency
+from .factory import factory_methods
+
+if T.TYPE_CHECKING:
+    from . factory import DependencyGenerator
+    from ..environment import Environment, MachineChoice
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM})
+def coarray_factory(env: 'Environment',
+                    for_machine: 'MachineChoice',
+                    kwargs: T.Dict[str, T.Any],
+                    methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    fcid = detect_compiler('coarray', env, for_machine, 'fortran').get_id()
+    candidates: T.List['DependencyGenerator'] = []
+
+    if fcid == 'gcc':
+        # OpenCoarrays is the most commonly used method for Fortran Coarray with GCC
+        if DependencyMethods.PKGCONFIG in methods:
+            for pkg in ['caf-openmpi', 'caf']:
+                candidates.append(functools.partial(
+                    PkgConfigDependency, pkg, env, kwargs, language='fortran'))
+
+        if DependencyMethods.CMAKE in methods:
+            if 'modules' not in kwargs:
+                kwargs['modules'] = 'OpenCoarrays::caf_mpi'
+            candidates.append(functools.partial(
+                CMakeDependency, 'OpenCoarrays', env, kwargs, language='fortran'))
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(CoarrayDependency, env, kwargs))
+
+    return candidates
+packages['coarray'] = coarray_factory
+
+
+class CoarrayDependency(SystemDependency):
+    """
+    Coarrays are a Fortran 2008 feature.
+
+    Coarrays are sometimes implemented via external library (GCC+OpenCoarrays),
+    while other compilers just build in support (Cray, IBM, Intel, NAG).
+    Coarrays may be thought of as a high-level language abstraction of
+    low-level MPI calls.
+    """
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('coarray', environment, kwargs, language='fortran')
+        kwargs['required'] = False
+        kwargs['silent'] = True
+
+        cid = self.get_compiler().get_id()
+        if cid == 'gcc':
+            # Fallback to single image
+            self.compile_args = ['-fcoarray=single']
+            self.version = 'single image (fallback)'
+            self.is_found = True
+        elif cid == 'intel':
+            # Coarrays are built into Intel compilers, no external library needed
+            self.is_found = True
+            self.link_args = ['-coarray=shared']
+            self.compile_args = self.link_args
+        elif cid == 'intel-cl':
+            # Coarrays are built into Intel compilers, no external library needed
+            self.is_found = True
+            self.compile_args = ['/Qcoarray:shared']
+        elif cid == 'nagfor':
+            # NAG doesn't require any special arguments for Coarray
+            self.is_found = True
diff --git a/devtools/meson/mesonbuild/dependencies/configtool.py b/devtools/meson/mesonbuild/dependencies/configtool.py
new file mode 100644
index 0000000..5a4294e
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/configtool.py
@@ -0,0 +1,187 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from .base import ExternalDependency, DependencyException, DependencyTypeName
+from ..mesonlib import listify, Popen_safe, Popen_safe_logged, split_args, version_compare, version_compare_many
+from ..programs import find_external_program
+from .. import mlog
+import re
+import typing as T
+
+from mesonbuild import mesonlib
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class ConfigToolDependency(ExternalDependency):
+
+    """Class representing dependencies found using a config tool.
+
+    Takes the following extra keys in kwargs that it uses internally:
+    :tools List[str]: A list of tool names to use
+    :version_arg str: The argument to pass to the tool to get it's version
+    :skip_version str: The argument to pass to the tool to ignore its version
+        (if ``version_arg`` fails, but it may start accepting it in the future)
+        Because some tools are stupid and don't accept --version
+    :returncode_value int: The value of the correct returncode
+        Because some tools are stupid and don't return 0
+    """
+
+    tools: T.Optional[T.List[str]] = None
+    tool_name: T.Optional[str] = None
+    version_arg = '--version'
+    skip_version: T.Optional[str] = None
+    allow_default_for_cross = False
+    __strip_version = re.compile(r'^[0-9][0-9.]+')
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
+        super().__init__(DependencyTypeName('config-tool'), environment, kwargs, language=language)
+        self.name = name
+        # You may want to overwrite the class version in some cases
+        self.tools = listify(kwargs.get('tools', self.tools))
+        if not self.tool_name:
+            self.tool_name = self.tools[0]
+        if 'version_arg' in kwargs:
+            self.version_arg = kwargs['version_arg']
+
+        req_version_raw = kwargs.get('version', None)
+        if req_version_raw is not None:
+            req_version = mesonlib.stringlistify(req_version_raw)
+        else:
+            req_version = []
+        tool, version = self.find_config(req_version, kwargs.get('returncode_value', 0))
+        self.config = tool
+        self.is_found = self.report_config(version, req_version)
+        if not self.is_found:
+            self.config = None
+            return
+        self.version = version
+
+    def _sanitize_version(self, version: str) -> str:
+        """Remove any non-numeric, non-point version suffixes."""
+        m = self.__strip_version.match(version)
+        if m:
+            # Ensure that there isn't a trailing '.', such as an input like
+            # `1.2.3.git-1234`
+            return m.group(0).rstrip('.')
+        return version
+
+    def find_config(self, versions: T.List[str], returncode: int = 0) \
+            -> T.Tuple[T.Optional[T.List[str]], T.Optional[str]]:
+        """Helper method that searches for config tool binaries in PATH and
+        returns the one that best matches the given version requirements.
+        """
+        best_match: T.Tuple[T.Optional[T.List[str]], T.Optional[str]] = (None, None)
+        for potential_bin in find_external_program(
+                self.env, self.for_machine, self.tool_name,
+                self.tool_name, self.tools, allow_default_for_cross=self.allow_default_for_cross):
+            if not potential_bin.found():
+                continue
+            tool = potential_bin.get_command()
+            try:
+                p, out = Popen_safe(tool + [self.version_arg])[:2]
+            except (FileNotFoundError, PermissionError):
+                continue
+            if p.returncode != returncode:
+                if self.skip_version:
+                    # maybe the executable is valid even if it doesn't support --version
+                    p = Popen_safe(tool + [self.skip_version])[0]
+                    if p.returncode != returncode:
+                        continue
+                else:
+                    continue
+
+            out = self._sanitize_version(out.strip())
+            # Some tools, like pcap-config don't supply a version, but also
+            # don't fail with --version, in that case just assume that there is
+            # only one version and return it.
+            if not out:
+                return (tool, None)
+            if versions:
+                is_found = version_compare_many(out, versions)[0]
+                # This allows returning a found version without a config tool,
+                # which is useful to inform the user that you found version x,
+                # but y was required.
+                if not is_found:
+                    tool = None
+            if best_match[1]:
+                if version_compare(out, '> {}'.format(best_match[1])):
+                    best_match = (tool, out)
+            else:
+                best_match = (tool, out)
+
+        return best_match
+
+    def report_config(self, version: T.Optional[str], req_version: T.List[str]) -> bool:
+        """Helper method to print messages about the tool."""
+
+        found_msg: T.List[T.Union[str, mlog.AnsiDecorator]] = [mlog.bold(self.tool_name), 'found:']
+
+        if self.config is None:
+            found_msg.append(mlog.red('NO'))
+            if version is not None and req_version:
+                found_msg.append(f'found {version!r} but need {req_version!r}')
+            elif req_version:
+                found_msg.append(f'need {req_version!r}')
+        else:
+            found_msg += [mlog.green('YES'), '({})'.format(' '.join(self.config)), version]
+
+        mlog.log(*found_msg)
+
+        return self.config is not None
+
+    def get_config_value(self, args: T.List[str], stage: str) -> T.List[str]:
+        p, out, err = Popen_safe_logged(self.config + args)
+        if p.returncode != 0:
+            if self.required:
+                raise DependencyException(f'Could not generate {stage} for {self.name}.\n{err}')
+            return []
+        return split_args(out)
+
+    def get_configtool_variable(self, variable_name: str) -> str:
+        p, out, _ = Popen_safe(self.config + [f'--{variable_name}'])
+        if p.returncode != 0:
+            if self.required:
+                raise DependencyException(
+                    'Could not get variable "{}" for dependency {}'.format(
+                        variable_name, self.name))
+        variable = out.strip()
+        mlog.debug(f'Got config-tool variable {variable_name} : {variable}')
+        return variable
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'config-tool'
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> str:
+        if configtool:
+            # In the not required case '' (empty string) will be returned if the
+            # variable is not found. Since '' is a valid value to return we
+            # set required to True here to force and error, and use the
+            # finally clause to ensure it's restored.
+            restore = self.required
+            self.required = True
+            try:
+                return self.get_configtool_variable(configtool)
+            except DependencyException:
+                pass
+            finally:
+                self.required = restore
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'Could not get config-tool variable and no default provided for {self!r}')
diff --git a/devtools/meson/mesonbuild/dependencies/cuda.py b/devtools/meson/mesonbuild/dependencies/cuda.py
new file mode 100644
index 0000000..f1c890b
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/cuda.py
@@ -0,0 +1,305 @@
+# Copyright 2013-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import glob
+import re
+import os
+import typing as T
+from pathlib import Path
+
+from .. import mesonlib
+from .. import mlog
+from ..environment import detect_cpu_family
+from .base import DependencyException, SystemDependency
+from .detect import packages
+
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from ..compilers import Compiler
+
+    TV_ResultTuple = T.Tuple[T.Optional[str], T.Optional[str], bool]
+
+class CudaDependency(SystemDependency):
+
+    supported_languages = ['cuda', 'cpp', 'c'] # see also _default_language
+
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        compilers = environment.coredata.compilers[self.get_for_machine_from_kwargs(kwargs)]
+        language = self._detect_language(compilers)
+        if language not in self.supported_languages:
+            raise DependencyException(f'Language \'{language}\' is not supported by the CUDA Toolkit. Supported languages are {self.supported_languages}.')
+
+        super().__init__('cuda', environment, kwargs, language=language)
+        self.lib_modules: T.Dict[str, T.List[str]] = {}
+        self.requested_modules = self.get_requested(kwargs)
+        if not any(runtime in self.requested_modules for runtime in ['cudart', 'cudart_static']):
+            # By default, we prefer to link the static CUDA runtime, since this is what nvcc also does by default:
+            # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#cudart-none-shared-static-cudart
+            req_modules = ['cudart']
+            if kwargs.get('static', True):
+                req_modules = ['cudart_static']
+                machine = self.env.machines[self.for_machine]
+                if machine.is_linux():
+                    # extracted by running
+                    #   nvcc -v foo.o
+                    req_modules += ['rt', 'pthread', 'dl']
+            self.requested_modules = req_modules + self.requested_modules
+
+        (self.cuda_path, self.version, self.is_found) = self._detect_cuda_path_and_version()
+        if not self.is_found:
+            return
+
+        if not os.path.isabs(self.cuda_path):
+            raise DependencyException(f'CUDA Toolkit path must be absolute, got \'{self.cuda_path}\'.')
+
+        # nvcc already knows where to find the CUDA Toolkit, but if we're compiling
+        # a mixed C/C++/CUDA project, we still need to make the include dir searchable
+        if self.language != 'cuda' or len(compilers) > 1:
+            self.incdir = os.path.join(self.cuda_path, 'include')
+            self.compile_args += [f'-I{self.incdir}']
+
+        if self.language != 'cuda':
+            arch_libdir = self._detect_arch_libdir()
+            self.libdir = os.path.join(self.cuda_path, arch_libdir)
+            mlog.debug('CUDA library directory is', mlog.bold(self.libdir))
+        else:
+            self.libdir = None
+
+        self.is_found = self._find_requested_libraries()
+
+    @classmethod
+    def _detect_language(cls, compilers: T.Dict[str, 'Compiler']) -> str:
+        for lang in cls.supported_languages:
+            if lang in compilers:
+                return lang
+        return list(compilers.keys())[0]
+
+    def _detect_cuda_path_and_version(self) -> TV_ResultTuple:
+        self.env_var = self._default_path_env_var()
+        mlog.debug('Default path env var:', mlog.bold(self.env_var))
+
+        version_reqs = self.version_reqs
+        if self.language == 'cuda':
+            nvcc_version = self._strip_patch_version(self.get_compiler().version)
+            mlog.debug('nvcc version:', mlog.bold(nvcc_version))
+            if version_reqs:
+                # make sure nvcc version satisfies specified version requirements
+                (found_some, not_found, found) = mesonlib.version_compare_many(nvcc_version, version_reqs)
+                if not_found:
+                    msg = f'The current nvcc version {nvcc_version} does not satisfy the specified CUDA Toolkit version requirements {version_reqs}.'
+                    return self._report_dependency_error(msg, (None, None, False))
+
+            # use nvcc version to find a matching CUDA Toolkit
+            version_reqs = [f'={nvcc_version}']
+        else:
+            nvcc_version = None
+
+        paths = [(path, self._cuda_toolkit_version(path), default) for (path, default) in self._cuda_paths()]
+        if version_reqs:
+            return self._find_matching_toolkit(paths, version_reqs, nvcc_version)
+
+        defaults = [(path, version) for (path, version, default) in paths if default]
+        if defaults:
+            return (defaults[0][0], defaults[0][1], True)
+
+        platform_msg = 'set the CUDA_PATH environment variable' if self._is_windows() \
+            else 'set the CUDA_PATH environment variable/create the \'/usr/local/cuda\' symbolic link'
+        msg = f'Please specify the desired CUDA Toolkit version (e.g. dependency(\'cuda\', version : \'>=10.1\')) or {platform_msg} to point to the location of your desired version.'
+        return self._report_dependency_error(msg, (None, None, False))
+
+    def _find_matching_toolkit(self, paths: T.List[TV_ResultTuple], version_reqs: T.List[str], nvcc_version: T.Optional[str]) -> TV_ResultTuple:
+        # keep the default paths order intact, sort the rest in the descending order
+        # according to the toolkit version
+        part_func: T.Callable[[TV_ResultTuple], bool] = lambda t: not t[2]
+        defaults_it, rest_it = mesonlib.partition(part_func, paths)
+        defaults = list(defaults_it)
+        paths = defaults + sorted(rest_it, key=lambda t: mesonlib.Version(t[1]), reverse=True)
+        mlog.debug(f'Search paths: {paths}')
+
+        if nvcc_version and defaults:
+            default_src = f"the {self.env_var} environment variable" if self.env_var else "the \'/usr/local/cuda\' symbolic link"
+            nvcc_warning = 'The default CUDA Toolkit as designated by {} ({}) doesn\'t match the current nvcc version {} and will be ignored.'.format(default_src, os.path.realpath(defaults[0][0]), nvcc_version)
+        else:
+            nvcc_warning = None
+
+        for (path, version, default) in paths:
+            (found_some, not_found, found) = mesonlib.version_compare_many(version, version_reqs)
+            if not not_found:
+                if not default and nvcc_warning:
+                    mlog.warning(nvcc_warning)
+                return (path, version, True)
+
+        if nvcc_warning:
+            mlog.warning(nvcc_warning)
+        return (None, None, False)
+
+    def _default_path_env_var(self) -> T.Optional[str]:
+        env_vars = ['CUDA_PATH'] if self._is_windows() else ['CUDA_PATH', 'CUDA_HOME', 'CUDA_ROOT']
+        env_vars = [var for var in env_vars if var in os.environ]
+        user_defaults = {os.environ[var] for var in env_vars}
+        if len(user_defaults) > 1:
+            mlog.warning('Environment variables {} point to conflicting toolkit locations ({}). Toolkit selection might produce unexpected results.'.format(', '.join(env_vars), ', '.join(user_defaults)))
+        return env_vars[0] if env_vars else None
+
+    def _cuda_paths(self) -> T.List[T.Tuple[str, bool]]:
+        return ([(os.environ[self.env_var], True)] if self.env_var else []) \
+            + (self._cuda_paths_win() if self._is_windows() else self._cuda_paths_nix())
+
+    def _cuda_paths_win(self) -> T.List[T.Tuple[str, bool]]:
+        env_vars = os.environ.keys()
+        return [(os.environ[var], False) for var in env_vars if var.startswith('CUDA_PATH_')]
+
+    def _cuda_paths_nix(self) -> T.List[T.Tuple[str, bool]]:
+        # include /usr/local/cuda default only if no env_var was found
+        pattern = '/usr/local/cuda-*' if self.env_var else '/usr/local/cuda*'
+        return [(path, os.path.basename(path) == 'cuda') for path in glob.iglob(pattern)]
+
+    toolkit_version_regex = re.compile(r'^CUDA Version\s+(.*)$')
+    path_version_win_regex = re.compile(r'^v(.*)$')
+    path_version_nix_regex = re.compile(r'^cuda-(.*)$')
+    cudart_version_regex = re.compile(r'#define\s+CUDART_VERSION\s+([0-9]+)')
+
+    def _cuda_toolkit_version(self, path: str) -> str:
+        version = self._read_toolkit_version_txt(path)
+        if version:
+            return version
+        version = self._read_cuda_runtime_api_version(path)
+        if version:
+            return version
+
+        mlog.debug('Falling back to extracting version from path')
+        path_version_regex = self.path_version_win_regex if self._is_windows() else self.path_version_nix_regex
+        try:
+            m = path_version_regex.match(os.path.basename(path))
+            if m:
+                return m.group(1)
+            else:
+                mlog.warning(f'Could not detect CUDA Toolkit version for {path}')
+        except Exception as e:
+            mlog.warning(f'Could not detect CUDA Toolkit version for {path}: {e!s}')
+
+        return '0.0'
+
+    def _read_cuda_runtime_api_version(self, path_str: str) -> T.Optional[str]:
+        path = Path(path_str)
+        for i in path.rglob('cuda_runtime_api.h'):
+            raw = i.read_text(encoding='utf-8')
+            m = self.cudart_version_regex.search(raw)
+            if not m:
+                continue
+            try:
+                vers_int = int(m.group(1))
+            except ValueError:
+                continue
+            # use // for floor instead of / which produces a float
+            major = vers_int // 1000                  # type: int
+            minor = (vers_int - major * 1000) // 10   # type: int
+            return f'{major}.{minor}'
+        return None
+
+    def _read_toolkit_version_txt(self, path: str) -> T.Optional[str]:
+        # Read 'version.txt' at the root of the CUDA Toolkit directory to determine the toolkit version
+        version_file_path = os.path.join(path, 'version.txt')
+        try:
+            with open(version_file_path, encoding='utf-8') as version_file:
+                version_str = version_file.readline() # e.g. 'CUDA Version 10.1.168'
+                m = self.toolkit_version_regex.match(version_str)
+                if m:
+                    return self._strip_patch_version(m.group(1))
+        except Exception as e:
+            mlog.debug(f'Could not read CUDA Toolkit\'s version file {version_file_path}: {e!s}')
+
+        return None
+
+    @classmethod
+    def _strip_patch_version(cls, version: str) -> str:
+        return '.'.join(version.split('.')[:2])
+
+    def _detect_arch_libdir(self) -> str:
+        arch = detect_cpu_family(self.env.coredata.compilers.host)
+        machine = self.env.machines[self.for_machine]
+        msg = '{} architecture is not supported in {} version of the CUDA Toolkit.'
+        if machine.is_windows():
+            libdirs = {'x86': 'Win32', 'x86_64': 'x64'}
+            if arch not in libdirs:
+                raise DependencyException(msg.format(arch, 'Windows'))
+            return os.path.join('lib', libdirs[arch])
+        elif machine.is_linux():
+            libdirs = {'x86_64': 'lib64', 'ppc64': 'lib', 'aarch64': 'lib64', 'loongarch64': 'lib64'}
+            if arch not in libdirs:
+                raise DependencyException(msg.format(arch, 'Linux'))
+            return libdirs[arch]
+        elif machine.is_darwin():
+            libdirs = {'x86_64': 'lib64'}
+            if arch not in libdirs:
+                raise DependencyException(msg.format(arch, 'macOS'))
+            return libdirs[arch]
+        else:
+            raise DependencyException('CUDA Toolkit: unsupported platform.')
+
+    def _find_requested_libraries(self) -> bool:
+        all_found = True
+
+        for module in self.requested_modules:
+            args = self.clib_compiler.find_library(module, self.env, [self.libdir] if self.libdir else [])
+            if args is None:
+                self._report_dependency_error(f'Couldn\'t find requested CUDA module \'{module}\'')
+                all_found = False
+            else:
+                mlog.debug(f'Link args for CUDA module \'{module}\' are {args}')
+                self.lib_modules[module] = args
+
+        return all_found
+
+    def _is_windows(self) -> bool:
+        return self.env.machines[self.for_machine].is_windows()
+
+    @T.overload
+    def _report_dependency_error(self, msg: str) -> None: ...
+
+    @T.overload
+    def _report_dependency_error(self, msg: str, ret_val: TV_ResultTuple) -> TV_ResultTuple: ... # noqa: F811
+
+    def _report_dependency_error(self, msg: str, ret_val: T.Optional[TV_ResultTuple] = None) -> T.Optional[TV_ResultTuple]: # noqa: F811
+        if self.required:
+            raise DependencyException(msg)
+
+        mlog.debug(msg)
+        return ret_val
+
+    def log_details(self) -> str:
+        module_str = ', '.join(self.requested_modules)
+        return 'modules: ' + module_str
+
+    def log_info(self) -> str:
+        return self.cuda_path if self.cuda_path else ''
+
+    def get_requested(self, kwargs: T.Dict[str, T.Any]) -> T.List[str]:
+        candidates = mesonlib.extract_as_list(kwargs, 'modules')
+        for c in candidates:
+            if not isinstance(c, str):
+                raise DependencyException('CUDA module argument is not a string.')
+        return candidates
+
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
+        args: T.List[str] = []
+        if self.libdir:
+            args += self.clib_compiler.get_linker_search_args(self.libdir)
+        for lib in self.requested_modules:
+            args += self.lib_modules[lib]
+        return args
+
+packages['cuda'] = CudaDependency
diff --git a/devtools/meson/mesonbuild/dependencies/data/CMakeLists.txt b/devtools/meson/mesonbuild/dependencies/data/CMakeLists.txt
new file mode 100644
index 0000000..d682cb8
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/data/CMakeLists.txt
@@ -0,0 +1,102 @@
+# fail noisily if attempt to use this file without setting:
+# cmake_minimum_required(VERSION ${CMAKE_VERSION})
+# project(... LANGUAGES ...)
+
+cmake_policy(SET CMP0000 NEW)
+
+set(PACKAGE_FOUND FALSE)
+set(_packageName "${NAME}")
+string(TOUPPER "${_packageName}" PACKAGE_NAME)
+
+if("${STATIC}" STREQUAL "True")
+  set("${NAME}_USE_STATIC_LIBS" "ON")
+endif()
+
+while(TRUE)
+  if ("${VERSION}" STREQUAL "")
+    find_package("${NAME}" QUIET COMPONENTS ${COMPS})
+  else()
+    find_package("${NAME}" "${VERSION}" QUIET COMPONENTS ${COMPS})
+  endif()
+
+  # ARCHS has to be set via the CMD interface
+  if(${_packageName}_FOUND OR ${PACKAGE_NAME}_FOUND OR "${ARCHS}" STREQUAL "")
+    break()
+  endif()
+
+  list(GET       ARCHS 0 CMAKE_LIBRARY_ARCHITECTURE)
+  list(REMOVE_AT ARCHS 0)
+endwhile()
+
+if(${_packageName}_FOUND  OR  ${PACKAGE_NAME}_FOUND)
+  set(PACKAGE_FOUND TRUE)
+
+  # Check the following variables:
+  # FOO_VERSION
+  # Foo_VERSION
+  # FOO_VERSION_STRING
+  # Foo_VERSION_STRING
+  if(NOT DEFINED PACKAGE_VERSION)
+    if(DEFINED ${_packageName}_VERSION)
+      set(PACKAGE_VERSION "${${_packageName}_VERSION}")
+    elseif(DEFINED ${PACKAGE_NAME}_VERSION)
+      set(PACKAGE_VERSION "${${PACKAGE_NAME}_VERSION}")
+    elseif(DEFINED ${_packageName}_VERSION_STRING)
+      set(PACKAGE_VERSION "${${_packageName}_VERSION_STRING}")
+    elseif(DEFINED ${PACKAGE_NAME}_VERSION_STRING)
+      set(PACKAGE_VERSION "${${PACKAGE_NAME}_VERSION_STRING}")
+    endif()
+  endif()
+
+  # Check the following variables:
+  # FOO_LIBRARIES
+  # Foo_LIBRARIES
+  # FOO_LIBS
+  # Foo_LIBS
+  set(libs)
+  if(DEFINED ${_packageName}_LIBRARIES)
+    set(libs ${_packageName}_LIBRARIES)
+  elseif(DEFINED ${PACKAGE_NAME}_LIBRARIES)
+    set(libs ${PACKAGE_NAME}_LIBRARIES)
+  elseif(DEFINED ${_packageName}_LIBS)
+    set(libs ${_packageName}_LIBS)
+  elseif(DEFINED ${PACKAGE_NAME}_LIBS)
+    set(libs ${PACKAGE_NAME}_LIBS)
+  endif()
+
+  # Check the following variables:
+  # FOO_INCLUDE_DIRS
+  # Foo_INCLUDE_DIRS
+  # FOO_INCLUDES
+  # Foo_INCLUDES
+  # FOO_INCLUDE_DIR
+  # Foo_INCLUDE_DIR
+  set(includes)
+  if(DEFINED ${_packageName}_INCLUDE_DIRS)
+    set(includes ${_packageName}_INCLUDE_DIRS)
+  elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIRS)
+    set(includes ${PACKAGE_NAME}_INCLUDE_DIRS)
+  elseif(DEFINED ${_packageName}_INCLUDES)
+    set(includes ${_packageName}_INCLUDES)
+  elseif(DEFINED ${PACKAGE_NAME}_INCLUDES)
+    set(includes ${PACKAGE_NAME}_INCLUDES)
+  elseif(DEFINED ${_packageName}_INCLUDE_DIR)
+    set(includes ${_packageName}_INCLUDE_DIR)
+  elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIR)
+    set(includes ${PACKAGE_NAME}_INCLUDE_DIR)
+  endif()
+
+  # Check the following variables:
+  # FOO_DEFINITIONS
+  # Foo_DEFINITIONS
+  set(definitions)
+  if(DEFINED ${_packageName}_DEFINITIONS)
+    set(definitions ${_packageName}_DEFINITIONS)
+  elseif(DEFINED ${PACKAGE_NAME}_DEFINITIONS)
+    set(definitions ${PACKAGE_NAME}_DEFINITIONS)
+  endif()
+
+  set(PACKAGE_INCLUDE_DIRS "${${includes}}")
+  set(PACKAGE_DEFINITIONS  "${${definitions}}")
+  set(PACKAGE_LIBRARIES    "${${libs}}")
+endif()
diff --git a/devtools/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt b/devtools/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt
new file mode 100644
index 0000000..4a93822
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt
@@ -0,0 +1,204 @@
+# fail noisily if attempt to use this file without setting:
+# cmake_minimum_required(VERSION ${CMAKE_VERSION})
+# project(... LANGUAGES ...)
+
+cmake_policy(SET CMP0000 NEW)
+
+set(PACKAGE_FOUND FALSE)
+
+list(REMOVE_DUPLICATES LLVM_MESON_VERSIONS)
+
+while(TRUE)
+  #Activate CMake version selection
+  foreach(i IN LISTS LLVM_MESON_VERSIONS)
+    find_package(LLVM ${i}
+      CONFIG
+      NAMES ${LLVM_MESON_PACKAGE_NAMES}
+      QUIET)
+    if(LLVM_FOUND)
+      break()
+    endif()
+  endforeach()
+
+  # ARCHS has to be set via the CMD interface
+  if(LLVM_FOUND OR "${ARCHS}" STREQUAL "")
+    break()
+  endif()
+
+  list(GET       ARCHS 0 CMAKE_LIBRARY_ARCHITECTURE)
+  list(REMOVE_AT ARCHS 0)
+endwhile()
+
+function(meson_llvm_cmake_dynamic_available mod out)
+  # Check if we can only compare LLVM_DYLIB_COMPONENTS, because
+  # we do not need complex component translation logic, if all
+  # is covered by one variable
+  if(mod IN_LIST LLVM_DYLIB_COMPONENTS)
+    set(${out} TRUE PARENT_SCOPE)
+    return()
+  elseif((NOT (mod IN_LIST LLVM_DYLIB_COMPONENTS))
+      AND (NOT("${LLVM_DYLIB_COMPONENTS}" STREQUAL "all")))
+    set(${out} FALSE PARENT_SCOPE)
+    return()
+  endif()
+
+  # Complex heuristic to filter all pseudo-components and skip invalid names
+  # LLVM_DYLIB_COMPONENTS will be 'all', because in other case we returned
+  # in previous check. 'all' is also handled there.
+  set(llvm_pseudo_components "native" "backend" "engine" "all-targets")
+  is_llvm_target_specifier(${mod} mod_spec INCLUDED_TARGETS)
+  string(TOUPPER "${LLVM_AVAILABLE_LIBS}" capitalized_libs)
+  string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" capitalized_tgts)
+  if(mod_spec)
+    set(${out} TRUE PARENT_SCOPE)
+  elseif(mod IN_LIST capitalized_tgts)
+    set(${out} TRUE PARENT_SCOPE)
+  elseif(mod IN_LIST llvm_pseudo_components)
+    set(${out} TRUE PARENT_SCOPE)
+  elseif(LLVM${mod} IN_LIST capitalized_libs)
+    set(${out} TRUE PARENT_SCOPE)
+  else()
+    set(${out} FALSE PARENT_SCOPE)
+  endif()
+endfunction()
+
+function(is_static target ret)
+  if(TARGET ${target})
+    get_target_property(target_type ${target} TYPE)
+    if(target_type STREQUAL "STATIC_LIBRARY")
+      set(${ret} TRUE PARENT_SCOPE)
+      return()
+    endif()
+  endif()
+  set(${ret} FALSE PARENT_SCOPE)
+endfunction()
+
+# Concatenate LLVM_MESON_REQUIRED_MODULES and LLVM_MESON_OPTIONAL_MODULES
+set(LLVM_MESON_MODULES ${LLVM_MESON_REQUIRED_MODULES} ${LLVM_MESON_OPTIONAL_MODULES})
+
+
+# Check if LLVM exists in dynamic world
+# Initialization before modules checking
+if(LLVM_FOUND)
+  if(LLVM_MESON_DYLIB AND TARGET LLVM)
+    set(PACKAGE_FOUND TRUE)
+  elseif(NOT LLVM_MESON_DYLIB)
+    # Use LLVMSupport to check if static targets exist
+    set(static_tg FALSE)
+    is_static(LLVMSupport static_tg)
+    if(static_tg)
+      set(PACKAGE_FOUND TRUE)
+    endif(static_tg)
+  endif()
+endif()
+
+if(PACKAGE_FOUND)
+  foreach(mod IN LISTS LLVM_MESON_MODULES)
+    # Reset variables
+    set(out_mods)
+    set(real_mods)
+
+    # Generate a lower and upper case version
+    string(TOLOWER "${mod}" mod_L)
+    string(TOUPPER "${mod}" mod_U)
+
+    # Special case - "all-targets" pseudo target
+    # Just append all targets, if pseudo-target exists
+    if("${mod}" STREQUAL "all-targets")
+      set(mod_L  ${LLVM_TARGETS_TO_BUILD})
+      string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" mod_U)
+    endif()
+
+    # Check if required module is linked is inside libLLVM.so.
+    # If not, skip this module
+    if(LLVM_MESON_DYLIB
+       AND DEFINED LLVM_DYLIB_COMPONENTS)
+        meson_llvm_cmake_dynamic_available(${mod} MOD_F)
+        meson_llvm_cmake_dynamic_available(${mod_L} MOD_L_F)
+        meson_llvm_cmake_dynamic_available(${mod_U} MOD_U_F)
+        if(MOD_F OR MOD_L_F OR MOD_U_F)
+          set(MESON_LLVM_TARGETS_${mod} LLVM)
+        endif()
+    elseif(LLVM_MESON_DYLIB AND (mod IN_LIST LLVM_MESON_REQUIRED_MODULES))
+      # Dynamic was requested, but no required variables set, we cannot continue
+      set(PACKAGE_FOUND FALSE)
+      break()
+    elseif(LLVM_MESON_DYLIB)
+      # Dynamic was requested, and we request optional modules only. Continue
+      continue()
+    else()
+      # CMake only do this for static components, and we
+      # replicate its behaviour
+      # Get the mapped components
+      llvm_map_components_to_libnames(out_mods ${mod} ${mod_L} ${mod_U})
+      list(SORT              out_mods)
+      list(REMOVE_DUPLICATES out_mods)
+
+      # Make sure that the modules exist
+      foreach(i IN LISTS out_mods)
+        set(static_tg FALSE)
+        is_static(${i} static_tg)
+        if(static_tg)
+          list(APPEND real_mods ${i})
+        endif()
+      endforeach()
+
+      # Set the output variables
+      set(MESON_LLVM_TARGETS_${mod} ${real_mods})
+      foreach(i IN LISTS real_mods)
+        set(MESON_TARGET_TO_LLVM_${i} ${mod})
+      endforeach()
+    endif()
+  endforeach()
+
+  # Check the following variables:
+  # LLVM_PACKAGE_VERSION
+  # LLVM_VERSION
+  # LLVM_VERSION_STRING
+  if(NOT DEFINED PACKAGE_VERSION)
+    if(DEFINED LLVM_PACKAGE_VERSION)
+      set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
+    elseif(DEFINED LLVM_VERSION)
+      set(PACKAGE_VERSION "${LLVM_VERSION}")
+    elseif(DEFINED LLVM_VERSION_STRING)
+      set(PACKAGE_VERSION "${LLVM_VERSION_STRING}")
+    endif()
+  endif()
+
+  # Check the following variables:
+  # LLVM_LIBRARIES
+  # LLVM_LIBS
+  set(libs)
+  #Hardcode LLVM, because we links with libLLVM.so when dynamic
+  if(LLVM_MESON_DYLIB)
+    get_target_property(libs LLVM IMPORTED_LOCATION)
+  elseif(DEFINED LLVM_LIBRARIES)
+    set(libs LLVM_LIBRARIES)
+  elseif(DEFINED LLVM_LIBS)
+    set(libs LLVM_LIBS)
+  endif()
+
+  # Check the following variables:
+  # LLVM_INCLUDE_DIRS
+  # LLVM_INCLUDES
+  # LLVM_INCLUDE_DIR
+  set(includes)
+  if(DEFINED LLVM_INCLUDE_DIRS)
+    set(includes LLVM_INCLUDE_DIRS)
+  elseif(DEFINED LLVM_INCLUDES)
+    set(includes LLVM_INCLUDES)
+  elseif(DEFINED LLVM_INCLUDE_DIR)
+    set(includes LLVM_INCLUDE_DIR)
+  endif()
+
+  # Check the following variables:
+  # LLVM_DEFINITIONS
+  set(definitions)
+  if(DEFINED LLVM_DEFINITIONS)
+    set(definitions LLVM_DEFINITIONS)
+  endif()
+
+  set(PACKAGE_INCLUDE_DIRS "${${includes}}")
+  set(PACKAGE_DEFINITIONS  "${${definitions}}")
+  set(PACKAGE_LIBRARIES    "${${libs}}")
+endif()
diff --git a/devtools/meson/mesonbuild/dependencies/data/CMakePathInfo.txt b/devtools/meson/mesonbuild/dependencies/data/CMakePathInfo.txt
new file mode 100644
index 0000000..662ec58
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/data/CMakePathInfo.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION})
+
+set(TMP_PATHS_LIST)
+list(APPEND TMP_PATHS_LIST ${CMAKE_PREFIX_PATH})
+list(APPEND TMP_PATHS_LIST ${CMAKE_FRAMEWORK_PATH})
+list(APPEND TMP_PATHS_LIST ${CMAKE_APPBUNDLE_PATH})
+list(APPEND TMP_PATHS_LIST $ENV{CMAKE_PREFIX_PATH})
+list(APPEND TMP_PATHS_LIST $ENV{CMAKE_FRAMEWORK_PATH})
+list(APPEND TMP_PATHS_LIST $ENV{CMAKE_APPBUNDLE_PATH})
+list(APPEND TMP_PATHS_LIST ${CMAKE_SYSTEM_PREFIX_PATH})
+list(APPEND TMP_PATHS_LIST ${CMAKE_SYSTEM_FRAMEWORK_PATH})
+list(APPEND TMP_PATHS_LIST ${CMAKE_SYSTEM_APPBUNDLE_PATH})
+
+set(LIB_ARCH_LIST)
+if(CMAKE_LIBRARY_ARCHITECTURE_REGEX)
+  file(GLOB implicit_dirs RELATIVE /lib /lib/*-linux-gnu* )
+  foreach(dir ${implicit_dirs})
+    if("${dir}" MATCHES "${CMAKE_LIBRARY_ARCHITECTURE_REGEX}")
+      list(APPEND LIB_ARCH_LIST "${dir}")
+    endif()
+  endforeach()
+endif()
+
+# "Export" these variables:
+set(MESON_ARCH_LIST ${LIB_ARCH_LIST})
+set(MESON_PATHS_LIST ${TMP_PATHS_LIST})
+set(MESON_CMAKE_ROOT ${CMAKE_ROOT})
+set(MESON_CMAKE_SYSROOT ${CMAKE_SYSROOT})
+set(MESON_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH})
+
+message(STATUS ${TMP_PATHS_LIST})
diff --git a/devtools/meson/mesonbuild/dependencies/data/__init__.py b/devtools/meson/mesonbuild/dependencies/data/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/devtools/meson/mesonbuild/dependencies/detect.py b/devtools/meson/mesonbuild/dependencies/detect.py
new file mode 100644
index 0000000..9428d54
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/detect.py
@@ -0,0 +1,235 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import collections, functools, importlib
+import typing as T
+
+from .base import ExternalDependency, DependencyException, DependencyMethods, NotFoundDependency
+
+from ..mesonlib import listify, MachineChoice, PerMachine
+from .. import mlog
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from .factory import DependencyFactory, WrappedFactoryFunc, DependencyGenerator
+
+    TV_DepIDEntry = T.Union[str, bool, int, T.Tuple[str, ...]]
+    TV_DepID = T.Tuple[T.Tuple[str, TV_DepIDEntry], ...]
+    PackageTypes = T.Union[T.Type[ExternalDependency], DependencyFactory, WrappedFactoryFunc]
+
+class DependencyPackages(collections.UserDict):
+    data: T.Dict[str, PackageTypes]
+    defaults: T.Dict[str, str] = {}
+
+    def __missing__(self, key: str) -> PackageTypes:
+        if key in self.defaults:
+            modn = self.defaults[key]
+            importlib.import_module(f'mesonbuild.dependencies.{modn}')
+
+            return self.data[key]
+        raise KeyError(key)
+
+    def __contains__(self, key: object) -> bool:
+        return key in self.defaults or key in self.data
+
+# These must be defined in this file to avoid cyclical references.
+packages = DependencyPackages()
+_packages_accept_language: T.Set[str] = set()
+
+def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID':
+    identifier: 'TV_DepID' = (('name', name), )
+    from ..interpreter import permitted_dependency_kwargs
+    assert len(permitted_dependency_kwargs) == 19, \
+           'Extra kwargs have been added to dependency(), please review if it makes sense to handle it here'
+    for key, value in kwargs.items():
+        # 'version' is irrelevant for caching; the caller must check version matches
+        # 'native' is handled above with `for_machine`
+        # 'required' is irrelevant for caching; the caller handles it separately
+        # 'fallback' and 'allow_fallback' is not part of the cache because,
+        #     once a dependency has been found through a fallback, it should
+        #     be used for the rest of the Meson run.
+        # 'default_options' is only used in fallback case
+        # 'not_found_message' has no impact on the dependency lookup
+        # 'include_type' is handled after the dependency lookup
+        if key in {'version', 'native', 'required', 'fallback', 'allow_fallback', 'default_options',
+                   'not_found_message', 'include_type'}:
+            continue
+        # All keyword arguments are strings, ints, or lists (or lists of lists)
+        if isinstance(value, list):
+            for i in value:
+                assert isinstance(i, str)
+            value = tuple(frozenset(listify(value)))
+        else:
+            assert isinstance(value, (str, bool, int))
+        identifier = (*identifier, (key, value),)
+    return identifier
+
+display_name_map = {
+    'boost': 'Boost',
+    'cuda': 'CUDA',
+    'dub': 'DUB',
+    'gmock': 'GMock',
+    'gtest': 'GTest',
+    'hdf5': 'HDF5',
+    'llvm': 'LLVM',
+    'mpi': 'MPI',
+    'netcdf': 'NetCDF',
+    'openmp': 'OpenMP',
+    'wxwidgets': 'WxWidgets',
+}
+
+def find_external_dependency(name: str, env: 'Environment', kwargs: T.Dict[str, object], candidates: T.Optional[T.List['DependencyGenerator']] = None) -> T.Union['ExternalDependency', NotFoundDependency]:
+    assert name
+    required = kwargs.get('required', True)
+    if not isinstance(required, bool):
+        raise DependencyException('Keyword "required" must be a boolean.')
+    if not isinstance(kwargs.get('method', ''), str):
+        raise DependencyException('Keyword "method" must be a string.')
+    lname = name.lower()
+    if lname not in _packages_accept_language and 'language' in kwargs:
+        raise DependencyException(f'{name} dependency does not accept "language" keyword argument')
+    if not isinstance(kwargs.get('version', ''), (str, list)):
+        raise DependencyException('Keyword "Version" must be string or list.')
+
+    # display the dependency name with correct casing
+    display_name = display_name_map.get(lname, lname)
+
+    for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST
+
+    type_text = PerMachine('Build-time', 'Run-time')[for_machine] + ' dependency'
+
+    # build a list of dependency methods to try
+    if candidates is None:
+        candidates = _build_external_dependency_list(name, env, for_machine, kwargs)
+
+    pkg_exc: T.List[DependencyException] = []
+    pkgdep:  T.List[ExternalDependency] = []
+    details = ''
+
+    for c in candidates:
+        # try this dependency method
+        try:
+            d = c()
+            d._check_version()
+            pkgdep.append(d)
+        except DependencyException as e:
+            assert isinstance(c, functools.partial), 'for mypy'
+            bettermsg = f'Dependency lookup for {name} with method {c.func.log_tried()!r} failed: {e}'
+            mlog.debug(bettermsg)
+            e.args = (bettermsg,)
+            pkg_exc.append(e)
+        else:
+            pkg_exc.append(None)
+            details = d.log_details()
+            if details:
+                details = '(' + details + ') '
+            if 'language' in kwargs:
+                details += 'for ' + d.language + ' '
+
+            # if the dependency was found
+            if d.found():
+
+                info: mlog.TV_LoggableList = []
+                if d.version:
+                    info.append(mlog.normal_cyan(d.version))
+
+                log_info = d.log_info()
+                if log_info:
+                    info.append('(' + log_info + ')')
+
+                mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.green('YES'), *info)
+
+                return d
+
+    # otherwise, the dependency could not be found
+    tried_methods = [d.log_tried() for d in pkgdep if d.log_tried()]
+    if tried_methods:
+        tried = mlog.format_list(tried_methods)
+    else:
+        tried = ''
+
+    mlog.log(type_text, mlog.bold(display_name), details + 'found:', mlog.red('NO'),
+             f'(tried {tried})' if tried else '')
+
+    if required:
+        # if an exception occurred with the first detection method, re-raise it
+        # (on the grounds that it came from the preferred dependency detection
+        # method)
+        if pkg_exc and pkg_exc[0]:
+            raise pkg_exc[0]
+
+        # we have a list of failed ExternalDependency objects, so we can report
+        # the methods we tried to find the dependency
+        raise DependencyException(f'Dependency "{name}" not found' +
+                                  (f', tried {tried}' if tried else ''))
+
+    return NotFoundDependency(name, env)
+
+
+def _build_external_dependency_list(name: str, env: 'Environment', for_machine: MachineChoice,
+                                    kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
+    # First check if the method is valid
+    if 'method' in kwargs and kwargs['method'] not in [e.value for e in DependencyMethods]:
+        raise DependencyException('method {!r} is invalid'.format(kwargs['method']))
+
+    # Is there a specific dependency detector for this dependency?
+    lname = name.lower()
+    if lname in packages:
+        # Create the list of dependency object constructors using a factory
+        # class method, if one exists, otherwise the list just consists of the
+        # constructor
+        if isinstance(packages[lname], type):
+            entry1 = T.cast('T.Type[ExternalDependency]', packages[lname])  # mypy doesn't understand isinstance(..., type)
+            if issubclass(entry1, ExternalDependency):
+                func: T.Callable[[], 'ExternalDependency'] = functools.partial(entry1, env, kwargs)
+                dep = [func]
+        else:
+            entry2 = T.cast('T.Union[DependencyFactory, WrappedFactoryFunc]', packages[lname])
+            dep = entry2(env, for_machine, kwargs)
+        return dep
+
+    candidates: T.List['DependencyGenerator'] = []
+
+    if kwargs.get('method', 'auto') == 'auto':
+        # Just use the standard detection methods.
+        methods = ['pkg-config', 'extraframework', 'cmake']
+    else:
+        # If it's explicitly requested, use that detection method (only).
+        methods = [kwargs['method']]
+
+    # Exclusive to when it is explicitly requested
+    if 'dub' in methods:
+        from .dub import DubDependency
+        candidates.append(functools.partial(DubDependency, name, env, kwargs))
+
+    # Preferred first candidate for auto.
+    if 'pkg-config' in methods:
+        from .pkgconfig import PkgConfigDependency
+        candidates.append(functools.partial(PkgConfigDependency, name, env, kwargs))
+
+    # On OSX only, try framework dependency detector.
+    if 'extraframework' in methods:
+        if env.machines[for_machine].is_darwin():
+            from .framework import ExtraFrameworkDependency
+            candidates.append(functools.partial(ExtraFrameworkDependency, name, env, kwargs))
+
+    # Only use CMake:
+    # - if it's explicitly requested
+    # - as a last resort, since it might not work 100% (see #6113)
+    if 'cmake' in methods:
+        from .cmake import CMakeDependency
+        candidates.append(functools.partial(CMakeDependency, name, env, kwargs))
+
+    return candidates
diff --git a/devtools/meson/mesonbuild/dependencies/dev.py b/devtools/meson/mesonbuild/dependencies/dev.py
new file mode 100644
index 0000000..09f55b7
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/dev.py
@@ -0,0 +1,720 @@
+# Copyright 2013-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file contains the detection logic for external dependencies useful for
+# development purposes, such as testing, debugging, etc..
+
+from __future__ import annotations
+
+import glob
+import os
+import re
+import pathlib
+import shutil
+import subprocess
+import typing as T
+import functools
+
+from mesonbuild.interpreterbase.decorators import FeatureDeprecated
+
+from .. import mesonlib, mlog
+from ..environment import get_llvm_tool_names
+from ..mesonlib import version_compare, version_compare_many, search_version, stringlistify, extract_as_list
+from .base import DependencyException, DependencyMethods, detect_compiler, strip_system_includedirs, strip_system_libdirs, SystemDependency, ExternalDependency, DependencyTypeName
+from .cmake import CMakeDependency
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .factory import DependencyFactory
+from .misc import threads_factory
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+    from typing_extensions import TypedDict
+
+    class JNISystemDependencyKW(TypedDict):
+        modules: T.List[str]
+        # FIXME: When dependency() moves to typed Kwargs, this should inherit
+        # from its TypedDict type.
+        version: T.Optional[str]
+
+
+def get_shared_library_suffix(environment: 'Environment', for_machine: MachineChoice) -> str:
+    """This is only guaranteed to work for languages that compile to machine
+    code, not for languages like C# that use a bytecode and always end in .dll
+    """
+    m = environment.machines[for_machine]
+    if m.is_windows():
+        return '.dll'
+    elif m.is_darwin():
+        return '.dylib'
+    return '.so'
+
+
+class GTestDependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs, language='cpp')
+        self.main = kwargs.get('main', False)
+        self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src']
+        if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+            self.is_found = False
+            return
+        self.detect()
+
+    def detect(self) -> None:
+        gtest_detect = self.clib_compiler.find_library("gtest", self.env, [])
+        gtest_main_detect = self.clib_compiler.find_library("gtest_main", self.env, [])
+        if gtest_detect and (not self.main or gtest_main_detect):
+            self.is_found = True
+            self.compile_args = []
+            self.link_args = gtest_detect
+            if self.main:
+                self.link_args += gtest_main_detect
+            self.sources = []
+            self.prebuilt = True
+        elif self.detect_srcdir():
+            self.is_found = True
+            self.compile_args = ['-I' + d for d in self.src_include_dirs]
+            self.link_args = []
+            if self.main:
+                self.sources = [self.all_src, self.main_src]
+            else:
+                self.sources = [self.all_src]
+            self.prebuilt = False
+        else:
+            self.is_found = False
+
+    def detect_srcdir(self) -> bool:
+        for s in self.src_dirs:
+            if os.path.exists(s):
+                self.src_dir = s
+                self.all_src = mesonlib.File.from_absolute_file(
+                    os.path.join(self.src_dir, 'gtest-all.cc'))
+                self.main_src = mesonlib.File.from_absolute_file(
+                    os.path.join(self.src_dir, 'gtest_main.cc'))
+                self.src_include_dirs = [os.path.normpath(os.path.join(self.src_dir, '..')),
+                                         os.path.normpath(os.path.join(self.src_dir, '../include')),
+                                         ]
+                return True
+        return False
+
+    def log_info(self) -> str:
+        if self.prebuilt:
+            return 'prebuilt'
+        else:
+            return 'building self'
+
+
+class GTestDependencyPC(PkgConfigDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        assert name == 'gtest'
+        if kwargs.get('main'):
+            name = 'gtest_main'
+        super().__init__(name, environment, kwargs)
+
+
+class GMockDependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs, language='cpp')
+        self.main = kwargs.get('main', False)
+        if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+            self.is_found = False
+            return
+
+        # If we are getting main() from GMock, we definitely
+        # want to avoid linking in main() from GTest
+        gtest_kwargs = kwargs.copy()
+        if self.main:
+            gtest_kwargs['main'] = False
+
+        # GMock without GTest is pretty much useless
+        # this also mimics the structure given in WrapDB,
+        # where GMock always pulls in GTest
+        found = self._add_sub_dependency(gtest_factory(environment, self.for_machine, gtest_kwargs))
+        if not found:
+            self.is_found = False
+            return
+
+        # GMock may be a library or just source.
+        # Work with both.
+        gmock_detect = self.clib_compiler.find_library("gmock", self.env, [])
+        gmock_main_detect = self.clib_compiler.find_library("gmock_main", self.env, [])
+        if gmock_detect and (not self.main or gmock_main_detect):
+            self.is_found = True
+            self.link_args += gmock_detect
+            if self.main:
+                self.link_args += gmock_main_detect
+            self.prebuilt = True
+            return
+
+        for d in ['/usr/src/googletest/googlemock/src', '/usr/src/gmock/src', '/usr/src/gmock']:
+            if os.path.exists(d):
+                self.is_found = True
+                # Yes, we need both because there are multiple
+                # versions of gmock that do different things.
+                d2 = os.path.normpath(os.path.join(d, '..'))
+                self.compile_args += ['-I' + d, '-I' + d2, '-I' + os.path.join(d2, 'include')]
+                all_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock-all.cc'))
+                main_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock_main.cc'))
+                if self.main:
+                    self.sources += [all_src, main_src]
+                else:
+                    self.sources += [all_src]
+                self.prebuilt = False
+                return
+
+        self.is_found = False
+
+    def log_info(self) -> str:
+        if self.prebuilt:
+            return 'prebuilt'
+        else:
+            return 'building self'
+
+
+class GMockDependencyPC(PkgConfigDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        assert name == 'gmock'
+        if kwargs.get('main'):
+            name = 'gmock_main'
+        super().__init__(name, environment, kwargs)
+
+
+class LLVMDependencyConfigTool(ConfigToolDependency):
+    """
+    LLVM uses a special tool, llvm-config, which has arguments for getting
+    c args, cxx args, and ldargs as well as version.
+    """
+    tool_name = 'llvm-config'
+    __cpp_blacklist = {'-DNDEBUG'}
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        self.tools = get_llvm_tool_names('llvm-config')
+
+        # Fedora starting with Fedora 30 adds a suffix of the number
+        # of bits in the isa that llvm targets, for example, on x86_64
+        # and aarch64 the name will be llvm-config-64, on x86 and arm
+        # it will be llvm-config-32.
+        if environment.machines[self.get_for_machine_from_kwargs(kwargs)].is_64_bit:
+            self.tools.append('llvm-config-64')
+        else:
+            self.tools.append('llvm-config-32')
+
+        # It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0
+        # the C linker works fine if only using the C API.
+        super().__init__(name, environment, kwargs, language='cpp')
+        self.provided_modules: T.List[str] = []
+        self.required_modules: mesonlib.OrderedSet[str] = mesonlib.OrderedSet()
+        self.module_details:   T.List[str] = []
+        if not self.is_found:
+            return
+
+        self.provided_modules = self.get_config_value(['--components'], 'modules')
+        modules = stringlistify(extract_as_list(kwargs, 'modules'))
+        self.check_components(modules)
+        opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
+        self.check_components(opt_modules, required=False)
+
+        cargs = mesonlib.OrderedSet(self.get_config_value(['--cppflags'], 'compile_args'))
+        self.compile_args = list(cargs.difference(self.__cpp_blacklist))
+
+        if version_compare(self.version, '>= 3.9'):
+            self._set_new_link_args(environment)
+        else:
+            self._set_old_link_args()
+        self.link_args = strip_system_libdirs(environment, self.for_machine, self.link_args)
+        self.link_args = self.__fix_bogus_link_args(self.link_args)
+        if not self._add_sub_dependency(threads_factory(environment, self.for_machine, {})):
+            self.is_found = False
+            return
+
+    def __fix_bogus_link_args(self, args: T.List[str]) -> T.List[str]:
+        """This function attempts to fix bogus link arguments that llvm-config
+        generates.
+
+        Currently it works around the following:
+            - FreeBSD: when statically linking -l/usr/lib/libexecinfo.so will
+              be generated, strip the -l in cases like this.
+            - Windows: We may get -LIBPATH:... which is later interpreted as
+              "-L IBPATH:...", if we're using an msvc like compilers convert
+              that to "/LIBPATH", otherwise to "-L ..."
+        """
+
+        new_args = []
+        for arg in args:
+            if arg.startswith('-l') and arg.endswith('.so'):
+                new_args.append(arg.lstrip('-l'))
+            elif arg.startswith('-LIBPATH:'):
+                cpp = self.env.coredata.compilers[self.for_machine]['cpp']
+                new_args.extend(cpp.get_linker_search_args(arg.lstrip('-LIBPATH:')))
+            else:
+                new_args.append(arg)
+        return new_args
+
+    def __check_libfiles(self, shared: bool) -> None:
+        """Use llvm-config's --libfiles to check if libraries exist."""
+        mode = '--link-shared' if shared else '--link-static'
+
+        # Set self.required to true to force an exception in get_config_value
+        # if the returncode != 0
+        restore = self.required
+        self.required = True
+
+        try:
+            # It doesn't matter what the stage is, the caller needs to catch
+            # the exception anyway.
+            self.link_args = self.get_config_value(['--libfiles', mode], '')
+        finally:
+            self.required = restore
+
+    def _set_new_link_args(self, environment: 'Environment') -> None:
+        """How to set linker args for LLVM versions >= 3.9"""
+        try:
+            mode = self.get_config_value(['--shared-mode'], 'link_args')[0]
+        except IndexError:
+            mlog.debug('llvm-config --shared-mode returned an error')
+            self.is_found = False
+            return
+
+        if not self.static and mode == 'static':
+            # If llvm is configured with LLVM_BUILD_LLVM_DYLIB but not with
+            # LLVM_LINK_LLVM_DYLIB and not LLVM_BUILD_SHARED_LIBS (which
+            # upstream doesn't recommend using), then llvm-config will lie to
+            # you about how to do shared-linking. It wants to link to a a bunch
+            # of individual shared libs (which don't exist because llvm wasn't
+            # built with LLVM_BUILD_SHARED_LIBS.
+            #
+            # Therefore, we'll try to get the libfiles, if the return code is 0
+            # or we get an empty list, then we'll try to build a working
+            # configuration by hand.
+            try:
+                self.__check_libfiles(True)
+            except DependencyException:
+                lib_ext = get_shared_library_suffix(environment, self.for_machine)
+                libdir = self.get_config_value(['--libdir'], 'link_args')[0]
+                # Sort for reproducibility
+                matches = sorted(glob.iglob(os.path.join(libdir, f'libLLVM*{lib_ext}')))
+                if not matches:
+                    if self.required:
+                        raise
+                    self.is_found = False
+                    return
+
+                self.link_args = self.get_config_value(['--ldflags'], 'link_args')
+                libname = os.path.basename(matches[0]).rstrip(lib_ext).lstrip('lib')
+                self.link_args.append(f'-l{libname}')
+                return
+        elif self.static and mode == 'shared':
+            # If, however LLVM_BUILD_SHARED_LIBS is true # (*cough* gentoo *cough*)
+            # then this is correct. Building with LLVM_BUILD_SHARED_LIBS has a side
+            # effect, it stops the generation of static archives. Therefore we need
+            # to check for that and error out on static if this is the case
+            try:
+                self.__check_libfiles(False)
+            except DependencyException:
+                if self.required:
+                    raise
+                self.is_found = False
+                return
+
+        link_args = ['--link-static', '--system-libs'] if self.static else ['--link-shared']
+        self.link_args = self.get_config_value(
+            ['--libs', '--ldflags'] + link_args + list(self.required_modules),
+            'link_args')
+
+    def _set_old_link_args(self) -> None:
+        """Setting linker args for older versions of llvm.
+
+        Old versions of LLVM bring an extra level of insanity with them.
+        llvm-config will provide the correct arguments for static linking, but
+        not for shared-linnking, we have to figure those out ourselves, because
+        of course we do.
+        """
+        if self.static:
+            self.link_args = self.get_config_value(
+                ['--libs', '--ldflags', '--system-libs'] + list(self.required_modules),
+                'link_args')
+        else:
+            # llvm-config will provide arguments for static linking, so we get
+            # to figure out for ourselves what to link with. We'll do that by
+            # checking in the directory provided by --libdir for a library
+            # called libLLVM-.(so|dylib|dll)
+            libdir = self.get_config_value(['--libdir'], 'link_args')[0]
+
+            expected_name = f'libLLVM-{self.version}'
+            re_name = re.compile(fr'{expected_name}.(so|dll|dylib)$')
+
+            for file_ in os.listdir(libdir):
+                if re_name.match(file_):
+                    self.link_args = [f'-L{libdir}',
+                                      '-l{}'.format(os.path.splitext(file_.lstrip('lib'))[0])]
+                    break
+            else:
+                raise DependencyException(
+                    'Could not find a dynamically linkable library for LLVM.')
+
+    def check_components(self, modules: T.List[str], required: bool = True) -> None:
+        """Check for llvm components (modules in meson terms).
+
+        The required option is whether the module is required, not whether LLVM
+        is required.
+        """
+        for mod in sorted(set(modules)):
+            status = ''
+
+            if mod not in self.provided_modules:
+                if required:
+                    self.is_found = False
+                    if self.required:
+                        raise DependencyException(
+                            f'Could not find required LLVM Component: {mod}')
+                    status = '(missing)'
+                else:
+                    status = '(missing but optional)'
+            else:
+                self.required_modules.add(mod)
+
+            self.module_details.append(mod + status)
+
+    def log_details(self) -> str:
+        if self.module_details:
+            return 'modules: ' + ', '.join(self.module_details)
+        return ''
+
+class LLVMDependencyCMake(CMakeDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        self.llvm_modules = stringlistify(extract_as_list(kwargs, 'modules'))
+        self.llvm_opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
+
+        compilers = None
+        if kwargs.get('native', False):
+            compilers = env.coredata.compilers.build
+        else:
+            compilers = env.coredata.compilers.host
+        if not compilers or not all(x in compilers for x in ('c', 'cpp')):
+            # Initialize basic variables
+            ExternalDependency.__init__(self, DependencyTypeName('cmake'), env, kwargs)
+
+            # Initialize CMake specific variables
+            self.found_modules: T.List[str] = []
+            self.name = name
+
+            # Warn and return
+            mlog.warning('The LLVM dependency was not found via CMake since both a C and C++ compiler are required.')
+            return
+
+        super().__init__(name, env, kwargs, language='cpp', force_use_global_compilers=True)
+
+        if self.traceparser is None:
+            return
+
+        if not self.is_found:
+            return
+
+        #CMake will return not found due to not defined LLVM_DYLIB_COMPONENTS
+        if not self.static and version_compare(self.version, '< 7.0') and self.llvm_modules:
+            mlog.warning('Before version 7.0 cmake does not export modules for dynamic linking, cannot check required modules')
+            return
+
+        # Extract extra include directories and definitions
+        inc_dirs = self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS')
+        defs = self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS')
+        # LLVM explicitly uses space-separated variables rather than semicolon lists
+        if len(defs) == 1:
+            defs = defs[0].split(' ')
+        temp = ['-I' + x for x in inc_dirs] + defs
+        self.compile_args += [x for x in temp if x not in self.compile_args]
+        self.compile_args = strip_system_includedirs(env, self.for_machine, self.compile_args)
+        if not self._add_sub_dependency(threads_factory(env, self.for_machine, {})):
+            self.is_found = False
+            return
+
+    def _main_cmake_file(self) -> str:
+        # Use a custom CMakeLists.txt for LLVM
+        return 'CMakeListsLLVM.txt'
+
+    # Check version in CMake to return exact version as config tool (latest allowed)
+    # It is safe to add .0 to latest argument, it will discarded if we use search_version
+    def llvm_cmake_versions(self) -> T.List[str]:
+
+        def ver_from_suf(req: str) -> str:
+            return search_version(req.strip('-')+'.0')
+
+        def version_sorter(a: str, b: str) -> int:
+            if version_compare(a, "="+b):
+                return 0
+            if version_compare(a, "<"+b):
+                return 1
+            return -1
+
+        llvm_requested_versions = [ver_from_suf(x) for x in get_llvm_tool_names('') if version_compare(ver_from_suf(x), '>=0')]
+        if self.version_reqs:
+            llvm_requested_versions = [ver_from_suf(x) for x in get_llvm_tool_names('') if version_compare_many(ver_from_suf(x), self.version_reqs)]
+        # CMake sorting before 3.18 is incorrect, sort it here instead
+        return sorted(llvm_requested_versions, key=functools.cmp_to_key(version_sorter))
+
+    # Split required and optional modules to distinguish it in CMake
+    def _extra_cmake_opts(self) -> T.List[str]:
+        return ['-DLLVM_MESON_REQUIRED_MODULES={}'.format(';'.join(self.llvm_modules)),
+                '-DLLVM_MESON_OPTIONAL_MODULES={}'.format(';'.join(self.llvm_opt_modules)),
+                '-DLLVM_MESON_PACKAGE_NAMES={}'.format(';'.join(get_llvm_tool_names(self.name))),
+                '-DLLVM_MESON_VERSIONS={}'.format(';'.join(self.llvm_cmake_versions())),
+                '-DLLVM_MESON_DYLIB={}'.format('OFF' if self.static else 'ON')]
+
+    def _map_module_list(self, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]]) -> T.List[T.Tuple[str, bool]]:
+        res = []
+        for mod, required in modules:
+            cm_targets = self.traceparser.get_cmake_var(f'MESON_LLVM_TARGETS_{mod}')
+            if not cm_targets:
+                if required:
+                    raise self._gen_exception(f'LLVM module {mod} was not found')
+                else:
+                    mlog.warning('Optional LLVM module', mlog.bold(mod), 'was not found', fatal=False)
+                    continue
+            for i in cm_targets:
+                res += [(i, required)]
+        return res
+
+    def _original_module_name(self, module: str) -> str:
+        orig_name = self.traceparser.get_cmake_var(f'MESON_TARGET_TO_LLVM_{module}')
+        if orig_name:
+            return orig_name[0]
+        return module
+
+
+class ValgrindDependency(PkgConfigDependency):
+    '''
+    Consumers of Valgrind usually only need the compile args and do not want to
+    link to its (static) libraries.
+    '''
+    def __init__(self, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__('valgrind', env, kwargs)
+
+    def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
+        return []
+
+packages['valgrind'] = ValgrindDependency
+
+
+class ZlibSystemDependency(SystemDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        from ..compilers.c import AppleClangCCompiler
+        from ..compilers.cpp import AppleClangCPPCompiler
+
+        m = self.env.machines[self.for_machine]
+
+        # I'm not sure this is entirely correct. What if we're cross compiling
+        # from something to macOS?
+        if ((m.is_darwin() and isinstance(self.clib_compiler, (AppleClangCCompiler, AppleClangCPPCompiler))) or
+                m.is_freebsd() or m.is_dragonflybsd() or m.is_android()):
+            # No need to set includes,
+            # on macos xcode/clang will do that for us.
+            # on freebsd zlib.h is in /usr/include
+
+            self.is_found = True
+            self.link_args = ['-lz']
+        else:
+            if self.clib_compiler.get_argument_syntax() == 'msvc':
+                libs = ['zlib1', 'zlib']
+            else:
+                libs = ['z']
+            for lib in libs:
+                l = self.clib_compiler.find_library(lib, environment, [], self.libtype)
+                h = self.clib_compiler.has_header('zlib.h', '', environment, dependencies=[self])
+                if l and h[0]:
+                    self.is_found = True
+                    self.link_args = l
+                    break
+            else:
+                return
+
+        v, _ = self.clib_compiler.get_define('ZLIB_VERSION', '#include ', self.env, [], [self])
+        self.version = v.strip('"')
+
+
+class JNISystemDependency(SystemDependency):
+    def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW):
+        super().__init__('jni', environment, T.cast('T.Dict[str, T.Any]', kwargs))
+
+        self.feature_since = ('0.62.0', '')
+
+        m = self.env.machines[self.for_machine]
+
+        if 'java' not in environment.coredata.compilers[self.for_machine]:
+            detect_compiler(self.name, environment, self.for_machine, 'java')
+        self.javac = environment.coredata.compilers[self.for_machine]['java']
+        self.version = self.javac.version
+
+        modules: T.List[str] = mesonlib.listify(kwargs.get('modules', []))
+        for module in modules:
+            if module not in {'jvm', 'awt'}:
+                msg = f'Unknown JNI module ({module})'
+                if self.required:
+                    mlog.error(msg)
+                else:
+                    mlog.debug(msg)
+                self.is_found = False
+                return
+
+        if 'version' in kwargs and not version_compare(self.version, kwargs['version']):
+            mlog.error(f'Incorrect JDK version found ({self.version}), wanted {kwargs["version"]}')
+            self.is_found = False
+            return
+
+        self.java_home = environment.properties[self.for_machine].get_java_home()
+        if not self.java_home:
+            self.java_home = pathlib.Path(shutil.which(self.javac.exelist[0])).resolve().parents[1]
+            if m.is_darwin():
+                problem_java_prefix = pathlib.Path('/System/Library/Frameworks/JavaVM.framework/Versions')
+                if problem_java_prefix in self.java_home.parents:
+                    res = subprocess.run(['/usr/libexec/java_home', '--failfast', '--arch', m.cpu_family],
+                                         stdout=subprocess.PIPE)
+                    if res.returncode != 0:
+                        msg = 'JAVA_HOME could not be discovered on the system. Please set it explicitly.'
+                        if self.required:
+                            mlog.error(msg)
+                        else:
+                            mlog.debug(msg)
+                        self.is_found = False
+                        return
+                    self.java_home = pathlib.Path(res.stdout.decode().strip())
+
+        platform_include_dir = self.__machine_info_to_platform_include_dir(m)
+        if platform_include_dir is None:
+            mlog.error("Could not find a JDK platform include directory for your OS, please open an issue or provide a pull request.")
+            self.is_found = False
+            return
+
+        java_home_include = self.java_home / 'include'
+        self.compile_args.append(f'-I{java_home_include}')
+        self.compile_args.append(f'-I{java_home_include / platform_include_dir}')
+
+        if modules:
+            if m.is_windows():
+                java_home_lib = self.java_home / 'lib'
+                java_home_lib_server = java_home_lib
+            else:
+                if version_compare(self.version, '<= 1.8.0'):
+                    java_home_lib = self.java_home / 'jre' / 'lib' / self.__cpu_translate(m.cpu_family)
+                else:
+                    java_home_lib = self.java_home / 'lib'
+
+                java_home_lib_server = java_home_lib / 'server'
+
+            if 'jvm' in modules:
+                jvm = self.clib_compiler.find_library('jvm', environment, extra_dirs=[str(java_home_lib_server)])
+                if jvm is None:
+                    mlog.debug('jvm library not found.')
+                    self.is_found = False
+                else:
+                    self.link_args.extend(jvm)
+            if 'awt' in modules:
+                jawt = self.clib_compiler.find_library('jawt', environment, extra_dirs=[str(java_home_lib)])
+                if jawt is None:
+                    mlog.debug('jawt library not found.')
+                    self.is_found = False
+                else:
+                    self.link_args.extend(jawt)
+
+        self.is_found = True
+
+    @staticmethod
+    def __cpu_translate(cpu: str) -> str:
+        '''
+        The JDK and Meson have a disagreement here, so translate it over. In the event more
+        translation needs to be done, add to following dict.
+        '''
+        java_cpus = {
+            'x86_64': 'amd64',
+        }
+
+        return java_cpus.get(cpu, cpu)
+
+    @staticmethod
+    def __machine_info_to_platform_include_dir(m: 'MachineInfo') -> T.Optional[str]:
+        '''Translates the machine information to the platform-dependent include directory
+
+        When inspecting a JDK release tarball or $JAVA_HOME, inside the `include/` directory is a
+        platform-dependent directory that must be on the target's include path in addition to the
+        parent `include/` directory.
+        '''
+        if m.is_linux():
+            return 'linux'
+        elif m.is_windows():
+            return 'win32'
+        elif m.is_darwin():
+            return 'darwin'
+        elif m.is_sunos():
+            return 'solaris'
+        elif m.is_freebsd():
+            return 'freebsd'
+        elif m.is_netbsd():
+            return 'netbsd'
+        elif m.is_openbsd():
+            return 'openbsd'
+        elif m.is_dragonflybsd():
+            return 'dragonfly'
+
+        return None
+
+packages['jni'] = JNISystemDependency
+
+
+class JDKSystemDependency(JNISystemDependency):
+    def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW):
+        super().__init__(environment, kwargs)
+
+        self.feature_since = ('0.59.0', '')
+        self.featurechecks.append(FeatureDeprecated(
+            'jdk system dependency',
+            '0.62.0',
+            'Use the jni system dependency instead'
+        ))
+
+packages['jdk'] = JDKSystemDependency
+
+
+packages['llvm'] = llvm_factory = DependencyFactory(
+    'LLVM',
+    [DependencyMethods.CMAKE, DependencyMethods.CONFIG_TOOL],
+    cmake_class=LLVMDependencyCMake,
+    configtool_class=LLVMDependencyConfigTool,
+)
+
+packages['gtest'] = gtest_factory = DependencyFactory(
+    'gtest',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    pkgconfig_class=GTestDependencyPC,
+    system_class=GTestDependencySystem,
+)
+
+packages['gmock'] = gmock_factory = DependencyFactory(
+    'gmock',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    pkgconfig_class=GMockDependencyPC,
+    system_class=GMockDependencySystem,
+)
+
+packages['zlib'] = zlib_factory = DependencyFactory(
+    'zlib',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM],
+    cmake_name='ZLIB',
+    system_class=ZlibSystemDependency,
+)
diff --git a/devtools/meson/mesonbuild/dependencies/dub.py b/devtools/meson/mesonbuild/dependencies/dub.py
new file mode 100644
index 0000000..37a9ea1
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/dub.py
@@ -0,0 +1,434 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from .base import ExternalDependency, DependencyException, DependencyTypeName
+from .pkgconfig import PkgConfigDependency
+from ..mesonlib import (Popen_safe, OptionKey, join_args, version_compare)
+from ..programs import ExternalProgram
+from .. import mlog
+import re
+import os
+import json
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+
+class DubDependency(ExternalDependency):
+    # dub program and version
+    class_dubbin: T.Optional[T.Tuple[ExternalProgram, str]] = None
+    class_dubbin_searched = False
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(DependencyTypeName('dub'), environment, kwargs, language='d')
+        self.name = name
+        from ..compilers.d import DCompiler, d_feature_args
+
+        _temp_comp = super().get_compiler()
+        assert isinstance(_temp_comp, DCompiler)
+        self.compiler = _temp_comp
+
+        if 'required' in kwargs:
+            self.required = kwargs.get('required')
+
+        if DubDependency.class_dubbin is None and not DubDependency.class_dubbin_searched:
+            DubDependency.class_dubbin = self._check_dub()
+            DubDependency.class_dubbin_searched = True
+        if DubDependency.class_dubbin is None:
+            if self.required:
+                raise DependencyException('DUB not found.')
+            self.is_found = False
+            return
+
+        (self.dubbin, dubver) = DubDependency.class_dubbin
+
+        assert isinstance(self.dubbin, ExternalProgram)
+
+        # Check if Dub version is compatible with Meson
+        if version_compare(dubver, '>1.31.1'):
+            if self.required:
+                raise DependencyException(
+                    f"DUB version {dubver} is not compatible with Meson (can't locate artifacts in Dub cache)")
+            self.is_found = False
+            return
+
+        mlog.debug('Determining dependency {!r} with DUB executable '
+                   '{!r}'.format(name, self.dubbin.get_path()))
+
+        # if an explicit version spec was stated, use this when querying Dub
+        main_pack_spec = name
+        if 'version' in kwargs:
+            version_spec = kwargs['version']
+            if isinstance(version_spec, list):
+                version_spec = " ".join(version_spec)
+            main_pack_spec = f'{name}@{version_spec}'
+
+        # we need to know the target architecture
+        dub_arch = self.compiler.arch
+
+        # we need to know the build type as well
+        dub_buildtype = str(environment.coredata.get_option(OptionKey('buildtype')))
+        # MESON types: choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])),
+        # DUB types: debug (default), plain, release, release-debug, release-nobounds, unittest, profile, profile-gc,
+        # docs, ddox, cov, unittest-cov, syntax and custom
+        if dub_buildtype == 'debugoptimized':
+            dub_buildtype = 'release-debug'
+        elif dub_buildtype == 'minsize':
+            dub_buildtype = 'release'
+
+        # Ask dub for the package
+        describe_cmd = [
+            'describe', main_pack_spec, '--arch=' + dub_arch,
+            '--build=' + dub_buildtype, '--compiler=' + self.compiler.get_exelist()[-1]
+        ]
+        ret, res, err = self._call_dubbin(describe_cmd)
+
+        if ret != 0:
+            mlog.debug('DUB describe failed: ' + err)
+            if 'locally' in err:
+                fetch_cmd = ['dub', 'fetch', main_pack_spec]
+                mlog.error(mlog.bold(main_pack_spec), 'is not present locally. You may try the following command:')
+                mlog.log(mlog.bold(join_args(fetch_cmd)))
+            self.is_found = False
+            return
+
+        # A command that might be useful in case of missing DUB package
+        def dub_build_deep_command() -> str:
+            cmd = [
+                'dub', 'run', 'dub-build-deep', '--yes', '--', main_pack_spec,
+                '--arch=' + dub_arch, '--compiler=' + self.compiler.get_exelist()[-1],
+                '--build=' + dub_buildtype
+            ]
+            return join_args(cmd)
+
+        dub_comp_id = self.compiler.get_id().replace('llvm', 'ldc').replace('gcc', 'gdc')
+        description = json.loads(res)
+
+        self.compile_args = []
+        self.link_args = self.raw_link_args = []
+
+        show_buildtype_warning = False
+
+        def find_package_target(pkg: T.Dict[str, str]) -> bool:
+            nonlocal show_buildtype_warning
+            # try to find a static library in a DUB folder corresponding to
+            # version, configuration, compiler, arch and build-type
+            # if can find, add to link_args.
+            # link_args order is meaningful, so this function MUST be called in the right order
+            pack_id = f'{pkg["name"]}@{pkg["version"]}'
+            (tgt_file, compatibilities) = self._find_compatible_package_target(description, pkg, dub_comp_id)
+            if tgt_file is None:
+                if not compatibilities:
+                    mlog.error(mlog.bold(pack_id), 'not found')
+                elif 'compiler' not in compatibilities:
+                    mlog.error(mlog.bold(pack_id), 'found but not compiled with ', mlog.bold(dub_comp_id))
+                elif dub_comp_id != 'gdc' and 'compiler_version' not in compatibilities:
+                    mlog.error(mlog.bold(pack_id), 'found but not compiled with',
+                               mlog.bold(f'{dub_comp_id}-{self.compiler.version}'))
+                elif 'arch' not in compatibilities:
+                    mlog.error(mlog.bold(pack_id), 'found but not compiled for', mlog.bold(dub_arch))
+                elif 'platform' not in compatibilities:
+                    mlog.error(mlog.bold(pack_id), 'found but not compiled for',
+                               mlog.bold(description['platform'].join('.')))
+                elif 'configuration' not in compatibilities:
+                    mlog.error(mlog.bold(pack_id), 'found but not compiled for the',
+                               mlog.bold(pkg['configuration']), 'configuration')
+                else:
+                    mlog.error(mlog.bold(pack_id), 'not found')
+
+                mlog.log('You may try the following command to install the necessary DUB libraries:')
+                mlog.log(mlog.bold(dub_build_deep_command()))
+
+                return False
+
+            if 'build_type' not in compatibilities:
+                mlog.warning(mlog.bold(pack_id), 'found but not compiled as', mlog.bold(dub_buildtype))
+                show_buildtype_warning = True
+
+            self.link_args.append(tgt_file)
+            return True
+
+        # Main algorithm:
+        # 1. Ensure that the target is a compatible library type (not dynamic)
+        # 2. Find a compatible built library for the main dependency
+        # 3. Do the same for each sub-dependency.
+        #    link_args MUST be in the same order than the "linkDependencies" of the main target
+        # 4. Add other build settings (imports, versions etc.)
+
+        # 1
+        self.is_found = False
+        packages = {}
+        for pkg in description['packages']:
+            packages[pkg['name']] = pkg
+
+            if not pkg['active']:
+                continue
+
+            if pkg['targetType'] == 'dynamicLibrary':
+                mlog.error('DUB dynamic library dependencies are not supported.')
+                self.is_found = False
+                return
+
+            # check that the main dependency is indeed a library
+            if pkg['name'] == name:
+                self.is_found = True
+
+                if pkg['targetType'] not in ['library', 'sourceLibrary', 'staticLibrary']:
+                    mlog.error(mlog.bold(name), "found but it isn't a library")
+                    self.is_found = False
+                    return
+
+                self.version = pkg['version']
+                self.pkg = pkg
+
+        # collect all targets
+        targets = {}
+        for tgt in description['targets']:
+            targets[tgt['rootPackage']] = tgt
+
+        if name not in targets:
+            self.is_found = False
+            if self.pkg['targetType'] == 'sourceLibrary':
+                # source libraries have no associated targets,
+                # but some build settings like import folders must be found from the package object.
+                # Current algo only get these from "buildSettings" in the target object.
+                # Let's save this for a future PR.
+                # (See openssl DUB package for example of sourceLibrary)
+                mlog.error('DUB targets of type', mlog.bold('sourceLibrary'), 'are not supported.')
+            else:
+                mlog.error('Could not find target description for', mlog.bold(main_pack_spec))
+
+        if not self.is_found:
+            mlog.error(f'Could not find {name} in DUB description')
+            return
+
+        # Current impl only supports static libraries
+        self.static = True
+
+        # 2
+        if not find_package_target(self.pkg):
+            self.is_found = False
+            return
+
+        # 3
+        for link_dep in targets[name]['linkDependencies']:
+            pkg = packages[link_dep]
+            if not find_package_target(pkg):
+                self.is_found = False
+                return
+
+        if show_buildtype_warning:
+            mlog.log('If it is not suitable, try the following command and reconfigure Meson with', mlog.bold('--clearcache'))
+            mlog.log(mlog.bold(dub_build_deep_command()))
+
+        # 4
+        bs = targets[name]['buildSettings']
+
+        for flag in bs['dflags']:
+            self.compile_args.append(flag)
+
+        for path in bs['importPaths']:
+            self.compile_args.append('-I' + path)
+
+        for path in bs['stringImportPaths']:
+            if 'import_dir' not in d_feature_args[self.compiler.id]:
+                break
+            flag = d_feature_args[self.compiler.id]['import_dir']
+            self.compile_args.append(f'{flag}={path}')
+
+        for ver in bs['versions']:
+            if 'version' not in d_feature_args[self.compiler.id]:
+                break
+            flag = d_feature_args[self.compiler.id]['version']
+            self.compile_args.append(f'{flag}={ver}')
+
+        if bs['mainSourceFile']:
+            self.compile_args.append(bs['mainSourceFile'])
+
+        # pass static libraries
+        # linkerFiles are added during step 3
+        # for file in bs['linkerFiles']:
+        #     self.link_args.append(file)
+
+        for file in bs['sourceFiles']:
+            # sourceFiles may contain static libraries
+            if file.endswith('.lib') or file.endswith('.a'):
+                self.link_args.append(file)
+
+        for flag in bs['lflags']:
+            self.link_args.append(flag)
+
+        is_windows = self.env.machines.host.is_windows()
+        if is_windows:
+            winlibs = ['kernel32', 'user32', 'gdi32', 'winspool', 'shell32', 'ole32',
+                       'oleaut32', 'uuid', 'comdlg32', 'advapi32', 'ws2_32']
+
+        for lib in bs['libs']:
+            if os.name != 'nt':
+                # trying to add system libraries by pkg-config
+                pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': 'true'})
+                if pkgdep.is_found:
+                    for arg in pkgdep.get_compile_args():
+                        self.compile_args.append(arg)
+                    for arg in pkgdep.get_link_args():
+                        self.link_args.append(arg)
+                    for arg in pkgdep.get_link_args(raw=True):
+                        self.raw_link_args.append(arg)
+                    continue
+
+            if is_windows and lib in winlibs:
+                self.link_args.append(lib + '.lib')
+                continue
+
+            # fallback
+            self.link_args.append('-l'+lib)
+
+    # This function finds the target of the provided JSON package, built for the right
+    # compiler, architecture, configuration...
+    # It returns (target|None, {compatibilities})
+    # If None is returned for target, compatibilities will list what other targets were found without full compatibility
+    def _find_compatible_package_target(self, jdesc: T.Dict[str, str], jpack: T.Dict[str, str], dub_comp_id: str) -> T.Tuple[str, T.Set[str]]:
+        dub_build_path = os.path.join(jpack['path'], '.dub', 'build')
+
+        if not os.path.exists(dub_build_path):
+            return (None, None)
+
+        # try to find a dir like library-debug-linux.posix-x86_64-ldc_2081-EF934983A3319F8F8FF2F0E107A363BA
+
+        # fields are:
+        #  - configuration
+        #  - build type
+        #  - platform
+        #  - architecture
+        #  - compiler id (dmd, ldc, gdc)
+        #  - compiler version or frontend id or frontend version?
+
+        conf = jpack['configuration']
+        build_type = jdesc['buildType']
+        platforms = jdesc['platform']
+        archs = jdesc['architecture']
+
+        # Get D frontend version implemented in the compiler, or the compiler version itself
+        # gdc doesn't support this
+        comp_versions = []
+
+        if dub_comp_id != 'gdc':
+            comp_versions.append(self.compiler.version)
+
+            ret, res = self._call_compbin(['--version'])[0:2]
+            if ret != 0:
+                mlog.error('Failed to run {!r}', mlog.bold(dub_comp_id))
+                return (None, None)
+            d_ver_reg = re.search('v[0-9].[0-9][0-9][0-9].[0-9]', res)  # Ex.: v2.081.2
+
+            if d_ver_reg is not None:
+                frontend_version = d_ver_reg.group()
+                frontend_id = frontend_version.rsplit('.', 1)[0].replace(
+                    'v', '').replace('.', '')  # Fix structure. Ex.: 2081
+                comp_versions.extend([frontend_version, frontend_id])
+
+        compatibilities: T.Set[str] = set()
+
+        # build_type is not in check_list because different build types might be compatible.
+        # We do show a WARNING that the build type is not the same.
+        # It might be critical in release builds, and acceptable otherwise
+        check_list = ('configuration', 'platform', 'arch', 'compiler', 'compiler_version')
+
+        for entry in os.listdir(dub_build_path):
+
+            target = os.path.join(dub_build_path, entry, jpack['targetFileName'])
+            if not os.path.exists(target):
+                # unless Dub and Meson are racing, the target file should be present
+                # when the directory is present
+                mlog.debug("WARNING: Could not find a Dub target: " + target)
+                continue
+
+            # we build a new set for each entry, because if this target is returned
+            # we want to return only the compatibilities associated to this target
+            # otherwise we could miss the WARNING about build_type
+            comps = set()
+
+            if conf in entry:
+                comps.add('configuration')
+
+            if build_type in entry:
+                comps.add('build_type')
+
+            if all(platform in entry for platform in platforms):
+                comps.add('platform')
+
+            if all(arch in entry for arch in archs):
+                comps.add('arch')
+
+            if dub_comp_id in entry:
+                comps.add('compiler')
+
+            if dub_comp_id == 'gdc' or any(cv in entry for cv in comp_versions):
+                comps.add('compiler_version')
+
+            if all(key in comps for key in check_list):
+                return (target, comps)
+            else:
+                compatibilities = set.union(compatibilities, comps)
+
+        return (None, compatibilities)
+
+    def _call_dubbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]:
+        assert isinstance(self.dubbin, ExternalProgram)
+        p, out, err = Popen_safe(self.dubbin.get_command() + args, env=env)
+        return p.returncode, out.strip(), err.strip()
+
+    def _call_compbin(self, args: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]:
+        p, out, err = Popen_safe(self.compiler.get_exelist() + args, env=env)
+        return p.returncode, out.strip(), err.strip()
+
+    def _check_dub(self) -> T.Optional[T.Tuple[ExternalProgram, str]]:
+
+        def find() -> T.Optional[T.Tuple[ExternalProgram, str]]:
+            dubbin = ExternalProgram('dub', silent=True)
+
+            if not dubbin.found():
+                return None
+
+            try:
+                p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2]
+                if p.returncode != 0:
+                    mlog.warning('Found dub {!r} but couldn\'t run it'
+                                 ''.format(' '.join(dubbin.get_command())))
+                    return None
+
+            except (FileNotFoundError, PermissionError):
+                return None
+
+            vermatch = re.search(r'DUB version (\d+\.\d+\.\d+.*), ', out.strip())
+            if vermatch:
+                dubver = vermatch.group(1)
+            else:
+                mlog.warning(f"Found dub {' '.join(dubbin.get_command())} but couldn't parse version in {out.strip()}")
+                return None
+
+            return (dubbin, dubver)
+
+        found = find()
+
+        if found is None:
+            mlog.log('Found DUB:', mlog.red('NO'))
+        else:
+            (dubbin, dubver) = found
+            mlog.log('Found DUB:', mlog.bold(dubbin.get_path()),
+                     '(version %s)' % dubver)
+
+        return found
diff --git a/devtools/meson/mesonbuild/dependencies/factory.py b/devtools/meson/mesonbuild/dependencies/factory.py
new file mode 100644
index 0000000..d50ce0f
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/factory.py
@@ -0,0 +1,156 @@
+# Copyright 2013-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import functools
+import typing as T
+
+from .base import DependencyException, DependencyMethods
+from .base import process_method_kw
+from .base import BuiltinDependency, SystemDependency
+from .cmake import CMakeDependency
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from .base import ExternalDependency
+    from .configtool import ConfigToolDependency
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+
+    DependencyGenerator = T.Callable[[], ExternalDependency]
+    FactoryFunc = T.Callable[
+        [
+            'Environment',
+            MachineChoice,
+            T.Dict[str, T.Any],
+            T.List[DependencyMethods]
+        ],
+        T.List[DependencyGenerator]
+    ]
+
+    WrappedFactoryFunc = T.Callable[
+        [
+            'Environment',
+            MachineChoice,
+            T.Dict[str, T.Any]
+        ],
+        T.List[DependencyGenerator]
+    ]
+
+    # This should be str, Environment, T.Dict[str, T.Any], T.Optional[str]
+    # But if you try that, you get error: Cannot infer type of lambda
+    CmakeDependencyFunc = T.Callable[..., CMakeDependency]
+
+class DependencyFactory:
+
+    """Factory to get dependencies from multiple sources.
+
+    This class provides an initializer that takes a set of names and classes
+    for various kinds of dependencies. When the initialized object is called
+    it returns a list of callables return Dependency objects to try in order.
+
+    :name: The name of the dependency. This will be passed as the name
+        parameter of the each dependency unless it is overridden on a per
+        type basis.
+    :methods: An ordered list of DependencyMethods. This is the order
+        dependencies will be returned in unless they are removed by the
+        _process_method function
+    :*_name: This will overwrite the name passed to the corresponding class.
+        For example, if the name is 'zlib', but cmake calls the dependency
+        'Z', then using `cmake_name='Z'` will pass the name as 'Z' to cmake.
+    :*_class: A *type* or callable that creates a class, and has the
+        signature of an ExternalDependency
+    :system_class: If you pass DependencyMethods.SYSTEM in methods, you must
+        set this argument.
+    """
+
+    def __init__(self, name: str, methods: T.List[DependencyMethods], *,
+                 extra_kwargs: T.Optional[T.Dict[str, T.Any]] = None,
+                 pkgconfig_name: T.Optional[str] = None,
+                 pkgconfig_class: 'T.Type[PkgConfigDependency]' = PkgConfigDependency,
+                 cmake_name: T.Optional[str] = None,
+                 cmake_class: 'T.Union[T.Type[CMakeDependency], CmakeDependencyFunc]' = CMakeDependency,
+                 configtool_class: 'T.Optional[T.Type[ConfigToolDependency]]' = None,
+                 framework_name: T.Optional[str] = None,
+                 framework_class: 'T.Type[ExtraFrameworkDependency]' = ExtraFrameworkDependency,
+                 builtin_class: 'T.Type[BuiltinDependency]' = BuiltinDependency,
+                 system_class: 'T.Type[SystemDependency]' = SystemDependency):
+
+        if DependencyMethods.CONFIG_TOOL in methods and not configtool_class:
+            raise DependencyException('A configtool must have a custom class')
+
+        self.extra_kwargs = extra_kwargs or {}
+        self.methods = methods
+        self.classes: T.Dict[
+            DependencyMethods,
+            T.Callable[['Environment', T.Dict[str, T.Any]], ExternalDependency]
+        ] = {
+            # Just attach the correct name right now, either the generic name
+            # or the method specific name.
+            DependencyMethods.EXTRAFRAMEWORK: functools.partial(framework_class, framework_name or name),
+            DependencyMethods.PKGCONFIG: functools.partial(pkgconfig_class, pkgconfig_name or name),
+            DependencyMethods.CMAKE: functools.partial(cmake_class, cmake_name or name),
+            DependencyMethods.SYSTEM: functools.partial(system_class, name),
+            DependencyMethods.BUILTIN: functools.partial(builtin_class, name),
+            DependencyMethods.CONFIG_TOOL: None,
+        }
+        if configtool_class is not None:
+            self.classes[DependencyMethods.CONFIG_TOOL] = functools.partial(configtool_class, name)
+
+    @staticmethod
+    def _process_method(method: DependencyMethods, env: 'Environment', for_machine: MachineChoice) -> bool:
+        """Report whether a method is valid or not.
+
+        If the method is valid, return true, otherwise return false. This is
+        used in a list comprehension to filter methods that are not possible.
+
+        By default this only remove EXTRAFRAMEWORK dependencies for non-mac platforms.
+        """
+        # Extra frameworks are only valid for macOS and other apple products
+        if (method is DependencyMethods.EXTRAFRAMEWORK and
+                not env.machines[for_machine].is_darwin()):
+            return False
+        return True
+
+    def __call__(self, env: 'Environment', for_machine: MachineChoice,
+                 kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
+        """Return a list of Dependencies with the arguments already attached."""
+        methods = process_method_kw(self.methods, kwargs)
+        nwargs = self.extra_kwargs.copy()
+        nwargs.update(kwargs)
+
+        return [functools.partial(self.classes[m], env, nwargs) for m in methods
+                if self._process_method(m, env, for_machine)]
+
+
+def factory_methods(methods: T.Set[DependencyMethods]) -> T.Callable[['FactoryFunc'], 'WrappedFactoryFunc']:
+    """Decorator for handling methods for dependency factory functions.
+
+    This helps to make factory functions self documenting
+    >>> @factory_methods([DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE])
+    >>> def factory(env: Environment, for_machine: MachineChoice, kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    >>>     pass
+    """
+
+    def inner(func: 'FactoryFunc') -> 'WrappedFactoryFunc':
+
+        @functools.wraps(func)
+        def wrapped(env: 'Environment', for_machine: MachineChoice, kwargs: T.Dict[str, T.Any]) -> T.List['DependencyGenerator']:
+            return func(env, for_machine, kwargs, process_method_kw(methods, kwargs))
+
+        return wrapped
+
+    return inner
diff --git a/devtools/meson/mesonbuild/dependencies/framework.py b/devtools/meson/mesonbuild/dependencies/framework.py
new file mode 100644
index 0000000..b02b3ce
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/framework.py
@@ -0,0 +1,121 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from .base import DependencyTypeName, ExternalDependency, DependencyException
+from ..mesonlib import MesonException, Version, stringlistify
+from .. import mlog
+from pathlib import Path
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class ExtraFrameworkDependency(ExternalDependency):
+    system_framework_paths: T.Optional[T.List[str]] = None
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        paths = stringlistify(kwargs.get('paths', []))
+        super().__init__(DependencyTypeName('extraframeworks'), env, kwargs, language=language)
+        self.name = name
+        # Full path to framework directory
+        self.framework_path: T.Optional[str] = None
+        if not self.clib_compiler:
+            raise DependencyException('No C-like compilers are available')
+        if self.system_framework_paths is None:
+            try:
+                self.system_framework_paths = self.clib_compiler.find_framework_paths(self.env)
+            except MesonException as e:
+                if 'non-clang' in str(e):
+                    # Apple frameworks can only be found (and used) with the
+                    # system compiler. It is not available so bail immediately.
+                    self.is_found = False
+                    return
+                raise
+        self.detect(name, paths)
+
+    def detect(self, name: str, paths: T.List[str]) -> None:
+        if not paths:
+            paths = self.system_framework_paths
+        for p in paths:
+            mlog.debug(f'Looking for framework {name} in {p}')
+            # We need to know the exact framework path because it's used by the
+            # Qt5 dependency class, and for setting the include path. We also
+            # want to avoid searching in an invalid framework path which wastes
+            # time and can cause a false positive.
+            framework_path = self._get_framework_path(p, name)
+            if framework_path is None:
+                continue
+            # We want to prefer the specified paths (in order) over the system
+            # paths since these are "extra" frameworks.
+            # For example, Python2's framework is in /System/Library/Frameworks and
+            # Python3's framework is in /Library/Frameworks, but both are called
+            # Python.framework. We need to know for sure that the framework was
+            # found in the path we expect.
+            allow_system = p in self.system_framework_paths
+            args = self.clib_compiler.find_framework(name, self.env, [p], allow_system)
+            if args is None:
+                continue
+            self.link_args = args
+            self.framework_path = framework_path.as_posix()
+            self.compile_args = ['-F' + self.framework_path]
+            # We need to also add -I includes to the framework because all
+            # cross-platform projects such as OpenGL, Python, Qt, GStreamer,
+            # etc do not use "framework includes":
+            # https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/IncludingFrameworks.html
+            incdir = self._get_framework_include_path(framework_path)
+            if incdir:
+                self.compile_args += ['-I' + incdir]
+            self.is_found = True
+            return
+
+    def _get_framework_path(self, path: str, name: str) -> T.Optional[Path]:
+        p = Path(path)
+        lname = name.lower()
+        for d in p.glob('*.framework/'):
+            if lname == d.name.rsplit('.', 1)[0].lower():
+                return d
+        return None
+
+    def _get_framework_latest_version(self, path: Path) -> str:
+        versions = []
+        for each in path.glob('Versions/*'):
+            # macOS filesystems are usually case-insensitive
+            if each.name.lower() == 'current':
+                continue
+            versions.append(Version(each.name))
+        if len(versions) == 0:
+            # most system frameworks do not have a 'Versions' directory
+            return 'Headers'
+        return 'Versions/{}/Headers'.format(sorted(versions)[-1]._s)
+
+    def _get_framework_include_path(self, path: Path) -> T.Optional[str]:
+        # According to the spec, 'Headers' must always be a symlink to the
+        # Headers directory inside the currently-selected version of the
+        # framework, but sometimes frameworks are broken. Look in 'Versions'
+        # for the currently-selected version or pick the latest one.
+        trials = ('Headers', 'Versions/Current/Headers',
+                  self._get_framework_latest_version(path))
+        for each in trials:
+            trial = path / each
+            if trial.is_dir():
+                return trial.as_posix()
+        return None
+
+    def log_info(self) -> str:
+        return self.framework_path or ''
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'framework'
diff --git a/devtools/meson/mesonbuild/dependencies/hdf5.py b/devtools/meson/mesonbuild/dependencies/hdf5.py
new file mode 100644
index 0000000..392bb09
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/hdf5.py
@@ -0,0 +1,183 @@
+# Copyright 2013-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file contains the detection logic for miscellaneous external dependencies.
+from __future__ import annotations
+
+import functools
+import os
+import re
+import subprocess
+from pathlib import Path
+
+from ..mesonlib import Popen_safe, OrderedSet, join_args
+from ..programs import ExternalProgram
+from .base import DependencyException, DependencyMethods
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .pkgconfig import PkgConfigDependency
+from .factory import factory_methods
+import typing as T
+
+if T.TYPE_CHECKING:
+    from .factory import DependencyGenerator
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+
+
+class HDF5PkgConfigDependency(PkgConfigDependency):
+
+    """Handle brokenness in the HDF5 pkg-config files."""
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        language = language or 'c'
+        if language not in {'c', 'cpp', 'fortran'}:
+            raise DependencyException(f'Language {language} is not supported with HDF5.')
+
+        super().__init__(name, environment, kwargs, language)
+        if not self.is_found:
+            return
+
+        # some broken pkgconfig don't actually list the full path to the needed includes
+        newinc = []  # type: T.List[str]
+        for arg in self.compile_args:
+            if arg.startswith('-I'):
+                stem = 'static' if self.static else 'shared'
+                if (Path(arg[2:]) / stem).is_dir():
+                    newinc.append('-I' + str(Path(arg[2:]) / stem))
+        self.compile_args += newinc
+
+        link_args = []  # type: T.List[str]
+        for larg in self.get_link_args():
+            lpath = Path(larg)
+            # some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries,
+            # so let's add them if they exist
+            # additionally, some pkgconfig HDF5 HL files are malformed so let's be sure to find HL anyway
+            if lpath.is_file():
+                hl = []
+                if language == 'cpp':
+                    hl += ['_hl_cpp', '_cpp']
+                elif language == 'fortran':
+                    hl += ['_hl_fortran', 'hl_fortran', '_fortran']
+                hl += ['_hl']  # C HL library, always needed
+
+                suffix = '.' + lpath.name.split('.', 1)[1]  # in case of .dll.a
+                for h in hl:
+                    hlfn = lpath.parent / (lpath.name.split('.', 1)[0] + h + suffix)
+                    if hlfn.is_file():
+                        link_args.append(str(hlfn))
+                # HDF5 C libs are required by other HDF5 languages
+                link_args.append(larg)
+            else:
+                link_args.append(larg)
+
+        self.link_args = link_args
+
+
+class HDF5ConfigToolDependency(ConfigToolDependency):
+
+    """Wrapper around hdf5 binary config tools."""
+
+    version_arg = '-showconfig'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        language = language or 'c'
+        if language not in {'c', 'cpp', 'fortran'}:
+            raise DependencyException(f'Language {language} is not supported with HDF5.')
+
+        if language == 'c':
+            cenv = 'CC'
+            tools = ['h5cc', 'h5pcc']
+        elif language == 'cpp':
+            cenv = 'CXX'
+            tools = ['h5c++', 'h5pc++']
+        elif language == 'fortran':
+            cenv = 'FC'
+            tools = ['h5fc', 'h5pfc']
+        else:
+            raise DependencyException('How did you get here?')
+
+        # We need this before we call super()
+        for_machine = self.get_for_machine_from_kwargs(kwargs)
+
+        nkwargs = kwargs.copy()
+        nkwargs['tools'] = tools
+
+        # Override the compiler that the config tools are going to use by
+        # setting the environment variables that they use for the compiler and
+        # linkers.
+        compiler = environment.coredata.compilers[for_machine][language]
+        try:
+            os.environ[f'HDF5_{cenv}'] = join_args(compiler.get_exelist())
+            os.environ[f'HDF5_{cenv}LINKER'] = join_args(compiler.get_linker_exelist())
+            super().__init__(name, environment, nkwargs, language)
+        finally:
+            del os.environ[f'HDF5_{cenv}']
+            del os.environ[f'HDF5_{cenv}LINKER']
+        if not self.is_found:
+            return
+
+        # We first need to call the tool with -c to get the compile arguments
+        # and then without -c to get the link arguments.
+        args = self.get_config_value(['-show', '-c'], 'args')[1:]
+        args += self.get_config_value(['-show', '-noshlib' if self.static else '-shlib'], 'args')[1:]
+        for arg in args:
+            if arg.startswith(('-I', '-f', '-D')) or arg == '-pthread':
+                self.compile_args.append(arg)
+            elif arg.startswith(('-L', '-l', '-Wl')):
+                self.link_args.append(arg)
+            elif Path(arg).is_file():
+                self.link_args.append(arg)
+
+        # If the language is not C we need to add C as a subdependency
+        if language != 'c':
+            nkwargs = kwargs.copy()
+            nkwargs['language'] = 'c'
+            # I'm being too clever for mypy and pylint
+            self.is_found = self._add_sub_dependency(hdf5_factory(environment, for_machine, nkwargs))  # pylint: disable=no-value-for-parameter
+
+    def _sanitize_version(self, ver: str) -> str:
+        v = re.search(r'\s*HDF5 Version: (\d+\.\d+\.\d+)', ver)
+        return v.group(1)
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL})
+def hdf5_factory(env: 'Environment', for_machine: 'MachineChoice',
+                 kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    language = kwargs.get('language')
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        # Use an ordered set so that these remain the first tried pkg-config files
+        pkgconfig_files = OrderedSet(['hdf5', 'hdf5-serial'])
+        PCEXE = PkgConfigDependency._detect_pkgbin(False, env, for_machine)
+        pcenv = PkgConfigDependency.setup_env(os.environ, env, for_machine)
+        if PCEXE:
+            assert isinstance(PCEXE, ExternalProgram)
+            # some distros put hdf5-1.2.3.pc with version number in .pc filename.
+            ret, stdout, _ = Popen_safe(PCEXE.get_command() + ['--list-all'], stderr=subprocess.DEVNULL, env=pcenv)
+            if ret.returncode == 0:
+                for pkg in stdout.split('\n'):
+                    if pkg.startswith('hdf5'):
+                        pkgconfig_files.add(pkg.split(' ', 1)[0])
+
+        for pkg in pkgconfig_files:
+            candidates.append(functools.partial(HDF5PkgConfigDependency, pkg, env, kwargs, language))
+
+    if DependencyMethods.CONFIG_TOOL in methods:
+        candidates.append(functools.partial(HDF5ConfigToolDependency, 'hdf5', env, kwargs, language))
+
+    return candidates
+
+packages['hdf5'] = hdf5_factory
diff --git a/devtools/meson/mesonbuild/dependencies/misc.py b/devtools/meson/mesonbuild/dependencies/misc.py
new file mode 100644
index 0000000..b2df208
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/misc.py
@@ -0,0 +1,619 @@
+# Copyright 2013-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file contains the detection logic for miscellaneous external dependencies.
+from __future__ import annotations
+
+import functools
+import re
+import typing as T
+
+from .. import mesonlib
+from .. import mlog
+from .base import DependencyException, DependencyMethods
+from .base import BuiltinDependency, SystemDependency
+from .cmake import CMakeDependency, CMakeDependencyFactory
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .factory import DependencyFactory, factory_methods
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment, MachineChoice
+    from .factory import DependencyGenerator
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
+def netcdf_factory(env: 'Environment',
+                   for_machine: 'MachineChoice',
+                   kwargs: T.Dict[str, T.Any],
+                   methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    language = kwargs.get('language', 'c')
+    if language not in ('c', 'cpp', 'fortran'):
+        raise DependencyException(f'Language {language} is not supported with NetCDF.')
+
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        if language == 'fortran':
+            pkg = 'netcdf-fortran'
+        else:
+            pkg = 'netcdf'
+
+        candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs, language=language))
+
+    if DependencyMethods.CMAKE in methods:
+        candidates.append(functools.partial(CMakeDependency, 'NetCDF', env, kwargs, language=language))
+
+    return candidates
+
+packages['netcdf'] = netcdf_factory
+
+
+class DlBuiltinDependency(BuiltinDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`")
+
+        if self.clib_compiler.has_function('dlopen', '#include ', env)[0]:
+            self.is_found = True
+
+
+class DlSystemDependency(SystemDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`")
+
+        h = self.clib_compiler.has_header('dlfcn.h', '', env)
+        self.link_args = self.clib_compiler.find_library('dl', env, [], self.libtype)
+
+        if h[0] and self.link_args:
+            self.is_found = True
+
+
+class OpenMPDependency(SystemDependency):
+    # Map date of specification release (which is the macro value) to a version.
+    VERSIONS = {
+        '202111': '5.2',
+        '202011': '5.1',
+        '201811': '5.0',
+        '201611': '5.0-revision1',  # This is supported by ICC 19.x
+        '201511': '4.5',
+        '201307': '4.0',
+        '201107': '3.1',
+        '200805': '3.0',
+        '200505': '2.5',
+        '200203': '2.0',
+        '199810': '1.0',
+    }
+
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        language = kwargs.get('language')
+        super().__init__('openmp', environment, kwargs, language=language)
+        self.is_found = False
+        if self.clib_compiler.get_id() == 'nagfor':
+            # No macro defined for OpenMP, but OpenMP 3.1 is supported.
+            self.version = '3.1'
+            self.is_found = True
+            self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+            return
+        if self.clib_compiler.get_id() == 'pgi':
+            # through at least PGI 19.4, there is no macro defined for OpenMP, but OpenMP 3.1 is supported.
+            self.version = '3.1'
+            self.is_found = True
+            self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+            return
+        try:
+            openmp_date = self.clib_compiler.get_define(
+                '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0]
+        except mesonlib.EnvironmentException as e:
+            mlog.debug('OpenMP support not available in the compiler')
+            mlog.debug(e)
+            openmp_date = None
+
+        if openmp_date:
+            try:
+                self.version = self.VERSIONS[openmp_date]
+            except KeyError:
+                mlog.debug(f'Could not find an OpenMP version matching {openmp_date}')
+                if openmp_date == '_OPENMP':
+                    mlog.debug('This can be caused by flags such as gcc\'s `-fdirectives-only`, which affect preprocessor behavior.')
+                return
+            # Flang has omp_lib.h
+            header_names = ('omp.h', 'omp_lib.h')
+            for name in header_names:
+                if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]:
+                    self.is_found = True
+                    self.compile_args = self.clib_compiler.openmp_flags()
+                    self.link_args = self.clib_compiler.openmp_link_flags()
+                    break
+            if not self.is_found:
+                mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
+
+packages['openmp'] = OpenMPDependency
+
+
+class ThreadDependency(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs)
+        self.is_found = True
+        # Happens if you are using a language with threads
+        # concept without C, such as plain Cuda.
+        if not self.clib_compiler:
+            self.compile_args = []
+            self.link_args = []
+        else:
+            self.compile_args = self.clib_compiler.thread_flags(environment)
+            self.link_args = self.clib_compiler.thread_link_flags(environment)
+
+
+class BlocksDependency(SystemDependency):
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('blocks', environment, kwargs)
+        self.name = 'blocks'
+        self.is_found = False
+
+        if self.env.machines[self.for_machine].is_darwin():
+            self.compile_args = []
+            self.link_args = []
+        else:
+            self.compile_args = ['-fblocks']
+            self.link_args = ['-lBlocksRuntime']
+
+            if not self.clib_compiler.has_header('Block.h', '', environment, disable_cache=True) or \
+               not self.clib_compiler.find_library('BlocksRuntime', environment, []):
+                mlog.log(mlog.red('ERROR:'), 'BlocksRuntime not found.')
+                return
+
+        source = '''
+            int main(int argc, char **argv)
+            {
+                int (^callback)(void) = ^ int (void) { return 0; };
+                return callback();
+            }'''
+
+        with self.clib_compiler.compile(source, extra_args=self.compile_args + self.link_args) as p:
+            if p.returncode != 0:
+                mlog.log(mlog.red('ERROR:'), 'Compiler does not support blocks extension.')
+                return
+
+            self.is_found = True
+
+packages['blocks'] = BlocksDependency
+
+
+class PcapDependencyConfigTool(ConfigToolDependency):
+
+    tools = ['pcap-config']
+    tool_name = 'pcap-config'
+
+    # version 1.10.2 added error checking for invalid arguments
+    # version 1.10.3 will hopefully add actual support for --version
+    skip_version = '--help'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+        if self.version is None:
+            # older pcap-config versions don't support this
+            self.version = self.get_pcap_lib_version()
+
+    def get_pcap_lib_version(self) -> T.Optional[str]:
+        # Since we seem to need to run a program to discover the pcap version,
+        # we can't do that when cross-compiling
+        # FIXME: this should be handled if we have an exe_wrapper
+        if not self.env.machines.matches_build_machine(self.for_machine):
+            return None
+
+        v = self.clib_compiler.get_return_value('pcap_lib_version', 'string',
+                                                '#include ', self.env, [], [self])
+        v = re.sub(r'libpcap version ', '', str(v))
+        v = re.sub(r' -- Apple version.*$', '', v)
+        return v
+
+
+class CupsDependencyConfigTool(ConfigToolDependency):
+
+    tools = ['cups-config']
+    tool_name = 'cups-config'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--ldflags', '--libs'], 'link_args')
+
+
+class LibWmfDependencyConfigTool(ConfigToolDependency):
+
+    tools = ['libwmf-config']
+    tool_name = 'libwmf-config'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+
+
+class LibGCryptDependencyConfigTool(ConfigToolDependency):
+
+    tools = ['libgcrypt-config']
+    tool_name = 'libgcrypt-config'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+        self.version = self.get_config_value(['--version'], 'version')[0]
+
+
+class GpgmeDependencyConfigTool(ConfigToolDependency):
+
+    tools = ['gpgme-config']
+    tool_name = 'gpg-config'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+        self.version = self.get_config_value(['--version'], 'version')[0]
+
+
+class ShadercDependency(SystemDependency):
+
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__('shaderc', environment, kwargs)
+
+        static_lib = 'shaderc_combined'
+        shared_lib = 'shaderc_shared'
+
+        libs = [shared_lib, static_lib]
+        if self.static:
+            libs.reverse()
+
+        cc = self.get_compiler()
+
+        for lib in libs:
+            self.link_args = cc.find_library(lib, environment, [])
+            if self.link_args is not None:
+                self.is_found = True
+
+                if self.static and lib != static_lib:
+                    mlog.warning(f'Static library {static_lib!r} not found for dependency '
+                                 f'{self.name!r}, may not be statically linked')
+
+                break
+
+
+class CursesConfigToolDependency(ConfigToolDependency):
+
+    """Use the curses config tools."""
+
+    tool = 'curses-config'
+    # ncurses5.4-config is for macOS Catalina
+    tools = ['ncursesw6-config', 'ncursesw5-config', 'ncurses6-config', 'ncurses5-config', 'ncurses5.4-config']
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+
+
+class CursesSystemDependency(SystemDependency):
+
+    """Curses dependency the hard way.
+
+    This replaces hand rolled find_library() and has_header() calls. We
+    provide this for portability reasons, there are a large number of curses
+    implementations, and the differences between them can be very annoying.
+    """
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+
+        candidates = [
+            ('pdcurses', ['pdcurses/curses.h']),
+            ('ncursesw',  ['ncursesw/ncurses.h', 'ncurses.h']),
+            ('ncurses',  ['ncurses/ncurses.h', 'ncurses/curses.h', 'ncurses.h']),
+            ('curses',  ['curses.h']),
+        ]
+
+        # Not sure how else to elegantly break out of both loops
+        for lib, headers in candidates:
+            l = self.clib_compiler.find_library(lib, env, [])
+            if l:
+                for header in headers:
+                    h = self.clib_compiler.has_header(header, '', env)
+                    if h[0]:
+                        self.is_found = True
+                        self.link_args = l
+                        # Not sure how to find version for non-ncurses curses
+                        # implementations. The one in illumos/OpenIndiana
+                        # doesn't seem to have a version defined in the header.
+                        if lib.startswith('ncurses'):
+                            v, _ = self.clib_compiler.get_define('NCURSES_VERSION', f'#include <{header}>', env, [], [self])
+                            self.version = v.strip('"')
+                        if lib.startswith('pdcurses'):
+                            v_major, _ = self.clib_compiler.get_define('PDC_VER_MAJOR', f'#include <{header}>', env, [], [self])
+                            v_minor, _ = self.clib_compiler.get_define('PDC_VER_MINOR', f'#include <{header}>', env, [], [self])
+                            self.version = f'{v_major}.{v_minor}'
+
+                        # Check the version if possible, emit a warning if we can't
+                        req = kwargs.get('version')
+                        if req:
+                            if self.version:
+                                self.is_found = mesonlib.version_compare(self.version, req)
+                            else:
+                                mlog.warning('Cannot determine version of curses to compare against.')
+
+                        if self.is_found:
+                            mlog.debug('Curses library:', l)
+                            mlog.debug('Curses header:', header)
+                            break
+            if self.is_found:
+                break
+
+
+class IconvBuiltinDependency(BuiltinDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without `find_library('iconv')`")
+        code = '''#include \n\nint main() {\n    iconv_open("","");\n}''' # [ignore encoding] this is C, not python, Mr. Lint
+
+        if self.clib_compiler.links(code, env)[0]:
+            self.is_found = True
+
+
+class IconvSystemDependency(SystemDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without find_library('iconv')")
+
+        h = self.clib_compiler.has_header('iconv.h', '', env)
+        self.link_args = self.clib_compiler.find_library('iconv', env, [], self.libtype)
+
+        if h[0] and self.link_args:
+            self.is_found = True
+
+
+class IntlBuiltinDependency(BuiltinDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`")
+        code = '''#include \n\nint main() {\n    gettext("Hello world");\n}'''
+
+        if self.clib_compiler.links(code, env)[0]:
+            self.is_found = True
+
+
+class IntlSystemDependency(SystemDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`")
+
+        h = self.clib_compiler.has_header('libintl.h', '', env)
+        self.link_args = self.clib_compiler.find_library('intl', env, [], self.libtype)
+
+        if h[0] and self.link_args:
+            self.is_found = True
+
+            if self.static:
+                if not self._add_sub_dependency(iconv_factory(env, self.for_machine, {'static': True})):
+                    self.is_found = False
+                    return
+
+
+class OpensslSystemDependency(SystemDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+
+        dependency_kwargs = {
+            'method': 'system',
+            'static': self.static,
+        }
+        if not self.clib_compiler.has_header('openssl/ssl.h', '', env)[0]:
+            return
+
+        # openssl >= 3 only
+        self.version = self.clib_compiler.get_define('OPENSSL_VERSION_STR', '#include ', env, [], [self])[0]
+        # openssl < 3 only
+        if not self.version:
+            version_hex = self.clib_compiler.get_define('OPENSSL_VERSION_NUMBER', '#include ', env, [], [self])[0]
+            if not version_hex:
+                return
+            version_hex = version_hex.rstrip('L')
+            version_ints = [((int(version_hex.rstrip('L'), 16) >> 4 + i) & 0xFF) for i in (24, 16, 8, 0)]
+            # since this is openssl, the format is 1.2.3a in four parts
+            self.version = '.'.join(str(i) for i in version_ints[:3]) + chr(ord('a') + version_ints[3] - 1)
+
+        if name == 'openssl':
+            if self._add_sub_dependency(libssl_factory(env, self.for_machine, dependency_kwargs)) and \
+                    self._add_sub_dependency(libcrypto_factory(env, self.for_machine, dependency_kwargs)):
+                self.is_found = True
+            return
+        else:
+            self.link_args = self.clib_compiler.find_library(name.lstrip('lib'), env, [], self.libtype)
+            if not self.link_args:
+                return
+
+        if not self.static:
+            self.is_found = True
+        else:
+            if name == 'libssl':
+                if self._add_sub_dependency(libcrypto_factory(env, self.for_machine, dependency_kwargs)):
+                    self.is_found = True
+            elif name == 'libcrypto':
+                use_threads = self.clib_compiler.has_header_symbol('openssl/opensslconf.h', 'OPENSSL_THREADS', '', env, dependencies=[self])[0]
+                if not use_threads or self._add_sub_dependency(threads_factory(env, self.for_machine, {})):
+                    self.is_found = True
+                # only relevant on platforms where it is distributed with the libc, in which case it always succeeds
+                sublib = self.clib_compiler.find_library('dl', env, [], self.libtype)
+                if sublib:
+                    self.link_args.extend(sublib)
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM})
+def curses_factory(env: 'Environment',
+                   for_machine: 'MachineChoice',
+                   kwargs: T.Dict[str, T.Any],
+                   methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        pkgconfig_files = ['pdcurses', 'ncursesw', 'ncurses', 'curses']
+        for pkg in pkgconfig_files:
+            candidates.append(functools.partial(PkgConfigDependency, pkg, env, kwargs))
+
+    # There are path handling problems with these methods on msys, and they
+    # don't apply to windows otherwise (cygwin is handled separately from
+    # windows)
+    if not env.machines[for_machine].is_windows():
+        if DependencyMethods.CONFIG_TOOL in methods:
+            candidates.append(functools.partial(CursesConfigToolDependency, 'curses', env, kwargs))
+
+        if DependencyMethods.SYSTEM in methods:
+            candidates.append(functools.partial(CursesSystemDependency, 'curses', env, kwargs))
+
+    return candidates
+packages['curses'] = curses_factory
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM})
+def shaderc_factory(env: 'Environment',
+                    for_machine: 'MachineChoice',
+                    kwargs: T.Dict[str, T.Any],
+                    methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    """Custom DependencyFactory for ShaderC.
+
+    ShaderC's odd you get three different libraries from the same build
+    thing are just easier to represent as a separate function than
+    twisting DependencyFactory even more.
+    """
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        # ShaderC packages their shared and static libs together
+        # and provides different pkg-config files for each one. We
+        # smooth over this difference by handling the static
+        # keyword before handing off to the pkg-config handler.
+        shared_libs = ['shaderc']
+        static_libs = ['shaderc_combined', 'shaderc_static']
+
+        if kwargs.get('static', env.coredata.get_option(mesonlib.OptionKey('prefer_static'))):
+            c = [functools.partial(PkgConfigDependency, name, env, kwargs)
+                 for name in static_libs + shared_libs]
+        else:
+            c = [functools.partial(PkgConfigDependency, name, env, kwargs)
+                 for name in shared_libs + static_libs]
+        candidates.extend(c)
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(ShadercDependency, env, kwargs))
+
+    return candidates
+packages['shaderc'] = shaderc_factory
+
+
+packages['cups'] = cups_factory = DependencyFactory(
+    'cups',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE],
+    configtool_class=CupsDependencyConfigTool,
+    cmake_name='Cups',
+)
+
+packages['dl'] = dl_factory = DependencyFactory(
+    'dl',
+    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
+    builtin_class=DlBuiltinDependency,
+    system_class=DlSystemDependency,
+)
+
+packages['gpgme'] = gpgme_factory = DependencyFactory(
+    'gpgme',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=GpgmeDependencyConfigTool,
+)
+
+packages['libgcrypt'] = libgcrypt_factory = DependencyFactory(
+    'libgcrypt',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=LibGCryptDependencyConfigTool,
+)
+
+packages['libwmf'] = libwmf_factory = DependencyFactory(
+    'libwmf',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=LibWmfDependencyConfigTool,
+)
+
+packages['pcap'] = pcap_factory = DependencyFactory(
+    'pcap',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    configtool_class=PcapDependencyConfigTool,
+    pkgconfig_name='libpcap',
+)
+
+packages['threads'] = threads_factory = DependencyFactory(
+    'threads',
+    [DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
+    cmake_name='Threads',
+    system_class=ThreadDependency,
+)
+
+packages['iconv'] = iconv_factory = DependencyFactory(
+    'iconv',
+    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
+    builtin_class=IconvBuiltinDependency,
+    system_class=IconvSystemDependency,
+)
+
+packages['intl'] = intl_factory = DependencyFactory(
+    'intl',
+    [DependencyMethods.BUILTIN, DependencyMethods.SYSTEM],
+    builtin_class=IntlBuiltinDependency,
+    system_class=IntlSystemDependency,
+)
+
+packages['openssl'] = openssl_factory = DependencyFactory(
+    'openssl',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
+    system_class=OpensslSystemDependency,
+    cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::Crypto', 'OpenSSL::SSL']),
+)
+
+packages['libcrypto'] = libcrypto_factory = DependencyFactory(
+    'libcrypto',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
+    system_class=OpensslSystemDependency,
+    cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::Crypto']),
+)
+
+packages['libssl'] = libssl_factory = DependencyFactory(
+    'libssl',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE],
+    system_class=OpensslSystemDependency,
+    cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::SSL']),
+)
diff --git a/devtools/meson/mesonbuild/dependencies/mpi.py b/devtools/meson/mesonbuild/dependencies/mpi.py
new file mode 100644
index 0000000..9100681
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/mpi.py
@@ -0,0 +1,240 @@
+# Copyright 2013-2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import functools
+import typing as T
+import os
+import re
+
+from ..environment import detect_cpu_family
+from .base import DependencyMethods, detect_compiler, SystemDependency
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .factory import factory_methods
+from .pkgconfig import PkgConfigDependency
+
+if T.TYPE_CHECKING:
+    from .factory import DependencyGenerator
+    from ..environment import Environment, MachineChoice
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM})
+def mpi_factory(env: 'Environment',
+                for_machine: 'MachineChoice',
+                kwargs: T.Dict[str, T.Any],
+                methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    language = kwargs.get('language', 'c')
+    if language not in {'c', 'cpp', 'fortran'}:
+        # OpenMPI doesn't work without any other languages
+        return []
+
+    candidates: T.List['DependencyGenerator'] = []
+    compiler = detect_compiler('mpi', env, for_machine, language)
+    if not compiler:
+        return []
+    compiler_is_intel = compiler.get_id() in {'intel', 'intel-cl'}
+
+    # Only OpenMPI has pkg-config, and it doesn't work with the intel compilers
+    if DependencyMethods.PKGCONFIG in methods and not compiler_is_intel:
+        pkg_name = None
+        if language == 'c':
+            pkg_name = 'ompi-c'
+        elif language == 'cpp':
+            pkg_name = 'ompi-cxx'
+        elif language == 'fortran':
+            pkg_name = 'ompi-fort'
+        candidates.append(functools.partial(
+            PkgConfigDependency, pkg_name, env, kwargs, language=language))
+
+    if DependencyMethods.CONFIG_TOOL in methods:
+        nwargs = kwargs.copy()
+
+        if compiler_is_intel:
+            if env.machines[for_machine].is_windows():
+                nwargs['version_arg'] = '-v'
+                nwargs['returncode_value'] = 3
+
+            if language == 'c':
+                tool_names = [os.environ.get('I_MPI_CC'), 'mpiicc']
+            elif language == 'cpp':
+                tool_names = [os.environ.get('I_MPI_CXX'), 'mpiicpc']
+            elif language == 'fortran':
+                tool_names = [os.environ.get('I_MPI_F90'), 'mpiifort']
+
+            cls = IntelMPIConfigToolDependency  # type: T.Type[ConfigToolDependency]
+        else: # OpenMPI, which doesn't work with intel
+            #
+            # We try the environment variables for the tools first, but then
+            # fall back to the hardcoded names
+            if language == 'c':
+                tool_names = [os.environ.get('MPICC'), 'mpicc']
+            elif language == 'cpp':
+                tool_names = [os.environ.get('MPICXX'), 'mpic++', 'mpicxx', 'mpiCC']
+            elif language == 'fortran':
+                tool_names = [os.environ.get(e) for e in ['MPIFC', 'MPIF90', 'MPIF77']]
+                tool_names.extend(['mpifort', 'mpif90', 'mpif77'])
+
+            cls = OpenMPIConfigToolDependency
+
+        tool_names = [t for t in tool_names if t]  # remove empty environment variables
+        assert tool_names
+
+        nwargs['tools'] = tool_names
+        candidates.append(functools.partial(
+            cls, tool_names[0], env, nwargs, language=language))
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(
+            MSMPIDependency, 'msmpi', env, kwargs, language=language))
+
+    return candidates
+
+packages['mpi'] = mpi_factory
+
+
+class _MPIConfigToolDependency(ConfigToolDependency):
+
+    def _filter_compile_args(self, args: T.List[str]) -> T.List[str]:
+        """
+        MPI wrappers return a bunch of garbage args.
+        Drop -O2 and everything that is not needed.
+        """
+        result = []
+        multi_args: T.Tuple[str, ...] = ('-I', )
+        if self.language == 'fortran':
+            fc = self.env.coredata.compilers[self.for_machine]['fortran']
+            multi_args += fc.get_module_incdir_args()
+
+        include_next = False
+        for f in args:
+            if f.startswith(('-D', '-f') + multi_args) or f == '-pthread' \
+                    or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
+                result.append(f)
+                if f in multi_args:
+                    # Path is a separate argument.
+                    include_next = True
+            elif include_next:
+                include_next = False
+                result.append(f)
+        return result
+
+    def _filter_link_args(self, args: T.List[str]) -> T.List[str]:
+        """
+        MPI wrappers return a bunch of garbage args.
+        Drop -O2 and everything that is not needed.
+        """
+        result = []
+        include_next = False
+        for f in args:
+            if self._is_link_arg(f):
+                result.append(f)
+                if f in {'-L', '-Xlinker'}:
+                    include_next = True
+            elif include_next:
+                include_next = False
+                result.append(f)
+        return result
+
+    def _is_link_arg(self, f: str) -> bool:
+        if self.clib_compiler.id == 'intel-cl':
+            return f == '/link' or f.startswith('/LIBPATH') or f.endswith('.lib')   # always .lib whether static or dynamic
+        else:
+            return (f.startswith(('-L', '-l', '-Xlinker')) or
+                    f == '-pthread' or
+                    (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')))
+
+
+class IntelMPIConfigToolDependency(_MPIConfigToolDependency):
+
+    """Wrapper around Intel's mpiicc and friends."""
+
+    version_arg = '-v'  # --version is not the same as -v
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        if not self.is_found:
+            return
+
+        args = self.get_config_value(['-show'], 'link and compile args')
+        self.compile_args = self._filter_compile_args(args)
+        self.link_args = self._filter_link_args(args)
+
+    def _sanitize_version(self, out: str) -> str:
+        v = re.search(r'(\d{4}) Update (\d)', out)
+        if v:
+            return '{}.{}'.format(v.group(1), v.group(2))
+        return out
+
+
+class OpenMPIConfigToolDependency(_MPIConfigToolDependency):
+
+    """Wrapper around OpenMPI mpicc and friends."""
+
+    version_arg = '--showme:version'
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        if not self.is_found:
+            return
+
+        c_args = self.get_config_value(['--showme:compile'], 'compile_args')
+        self.compile_args = self._filter_compile_args(c_args)
+
+        l_args = self.get_config_value(['--showme:link'], 'link_args')
+        self.link_args = self._filter_link_args(l_args)
+
+    def _sanitize_version(self, out: str) -> str:
+        v = re.search(r'\d+.\d+.\d+', out)
+        if v:
+            return v.group(0)
+        return out
+
+
+class MSMPIDependency(SystemDependency):
+
+    """The Microsoft MPI."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        # MSMPI only supports the C API
+        if language not in {'c', 'fortran', None}:
+            self.is_found = False
+            return
+        # MSMPI is only for windows, obviously
+        if not self.env.machines[self.for_machine].is_windows():
+            return
+
+        incdir = os.environ.get('MSMPI_INC')
+        arch = detect_cpu_family(self.env.coredata.compilers.host)
+        libdir = None
+        if arch == 'x86':
+            libdir = os.environ.get('MSMPI_LIB32')
+            post = 'x86'
+        elif arch == 'x86_64':
+            libdir = os.environ.get('MSMPI_LIB64')
+            post = 'x64'
+
+        if libdir is None or incdir is None:
+            self.is_found = False
+            return
+
+        self.is_found = True
+        self.link_args = ['-l' + os.path.join(libdir, 'msmpi')]
+        self.compile_args = ['-I' + incdir, '-I' + os.path.join(incdir, post)]
+        if self.language == 'fortran':
+            self.link_args.append('-l' + os.path.join(libdir, 'msmpifec'))
diff --git a/devtools/meson/mesonbuild/dependencies/pkgconfig.py b/devtools/meson/mesonbuild/dependencies/pkgconfig.py
new file mode 100644
index 0000000..0c40847
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/pkgconfig.py
@@ -0,0 +1,500 @@
+# Copyright 2013-2021 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from pathlib import Path
+
+from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName
+from ..mesonlib import OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged
+from ..programs import find_external_program, ExternalProgram
+from .. import mlog
+from pathlib import PurePath
+import re
+import os
+import shlex
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+    from ..utils.core import EnvironOrDict
+    from .._typing import ImmutableListProtocol
+    from ..build import EnvironmentVariables
+
+class PkgConfigDependency(ExternalDependency):
+    # The class's copy of the pkg-config path. Avoids having to search for it
+    # multiple times in the same Meson invocation.
+    class_pkgbin: PerMachine[T.Union[None, bool, ExternalProgram]] = PerMachine(None, None)
+    # We cache all pkg-config subprocess invocations to avoid redundant calls
+    pkgbin_cache: T.Dict[
+        T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]],
+        T.Tuple[int, str, str]
+    ] = {}
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        super().__init__(DependencyTypeName('pkgconfig'), environment, kwargs, language=language)
+        self.name = name
+        self.is_libtool = False
+        # Store a copy of the pkg-config path on the object itself so it is
+        # stored in the pickled coredata and recovered.
+        self.pkgbin = self._detect_pkgbin(self.silent, self.env, self.for_machine)
+        if self.pkgbin is False:
+            self.pkgbin = None
+            msg = f'Pkg-config binary for machine {self.for_machine} not found. Giving up.'
+            if self.required:
+                raise DependencyException(msg)
+            else:
+                mlog.debug(msg)
+                return
+
+        assert isinstance(self.pkgbin, ExternalProgram)
+        mlog.debug('Determining dependency {!r} with pkg-config executable '
+                   '{!r}'.format(name, self.pkgbin.get_path()))
+        ret, self.version, _ = self._call_pkgbin(['--modversion', name])
+        if ret != 0:
+            return
+
+        self.is_found = True
+
+        try:
+            # Fetch cargs to be used while using this dependency
+            self._set_cargs()
+            # Fetch the libraries and library paths needed for using this
+            self._set_libs()
+        except DependencyException as e:
+            mlog.debug(f"pkg-config error with '{name}': {e}")
+            if self.required:
+                raise
+            else:
+                self.compile_args = []
+                self.link_args = []
+                self.is_found = False
+                self.reason = e
+
+    def __repr__(self) -> str:
+        s = '<{0} {1}: {2} {3}>'
+        return s.format(self.__class__.__name__, self.name, self.is_found,
+                        self.version_reqs)
+
+    @classmethod
+    def _detect_pkgbin(cls, silent: bool, env: Environment,
+                       for_machine: MachineChoice) -> T.Union[None, bool, ExternalProgram]:
+        # Only search for pkg-config for each machine the first time and store
+        # the result in the class definition
+        if cls.class_pkgbin[for_machine] is False:
+            mlog.debug(f'Pkg-config binary for {for_machine} is cached as not found.')
+        elif cls.class_pkgbin[for_machine] is not None:
+            mlog.debug(f'Pkg-config binary for {for_machine} is cached.')
+        else:
+            assert cls.class_pkgbin[for_machine] is None, 'for mypy'
+            mlog.debug(f'Pkg-config binary for {for_machine} is not cached.')
+            for potential_pkgbin in find_external_program(
+                    env, for_machine, 'pkgconfig', 'Pkg-config',
+                    env.default_pkgconfig, allow_default_for_cross=False):
+                version_if_ok = cls.check_pkgconfig(env, potential_pkgbin)
+                if not version_if_ok:
+                    continue
+                if not silent:
+                    mlog.log('Found pkg-config:', mlog.bold(potential_pkgbin.get_path()),
+                             f'({version_if_ok})')
+                cls.class_pkgbin[for_machine] = potential_pkgbin
+                break
+            else:
+                if not silent:
+                    mlog.log('Found Pkg-config:', mlog.red('NO'))
+                # Set to False instead of None to signify that we've already
+                # searched for it and not found it
+                cls.class_pkgbin[for_machine] = False
+
+        return cls.class_pkgbin[for_machine]
+
+    def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple[int, str, str]:
+        assert isinstance(self.pkgbin, ExternalProgram)
+        cmd = self.pkgbin.get_command() + args
+        p, out, err = Popen_safe_logged(cmd, env=env)
+        return p.returncode, out.strip(), err.strip()
+
+    @staticmethod
+    def get_env(environment: 'Environment', for_machine: MachineChoice,
+                uninstalled: bool = False) -> 'EnvironmentVariables':
+        from ..build import EnvironmentVariables
+        env = EnvironmentVariables()
+        key = OptionKey('pkg_config_path', machine=for_machine)
+        extra_paths: T.List[str] = environment.coredata.options[key].value[:]
+        if uninstalled:
+            uninstalled_path = Path(environment.get_build_dir(), 'meson-uninstalled').as_posix()
+            if uninstalled_path not in extra_paths:
+                extra_paths.append(uninstalled_path)
+        env.set('PKG_CONFIG_PATH', extra_paths)
+        sysroot = environment.properties[for_machine].get_sys_root()
+        if sysroot:
+            env.set('PKG_CONFIG_SYSROOT_DIR', [sysroot])
+        pkg_config_libdir_prop = environment.properties[for_machine].get_pkg_config_libdir()
+        if pkg_config_libdir_prop:
+            env.set('PKG_CONFIG_LIBDIR', pkg_config_libdir_prop)
+        return env
+
+    @staticmethod
+    def setup_env(env: EnvironOrDict, environment: 'Environment', for_machine: MachineChoice,
+                  uninstalled: bool = False) -> T.Dict[str, str]:
+        envvars = PkgConfigDependency.get_env(environment, for_machine, uninstalled)
+        env = envvars.get_env(env)
+        # Dump all PKG_CONFIG environment variables
+        for key, value in env.items():
+            if key.startswith('PKG_'):
+                mlog.debug(f'env[{key}]: {value}')
+        return env
+
+    def _call_pkgbin(self, args: T.List[str], env: T.Optional[EnvironOrDict] = None) -> T.Tuple[int, str, str]:
+        assert isinstance(self.pkgbin, ExternalProgram)
+        env = env or os.environ
+        env = PkgConfigDependency.setup_env(env, self.env, self.for_machine)
+
+        fenv = frozenset(env.items())
+        targs = tuple(args)
+        cache = PkgConfigDependency.pkgbin_cache
+        if (self.pkgbin, targs, fenv) not in cache:
+            cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env)
+        return cache[(self.pkgbin, targs, fenv)]
+
+    def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]:
+        '''
+        Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo
+        paths so convert them to C:/foo. We cannot resolve other paths starting
+        with / like /home/foo so leave them as-is so that the user gets an
+        error/warning from the compiler/linker.
+        '''
+        if not self.env.machines.build.is_windows():
+            return args
+        converted = []
+        for arg in args:
+            pargs: T.Tuple[str, ...] = tuple()
+            # Library search path
+            if arg.startswith('-L/'):
+                pargs = PurePath(arg[2:]).parts
+                tmpl = '-L{}:/{}'
+            elif arg.startswith('-I/'):
+                pargs = PurePath(arg[2:]).parts
+                tmpl = '-I{}:/{}'
+            # Full path to library or .la file
+            elif arg.startswith('/'):
+                pargs = PurePath(arg).parts
+                tmpl = '{}:/{}'
+            elif arg.startswith(('-L', '-I')) or (len(arg) > 2 and arg[1] == ':'):
+                # clean out improper '\\ ' as comes from some Windows pkg-config files
+                arg = arg.replace('\\ ', ' ')
+            if len(pargs) > 1 and len(pargs[1]) == 1:
+                arg = tmpl.format(pargs[1], '/'.join(pargs[2:]))
+            converted.append(arg)
+        return converted
+
+    def _split_args(self, cmd: str) -> T.List[str]:
+        # pkg-config paths follow Unix conventions, even on Windows; split the
+        # output using shlex.split rather than mesonlib.split_args
+        return shlex.split(cmd)
+
+    def _set_cargs(self) -> None:
+        env = None
+        if self.language == 'fortran':
+            # gfortran doesn't appear to look in system paths for INCLUDE files,
+            # so don't allow pkg-config to suppress -I flags for system paths
+            env = os.environ.copy()
+            env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1'
+        ret, out, err = self._call_pkgbin(['--cflags', self.name], env=env)
+        if ret != 0:
+            raise DependencyException(f'Could not generate cargs for {self.name}:\n{err}\n')
+        self.compile_args = self._convert_mingw_paths(self._split_args(out))
+
+    def _search_libs(self, out: str, out_raw: str) -> T.Tuple[T.List[str], T.List[str]]:
+        '''
+        @out: PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs
+        @out_raw: pkg-config --libs
+
+        We always look for the file ourselves instead of depending on the
+        compiler to find it with -lfoo or foo.lib (if possible) because:
+        1. We want to be able to select static or shared
+        2. We need the full path of the library to calculate RPATH values
+        3. De-dup of libraries is easier when we have absolute paths
+
+        Libraries that are provided by the toolchain or are not found by
+        find_library() will be added with -L -l pairs.
+        '''
+        # Library paths should be safe to de-dup
+        #
+        # First, figure out what library paths to use. Originally, we were
+        # doing this as part of the loop, but due to differences in the order
+        # of -L values between pkg-config and pkgconf, we need to do that as
+        # a separate step. See:
+        # https://github.com/mesonbuild/meson/issues/3951
+        # https://github.com/mesonbuild/meson/issues/4023
+        #
+        # Separate system and prefix paths, and ensure that prefix paths are
+        # always searched first.
+        prefix_libpaths: OrderedSet[str] = OrderedSet()
+        # We also store this raw_link_args on the object later
+        raw_link_args = self._convert_mingw_paths(self._split_args(out_raw))
+        for arg in raw_link_args:
+            if arg.startswith('-L') and not arg.startswith(('-L-l', '-L-L')):
+                path = arg[2:]
+                if not os.path.isabs(path):
+                    # Resolve the path as a compiler in the build directory would
+                    path = os.path.join(self.env.get_build_dir(), path)
+                prefix_libpaths.add(path)
+        # Library paths are not always ordered in a meaningful way
+        #
+        # Instead of relying on pkg-config or pkgconf to provide -L flags in a
+        # specific order, we reorder library paths ourselves, according to th
+        # order specified in PKG_CONFIG_PATH. See:
+        # https://github.com/mesonbuild/meson/issues/4271
+        #
+        # Only prefix_libpaths are reordered here because there should not be
+        # too many system_libpaths to cause library version issues.
+        pkg_config_path: T.List[str] = self.env.coredata.options[OptionKey('pkg_config_path', machine=self.for_machine)].value
+        pkg_config_path = self._convert_mingw_paths(pkg_config_path)
+        prefix_libpaths = OrderedSet(sort_libpaths(list(prefix_libpaths), pkg_config_path))
+        system_libpaths: OrderedSet[str] = OrderedSet()
+        full_args = self._convert_mingw_paths(self._split_args(out))
+        for arg in full_args:
+            if arg.startswith(('-L-l', '-L-L')):
+                # These are D language arguments, not library paths
+                continue
+            if arg.startswith('-L') and arg[2:] not in prefix_libpaths:
+                system_libpaths.add(arg[2:])
+        # Use this re-ordered path list for library resolution
+        libpaths = list(prefix_libpaths) + list(system_libpaths)
+        # Track -lfoo libraries to avoid duplicate work
+        libs_found: OrderedSet[str] = OrderedSet()
+        # Track not-found libraries to know whether to add library paths
+        libs_notfound = []
+        # Generate link arguments for this library
+        link_args = []
+        for lib in full_args:
+            if lib.startswith(('-L-l', '-L-L')):
+                # These are D language arguments, add them as-is
+                pass
+            elif lib.startswith('-L'):
+                # We already handled library paths above
+                continue
+            elif lib.startswith('-l:'):
+                # see: https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a
+                # also : See the documentation of -lnamespec | --library=namespec in the linker manual
+                #                     https://sourceware.org/binutils/docs-2.18/ld/Options.html
+
+                # Don't resolve the same -l:libfoo.a argument again
+                if lib in libs_found:
+                    continue
+                libfilename = lib[3:]
+                foundname = None
+                for libdir in libpaths:
+                    target = os.path.join(libdir, libfilename)
+                    if os.path.exists(target):
+                        foundname = target
+                        break
+                if foundname is None:
+                    if lib in libs_notfound:
+                        continue
+                    else:
+                        mlog.warning('Library {!r} not found for dependency {!r}, may '
+                                     'not be successfully linked'.format(libfilename, self.name))
+                    libs_notfound.append(lib)
+                else:
+                    lib = foundname
+            elif lib.startswith('-l'):
+                # Don't resolve the same -lfoo argument again
+                if lib in libs_found:
+                    continue
+                if self.clib_compiler:
+                    args = self.clib_compiler.find_library(lib[2:], self.env,
+                                                           libpaths, self.libtype,
+                                                           lib_prefix_warning=False)
+                # If the project only uses a non-clib language such as D, Rust,
+                # C#, Python, etc, all we can do is limp along by adding the
+                # arguments as-is and then adding the libpaths at the end.
+                else:
+                    args = None
+                if args is not None:
+                    libs_found.add(lib)
+                    # Replace -l arg with full path to library if available
+                    # else, library is either to be ignored, or is provided by
+                    # the compiler, can't be resolved, and should be used as-is
+                    if args:
+                        if not args[0].startswith('-l'):
+                            lib = args[0]
+                    else:
+                        continue
+                else:
+                    # Library wasn't found, maybe we're looking in the wrong
+                    # places or the library will be provided with LDFLAGS or
+                    # LIBRARY_PATH from the environment (on macOS), and many
+                    # other edge cases that we can't account for.
+                    #
+                    # Add all -L paths and use it as -lfoo
+                    if lib in libs_notfound:
+                        continue
+                    if self.static:
+                        mlog.warning('Static library {!r} not found for dependency {!r}, may '
+                                     'not be statically linked'.format(lib[2:], self.name))
+                    libs_notfound.append(lib)
+            elif lib.endswith(".la"):
+                shared_libname = self.extract_libtool_shlib(lib)
+                shared_lib = os.path.join(os.path.dirname(lib), shared_libname)
+                if not os.path.exists(shared_lib):
+                    shared_lib = os.path.join(os.path.dirname(lib), ".libs", shared_libname)
+
+                if not os.path.exists(shared_lib):
+                    raise DependencyException(f'Got a libtools specific "{lib}" dependencies'
+                                              'but we could not compute the actual shared'
+                                              'library path')
+                self.is_libtool = True
+                lib = shared_lib
+                if lib in link_args:
+                    continue
+            link_args.append(lib)
+        # Add all -Lbar args if we have -lfoo args in link_args
+        if libs_notfound:
+            # Order of -L flags doesn't matter with ld, but it might with other
+            # linkers such as MSVC, so prepend them.
+            link_args = ['-L' + lp for lp in prefix_libpaths] + link_args
+        return link_args, raw_link_args
+
+    def _set_libs(self) -> None:
+        env = None
+        libcmd = ['--libs']
+
+        if self.static:
+            libcmd.append('--static')
+
+        libcmd.append(self.name)
+
+        # Force pkg-config to output -L fields even if they are system
+        # paths so we can do manual searching with cc.find_library() later.
+        env = os.environ.copy()
+        env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1'
+        ret, out, err = self._call_pkgbin(libcmd, env=env)
+        if ret != 0:
+            raise DependencyException(f'Could not generate libs for {self.name}:\n{err}\n')
+        # Also get the 'raw' output without -Lfoo system paths for adding -L
+        # args with -lfoo when a library can't be found, and also in
+        # gnome.generate_gir + gnome.gtkdoc which need -L -l arguments.
+        ret, out_raw, err_raw = self._call_pkgbin(libcmd)
+        if ret != 0:
+            raise DependencyException(f'Could not generate libs for {self.name}:\n\n{out_raw}')
+        self.link_args, self.raw_link_args = self._search_libs(out, out_raw)
+
+    def get_pkgconfig_variable(self, variable_name: str,
+                               define_variable: 'ImmutableListProtocol[str]',
+                               default: T.Optional[str]) -> str:
+        options = ['--variable=' + variable_name, self.name]
+
+        if define_variable:
+            options = ['--define-variable=' + '='.join(define_variable)] + options
+
+        ret, out, err = self._call_pkgbin(options)
+        variable = ''
+        if ret != 0:
+            if self.required:
+                raise DependencyException(f'dependency {self.name} not found:\n{err}\n')
+        else:
+            variable = out.strip()
+
+            # pkg-config doesn't distinguish between empty and nonexistent variables
+            # use the variable list to check for variable existence
+            if not variable:
+                ret, out, _ = self._call_pkgbin(['--print-variables', self.name])
+                if not re.search(r'^' + variable_name + r'$', out, re.MULTILINE):
+                    if default is not None:
+                        variable = default
+                    else:
+                        mlog.warning(f"pkgconfig variable '{variable_name}' not defined for dependency {self.name}.")
+
+        mlog.debug(f'Got pkgconfig variable {variable_name} : {variable}')
+        return variable
+
+    @staticmethod
+    def check_pkgconfig(env: Environment, pkgbin: ExternalProgram) -> T.Optional[str]:
+        if not pkgbin.found():
+            mlog.log(f'Did not find pkg-config by name {pkgbin.name!r}')
+            return None
+        command_as_string = ' '.join(pkgbin.get_command())
+        try:
+            helptext = Popen_safe(pkgbin.get_command() + ['--help'])[1]
+            if 'Pure-Perl' in helptext:
+                mlog.log(f'found pkg-config {command_as_string!r} but it is Strawberry Perl and thus broken. Ignoring...')
+                return None
+            p, out = Popen_safe(pkgbin.get_command() + ['--version'])[0:2]
+            if p.returncode != 0:
+                mlog.warning(f'Found pkg-config {command_as_string!r} but it failed when run')
+                return None
+        except FileNotFoundError:
+            mlog.warning(f'We thought we found pkg-config {command_as_string!r} but now it\'s not there. How odd!')
+            return None
+        except PermissionError:
+            msg = f'Found pkg-config {command_as_string!r} but didn\'t have permissions to run it.'
+            if not env.machines.build.is_windows():
+                msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.'
+            mlog.warning(msg)
+            return None
+        return out.strip()
+
+    def extract_field(self, la_file: str, fieldname: str) -> T.Optional[str]:
+        with open(la_file, encoding='utf-8') as f:
+            for line in f:
+                arr = line.strip().split('=')
+                if arr[0] == fieldname:
+                    return arr[1][1:-1]
+        return None
+
+    def extract_dlname_field(self, la_file: str) -> T.Optional[str]:
+        return self.extract_field(la_file, 'dlname')
+
+    def extract_libdir_field(self, la_file: str) -> T.Optional[str]:
+        return self.extract_field(la_file, 'libdir')
+
+    def extract_libtool_shlib(self, la_file: str) -> T.Optional[str]:
+        '''
+        Returns the path to the shared library
+        corresponding to this .la file
+        '''
+        dlname = self.extract_dlname_field(la_file)
+        if dlname is None:
+            return None
+
+        # Darwin uses absolute paths where possible; since the libtool files never
+        # contain absolute paths, use the libdir field
+        if self.env.machines[self.for_machine].is_darwin():
+            dlbasename = os.path.basename(dlname)
+            libdir = self.extract_libdir_field(la_file)
+            if libdir is None:
+                return dlbasename
+            return os.path.join(libdir, dlbasename)
+        # From the comments in extract_libtool(), older libtools had
+        # a path rather than the raw dlname
+        return os.path.basename(dlname)
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'pkgconfig'
+
+    def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None,
+                     configtool: T.Optional[str] = None, internal: T.Optional[str] = None,
+                     default_value: T.Optional[str] = None,
+                     pkgconfig_define: T.Optional[T.List[str]] = None) -> str:
+        if pkgconfig:
+            try:
+                return self.get_pkgconfig_variable(pkgconfig, pkgconfig_define or [], default_value)
+            except DependencyException:
+                pass
+        if default_value is not None:
+            return default_value
+        raise DependencyException(f'Could not get pkg-config variable and no default provided for {self!r}')
diff --git a/devtools/meson/mesonbuild/dependencies/platform.py b/devtools/meson/mesonbuild/dependencies/platform.py
new file mode 100644
index 0000000..87726b5
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/platform.py
@@ -0,0 +1,63 @@
+# Copyright 2013-2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file contains the detection logic for external dependencies that are
+# platform-specific (generally speaking).
+from __future__ import annotations
+
+from .base import DependencyTypeName, ExternalDependency, DependencyException
+from .detect import packages
+from ..mesonlib import MesonException
+import typing as T
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+class AppleFrameworks(ExternalDependency):
+    def __init__(self, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(DependencyTypeName('appleframeworks'), env, kwargs)
+        modules = kwargs.get('modules', [])
+        if isinstance(modules, str):
+            modules = [modules]
+        if not modules:
+            raise DependencyException("AppleFrameworks dependency requires at least one module.")
+        self.frameworks = modules
+        if not self.clib_compiler:
+            raise DependencyException('No C-like compilers are available, cannot find the framework')
+        self.is_found = True
+        for f in self.frameworks:
+            try:
+                args = self.clib_compiler.find_framework(f, env, [])
+            except MesonException as e:
+                if 'non-clang' in str(e):
+                    self.is_found = False
+                    self.link_args = []
+                    self.compile_args = []
+                    return
+                raise
+
+            if args is not None:
+                # No compile args are needed for system frameworks
+                self.link_args += args
+            else:
+                self.is_found = False
+
+    def log_info(self) -> str:
+        return ', '.join(self.frameworks)
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'framework'
+
+packages['appleframeworks'] = AppleFrameworks
diff --git a/devtools/meson/mesonbuild/dependencies/python.py b/devtools/meson/mesonbuild/dependencies/python.py
new file mode 100644
index 0000000..1607728
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/python.py
@@ -0,0 +1,417 @@
+# Copyright 2022 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import functools, json, os, textwrap
+from pathlib import Path
+import typing as T
+
+from .. import mesonlib, mlog
+from .base import process_method_kw, DependencyMethods, DependencyTypeName, ExternalDependency, SystemDependency
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .factory import DependencyFactory
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+from ..environment import detect_cpu_family
+from ..programs import ExternalProgram
+
+if T.TYPE_CHECKING:
+    from typing_extensions import TypedDict
+
+    from .factory import DependencyGenerator
+    from ..environment import Environment
+    from ..mesonlib import MachineChoice
+
+    class PythonIntrospectionDict(TypedDict):
+
+        install_paths: T.Dict[str, str]
+        is_pypy: bool
+        is_venv: bool
+        link_libpython: bool
+        sysconfig_paths: T.Dict[str, str]
+        paths: T.Dict[str, str]
+        platform: str
+        suffix: str
+        variables: T.Dict[str, str]
+        version: str
+
+    _Base = ExternalDependency
+else:
+    _Base = object
+
+
+class Pybind11ConfigToolDependency(ConfigToolDependency):
+
+    tools = ['pybind11-config']
+
+    # any version of the tool is valid, since this is header-only
+    allow_default_for_cross = True
+
+    # pybind11 in 2.10.4 added --version, sanity-check another flag unique to it
+    # in the meantime
+    skip_version = '--pkgconfigdir'
+
+    def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--includes'], 'compile_args')
+
+
+class BasicPythonExternalProgram(ExternalProgram):
+    def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
+                 ext_prog: T.Optional[ExternalProgram] = None):
+        if ext_prog is None:
+            super().__init__(name, command=command, silent=True)
+        else:
+            self.name = name
+            self.command = ext_prog.command
+            self.path = ext_prog.path
+            self.cached_version = None
+
+        # We want strong key values, so we always populate this with bogus data.
+        # Otherwise to make the type checkers happy we'd have to do .get() for
+        # everycall, even though we know that the introspection data will be
+        # complete
+        self.info: 'PythonIntrospectionDict' = {
+            'install_paths': {},
+            'is_pypy': False,
+            'is_venv': False,
+            'link_libpython': False,
+            'sysconfig_paths': {},
+            'paths': {},
+            'platform': 'sentinel',
+            'suffix': 'sentinel',
+            'variables': {},
+            'version': '0.0',
+        }
+        self.pure: bool = True
+
+    def _check_version(self, version: str) -> bool:
+        if self.name == 'python2':
+            return mesonlib.version_compare(version, '< 3.0')
+        elif self.name == 'python3':
+            return mesonlib.version_compare(version, '>= 3.0')
+        return True
+
+    def sanity(self) -> bool:
+        # Sanity check, we expect to have something that at least quacks in tune
+
+        import importlib.resources
+
+        with importlib.resources.path('mesonbuild.scripts', 'python_info.py') as f:
+            cmd = self.get_command() + [str(f)]
+            p, stdout, stderr = mesonlib.Popen_safe(cmd)
+
+        try:
+            info = json.loads(stdout)
+        except json.JSONDecodeError:
+            info = None
+            mlog.debug('Could not introspect Python (%s): exit code %d' % (str(p.args), p.returncode))
+            mlog.debug('Program stdout:\n')
+            mlog.debug(stdout)
+            mlog.debug('Program stderr:\n')
+            mlog.debug(stderr)
+
+        if info is not None and self._check_version(info['version']):
+            self.info = T.cast('PythonIntrospectionDict', info)
+            return True
+        else:
+            return False
+
+
+class _PythonDependencyBase(_Base):
+
+    def __init__(self, python_holder: 'BasicPythonExternalProgram', embed: bool):
+        self.embed = embed
+        self.version: str = python_holder.info['version']
+        self.platform = python_holder.info['platform']
+        self.variables = python_holder.info['variables']
+        self.paths = python_holder.info['paths']
+        self.is_pypy = python_holder.info['is_pypy']
+        # The "-embed" version of python.pc / python-config was introduced in 3.8,
+        # and distutils extension linking was changed to be considered a non embed
+        # usage. Before then, this dependency always uses the embed=True handling
+        # because that is the only one that exists.
+        #
+        # On macOS and some Linux distros (Debian) distutils doesn't link extensions
+        # against libpython, even on 3.7 and below. We call into distutils and
+        # mirror its behavior. See https://github.com/mesonbuild/meson/issues/4117
+        self.link_libpython = python_holder.info['link_libpython'] or embed
+        self.info: T.Optional[T.Dict[str, str]] = None
+        if mesonlib.version_compare(self.version, '>= 3.0'):
+            self.major_version = 3
+        else:
+            self.major_version = 2
+
+
+class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase):
+
+    def __init__(self, name: str, environment: 'Environment',
+                 kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram',
+                 libpc: bool = False):
+        if libpc:
+            mlog.debug(f'Searching for {name!r} via pkgconfig lookup in LIBPC')
+        else:
+            mlog.debug(f'Searching for {name!r} via fallback pkgconfig lookup in default paths')
+
+        PkgConfigDependency.__init__(self, name, environment, kwargs)
+        _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
+
+        if libpc and not self.is_found:
+            mlog.debug(f'"python-{self.version}" could not be found in LIBPC, this is likely due to a relocated python installation')
+
+        # pkg-config files are usually accurate starting with python 3.8
+        if not self.link_libpython and mesonlib.version_compare(self.version, '< 3.8'):
+            self.link_args = []
+
+
+class PythonFrameworkDependency(ExtraFrameworkDependency, _PythonDependencyBase):
+
+    def __init__(self, name: str, environment: 'Environment',
+                 kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram'):
+        ExtraFrameworkDependency.__init__(self, name, environment, kwargs)
+        _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
+
+
+class PythonSystemDependency(SystemDependency, _PythonDependencyBase):
+
+    def __init__(self, name: str, environment: 'Environment',
+                 kwargs: T.Dict[str, T.Any], installation: 'BasicPythonExternalProgram'):
+        SystemDependency.__init__(self, name, environment, kwargs)
+        _PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
+
+        # match pkg-config behavior
+        if self.link_libpython:
+            # link args
+            if mesonlib.is_windows():
+                self.find_libpy_windows(environment)
+            else:
+                self.find_libpy(environment)
+        else:
+            self.is_found = True
+
+        # compile args
+        inc_paths = mesonlib.OrderedSet([
+            self.variables.get('INCLUDEPY'),
+            self.paths.get('include'),
+            self.paths.get('platinclude')])
+
+        self.compile_args += ['-I' + path for path in inc_paths if path]
+
+        # https://sourceforge.net/p/mingw-w64/mailman/message/30504611/
+        # https://github.com/python/cpython/pull/100137
+        if mesonlib.is_windows() and self.get_windows_python_arch().endswith('64') and mesonlib.version_compare(self.version, '<3.12'):
+            self.compile_args += ['-DMS_WIN64=']
+
+        if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args):
+            self.is_found = False
+
+    def find_libpy(self, environment: 'Environment') -> None:
+        if self.is_pypy:
+            if self.major_version == 3:
+                libname = 'pypy3-c'
+            else:
+                libname = 'pypy-c'
+            libdir = os.path.join(self.variables.get('base'), 'bin')
+            libdirs = [libdir]
+        else:
+            libname = f'python{self.version}'
+            if 'DEBUG_EXT' in self.variables:
+                libname += self.variables['DEBUG_EXT']
+            if 'ABIFLAGS' in self.variables:
+                libname += self.variables['ABIFLAGS']
+            libdirs = []
+
+        largs = self.clib_compiler.find_library(libname, environment, libdirs)
+        if largs is not None:
+            self.link_args = largs
+            self.is_found = True
+
+    def get_windows_python_arch(self) -> T.Optional[str]:
+        if self.platform == 'mingw':
+            pycc = self.variables.get('CC')
+            if pycc.startswith('x86_64'):
+                return 'x86_64'
+            elif pycc.startswith(('i686', 'i386')):
+                return 'x86'
+            else:
+                mlog.log(f'MinGW Python built with unknown CC {pycc!r}, please file a bug')
+                return None
+        elif self.platform == 'win32':
+            return 'x86'
+        elif self.platform in {'win64', 'win-amd64'}:
+            return 'x86_64'
+        elif self.platform in {'win-arm64'}:
+            return 'aarch64'
+        mlog.log(f'Unknown Windows Python platform {self.platform!r}')
+        return None
+
+    def get_windows_link_args(self) -> T.Optional[T.List[str]]:
+        if self.platform.startswith('win'):
+            vernum = self.variables.get('py_version_nodot')
+            verdot = self.variables.get('py_version_short')
+            imp_lower = self.variables.get('implementation_lower', 'python')
+            if self.static:
+                libpath = Path('libs') / f'libpython{vernum}.a'
+            else:
+                comp = self.get_compiler()
+                if comp.id == "gcc":
+                    if imp_lower == 'pypy' and verdot == '3.8':
+                        # The naming changed between 3.8 and 3.9
+                        libpath = Path('libpypy3-c.dll')
+                    elif imp_lower == 'pypy':
+                        libpath = Path(f'libpypy{verdot}-c.dll')
+                    else:
+                        libpath = Path(f'python{vernum}.dll')
+                else:
+                    libpath = Path('libs') / f'python{vernum}.lib'
+                    # For a debug build, pyconfig.h may force linking with
+                    # pythonX_d.lib (see meson#10776). This cannot be avoided
+                    # and won't work unless we also have a debug build of
+                    # Python itself (except with pybind11, which has an ugly
+                    # hack to work around this) - so emit a warning to explain
+                    # the cause of the expected link error.
+                    buildtype = self.env.coredata.get_option(mesonlib.OptionKey('buildtype'))
+                    assert isinstance(buildtype, str)
+                    debug = self.env.coredata.get_option(mesonlib.OptionKey('debug'))
+                    # `debugoptimized` buildtype may not set debug=True currently, see gh-11645
+                    is_debug_build = debug or buildtype == 'debug'
+                    vscrt_debug = False
+                    if mesonlib.OptionKey('b_vscrt') in self.env.coredata.options:
+                        vscrt = self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value
+                        if vscrt in {'mdd', 'mtd', 'from_buildtype', 'static_from_buildtype'}:
+                            vscrt_debug = True
+                    if is_debug_build and vscrt_debug and not self.variables.get('Py_DEBUG'):
+                        mlog.warning(textwrap.dedent('''\
+                            Using a debug build type with MSVC or an MSVC-compatible compiler
+                            when the Python interpreter is not also a debug build will almost
+                            certainly result in a failed build. Prefer using a release build
+                            type or a debug Python interpreter.
+                            '''))
+            # base_prefix to allow for virtualenvs.
+            lib = Path(self.variables.get('base_prefix')) / libpath
+        elif self.platform == 'mingw':
+            if self.static:
+                libname = self.variables.get('LIBRARY')
+            else:
+                libname = self.variables.get('LDLIBRARY')
+            lib = Path(self.variables.get('LIBDIR')) / libname
+        else:
+            raise mesonlib.MesonBugException(
+                'On a Windows path, but the OS doesn\'t appear to be Windows or MinGW.')
+        if not lib.exists():
+            mlog.log('Could not find Python3 library {!r}'.format(str(lib)))
+            return None
+        return [str(lib)]
+
+    def find_libpy_windows(self, env: 'Environment') -> None:
+        '''
+        Find python3 libraries on Windows and also verify that the arch matches
+        what we are building for.
+        '''
+        pyarch = self.get_windows_python_arch()
+        if pyarch is None:
+            self.is_found = False
+            return
+        arch = detect_cpu_family(env.coredata.compilers.host)
+        if arch != pyarch:
+            mlog.log('Need', mlog.bold(self.name), f'for {arch}, but found {pyarch}')
+            self.is_found = False
+            return
+        # This can fail if the library is not found
+        largs = self.get_windows_link_args()
+        if largs is None:
+            self.is_found = False
+            return
+        self.link_args = largs
+        self.is_found = True
+
+    @staticmethod
+    def log_tried() -> str:
+        return 'sysconfig'
+
+def python_factory(env: 'Environment', for_machine: 'MachineChoice',
+                   kwargs: T.Dict[str, T.Any],
+                   installation: T.Optional['BasicPythonExternalProgram'] = None) -> T.List['DependencyGenerator']:
+    # We can't use the factory_methods decorator here, as we need to pass the
+    # extra installation argument
+    methods = process_method_kw({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}, kwargs)
+    embed = kwargs.get('embed', False)
+    candidates: T.List['DependencyGenerator'] = []
+    from_installation = installation is not None
+    # When not invoked through the python module, default installation.
+    if installation is None:
+        installation = BasicPythonExternalProgram('python3', mesonlib.python_command)
+        installation.sanity()
+    pkg_version = installation.info['variables'].get('LDVERSION') or installation.info['version']
+
+    if DependencyMethods.PKGCONFIG in methods:
+        if from_installation:
+            pkg_libdir = installation.info['variables'].get('LIBPC')
+            pkg_embed = '-embed' if embed and mesonlib.version_compare(installation.info['version'], '>=3.8') else ''
+            pkg_name = f'python-{pkg_version}{pkg_embed}'
+
+            # If python-X.Y.pc exists in LIBPC, we will try to use it
+            def wrap_in_pythons_pc_dir(name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                                       installation: 'BasicPythonExternalProgram') -> 'ExternalDependency':
+                if not pkg_libdir:
+                    # there is no LIBPC, so we can't search in it
+                    empty = ExternalDependency(DependencyTypeName('pkgconfig'), env, {})
+                    empty.name = 'python'
+                    return empty
+
+                old_pkg_libdir = os.environ.pop('PKG_CONFIG_LIBDIR', None)
+                old_pkg_path = os.environ.pop('PKG_CONFIG_PATH', None)
+                os.environ['PKG_CONFIG_LIBDIR'] = pkg_libdir
+                try:
+                    return PythonPkgConfigDependency(name, env, kwargs, installation, True)
+                finally:
+                    def set_env(name: str, value: str) -> None:
+                        if value is not None:
+                            os.environ[name] = value
+                        elif name in os.environ:
+                            del os.environ[name]
+                    set_env('PKG_CONFIG_LIBDIR', old_pkg_libdir)
+                    set_env('PKG_CONFIG_PATH', old_pkg_path)
+
+            candidates.append(functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation))
+            # We only need to check both, if a python install has a LIBPC. It might point to the wrong location,
+            # e.g. relocated / cross compilation, but the presence of LIBPC indicates we should definitely look for something.
+            if pkg_libdir is not None:
+                candidates.append(functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation))
+        else:
+            candidates.append(functools.partial(PkgConfigDependency, 'python3', env, kwargs))
+
+    if DependencyMethods.SYSTEM in methods:
+        candidates.append(functools.partial(PythonSystemDependency, 'python', env, kwargs, installation))
+
+    if DependencyMethods.EXTRAFRAMEWORK in methods:
+        nkwargs = kwargs.copy()
+        if mesonlib.version_compare(pkg_version, '>= 3'):
+            # There is a python in /System/Library/Frameworks, but that's python 2.x,
+            # Python 3 will always be in /Library
+            nkwargs['paths'] = ['/Library/Frameworks']
+        candidates.append(functools.partial(PythonFrameworkDependency, 'Python', env, nkwargs, installation))
+
+    return candidates
+
+packages['python3'] = python_factory
+
+packages['pybind11'] = pybind11_factory = DependencyFactory(
+    'pybind11',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.CMAKE],
+    configtool_class=Pybind11ConfigToolDependency,
+)
diff --git a/devtools/meson/mesonbuild/dependencies/qt.py b/devtools/meson/mesonbuild/dependencies/qt.py
new file mode 100644
index 0000000..ba9b420
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/qt.py
@@ -0,0 +1,490 @@
+# Copyright 2013-2017 The Meson development team
+# Copyright © 2021 Intel Corporation
+# SPDX-license-identifier: Apache-2.0
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+"""Dependency finders for the Qt framework."""
+
+import abc
+import re
+import os
+import typing as T
+
+from .base import DependencyException, DependencyMethods
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import DependencyFactory
+from .. import mlog
+from .. import mesonlib
+
+if T.TYPE_CHECKING:
+    from ..compilers import Compiler
+    from ..envconfig import MachineInfo
+    from ..environment import Environment
+    from ..dependencies import MissingCompiler
+
+
+def _qt_get_private_includes(mod_inc_dir: str, module: str, mod_version: str) -> T.List[str]:
+    # usually Qt5 puts private headers in /QT_INSTALL_HEADERS/module/VERSION/module/private
+    # except for at least QtWebkit and Enginio where the module version doesn't match Qt version
+    # as an example with Qt 5.10.1 on linux you would get:
+    # /usr/include/qt5/QtCore/5.10.1/QtCore/private/
+    # /usr/include/qt5/QtWidgets/5.10.1/QtWidgets/private/
+    # /usr/include/qt5/QtWebKit/5.212.0/QtWebKit/private/
+
+    # on Qt4 when available private folder is directly in module folder
+    # like /usr/include/QtCore/private/
+    if int(mod_version.split('.')[0]) < 5:
+        return []
+
+    private_dir = os.path.join(mod_inc_dir, mod_version)
+    # fallback, let's try to find a directory with the latest version
+    if os.path.isdir(mod_inc_dir) and not os.path.exists(private_dir):
+        dirs = [filename for filename in os.listdir(mod_inc_dir)
+                if os.path.isdir(os.path.join(mod_inc_dir, filename))]
+
+        for dirname in sorted(dirs, reverse=True):
+            if len(dirname.split('.')) == 3:
+                private_dir = dirname
+                break
+    return [private_dir, os.path.join(private_dir, 'Qt' + module)]
+
+
+def get_qmake_host_bins(qvars: T.Dict[str, str]) -> str:
+    # Prefer QT_HOST_BINS (qt5, correct for cross and native compiling)
+    # but fall back to QT_INSTALL_BINS (qt4)
+    if 'QT_HOST_BINS' in qvars:
+        return qvars['QT_HOST_BINS']
+    return qvars['QT_INSTALL_BINS']
+
+
+def get_qmake_host_libexecs(qvars: T.Dict[str, str]) -> T.Optional[str]:
+    if 'QT_HOST_LIBEXECS' in qvars:
+        return qvars['QT_HOST_LIBEXECS']
+    return qvars.get('QT_INSTALL_LIBEXECS')
+
+
+def _get_modules_lib_suffix(version: str, info: 'MachineInfo', is_debug: bool) -> str:
+    """Get the module suffix based on platform and debug type."""
+    suffix = ''
+    if info.is_windows():
+        if is_debug:
+            suffix += 'd'
+        if version.startswith('4'):
+            suffix += '4'
+    if info.is_darwin():
+        if is_debug:
+            suffix += '_debug'
+    if mesonlib.version_compare(version, '>= 5.14.0'):
+        if info.is_android():
+            if info.cpu_family == 'x86':
+                suffix += '_x86'
+            elif info.cpu_family == 'x86_64':
+                suffix += '_x86_64'
+            elif info.cpu_family == 'arm':
+                suffix += '_armeabi-v7a'
+            elif info.cpu_family == 'aarch64':
+                suffix += '_arm64-v8a'
+            else:
+                mlog.warning(f'Android target arch "{info.cpu_family}"" for Qt5 is unknown, '
+                             'module detection may not work')
+    return suffix
+
+
+class QtExtraFrameworkDependency(ExtraFrameworkDependency):
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], qvars: T.Dict[str, str], language: T.Optional[str] = None):
+        super().__init__(name, env, kwargs, language=language)
+        self.mod_name = name[2:]
+        self.qt_extra_include_directory = qvars['QT_INSTALL_HEADERS']
+
+    def get_compile_args(self, with_private_headers: bool = False, qt_version: str = "0") -> T.List[str]:
+        if self.found():
+            mod_inc_dir = os.path.join(self.framework_path, 'Headers')
+            args = ['-I' + mod_inc_dir]
+            if with_private_headers:
+                args += ['-I' + dirname for dirname in _qt_get_private_includes(mod_inc_dir, self.mod_name, qt_version)]
+            if self.qt_extra_include_directory:
+                args += ['-I' + self.qt_extra_include_directory]
+            return args
+        return []
+
+
+class _QtBase:
+
+    """Mixin class for shared components between PkgConfig and Qmake."""
+
+    link_args: T.List[str]
+    clib_compiler: T.Union['MissingCompiler', 'Compiler']
+    env: 'Environment'
+    libexecdir: T.Optional[str] = None
+
+    def __init__(self, name: str, kwargs: T.Dict[str, T.Any]):
+        self.name = name
+        self.qtname = name.capitalize()
+        self.qtver = name[-1]
+        if self.qtver == "4":
+            self.qtpkgname = 'Qt'
+        else:
+            self.qtpkgname = self.qtname
+
+        self.private_headers = T.cast('bool', kwargs.get('private_headers', False))
+
+        self.requested_modules = mesonlib.stringlistify(mesonlib.extract_as_list(kwargs, 'modules'))
+        if not self.requested_modules:
+            raise DependencyException('No ' + self.qtname + '  modules specified.')
+
+        self.qtmain = T.cast('bool', kwargs.get('main', False))
+        if not isinstance(self.qtmain, bool):
+            raise DependencyException('"main" argument must be a boolean')
+
+    def _link_with_qt_winmain(self, is_debug: bool, libdir: T.Union[str, T.List[str]]) -> bool:
+        libdir = mesonlib.listify(libdir)  # TODO: shouldn't be necessary
+        base_name = self.get_qt_winmain_base_name(is_debug)
+        qt_winmain = self.clib_compiler.find_library(base_name, self.env, libdir)
+        if qt_winmain:
+            self.link_args.append(qt_winmain[0])
+            return True
+        return False
+
+    def get_qt_winmain_base_name(self, is_debug: bool) -> str:
+        return 'qtmaind' if is_debug else 'qtmain'
+
+    def get_exe_args(self, compiler: 'Compiler') -> T.List[str]:
+        # Originally this was -fPIE but nowadays the default
+        # for upstream and distros seems to be -reduce-relocations
+        # which requires -fPIC. This may cause a performance
+        # penalty when using self-built Qt or on platforms
+        # where -fPIC is not required. If this is an issue
+        # for you, patches are welcome.
+        return compiler.get_pic_args()
+
+    def log_details(self) -> str:
+        return f'modules: {", ".join(sorted(self.requested_modules))}'
+
+
+class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta):
+
+    """Specialization of the PkgConfigDependency for Qt."""
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        _QtBase.__init__(self, name, kwargs)
+
+        # Always use QtCore as the "main" dependency, since it has the extra
+        # pkg-config variables that a user would expect to get. If "Core" is
+        # not a requested module, delete the compile and link arguments to
+        # avoid linking with something they didn't ask for
+        PkgConfigDependency.__init__(self, self.qtpkgname + 'Core', env, kwargs)
+        if 'Core' not in self.requested_modules:
+            self.compile_args = []
+            self.link_args = []
+
+        for m in self.requested_modules:
+            mod = PkgConfigDependency(self.qtpkgname + m, self.env, kwargs, language=self.language)
+            if not mod.found():
+                self.is_found = False
+                return
+            if self.private_headers:
+                qt_inc_dir = mod.get_pkgconfig_variable('includedir', [], None)
+                mod_private_dir = os.path.join(qt_inc_dir, 'Qt' + m)
+                if not os.path.isdir(mod_private_dir):
+                    # At least some versions of homebrew don't seem to set this
+                    # up correctly. /usr/local/opt/qt/include/Qt + m_name is a
+                    # symlink to /usr/local/opt/qt/include, but the pkg-config
+                    # file points to /usr/local/Cellar/qt/x.y.z/Headers/, and
+                    # the Qt + m_name there is not a symlink, it's a file
+                    mod_private_dir = qt_inc_dir
+                mod_private_inc = _qt_get_private_includes(mod_private_dir, m, mod.version)
+                for directory in mod_private_inc:
+                    mod.compile_args.append('-I' + directory)
+            self._add_sub_dependency([lambda: mod])
+
+        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
+            # Check if we link with debug binaries
+            debug_lib_name = self.qtpkgname + 'Core' + _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], True)
+            is_debug = False
+            for arg in self.get_link_args():
+                if arg == f'-l{debug_lib_name}' or arg.endswith(f'{debug_lib_name}.lib') or arg.endswith(f'{debug_lib_name}.a'):
+                    is_debug = True
+                    break
+            libdir = self.get_pkgconfig_variable('libdir', [], None)
+            if not self._link_with_qt_winmain(is_debug, libdir):
+                self.is_found = False
+                return
+
+        self.bindir = self.get_pkgconfig_host_bins(self)
+        if not self.bindir:
+            # If exec_prefix is not defined, the pkg-config file is broken
+            prefix = self.get_pkgconfig_variable('exec_prefix', [], None)
+            if prefix:
+                self.bindir = os.path.join(prefix, 'bin')
+
+        self.libexecdir = self.get_pkgconfig_host_libexecs(self)
+
+    @staticmethod
+    @abc.abstractmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]:
+        pass
+
+    @staticmethod
+    @abc.abstractmethod
+    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> T.Optional[str]:
+        pass
+
+    @abc.abstractmethod
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        pass
+
+    def log_info(self) -> str:
+        return 'pkg-config'
+
+
+class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta):
+
+    """Find Qt using Qmake as a config-tool."""
+
+    version_arg = '-v'
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        _QtBase.__init__(self, name, kwargs)
+        self.tool_name = f'qmake{self.qtver}'
+        self.tools = [f'qmake{self.qtver}', f'qmake-{self.name}', 'qmake']
+
+        # Add additional constraints that the Qt version is met, but preserve
+        # any version requirements the user has set as well. For example, if Qt5
+        # is requested, add "">= 5, < 6", but if the user has ">= 5.6", don't
+        # lose that.
+        kwargs = kwargs.copy()
+        _vers = mesonlib.listify(kwargs.get('version', []))
+        _vers.extend([f'>= {self.qtver}', f'< {int(self.qtver) + 1}'])
+        kwargs['version'] = _vers
+
+        ConfigToolDependency.__init__(self, name, env, kwargs)
+        if not self.found():
+            return
+
+        # Query library path, header path, and binary path
+        stdo = self.get_config_value(['-query'], 'args')
+        qvars: T.Dict[str, str] = {}
+        for line in stdo:
+            line = line.strip()
+            if line == '':
+                continue
+            k, v = line.split(':', 1)
+            qvars[k] = v
+        # Qt on macOS uses a framework, but Qt for iOS/tvOS does not
+        xspec = qvars.get('QMAKE_XSPEC', '')
+        if self.env.machines.host.is_darwin() and not any(s in xspec for s in ['ios', 'tvos']):
+            mlog.debug("Building for macOS, looking for framework")
+            self._framework_detect(qvars, self.requested_modules, kwargs)
+            # Sometimes Qt is built not as a framework (for instance, when using conan pkg manager)
+            # skip and fall back to normal procedure then
+            if self.is_found:
+                return
+            else:
+                mlog.debug("Building for macOS, couldn't find framework, falling back to library search")
+        incdir = qvars['QT_INSTALL_HEADERS']
+        self.compile_args.append('-I' + incdir)
+        libdir = qvars['QT_INSTALL_LIBS']
+        # Used by qt.compilers_detect()
+        self.bindir = get_qmake_host_bins(qvars)
+        self.libexecdir = get_qmake_host_libexecs(qvars)
+
+        # Use the buildtype by default, but look at the b_vscrt option if the
+        # compiler supports it.
+        is_debug = self.env.coredata.get_option(mesonlib.OptionKey('buildtype')) == 'debug'
+        if mesonlib.OptionKey('b_vscrt') in self.env.coredata.options:
+            if self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value in {'mdd', 'mtd'}:
+                is_debug = True
+        modules_lib_suffix = _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], is_debug)
+
+        for module in self.requested_modules:
+            mincdir = os.path.join(incdir, 'Qt' + module)
+            self.compile_args.append('-I' + mincdir)
+
+            if module == 'QuickTest':
+                define_base = 'QMLTEST'
+            elif module == 'Test':
+                define_base = 'TESTLIB'
+            else:
+                define_base = module.upper()
+            self.compile_args.append(f'-DQT_{define_base}_LIB')
+
+            if self.private_headers:
+                priv_inc = self.get_private_includes(mincdir, module)
+                for directory in priv_inc:
+                    self.compile_args.append('-I' + directory)
+            libfiles = self.clib_compiler.find_library(
+                self.qtpkgname + module + modules_lib_suffix, self.env,
+                mesonlib.listify(libdir)) # TODO: shouldn't be necessary
+            if libfiles:
+                libfile = libfiles[0]
+            else:
+                mlog.log("Could not find:", module,
+                         self.qtpkgname + module + modules_lib_suffix,
+                         'in', libdir)
+                self.is_found = False
+                break
+            self.link_args.append(libfile)
+
+        if self.env.machines[self.for_machine].is_windows() and self.qtmain:
+            if not self._link_with_qt_winmain(is_debug, libdir):
+                self.is_found = False
+
+    def _sanitize_version(self, version: str) -> str:
+        m = re.search(rf'({self.qtver}(\.\d+)+)', version)
+        if m:
+            return m.group(0).rstrip('.')
+        return version
+
+    @abc.abstractmethod
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        pass
+
+    def _framework_detect(self, qvars: T.Dict[str, str], modules: T.List[str], kwargs: T.Dict[str, T.Any]) -> None:
+        libdir = qvars['QT_INSTALL_LIBS']
+
+        # ExtraFrameworkDependency doesn't support any methods
+        fw_kwargs = kwargs.copy()
+        fw_kwargs.pop('method', None)
+        fw_kwargs['paths'] = [libdir]
+
+        for m in modules:
+            fname = 'Qt' + m
+            mlog.debug('Looking for qt framework ' + fname)
+            fwdep = QtExtraFrameworkDependency(fname, self.env, fw_kwargs, qvars, language=self.language)
+            if fwdep.found():
+                self.compile_args.append('-F' + libdir)
+                self.compile_args += fwdep.get_compile_args(with_private_headers=self.private_headers,
+                                                            qt_version=self.version)
+                self.link_args += fwdep.get_link_args()
+            else:
+                self.is_found = False
+                break
+        else:
+            self.is_found = True
+            # Used by self.compilers_detect()
+            self.bindir = get_qmake_host_bins(qvars)
+            self.libexecdir = get_qmake_host_libexecs(qvars)
+
+    def log_info(self) -> str:
+        return 'qmake'
+
+
+class Qt6WinMainMixin:
+
+    def get_qt_winmain_base_name(self, is_debug: bool) -> str:
+        return 'Qt6EntryPointd' if is_debug else 'Qt6EntryPoint'
+
+
+class Qt4ConfigToolDependency(QmakeQtDependency):
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return []
+
+
+class Qt5ConfigToolDependency(QmakeQtDependency):
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return _qt_get_private_includes(mod_inc_dir, module, self.version)
+
+
+class Qt6ConfigToolDependency(Qt6WinMainMixin, QmakeQtDependency):
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return _qt_get_private_includes(mod_inc_dir, module, self.version)
+
+
+class Qt4PkgConfigDependency(QtPkgConfigDependency):
+
+    @staticmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]:
+        # Only return one bins dir, because the tools are generally all in one
+        # directory for Qt4, in Qt5, they must all be in one directory. Return
+        # the first one found among the bin variables, in case one tool is not
+        # configured to be built.
+        applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease']
+        for application in applications:
+            try:
+                return os.path.dirname(core.get_pkgconfig_variable(f'{application}_location', [], None))
+            except mesonlib.MesonException:
+                pass
+        return None
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return []
+
+    @staticmethod
+    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str:
+        return None
+
+
+class Qt5PkgConfigDependency(QtPkgConfigDependency):
+
+    @staticmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
+        return core.get_pkgconfig_variable('host_bins', [], None)
+
+    @staticmethod
+    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str:
+        return None
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return _qt_get_private_includes(mod_inc_dir, module, self.version)
+
+
+class Qt6PkgConfigDependency(Qt6WinMainMixin, QtPkgConfigDependency):
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, env, kwargs)
+        if not self.libexecdir:
+            mlog.debug(f'detected Qt6 {self.version} pkg-config dependency does not '
+                       'have proper tools support, ignoring')
+            self.is_found = False
+
+    @staticmethod
+    def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
+        return core.get_pkgconfig_variable('bindir', [], None)
+
+    @staticmethod
+    def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str:
+        # Qt6 pkg-config for Qt defines libexecdir from 6.3+
+        return core.get_pkgconfig_variable('libexecdir', [], None)
+
+    def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
+        return _qt_get_private_includes(mod_inc_dir, module, self.version)
+
+
+packages['qt4'] = qt4_factory = DependencyFactory(
+    'qt4',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    pkgconfig_class=Qt4PkgConfigDependency,
+    configtool_class=Qt4ConfigToolDependency,
+)
+
+packages['qt5'] = qt5_factory = DependencyFactory(
+    'qt5',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    pkgconfig_class=Qt5PkgConfigDependency,
+    configtool_class=Qt5ConfigToolDependency,
+)
+
+packages['qt6'] = qt6_factory = DependencyFactory(
+    'qt6',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL],
+    pkgconfig_class=Qt6PkgConfigDependency,
+    configtool_class=Qt6ConfigToolDependency,
+)
diff --git a/devtools/meson/mesonbuild/dependencies/scalapack.py b/devtools/meson/mesonbuild/dependencies/scalapack.py
new file mode 100644
index 0000000..257e4aa
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/scalapack.py
@@ -0,0 +1,159 @@
+# Copyright 2013-2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from pathlib import Path
+import functools
+import os
+import typing as T
+
+from ..mesonlib import OptionKey
+from .base import DependencyMethods
+from .base import DependencyException
+from .cmake import CMakeDependency
+from .detect import packages
+from .pkgconfig import PkgConfigDependency
+from .factory import factory_methods
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment, MachineChoice
+    from .factory import DependencyGenerator
+
+
+@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
+def scalapack_factory(env: 'Environment', for_machine: 'MachineChoice',
+                      kwargs: T.Dict[str, T.Any],
+                      methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
+    candidates: T.List['DependencyGenerator'] = []
+
+    if DependencyMethods.PKGCONFIG in methods:
+        static_opt = kwargs.get('static', env.coredata.get_option(OptionKey('prefer_static')))
+        mkl = 'mkl-static-lp64-iomp' if static_opt else 'mkl-dynamic-lp64-iomp'
+        candidates.append(functools.partial(
+            MKLPkgConfigDependency, mkl, env, kwargs))
+
+        for pkg in ['scalapack-openmpi', 'scalapack']:
+            candidates.append(functools.partial(
+                PkgConfigDependency, pkg, env, kwargs))
+
+    if DependencyMethods.CMAKE in methods:
+        candidates.append(functools.partial(
+            CMakeDependency, 'Scalapack', env, kwargs))
+
+    return candidates
+
+packages['scalapack'] = scalapack_factory
+
+
+class MKLPkgConfigDependency(PkgConfigDependency):
+
+    """PkgConfigDependency for Intel MKL.
+
+    MKL's pkg-config is pretty much borked in every way. We need to apply a
+    bunch of fixups to make it work correctly.
+    """
+
+    def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
+                 language: T.Optional[str] = None):
+        _m = os.environ.get('MKLROOT')
+        self.__mklroot = Path(_m).resolve() if _m else None
+
+        # We need to call down into the normal super() method even if we don't
+        # find mklroot, otherwise we won't have all of the instance variables
+        # initialized that meson expects.
+        super().__init__(name, env, kwargs, language=language)
+
+        # Doesn't work with gcc on windows, but does on Linux
+        if (not self.__mklroot or (env.machines[self.for_machine].is_windows()
+                                   and self.clib_compiler.id == 'gcc')):
+            self.is_found = False
+
+        # This can happen either because we're using GCC, we couldn't find the
+        # mklroot, or the pkg-config couldn't find it.
+        if not self.is_found:
+            return
+
+        assert self.version != '', 'This should not happen if we didn\'t return above'
+
+        if self.version == 'unknown':
+            # At least by 2020 the version is in the pkg-config, just not with
+            # the correct name
+            v = self.get_variable(pkgconfig='Version', default_value='')
+
+            if not v and self.__mklroot:
+                try:
+                    v = (
+                        self.__mklroot.as_posix()
+                        .split('compilers_and_libraries_')[1]
+                        .split('/', 1)[0]
+                    )
+                except IndexError:
+                    pass
+
+            if v:
+                assert isinstance(v, str)
+                self.version = v
+
+    def _set_libs(self) -> None:
+        super()._set_libs()
+
+        if self.env.machines[self.for_machine].is_windows():
+            suffix = '.lib'
+        elif self.static:
+            suffix = '.a'
+        else:
+            suffix = ''
+        libdir = self.__mklroot / 'lib/intel64'
+
+        if self.clib_compiler.id == 'gcc':
+            for i, a in enumerate(self.link_args):
+                # only replace in filename, not in directory names
+                dirname, basename = os.path.split(a)
+                if 'mkl_intel_lp64' in basename:
+                    basename = basename.replace('intel', 'gf')
+                    self.link_args[i] = '/' + os.path.join(dirname, basename)
+        # MKL pkg-config omits scalapack
+        # be sure "-L" and "-Wl" are first if present
+        i = 0
+        for j, a in enumerate(self.link_args):
+            if a.startswith(('-L', '-Wl')):
+                i = j + 1
+            elif j > 3:
+                break
+        if self.env.machines[self.for_machine].is_windows() or self.static:
+            self.link_args.insert(
+                i, str(libdir / ('mkl_scalapack_lp64' + suffix))
+            )
+            self.link_args.insert(
+                i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
+            )
+        else:
+            self.link_args.insert(i, '-lmkl_scalapack_lp64')
+            self.link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
+
+    def _set_cargs(self) -> None:
+        env = None
+        if self.language == 'fortran':
+            # gfortran doesn't appear to look in system paths for INCLUDE files,
+            # so don't allow pkg-config to suppress -I flags for system paths
+            env = os.environ.copy()
+            env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1'
+        ret, out, err = self._call_pkgbin([
+            '--cflags', self.name,
+            '--define-variable=prefix=' + self.__mklroot.as_posix()],
+            env=env)
+        if ret != 0:
+            raise DependencyException('Could not generate cargs for %s:\n%s\n' %
+                                      (self.name, err))
+        self.compile_args = self._convert_mingw_paths(self._split_args(out))
diff --git a/devtools/meson/mesonbuild/dependencies/ui.py b/devtools/meson/mesonbuild/dependencies/ui.py
new file mode 100644
index 0000000..1dffa1f
--- /dev/null
+++ b/devtools/meson/mesonbuild/dependencies/ui.py
@@ -0,0 +1,268 @@
+# Copyright 2013-2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file contains the detection logic for external dependencies that
+# are UI-related.
+from __future__ import annotations
+
+import os
+import subprocess
+import typing as T
+
+from .. import mlog
+from .. import mesonlib
+from ..mesonlib import (
+    Popen_safe, extract_as_list, version_compare_many
+)
+from ..environment import detect_cpu_family
+
+from .base import DependencyException, DependencyMethods, DependencyTypeName, SystemDependency
+from .configtool import ConfigToolDependency
+from .detect import packages
+from .factory import DependencyFactory
+
+if T.TYPE_CHECKING:
+    from ..environment import Environment
+
+
+class GLDependencySystem(SystemDependency):
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__(name, environment, kwargs)
+
+        if self.env.machines[self.for_machine].is_darwin():
+            self.is_found = True
+            # FIXME: Use AppleFrameworks dependency
+            self.link_args = ['-framework', 'OpenGL']
+            # FIXME: Detect version using self.clib_compiler
+            return
+        elif self.env.machines[self.for_machine].is_windows():
+            self.is_found = True
+            # FIXME: Use self.clib_compiler.find_library()
+            self.link_args = ['-lopengl32']
+            # FIXME: Detect version using self.clib_compiler
+            return
+        else:
+            links = self.clib_compiler.find_library('GL', environment, [])
+            has_header = self.clib_compiler.has_header('GL/gl.h', '', environment)[0]
+            if links and has_header:
+                self.is_found = True
+                self.link_args = links
+            elif links:
+                raise DependencyException('Found GL runtime library but no development header files')
+
+class GnuStepDependency(ConfigToolDependency):
+
+    tools = ['gnustep-config']
+    tool_name = 'gnustep-config'
+
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
+        super().__init__('gnustep', environment, kwargs, language='objc')
+        if not self.is_found:
+            return
+        self.modules = kwargs.get('modules', [])
+        self.compile_args = self.filter_args(
+            self.get_config_value(['--objc-flags'], 'compile_args'))
+        self.link_args = self.weird_filter(self.get_config_value(
+            ['--gui-libs' if 'gui' in self.modules else '--base-libs'],
+            'link_args'))
+
+    def find_config(self, versions: T.Optional[T.List[str]] = None, returncode: int = 0) -> T.Tuple[T.Optional[T.List[str]], T.Optional[str]]:
+        tool = [self.tools[0]]
+        try:
+            p, out = Popen_safe(tool + ['--help'])[:2]
+        except (FileNotFoundError, PermissionError):
+            return (None, None)
+        if p.returncode != returncode:
+            return (None, None)
+        self.config = tool
+        found_version = self.detect_version()
+        if versions and not version_compare_many(found_version, versions)[0]:
+            return (None, found_version)
+
+        return (tool, found_version)
+
+    @staticmethod
+    def weird_filter(elems: T.List[str]) -> T.List[str]:
+        """When building packages, the output of the enclosing Make is
+        sometimes mixed among the subprocess output. I have no idea why. As a
+        hack filter out everything that is not a flag.
+        """
+        return [e for e in elems if e.startswith('-')]
+
+    @staticmethod
+    def filter_args(args: T.List[str]) -> T.List[str]:
+        """gnustep-config returns a bunch of garbage args such as -O2 and so
+        on. Drop everything that is not needed.
+        """
+        result = []
+        for f in args:
+            if f.startswith('-D') \
+                    or f.startswith('-f') \
+                    or f.startswith('-I') \
+                    or f == '-pthread' \
+                    or (f.startswith('-W') and not f == '-Wall'):
+                result.append(f)
+        return result
+
+    def detect_version(self) -> str:
+        gmake = self.get_config_value(['--variable=GNUMAKE'], 'variable')[0]
+        makefile_dir = self.get_config_value(['--variable=GNUSTEP_MAKEFILES'], 'variable')[0]
+        # This Makefile has the GNUStep version set
+        base_make = os.path.join(makefile_dir, 'Additional', 'base.make')
+        # Print the Makefile variable passed as the argument. For instance, if
+        # you run the make target `print-SOME_VARIABLE`, this will print the
+        # value of the variable `SOME_VARIABLE`.
+        printver = "print-%:\n\t@echo '$($*)'"
+        env = os.environ.copy()
+        # See base.make to understand why this is set
+        env['FOUNDATION_LIB'] = 'gnu'
+        p, o, e = Popen_safe([gmake, '-f', '-', '-f', base_make,
+                              'print-GNUSTEP_BASE_VERSION'],
+                             env=env, write=printver, stdin=subprocess.PIPE)
+        version = o.strip()
+        if not version:
+            mlog.debug("Couldn't detect GNUStep version, falling back to '1'")
+            # Fallback to setting some 1.x version
+            version = '1'
+        return version
+
+packages['gnustep'] = GnuStepDependency
+
+
+class SDL2DependencyConfigTool(ConfigToolDependency):
+
+    tools = ['sdl2-config']
+    tool_name = 'sdl2-config'
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__(name, environment, kwargs)
+        if not self.is_found:
+            return
+        self.compile_args = self.get_config_value(['--cflags'], 'compile_args')
+        self.link_args = self.get_config_value(['--libs'], 'link_args')
+
+
+class WxDependency(ConfigToolDependency):
+
+    tools = ['wx-config-3.0', 'wx-config-3.1', 'wx-config', 'wx-config-gtk3']
+    tool_name = 'wx-config'
+
+    def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+        super().__init__('WxWidgets', environment, kwargs, language='cpp')
+        if not self.is_found:
+            return
+        self.requested_modules = self.get_requested(kwargs)
+
+        extra_args = []
+        if self.static:
+            extra_args.append('--static=yes')
+
+            # Check to make sure static is going to work
+            err = Popen_safe(self.config + extra_args)[2]
+            if 'No config found to match' in err:
+                mlog.debug('WxWidgets is missing static libraries.')
+                self.is_found = False
+                return
+
+        # wx-config seems to have a cflags as well but since it requires C++,
+        # this should be good, at least for now.
+        self.compile_args = self.get_config_value(['--cxxflags'] + extra_args + self.requested_modules, 'compile_args')
+        self.link_args = self.get_config_value(['--libs'] + extra_args + self.requested_modules, 'link_args')
+
+    @staticmethod
+    def get_requested(kwargs: T.Dict[str, T.Any]) -> T.List[str]:
+        if 'modules' not in kwargs:
+            return []
+        candidates = extract_as_list(kwargs, 'modules')
+        for c in candidates:
+            if not isinstance(c, str):
+                raise DependencyException('wxwidgets module argument is not a string')
+        return candidates
+
+packages['wxwidgets'] = WxDependency
+
+class VulkanDependencySystem(SystemDependency):
+
+    def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
+        super().__init__(name, environment, kwargs, language=language)
+
+        try:
+            self.vulkan_sdk = os.environ['VULKAN_SDK']
+            if not os.path.isabs(self.vulkan_sdk):
+                raise DependencyException('VULKAN_SDK must be an absolute path.')
+        except KeyError:
+            self.vulkan_sdk = None
+
+        if self.vulkan_sdk:
+            # TODO: this config might not work on some platforms, fix bugs as reported
+            # we should at least detect other 64-bit platforms (e.g. armv8)
+            lib_name = 'vulkan'
+            lib_dir = 'lib'
+            inc_dir = 'include'
+            if mesonlib.is_windows():
+                lib_name = 'vulkan-1'
+                lib_dir = 'Lib32'
+                inc_dir = 'Include'
+                if detect_cpu_family(self.env.coredata.compilers.host) == 'x86_64':
+                    lib_dir = 'Lib'
+
+            # make sure header and lib are valid
+            inc_path = os.path.join(self.vulkan_sdk, inc_dir)
+            header = os.path.join(inc_path, 'vulkan', 'vulkan.h')
+            lib_path = os.path.join(self.vulkan_sdk, lib_dir)
+            find_lib = self.clib_compiler.find_library(lib_name, environment, [lib_path])
+
+            if not find_lib:
+                raise DependencyException('VULKAN_SDK point to invalid directory (no lib)')
+
+            if not os.path.isfile(header):
+                raise DependencyException('VULKAN_SDK point to invalid directory (no include)')
+
+            # XXX: this is very odd, and may deserve being removed
+            self.type_name = DependencyTypeName('vulkan_sdk')
+            self.is_found = True
+            self.compile_args.append('-I' + inc_path)
+            self.link_args.append('-L' + lib_path)
+            self.link_args.append('-l' + lib_name)
+
+            # TODO: find a way to retrieve the version from the sdk?
+            # Usually it is a part of the path to it (but does not have to be)
+            return
+        else:
+            # simply try to guess it, usually works on linux
+            libs = self.clib_compiler.find_library('vulkan', environment, [])
+            if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment, disable_cache=True)[0]:
+                self.is_found = True
+                for lib in libs:
+                    self.link_args.append(lib)
+                return
+
+packages['gl'] = gl_factory = DependencyFactory(
+    'gl',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    system_class=GLDependencySystem,
+)
+
+packages['sdl2'] = sdl2_factory = DependencyFactory(
+    'sdl2',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.EXTRAFRAMEWORK, DependencyMethods.CMAKE],
+    configtool_class=SDL2DependencyConfigTool,
+    cmake_name='SDL2',
+)
+
+packages['vulkan'] = vulkan_factory = DependencyFactory(
+    'vulkan',
+    [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+    system_class=VulkanDependencySystem,
+)
diff --git a/devtools/meson/mesonbuild/depfile.py b/devtools/meson/mesonbuild/depfile.py
new file mode 100644
index 0000000..d346136
--- /dev/null
+++ b/devtools/meson/mesonbuild/depfile.py
@@ -0,0 +1,91 @@
+# Copyright 2019 Red Hat, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import typing as T
+
+
+def parse(lines: T.Iterable[str]) -> T.List[T.Tuple[T.List[str], T.List[str]]]:
+    rules: T.List[T.Tuple[T.List[str], T.List[str]]] = []
+    targets: T.List[str] = []
+    deps: T.List[str] = []
+    in_deps = False
+    out = ''
+    for line in lines:
+        if not line.endswith('\n'):
+            line += '\n'
+        escape = None
+        for c in line:
+            if escape:
+                if escape == '$' and c != '$':
+                    out += '$'
+                if escape == '\\' and c == '\n':
+                    continue
+                out += c
+                escape = None
+                continue
+            if c in {'\\', '$'}:
+                escape = c
+                continue
+            elif c in {' ', '\n'}:
+                if out != '':
+                    if in_deps:
+                        deps.append(out)
+                    else:
+                        targets.append(out)
+                out = ''
+                if c == '\n':
+                    rules.append((targets, deps))
+                    targets = []
+                    deps = []
+                    in_deps = False
+                continue
+            elif c == ':':
+                targets.append(out)
+                out = ''
+                in_deps = True
+                continue
+            out += c
+    return rules
+
+class Target(T.NamedTuple):
+
+    deps: T.Set[str]
+
+
+class DepFile:
+    def __init__(self, lines: T.Iterable[str]):
+        rules = parse(lines)
+        depfile: T.Dict[str, Target] = {}
+        for (targets, deps) in rules:
+            for target in targets:
+                t = depfile.setdefault(target, Target(deps=set()))
+                for dep in deps:
+                    t.deps.add(dep)
+        self.depfile = depfile
+
+    def get_all_dependencies(self, name: str, visited: T.Optional[T.Set[str]] = None) -> T.List[str]:
+        deps: T.Set[str] = set()
+        if not visited:
+            visited = set()
+        if name in visited:
+            return []
+        visited.add(name)
+
+        target = self.depfile.get(name)
+        if not target:
+            return []
+        deps.update(target.deps)
+        for dep in target.deps:
+            deps.update(self.get_all_dependencies(dep, visited))
+        return sorted(deps)
diff --git a/devtools/meson/mesonbuild/envconfig.py b/devtools/meson/mesonbuild/envconfig.py
new file mode 100644
index 0000000..cd464fd
--- /dev/null
+++ b/devtools/meson/mesonbuild/envconfig.py
@@ -0,0 +1,475 @@
+# Copyright 2012-2016 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+from dataclasses import dataclass
+import subprocess
+import typing as T
+from enum import Enum
+
+from . import mesonlib
+from .mesonlib import EnvironmentException, HoldableObject
+from . import mlog
+from pathlib import Path
+
+
+# These classes contains all the data pulled from configuration files (native
+# and cross file currently), and also assists with the reading environment
+# variables.
+#
+# At this time there isn't an ironclad difference between this and other sources
+# of state like `coredata`. But one rough guide is much what is in `coredata` is
+# the *output* of the configuration process: the final decisions after tests.
+# This, on the other hand has *inputs*. The config files are parsed, but
+# otherwise minimally transformed. When more complex fallbacks (environment
+# detection) exist, they are defined elsewhere as functions that construct
+# instances of these classes.
+
+
+known_cpu_families = (
+    'aarch64',
+    'alpha',
+    'arc',
+    'arm',
+    'avr',
+    'c2000',
+    'csky',
+    'dspic',
+    'e2k',
+    'ft32',
+    'ia64',
+    'loongarch64',
+    'm68k',
+    'microblaze',
+    'mips',
+    'mips64',
+    'msp430',
+    'parisc',
+    'pic24',
+    'ppc',
+    'ppc64',
+    'riscv32',
+    'riscv64',
+    'rl78',
+    'rx',
+    's390',
+    's390x',
+    'sh4',
+    'sparc',
+    'sparc64',
+    'sw_64',
+    'wasm32',
+    'wasm64',
+    'x86',
+    'x86_64',
+)
+
+# It would feel more natural to call this "64_BIT_CPU_FAMILIES", but
+# python identifiers cannot start with numbers
+CPU_FAMILIES_64_BIT = [
+    'aarch64',
+    'alpha',
+    'ia64',
+    'loongarch64',
+    'mips64',
+    'ppc64',
+    'riscv64',
+    's390x',
+    'sparc64',
+    'sw_64',
+    'wasm64',
+    'x86_64',
+]
+
+# Map from language identifiers to environment variables.
+ENV_VAR_COMPILER_MAP: T.Mapping[str, str] = {
+    # Compilers
+    'c': 'CC',
+    'cpp': 'CXX',
+    'cs': 'CSC',
+    'd': 'DC',
+    'fortran': 'FC',
+    'objc': 'OBJC',
+    'objcpp': 'OBJCXX',
+    'rust': 'RUSTC',
+    'vala': 'VALAC',
+    'nasm': 'NASM',
+
+    # Linkers
+    'c_ld': 'CC_LD',
+    'cpp_ld': 'CXX_LD',
+    'd_ld': 'DC_LD',
+    'fortran_ld': 'FC_LD',
+    'objc_ld': 'OBJC_LD',
+    'objcpp_ld': 'OBJCXX_LD',
+    'rust_ld': 'RUSTC_LD',
+}
+
+# Map from utility names to environment variables.
+ENV_VAR_TOOL_MAP: T.Mapping[str, str] = {
+    # Binutils
+    'ar': 'AR',
+    'as': 'AS',
+    'ld': 'LD',
+    'nm': 'NM',
+    'objcopy': 'OBJCOPY',
+    'objdump': 'OBJDUMP',
+    'ranlib': 'RANLIB',
+    'readelf': 'READELF',
+    'size': 'SIZE',
+    'strings': 'STRINGS',
+    'strip': 'STRIP',
+    'windres': 'WINDRES',
+
+    # Other tools
+    'cmake': 'CMAKE',
+    'qmake': 'QMAKE',
+    'pkgconfig': 'PKG_CONFIG',
+    'pkg-config': 'PKG_CONFIG',
+    'make': 'MAKE',
+    'vapigen': 'VAPIGEN',
+    'llvm-config': 'LLVM_CONFIG',
+}
+
+ENV_VAR_PROG_MAP = {**ENV_VAR_COMPILER_MAP, **ENV_VAR_TOOL_MAP}
+
+# Deprecated environment variables mapped from the new variable to the old one
+# Deprecated in 0.54.0
+DEPRECATED_ENV_PROG_MAP: T.Mapping[str, str] = {
+    'd_ld': 'D_LD',
+    'fortran_ld': 'F_LD',
+    'rust_ld': 'RUST_LD',
+    'objcpp_ld': 'OBJCPP_LD',
+}
+
+class CMakeSkipCompilerTest(Enum):
+    ALWAYS = 'always'
+    NEVER = 'never'
+    DEP_ONLY = 'dep_only'
+
+class Properties:
+    def __init__(
+            self,
+            properties: T.Optional[T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]]] = None,
+    ):
+        self.properties = properties or {}  # type: T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]]
+
+    def has_stdlib(self, language: str) -> bool:
+        return language + '_stdlib' in self.properties
+
+    # Some of get_stdlib, get_root, get_sys_root are wider than is actually
+    # true, but without heterogeneous dict annotations it's not practical to
+    # narrow them
+    def get_stdlib(self, language: str) -> T.Union[str, T.List[str]]:
+        stdlib = self.properties[language + '_stdlib']
+        if isinstance(stdlib, str):
+            return stdlib
+        assert isinstance(stdlib, list)
+        for i in stdlib:
+            assert isinstance(i, str)
+        return stdlib
+
+    def get_root(self) -> T.Optional[str]:
+        root = self.properties.get('root', None)
+        assert root is None or isinstance(root, str)
+        return root
+
+    def get_sys_root(self) -> T.Optional[str]:
+        sys_root = self.properties.get('sys_root', None)
+        assert sys_root is None or isinstance(sys_root, str)
+        return sys_root
+
+    def get_pkg_config_libdir(self) -> T.Optional[T.List[str]]:
+        p = self.properties.get('pkg_config_libdir', None)
+        if p is None:
+            return p
+        res = mesonlib.listify(p)
+        for i in res:
+            assert isinstance(i, str)
+        return res
+
+    def get_cmake_defaults(self) -> bool:
+        if 'cmake_defaults' not in self.properties:
+            return True
+        res = self.properties['cmake_defaults']
+        assert isinstance(res, bool)
+        return res
+
+    def get_cmake_toolchain_file(self) -> T.Optional[Path]:
+        if 'cmake_toolchain_file' not in self.properties:
+            return None
+        raw = self.properties['cmake_toolchain_file']
+        assert isinstance(raw, str)
+        cmake_toolchain_file = Path(raw)
+        if not cmake_toolchain_file.is_absolute():
+            raise EnvironmentException(f'cmake_toolchain_file ({raw}) is not absolute')
+        return cmake_toolchain_file
+
+    def get_cmake_skip_compiler_test(self) -> CMakeSkipCompilerTest:
+        if 'cmake_skip_compiler_test' not in self.properties:
+            return CMakeSkipCompilerTest.DEP_ONLY
+        raw = self.properties['cmake_skip_compiler_test']
+        assert isinstance(raw, str)
+        try:
+            return CMakeSkipCompilerTest(raw)
+        except ValueError:
+            raise EnvironmentException(
+                '"{}" is not a valid value for cmake_skip_compiler_test. Supported values are {}'
+                .format(raw, [e.value for e in CMakeSkipCompilerTest]))
+
+    def get_cmake_use_exe_wrapper(self) -> bool:
+        if 'cmake_use_exe_wrapper' not in self.properties:
+            return True
+        res = self.properties['cmake_use_exe_wrapper']
+        assert isinstance(res, bool)
+        return res
+
+    def get_java_home(self) -> T.Optional[Path]:
+        value = T.cast('T.Optional[str]', self.properties.get('java_home'))
+        return Path(value) if value else None
+
+    def get_bindgen_clang_args(self) -> T.List[str]:
+        value = mesonlib.listify(self.properties.get('bindgen_clang_arguments', []))
+        if not all(isinstance(v, str) for v in value):
+            raise EnvironmentException('bindgen_clang_arguments must be a string or an array of strings')
+        return T.cast('T.List[str]', value)
+
+    def __eq__(self, other: object) -> bool:
+        if isinstance(other, type(self)):
+            return self.properties == other.properties
+        return NotImplemented
+
+    # TODO consider removing so Properties is less freeform
+    def __getitem__(self, key: str) -> T.Optional[T.Union[str, bool, int, T.List[str]]]:
+        return self.properties[key]
+
+    # TODO consider removing so Properties is less freeform
+    def __contains__(self, item: T.Union[str, bool, int, T.List[str]]) -> bool:
+        return item in self.properties
+
+    # TODO consider removing, for same reasons as above
+    def get(self, key: str, default: T.Optional[T.Union[str, bool, int, T.List[str]]] = None) -> T.Optional[T.Union[str, bool, int, T.List[str]]]:
+        return self.properties.get(key, default)
+
+@dataclass(unsafe_hash=True)
+class MachineInfo(HoldableObject):
+    system: str
+    cpu_family: str
+    cpu: str
+    endian: str
+    kernel: T.Optional[str]
+    subsystem: T.Optional[str]
+
+    def __post_init__(self) -> None:
+        self.is_64_bit: bool = self.cpu_family in CPU_FAMILIES_64_BIT
+
+    def __repr__(self) -> str:
+        return f''
+
+    @classmethod
+    def from_literal(cls, literal: T.Dict[str, str]) -> 'MachineInfo':
+        minimum_literal = {'cpu', 'cpu_family', 'endian', 'system'}
+        if set(literal) < minimum_literal:
+            raise EnvironmentException(
+                f'Machine info is currently {literal}\n' +
+                'but is missing {}.'.format(minimum_literal - set(literal)))
+
+        cpu_family = literal['cpu_family']
+        if cpu_family not in known_cpu_families:
+            mlog.warning(f'Unknown CPU family {cpu_family}, please report this at https://github.com/mesonbuild/meson/issues/new')
+
+        endian = literal['endian']
+        if endian not in ('little', 'big'):
+            mlog.warning(f'Unknown endian {endian}')
+
+        system = literal['system']
+        kernel = literal.get('kernel', None)
+        subsystem = literal.get('subsystem', None)
+
+        return cls(system, cpu_family, literal['cpu'], endian, kernel, subsystem)
+
+    def is_windows(self) -> bool:
+        """
+        Machine is windows?
+        """
+        return self.system == 'windows'
+
+    def is_cygwin(self) -> bool:
+        """
+        Machine is cygwin?
+        """
+        return self.system == 'cygwin'
+
+    def is_linux(self) -> bool:
+        """
+        Machine is linux?
+        """
+        return self.system == 'linux'
+
+    def is_darwin(self) -> bool:
+        """
+        Machine is Darwin (iOS/tvOS/OS X)?
+        """
+        return self.system in {'darwin', 'ios', 'tvos'}
+
+    def is_android(self) -> bool:
+        """
+        Machine is Android?
+        """
+        return self.system == 'android'
+
+    def is_haiku(self) -> bool:
+        """
+        Machine is Haiku?
+        """
+        return self.system == 'haiku'
+
+    def is_netbsd(self) -> bool:
+        """
+        Machine is NetBSD?
+        """
+        return self.system == 'netbsd'
+
+    def is_openbsd(self) -> bool:
+        """
+        Machine is OpenBSD?
+        """
+        return self.system == 'openbsd'
+
+    def is_dragonflybsd(self) -> bool:
+        """Machine is DragonflyBSD?"""
+        return self.system == 'dragonfly'
+
+    def is_freebsd(self) -> bool:
+        """Machine is FreeBSD?"""
+        return self.system == 'freebsd'
+
+    def is_sunos(self) -> bool:
+        """Machine is illumos or Solaris?"""
+        return self.system == 'sunos'
+
+    def is_hurd(self) -> bool:
+        """
+        Machine is GNU/Hurd?
+        """
+        return self.system == 'gnu'
+
+    def is_aix(self) -> bool:
+        """
+        Machine is aix?
+        """
+        return self.system == 'aix'
+
+    def is_irix(self) -> bool:
+        """Machine is IRIX?"""
+        return self.system.startswith('irix')
+
+    # Various prefixes and suffixes for import libraries, shared libraries,
+    # static libraries, and executables.
+    # Versioning is added to these names in the backends as-needed.
+    def get_exe_suffix(self) -> str:
+        if self.is_windows() or self.is_cygwin():
+            return 'exe'
+        else:
+            return ''
+
+    def get_object_suffix(self) -> str:
+        if self.is_windows():
+            return 'obj'
+        else:
+            return 'o'
+
+    def libdir_layout_is_win(self) -> bool:
+        return self.is_windows() or self.is_cygwin()
+
+class BinaryTable:
+
+    def __init__(
+            self,
+            binaries: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None,
+    ):
+        self.binaries: T.Dict[str, T.List[str]] = {}
+        if binaries:
+            for name, command in binaries.items():
+                if not isinstance(command, (list, str)):
+                    raise mesonlib.MesonException(
+                        f'Invalid type {command!r} for entry {name!r} in cross file')
+                self.binaries[name] = mesonlib.listify(command)
+
+    @staticmethod
+    def detect_ccache() -> T.List[str]:
+        try:
+            subprocess.check_call(['ccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except (OSError, subprocess.CalledProcessError):
+            return []
+        return ['ccache']
+
+    @staticmethod
+    def detect_sccache() -> T.List[str]:
+        try:
+            subprocess.check_call(['sccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except (OSError, subprocess.CalledProcessError):
+            return []
+        return ['sccache']
+
+    @staticmethod
+    def detect_compiler_cache() -> T.List[str]:
+        # Sccache is "newer" so it is assumed that people would prefer it by default.
+        cache = BinaryTable.detect_sccache()
+        if cache:
+            return cache
+        return BinaryTable.detect_ccache()
+
+    @classmethod
+    def parse_entry(cls, entry: T.Union[str, T.List[str]]) -> T.Tuple[T.List[str], T.List[str]]:
+        compiler = mesonlib.stringlistify(entry)
+        # Ensure ccache exists and remove it if it doesn't
+        if compiler[0] == 'ccache':
+            compiler = compiler[1:]
+            ccache = cls.detect_ccache()
+        elif compiler[0] == 'sccache':
+            compiler = compiler[1:]
+            ccache = cls.detect_sccache()
+        else:
+            ccache = []
+        # Return value has to be a list of compiler 'choices'
+        return compiler, ccache
+
+    def lookup_entry(self, name: str) -> T.Optional[T.List[str]]:
+        """Lookup binary in cross/native file and fallback to environment.
+
+        Returns command with args as list if found, Returns `None` if nothing is
+        found.
+        """
+        command = self.binaries.get(name)
+        if not command:
+            return None
+        elif not command[0].strip():
+            return None
+        return command
+
+class CMakeVariables:
+    def __init__(self, variables: T.Optional[T.Dict[str, T.Any]] = None) -> None:
+        variables = variables or {}
+        self.variables = {}  # type: T.Dict[str, T.List[str]]
+
+        for key, value in variables.items():
+            value = mesonlib.listify(value)
+            for i in value:
+                if not isinstance(i, str):
+                    raise EnvironmentException(f"Value '{i}' of CMake variable '{key}' defined in a machine file is a {type(i).__name__} and not a str")
+            self.variables[key] = value
+
+    def get_variables(self) -> T.Dict[str, T.List[str]]:
+        return self.variables
diff --git a/devtools/meson/mesonbuild/environment.py b/devtools/meson/mesonbuild/environment.py
new file mode 100644
index 0000000..cd9d487
--- /dev/null
+++ b/devtools/meson/mesonbuild/environment.py
@@ -0,0 +1,923 @@
+# Copyright 2012-2020 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from __future__ import annotations
+
+import itertools
+import os, platform, re, sys, shutil
+import typing as T
+import collections
+
+from . import coredata
+from . import mesonlib
+from .mesonlib import (
+    MesonException, MachineChoice, Popen_safe, PerMachine,
+    PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg, OptionKey,
+    search_version, MesonBugException
+)
+from . import mlog
+from .programs import ExternalProgram
+
+from .envconfig import (
+    BinaryTable, MachineInfo, Properties, known_cpu_families, CMakeVariables,
+)
+from . import compilers
+from .compilers import (
+    Compiler,
+    is_assembly,
+    is_header,
+    is_library,
+    is_llvm_ir,
+    is_object,
+    is_source,
+)
+
+from functools import lru_cache
+from mesonbuild import envconfig
+
+if T.TYPE_CHECKING:
+    import argparse
+    from configparser import ConfigParser
+
+    from .wrap.wrap import Resolver
+
+    CompilersDict = T.Dict[str, Compiler]
+
+
+build_filename = 'meson.build'
+
+
+def _get_env_var(for_machine: MachineChoice, is_cross: bool, var_name: str) -> T.Optional[str]:
+    """
+    Returns the exact env var and the value.
+    """
+    candidates = PerMachine(
+        # The prefixed build version takes priority, but if we are native
+        # compiling we fall back on the unprefixed host version. This
+        # allows native builds to never need to worry about the 'BUILD_*'
+        # ones.
+        ([var_name + '_FOR_BUILD'] if is_cross else [var_name]),
+        # Always just the unprefixed host versions
+        [var_name]
+    )[for_machine]
+    for var in candidates:
+        value = os.environ.get(var)
+        if value is not None:
+            break
+    else:
+        formatted = ', '.join([f'{var!r}' for var in candidates])
+        mlog.debug(f'None of {formatted} are defined in the environment, not changing global flags.')
+        return None
+    mlog.debug(f'Using {var!r} from environment with value: {value!r}')
+    return value
+
+
+def detect_gcovr(min_version='3.3', log=False):
+    gcovr_exe = 'gcovr'
+    try:
+        p, found = Popen_safe([gcovr_exe, '--version'])[0:2]
+    except (FileNotFoundError, PermissionError):
+        # Doesn't exist in PATH or isn't executable
+        return None, None
+    found = search_version(found)
+    if p.returncode == 0 and mesonlib.version_compare(found, '>=' + min_version):
+        if log:
+            mlog.log('Found gcovr-{} at {}'.format(found, quote_arg(shutil.which(gcovr_exe))))
+        return gcovr_exe, found
+    return None, None
+
+def detect_llvm_cov():
+    tools = get_llvm_tool_names('llvm-cov')
+    for tool in tools:
+        if mesonlib.exe_exists([tool, '--version']):
+            return tool
+    return None
+
+def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]:
+    gcovr_exe, gcovr_version = detect_gcovr()
+
+    llvm_cov_exe = detect_llvm_cov()
+
+    lcov_exe = 'lcov'
+    genhtml_exe = 'genhtml'
+
+    if not mesonlib.exe_exists([lcov_exe, '--version']):
+        lcov_exe = None
+    if not mesonlib.exe_exists([genhtml_exe, '--version']):
+        genhtml_exe = None
+
+    return gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe
+
+def detect_ninja(version: str = '1.8.2', log: bool = False) -> T.List[str]:
+    r = detect_ninja_command_and_version(version, log)
+    return r[0] if r else None
+
+def detect_ninja_command_and_version(version: str = '1.8.2', log: bool = False) -> T.Tuple[T.List[str], str]:
+    env_ninja = os.environ.get('NINJA', None)
+    for n in [env_ninja] if env_ninja else ['ninja', 'ninja-build', 'samu']:
+        prog = ExternalProgram(n, silent=True)
+        if not prog.found():
+            continue
+        try:
+            p, found = Popen_safe(prog.command + ['--version'])[0:2]
+        except (FileNotFoundError, PermissionError):
+            # Doesn't exist in PATH or isn't executable
+            continue
+        found = found.strip()
+        # Perhaps we should add a way for the caller to know the failure mode
+        # (not found or too old)
+        if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version):
+            if log:
+                name = os.path.basename(n)
+                if name.endswith('-' + found):
+                    name = name[0:-1 - len(found)]
+                if name == 'ninja-build':
+                    name = 'ninja'
+                if name == 'samu':
+                    name = 'samurai'
+                mlog.log('Found {}-{} at {}'.format(name, found,
+                         ' '.join([quote_arg(x) for x in prog.command])))
+            return (prog.command, found)
+
+def get_llvm_tool_names(tool: str) -> T.List[str]:
+    # Ordered list of possible suffixes of LLVM executables to try. Start with
+    # base, then try newest back to oldest (3.5 is arbitrary), and finally the
+    # devel version. Please note that the development snapshot in Debian does
+    # not have a distinct name. Do not move it to the beginning of the list
+    # unless it becomes a stable release.
+    suffixes = [
+        '', # base (no suffix)
+        '-17',  '17',
+        '-16',  '16',
+        '-15',  '15',
+        '-14',  '14',
+        '-13',  '13',
+        '-12',  '12',
+        '-11',  '11',
+        '-10',  '10',
+        '-9',   '90',
+        '-8',   '80',
+        '-7',   '70',
+        '-6.0', '60',
+        '-5.0', '50',
+        '-4.0', '40',
+        '-3.9', '39',
+        '-3.8', '38',
+        '-3.7', '37',
+        '-3.6', '36',
+        '-3.5', '35',
+        '-15',    # Debian development snapshot
+        '-devel', # FreeBSD development snapshot
+    ]
+    names = []
+    for suffix in suffixes:
+        names.append(tool + suffix)
+    return names
+
+def detect_scanbuild() -> T.List[str]:
+    """ Look for scan-build binary on build platform
+
+    First, if a SCANBUILD env variable has been provided, give it precedence
+    on all platforms.
+
+    For most platforms, scan-build is found is the PATH contains a binary
+    named "scan-build". However, some distribution's package manager (FreeBSD)
+    don't. For those, loop through a list of candidates to see if one is
+    available.
+
+    Return: a single-element list of the found scan-build binary ready to be
+        passed to Popen()
+    """
+    exelist = []
+    if 'SCANBUILD' in os.environ:
+        exelist = split_args(os.environ['SCANBUILD'])
+
+    else:
+        tools = get_llvm_tool_names('scan-build')
+        for tool in tools:
+            if shutil.which(tool) is not None:
+                exelist = [shutil.which(tool)]
+                break
+
+    if exelist:
+        tool = exelist[0]
+        if os.path.isfile(tool) and os.access(tool, os.X_OK):
+            return [tool]
+    return []
+
+def detect_clangformat() -> T.List[str]:
+    """ Look for clang-format binary on build platform
+
+    Do the same thing as detect_scanbuild to find clang-format except it
+    currently does not check the environment variable.
+
+    Return: a single-element list of the found clang-format binary ready to be
+        passed to Popen()
+    """
+    tools = get_llvm_tool_names('clang-format')
+    for tool in tools:
+        path = shutil.which(tool)
+        if path is not None:
+            return [path]
+    return []
+
+def detect_windows_arch(compilers: CompilersDict) -> str:
+    """
+    Detecting the 'native' architecture of Windows is not a trivial task. We
+    cannot trust that the architecture that Python is built for is the 'native'
+    one because you can run 32-bit apps on 64-bit Windows using WOW64 and
+    people sometimes install 32-bit Python on 64-bit Windows.
+
+    We also can't rely on the architecture of the OS itself, since it's
+    perfectly normal to compile and run 32-bit applications on Windows as if
+    they were native applications. It's a terrible experience to require the
+    user to supply a cross-info file to compile 32-bit applications on 64-bit
+    Windows. Thankfully, the only way to compile things with Visual Studio on
+    Windows is by entering the 'msvc toolchain' environment, which can be
+    easily detected.
+
+    In the end, the sanest method is as follows:
+    1. Check environment variables that are set by Windows and WOW64 to find out
+       if this is x86 (possibly in WOW64), if so use that as our 'native'
+       architecture.
+    2. If the compiler toolchain target architecture is x86, use that as our
+      'native' architecture.
+    3. Otherwise, use the actual Windows architecture
+
+    """
+    os_arch = mesonlib.windows_detect_native_arch()
+    if os_arch == 'x86':
+        return os_arch
+    # If we're on 64-bit Windows, 32-bit apps can be compiled without
+    # cross-compilation. So if we're doing that, just set the native arch as
+    # 32-bit and pretend like we're running under WOW64. Else, return the
+    # actual Windows architecture that we deduced above.
+    for compiler in compilers.values():
+        if compiler.id == 'msvc' and (compiler.target in {'x86', '80x86'}):
+            return 'x86'
+        if compiler.id == 'clang-cl' and compiler.target == 'x86':
+            return 'x86'
+        if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'):
+            return 'x86'
+    return os_arch
+
+def any_compiler_has_define(compilers: CompilersDict, define):
+    for c in compilers.values():
+        try:
+            if c.has_builtin_define(define):
+                return True
+        except mesonlib.MesonException:
+            # Ignore compilers that do not support has_builtin_define.
+            pass
+    return False
+
+def detect_cpu_family(compilers: CompilersDict) -> str:
+    """
+    Python is inconsistent in its platform module.
+    It returns different values for the same cpu.
+    For x86 it might return 'x86', 'i686' or somesuch.
+    Do some canonicalization.
+    """
+    if mesonlib.is_windows():
+        trial = detect_windows_arch(compilers)
+    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_qnx() or mesonlib.is_aix():
+        trial = platform.processor().lower()
+    else:
+        trial = platform.machine().lower()
+    if trial.startswith('i') and trial.endswith('86'):
+        trial = 'x86'
+    elif trial == 'bepc':
+        trial = 'x86'
+    elif trial == 'arm64':
+        trial = 'aarch64'
+    elif trial.startswith('aarch64'):
+        # This can be `aarch64_be`
+        trial = 'aarch64'
+    elif trial.startswith('arm') or trial.startswith('earm'):
+        trial = 'arm'
+    elif trial.startswith(('powerpc64', 'ppc64')):
+        trial = 'ppc64'
+    elif trial.startswith(('powerpc', 'ppc')) or trial in {'macppc', 'power macintosh'}:
+        trial = 'ppc'
+    elif trial in {'amd64', 'x64', 'i86pc'}:
+        trial = 'x86_64'
+    elif trial in {'sun4u', 'sun4v'}:
+        trial = 'sparc64'
+    elif trial.startswith('mips'):
+        if '64' not in trial:
+            trial = 'mips'
+        else:
+            trial = 'mips64'
+    elif trial in {'ip30', 'ip35'}:
+        trial = 'mips64'
+
+    # On Linux (and maybe others) there can be any mixture of 32/64 bit code in
+    # the kernel, Python, system, 32-bit chroot on 64-bit host, etc. The only
+    # reliable way to know is to check the compiler defines.
+    if trial == 'x86_64':
+        if any_compiler_has_define(compilers, '__i386__'):
+            trial = 'x86'
+    elif trial == 'aarch64':
+        if any_compiler_has_define(compilers, '__arm__'):
+            trial = 'arm'
+    # Add more quirks here as bugs are reported. Keep in sync with detect_cpu()
+    # below.
+    elif trial == 'parisc64':
+        # ATM there is no 64 bit userland for PA-RISC. Thus always
+        # report it as 32 bit for simplicity.
+        trial = 'parisc'
+    elif trial == 'ppc':
+        # AIX always returns powerpc, check here for 64-bit
+        if any_compiler_has_define(compilers, '__64BIT__'):
+            trial = 'ppc64'
+    # MIPS64 is able to run MIPS32 code natively, so there is a chance that
+    # such mixture mentioned above exists.
+    elif trial == 'mips64':
+        if compilers and not any_compiler_has_define(compilers, '__mips64'):
+            trial = 'mips'
+
+    if trial not in known_cpu_families:
+        mlog.warning(f'Unknown CPU family {trial!r}, please report this at '
+                     'https://github.com/mesonbuild/meson/issues/new with the '
+                     'output of `uname -a` and `cat /proc/cpuinfo`')
+
+    return trial
+
+def detect_cpu(compilers: CompilersDict) -> str:
+    if mesonlib.is_windows():
+        trial = detect_windows_arch(compilers)
+    elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_aix():
+        trial = platform.processor().lower()
+    else:
+        trial = platform.machine().lower()
+
+    if trial in {'amd64', 'x64', 'i86pc'}:
+        trial = 'x86_64'
+    if trial == 'x86_64':
+        # Same check as above for cpu_family
+        if any_compiler_has_define(compilers, '__i386__'):
+            trial = 'i686' # All 64 bit cpus have at least this level of x86 support.
+    elif trial.startswith('aarch64') or trial.startswith('arm64'):
+        # Same check as above for cpu_family
+        if any_compiler_has_define(compilers, '__arm__'):
+            trial = 'arm'
+        else:
+            # for aarch64_be
+            trial = 'aarch64'
+    elif trial.startswith('earm'):
+        trial = 'arm'
+    elif trial == 'e2k':
+        # Make more precise CPU detection for Elbrus platform.
+        trial = platform.processor().lower()
+    elif trial.startswith('mips'):
+        if '64' not in trial:
+            trial = 'mips'
+        else:
+            if compilers and not any_compiler_has_define(compilers, '__mips64'):
+                trial = 'mips'
+            else:
+                trial = 'mips64'
+    elif trial == 'ppc':
+        # AIX always returns powerpc, check here for 64-bit
+        if any_compiler_has_define(compilers, '__64BIT__'):
+            trial = 'ppc64'
+
+    # Add more quirks here as bugs are reported. Keep in sync with
+    # detect_cpu_family() above.
+    return trial
+
+KERNEL_MAPPINGS: T.Mapping[str, str] = {'freebsd': 'freebsd',
+                                        'openbsd': 'openbsd',
+                                        'netbsd': 'netbsd',
+                                        'windows': 'nt',
+                                        'android': 'linux',
+                                        'linux': 'linux',
+                                        'cygwin': 'nt',
+                                        'darwin': 'xnu',
+                                        'dragonfly': 'dragonfly',
+                                        'haiku': 'haiku',
+                                        }
+
+def detect_kernel(system: str) -> T.Optional[str]:
+    if system == 'sunos':
+        # Solaris 5.10 uname doesn't support the -o switch, and illumos started
+        # with version 5.11 so shortcut the logic to report 'solaris' in such
+        # cases where the version is 5.10 or below.
+        if mesonlib.version_compare(platform.uname().release, '<=5.10'):
+            return 'solaris'
+        # This needs to be /usr/bin/uname because gnu-uname could be installed and
+        # won't provide the necessary information
+        p, out, _ = Popen_safe(['/usr/bin/uname', '-o'])
+        if p.returncode != 0:
+            raise MesonException('Failed to run "/usr/bin/uname -o"')
+        out = out.lower().strip()
+        if out not in {'illumos', 'solaris'}:
+            mlog.warning(f'Got an unexpected value for kernel on a SunOS derived platform, expcted either "illumos" or "solaris", but got "{out}".'
+                         "Please open a Meson issue with the OS you're running and the value detected for your kernel.")
+            return None
+        return out
+    return KERNEL_MAPPINGS.get(system, None)
+
+def detect_subsystem(system: str) -> T.Optional[str]:
+    if system == 'darwin':
+        return 'macos'
+    return system
+
+def detect_system() -> str:
+    if sys.platform == 'cygwin':
+        return 'cygwin'
+    return platform.system().lower()
+
+def detect_msys2_arch() -> T.Optional[str]:
+    return os.environ.get('MSYSTEM_CARCH', None)
+
+def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo:
+    """Detect the machine we're running on
+
+    If compilers are not provided, we cannot know as much. None out those
+    fields to avoid accidentally depending on partial knowledge. The
+    underlying ''detect_*'' method can be called to explicitly use the
+    partial information.
+    """
+    system = detect_system()
+    return MachineInfo(
+        system,
+        detect_cpu_family(compilers) if compilers is not None else None,
+        detect_cpu(compilers) if compilers is not None else None,
+        sys.byteorder,
+        detect_kernel(system),
+        detect_subsystem(system))
+
+# TODO make this compare two `MachineInfo`s purely. How important is the
+# `detect_cpu_family({})` distinction? It is the one impediment to that.
+def machine_info_can_run(machine_info: MachineInfo):
+    """Whether we can run binaries for this machine on the current machine.
+
+    Can almost always run 32-bit binaries on 64-bit natively if the host
+    and build systems are the same. We don't pass any compilers to
+    detect_cpu_family() here because we always want to know the OS
+    architecture, not what the compiler environment tells us.
+    """
+    if machine_info.system != detect_system():
+        return False
+    true_build_cpu_family = detect_cpu_family({})
+    return \
+        (machine_info.cpu_family == true_build_cpu_family) or \
+        ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \
+        ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) or \
+        ((true_build_cpu_family == 'aarch64') and (machine_info.cpu_family == 'arm'))
+
+class Environment:
+    private_dir = 'meson-private'
+    log_dir = 'meson-logs'
+    info_dir = 'meson-info'
+
+    def __init__(self, source_dir: T.Optional[str], build_dir: T.Optional[str], options: 'argparse.Namespace') -> None:
+        self.source_dir = source_dir
+        self.build_dir = build_dir
+        # Do not try to create build directories when build_dir is none.
+        # This reduced mode is used by the --buildoptions introspector
+        if build_dir is not None:
+            self.scratch_dir = os.path.join(build_dir, Environment.private_dir)
+            self.log_dir = os.path.join(build_dir, Environment.log_dir)
+            self.info_dir = os.path.join(build_dir, Environment.info_dir)
+            os.makedirs(self.scratch_dir, exist_ok=True)
+            os.makedirs(self.log_dir, exist_ok=True)
+            os.makedirs(self.info_dir, exist_ok=True)
+            try:
+                self.coredata: coredata.CoreData = coredata.load(self.get_build_dir(), suggest_reconfigure=False)
+                self.first_invocation = False
+            except FileNotFoundError:
+                self.create_new_coredata(options)
+            except coredata.MesonVersionMismatchException as e:
+                # This is routine, but tell the user the update happened
+                mlog.log('Regenerating configuration from scratch:', str(e))
+                coredata.read_cmd_line_file(self.build_dir, options)
+                self.create_new_coredata(options)
+            except MesonException as e:
+                # If we stored previous command line options, we can recover from
+                # a broken/outdated coredata.
+                if os.path.isfile(coredata.get_cmd_line_file(self.build_dir)):
+                    mlog.warning('Regenerating configuration from scratch.', fatal=False)
+                    mlog.log('Reason:', mlog.red(str(e)))
+                    coredata.read_cmd_line_file(self.build_dir, options)
+                    self.create_new_coredata(options)
+                else:
+                    raise MesonException(f'{str(e)} Try regenerating using "meson setup --wipe".')
+        else:
+            # Just create a fresh coredata in this case
+            self.scratch_dir = ''
+            self.create_new_coredata(options)
+
+        ## locally bind some unfrozen configuration
+
+        # Stores machine infos, the only *three* machine one because we have a
+        # target machine info on for the user (Meson never cares about the
+        # target machine.)
+        machines: PerThreeMachineDefaultable[MachineInfo] = PerThreeMachineDefaultable()
+
+        # Similar to coredata.compilers, but lower level in that there is no
+        # meta data, only names/paths.
+        binaries = PerMachineDefaultable()  # type: PerMachineDefaultable[BinaryTable]
+
+        # Misc other properties about each machine.
+        properties = PerMachineDefaultable()  # type: PerMachineDefaultable[Properties]
+
+        # CMake toolchain variables
+        cmakevars = PerMachineDefaultable()  # type: PerMachineDefaultable[CMakeVariables]
+
+        ## Setup build machine defaults
+
+        # Will be fully initialized later using compilers later.
+        machines.build = detect_machine_info()
+
+        # Just uses hard-coded defaults and environment variables. Might be
+        # overwritten by a native file.
+        binaries.build = BinaryTable()
+        properties.build = Properties()
+
+        # Options with the key parsed into an OptionKey type.
+        #
+        # Note that order matters because of 'buildtype', if it is after
+        # 'optimization' and 'debug' keys, it override them.
+        self.options: T.MutableMapping[OptionKey, T.Union[str, T.List[str]]] = collections.OrderedDict()
+
+        ## Read in native file(s) to override build machine configuration
+
+        if self.coredata.config_files is not None:
+            config = coredata.parse_machine_files(self.coredata.config_files)
+            binaries.build = BinaryTable(config.get('binaries', {}))
+            properties.build = Properties(config.get('properties', {}))
+            cmakevars.build = CMakeVariables(config.get('cmake', {}))
+            self._load_machine_file_options(
+                config, properties.build,
+                MachineChoice.BUILD if self.coredata.cross_files else MachineChoice.HOST)
+
+        ## Read in cross file(s) to override host machine configuration
+
+        if self.coredata.cross_files:
+            config = coredata.parse_machine_files(self.coredata.cross_files)
+            properties.host = Properties(config.get('properties', {}))
+            binaries.host = BinaryTable(config.get('binaries', {}))
+            cmakevars.host = CMakeVariables(config.get('cmake', {}))
+            if 'host_machine' in config:
+                machines.host = MachineInfo.from_literal(config['host_machine'])
+            if 'target_machine' in config:
+                machines.target = MachineInfo.from_literal(config['target_machine'])
+            # Keep only per machine options from the native file. The cross
+            # file takes precedence over all other options.
+            for key, value in list(self.options.items()):
+                if self.coredata.is_per_machine_option(key):
+                    self.options[key.as_build()] = value
+            self._load_machine_file_options(config, properties.host, MachineChoice.HOST)
+
+        ## "freeze" now initialized configuration, and "save" to the class.
+
+        self.machines = machines.default_missing()
+        self.binaries = binaries.default_missing()
+        self.properties = properties.default_missing()
+        self.cmakevars = cmakevars.default_missing()
+
+        # Command line options override those from cross/native files
+        self.options.update(options.cmd_line_options)
+
+        # Take default value from env if not set in cross/native files or command line.
+        self._set_default_options_from_env()
+        self._set_default_binaries_from_env()
+        self._set_default_properties_from_env()
+
+        # Warn if the user is using two different ways of setting build-type
+        # options that override each other
+        bt = OptionKey('buildtype')
+        db = OptionKey('debug')
+        op = OptionKey('optimization')
+        if bt in self.options and (db in self.options or op in self.options):
+            mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. '
+                         'Using both is redundant since they override each other. '
+                         'See: https://mesonbuild.com/Builtin-options.html#build-type-options',
+                         fatal=False)
+
+        exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper')
+        if exe_wrapper is not None:
+            self.exe_wrapper = ExternalProgram.from_bin_list(self, MachineChoice.HOST, 'exe_wrapper')
+        else:
+            self.exe_wrapper = None
+
+        self.default_cmake = ['cmake']
+        self.default_pkgconfig = ['pkg-config']
+        self.wrap_resolver: T.Optional['Resolver'] = None
+
+    def _load_machine_file_options(self, config: 'ConfigParser', properties: Properties, machine: MachineChoice) -> None:
+        """Read the contents of a Machine file and put it in the options store."""
+
+        # Look for any options in the deprecated paths section, warn about
+        # those, then assign them. They will be overwritten by the ones in the
+        # "built-in options" section if they're in both sections.
+        paths = config.get('paths')
+        if paths:
+            mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.')
+            for k, v in paths.items():
+                self.options[OptionKey.from_string(k).evolve(machine=machine)] = v
+
+        # Next look for compiler options in the "properties" section, this is
+        # also deprecated, and these will also be overwritten by the "built-in
+        # options" section. We need to remove these from this section, as well.
+        deprecated_properties: T.Set[str] = set()
+        for lang in compilers.all_languages:
+            deprecated_properties.add(lang + '_args')
+            deprecated_properties.add(lang + '_link_args')
+        for k, v in properties.properties.copy().items():
+            if k in deprecated_properties:
+                mlog.deprecation(f'{k} in the [properties] section of the machine file is deprecated, use the [built-in options] section.')
+                self.options[OptionKey.from_string(k).evolve(machine=machine)] = v
+                del properties.properties[k]
+
+        for section, values in config.items():
+            if ':' in section:
+                subproject, section = section.split(':')
+            else:
+                subproject = ''
+            if section == 'built-in options':
+                for k, v in values.items():
+                    key = OptionKey.from_string(k)
+                    # If we're in the cross file, and there is a `build.foo` warn about that. Later we'll remove it.
+                    if machine is MachineChoice.HOST and key.machine is not machine:
+                        mlog.deprecation('Setting build machine options in cross files, please use a native file instead, this will be removed in meson 0.60', once=True)
+                    if key.subproject:
+                        raise MesonException('Do not set subproject options in [built-in options] section, use [subproject:built-in options] instead.')
+                    self.options[key.evolve(subproject=subproject, machine=machine)] = v
+            elif section == 'project options' and machine is MachineChoice.HOST:
+                # Project options are only for the host machine, we don't want
+                # to read these from the native file
+                for k, v in values.items():
+                    # Project options are always for the host machine
+                    key = OptionKey.from_string(k)
+                    if key.subproject:
+                        raise MesonException('Do not set subproject options in [built-in options] section, use [subproject:built-in options] instead.')
+                    self.options[key.evolve(subproject=subproject)] = v
+
+    def _set_default_options_from_env(self) -> None:
+        opts: T.List[T.Tuple[str, str]] = (
+            [(v, f'{k}_args') for k, v in compilers.compilers.CFLAGS_MAPPING.items()] +
+            [
+                ('PKG_CONFIG_PATH', 'pkg_config_path'),
+                ('CMAKE_PREFIX_PATH', 'cmake_prefix_path'),
+                ('LDFLAGS', 'ldflags'),
+                ('CPPFLAGS', 'cppflags'),
+            ]
+        )
+
+        env_opts: T.DefaultDict[OptionKey, T.List[str]] = collections.defaultdict(list)
+
+        for (evar, keyname), for_machine in itertools.product(opts, MachineChoice):
+            p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
+            if p_env is not None:
+                # these may contain duplicates, which must be removed, else
+                # a duplicates-in-array-option warning arises.
+                if keyname == 'cmake_prefix_path':
+                    if self.machines[for_machine].is_windows():
+                        # Cannot split on ':' on Windows because its in the drive letter
+                        _p_env = p_env.split(os.pathsep)
+                    else:
+                        # https://github.com/mesonbuild/meson/issues/7294
+                        _p_env = re.split(r':|;', p_env)
+                    p_list = list(mesonlib.OrderedSet(_p_env))
+                elif keyname == 'pkg_config_path':
+                    p_list = list(mesonlib.OrderedSet(p_env.split(os.pathsep)))
+                else:
+                    p_list = split_args(p_env)
+                p_list = [e for e in p_list if e]  # filter out any empty elements
+
+                # Take env vars only on first invocation, if the env changes when
+                # reconfiguring it gets ignored.
+                # FIXME: We should remember if we took the value from env to warn
+                # if it changes on future invocations.
+                if self.first_invocation:
+                    if keyname == 'ldflags':
+                        key = OptionKey('link_args', machine=for_machine, lang='c')  # needs a language to initialize properly
+                        for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS:
+                            key = key.evolve(lang=lang)
+                            env_opts[key].extend(p_list)
+                    elif keyname == 'cppflags':
+                        key = OptionKey('env_args', machine=for_machine, lang='c')
+                        for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS:
+                            key = key.evolve(lang=lang)
+                            env_opts[key].extend(p_list)
+                    else:
+                        key = OptionKey.from_string(keyname).evolve(machine=for_machine)
+                        if evar in compilers.compilers.CFLAGS_MAPPING.values():
+                            # If this is an environment variable, we have to
+                            # store it separately until the compiler is
+                            # instantiated, as we don't know whether the
+                            # compiler will want to use these arguments at link
+                            # time and compile time (instead of just at compile
+                            # time) until we're instantiating that `Compiler`
+                            # object. This is required so that passing
+                            # `-Dc_args=` on the command line and `$CFLAGS`
+                            # have subtly different behavior. `$CFLAGS` will be
+                            # added to the linker command line if the compiler
+                            # acts as a linker driver, `-Dc_args` will not.
+                            #
+                            # We still use the original key as the base here, as
+                            # we want to inherit the machine and the compiler
+                            # language
+                            key = key.evolve('env_args')
+                        env_opts[key].extend(p_list)
+
+        # Only store options that are not already in self.options,
+        # otherwise we'd override the machine files
+        for k, v in env_opts.items():
+            if k not in self.options:
+                self.options[k] = v
+
+    def _set_default_binaries_from_env(self) -> None:
+        """Set default binaries from the environment.
+
+        For example, pkg-config can be set via PKG_CONFIG, or in the machine
+        file. We want to set the default to the env variable.
+        """
+        opts = itertools.chain(envconfig.DEPRECATED_ENV_PROG_MAP.items(),
+                               envconfig.ENV_VAR_PROG_MAP.items())
+
+        for (name, evar), for_machine in itertools.product(opts, MachineChoice):
+            p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
+            if p_env is not None:
+                self.binaries[for_machine].binaries.setdefault(name, mesonlib.split_args(p_env))
+
+    def _set_default_properties_from_env(self) -> None:
+        """Properties which can also be set from the environment."""
+        # name, evar, split
+        opts: T.List[T.Tuple[str, T.List[str], bool]] = [
+            ('boost_includedir', ['BOOST_INCLUDEDIR'], False),
+            ('boost_librarydir', ['BOOST_LIBRARYDIR'], False),
+            ('boost_root', ['BOOST_ROOT', 'BOOSTROOT'], True),
+            ('java_home', ['JAVA_HOME'], False),
+        ]
+
+        for (name, evars, split), for_machine in itertools.product(opts, MachineChoice):
+            for evar in evars:
+                p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
+                if p_env is not None:
+                    if split:
+                        self.properties[for_machine].properties.setdefault(name, p_env.split(os.pathsep))
+                    else:
+                        self.properties[for_machine].properties.setdefault(name, p_env)
+                    break
+
+    def create_new_coredata(self, options: 'argparse.Namespace') -> None:
+        # WARNING: Don't use any values from coredata in __init__. It gets
+        # re-initialized with project options by the interpreter during
+        # build file parsing.
+        # meson_command is used by the regenchecker script, which runs meson
+        self.coredata = coredata.CoreData(options, self.scratch_dir, mesonlib.get_meson_command())
+        self.first_invocation = True
+
+    def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
+        return self.coredata.is_cross_build(when_building_for)
+
+    def dump_coredata(self) -> str:
+        return coredata.save(self.coredata, self.get_build_dir())
+
+    def get_log_dir(self) -> str:
+        return self.log_dir
+
+    def get_coredata(self) -> coredata.CoreData:
+        return self.coredata
+
+    @staticmethod
+    def get_build_command(unbuffered: bool = False) -> T.List[str]:
+        cmd = mesonlib.get_meson_command()
+        if cmd is None:
+            raise MesonBugException('No command?')
+        cmd = cmd.copy()
+        if unbuffered and 'python' in os.path.basename(cmd[0]):
+            cmd.insert(1, '-u')
+        return cmd
+
+    def is_header(self, fname: 'mesonlib.FileOrString') -> bool:
+        return is_header(fname)
+
+    def is_source(self, fname: 'mesonlib.FileOrString') -> bool:
+        return is_source(fname)
+
+    def is_assembly(self, fname: 'mesonlib.FileOrString') -> bool:
+        return is_assembly(fname)
+
+    def is_llvm_ir(self, fname: 'mesonlib.FileOrString') -> bool:
+        return is_llvm_ir(fname)
+
+    def is_object(self, fname: 'mesonlib.FileOrString') -> bool:
+        return is_object(fname)
+
+    @lru_cache(maxsize=None)
+    def is_library(self, fname):
+        return is_library(fname)
+
+    def lookup_binary_entry(self, for_machine: MachineChoice, name: str) -> T.Optional[T.List[str]]:
+        return self.binaries[for_machine].lookup_entry(name)
+
+    def get_scratch_dir(self) -> str:
+        return self.scratch_dir
+
+    def get_source_dir(self) -> str:
+        return self.source_dir
+
+    def get_build_dir(self) -> str:
+        return self.build_dir
+
+    def get_import_lib_dir(self) -> str:
+        "Install dir for the import library (library used for linking)"
+        return self.get_libdir()
+
+    def get_shared_module_dir(self) -> str:
+        "Install dir for shared modules that are loaded at runtime"
+        return self.get_libdir()
+
+    def get_shared_lib_dir(self) -> str:
+        "Install dir for the shared library"
+        m = self.machines.host
+        # Windows has no RPATH or similar, so DLLs must be next to EXEs.
+        if m.is_windows() or m.is_cygwin():
+            return self.get_bindir()
+        return self.get_libdir()
+
+    def get_jar_dir(self) -> str:
+        """Install dir for JAR files"""
+        return f"{self.get_datadir()}/java"
+
+    def get_static_lib_dir(self) -> str:
+        "Install dir for the static library"
+        return self.get_libdir()
+
+    def get_prefix(self) -> str:
+        return self.coredata.get_option(OptionKey('prefix'))
+
+    def get_libdir(self) -> str:
+        return self.coredata.get_option(OptionKey('libdir'))
+
+    def get_libexecdir(self) -> str:
+        return self.coredata.get_option(OptionKey('libexecdir'))
+
+    def get_bindir(self) -> str:
+        return self.coredata.get_option(OptionKey('bindir'))
+
+    def get_includedir(self) -> str:
+        return self.coredata.get_option(OptionKey('includedir'))
+
+    def get_mandir(self) -> str:
+        return self.coredata.get_option(OptionKey('mandir'))
+
+    def get_datadir(self) -> str:
+        return self.coredata.get_option(OptionKey('datadir'))
+
+    def get_compiler_system_lib_dirs(self, for_machine: MachineChoice):
+        for comp in self.coredata.compilers[for_machine].values():
+            if comp.id == 'clang':
+                index = 1
+                break
+            elif comp.id == 'gcc':
+                index = 2
+                break
+        else:
+            # This option is only supported by gcc and clang. If we don't get a
+            # GCC or Clang compiler return and empty list.
+            return []
+
+        p, out, _ = Popen_safe(comp.get_exelist() + ['-print-search-dirs'])
+        if p.returncode != 0:
+            raise mesonlib.MesonException('Could not calculate system search dirs')
+        out = out.split('\n')[index].lstrip('libraries: =').split(':')
+        return [os.path.normpath(p) for p in out]
+
+    def get_compiler_system_include_dirs(self, for_machine: MachineChoice):
+        for comp in self.coredata.compilers[for_machine].values():
+            if comp.id == 'clang':
+                break
+            elif comp.id == 'gcc':
+                break
+        else:
+            # This option is only supported by gcc and clang. If we don't get a
+            # GCC or Clang compiler return and empty list.
+            return []
+        return comp.get_default_include_dirs()
+
+    def need_exe_wrapper(self, for_machine: MachineChoice = MachineChoice.HOST):
+        value = self.properties[for_machine].get('needs_exe_wrapper', None)
+        if value is not None:
+            return value
+        return not machine_info_can_run(self.machines[for_machine])
+
+    def get_exe_wrapper(self) -> T.Optional[ExternalProgram]:
+        if not self.need_exe_wrapper():
+            return None
+        return self.exe_wrapper
diff --git a/devtools/meson/mesonbuild/interpreter/__init__.py b/devtools/meson/mesonbuild/interpreter/__init__.py
new file mode 100644
index 0000000..016e4dc
--- /dev/null
+++ b/devtools/meson/mesonbuild/interpreter/__init__.py
@@ -0,0 +1,59 @@
+# SPDX-license-identifier: Apache-2.0
+# Copyright 2012-2021 The Meson development team
+# Copyright © 2021 Intel Corporation
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Meson interpreter."""
+
+__all__ = [
+    'Interpreter',
+    'permitted_dependency_kwargs',
+
+    'CompilerHolder',
+
+    'ExecutableHolder',
+    'BuildTargetHolder',
+    'CustomTargetHolder',
+    'CustomTargetIndexHolder',
+    'MachineHolder',
+    'Test',
+    'ConfigurationDataHolder',
+    'SubprojectHolder',
+    'DependencyHolder',
+    'GeneratedListHolder',
+    'ExternalProgramHolder',
+    'extract_required_kwarg',
+
+    'ArrayHolder',
+    'BooleanHolder',
+    'DictHolder',
+    'IntegerHolder',
+    'StringHolder',
+]
+
+from .interpreter import Interpreter, permitted_dependency_kwargs
+from .compiler import CompilerHolder
+from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder,
+                                 CustomTargetIndexHolder, MachineHolder, Test,
+                                 ConfigurationDataHolder, SubprojectHolder, DependencyHolder,
+                                 GeneratedListHolder, ExternalProgramHolder,
+                                 extract_required_kwarg)
+
+from .primitives import (
+    ArrayHolder,
+    BooleanHolder,
+    DictHolder,
+    IntegerHolder,
+    StringHolder,
+)
diff --git a/devtools/meson/mesonbuild/interpreter/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/__pycache__/__init__.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..71de667864d675ceb4303aeb74cc7b92a8fae6b6
GIT binary patch
literal 1033
zcmbu7OK;Oa5XbGj6WfX7y!yCs&831HLI^>d3M#b-sXeVMS&nC$F5R`wdR-De4;Q`z
zH@=0hoVao3#7^p@L4p%&`M0yPm{&xVR7H){Ohd0Hye=A~v9|Yk
zQ?y7+v`JfZNJm)25;n1gLmbg1UC|>w;SyK$Nnd!x69Y0>@7w1?F(M-|CSx%n6R}73
z#6H>A-wrN~>ES2uf@Vqlh{cM^R8q~O!a93c6^AL6f+$TzDYPxS-7W58s#dSb6R@($2sG0rK71TUEWEasYLwYo9z0|bdqHm>|BJ=4U0Fw
zt6kAd6_b-BzGjPDhKeQeEL7np|7AW;W%8azn`G{6TXY#ScuixfcTzZK*(Pjsy3|LH
zL;g-C3mJ+sc1)K_hLH*+{g5-Md$2xuVZD+vTy07`P7+STxLkH-Y@6M|PA<0Xu`iWm
z@!~%4hpAOEtw@|?1#MGSak6C%U3EkQp><}+7NU(n0ZI#DBOF8*(bJgLrHghS;UNYH
zl;+#%LD38XNTMJ>Bjj8g*3Q*G)Kavf@@CgH5pO3dnPY#m|EZF6QpvQc*d5LOS??D^
z9$@W=U+1%DKF~XVp@o*o$iLxF{0wdbw6$O9E699-TE6ETW#{iy?FRvinF@lVbXByT
fiv)5`UtpWE#~QV2#jM~k|N3nGjjC(f=F`S+#9kc<

literal 0
HcmV?d00001

diff --git a/devtools/meson/mesonbuild/interpreter/__pycache__/compiler.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/__pycache__/compiler.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6000cdf516521134faceaf49698e4df29453f7a6
GIT binary patch
literal 29729
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
U7`^!8sH@lNjSfeK!&}1t54~8(ssI20

literal 0
HcmV?d00001

diff --git a/devtools/meson/mesonbuild/interpreter/__pycache__/dependencyfallbacks.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/__pycache__/dependencyfallbacks.cpython-37.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..23aec25978844e1705365c58242dd2df2d29a0a4
GIT binary patch
literal 11883
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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/__pycache__/interpreter.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/__pycache__/interpreter.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..447b879452bbdbc6843297ad2187ff5e83a66d14 GIT binary patch literal 109747 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%0AVZ1*h%^7E+z>*NT9Uji&Q zzTFTCDX6MF{)tn^&(0M~wqb&Szes8o23(t2k801dXfB-ohE}bNVL@ zRzj#gzz^+kW~t2y;?r|~)m_2C%$(RzNg6S`3D=@FoWvnd(kBJ)RGLgUR;g1kHq4`^ zng=8KVqRncjY;biID8!8c8hteWUcc(j(v=}v~`L^NjSTKY-|z3t*C*Q6qa-_QNqw! zwnZP7mZ-oFOw5>70c^v|3AP*>3;jajR>}N}Iz>#@G|1KN8S^UC5K9;F9-gm3BsAK! zrWpQrsn7W@V_ zSchbaS97Q5W`Zj=!kv^yz;n7P%gJO{33qbW)(IxDXnq3e1R=O+l_5>dzo)+aSWJkV;9k#aYvbZ?oZumkM6W`=Sl8> zwy$R{%4SNc1#<>V^IO$*P&&E2M~0OI(w^oA?pl-HsMFSG)|h zcBh>IOUdu8=6XVMNh~J0;x_nle$`DU{cZY~xgkztG8pK+knD~coU zrll*FxpTmBPOzlq{*|rpU_DEFEuHKxK;*ZPLaBdV;F_7>E0vx~FR+O{3td2!Zg(j8 zmojHQhnU_&nx=1&%b;grW$B}pp83ngSE1K_2`JJl(4enddalyP?+{q|ZGg%T8(imZ z`@)e*|3#@V*0bsB-j(w^?CxEa{`srydPk*yWhX6LUs<;@Dv(c-;>X93kXb#(FMl#(AEojXZx?}RvN+l72!6Jh@{ z{iCIHJ2YX`;5EfORJVDnBUS^qo<+WBF)(bP+2DimmetZ0-oBb>_*1p5>XLPtzAxE( zp(wWZmelro@Ok!KnZ4p9bu##vLzl5w#&(I%syBHw(mvrlz8p6k9Jo|yKz$Qy4Nr30 zg*Tp_Cc+qInnYW;5fZ;-vC(=A|GZd3rJ!e5IvGQ&3B!1XryIOVpEM3Z((jW3AB=vU zSUfpvu*}9q&qnxeDr#_#MSTBG8#{l(L#oYv;T%dRG1HFU80Bpl|6X*bxPXc`VmgdbcP>*0E;wt_&;}y8B~H5s5hYHolQ^Xknu;C`f^#$enMZawbdrT(B0pC z4b)6w&WVX9cDTwbnDgOa%pCY!GR@$=u>X+-Bo|`*uzL~L&N9@x)<5R5t&G*F{tl&*FCnwVh*SMsJlt@qujP{y4mG@n6>to~XYyz? zA_VT?GW7h@p@d$p2CV0M2v?+rxfJtM&}`uT1;#&rL}$iC|ESJP_c)@nXZ5Dv=S|hEo?OZm zoMwrMBGMt~rCM%LpIfi!F;g|ZtTVHNzMyYdr=O<5l+lbRJA6*ih)D@v?U|DjuY|P> zm6(g1Ur`%=K_4n>K_HMO*OQ7R3naj~TkD|Pm>L+uZ|RNS)WL*8Ymem5$vn%jG?|?} zR?QRDYyf#07T1JIUNa;)N0)mu&pUvjhO-p(>!so{Wnos`Hd`c*yr|hCJC0;Y!JT1L z%?n&jb~*v4^<=Ve{?Xr@vXwg!n*ZH`K2?#FUHKs#IrS9Ll-Yi=!?m>vN=>q-^1vx~ z7lG1fW5vY|p@#*6jeF#R8(wQ!rUF?K$@GV5s{CwOI3IFL40_q@a@K4wv(BbOPR-jF(7X(nGxRASFqatbM@dZMgeDu<=T%8S_}m#3+v$g@NJsIEZG&I{2@ zz8Rpmn;d&)yX+${JDEsvMK0{i8Le>n4taHHCx{e25iyN69_F7rxdZrsCIDwG`R6_Y z(Vb@V5^_j{Uli-xOx%h1sCgPt2ygVE1}5 z1^&kscvtbr4C2aC}^zvLIKn`16)=>IM;T4da zgc)LtxmeW55R7zf3--UNdyMpCwUV_K%>kOg3X~{BUL`?~w#qCYx1k<3eD|O5-G8U= z)>KwzJK4n3{)r8mq?8FV`LuiWX?NH}-)HVZsAt$Oht7~7))KQz0#n8o{US3t5mQ9v zvt*?8#lUE0y|(BxbBDs6iN224TNt{LVNKm=vdZoh3BK)3r;$yKKUY7E(YSb47|k~N zB^MBPIB4jTzok#Utv=y@`b0EEIU*Zj5S#20;U-f|BKeNryLhswz4yVRa$3Nt$eDTH zAzc~InAt!5)&Dj}H2;_rFdl5fxnK}$4Fc|S85@5bGvAPOj5$lr;F)Z1AeclrfzxO} zBgCDQ7f052I_rtZ>isI8*}&*lHze*3QSIy>nO?d=^H{_<9eUoRbi!uPyS1|qK3f$g2+oj@H^i=J!p8PD)s zN79A(W2X~!nfEX5h6&PXuty(rL;NvuOo4sWU2`SPso;nL3m!Cs@$|{Zqfb2&cGaQ@ z5{XXVoorKYulsIzThgGg84XoXYMqzIFs=ccVS@8$I>7lmm_Zaoi_&T#2Y0a5Nb!k0 z7-9O+W2V-MR#r?3rJxOIqvyKhahwxoBFq+8m1xxgctv%~PO}~Dob4i& zOt4GrlA;ObHBx-4BFPViqX*&)mash|3&zgW@a&0S0>mCZVVpfyu|z&apW#vGpryYI z{$IW(_(u*%dB$L<>PE^XX=ATG*)~-eO0lhJ6pK@cW(4^up6e8GcH*pDunOKt<>9(` z`8Sd=bp+GjJ44e_p1BrO!BVc9mQirb9!k8nxp|h?zA>4b`Q~%87}1~Lb~SQ5ZY0u1 ziXibjO`&w*NVxu?sR!@4fBa$08?)LTu{4qTf);vDir-I`pJZH-E*tcDP9WDn`z*I& z#Sua32)0!CRTSUbX1{mJ(xXt3r$9SLo$QkVR)gOM`HkN)ioZ5eDYqzaJThM++>7{| zsxPNxaP%S21ALyxk%YtM_7EF)i4$FzJ#NDlZZDA#z3zrEsnI=P7qv&ieq32jCwQc{ z-FjWT-Q{fw1wX(`CcEo;!?x(=<`Y>N@xDOF;+;B@xS(O3EmPgC8bGPOTJi#?R!}cT zq@3D+VanoWL@>~RjCJ{*Y#Vd%e^Lc0P!1kCG?qCCtvkdj;ul}AmDlj+Uj4~&jdMxb zDwbi-^y9?X*MiTh3%{Vl7j=+?6tqz?Kr`PG{CEBQjt;-BpZ~iKU)AAjI{aTc2!KBL z2OT=J8b?(4Sskv>;g}9j=*A;D6I}>SsqhZFtFtS0R?uO)4xtW{Iy|bw_v!G24pTZD z*P$j;pU_XuJ7==Z?)9W9eMZ;brn5Ke_~-gr)L}}87j^ic4zei+f21N`(cv$3_@)kjtHXcR;qP_$2OW&?iRJ|&J;Aqi zEw8f~wd90u9M{1#Emx^ImnpZig?HBLx=mmz1=A{fREHZ>w%@f%0vn48tmxj4>F_Zf zKBI#)v_Vnto8_!J;189`u-frs@2S6WqVC28-5B&IBBNCN%w*~ru>9j2@8(8uUU#GR z&4V=`weOrRZ}$4?mA~=*$Mx(3YU?2#{+WKhSI_jg-BYlLi^bq7b>Y1#ai0$N>+lvG z-m1fsIy|hyVI3xPcwC1gIy|8|-=#X+CQO4IJfJoDR~7dH#q+{Zv}opro@OP~p$%>?xi7e{G%5ZyQAv z$20bNy>`ai^~Oz?jpJ^e$PL7bLY1ZkqLh+^1|fd7Ah3i&iz29$HZZ0LE)*pG0g$+H z<$@3=Zk*u{K%9Kw58%*$fD7;Q#z|TiS^oOXubutnd2iml_vSU=J(8+iA}qE>(ROb` z-J~~X-FUSw|KmCG zqlmq84i07i4OQx?dByM4*CkKZF#Uok^L@wU*D>33{{ncTx$|`M6)oVMZV5oHRN>7b z%y?xY{L(Szx<6@lJQ&M(SRwaI8jb{}B{h6gjvrM-B%Ap3FUI9Kjkn{g>2%UbD{&l` zlLg5;jhuw&YD?`+*|t0&Rl<8v@>)t$DqB;_oZXt~wnFHf?BYS&)je8|S-N@o#!B7Vl2!qi%|*UFEkcZYMW&8>-nw{i&&mIB>O6g^I4rzwX>?Zp7h99$D% zHtA*n<%DWlfhme#GC*PDo)8#CVv8kCH=%b-8 zGVl!WtiT`{8z`=fe~0cl$~J&apve$-1?pF!Mm1G?-MM-Du6tfG2Q$Z^pS}>U$pelu zbXTeV0S)K%3PJ{s9dG;+yui^(NLv5mB~){ z$bc@DohldfJe53^1>c9d3EToc0KDu0rIP1|P#*!e0hJV$3m%ZX1ANP!QOh}mj=PdI z3ic)VraPqc0q`5}x9|q{6Y!6;aNkoglpDbvXviDvT}V@Tt99exQA2mf-P+yRdikYS zuW2M5@mUz|51PJ_1};-$=%M?V4n7eWRL2|XI!9`5;ysiHJ={O^ibOZ0(Wk&Y;4^_y zMcsJ(dee`brV3=(drjKOe=XGqV;2MOC8HADpmALnbH@%cBa2o4kt5I`e$)kM(A0$r zFWUHaUJCw(6Z#Gaxib}@3Isq6r~`jcr3|&heS;65uxL-gphwY$$b9z>_BZ+S4}TW0 zGF_kiFzT)mlTrNrMlEY(fE=4VP?Q(YsQY5&$nq6vkFx?;rm;+lg z;L!_8vbefUS+XS`66HrGwqwch^LtMGe91>-+0S--B#v`+k{8E*c`vdPM~P#{k*|E; zU)?=D2M)?F4)D6Cy1KgRud2WP`s@Gy`s;Xqe=2~#uYBW|=4O5(5cmT=xPM6mo(p6G zjoD}*a4BE}j9?{D4d#PEhC`K5J|w^4d{}-X`H1{R^HKSYW=)5>dySm z>O=X5s=M;Lst@NMuI|q7uI|b2sqW41txo1AtB>R#k$lsYN2~kt`>Ol%`{lX6lB*ub zAE+M8AFLkAACkC%%Hir``Nt$YSm~=io`1ahME;5DlldpBPvxINJlpE&{4?e=^G7}% zR6k>6j3LzT+5EHe&2Z&t^0wfwLg7ZzA@z@jPOmM{M7GQDSEi`+{)>v1cT0Nn#DezG%FJ*q0>Ml-N1MzHFRD z>{*GuBC%HyJ8hgp>^X@oOYA&i&l~SS?0Y13L1HV2y_v&KN^A|WGsY#vUXs|l z#4aNC72{RJzAAn77M@=--izn=nvbLJ6rS_O>v(=$-Z$|4hH)9smyyem*((rxNgpc#sfz2PAG37^{i1s>JoCWB!{;VXBZ~pO!IA|UY6Kf zh@CU8AohyHzF%TLfY_@>8L?%F{h-8t8)D~;1;j2$>`jUN5MnDv6|q%`y)CitAhu@I z5nGqo4@>Mv5W8r+h1j>GeLgC&A49A%8i;L3?8hbc6NqgZONd>P*iTCAwkdHj4;H zXP3$q1A$1jQok}8v4_sqjirit!E7$6+AGD%l4+-P)VbMtv(&Wv^wUL@Y1)IQZZyqW z1BL5YWR#vU8_n~o-mI7EmB|r%=tRBNES77gnz^}Xo~g~%?c__>i|UF5`_B@tbBm@b zHtWhBmB%x+rl}Sc&__9iruFX&^@?FCd+h8|vp8EpW}WF$r_CY&H>b_(_K*`kX(Fo< zpf&7)CO|L>i}gkU05t5heqJCr4fk!`1twFgPa*zvrPxFz%e5;8s{&U65TnuT_?-U2-l9;s$~CjlFiZ8CQK*>L%t}EgZrCF}@K4<+nTza0J9DOX ztyn1=D0!)B)|w5w&xtuvH%xSJV!B>4*_3wX)buNbi>J;{U6`6VccJjotCL|nh1!}m z!>pBV>dsNMV&&!XtSYLT_OO(Qh*lzWnDil&q0_FYViia*z=mcEJI$XwC&0aA-n8SD za-&(EyJ@G+qoHbrMsd#kdQc--OgAL*%$zt|T=4e~;`+`OOILvh?DxsIopHM7#8tDj zaJ<+s?IB--I0dIJF3kcgLA=Dwd(WRLTq`QOPeM+wCFKE)rhs}(QS+cc%XtU_0FrDq z<7BziEOGF-e_;fKbs0s#4CI4GARht?6Ewp{2$NqJ!!2Tuo~m6dt9p%na?xBY3ckMd zsvT}Lm7Q$3G1EwzC=_bNs#z%5sY0PD!wKPZq43sHvEsZLEEIeLw@~;}Kuw`|xqb7M zlSke#%xiC4K`%5^>5Z$ELvJ*Ug#yEfZ`SLT#v3xA^EE+hc9<<SOJi$;~V+R?OG=v@fgg zzV8Hr$*9T!bUW2pnq73zqJK^g`9g_^WXBD2uDDcb+A%#EOA&m)zXUFZPmoLf7y`?I zd+6ll@cq!Oh!MIK#RVSpR=gQpjxk1mLqshG*d?GcJM>N<=8SxJsMb! zA{3t^a>b|ZgmRkhw6*b4!&KS247lu0r*b>3*umW6Pvs8ISnqO^W*5wx*Xzp2f*uK} z$X1sc&Frixjb|2X*}BRWvrZ09j+1?M_=?%IQ{_gv)@T-MB~!)G81@j0bvj3PyV}V3 z@DfI5gjj3$l^X@4+#p>rm_fm;Nm!jiLY2jBG9mq=PBY?p-d@1X4uhiE3HMX=BIDu? zTrIR$#~D9rYFq*_)yPy396Nw_ja|3}BI#g6{`s52e=L}AE`&pgXd&cJ?`V2lQk&^L`m=eP!*fNhmGjJ~mj0qXRD}no=`@vg5 zBV>f%2`mRs25tv$g>D>K4xJ2KK71>Tlwsh(bIalR$i1i$xgS)|y|sHed@puC(AeFK z8`0(P7Xn7?i(%r!Tf1Kk7;(u7-`@@b9}?4c!~mEcFdVJ~=ps>f41p^^-piR=!6u5o z9lRI3ANWk@t;j`9K2RT$G&^P9SS;2I^q<1C5y~C3gGNVde=~KIWQbt|SW_EY4yI zTxy!xMQ|gz-c=fLtCV)DN92R%9{fDQ)!QDQ+grq%mL&a#eXZYz!M4_zk{F zb-WodHac(m_{K~dqsFG&A>X%HC+ZaVy1(P=31hSK^#DrR0vNWUG^`&1!yxj?GA}b@ z>@bJ$JB;5A$a^PNl|g}Pm+`Qd_XyHsjVbB(I_dXzq@Oe%@zQTZ`bVAg`<(RqI@0eq za$fpTq(30=BmvPuegQ}Z9Y_uthrN`Wkn%CfnJFLdNQrf*mvZc*7_IqnjO3^64Q(V< z^RL!~%Yf&)h_2PY$H%nn!N85_sQ}p7n%_$t;QS+1NaG3lTq`%h zhs8O{k+~h5u_L8oqiKiD+BH21#&uga)FS`}Z|jRU?Y^sK#VBYlN}XeTylOVD){TZ8 zTUx|2%CsF|3@}lAVY|?J5d%)O+ys464JY-0Q%U#bs9P1Mu5SFs_A0y4LvHf&oEw$# z8o-GGQyOWQl{sYsel^Ei88`C8g+i%PY%~f5O~N<_s|DOh)f!uH3xHOoLleQYOtyOJ zb??@e9_XEOn_AQDplX{~Il=OhiFFtOU{IiuGBEKmG|vezG_8mYAo&VEb`%tSSkT(u3rJu3Zw1t=$Q=_FK~>+z8{4i8N~Y+9 zGKEq#wir#k_5-t9>+-2Ei^#ltbGl+#~gsWs9W93pT{*s@O#-}`)y>0{- zDAYi|OD%#L?67X!caTVDG{unI1WlLlcoUcI`mnXL7r+j*&Oq=8=Ne!L`mGa;YXE^* z;DYf`FEE@z>QV%2Y|dG=Xo{0_2*ln=GWt(ElRLO3q+B_;17)3%UI&!7JxC+H8?2pF ztqF$HZ0K=@URu@qTUKfrnf*Oqr5NR~$BRr=Lk)ePd^XZ|t~)QgFdq&j=z#b4O5XuJ|ZoJ4TPXg}5KVrAJLX;f$ID z)?*koyLz>?*II5}rRO(OC(zWJ)J4JLcFL3`z# zCYYR1?_z<+czZW*2MW#UnY>Jbz;*=<4Pi;|6)d@Ni@x zIuH#7$0GU)1+x+w?n_`Cgz+9TA@ci9NOMSe9XfvL`6Jm@vw2eI zMJyvtNTX|6r~^#DLJ4XqM;H$kmK|#}jrtM<^!NpvGdZXzUzOpb$f!v#*aK6@O_9Mn zMg4^OEZ*3CYN=L$w6Y4hrurPyem8I5!&`$lu3_waZy zcARqO`;aN#joj*6PN-wlen5x>4F$wQ>Dqwv9MR8sf?WH4;8y=~KTxWV$N}kge7PS| zaiUB@U27)iQ?&^0eYXah5F;7U=D@wd<<$M)eTb!QezutbQVuNlFQ<*zoyZ&ETZ6YU zwm<-z$Oqi-S1aC6v5 z-`n8Az&H0H{=(2eXgRYyL_JI-&>UGvAvNq`_>XV;-7iMbLLUmgH&6?`ro~(X)87nc z+m`9%b45Tuihu~{2Pn;^Fz$ZPFV7A^CUv!9-ms%@E!CS)={kb#8=dS51>1j&OD1SY zWP))gk4l+JQnwQQm6yK!`+~=_&XV!r~|tISs&q z;>`I|cKqb2SEet${IW`-2kfX}&MsZiiiIRI7yALV5AQS`$}&}KuCA)ZCM*w7i|Kmv zbbYC22>F^EesB_#?|15mvQ+VAJ_6PAHT8oiD4&EP9YRSyvpekIq8)@l)9l0`u8)2X zSL12i0;x2nZvKyjBEd|EDhU1$<3AJ}1(`~LA=WxI#D|8FE{#Q{HQF2RRuBN$VGuIl zi4f8pifvz)ljG%DPe@Y?0StPssDsm>rX=ZW@@$_+BA5Ys@|G=r@WcY6glWbh^=+Ky zisiBq*DUu7NHpXtcg$CA+w`)&GC66jS>|0N8eO?e-y9Y`eR^gxcp7tA54Kbh5mbu> zWfLmaN3j6)3ErmMn>(us^Y}@`{u-{v2yTfK3FF?8oe#B`N5vFvtROp8lvn=>KOQUC zLwV&_UBMg_%%G8mF=4+k07Vg*MkuQA45p8&EHiFwfTAfu=I>4fimVN03d$NVd`LG2 zrf}Sta9F=Sq}|+>c5_GCEyh+SZ5nB}wWZzGk#@V0b<*|=<2V3p-C<9hYT1K$ETOC4 zS($0<*6)O&S`d+Z8``iDg}Eb%=}_uGSf!Uj7&>6<=Aq^Dv1p-bh{wVW==fvBMcM+{ zao9gG09jOv(`vCxDWvrnBmIf{IN*HgJiF-n(|}1pc2PxeNAQIV&{iTW*$=7?gz7e!K%AK9-{MH)u)g*_psP>~&phO(C5>vyzD)b%2>cF)FSS_!v|uPg$~!8f20z7=tLjBCXZ#kKdt zPQO6qa1`m#?;KI;XBdulDr%(NV$xMz<{CeTFAjU7Dh$Ef!#=QIaaY%ltg}U%tYLpU zX*%VR%(i+wf)ZNw0IiVqD=7w~X)D(#tbUa>l4||ziq%qF-gO{^`gz1X?co6GlnPpV zSE*GSm9;kbE9Ow#|7SJ(%7fMH7myr#3>@s%HJeW>th>H4cTeZ!;kj4ka`aABbcknb<&ZTND?5g*w`OhS?~ovNp0EE}S?w zeY$XRYGw)sv@vbc8>HLfw4YAt|^cA@kS_TyFOgPu04mqTI?Dq5#(+2khjf?ybZs7VBth` zA#)#CxP(yFd=&KW(80X0Xd*2z@?lIm+L|o_1JFi3&4uhz&3T)`%yz{r%&B^HGTn>a zlaXboC101#8zPm}8Msj?PHm2XN{S^o;Xan>K5Xz8?M4o@AaJ7G+0<*g-fZK`9K^$D zKbLKEtxUjpWxIODnIBwR6Dy{KUn#?t@MqA5Z(~j%fNA~-w9@=q z1FRS%Hon3f#yH!&T5M*4YuQ=TtYukf4z>9=$X#V|>s^^Vcvq2*3zY9;jmT~WM2ojl zo&29zqiw(xxEY45m-TQ5cXg=-I-xmv5zo>r{jyK}-Bs8{v$+bp)y5d_1;n}uX{bjg z3#=B@esf&baB&kf!s7vKK%jUeGA(SO`VD-fHGg4ySD~wTJu3WF)%*;Z7Izr7SiyD_ z5y~*@H6}T;ohuZ;wsHoywY7IsI`qUEYHLw2t(QH*$vz|FCJ6N$0&Z(iHjUb&EnsgA z<_&V?FtpCJnudV}S}EeR5-hBd4jN~tm15IY=#8DyQr`^j^fgvg{afU(ei%1MUl%K7 zEcqBA?c!Kpc#povhwJ$7fgBNW$);kw${n@ z)o+^#{q=1qiHw-j!jR)57VYh{Ff{mFo>=*n>Y>+PwWaE;sd52HQVmx{d7O)(!v4D}>V_4Pqq~k~d6rw3FSI^d=j&XHP zmH^n(v{Gwawl=Ns%4;H0E?z>pUPM4Q5lqKuq7Yb!sh#`<6$AC+n1lI-&@&^jkW^3V zFijd9ss=k6ZvusB85>s*v)CzUhq0q#vtV|)a}t$#3v^xZ>?MAc#jV>IMnp7Id@naL z1nOVl_F;BN8i4>5{xl#U|h<4*CjPX|OBn z0sBGO0Qu{GgFgsF+IvLnwYkLYEh|wM@TzmB`Im_M3_EBT0o_5v=%7?66Wl36rjeC>f|m;xAqiGeT^l^@0;@QPWwoxgZ^RYpA;l$}?2T`iM<~{5HE|bL zp)gPgG!7$>2#usO;ejwjUJ!SsMBKG4GXTpj@}(0gxesK}GNIr^WFVXhDt-@PH+K9% zM=e_H(^zD^z}RG^Tw9PRJIY|gPLyk<$`T}Jc3hh>HA+b6{Ryu^3#3;tg4Yt0-E}sp zImTR~?SqL|SWLXMs74!e@l8zLh~P{_SK64X^-XK*T2josT5npWVJQgMs2v=GSPUE3 z%zlW72Jkxw7bpE@hAvJJo-iTsGW%hIw&hOvN&vrbbpn?Q+wVkghsEIu4bj37EIs6j zpf;Ez1~#eT`#$_`g0L)X#!$u{mVs}e$CPjO(k%+%mpW|3S8$JlucCnCMRWA~L!T1Y zDA;Vq66h4g6LKLf1Z7B@#-_A>2;UChA@m0U@nb&dANPfy@P(h$VG7eAv>P;@@x43J zRpV#xL~h58qY$ZSxQ`j{_8=JpB+nUB0(DI5Xa(Bi#tARYIMSSyG;D>FF1*MQaxF=H z$~f(%o(if-;1! zU&TtQ&91J2%4_4ev;gc7K|ABY?Zyl^;JeR#;;_Jx{$*MYh@!KAhVQWVhl%0svHt1M4VXr0- z&@jkWn+$!|@R?gu0aX~D54cLFvFMD;3=lxYW?B|}%K_gn9-V`& zk{w+v`n?VEr zy0X$f0mEf$ySp>0)#&FJu4o?om7;3j8|5*~tgap>nr)tg4DM6h=+Gf*`D3J8v;Y4$ z68&ed{|9>vUazklQflq&=v5z8cRQF^AnW-jR>OkUhaG5OJ=C*^Lfh=uHY7Y6D>5i8 zP7z^>>;UO#nE$?>hWT?O`ZKR#V%E-9A35rz7Whufd~>T0?CyC?8ihjxV(ypeP{eaa zblG~O8xzioz4>`Pr?(1kAqDH~AqCg{8Y$+W8u%21;LF_f>5+0cG5#R zJJo7r_18!u(S4J^YqWgppF8Bz;0ZIJ262PQ(^~IkojQ#gYmYs@!jLS;zkyH}8o>*L_N~Ou78|N5ejqoJ zQ}usvi-J0fDMld8Jw)29SQ{E+<9oIX!(6=Sg;##&P_X3iTKl5)Rx#fY$q+aF`K(Dj z{{ofR%1YqEu&{P@f$Y!D1$)Fd96a{5H#u`@z38|gGh4*u=5A_3x512D^Ye}v&7Qbo z!g(J2OgMbLZ!NH9W&RTRJ>;uQHy`H#>(*qfy(X;%g;$$4BDE7GXqlC0okp72R83hn zMn{kv79FA$nzl~2G4ZZC2ud7L1;I_nq6ponDmF|wrBK*7<*_DvCmoG(0}@m&jI=^x_caCEg}%#>R77b-R8XwkYSN{z=4`ug@XH@YAmW24i9QM6z{wAK0=mP!sY#WmRG-ysCJPO z_9um9*C0&8weKT{4`er?k%IUHLKiJQfT=k53&v@MWeh@y!!#L5Bc|kzI3^*fU`B2X zKxorS;|Y-H7YW~uLU2VNxe=&^nQxMY=51dM7Zf5z@-2h$?e@lwU2z(X z^p?YRr$5@THf)C+d4^tok}cpLf7wbR)HsO1dW0Gc8P;C+C*1 zg_N6RV0tvq=mp*yyft|vqS}2-;NZGot)20{bBBPV>D&Y?T4h!K7)Kb_U9DBQwXJ6h zd5iItmc+6~Uv){0viwV8TCHe4D!Bf2<`DwSi~`VI_6F3y(6mN6(&X55GKoC_c5x4R z=*|>gQ-avJizlx4J;KYbU%4*uHtFTC=EN|L?s>OYrKq)|0~nA0^ZMHw??{sKN?Rv@ zie{Q?LNVcI-figqcvTWz4 z>U$A~IbDQ8GVrFDNN&d&V(YxjitAxP?g<;Rz%%u3fL3Q)n>teD96Vg7 zpwP}nxk+bVjyXPg66}eD^~gd>J+AjeQhwv?fW%hdXSy57DS54Svg1p&gD1#`v?eg2|&BqyLiDP$ZFq(L>xahWjV z;soi@>~?57WyWGo)qC<-eZ;M0O~v6-^TFdy*zNH6C+xo)L64}eyc)MHq}G!5s047P zYZ;?(P=;^BYmXnqG^uR)huYZwtF$a)3GYy|Y;V-;$& z9f^trk*galG#qL~#WmcE@NFCY;YgJ|rN4-uza{;l`;jm;oepJ+ldbpBEV>*KJtSO+ zw7+TTqmvzPTKecz#~Y7&@lzNeddrK{R?IwTp`Voti@;ShPk zBrc(2Pb07v9m724?LGiai}{xYF~tqeaAUH#1To#>Qem!GEmv;ZG3Xx4#hM*kfU3r< zz~A}OtRtjI^;#{!--f6p9o|gmc>V1v^w>q05IlIDxaW9%b;=>-{f;_q z>p&3~4wpu(HFI&iDWbe0@+sngV%sSewwj1+C*HqJU?$KVn7LA}V9fUmVVPn&MfptI zM25(~b2LZc@}xD9fuRlY{0p(RIti_)o*1x|zjFef!gnnWU(fdkkn5KS5-xzG_`L2? zQ*>7HK*b$I_W#gV9G}-+T>lHu3By9>fl54t5`N5ABA?e?Vyb0=xz6@HjO>5hR~(<$ zUEI*cn^lUSAGlN;3l{hZU#Wavcd0lw2L5s?72wVTwJg^4fuHgf%I9?#nmk*qJy2;+ zAorj3mB#0Fmo{*U3jGJI;FBog=Y2);dEG^hKJTbrjC1-Fl?SRV&T|X=6JODMZY!Gd zeBo+e!%vGCz-A8WM#pg;HtBFJjkp9tsk;Lr0;jMW?*EahAHrtgSh4w-c69D`eU%+tT3CG zttVZjx3gKvF%tHralbpx{G87&%d(Hg=vrg$d@P$%WP47fJewm?azA#zTh$rgPofFC z9R&|)D?E5W(Ps$38+;iK+r#i8#gk%aQ-=eVu-y?WA&efdwh6fK)6Sjh$Pp(!$aW<# z!sUt`ZG(rg_^KI!fa1o#`43v|DNfM(I} z!&D0n`2vLyb|+x}2SRYRfO`~97XpPC{IAh5AI^(`Yd$*YOTu9vUG!tqFx>Ogsb6{- zuKEhvOIcbR_-Ei#El?POZ?!;SSlAAj3vBT5=;u(rn6RiLKu0_6w2bzN@hqa$QQmOI zAjDC;u^ALy0I279o8paJwVe>lY?`GXXWR+iPT~e(mdH4zq-Pk*lGJ+h?#Rp$VNDT= z4r z1#A=bJU)^ySL0sjrQ&PMnb0JH`^E;sig9gp3D1F*n3VBpD2l-KIe2rXbtuI;C)XE{ z`yaS<1GB>Cw$izp6{>g*KOR*a_fbUB!_?ilM+xCVR94-h@Pp5&u=W`x(nWfa+5oC3 z>+n1+%;C^LRD+|EQdE16N-!lfvkxdRVP{%()I?t_&fxyirI~H#bnMHn*esWY@XCI` zF8X9`^ck&qGH%&`=Iz7ryLi!>!MHtuC9&8|VhbXyC&fXfop81uHtdY+cF#R%!%mvs z0dq+l;!^>yP+HKVL5p^^PLcL>B1m`zflev~8LA}h|S>7lkvlCFZ(y zK+C9?2q7z14>H;t4jurfw>-P&N$kt|h>PaG+P52dnyfEt_^{N5u_%na0V~6yg^0>R z-6wl1;c5zYTe1i67~<&QD2n~$QN8mLDnRT6grk3KQ)|0Ozc6g?oz5HUmy7zgX@m#hETR9rU zm=p^%uh%_$utv^Gw;C?H)7rHYCvNGp*yufdPm_8|&kB!5H05SaXqL6Vt%y0SF0t*o z^USy+UC(0Ua?To|8-L83*f{MDB9xcjDJy)znH=^+hdG9_X!s5+(Bq1F2inLwu9EG< zOXkf}^y3R9^;J166Gup@9Z1zB(H6f~y{yaLgA$`eBuo`q&L2thY>O zLe{QUOKI9I6SE7AD$yg*76zah z+&F?WGcY;8#~b5t3?AZUIAMU*4Z+74&z%xEG}6SHNo>!BH%GOIauUlCFuXh-k!iy? zkTJO&Z}#Es=lK@XN_-x!hQU0?=Lc{IV;qeE#}9*-v_{!AEVKGxMBx~X<*eaaeLuH@ z?|05-1*V_2b|6w8&AMNXX5Ft*)0YOktV~KWxx9pSP&;uG4iJaJDn%YtZRd^h91%wA z@zBplDzWTga7y$mTcEv}c8O;9F|1t!;t*Qxu3Eo?^^HtXuM)ky&aq=SMilAst52AU z(m5{HG5EAY802*?r}@nsE?Gbkz&yq65qgI=he`_D1v!9H95z8~TQ@G{96Vu0IM%dt zjJ!z*r;xSpcASr|;KhVX@WJ5mxed?pPUATTayy>ig*B}a6&&Z%HExePNBwq#XAL`k z7QqQ{38CT&Mpx?+c|KMdNOd+;K0#I)Q+X(*)hJufrI_> ztR)iqz(Kn0?>C0QmBZ1Qqgm4j4)V=LdDC)yCI=4EWg1H2H!ZjQX>mo?Z@~GPu?1#* ztu$h6=kV|Y!r!;vZ8x$`nS*d-CWj8r51ZJ*IgkCA^P{*n%|(r!cS1ORaF_A0l!*fe zop0!ZZQR&vP8gFo>K(f`%`Nw~8vEeXVL$eVhPY?b`Nnf=mZvw_BzBaFYqK^u{f7i@ z$4(mU>Wu4=7QD|GM|9aRKinbfk)0R_&)P%2K6GgPEc&WjR~Vz)3wnRm9C8WRAb z){UKfIeU?Of=tYZ5fF#CoSZ}O{sV`qJh!+pp-tIvS~0u>gLe(_Wa8z}eDc0NHO%Te z`t~h&R)@1(_{vRbQuZ=()7#Sfd_alWTBkGJGHMI?4`g&AkI@8HuOzGqoK z50!Ix@H!1BtVY?H^AU6&-B*DLmS-H4d=(R!&E70vkD^fk!$v8%SlQtW7qE)(lmLTW${SZ=}#_k`fZl5nxVN~q+EMz|reCzFF4&M66oZ!=%)vN>Q3La*Jt$p29 z^yTT&a))%b)sA=|waXx&@w|2F6$flY^VJ_Dn#;a<2WFT4@X+S<0Zrm=_<-Ko4Rohn zv6b-pBszBWx!o0909x+rpsec3&;GH-Y) zyBWAgXzaOs`LcS7xsB@AP<5#yZ7a@cjb2-WL^@H?-J{j9<&65RV;K}C=gU(YS^IILXTr@+G(&~>Vx zZ8iw=`~n?RI`Z&U_vW^`kaqw9?Ya zu=_niN#d#&n4Q?~619aJwG&OC-gQ-6v}16i36xR9R>e-xTM$_P)r6o1QXXOZ9796b zO7#!KhU2oO(A!Q(QRq(RAi~444}md>U?iGF8rhwIt%N*s5P6l5jrWJ=z)D)mOpD3W zbKp9ali!X^zsK!R$WQpZ?m{}%qK+Hk;EX}U~gz!k?9_^HVBo; zwY};Vf51~7xIr$*OQ@Ip@s|sYFzc}wfz>1*kZ!c=D)YklG^B~)UTM~OmagVA80}u- ziH)Q~t*;ysVC!h_W0x{Ggyz!#dlgZ_efE@IR`6gQYfD>OxXViL+T|wBuaUhU9VQQC zaH#MVQv4(WuJ~Xcl6s+nkjvwI9XV;0&JFIxL~sE0mxQ1QyB|dtVLSJRmIz^=CrU_& zC;>azrMY;-BS%Cp@qu~^b#;|L)WqaNR}bMj+)IG)C03kdji>N%OV>(OcSH!ikEVAq z=%RnPV9IGN%I{(&)|w?ggG4{Z8gLSXCU&w{xAjC94`M%IX~XNa z0Q~HF0Ho0OAFm6*F2qf(Jf&?$WwlR4Hh^LwtIZYPf%o?a1cj8CD-r|F9HIE8#HMrq z@Vp}BAJ)CA^#u<^`#*xhRtE?Fy--x#48(P{bi+|D= zxB4v#HHBE8u!%h3FME}T7f@^ON|pD76YiXo>^XF0A6IMW3e))suTU26cENGReh&cn z1p+|oj8Ut3HO7_@;r)5Y{Aon3hRmJ%C5MfO;mDWXdq#OMG#QN{N#X6o0@5eplM_Bb z=hNbq6ZT(l%n;J99K_3<0vZJYcOyq z;EKBZ2Ews>P>JhfVcG@>){`72`FOJqhNIDhz<#CiVh=cJTz(_T)5z(jtf7Vgi5)#N zee%?6cA~xrHUY~37sJ*VV86*OPO&>hiIEONWxUznFdZYTC-Z?kS_0plcyO5yupT_| z0Xxs

Install finished

+ +

The Meson build system is now installed. Note that Meson does not + provide any GUI applications, it is only usable from the command + line. You can verify if your installation of Meson is working by + running the following command in a terminal +

+ +
+      $ meson --version
+    
+ +

If the system reports that the program could not be found + you might need to edit your configuration files so + that /usr/local/bin is in your path. +

+ + + diff --git a/devtools/meson/packaging/macpages/English.lproj/license.html b/devtools/meson/packaging/macpages/English.lproj/license.html new file mode 100644 index 0000000..235e582 --- /dev/null +++ b/devtools/meson/packaging/macpages/English.lproj/license.html @@ -0,0 +1,209 @@ + + + + +
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+  
+  
+
diff --git a/devtools/meson/packaging/macpages/English.lproj/welcome.html b/devtools/meson/packaging/macpages/English.lproj/welcome.html
new file mode 100644
index 0000000..3832223
--- /dev/null
+++ b/devtools/meson/packaging/macpages/English.lproj/welcome.html
@@ -0,0 +1,12 @@
+
+  
+  
+  
+
+  

Meson build system installer

+ +

This package will install the command line tools of Meson to + this computer. +

+ + diff --git a/devtools/meson/pyproject.toml b/devtools/meson/pyproject.toml new file mode 100644 index 0000000..8fe2f47 --- /dev/null +++ b/devtools/meson/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/devtools/meson/run_cross_test.py b/devtools/meson/run_cross_test.py new file mode 100644 index 0000000..bafdbb6 --- /dev/null +++ b/devtools/meson/run_cross_test.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 + +# Copyright 2013-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +'''Runs the basic test suite through a cross compiler. + +This is now just a wrapper around run_project_tests.py with specific arguments +''' + +import argparse +import subprocess +from mesonbuild import mesonlib +from mesonbuild.coredata import version as meson_version +from pathlib import Path +import json +import os + + +def runtests(cross_file, failfast, cross_only, test_list, env=None): + tests = ['--only'] + test_list + if not cross_only: + tests.append('native') + cmd = mesonlib.python_command + ['run_project_tests.py', '--backend', 'ninja'] + if failfast: + cmd += ['--failfast'] + cmd += tests + cmd += ['--cross-file', cross_file] + if cross_only: + cmd += ['--native-file', 'cross/none.txt'] + return subprocess.call(cmd, env=env) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--failfast', action='store_true') + parser.add_argument('--cross-only', action='store_true') + parser.add_argument('cross_file') + options = parser.parse_args() + cf_path = Path(options.cross_file) + try: + data = json.loads(cf_path.read_text(encoding='utf-8')) + real_cf = cf_path.resolve().parent / data['file'] + assert real_cf.exists() + env = os.environ.copy() + env.update(data['env']) + return runtests(real_cf.as_posix(), options.failfast, options.cross_only, data['tests'], env=env) + except Exception: + return runtests(options.cross_file, options.failfast, options.cross_only, ['common']) + +if __name__ == '__main__': + print('Meson build system', meson_version, 'Cross Tests') + raise SystemExit(main()) diff --git a/devtools/meson/run_meson_command_tests.py b/devtools/meson/run_meson_command_tests.py new file mode 100644 index 0000000..093d6ea --- /dev/null +++ b/devtools/meson/run_meson_command_tests.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 + +# Copyright 2018 The Meson development team +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import tempfile +import unittest +import subprocess +import zipapp +import sysconfig +from pathlib import Path + +from mesonbuild.mesonlib import windows_proof_rmtree, python_command, is_windows +from mesonbuild.coredata import version as meson_version + +scheme = None + +def needs_debian_path_hack(): + try: + import setuptools + return int(setuptools.__version__.split('.')[0]) < 65 + except ModuleNotFoundError: + return False + +if needs_debian_path_hack(): + # Handle the scheme that Debian patches in the as default + # This function was renamed and made public in Python 3.10 + if hasattr(sysconfig, 'get_default_scheme'): + scheme = sysconfig.get_default_scheme() + else: + scheme = sysconfig._get_default_scheme() + if scheme == 'posix_local': + scheme = 'posix_prefix' + +def get_pypath(): + if scheme: + pypath = sysconfig.get_path('purelib', scheme=scheme, vars={'base': ''}) + else: + pypath = sysconfig.get_path('purelib', vars={'base': ''}) + # Ensure that / is the path separator and not \, then strip / + return Path(pypath).as_posix().strip('/') + +def get_pybindir(): + # 'Scripts' on Windows and 'bin' on other platforms including MSYS + if scheme: + return sysconfig.get_path('scripts', scheme=scheme, vars={'base': ''}).strip('\\/') + return sysconfig.get_path('scripts', vars={'base': ''}).strip('\\/') + +class CommandTests(unittest.TestCase): + ''' + Test that running meson in various ways works as expected by checking the + value of mesonlib.meson_command that was set during configuration. + ''' + + def setUp(self): + super().setUp() + self.orig_env = os.environ.copy() + self.orig_dir = os.getcwd() + os.environ['MESON_COMMAND_TESTS'] = '1' + self.tmpdir = Path(tempfile.mkdtemp()).resolve() + self.src_root = Path(__file__).resolve().parent + self.testdir = str(self.src_root / 'test cases/common/1 trivial') + self.meson_args = ['--backend=ninja'] + + def tearDown(self): + try: + windows_proof_rmtree(str(self.tmpdir)) + except FileNotFoundError: + pass + os.environ.clear() + os.environ.update(self.orig_env) + os.chdir(str(self.orig_dir)) + super().tearDown() + + def _run(self, command, workdir=None, env=None): + ''' + Run a command while printing the stdout, and also return a copy of it + ''' + # If this call hangs CI will just abort. It is very hard to distinguish + # between CI issue and test bug in that case. Set timeout and fail loud + # instead. + p = subprocess.run(command, stdout=subprocess.PIPE, + env=env, text=True, + cwd=workdir, timeout=60 * 5) + print(p.stdout) + if p.returncode != 0: + raise subprocess.CalledProcessError(p.returncode, command) + return p.stdout + + def assertMesonCommandIs(self, line, cmd): + self.assertTrue(line.startswith('meson_command '), msg=line) + self.assertEqual(line, f'meson_command is {cmd!r}') + + def test_meson_uninstalled(self): + # This is what the meson command must be for all these cases + resolved_meson_command = python_command + [str(self.src_root / 'meson.py')] + # Absolute path to meson.py + os.chdir('/') + builddir = str(self.tmpdir / 'build1') + meson_py = str(self.src_root / 'meson.py') + meson_setup = [meson_py, 'setup'] + meson_command = python_command + meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # ./meson.py + os.chdir(str(self.src_root)) + builddir = str(self.tmpdir / 'build2') + meson_py = './meson.py' + meson_setup = [meson_py, 'setup'] + meson_command = python_command + meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # Symlink to meson.py + if is_windows(): + # Symlinks require admin perms + return + os.chdir(str(self.src_root)) + builddir = str(self.tmpdir / 'build3') + # Create a symlink to meson.py in bindir, and add it to PATH + bindir = (self.tmpdir / 'bin') + bindir.mkdir() + (bindir / 'meson').symlink_to(self.src_root / 'meson.py') + (bindir / 'python3').symlink_to(python_command[0]) + os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] + # use our overridden PATH-compatible python + path_resolved_meson_command = [str(bindir / 'meson')] + # See if it works! + meson_py = 'meson' + meson_setup = [meson_py, 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], path_resolved_meson_command) + + def test_meson_installed(self): + # Install meson + prefix = self.tmpdir / 'prefix' + pylibdir = prefix / get_pypath() + bindir = prefix / get_pybindir() + pylibdir.mkdir(parents=True) + # XXX: join with empty name so it always ends with os.sep otherwise + # distutils complains that prefix isn't contained in PYTHONPATH + os.environ['PYTHONPATH'] = os.path.join(str(pylibdir), '') + os.environ['PATH'] = str(bindir) + os.pathsep + os.environ['PATH'] + self._run(python_command + ['setup.py', 'install', '--prefix', str(prefix)]) + # Fix importlib-metadata by appending all dirs in pylibdir + PYTHONPATHS = [pylibdir] + [x for x in pylibdir.iterdir()] + PYTHONPATHS = [os.path.join(str(x), '') for x in PYTHONPATHS] + os.environ['PYTHONPATH'] = os.pathsep.join(PYTHONPATHS) + # Check that all the files were installed correctly + self.assertTrue(bindir.is_dir()) + self.assertTrue(pylibdir.is_dir()) + # Run `meson` + os.chdir('/') + resolved_meson_command = [str(bindir / 'meson')] + builddir = str(self.tmpdir / 'build1') + meson_setup = ['meson', 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # Run `/path/to/meson` + builddir = str(self.tmpdir / 'build2') + meson_setup = [str(bindir / 'meson'), 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + # Run `python3 -m mesonbuild.mesonmain` + resolved_meson_command = python_command + ['-m', 'mesonbuild.mesonmain'] + builddir = str(self.tmpdir / 'build3') + meson_setup = ['-m', 'mesonbuild.mesonmain', 'setup'] + meson_command = python_command + meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + if is_windows(): + # Next part requires a shell + return + # `meson` is a wrapper to `meson.real` + resolved_meson_command = [str(bindir / 'meson.real')] + builddir = str(self.tmpdir / 'build4') + (bindir / 'meson').rename(bindir / 'meson.real') + wrapper = (bindir / 'meson') + wrapper.write_text('#!/bin/sh\n\nmeson.real "$@"', encoding='utf-8') + wrapper.chmod(0o755) + meson_setup = [str(wrapper), 'setup'] + meson_command = meson_setup + self.meson_args + stdo = self._run(meson_command + [self.testdir, builddir]) + self.assertMesonCommandIs(stdo.split('\n')[0], resolved_meson_command) + + def test_meson_exe_windows(self): + raise unittest.SkipTest('NOT IMPLEMENTED') + + def test_meson_zipapp(self): + if is_windows(): + raise unittest.SkipTest('NOT IMPLEMENTED') + source = Path(__file__).resolve().parent + target = self.tmpdir / 'meson.pyz' + script = source / 'packaging' / 'create_zipapp.py' + self._run([script.as_posix(), source, '--outfile', target, '--interpreter', python_command[0]]) + self._run([target.as_posix(), '--help']) + + def test_meson_runpython(self): + meson_command = str(self.src_root / 'meson.py') + script_file = str(self.src_root / 'foo.py') + test_command = 'import sys; print(sys.argv[1])' + env = os.environ.copy() + del env['MESON_COMMAND_TESTS'] + with open(script_file, 'w') as f: + f.write('#!/usr/bin/env python3\n\n') + f.write(f'{test_command}\n') + + for cmd in [['-c', test_command, 'fake argument'], [script_file, 'fake argument']]: + pyout = self._run(python_command + cmd) + mesonout = self._run(python_command + [meson_command, 'runpython'] + cmd, env=env) + self.assertEqual(pyout, mesonout) + + +if __name__ == '__main__': + print('Meson build system', meson_version, 'Command Tests') + raise SystemExit(unittest.main(buffer=True)) diff --git a/devtools/meson/run_project_tests.py b/devtools/meson/run_project_tests.py new file mode 100644 index 0000000..33ee5ca --- /dev/null +++ b/devtools/meson/run_project_tests.py @@ -0,0 +1,1656 @@ +#!/usr/bin/env python3 + +# Copyright 2012-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +# Work around some pathlib bugs... +from mesonbuild import _pathlib +import sys +sys.modules['pathlib'] = _pathlib + +from concurrent.futures import ProcessPoolExecutor, CancelledError +from enum import Enum +from io import StringIO +from pathlib import Path, PurePath +import argparse +import functools +import itertools +import json +import multiprocessing +import os +import re +import shlex +import shutil +import signal +import subprocess +import tempfile +import time +import typing as T +import xml.etree.ElementTree as ET +import collections +import importlib.util + +from mesonbuild import build +from mesonbuild import environment +from mesonbuild import compilers +from mesonbuild import mesonlib +from mesonbuild import mlog +from mesonbuild import mtest +from mesonbuild.compilers import compiler_from_language, detect_objc_compiler, detect_objcpp_compiler +from mesonbuild.build import ConfigurationData +from mesonbuild.mesonlib import MachineChoice, Popen_safe, TemporaryDirectoryWinProof, setup_vsenv +from mesonbuild.mlog import blue, bold, cyan, green, red, yellow, normal_green +from mesonbuild.coredata import backendlist, version as meson_version +from mesonbuild.modules.python import PythonExternalProgram +from run_tests import get_fake_options, run_configure, get_meson_script +from run_tests import get_backend_commands, get_backend_args_for_dir, Backend +from run_tests import ensure_backend_detects_changes +from run_tests import guess_backend + +if T.TYPE_CHECKING: + from types import FrameType + from mesonbuild.environment import Environment + from mesonbuild._typing import Protocol + from concurrent.futures import Future + + class CompilerArgumentType(Protocol): + cross_file: str + native_file: str + use_tmpdir: bool + + + class ArgumentType(CompilerArgumentType): + + """Typing information for command line arguments.""" + + extra_args: T.List[str] + backend: str + num_workers: int + failfast: bool + no_unittests: bool + only: T.List[str] + +ALL_TESTS = ['cmake', 'common', 'native', 'warning-meson', 'failing-meson', 'failing-build', 'failing-test', + 'keyval', 'platform-osx', 'platform-windows', 'platform-linux', + 'java', 'C#', 'vala', 'cython', 'rust', 'd', 'objective c', 'objective c++', + 'fortran', 'swift', 'cuda', 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm', 'wayland' + ] + + +class BuildStep(Enum): + configure = 1 + build = 2 + test = 3 + install = 4 + clean = 5 + validate = 6 + + +class TestResult(BaseException): + def __init__(self, cicmds: T.List[str]) -> None: + self.msg = '' # empty msg indicates test success + self.stdo = '' + self.stde = '' + self.mlog = '' + self.cicmds = cicmds + self.conftime: float = 0 + self.buildtime: float = 0 + self.testtime: float = 0 + + def add_step(self, step: BuildStep, stdo: str, stde: str, mlog: str = '', time: float = 0) -> None: + self.step = step + self.stdo += stdo + self.stde += stde + self.mlog += mlog + if step == BuildStep.configure: + self.conftime = time + elif step == BuildStep.build: + self.buildtime = time + elif step == BuildStep.test: + self.testtime = time + + def fail(self, msg: str) -> None: + self.msg = msg + +python = PythonExternalProgram(sys.executable) +python.sanity() + +class InstalledFile: + def __init__(self, raw: T.Dict[str, str]): + self.path = raw['file'] + self.typ = raw['type'] + self.platform = raw.get('platform', None) + self.language = raw.get('language', 'c') # type: str + + version = raw.get('version', '') # type: str + if version: + self.version = version.split('.') # type: T.List[str] + else: + # split on '' will return [''], we want an empty list though + self.version = [] + + def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Path]: + p = Path(self.path) + canonical_compiler = compiler + if ((compiler in ['clang-cl', 'intel-cl']) or + (env.machines.host.is_windows() and compiler in {'pgi', 'dmd', 'ldc'})): + canonical_compiler = 'msvc' + + python_suffix = python.info['suffix'] + + has_pdb = False + if self.language in {'c', 'cpp'}: + has_pdb = canonical_compiler == 'msvc' + elif self.language == 'd': + # dmd's optlink does not generate pdb files + has_pdb = env.coredata.compilers.host['d'].linker.id in {'link', 'lld-link'} + + # Abort if the platform does not match + matches = { + 'msvc': canonical_compiler == 'msvc', + 'gcc': canonical_compiler != 'msvc', + 'cygwin': env.machines.host.is_cygwin(), + '!cygwin': not env.machines.host.is_cygwin(), + }.get(self.platform or '', True) + if not matches: + return None + + # Handle the different types + if self.typ in {'py_implib', 'python_lib', 'python_file', 'python_bytecode'}: + val = p.as_posix() + val = val.replace('@PYTHON_PLATLIB@', python.platlib) + val = val.replace('@PYTHON_PURELIB@', python.purelib) + p = Path(val) + if self.typ == 'python_file': + return p + if self.typ == 'python_lib': + return p.with_suffix(python_suffix) + if self.typ == 'py_implib': + p = p.with_suffix(python_suffix) + if env.machines.host.is_windows() and canonical_compiler == 'msvc': + return p.with_suffix('.lib') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): + return p.with_suffix('.dll.a') + else: + return None + if self.typ == 'python_bytecode': + return p.parent / importlib.util.cache_from_source(p.name) + elif self.typ in {'file', 'dir'}: + return p + elif self.typ == 'shared_lib': + if env.machines.host.is_windows() or env.machines.host.is_cygwin(): + # Windows only has foo.dll and foo-X.dll + if len(self.version) > 1: + return None + if self.version: + p = p.with_name('{}-{}'.format(p.name, self.version[0])) + return p.with_suffix('.dll') + + p = p.with_name(f'lib{p.name}') + if env.machines.host.is_darwin(): + # MacOS only has libfoo.dylib and libfoo.X.dylib + if len(self.version) > 1: + return None + + # pathlib.Path.with_suffix replaces, not appends + suffix = '.dylib' + if self.version: + suffix = '.{}{}'.format(self.version[0], suffix) + else: + # pathlib.Path.with_suffix replaces, not appends + suffix = '.so' + if self.version: + suffix = '{}.{}'.format(suffix, '.'.join(self.version)) + return p.with_suffix(suffix) + elif self.typ == 'exe': + if 'mwcc' in canonical_compiler: + return p.with_suffix('.nef') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): + return p.with_suffix('.exe') + elif self.typ == 'pdb': + if self.version: + p = p.with_name('{}-{}'.format(p.name, self.version[0])) + return p.with_suffix('.pdb') if has_pdb else None + elif self.typ in {'implib', 'implibempty'}: + if env.machines.host.is_windows() and canonical_compiler == 'msvc': + # only MSVC doesn't generate empty implibs + if self.typ == 'implibempty' and compiler == 'msvc': + return None + return p.parent / (re.sub(r'^lib', '', p.name) + '.lib') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): + return p.with_suffix('.dll.a') + else: + return None + elif self.typ == 'expr': + return Path(platform_fix_name(p.as_posix(), canonical_compiler, env)) + else: + raise RuntimeError(f'Invalid installed file type {self.typ}') + + return p + + def get_paths(self, compiler: str, env: environment.Environment, installdir: Path) -> T.List[Path]: + p = self.get_path(compiler, env) + if not p: + return [] + if self.typ == 'dir': + abs_p = installdir / p + if not abs_p.exists(): + raise RuntimeError(f'{p} does not exist') + if not abs_p.is_dir(): + raise RuntimeError(f'{p} is not a directory') + return [x.relative_to(installdir) for x in abs_p.rglob('*') if x.is_file() or x.is_symlink()] + else: + return [p] + +@functools.total_ordering +class TestDef: + def __init__(self, path: Path, name: T.Optional[str], args: T.List[str], skip: bool = False, skip_category: bool = False): + self.category = path.parts[1] + self.path = path + self.name = name + self.args = args + self.skip = skip + self.env = os.environ.copy() + self.installed_files = [] # type: T.List[InstalledFile] + self.do_not_set_opts = [] # type: T.List[str] + self.stdout = [] # type: T.List[T.Dict[str, str]] + self.skip_category = skip_category + self.skip_expected = False + + # Always print a stack trace for Meson exceptions + self.env['MESON_FORCE_BACKTRACE'] = '1' + + def __repr__(self) -> str: + return '<{}: {:<48} [{}: {}] -- {}>'.format(type(self).__name__, str(self.path), self.name, self.args, self.skip) + + def display_name(self) -> mlog.TV_LoggableList: + # Remove the redundant 'test cases' part + section, id = self.path.parts[1:3] + res: mlog.TV_LoggableList = [f'{section}:', bold(id)] + if self.name: + res += [f' ({self.name})'] + return res + + def __lt__(self, other: object) -> bool: + if isinstance(other, TestDef): + # None is not sortable, so replace it with an empty string + s_id = int(self.path.name.split(' ')[0]) + o_id = int(other.path.name.split(' ')[0]) + return (s_id, self.path, self.name or '') < (o_id, other.path, other.name or '') + return NotImplemented + +failing_testcases: T.List[str] = [] +failing_logs: T.List[str] = [] +print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ +under_ci = 'CI' in os.environ +ci_is_github = 'GITHUB_ACTIONS' in os.environ +raw_ci_jobname = os.environ.get('MESON_CI_JOBNAME', None) +ci_jobname = raw_ci_jobname if raw_ci_jobname != 'thirdparty' else None +do_debug = under_ci or print_debug +no_meson_log_msg = 'No meson-log.txt found.' + +host_c_compiler: T.Optional[str] = None +compiler_id_map: T.Dict[str, str] = {} +tool_vers_map: T.Dict[str, str] = {} + +compile_commands: T.List[str] +clean_commands: T.List[str] +test_commands: T.List[str] +install_commands: T.List[str] +uninstall_commands: T.List[str] + +backend: 'Backend' +backend_flags: T.List[str] + +stop: bool = False +is_worker_process: bool = False + +# Let's have colors in our CI output +if under_ci: + def _ci_colorize_console() -> bool: + return not is_worker_process + + mlog.colorize_console = _ci_colorize_console + +class StopException(Exception): + def __init__(self) -> None: + super().__init__('Stopped by user') + +def stop_handler(signal: int, frame: T.Optional['FrameType']) -> None: + global stop + stop = True +signal.signal(signal.SIGINT, stop_handler) +signal.signal(signal.SIGTERM, stop_handler) + +def setup_commands(optbackend: str) -> None: + global do_debug, backend, backend_flags + global compile_commands, clean_commands, test_commands, install_commands, uninstall_commands + backend, backend_flags = guess_backend(optbackend, shutil.which('msbuild')) + compile_commands, clean_commands, test_commands, install_commands, \ + uninstall_commands = get_backend_commands(backend, do_debug) + +# TODO try to eliminate or at least reduce this function +def platform_fix_name(fname: str, canonical_compiler: str, env: environment.Environment) -> str: + if '?lib' in fname: + if env.machines.host.is_windows() and canonical_compiler == 'msvc': + fname = re.sub(r'lib/\?lib(.*)\.', r'bin/\1.', fname) + fname = re.sub(r'/\?lib/', r'/bin/', fname) + elif env.machines.host.is_windows(): + fname = re.sub(r'lib/\?lib(.*)\.', r'bin/lib\1.', fname) + fname = re.sub(r'\?lib(.*)\.dll$', r'lib\1.dll', fname) + fname = re.sub(r'/\?lib/', r'/bin/', fname) + elif env.machines.host.is_cygwin(): + fname = re.sub(r'lib/\?lib(.*)\.so$', r'bin/cyg\1.dll', fname) + fname = re.sub(r'lib/\?lib(.*)\.', r'bin/cyg\1.', fname) + fname = re.sub(r'\?lib(.*)\.dll$', r'cyg\1.dll', fname) + fname = re.sub(r'/\?lib/', r'/bin/', fname) + else: + fname = re.sub(r'\?lib', 'lib', fname) + + if fname.endswith('?so'): + if env.machines.host.is_windows() and canonical_compiler == 'msvc': + fname = re.sub(r'lib/([^/]*)\?so$', r'bin/\1.dll', fname) + fname = re.sub(r'/(?:lib|)([^/]*?)\?so$', r'/\1.dll', fname) + return fname + elif env.machines.host.is_windows(): + fname = re.sub(r'lib/([^/]*)\?so$', r'bin/\1.dll', fname) + fname = re.sub(r'/([^/]*?)\?so$', r'/\1.dll', fname) + return fname + elif env.machines.host.is_cygwin(): + fname = re.sub(r'lib/([^/]*)\?so$', r'bin/\1.dll', fname) + fname = re.sub(r'/lib([^/]*?)\?so$', r'/cyg\1.dll', fname) + fname = re.sub(r'/([^/]*?)\?so$', r'/\1.dll', fname) + return fname + elif env.machines.host.is_darwin(): + return fname[:-3] + '.dylib' + else: + return fname[:-3] + '.so' + + return fname + +def validate_install(test: TestDef, installdir: Path, env: environment.Environment) -> str: + ret_msg = '' + expected_raw = [] # type: T.List[Path] + for i in test.installed_files: + try: + expected_raw += i.get_paths(host_c_compiler, env, installdir) + except RuntimeError as err: + ret_msg += f'Expected path error: {err}\n' + expected = {x: False for x in expected_raw} + found = [x.relative_to(installdir) for x in installdir.rglob('*') if x.is_file() or x.is_symlink()] + # Mark all found files as found and detect unexpected files + for fname in found: + if fname not in expected: + ret_msg += f'Extra file {fname} found.\n' + continue + expected[fname] = True + # Check if expected files were found + for p, f in expected.items(): + if not f: + ret_msg += f'Expected file {p} missing.\n' + # List dir content on error + if ret_msg != '': + ret_msg += '\nInstall dir contents:\n' + for p in found: + ret_msg += f' - {p}\n' + return ret_msg + +def log_text_file(logfile: T.TextIO, testdir: Path, result: TestResult) -> None: + logfile.write('%s\nstdout\n\n---\n' % testdir.as_posix()) + logfile.write(result.stdo) + logfile.write('\n\n---\n\nstderr\n\n---\n') + logfile.write(result.stde) + logfile.write('\n\n---\n\n') + if print_debug: + try: + print(result.stdo) + except UnicodeError: + sanitized_out = result.stdo.encode('ascii', errors='replace').decode() + print(sanitized_out) + try: + print(result.stde, file=sys.stderr) + except UnicodeError: + sanitized_err = result.stde.encode('ascii', errors='replace').decode() + print(sanitized_err, file=sys.stderr) + + +def _run_ci_include(args: T.List[str]) -> str: + header = f'Included file {args[0]}:' + footer = '' + if ci_is_github: + header = f'::group::==== {header} ====' + footer = '::endgroup::' + if not args: + return 'At least one parameter required' + try: + data = Path(args[0]).read_text(errors='ignore', encoding='utf-8') + return f'{header}\n{data}\n{footer}\n' + except Exception: + return 'Failed to open {}\n'.format(args[0]) + +ci_commands = { + 'ci_include': _run_ci_include +} + +def run_ci_commands(raw_log: str) -> T.List[str]: + res = [] + for l in raw_log.splitlines(): + if not l.startswith('!meson_ci!/'): + continue + cmd = shlex.split(l[11:]) + if not cmd or cmd[0] not in ci_commands: + continue + res += ['CI COMMAND {}:\n{}'.format(cmd[0], ci_commands[cmd[0]](cmd[1:]))] + return res + +class OutputMatch: + def __init__(self, how: str, expected: str, count: int) -> None: + self.how = how + self.expected = expected + self.count = count + + def match(self, actual: str) -> bool: + if self.how == "re": + return bool(re.match(self.expected, actual)) + return self.expected == actual + +def _compare_output(expected: T.List[T.Dict[str, str]], output: str, desc: str) -> str: + if expected: + matches: T.List[OutputMatch] = [] + nomatches: T.List[OutputMatch] = [] + for item in expected: + how = item.get('match', 'literal') + expected_line = item.get('line') + count = int(item.get('count', -1)) + + # Simple heuristic to automatically convert path separators for + # Windows: + # + # Any '/' appearing before 'WARNING' or 'ERROR' (i.e. a path in a + # filename part of a location) is replaced with '\' (in a re: '\\' + # which matches a literal '\') + # + # (There should probably be a way to turn this off for more complex + # cases which don't fit this) + if mesonlib.is_windows(): + if how != "re": + sub = r'\\' + else: + sub = r'\\\\' + expected_line = re.sub(r'/(?=.*(WARNING|ERROR|DEPRECATION))', sub, expected_line) + + m = OutputMatch(how, expected_line, count) + if count == 0: + nomatches.append(m) + else: + matches.append(m) + + + i = 0 + for actual in output.splitlines(): + # Verify this line does not match any unexpected lines (item.count == 0) + for match in nomatches: + if match.match(actual): + return f'unexpected "{match.expected}" found in {desc}' + # If we matched all expected lines, continue to verify there are + # no unexpected line. If nomatches is empty then we are done already. + if i >= len(matches): + if not nomatches: + break + continue + # Check if this line match current expected line + match = matches[i] + if match.match(actual): + if match.count < 0: + # count was not specified, continue with next expected line, + # it does not matter if this line will be matched again or + # not. + i += 1 + else: + # count was specified (must be >0), continue expecting this + # same line. If count reached 0 we continue with next + # expected line but remember that this one must not match + # anymore. + match.count -= 1 + if match.count == 0: + nomatches.append(match) + i += 1 + + if i < len(matches): + # reached the end of output without finding expected + return f'expected "{matches[i].expected}" not found in {desc}' + + return '' + +def validate_output(test: TestDef, stdo: str, stde: str) -> str: + return _compare_output(test.stdout, stdo, 'stdout') + +# There are some class variables and such that cache +# information. Clear all of these. The better solution +# would be to change the code so that no state is persisted +# but that would be a lot of work given that Meson was originally +# coded to run as a batch process. +def clear_internal_caches() -> None: + import mesonbuild.interpreterbase + from mesonbuild.dependencies.cmake import CMakeDependency + from mesonbuild.mesonlib import PerMachine + mesonbuild.interpreterbase.FeatureNew.feature_registry = {} + CMakeDependency.class_cmakeinfo = PerMachine(None, None) + +def run_test_inprocess(testdir: str) -> T.Tuple[int, str, str, str]: + old_stdout = sys.stdout + sys.stdout = mystdout = StringIO() + old_stderr = sys.stderr + sys.stderr = mystderr = StringIO() + old_cwd = os.getcwd() + os.chdir(testdir) + test_log_fname = os.path.join('meson-logs', 'testlog.txt') + try: + returncode_test = mtest.run_with_args(['--no-rebuild']) + if os.path.exists(test_log_fname): + test_log = _run_ci_include([test_log_fname]) + else: + test_log = '' + returncode_benchmark = mtest.run_with_args(['--no-rebuild', '--benchmark', '--logbase', 'benchmarklog']) + finally: + sys.stdout = old_stdout + sys.stderr = old_stderr + os.chdir(old_cwd) + return max(returncode_test, returncode_benchmark), mystdout.getvalue(), mystderr.getvalue(), test_log + +# Build directory name must be the same so Ccache works over +# consecutive invocations. +def create_deterministic_builddir(test: TestDef, use_tmpdir: bool) -> str: + import hashlib + src_dir = test.path.as_posix() + if test.name: + src_dir += test.name + rel_dirname = 'b ' + hashlib.sha256(src_dir.encode(errors='ignore')).hexdigest()[0:10] + abs_pathname = os.path.join(tempfile.gettempdir() if use_tmpdir else os.getcwd(), rel_dirname) + if os.path.exists(abs_pathname): + mesonlib.windows_proof_rmtree(abs_pathname) + os.mkdir(abs_pathname) + return abs_pathname + +def format_parameter_file(file_basename: str, test: TestDef, test_build_dir: str) -> Path: + confdata = ConfigurationData() + confdata.values = {'MESON_TEST_ROOT': (str(test.path.absolute()), 'base directory of current test')} + + template = test.path / (file_basename + '.in') + destination = Path(test_build_dir) / file_basename + mesonlib.do_conf_file(str(template), str(destination), confdata, 'meson') + + return destination + +def detect_parameter_files(test: TestDef, test_build_dir: str) -> T.Tuple[Path, Path]: + nativefile = test.path / 'nativefile.ini' + crossfile = test.path / 'crossfile.ini' + + if os.path.exists(str(test.path / 'nativefile.ini.in')): + nativefile = format_parameter_file('nativefile.ini', test, test_build_dir) + + if os.path.exists(str(test.path / 'crossfile.ini.in')): + crossfile = format_parameter_file('crossfile.ini', test, test_build_dir) + + return nativefile, crossfile + +# In previous python versions the global variables are lost in ProcessPoolExecutor. +# So, we use this tuple to restore some of them +class GlobalState(T.NamedTuple): + compile_commands: T.List[str] + clean_commands: T.List[str] + test_commands: T.List[str] + install_commands: T.List[str] + uninstall_commands: T.List[str] + + backend: 'Backend' + backend_flags: T.List[str] + + host_c_compiler: T.Optional[str] + +def run_test(test: TestDef, + extra_args: T.List[str], + should_fail: str, + use_tmp: bool, + state: T.Optional[GlobalState] = None) -> T.Optional[TestResult]: + # Unpack the global state + global compile_commands, clean_commands, test_commands, install_commands, uninstall_commands, backend, backend_flags, host_c_compiler + if state is not None: + compile_commands, clean_commands, test_commands, install_commands, uninstall_commands, backend, backend_flags, host_c_compiler = state + # Store that this is a worker process + global is_worker_process + is_worker_process = True + # Setup the test environment + assert not test.skip, 'Skipped test should not be run' + build_dir = create_deterministic_builddir(test, use_tmp) + try: + with TemporaryDirectoryWinProof(prefix='i ', dir=None if use_tmp else os.getcwd()) as install_dir: + try: + return _run_test(test, build_dir, install_dir, extra_args, should_fail) + except TestResult as r: + return r + finally: + mlog.shutdown() # Close the log file because otherwise Windows wets itself. + finally: + mesonlib.windows_proof_rmtree(build_dir) + +def _run_test(test: TestDef, + test_build_dir: str, + install_dir: str, + extra_args: T.List[str], + should_fail: str) -> TestResult: + gen_start = time.time() + # Configure in-process + gen_args = ['setup'] + if 'prefix' not in test.do_not_set_opts: + gen_args += ['--prefix', 'x:/usr'] if mesonlib.is_windows() else ['--prefix', '/usr'] + if 'libdir' not in test.do_not_set_opts: + gen_args += ['--libdir', 'lib'] + gen_args += [test.path.as_posix(), test_build_dir] + backend_flags + extra_args + + nativefile, crossfile = detect_parameter_files(test, test_build_dir) + + if nativefile.exists(): + gen_args.extend(['--native-file', nativefile.as_posix()]) + if crossfile.exists(): + gen_args.extend(['--cross-file', crossfile.as_posix()]) + inprocess, res = run_configure(gen_args, env=test.env, catch_exception=True) + returncode, stdo, stde = res + cmd = '(inprocess) $ ' if inprocess else '$ ' + cmd += mesonlib.join_args(gen_args) + logfile = os.path.join(test_build_dir, 'meson-logs', 'meson-log.txt') + if os.path.exists(logfile): + mesonlog = '\n'.join((cmd, _run_ci_include([logfile]))) + else: + mesonlog = no_meson_log_msg + cicmds = run_ci_commands(mesonlog) + testresult = TestResult(cicmds) + testresult.add_step(BuildStep.configure, '\n'.join((cmd, stdo)), stde, mesonlog, time.time() - gen_start) + output_msg = validate_output(test, stdo, stde) + testresult.mlog += output_msg + if output_msg: + testresult.fail('Unexpected output while configuring.') + return testresult + if should_fail == 'meson': + if returncode == 1: + return testresult + elif returncode != 0: + testresult.fail(f'Test exited with unexpected status {returncode}.') + return testresult + else: + testresult.fail('Test that should have failed succeeded.') + return testresult + if returncode != 0: + testresult.fail('Generating the build system failed.') + return testresult + builddata = build.load(test_build_dir) + dir_args = get_backend_args_for_dir(backend, test_build_dir) + + # Build with subprocess + def build_step() -> None: + build_start = time.time() + pc, o, _ = Popen_safe(compile_commands + dir_args, cwd=test_build_dir, stderr=subprocess.STDOUT) + testresult.add_step(BuildStep.build, o, '', '', time.time() - build_start) + if should_fail == 'build': + if pc.returncode != 0: + raise testresult + testresult.fail('Test that should have failed to build succeeded.') + raise testresult + if pc.returncode != 0: + testresult.fail('Compiling source code failed.') + raise testresult + + # Touch the meson.build file to force a regenerate + def force_regenerate() -> None: + ensure_backend_detects_changes(backend) + os.utime(str(test.path / 'meson.build')) + + # just test building + build_step() + + # test that regeneration works for build step + force_regenerate() + build_step() # TBD: assert nothing gets built after the regenerate? + + # test that regeneration works for test step + force_regenerate() + + # Test in-process + clear_internal_caches() + test_start = time.time() + (returncode, tstdo, tstde, test_log) = run_test_inprocess(test_build_dir) + testresult.add_step(BuildStep.test, tstdo, tstde, test_log, time.time() - test_start) + if should_fail == 'test': + if returncode != 0: + return testresult + testresult.fail('Test that should have failed to run unit tests succeeded.') + return testresult + if returncode != 0: + testresult.fail('Running unit tests failed.') + return testresult + + # Do installation, if the backend supports it + if install_commands: + env = test.env.copy() + env['DESTDIR'] = install_dir + # Install with subprocess + pi, o, e = Popen_safe(install_commands, cwd=test_build_dir, env=env) + testresult.add_step(BuildStep.install, o, e) + if pi.returncode != 0: + testresult.fail('Running install failed.') + return testresult + + # Clean with subprocess + env = test.env.copy() + pi, o, e = Popen_safe(clean_commands + dir_args, cwd=test_build_dir, env=env) + testresult.add_step(BuildStep.clean, o, e) + if pi.returncode != 0: + testresult.fail('Running clean failed.') + return testresult + + # Validate installed files + testresult.add_step(BuildStep.install, '', '') + if not install_commands: + return testresult + install_msg = validate_install(test, Path(install_dir), builddata.environment) + if install_msg: + testresult.fail('\n' + install_msg) + return testresult + + return testresult + + +# processing of test.json 'skip_*' keys, which can appear at top level, or in +# matrix: +def _skip_keys(test_def: T.Dict) -> T.Tuple[bool, bool]: + skip_expected = False + + # Test is expected to skip if MESON_CI_JOBNAME contains any of the list of + # substrings + if ('skip_on_jobname' in test_def) and (ci_jobname is not None): + skip_expected = any(s in ci_jobname for s in test_def['skip_on_jobname']) + + # Test is expected to skip if os matches + if 'skip_on_os' in test_def: + mesonenv = environment.Environment(None, None, get_fake_options('/')) + for skip_os in test_def['skip_on_os']: + if skip_os.startswith('!'): + if mesonenv.machines.host.system != skip_os[1:]: + skip_expected = True + else: + if mesonenv.machines.host.system == skip_os: + skip_expected = True + + # Skip if environment variable is present + skip = False + if 'skip_on_env' in test_def: + for skip_env_var in test_def['skip_on_env']: + if skip_env_var in os.environ: + skip = True + + return (skip, skip_expected) + + +def load_test_json(t: TestDef, stdout_mandatory: bool, skip_category: bool = False) -> T.List[TestDef]: + all_tests: T.List[TestDef] = [] + test_def = {} + test_def_file = t.path / 'test.json' + if test_def_file.is_file(): + test_def = json.loads(test_def_file.read_text(encoding='utf-8')) + + # Handle additional environment variables + env = {} # type: T.Dict[str, str] + if 'env' in test_def: + assert isinstance(test_def['env'], dict) + env = test_def['env'] + for key, val in env.items(): + val = val.replace('@ROOT@', t.path.resolve().as_posix()) + val = val.replace('@PATH@', t.env.get('PATH', '')) + env[key] = val + + # Handle installed files + installed = [] # type: T.List[InstalledFile] + if 'installed' in test_def: + installed = [InstalledFile(x) for x in test_def['installed']] + + # Handle expected output + stdout = test_def.get('stdout', []) + if stdout_mandatory and not stdout: + raise RuntimeError(f"{test_def_file} must contain a non-empty stdout key") + + # Handle the do_not_set_opts list + do_not_set_opts = test_def.get('do_not_set_opts', []) # type: T.List[str] + + (t.skip, t.skip_expected) = _skip_keys(test_def) + + # Skip tests if the tool requirements are not met + if 'tools' in test_def: + assert isinstance(test_def['tools'], dict) + for tool, vers_req in test_def['tools'].items(): + if tool not in tool_vers_map: + t.skip = True + elif not mesonlib.version_compare(tool_vers_map[tool], vers_req): + t.skip = True + + # Skip the matrix code and just update the existing test + if 'matrix' not in test_def: + t.env.update(env) + t.installed_files = installed + t.do_not_set_opts = do_not_set_opts + t.stdout = stdout + return [t] + + new_opt_list: T.List[T.List[T.Tuple[str, str, bool, bool]]] + + # 'matrix; entry is present, so build multiple tests from matrix definition + opt_list = [] # type: T.List[T.List[T.Tuple[str, str, bool, bool]]] + matrix = test_def['matrix'] + assert "options" in matrix + for key, val in matrix["options"].items(): + assert isinstance(val, list) + tmp_opts = [] # type: T.List[T.Tuple[str, str, bool, bool]] + for i in val: + assert isinstance(i, dict) + assert "val" in i + + (skip, skip_expected) = _skip_keys(i) + + # Only run the test if all compiler ID's match + if 'compilers' in i: + for lang, id_list in i['compilers'].items(): + if lang not in compiler_id_map or compiler_id_map[lang] not in id_list: + skip = True + break + + # Add an empty matrix entry + if i['val'] is None: + tmp_opts += [(key, None, skip, skip_expected)] + continue + + tmp_opts += [(key, i['val'], skip, skip_expected)] + + if opt_list: + new_opt_list = [] + for i in opt_list: + for j in tmp_opts: + new_opt_list += [[*i, j]] + opt_list = new_opt_list + else: + opt_list = [[x] for x in tmp_opts] + + # Exclude specific configurations + if 'exclude' in matrix: + assert isinstance(matrix['exclude'], list) + new_opt_list = [] + for i in opt_list: + exclude = False + opt_tuple = [(x[0], x[1]) for x in i] + for j in matrix['exclude']: + ex_list = [(k, v) for k, v in j.items()] + if all([x in opt_tuple for x in ex_list]): + exclude = True + break + + if not exclude: + new_opt_list += [i] + + opt_list = new_opt_list + + for i in opt_list: + name = ' '.join([f'{x[0]}={x[1]}' for x in i if x[1] is not None]) + opts = [f'-D{x[0]}={x[1]}' for x in i if x[1] is not None] + skip = any([x[2] for x in i]) + skip_expected = any([x[3] for x in i]) + test = TestDef(t.path, name, opts, skip or t.skip, skip_category) + test.env.update(env) + test.installed_files = installed + test.do_not_set_opts = do_not_set_opts + test.stdout = stdout + test.skip_expected = skip_expected or t.skip_expected + all_tests.append(test) + + return all_tests + + +def gather_tests(testdir: Path, stdout_mandatory: bool, only: T.List[str], skip_category: bool) -> T.List[TestDef]: + all_tests: T.List[TestDef] = [] + for t in testdir.iterdir(): + # Filter non-tests files (dot files, etc) + if not t.is_dir() or t.name.startswith('.'): + continue + if only and not any(t.name.startswith(prefix) for prefix in only): + continue + test_def = TestDef(t, None, [], skip_category=skip_category) + all_tests.extend(load_test_json(test_def, stdout_mandatory, skip_category)) + return sorted(all_tests) + + +def have_d_compiler() -> bool: + if shutil.which("ldc2"): + return True + elif shutil.which("ldc"): + return True + elif shutil.which("gdc"): + return True + elif shutil.which("dmd"): + # The Windows installer sometimes produces a DMD install + # that exists but segfaults every time the compiler is run. + # Don't know why. Don't know how to fix. Skip in this case. + cp = subprocess.run(['dmd', '--version'], + capture_output=True) + if cp.stdout == b'': + return False + return True + return False + +def have_objc_compiler(use_tmp: bool) -> bool: + with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: + env = environment.Environment(None, build_dir, get_fake_options('/')) + try: + objc_comp = detect_objc_compiler(env, MachineChoice.HOST) + except mesonlib.MesonException: + return False + if not objc_comp: + return False + env.coredata.process_new_compiler('objc', objc_comp, env) + try: + objc_comp.sanity_check(env.get_scratch_dir(), env) + except mesonlib.MesonException: + return False + return True + +def have_objcpp_compiler(use_tmp: bool) -> bool: + with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: + env = environment.Environment(None, build_dir, get_fake_options('/')) + try: + objcpp_comp = detect_objcpp_compiler(env, MachineChoice.HOST) + except mesonlib.MesonException: + return False + if not objcpp_comp: + return False + env.coredata.process_new_compiler('objcpp', objcpp_comp, env) + try: + objcpp_comp.sanity_check(env.get_scratch_dir(), env) + except mesonlib.MesonException: + return False + return True + +def have_java() -> bool: + if shutil.which('javac') and shutil.which('java'): + return True + return False + +def skip_dont_care(t: TestDef) -> bool: + # Everything is optional when not running on CI + if ci_jobname is None: + return True + + # Non-frameworks test are allowed to determine their own skipping under CI (currently) + if not t.category.endswith('frameworks'): + return True + + if mesonlib.is_osx() and '6 gettext' in str(t.path): + return True + + return False + +def skip_csharp(backend: Backend) -> bool: + if backend is not Backend.ninja: + return True + if not shutil.which('resgen'): + return True + if shutil.which('mcs'): + return False + if shutil.which('csc'): + # Only support VS2017 for now. Earlier versions fail + # under CI in mysterious ways. + try: + stdo = subprocess.check_output(['csc', '/version']) + except subprocess.CalledProcessError: + return True + # Having incrementing version numbers would be too easy. + # Microsoft reset the versioning back to 1.0 (from 4.x) + # when they got the Roslyn based compiler. Thus there + # is NO WAY to reliably do version number comparisons. + # Only support the version that ships with VS2017. + return not stdo.startswith(b'2.') + return True + +# In Azure some setups have a broken rustc that will error out +# on all compilation attempts. + +def has_broken_rustc() -> bool: + dirname = Path('brokenrusttest') + if dirname.exists(): + mesonlib.windows_proof_rmtree(dirname.as_posix()) + dirname.mkdir() + sanity_file = dirname / 'sanity.rs' + sanity_file.write_text('fn main() {\n}\n', encoding='utf-8') + pc = subprocess.run(['rustc', '-o', 'sanity.exe', 'sanity.rs'], + cwd=dirname.as_posix(), + stdout = subprocess.DEVNULL, + stderr = subprocess.DEVNULL) + mesonlib.windows_proof_rmtree(dirname.as_posix()) + return pc.returncode != 0 + +def should_skip_rust(backend: Backend) -> bool: + if not shutil.which('rustc'): + return True + if backend is not Backend.ninja: + return True + if mesonlib.is_windows(): + if has_broken_rustc(): + return True + return False + +def should_skip_wayland() -> bool: + if mesonlib.is_windows() or mesonlib.is_osx(): + return True + if not shutil.which('wayland-scanner'): + return True + return False + +def detect_tests_to_run(only: T.Dict[str, T.List[str]], use_tmp: bool) -> T.List[T.Tuple[str, T.List[TestDef], bool]]: + """ + Parameters + ---------- + only: dict of categories and list of test cases, optional + specify names of tests to run + + Returns + ------- + gathered_tests: list of tuple of str, list of TestDef, bool + tests to run + """ + + skip_fortran = not(shutil.which('gfortran') or + shutil.which('flang') or + shutil.which('pgfortran') or + shutil.which('nagfor') or + shutil.which('ifort') or + shutil.which('ifx')) + + skip_cmake = ((os.environ.get('compiler') == 'msvc2015' and under_ci) or + 'cmake' not in tool_vers_map or + not mesonlib.version_compare(tool_vers_map['cmake'], '>=3.14')) + + class TestCategory: + def __init__(self, category: str, subdir: str, skip: bool = False, stdout_mandatory: bool = False): + self.category = category # category name + self.subdir = subdir # subdirectory + self.skip = skip # skip condition + self.stdout_mandatory = stdout_mandatory # expected stdout is mandatory for tests in this category + + all_tests = [ + TestCategory('cmake', 'cmake', skip_cmake), + TestCategory('common', 'common'), + TestCategory('native', 'native'), + TestCategory('warning-meson', 'warning', stdout_mandatory=True), + TestCategory('failing-meson', 'failing', stdout_mandatory=True), + TestCategory('failing-build', 'failing build'), + TestCategory('failing-test', 'failing test'), + TestCategory('keyval', 'keyval'), + TestCategory('platform-osx', 'osx', not mesonlib.is_osx()), + TestCategory('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()), + TestCategory('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()), + TestCategory('java', 'java', backend is not Backend.ninja or not have_java()), + TestCategory('C#', 'csharp', skip_csharp(backend)), + TestCategory('vala', 'vala', backend is not Backend.ninja or not shutil.which(os.environ.get('VALAC', 'valac'))), + TestCategory('cython', 'cython', backend is not Backend.ninja or not shutil.which(os.environ.get('CYTHON', 'cython'))), + TestCategory('rust', 'rust', should_skip_rust(backend)), + TestCategory('d', 'd', backend is not Backend.ninja or not have_d_compiler()), + TestCategory('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler(options.use_tmpdir)), + TestCategory('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler(options.use_tmpdir)), + TestCategory('fortran', 'fortran', skip_fortran or backend != Backend.ninja), + TestCategory('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), + # CUDA tests on Windows: use Ninja backend: python run_project_tests.py --only cuda --backend ninja + TestCategory('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')), + TestCategory('python3', 'python3', backend is not Backend.ninja or 'python3' not in sys.executable), + TestCategory('python', 'python'), + TestCategory('fpga', 'fpga', shutil.which('yosys') is None), + TestCategory('frameworks', 'frameworks'), + TestCategory('nasm', 'nasm'), + TestCategory('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja), + TestCategory('wayland', 'wayland', should_skip_wayland()), + ] + + categories = [t.category for t in all_tests] + assert categories == ALL_TESTS, 'argparse("--only", choices=ALL_TESTS) need to be updated to match all_tests categories' + + if only: + for key in only.keys(): + assert key in categories, f'key `{key}` is not a recognized category' + all_tests = [t for t in all_tests if t.category in only.keys()] + + gathered_tests = [(t.category, gather_tests(Path('test cases', t.subdir), t.stdout_mandatory, only[t.category], t.skip), t.skip) for t in all_tests] + return gathered_tests + +def run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]], + log_name_base: str, + failfast: bool, + extra_args: T.List[str], + use_tmp: bool, + num_workers: int) -> T.Tuple[int, int, int]: + txtname = log_name_base + '.txt' + with open(txtname, 'w', encoding='utf-8', errors='ignore') as lf: + return _run_tests(all_tests, log_name_base, failfast, extra_args, use_tmp, num_workers, lf) + +class TestStatus(Enum): + OK = normal_green(' [SUCCESS] ') + SKIP = yellow(' [SKIPPED] ') + ERROR = red(' [ERROR] ') + UNEXSKIP = red('[UNEXSKIP] ') + UNEXRUN = red(' [UNEXRUN] ') + CANCELED = cyan('[CANCELED] ') + RUNNING = blue(' [RUNNING] ') # Should never be actually printed + LOG = bold(' [LOG] ') # Should never be actually printed + +def default_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: + print(*args, sep=sep) + +safe_print = default_print + +class TestRunFuture: + def __init__(self, name: str, testdef: TestDef, future: T.Optional['Future[T.Optional[TestResult]]']) -> None: + super().__init__() + self.name = name + self.testdef = testdef + self.future = future + self.status = TestStatus.RUNNING if self.future is not None else TestStatus.SKIP + + @property + def result(self) -> T.Optional[TestResult]: + return self.future.result() if self.future else None + + def log(self) -> None: + without_install = '' if install_commands else '(without install)' + safe_print(self.status.value, without_install, *self.testdef.display_name()) + + def update_log(self, new_status: TestStatus) -> None: + self.status = new_status + self.log() + + def cancel(self) -> None: + if self.future is not None and self.future.cancel(): + self.status = TestStatus.CANCELED + +class LogRunFuture: + def __init__(self, msgs: mlog.TV_LoggableList) -> None: + self.msgs = msgs + self.status = TestStatus.LOG + + def log(self) -> None: + safe_print(*self.msgs, sep='') + + def cancel(self) -> None: + pass + +RunFutureUnion = T.Union[TestRunFuture, LogRunFuture] + +def test_emits_skip_msg(line: str) -> bool: + for prefix in {'Problem encountered', 'Assert failed', 'Failed to configure the CMake subproject'}: + if f'{prefix}: MESON_SKIP_TEST' in line: + return True + return False + +def _run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]], + log_name_base: str, + failfast: bool, + extra_args: T.List[str], + use_tmp: bool, + num_workers: int, + logfile: T.TextIO) -> T.Tuple[int, int, int]: + global stop, host_c_compiler + xmlname = log_name_base + '.xml' + junit_root = ET.Element('testsuites') + conf_time: float = 0 + build_time: float = 0 + test_time: float = 0 + passing_tests = 0 + failing_tests = 0 + skipped_tests = 0 + + print(f'\nRunning tests with {num_workers} workers') + + # Pack the global state + state = GlobalState(compile_commands, clean_commands, test_commands, install_commands, uninstall_commands, backend, backend_flags, host_c_compiler) + executor = ProcessPoolExecutor(max_workers=num_workers) + + futures: T.List[RunFutureUnion] = [] + + # First, collect and start all tests and also queue log messages + for name, test_cases, skipped in all_tests: + current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))}) + if skipped: + futures += [LogRunFuture(['\n', bold(f'Not running {name} tests.'), '\n'])] + else: + futures += [LogRunFuture(['\n', bold(f'Running {name} tests.'), '\n'])] + + for t in test_cases: + # Jenkins screws us over by automatically sorting test cases by name + # and getting it wrong by not doing logical number sorting. + (testnum, testbase) = t.path.name.split(' ', 1) + testname = '%.3d %s' % (int(testnum), testbase) + if t.name: + testname += f' ({t.name})' + should_fail = '' + suite_args = [] + if name.startswith('failing'): + should_fail = name.split('failing-')[1] + if name.startswith('warning'): + suite_args = ['--fatal-meson-warnings'] + should_fail = name.split('warning-')[1] + + if skipped or t.skip: + futures += [TestRunFuture(testname, t, None)] + continue + result_future = executor.submit(run_test, t, extra_args + suite_args + t.args, should_fail, use_tmp, state=state) + futures += [TestRunFuture(testname, t, result_future)] + + # Ensure we only cancel once + tests_canceled = False + + # Optionally enable the tqdm progress bar, but only if there is at least + # one LogRunFuture and one TestRunFuture + global safe_print + futures_iter: T.Iterable[RunFutureUnion] = futures + if len(futures) > 2 and sys.stdout.isatty(): + try: + from tqdm import tqdm + futures_iter = tqdm(futures, desc='Running tests', unit='test') + + def tqdm_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: + tqdm.write(sep.join([str(x) for x in args])) + + safe_print = tqdm_print + except ImportError: + pass + + # Wait and handle the test results and print the stored log output + for f in futures_iter: + # Just a log entry to print something to stdout + sys.stdout.flush() + if isinstance(f, LogRunFuture): + f.log() + continue + + # Actual Test run + testname = f.name + t = f.testdef + try: + result = f.result + except (CancelledError, KeyboardInterrupt): + f.status = TestStatus.CANCELED + + if stop and not tests_canceled: + num_running = sum(1 if f2.status is TestStatus.RUNNING else 0 for f2 in futures) + for f2 in futures: + f2.cancel() + executor.shutdown() + num_canceled = sum(1 if f2.status is TestStatus.CANCELED else 0 for f2 in futures) + safe_print(f'\nCanceled {num_canceled} out of {num_running} running tests.') + safe_print(f'Finishing the remaining {num_running - num_canceled} tests.\n') + tests_canceled = True + + # Handle canceled tests + if f.status is TestStatus.CANCELED: + f.log() + continue + + # Handle skipped tests + if result is None: + # skipped due to skipped category skip or 'tools:' or 'skip_on_env:' + is_skipped = True + skip_reason = 'not run because preconditions were not met' + skip_as_expected = True + else: + # skipped due to test outputting 'MESON_SKIP_TEST' + for l in result.stdo.splitlines(): + if test_emits_skip_msg(l): + is_skipped = True + offset = l.index('MESON_SKIP_TEST') + 16 + skip_reason = l[offset:].strip() + break + else: + is_skipped = False + skip_reason = '' + if not skip_dont_care(t): + skip_as_expected = (is_skipped == t.skip_expected) + else: + skip_as_expected = True + + if is_skipped: + skipped_tests += 1 + + if is_skipped and skip_as_expected: + f.update_log(TestStatus.SKIP) + if not t.skip_category: + safe_print(bold('Reason:'), skip_reason) + current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, 'classname': t.category}) + ET.SubElement(current_test, 'skipped', {}) + continue + + if not skip_as_expected: + failing_tests += 1 + if is_skipped: + skip_msg = f'Test asked to be skipped ({skip_reason}), but was not expected to' + status = TestStatus.UNEXSKIP + else: + skip_msg = 'Test ran, but was expected to be skipped' + status = TestStatus.UNEXRUN + result.msg = f"{skip_msg} for MESON_CI_JOBNAME '{ci_jobname}'" + + f.update_log(status) + safe_print(bold('Reason:'), result.msg) + current_test = ET.SubElement(current_suite, 'testcase', {'name': testname, 'classname': t.category}) + ET.SubElement(current_test, 'failure', {'message': result.msg}) + continue + + # Handle Failed tests + if result.msg != '': + f.update_log(TestStatus.ERROR) + safe_print(bold('During:'), result.step.name) + safe_print(bold('Reason:'), result.msg) + failing_tests += 1 + # Append a visual separator for the different test cases + cols = shutil.get_terminal_size((100, 20)).columns + name_str = ' '.join([str(x) for x in f.testdef.display_name()]) + name_len = len(re.sub(r'\x1B[^m]+m', '', name_str)) # Do not count escape sequences + left_w = (cols // 2) - (name_len // 2) - 1 + left_w = max(3, left_w) + right_w = cols - left_w - name_len - 2 + right_w = max(3, right_w) + failing_testcases.append(name_str) + failing_logs.append(f'\n\x1b[31m{"="*left_w}\x1b[0m {name_str} \x1b[31m{"="*right_w}\x1b[0m\n') + _during = bold('Failed during:') + _reason = bold('Reason:') + failing_logs.append(f'{_during} {result.step.name}\n{_reason} {result.msg}\n') + if result.step == BuildStep.configure and result.mlog != no_meson_log_msg: + # For configure failures, instead of printing stdout, + # print the meson log if available since it's a superset + # of stdout and often has very useful information. + failing_logs.append(result.mlog) + elif under_ci: + # Always print the complete meson log when running in + # a CI. This helps debugging issues that only occur in + # a hard to reproduce environment + failing_logs.append(result.mlog) + failing_logs.append(result.stdo) + else: + failing_logs.append(result.stdo) + for cmd_res in result.cicmds: + failing_logs.append(cmd_res) + failing_logs.append(result.stde) + if failfast: + safe_print("Cancelling the rest of the tests") + for f2 in futures: + f2.cancel() + else: + f.update_log(TestStatus.OK) + passing_tests += 1 + conf_time += result.conftime + build_time += result.buildtime + test_time += result.testtime + total_time = conf_time + build_time + test_time + log_text_file(logfile, t.path, result) + current_test = ET.SubElement( + current_suite, + 'testcase', + {'name': testname, 'classname': t.category, 'time': '%.3f' % total_time} + ) + if result.msg != '': + ET.SubElement(current_test, 'failure', {'message': result.msg}) + stdoel = ET.SubElement(current_test, 'system-out') + stdoel.text = result.stdo + stdeel = ET.SubElement(current_test, 'system-err') + stdeel.text = result.stde + + # Reset, just in case + safe_print = default_print + + print() + print("Total configuration time: %.2fs" % conf_time) + print("Total build time: %.2fs" % build_time) + print("Total test time: %.2fs" % test_time) + ET.ElementTree(element=junit_root).write(xmlname, xml_declaration=True, encoding='UTF-8') + return passing_tests, failing_tests, skipped_tests + +def check_meson_commands_work(use_tmpdir: bool, extra_args: T.List[str]) -> None: + global backend, compile_commands, test_commands, install_commands + testdir = PurePath('test cases', 'common', '1 trivial').as_posix() + meson_commands = mesonlib.python_command + [get_meson_script()] + with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmpdir else '.') as build_dir: + print('Checking that configuring works...') + gen_cmd = meson_commands + ['setup' , testdir, build_dir] + backend_flags + extra_args + pc, o, e = Popen_safe(gen_cmd) + if pc.returncode != 0: + raise RuntimeError(f'Failed to configure {testdir!r}:\n{e}\n{o}') + print('Checking that introspect works...') + pc, o, e = Popen_safe(meson_commands + ['introspect', '--targets'], cwd=build_dir) + json.loads(o) + if pc.returncode != 0: + raise RuntimeError(f'Failed to introspect --targets {testdir!r}:\n{e}\n{o}') + print('Checking that building works...') + dir_args = get_backend_args_for_dir(backend, build_dir) + pc, o, e = Popen_safe(compile_commands + dir_args, cwd=build_dir) + if pc.returncode != 0: + raise RuntimeError(f'Failed to build {testdir!r}:\n{e}\n{o}') + print('Checking that testing works...') + pc, o, e = Popen_safe(test_commands, cwd=build_dir) + if pc.returncode != 0: + raise RuntimeError(f'Failed to test {testdir!r}:\n{e}\n{o}') + if install_commands: + print('Checking that installing works...') + pc, o, e = Popen_safe(install_commands, cwd=build_dir) + if pc.returncode != 0: + raise RuntimeError(f'Failed to install {testdir!r}:\n{e}\n{o}') + + +def detect_system_compiler(options: 'CompilerArgumentType') -> None: + global host_c_compiler, compiler_id_map + + fake_opts = get_fake_options('/') + if options.cross_file: + fake_opts.cross_file = [options.cross_file] + if options.native_file: + fake_opts.native_file = [options.native_file] + + env = environment.Environment(None, None, fake_opts) + + print_compilers(env, MachineChoice.HOST) + if options.cross_file: + print_compilers(env, MachineChoice.BUILD) + + for lang in sorted(compilers.all_languages): + try: + comp = compiler_from_language(env, lang, MachineChoice.HOST) + # note compiler id for later use with test.json matrix + compiler_id_map[lang] = comp.get_id() + except mesonlib.MesonException: + comp = None + + # note C compiler for later use by platform_fix_name() + if lang == 'c': + if comp: + host_c_compiler = comp.get_id() + else: + raise RuntimeError("Could not find C compiler.") + + +def print_compilers(env: 'Environment', machine: MachineChoice) -> None: + print() + print(f'{machine.get_lower_case_name()} machine compilers') + print() + for lang in sorted(compilers.all_languages): + try: + comp = compiler_from_language(env, lang, machine) + details = '{:<10} {} {}'.format('[' + comp.get_id() + ']', ' '.join(comp.get_exelist()), comp.get_version_string()) + except mesonlib.MesonException: + details = '[not found]' + print(f'{lang:<7}: {details}') + +class ToolInfo(T.NamedTuple): + tool: str + args: T.List[str] + regex: T.Pattern + match_group: int + +def print_tool_versions() -> None: + tools: T.List[ToolInfo] = [ + ToolInfo( + 'ninja', + ['--version'], + re.compile(r'^([0-9]+(\.[0-9]+)*(-[a-z0-9]+)?)$'), + 1, + ), + ToolInfo( + 'cmake', + ['--version'], + re.compile(r'^cmake version ([0-9]+(\.[0-9]+)*(-[a-z0-9]+)?)$'), + 1, + ), + ToolInfo( + 'hotdoc', + ['--version'], + re.compile(r'^([0-9]+(\.[0-9]+)*(-[a-z0-9]+)?)$'), + 1, + ), + ] + + def get_version(t: ToolInfo) -> str: + exe = shutil.which(t.tool) + if not exe: + return 'not found' + + args = [t.tool] + t.args + pc, o, e = Popen_safe(args) + if pc.returncode != 0: + return f'{exe} (invalid {t.tool} executable)' + for i in o.split('\n'): + i = i.strip('\n\r\t ') + m = t.regex.match(i) + if m is not None: + tool_vers_map[t.tool] = m.group(t.match_group) + return '{} ({})'.format(exe, m.group(t.match_group)) + + return f'{exe} (unknown)' + + print() + print('tools') + print() + + max_width = max([len(x.tool) for x in tools] + [7]) + for tool in tools: + print('{0:<{2}}: {1}'.format(tool.tool, get_version(tool), max_width)) + print() + +def clear_transitive_files() -> None: + a = Path('test cases/common') + for d in a.glob('*subproject subdir/subprojects/subsubsub*'): + if d.is_dir(): + mesonlib.windows_proof_rmtree(str(d)) + else: + mesonlib.windows_proof_rm(str(d)) + +if __name__ == '__main__': + if under_ci and not raw_ci_jobname: + raise SystemExit('Running under CI but $MESON_CI_JOBNAME is not set (set to "thirdparty" if you are running outside of the github org)') + + setup_vsenv() + + try: + # This fails in some CI environments for unknown reasons. + num_workers = multiprocessing.cpu_count() + except Exception as e: + print('Could not determine number of CPUs due to the following reason:', str(e)) + print('Defaulting to using only two processes') + num_workers = 2 + + if num_workers > 64: + # Too much parallelism seems to trigger a potential Python bug: + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1004107 + num_workers = 64 + + parser = argparse.ArgumentParser(description="Run the test suite of Meson.") + parser.add_argument('extra_args', nargs='*', + help='arguments that are passed directly to Meson (remember to have -- before these).') + parser.add_argument('--backend', dest='backend', choices=backendlist) + parser.add_argument('-j', dest='num_workers', type=int, default=num_workers, + help=f'Maximum number of parallel tests (default {num_workers})') + parser.add_argument('--failfast', action='store_true', + help='Stop running if test case fails') + parser.add_argument('--no-unittests', action='store_true', + help='Not used, only here to simplify run_tests.py') + parser.add_argument('--only', default=[], + help='name of test(s) to run, in format "category[/name]" where category is one of: ' + ', '.join(ALL_TESTS), nargs='+') + parser.add_argument('--cross-file', action='store', help='File describing cross compilation environment.') + parser.add_argument('--native-file', action='store', help='File describing native compilation environment.') + parser.add_argument('--use-tmpdir', action='store_true', help='Use tmp directory for temporary files.') + options = T.cast('ArgumentType', parser.parse_args()) + + if options.cross_file: + options.extra_args += ['--cross-file', options.cross_file] + if options.native_file: + options.extra_args += ['--native-file', options.native_file] + + clear_transitive_files() + + print('Meson build system', meson_version, 'Project Tests') + print('Using python', sys.version.split('\n')[0], f'({sys.executable!r})') + if 'VSCMD_VER' in os.environ: + print('VSCMD version', os.environ['VSCMD_VER']) + setup_commands(options.backend) + detect_system_compiler(options) + print_tool_versions() + script_dir = os.path.split(__file__)[0] + if script_dir != '': + os.chdir(script_dir) + check_meson_commands_work(options.use_tmpdir, options.extra_args) + only = collections.defaultdict(list) + for i in options.only: + try: + cat, case = i.split('/') + only[cat].append(case) + except ValueError: + only[i].append('') + try: + all_tests = detect_tests_to_run(only, options.use_tmpdir) + res = run_tests(all_tests, 'meson-test-run', options.failfast, options.extra_args, options.use_tmpdir, options.num_workers) + (passing_tests, failing_tests, skipped_tests) = res + except StopException: + pass + if failing_tests > 0: + print('\nMesonlogs of failing tests\n') + for l in failing_logs: + try: + print(l, '\n') + except UnicodeError: + print(l.encode('ascii', errors='replace').decode(), '\n') + print() + print('Total passed tests: ', green(str(passing_tests))) + print('Total failed tests: ', red(str(failing_tests))) + print('Total skipped tests:', yellow(str(skipped_tests))) + if failing_tests > 0: + print('\nAll failures:') + for c in failing_testcases: + print(f' -> {c}') + for name, dirs, _ in all_tests: + dir_names = list({x.path.name for x in dirs}) + for k, g in itertools.groupby(dir_names, key=lambda x: x.split()[0]): + tests = list(g) + if len(tests) != 1: + print('WARNING: The {} suite contains duplicate "{}" tests: "{}"'.format(name, k, '", "'.join(tests))) + clear_transitive_files() + raise SystemExit(failing_tests) diff --git a/devtools/meson/run_tests.py b/devtools/meson/run_tests.py new file mode 100644 index 0000000..66341e4 --- /dev/null +++ b/devtools/meson/run_tests.py @@ -0,0 +1,423 @@ +#!/usr/bin/env python3 + +# Copyright 2012-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Work around some pathlib bugs... +from mesonbuild import _pathlib +import sys +sys.modules['pathlib'] = _pathlib + +import collections +import os +import time +import shutil +import subprocess +import platform +import argparse +import traceback +from io import StringIO +from enum import Enum +from glob import glob +from pathlib import Path +from unittest import mock +import typing as T + +from mesonbuild.compilers.c import CCompiler +from mesonbuild.compilers.detect import detect_c_compiler +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +from mesonbuild import mesonlib +from mesonbuild import mesonmain +from mesonbuild import mtest +from mesonbuild import mlog +from mesonbuild.environment import Environment, detect_ninja, detect_machine_info +from mesonbuild.coredata import backendlist, version as meson_version +from mesonbuild.mesonlib import OptionKey, setup_vsenv + +NINJA_1_9_OR_NEWER = False +NINJA_CMD = None +# If we're on CI, detecting ninja for every subprocess unit test that we run is slow +# Optimize this by respecting $NINJA and skipping detection, then exporting it on +# first run. +try: + NINJA_1_9_OR_NEWER = bool(int(os.environ['NINJA_1_9_OR_NEWER'])) + NINJA_CMD = [os.environ['NINJA']] +except (KeyError, ValueError): + # Look for 1.9 to see if https://github.com/ninja-build/ninja/issues/1219 + # is fixed + NINJA_CMD = detect_ninja('1.9') + if NINJA_CMD is not None: + NINJA_1_9_OR_NEWER = True + else: + mlog.warning('Found ninja <1.9, tests will run slower', once=True) + NINJA_CMD = detect_ninja() + +if NINJA_CMD is not None: + os.environ['NINJA_1_9_OR_NEWER'] = str(int(NINJA_1_9_OR_NEWER)) + os.environ['NINJA'] = NINJA_CMD[0] +else: + raise RuntimeError('Could not find Ninja v1.7 or newer') + +# Emulate running meson with -X utf8 by making sure all open() calls have a +# sane encoding. This should be a python default, but PEP 540 considered it not +# backwards compatible. Instead, much line noise in diffs to update this, and in +# python 3.10 we can also make it a warning when absent. +os.environ['PYTHONWARNDEFAULTENCODING'] = '1' +# work around https://bugs.python.org/issue34624 +os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] = '1' +# python 3.11 adds a warning that in 3.15, UTF-8 mode will be default. +# This is fantastic news, we'd love that. Less fantastic: this warning is silly, +# we *want* these checks to be affected. Plus, the recommended alternative API +# would (in addition to warning people when UTF-8 mode removed the problem) also +# require using a minimum python version of 3.11 (in which the warning was added) +# or add verbose if/else soup. +if sys.version_info >= (3, 10): + import warnings + warnings.filterwarnings('ignore', message="UTF-8 Mode affects .*getpreferredencoding", category=EncodingWarning) + +def guess_backend(backend_str: str, msbuild_exe: str) -> T.Tuple['Backend', T.List[str]]: + # Auto-detect backend if unspecified + backend_flags = [] + if backend_str is None: + if msbuild_exe is not None and (mesonlib.is_windows() and not _using_intelcl()): + backend_str = 'vs' # Meson will auto-detect VS version to use + else: + backend_str = 'ninja' + + # Set backend arguments for Meson + if backend_str.startswith('vs'): + backend_flags = ['--backend=' + backend_str] + backend = Backend.vs + elif backend_str == 'xcode': + backend_flags = ['--backend=xcode'] + backend = Backend.xcode + elif backend_str == 'ninja': + backend_flags = ['--backend=ninja'] + backend = Backend.ninja + else: + raise RuntimeError(f'Unknown backend: {backend_str!r}') + return (backend, backend_flags) + + +def _using_intelcl() -> bool: + """ + detect if intending to using Intel-Cl compilers (Intel compilers on Windows) + Sufficient evidence of intent is that user is working in the Intel compiler + shell environment, otherwise this function returns False + """ + if not mesonlib.is_windows(): + return False + # handle where user tried to "blank" MKLROOT and left space(s) + if not os.environ.get('MKLROOT', '').strip(): + return False + if (os.environ.get('CC') == 'icl' or + os.environ.get('CXX') == 'icl' or + os.environ.get('FC') == 'ifort'): + return True + # Intel-Cl users might not have the CC,CXX,FC envvars set, + # but because they're in Intel shell, the exe's below are on PATH + if shutil.which('icl') or shutil.which('ifort'): + return True + mlog.warning('It appears you might be intending to use Intel compiler on Windows ' + 'since non-empty environment variable MKLROOT is set to {} ' + 'However, Meson cannot find the Intel WIndows compiler executables (icl,ifort).' + 'Please try using the Intel shell.'.format(os.environ.get('MKLROOT'))) + return False + + +# Fake classes and objects for mocking +class FakeBuild: + def __init__(self, env): + self.environment = env + +class FakeCompilerOptions: + def __init__(self): + self.value = [] + +# TODO: use a typing.Protocol here +def get_fake_options(prefix: str = '') -> argparse.Namespace: + opts = argparse.Namespace() + opts.native_file = [] + opts.cross_file = None + opts.wrap_mode = None + opts.prefix = prefix + opts.cmd_line_options = {} + return opts + +def get_fake_env(sdir='', bdir=None, prefix='', opts=None): + if opts is None: + opts = get_fake_options(prefix) + env = Environment(sdir, bdir, opts) + env.coredata.options[OptionKey('args', lang='c')] = FakeCompilerOptions() + env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library + return env + +def get_convincing_fake_env_and_cc(bdir, prefix): + ''' + Return a fake env and C compiler with the fake env + machine info properly detected using that compiler. + Useful for running compiler checks in the unit tests. + ''' + env = get_fake_env('', bdir, prefix) + cc = detect_c_compiler(env, mesonlib.MachineChoice.HOST) + # Detect machine info + env.machines.host = detect_machine_info({'c':cc}) + return (env, cc) + +Backend = Enum('Backend', 'ninja vs xcode') + +if 'MESON_EXE' in os.environ: + meson_exe = mesonlib.split_args(os.environ['MESON_EXE']) +else: + meson_exe = None + +if mesonlib.is_windows() or mesonlib.is_cygwin(): + exe_suffix = '.exe' +else: + exe_suffix = '' + +def get_meson_script() -> str: + ''' + Guess the meson that corresponds to the `mesonbuild` that has been imported + so we can run configure and other commands in-process, since mesonmain.run + needs to know the meson_command to use. + + Also used by run_unittests.py to determine what meson to run when not + running in-process (which is the default). + ''' + # Is there a meson.py next to the mesonbuild currently in use? + mesonbuild_dir = Path(mesonmain.__file__).resolve().parent.parent + meson_script = mesonbuild_dir / 'meson.py' + if meson_script.is_file(): + return str(meson_script) + # Then if mesonbuild is in PYTHONPATH, meson must be in PATH + mlog.warning('Could not find meson.py next to the mesonbuild module. ' + 'Trying system meson...') + meson_cmd = shutil.which('meson') + if meson_cmd: + return meson_cmd + raise RuntimeError(f'Could not find {meson_script!r} or a meson in PATH') + +def get_backend_args_for_dir(backend: Backend, builddir: str) -> T.List[str]: + ''' + Visual Studio backend needs to be given the solution to build + ''' + if backend is Backend.vs: + sln_name = glob(os.path.join(builddir, '*.sln'))[0] + return [os.path.split(sln_name)[-1]] + return [] + +def find_vcxproj_with_target(builddir, target): + import re, fnmatch + t, ext = os.path.splitext(target) + if ext: + p = fr'{t}\s*\{ext}' + else: + p = fr'{t}' + for _, _, files in os.walk(builddir): + for f in fnmatch.filter(files, '*.vcxproj'): + f = os.path.join(builddir, f) + with open(f, encoding='utf-8') as o: + if re.search(p, o.read(), flags=re.MULTILINE): + return f + raise RuntimeError(f'No vcxproj matching {p!r} in {builddir!r}') + +def get_builddir_target_args(backend: Backend, builddir, target): + dir_args = [] + if not target: + dir_args = get_backend_args_for_dir(backend, builddir) + if target is None: + return dir_args + if backend is Backend.vs: + vcxproj = find_vcxproj_with_target(builddir, target) + target_args = [vcxproj] + elif backend is Backend.xcode: + target_args = ['-target', target] + elif backend is Backend.ninja: + target_args = [target] + else: + raise AssertionError(f'Unknown backend: {backend!r}') + return target_args + dir_args + +def get_backend_commands(backend: Backend, debug: bool = False) -> \ + T.Tuple[T.List[str], T.List[str], T.List[str], T.List[str], T.List[str]]: + install_cmd: T.List[str] = [] + uninstall_cmd: T.List[str] = [] + clean_cmd: T.List[str] + cmd: T.List[str] + test_cmd: T.List[str] + if backend is Backend.vs: + cmd = ['msbuild'] + clean_cmd = cmd + ['/target:Clean'] + test_cmd = cmd + ['RUN_TESTS.vcxproj'] + elif backend is Backend.xcode: + cmd = ['xcodebuild'] + clean_cmd = cmd + ['-alltargets', 'clean'] + test_cmd = cmd + ['-target', 'RUN_TESTS'] + elif backend is Backend.ninja: + global NINJA_CMD + cmd = NINJA_CMD + ['-w', 'dupbuild=err', '-d', 'explain'] + if debug: + cmd += ['-v'] + clean_cmd = cmd + ['clean'] + test_cmd = cmd + ['test', 'benchmark'] + install_cmd = cmd + ['install'] + uninstall_cmd = cmd + ['uninstall'] + else: + raise AssertionError(f'Unknown backend: {backend!r}') + return cmd, clean_cmd, test_cmd, install_cmd, uninstall_cmd + +def ensure_backend_detects_changes(backend: Backend) -> None: + global NINJA_1_9_OR_NEWER + if backend is not Backend.ninja: + return + need_workaround = False + # We're using ninja >= 1.9 which has QuLogic's patch for sub-1s resolution + # timestamps + if not NINJA_1_9_OR_NEWER: + mlog.warning('Don\'t have ninja >= 1.9, enabling timestamp resolution workaround', once=True) + need_workaround = True + # Increase the difference between build.ninja's timestamp and the timestamp + # of whatever you changed: https://github.com/ninja-build/ninja/issues/371 + if need_workaround: + time.sleep(1) + +def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]: + out = StringIO() + with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out): + returncode = mtest.run_with_args(commandlist) + return returncode, out.getvalue() + +def clear_meson_configure_class_caches() -> None: + CCompiler.find_library_cache = {} + CCompiler.find_framework_cache = {} + PkgConfigDependency.pkgbin_cache = {} + PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None) + mesonlib.project_meson_versions = collections.defaultdict(str) + +def run_configure_inprocess(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]: + stderr = StringIO() + stdout = StringIO() + returncode = 0 + with mock.patch.dict(os.environ, env or {}), mock.patch.object(sys, 'stdout', stdout), mock.patch.object(sys, 'stderr', stderr): + try: + returncode = mesonmain.run(commandlist, get_meson_script()) + except Exception: + if catch_exception: + returncode = 1 + traceback.print_exc() + else: + raise + finally: + clear_meson_configure_class_caches() + return returncode, stdout.getvalue(), stderr.getvalue() + +def run_configure_external(full_command: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]: + pc, o, e = mesonlib.Popen_safe(full_command, env=env) + return pc.returncode, o, e + +def run_configure(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[bool, T.Tuple[int, str, str]]: + global meson_exe + if meson_exe: + return (False, run_configure_external(meson_exe + commandlist, env=env)) + return (True, run_configure_inprocess(commandlist, env=env, catch_exception=catch_exception)) + +def print_system_info(): + print(mlog.bold('System information.')) + print('Architecture:', platform.architecture()) + print('Machine:', platform.machine()) + print('Platform:', platform.system()) + print('Processor:', platform.processor()) + print('System:', platform.system()) + print('') + print(flush=True) + +def subprocess_call(cmd, **kwargs): + print(f'$ {mesonlib.join_args(cmd)}') + return subprocess.call(cmd, **kwargs) + +def main(): + print_system_info() + parser = argparse.ArgumentParser() + parser.add_argument('--backend', default=None, dest='backend', + choices=backendlist) + parser.add_argument('--cross', default=[], dest='cross', action='append') + parser.add_argument('--cross-only', action='store_true') + parser.add_argument('--failfast', action='store_true') + parser.add_argument('--no-unittests', action='store_true', default=False) + (options, _) = parser.parse_known_args() + returncode = 0 + _, backend_flags = guess_backend(options.backend, shutil.which('msbuild')) + no_unittests = options.no_unittests + # Running on a developer machine? Be nice! + if not mesonlib.is_windows() and not mesonlib.is_haiku() and 'CI' not in os.environ: + os.nice(20) + # Appveyor sets the `platform` environment variable which completely messes + # up building with the vs2010 and vs2015 backends. + # + # Specifically, MSBuild reads the `platform` environment variable to set + # the configured value for the platform (Win32/x64/arm), which breaks x86 + # builds. + # + # Appveyor setting this also breaks our 'native build arch' detection for + # Windows in environment.py:detect_windows_arch() by overwriting the value + # of `platform` set by vcvarsall.bat. + # + # While building for x86, `platform` should be unset. + if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': + os.environ.pop('platform') + # Run tests + # Can't pass arguments to unit tests, so set the backend to use in the environment + env = os.environ.copy() + if not options.cross: + cmd = mesonlib.python_command + ['run_meson_command_tests.py', '-v'] + if options.failfast: + cmd += ['--failfast'] + returncode += subprocess_call(cmd, env=env) + if options.failfast and returncode != 0: + return returncode + if no_unittests: + print('Skipping all unit tests.') + print(flush=True) + returncode = 0 + else: + print(mlog.bold('Running unittests.')) + print(flush=True) + cmd = mesonlib.python_command + ['run_unittests.py', '-v'] + backend_flags + if options.failfast: + cmd += ['--failfast'] + returncode += subprocess_call(cmd, env=env) + if options.failfast and returncode != 0: + return returncode + cmd = mesonlib.python_command + ['run_project_tests.py'] + sys.argv[1:] + returncode += subprocess_call(cmd, env=env) + else: + cross_test_args = mesonlib.python_command + ['run_cross_test.py'] + for cf in options.cross: + print(mlog.bold(f'Running {cf} cross tests.')) + print(flush=True) + cmd = cross_test_args + ['cross/' + cf] + if options.failfast: + cmd += ['--failfast'] + if options.cross_only: + cmd += ['--cross-only'] + returncode += subprocess_call(cmd, env=env) + if options.failfast and returncode != 0: + return returncode + return returncode + +if __name__ == '__main__': + setup_vsenv() + print('Meson build system', meson_version, 'Project and Unit Tests') + raise SystemExit(main()) diff --git a/devtools/meson/run_unittests.py b/devtools/meson/run_unittests.py new file mode 100644 index 0000000..7a2502a --- /dev/null +++ b/devtools/meson/run_unittests.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Work around some pathlib bugs... +from mesonbuild import _pathlib +import sys +sys.modules['pathlib'] = _pathlib + +import time +import subprocess +import os +import unittest + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.compilers +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import python_command, setup_vsenv +import mesonbuild.modules.pkgconfig + +from unittests.allplatformstests import AllPlatformTests +from unittests.cargotests import CargoVersionTest, CargoCfgTest +from unittests.darwintests import DarwinTests +from unittests.failuretests import FailureTests +from unittests.linuxcrosstests import LinuxCrossArmTests, LinuxCrossMingwTests +from unittests.machinefiletests import NativeFileTests, CrossFileTests +from unittests.rewritetests import RewriterTests +from unittests.taptests import TAPParserTests +from unittests.datatests import DataTests +from unittests.internaltests import InternalTests +from unittests.linuxliketests import LinuxlikeTests +from unittests.pythontests import PythonTests +from unittests.subprojectscommandtests import SubprojectsCommandTests +from unittests.windowstests import WindowsTests +from unittests.platformagnostictests import PlatformAgnosticTests + +def unset_envs(): + # For unit tests we must fully control all command lines + # so that there are no unexpected changes coming from the + # environment, for example when doing a package build. + varnames = ['CPPFLAGS', 'LDFLAGS'] + list(mesonbuild.compilers.compilers.CFLAGS_MAPPING.values()) + for v in varnames: + if v in os.environ: + del os.environ[v] + +def convert_args(argv): + # If we got passed a list of tests, pass it on + pytest_args = ['-v'] if '-v' in argv else [] + test_list = [] + for arg in argv: + if arg.startswith('-'): + if arg in ('-f', '--failfast'): + arg = '--exitfirst' + pytest_args.append(arg) + continue + # ClassName.test_name => 'ClassName and test_name' + if '.' in arg: + arg = ' and '.join(arg.split('.')) + test_list.append(arg) + if test_list: + pytest_args += ['-k', ' or '.join(test_list)] + return pytest_args + +def running_single_tests(argv, cases): + ''' + Check whether we only got arguments for running individual tests, not + entire testcases, and not all testcases (no test args). + ''' + got_test_arg = False + for arg in argv: + if arg.startswith('-'): + continue + for case in cases: + if not arg.startswith(case): + continue + if '.' not in arg: + # Got a testcase, done + return False + got_test_arg = True + return got_test_arg + +def setup_backend(): + filtered = [] + be = 'ninja' + for a in sys.argv: + if a.startswith('--backend'): + be = a.split('=')[1] + else: + filtered.append(a) + # Since we invoke the tests via unittest or xtest test runner + # we need to pass the backend to use to the spawned process via + # this side channel. Yes it sucks, but at least is is fully + # internal to this file. + os.environ['MESON_UNIT_TEST_BACKEND'] = be + sys.argv = filtered + +def main(): + unset_envs() + setup_backend() + cases = ['InternalTests', 'DataTests', 'AllPlatformTests', 'FailureTests', + 'PythonTests', 'NativeFileTests', 'RewriterTests', 'CrossFileTests', + 'TAPParserTests', 'SubprojectsCommandTests', 'PlatformAgnosticTests', + + 'LinuxlikeTests', 'LinuxCrossArmTests', 'LinuxCrossMingwTests', + 'WindowsTests', 'DarwinTests'] + + try: + import pytest # noqa: F401 + pytest_args = [] + try: + # Need pytest-xdist for `-n` arg + import xdist # noqa: F401 + # Don't use pytest-xdist when running single unit tests since it wastes + # time spawning a lot of processes to distribute tests to in that case. + if not running_single_tests(sys.argv, cases): + pytest_args += ['-n', 'auto'] + except ImportError: + print('pytest-xdist not found, tests will not be distributed across CPU cores') + # Let there be colors! + if 'CI' in os.environ: + pytest_args += ['--color=yes'] + pytest_args += ['unittests'] + pytest_args += convert_args(sys.argv[1:]) + # Always disable pytest-cov because we use a custom setup + try: + import pytest_cov # noqa: F401 + print('Disabling pytest-cov') + pytest_args += ['-p' 'no:cov'] + except ImportError: + pass + return subprocess.run(python_command + ['-m', 'pytest'] + pytest_args).returncode + except ImportError: + print('pytest not found, using unittest instead') + # Fallback to plain unittest. + return unittest.main(defaultTest=cases, buffer=True) + +if __name__ == '__main__': + setup_vsenv() + print('Meson build system', mesonbuild.coredata.version, 'Unit Tests') + start = time.monotonic() + try: + raise SystemExit(main()) + finally: + print('Total time: {:.3f} seconds'.format(time.monotonic() - start)) diff --git a/devtools/meson/setup.cfg b/devtools/meson/setup.cfg new file mode 100644 index 0000000..cb24ebb --- /dev/null +++ b/devtools/meson/setup.cfg @@ -0,0 +1,69 @@ +[metadata] +name = meson +version = attr: mesonbuild.coredata.version +description = A high performance build system +author = Jussi Pakkanen +author_email = jpakkane@gmail.com +url = https://mesonbuild.com +project_urls = + Source = https://github.com/mesonbuild/meson +keywords = + meson + mesonbuild + build system + cmake +license = Apache License, Version 2.0 +license_files = COPYING +classifiers = + Development Status :: 5 - Production/Stable + Environment :: Console + Intended Audience :: Developers + License :: OSI Approved :: Apache Software License + Natural Language :: English + Operating System :: MacOS :: MacOS X + Operating System :: Microsoft :: Windows + Operating System :: POSIX :: BSD + Operating System :: POSIX :: Linux + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Topic :: Software Development :: Build Tools +long_description = Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. + +[options] +packages = find: +python_requires = >= 3.7 + +[options.entry_points] +console_scripts = + meson = mesonbuild.mesonmain:main + +[options.extras_require] +ninja = + ninja>=1.8.2 +progress = + tqdm +typing = + mypy + typing_extensions; python_version <"3.8" + +[options.package_data] +mesonbuild.scripts = cmd_or_ps.ps1 +mesonbuild.cmake.data = * +mesonbuild.dependencies.data = * + +[options.packages.find] +include = mesonbuild, mesonbuild.* + +[tool:pytest] +python_classes = +python_files = + unittests/*tests.py + +[egg_info] +tag_build = +tag_date = 0 + diff --git a/devtools/meson/setup.py b/devtools/meson/setup.py new file mode 100644 index 0000000..7ff28e2 --- /dev/null +++ b/devtools/meson/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +if sys.version_info < (3, 7): + raise SystemExit('ERROR: Tried to install Meson with an unsupported Python version: \n{}' + '\nMeson requires Python 3.7.0 or greater'.format(sys.version)) + +from setuptools import setup + +data_files = [] +if sys.platform != 'win32': + # Only useful on UNIX-like systems + data_files = [('share/man/man1', ['man/meson.1']), + ('share/polkit-1/actions', ['data/com.mesonbuild.install.policy'])] + +setup(data_files=data_files,) diff --git a/devtools/meson/tools/ac_converter.py b/devtools/meson/tools/ac_converter.py new file mode 100644 index 0000000..f2a5599 --- /dev/null +++ b/devtools/meson/tools/ac_converter.py @@ -0,0 +1,453 @@ +#!/usr/bin/env python3 + +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +help_message = """Usage: {} + +This script reads config.h.meson, looks for header +checks and writes the corresponding meson declaration. + +Copy config.h.in to config.h.meson, replace #undef +with #mesondefine and run this. We can't do this automatically +because some configure scripts have #undef statements +that are unrelated to configure checks. +""" + +import sys + + +# Add stuff here as it is encountered. +function_data = \ + {'HAVE_FEENABLEEXCEPT': ('feenableexcept', 'fenv.h'), + 'HAVE_FECLEAREXCEPT': ('feclearexcept', 'fenv.h'), + 'HAVE_FEDISABLEEXCEPT': ('fedisableexcept', 'fenv.h'), + 'HAVE_MMAP': ('mmap', 'sys/mman.h'), + 'HAVE_GETPAGESIZE': ('getpagesize', 'unistd.h'), + 'HAVE_GETISAX': ('getisax', 'sys/auxv.h'), + 'HAVE_GETTIMEOFDAY': ('gettimeofday', 'sys/time.h'), + 'HAVE_MPROTECT': ('mprotect', 'sys/mman.h'), + 'HAVE_POSIX_MEMALIGN': ('posix_memalign', 'stdlib.h'), + 'HAVE_SIGACTION': ('sigaction', 'signal.h'), + 'HAVE_ALARM': ('alarm', 'unistd.h'), + 'HAVE_CTIME_R': ('ctime_r', 'time.h'), + 'HAVE_DRAND48': ('drand48', 'stdlib.h'), + 'HAVE_FLOCKFILE': ('flockfile', 'stdio.h'), + 'HAVE_FORK': ('fork', 'unistd.h'), + 'HAVE_FUNLOCKFILE': ('funlockfile', 'stdio.h'), + 'HAVE_GETLINE': ('getline', 'stdio.h'), + 'HAVE_LINK': ('link', 'unistd.h'), + 'HAVE_RAISE': ('raise', 'signal.h'), + 'HAVE_STRNDUP': ('strndup', 'string.h'), + 'HAVE_SCHED_GETAFFINITY': ('sched_getaffinity', 'sched.h'), + 'HAVE_WAITPID': ('waitpid', 'sys/wait.h'), + 'HAVE_XRENDERCREATECONICALGRADIENT': ('XRenderCreateConicalGradient', 'xcb/render.h'), + 'HAVE_XRENDERCREATELINEARGRADIENT': ('XRenderCreateLinearGradient', 'xcb/render.h'), + 'HAVE_XRENDERCREATERADIALGRADIENT': ('XRenderCreateRadialGradient', 'xcb/render.h'), + 'HAVE_XRENDERCREATESOLIDFILL': ('XRenderCreateSolidFill', 'xcb/render.h'), + 'HAVE_DCGETTEXT': ('dcgettext', 'libintl.h'), + 'HAVE_ENDMNTENT': ('endmntent', 'mntent.h'), + 'HAVE_ENDSERVENT': ('endservent', 'netdb.h'), + 'HAVE_EVENTFD': ('eventfd', 'sys/eventfd.h'), + 'HAVE_FALLOCATE': ('fallocate', 'fcntl.h'), + 'HAVE_FCHMOD': ('fchmod', 'sys/stat.h'), + 'HAVE_FCHOWN': ('fchown', 'unistd.h'), + 'HAVE_FDWALK': ('fdwalk', 'stdlib.h'), + 'HAVE_FSYNC': ('fsync', 'unistd.h'), + 'HAVE_GETC_UNLOCKED': ('getc_unlocked', 'stdio.h'), + 'HAVE_GETFSSTAT': ('getfsstat', 'sys/mount.h'), + 'HAVE_GETMNTENT_R': ('getmntent_r', 'mntent.h'), + 'HAVE_GETPROTOBYNAME_R': ('getprotobyname_r', 'netdb.h'), + 'HAVE_GETRESUID': ('getresuid', 'unistd.h'), + 'HAVE_GETVFSSTAT': ('getvfsstat', 'sys/statvfs.h'), + 'HAVE_GMTIME_R': ('gmtime_r', 'time.h'), + 'HAVE_HASMNTOPT': ('hasmntopt', 'mntent.h'), + 'HAVE_IF_INDEXTONAME': ('if_indextoname', 'net/if.h'), + 'HAVE_IF_NAMETOINDEX': ('if_nametoindex', 'net/if.h'), + 'HAVE_INOTIFY_INIT1': ('inotify_init1', 'sys/inotify.h'), + 'HAVE_ISSETUGID': ('issetugid', 'unistd.h'), + 'HAVE_KEVENT': ('kevent', 'sys/event.h'), + 'HAVE_KQUEUE': ('kqueue', 'sys/event.h'), + 'HAVE_LCHMOD': ('lchmod', 'sys/stat.h'), + 'HAVE_LCHOWN': ('lchown', 'unistd.h'), + 'HAVE_LSTAT': ('lstat', 'sys/stat.h'), + 'HAVE_MEMCPY': ('memcpy', 'string.h'), + 'HAVE_MEMALIGN': ('memalign', 'stdlib.h'), + 'HAVE_MEMMEM': ('memmem', 'string.h'), + 'HAVE_NEWLOCALE': ('newlocale', 'locale.h'), + 'HAVE_PIPE2': ('pipe2', 'fcntl.h'), + 'HAVE_POLL': ('poll', 'poll.h'), + 'HAVE_PRLIMIT': ('prlimit', 'sys/resource.h'), + 'HAVE_PTHREAD_ATTR_SETSTACKSIZE': ('pthread_attr_setstacksize', 'pthread.h'), + 'HAVE_PTHREAD_CONDATTR_SETCLOCK': ('pthread_condattr_setclock', 'pthread.h'), + 'HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP': ('pthread_cond_timedwait_relative_np', 'pthread.h'), + 'HAVE_READLINK': ('readlink', 'unistd.h'), + 'HAVE_RES_INIT': ('res_init', 'resolv.h'), + 'HAVE_SENDMMSG': ('sendmmsg', 'sys/socket.h'), + 'HAVE_SOCKET': ('socket', 'sys/socket.h'), + 'HAVE_GETENV': ('getenv', 'stdlib.h'), + 'HAVE_SETENV': ('setenv', 'stdlib.h'), + 'HAVE_PUTENV': ('putenv', 'stdlib.h'), + 'HAVE_UNSETENV': ('unsetenv', 'stdlib.h'), + 'HAVE_SETMNTENT': ('setmntent', 'mntent.h'), + 'HAVE_SNPRINTF': ('snprintf', 'stdio.h'), + 'HAVE_SPLICE': ('splice', 'fcntl.h'), + 'HAVE_STATFS': ('statfs', 'mount.h'), + 'HAVE_STATVFS': ('statvfs', 'sys/statvfs.h'), + 'HAVE_STPCOPY': ('stpcopy', 'string.h'), + 'HAVE_STRCASECMP': ('strcasecmp', 'strings.h'), + 'HAVE_STRLCPY': ('strlcpy', 'string.h'), + 'HAVE_STRNCASECMP': ('strncasecmp', 'strings.h'), + 'HAVE_STRSIGNAL': ('strsignal', 'signal.h'), + 'HAVE_STRTOD_L': ('strtod_l', 'stdlib.h'), + 'HAVE_STRTOLL_L': ('strtoll_l', 'stdlib.h'), + 'HAVE_STRTOULL_L': ('strtoull_l', 'stdlib.h'), + 'HAVE_SYMLINK': ('symlink', 'unistd.h'), + 'HAVE_SYSCTLBYNAME': ('sysctlbyname', 'sys/sysctl.h'), + 'HAVE_TIMEGM': ('timegm', 'time.h'), + 'HAVE_USELOCALE': ('uselocale', 'xlocale.h'), + 'HAVE_UTIMES': ('utimes', 'sys/time.h'), + 'HAVE_VALLOC': ('valloc', 'stdlib.h'), + 'HAVE_VASPRINTF': ('vasprintf', 'stdio.h'), + 'HAVE_VSNPRINTF': ('vsnprintf', 'stdio.h'), + 'HAVE_BCOPY': ('bcopy', 'strings.h'), + 'HAVE_STRERROR': ('strerror', 'string.h'), + 'HAVE_MEMMOVE': ('memmove', 'string.h'), + 'HAVE_STRTOIMAX': ('strtoimax', 'inttypes.h'), + 'HAVE_STRTOLL': ('strtoll', 'stdlib.h'), + 'HAVE_STRTOQ': ('strtoq', 'stdlib.h'), + 'HAVE_ACCEPT4': ('accept4', 'sys/socket.h'), + 'HAVE_CHMOD': ('chmod', 'sys/stat.h'), + 'HAVE_CHOWN': ('chown', 'unistd.h'), + 'HAVE_FSTAT': ('fstat', 'sys/stat.h'), + 'HAVE_GETADDRINFO': ('getaddrinfo', 'netdb.h'), + 'HAVE_GETGRGID_R': ('getgrgid_r', 'grp.h'), + 'HAVE_GETGRNAM_R': ('getgrnam_r', 'grp.h'), + 'HAVE_GETGROUPS': ('getgroups', 'grp.h'), + 'HAVE_GETOPT_LONG': ('getopt_long', 'getopt.h'), + 'HAVE_GETPWNAM_R': ('getpwnam', 'pwd.h'), + 'HAVE_GETPWUID_R': ('getpwuid_r', 'pwd.h'), + 'HAVE_GETUID': ('getuid', 'unistd.h'), + 'HAVE_LRINTF': ('lrintf', 'math.h'), + 'HAVE_DECL_ISNAN': ('isnan', 'math.h'), + 'HAVE_DECL_ISINF': ('isinf', 'math.h'), + 'HAVE_ROUND': ('round', 'math.h'), + 'HAVE_NEARBYINT': ('nearbyint', 'math.h'), + 'HAVE_RINT': ('rint', 'math.h'), + 'HAVE_MKFIFO': ('mkfifo', 'sys/stat.h'), + 'HAVE_MLOCK': ('mlock', 'sys/mman.h'), + 'HAVE_NANOSLEEP': ('nanosleep', 'time.h'), + 'HAVE_PIPE': ('pipe', 'unistd.h'), + 'HAVE_PPOLL': ('ppoll', 'poll.h'), + 'HAVE_REGEXEC': ('regexec', 'regex.h'), + 'HAVE_SETEGID': ('setegid', 'unistd.h'), + 'HAVE_SETEUID': ('seteuid', 'unistd.h'), + 'HAVE_SETPGID': ('setpgid', 'unistd.h'), + 'HAVE_SETREGID': ('setregid', 'unistd.h'), + 'HAVE_SETRESGID': ('setresgid', 'unistd.h'), + 'HAVE_SETRESUID': ('setresuid', 'unistd.h'), + 'HAVE_SHM_OPEN': ('shm_open', 'fcntl.h'), + 'HAVE_SLEEP': ('sleep', 'unistd.h'), + 'HAVE_STRERROR_R': ('strerror_r', 'string.h'), + 'HAVE_STRTOF': ('strtof', 'stdlib.h'), + 'HAVE_SYSCONF': ('sysconf', 'unistd.h'), + 'HAVE_USLEEP': ('usleep', 'unistd.h'), + 'HAVE_VFORK': ('vfork', 'unistd.h'), + 'HAVE_MALLOC': ('malloc', 'stdlib.h'), + 'HAVE_CALLOC': ('calloc', 'stdlib.h'), + 'HAVE_REALLOC': ('realloc', 'stdlib.h'), + 'HAVE_FREE': ('free', 'stdlib.h'), + 'HAVE_ALLOCA': ('alloca', 'alloca.h'), + 'HAVE_QSORT': ('qsort', 'stdlib.h'), + 'HAVE_ABS': ('abs', 'stdlib.h'), + 'HAVE_MEMSET': ('memset', 'string.h'), + 'HAVE_MEMCMP': ('memcmp', 'string.h'), + 'HAVE_STRLEN': ('strlen', 'string.h'), + 'HAVE_STRLCAT': ('strlcat', 'string.h'), + 'HAVE_STRDUP': ('strdup', 'string.h'), + 'HAVE__STRREV': ('_strrev', 'string.h'), + 'HAVE__STRUPR': ('_strupr', 'string.h'), + 'HAVE__STRLWR': ('_strlwr', 'string.h'), + 'HAVE_INDEX': ('index', 'strings.h'), + 'HAVE_RINDEX': ('rindex', 'strings.h'), + 'HAVE_STRCHR': ('strchr', 'string.h'), + 'HAVE_STRRCHR': ('strrchr', 'string.h'), + 'HAVE_STRSTR': ('strstr', 'string.h'), + 'HAVE_STRTOL': ('strtol', 'stdlib.h'), + 'HAVE_STRTOUL': ('strtoul', 'stdlib.h'), + 'HAVE_STRTOULL': ('strtoull', 'stdlib.h'), + 'HAVE_STRTOD': ('strtod', 'stdlib.h'), + 'HAVE_ATOI': ('atoi', 'stdlib.h'), + 'HAVE_ATOF': ('atof', 'stdlib.h'), + 'HAVE_STRCMP': ('strcmp', 'string.h'), + 'HAVE_STRNCMP': ('strncmp', 'string.h'), + 'HAVE_VSSCANF': ('vsscanf', 'stdio.h'), + 'HAVE_CHROOT': ('chroot', 'unistd.h'), + 'HAVE_CLOCK': ('clock', 'time.h'), + 'HAVE_CLOCK_GETRES': ('clock_getres', 'time.h'), + 'HAVE_CLOCK_GETTIME': ('clock_gettime', 'time.h'), + 'HAVE_CLOCK_SETTIME': ('clock_settime', 'time.h'), + 'HAVE_CONFSTR': ('confstr', 'time.h'), + 'HAVE_CTERMID': ('ctermid', 'stdio.h'), + 'HAVE_DIRFD': ('dirfd', 'dirent.h'), + 'HAVE_DLOPEN': ('dlopen', 'dlfcn.h'), + 'HAVE_DUP2': ('dup2', 'unistd.h'), + 'HAVE_DUP3': ('dup3', 'unistd.h'), + 'HAVE_EPOLL_CREATE1': ('epoll_create1', 'sys/epoll.h'), + 'HAVE_ERF': ('erf', 'math.h'), + 'HAVE_ERFC': ('erfc', 'math.h'), + 'HAVE_EXECV': ('execv', 'unistd.h'), + 'HAVE_FACCESSAT': ('faccessat', 'unistd.h'), + 'HAVE_FCHDIR': ('fchdir', 'unistd.h'), + 'HAVE_FCHMODAT': ('fchmodat', 'sys/stat.h'), + 'HAVE_FDATASYNC': ('fdatasync', 'unistd.h'), + 'HAVE_FDOPENDIR': ('fdopendir', 'dirent.h'), + 'HAVE_FEXECVE': ('fexecve', 'unistd.h'), + 'HAVE_FLOCK': ('flock', 'sys/file.h'), + 'HAVE_FORKPTY': ('forkpty', 'pty.h'), + 'HAVE_FPATHCONF': ('fpathconf', 'unistd.h'), + 'HAVE_FSTATAT': ('fstatat', 'unistd.h'), + 'HAVE_FSTATVFS': ('fstatvfs', 'sys/statvfs.h'), + 'HAVE_FTELLO': ('ftello', 'stdio.h'), + 'HAVE_FTIME': ('ftime', 'sys/timeb.h'), + 'HAVE_FTRUNCATE': ('ftruncate', 'unistd.h'), + 'HAVE_FUTIMENS': ('futimens', 'sys/stat.h'), + 'HAVE_FUTIMES': ('futimes', 'sys/time.h'), + 'HAVE_GAI_STRERROR': ('gai_strerror', 'netdb.h'), + 'HAVE_GETGROUPLIST': ('getgrouplist', 'grp.h'), + 'HAVE_GETHOSTBYNAME': ('gethostbyname', 'netdb.h'), + 'HAVE_GETHOSTBYNAME_R': ('gethostbyname_r', 'netdb.h'), + 'HAVE_GETITIMER': ('getitimer', 'sys/time.h'), + 'HAVE_GETLOADAVG': ('getloadavg', 'stdlib.h'), + 'HAVE_GETLOGIN': ('getlogin', 'unistd.h'), + 'HAVE_GETNAMEINFO': ('getnameinfo', 'netdb.h'), + 'HAVE_GETPEERNAME': ('getpeername', 'sys/socket.h'), + 'HAVE_GETPGID': ('getpgid', 'unistd.h'), + 'HAVE_GETPGRP': ('getpgrp', 'unistd.h'), + 'HAVE_GETPID': ('getpid', 'unistd.h'), + 'HAVE_GETPRIORITY': ('getpriority', 'sys/resource.h'), + 'HAVE_GETPWENT': ('getpwent', 'pwd.h'), + 'HAVE_GETRANDOM': ('getrandom', 'linux/random.h'), + 'HAVE_GETRESGID': ('getresgid', 'unistd.h'), + 'HAVE_GETSID': ('getsid', 'unistd.h'), + 'HAVE_GETSPENT': ('getspent', 'shadow.h'), + 'HAVE_GETSPNAM': ('getspnam', 'shadow.h'), + 'HAVE_GETWD': ('getwd', 'unistd.h'), + 'HAVE_HSTRERROR': ('hstrerror', 'netdb.h'), + 'HAVE_HTOLE64': ('htole64', 'endian.h'), + 'HAVE_IF_NAMEINDEX': ('if_nameindex', 'net/if.h'), + 'HAVE_INET_ATON': ('inet_aton', 'arpa/inet.h'), + 'HAVE_INET_PTON': ('inet_pton', 'arpa/inet.h'), + 'HAVE_INITGROUPS': ('initgroups', 'grp.h'), + 'HAVE_KILL': ('kill', 'signal.h'), + 'HAVE_KILLPG': ('killpg', 'signal.h'), + 'HAVE_LINKAT': ('linkat', 'unistd.h'), + 'HAVE_LOCKF': ('lockf', 'unistd.h'), + 'HAVE_LUTIMES': ('lutimes', 'sys/time.h'), + 'HAVE_MAKEDEV': ('makedev', 'sys/sysmacros.h'), + 'HAVE_MBRTOWC': ('mbrtowc', 'wchar.h'), + 'HAVE_MEMRCHR': ('memrchr', 'string.h'), + 'HAVE_MKDIRAT': ('mkdirat', 'sys/stat.h'), + 'HAVE_MKFIFOAT': ('mkfifoat', 'sys/stat.h'), + 'HAVE_MKNOD': ('mknod', 'unistd.h'), + 'HAVE_MKNODAT': ('mknodat', 'unistd.h'), + 'HAVE_MKTIME': ('mktime', 'unistd.h'), + 'HAVE_MKREMAP': ('mkremap', 'sys/mman.h'), + 'HAVE_NICE': ('nice', 'unistd.h'), + 'HAVE_OPENAT': ('openat', 'fcntl.h'), + 'HAVE_OPENPTY': ('openpty', 'pty.h'), + 'HAVE_PATHCONF': ('pathconf', 'unistd.h'), + 'HAVE_PAUSE': ('pause', 'unistd.h'), + 'HAVE_PREAD': ('pread', 'unistd.h'), + 'HAVE_PTHREAD_KILL': ('pthread_kill', 'signal.h'), + 'HAVE_PTHREAD_SIGMASK': ('pthread_sigmask', 'signal.h'), + 'HAVE_PWRITE': ('pwrite', 'unistd.h'), + 'HAVE_READLINKAT': ('readlinkat', 'unistd.h'), + 'HAVE_READV': ('readv', 'sys/uio.h'), + 'HAVE_RENAMEAT': ('renamat', 'stdio.h'), + 'HAVE_SCHED_GET_PRIORITY_MAX': ('sched_get_priority_max', 'sched.h'), + 'HAVE_SCHED_RR_GET_INTERVAL': ('sched_rr_get_interval', 'sched.h'), + 'HAVE_SCHED_SETAFFINITY': ('sched_setaffinity', 'sched.h'), + 'HAVE_SCHED_SETPARAM': ('sched_setparam', 'sched.h'), + 'HAVE_SCHED_SETSCHEDULER': ('sched_setscheduler', 'sched.h'), + 'HAVE_SELECT': ('select', 'sys/select.h'), + 'HAVE_SEM_GETVALUE': ('sem_getvalue', 'semaphore.h'), + 'HAVE_SEM_OPEN': ('sem_open', 'semaphore.h'), + 'HAVE_SEM_TIMEDWAIT': ('sem_timedwait', 'semaphore.h'), + 'HAVE_SEM_UNLINK': ('sem_unlink', 'semaphore.h'), + 'HAVE_SENDFILE': ('sendfile', 'sys/sendfile.h'), + 'HAVE_SETGID': ('setgid', 'unistd.h'), + 'HAVE_SETGROUPS': ('setgroups', 'grp.h'), + 'HAVE_SETHOSTNAME': ('sethostname', 'unistd.h'), + 'HAVE_SETITIMER': ('setitimer', 'sys/time.h'), + 'HAVE_SETLOCALE': ('setlocale', 'locale.h'), + 'HAVE_SETPGRP': ('setpgrp', 'unistd.h'), + 'HAVE_SETPRIORITY': ('setpriority', 'sys/resource.h'), + 'HAVE_SETREUID': ('setreuid', 'unistd.h'), + 'HAVE_SETSID': ('setsid', 'unistd.h'), + 'HAVE_SETUID': ('setuid', 'unistd.h'), + 'HAVE_SETVBUF': ('setvbuf', 'unistd.h'), + 'HAVE_SIGALTSTACK': ('sigaltstack', 'signal.h'), + 'HAVE_SIGINTERRUPT': ('siginterrupt', 'signal.h'), + 'HAVE_SIGPENDING': ('sigpending', 'signal.h'), + 'HAVE_SIGRELSE': ('sigrelse', 'signal.h'), + 'HAVE_SIGTIMEDWAIT': ('sigtimedwait', 'signal.h'), + 'HAVE_SIGWAIT': ('sigwait', 'signal.h'), + 'HAVE_SIGWAITINFO': ('sigwaitinfo', 'signal.h'), + 'HAVE_SOCKETPAIR': ('socketpair', 'sys/socket.h'), + 'HAVE_STRFTIME': ('strftime', 'time.h'), + 'HAVE_SYMLINKAT': ('symlinkat', 'unistd.h'), + 'HAVE_SYNC': ('sync', 'unistd.h'), + 'HAVE_TCGETPGRP': ('tcgetpgrp', 'unistd.h'), + 'HAVE_TCSETPGRP': ('tcsetpgrp', 'unistd.h'), + 'HAVE_TEMPNAM': ('tempnam', 'stdio.h'), + 'HAVE_TIMES': ('times', 'sys/times.h'), + 'HAVE_TEMPFILE': ('tempfile', 'stdio.h'), + 'HAVE_TMPNAM': ('tmpnam', 'stdio.h'), + 'HAVE_TMPNAM_R': ('tmpnam_r', 'stdio.h'), + 'HAVE_TRUNCATE': ('truncate', 'unistd.h'), + 'HAVE_TZNAME': ('tzname', 'time.h'), + 'HAVE_UNAME': ('uname', 'sys/utsname.h'), + 'HAVE_UNLINKAT': ('unlinkat', 'unistd.h'), + 'HAVE_UTIMENSAT': ('utimensat', 'sys/stat.h'), + 'HAVE_WAIT3': ('wait3', 'sys/wait.h'), + 'HAVE_WAIT4': ('wait4', 'sys/wait.h'), + 'HAVE_WAITID': ('waitid', 'sys/wait.h'), + 'HAVE_WRITEV': ('writev', 'sys/uio.h'), + 'HAVE_WMEMCMP': ('wmemcmp', 'wchar.h'), + 'HAVE_ATAN': ('atan', 'math.h'), + 'HAVE_ATAN2': ('atan2', 'math.h'), + 'HAVE_ACOS': ('acos', 'math.h'), + 'HAVE_ACOSH': ('acosh', 'math.h'), + 'HAVE_ASIN': ('asin', 'math.h'), + 'HAVE_ASINH': ('asinh', 'math.h'), + 'HAVE_ATANH': ('atanh', 'math.h'), + 'HAVE_CEIL': ('ceil', 'math.h'), + 'HAVE_COPYSIGN': ('copysign', 'math.h'), + 'HAVE_COS': ('cos', 'math.h'), + 'HAVE_COSH': ('cosh', 'math.h'), + 'HAVE_COSF': ('cosf', 'math.h'), + 'HAVE_EXPM1': ('expm1', 'math.h'), + 'HAVE_FABS': ('fabs', 'math.h'), + 'HAVE_FINITE': ('finite', 'math.h'), + 'HAVE_FLOOR': ('floor', 'math.h'), + 'HAVE_GAMMA': ('gamma', 'math.h'), + 'HAVE_HYPOT': ('hypot', 'math.h'), + 'HAVE_ISINF': ('isinf', 'math.h'), + 'HAVE_LOG': ('log', 'math.h'), + 'HAVE_LOG1P': ('log1p', 'math.h'), + 'HAVE_LOG2': ('log2', 'math.h'), + 'HAVE_LGAMMA': ('lgamma', 'math.h'), + 'HAVE_POW': ('pow', 'math.h'), + 'HAVE_SCALBN': ('scalbn', 'math.h'), + 'HAVE_SIN': ('sin', 'math.h'), + 'HAVE_SINF': ('sinf', 'math.h'), + 'HAVE_SINH': ('sinh', 'math.h'), + 'HAVE_SQRT': ('sqrt', 'math.h'), + 'HAVE_TGAMMA': ('tgamma', 'math.h'), + 'HAVE_FSEEKO': ('fseeko', 'stdio.h'), + 'HAVE_FSEEKO64': ('fseeko64', 'stdio.h'), + 'HAVE_SETJMP': ('setjmp', 'setjmp.h'), + 'HAVE_PTHREAD_SETNAME_NP': ('pthread_setname_np', 'pthread.h'), + 'HAVE_PTHREAD_SET_NAME_NP': ('pthread_set_name_np', 'pthread.h'), + } + +headers = [] +functions = [] +sizes = [] + +if len(sys.argv) != 2: + print(help_message.format(sys.argv[0])) + sys.exit(0) + +with open(sys.argv[1], encoding='utf-8') as f: + for line in f: + line = line.strip() + arr = line.split() + + # Check for headers. + if line.startswith('#mesondefine') and line.endswith('_H'): + token = line.split()[1] + tarr = token.split('_')[1:-1] + tarr = [x.lower() for x in tarr] + hname = '/'.join(tarr) + '.h' + headers.append(hname) + + # Check for functions. + try: + token = arr[1] + if token in function_data: + fdata = function_data[token] + functions.append([token, fdata[0], fdata[1]]) + elif token.startswith('HAVE_') and not token.endswith('_H'): + functions.append([token]) + except Exception: + pass + + # Check for sizeof tests. + if len(arr) != 2: + continue + elem = arr[1] + if elem.startswith('SIZEOF_'): + typename = elem.split('_', 1)[1] \ + .replace('_P', '*') \ + .replace('_', ' ') \ + .lower() \ + .replace('size t', 'size_t') + sizes.append((elem, typename)) + +print('''cc = meson.get_compiler('c') +cdata = configuration_data()''') + +# Convert header checks. + +print('check_headers = [') +for hname in headers: + print(f" '{hname}',") +print(']\n') + +print('''foreach h : check_headers + if cc.has_header(h) + cdata.set('HAVE_' + h.underscorify().to_upper(), 1) + endif +endforeach +''') + +# Convert function checks. + +print('check_functions = [') +for tok in functions: + if len(tok) == 3: + tokstr, fdata0, fdata1 = tok + print(f" ['{tokstr}', '{fdata0}', '#include<{fdata1}>'],") + else: + print('# check token', tok) +print(']\n') + +print('''foreach f : check_functions + if cc.has_function(f.get(1), prefix : f.get(2)) + cdata.set(f.get(0), 1) + endif +endforeach +''') + +# Convert sizeof checks. + +for elem, typename in sizes: + print(f"cdata.set('{elem}', cc.sizeof('{typename}'))") + +print(''' +configure_file(input : 'config.h.meson', + output : 'config.h', + configuration : cdata)''') diff --git a/devtools/meson/tools/boost_names.py b/devtools/meson/tools/boost_names.py new file mode 100644 index 0000000..f27d524 --- /dev/null +++ b/devtools/meson/tools/boost_names.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python3 + +# Copyright 2017 Niklas Claesson + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This is two implementations for how to get module names from the boost +sources. One relies on json metadata files in the sources, the other relies on +the folder names. + +Run the tool in the boost directory and append the stdout to the misc.py: + +boost/$ path/to/meson/tools/boost_names.py >> path/to/meson/dependencies/misc.py +""" + +import sys +import json +import re +import textwrap +import functools +import typing as T +from pathlib import Path + +lib_dir = Path('libs') +jamroot = Path('Jamroot') + +not_modules = ['config', 'disjoint_sets', 'headers'] + +export_modules = False + + +@functools.total_ordering +class BoostLibrary(): + def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]): + self.name = name + self.shared = sorted(set(shared)) + self.static = sorted(set(static)) + self.single = sorted(set(single)) + self.multi = sorted(set(multi)) + + def __lt__(self, other: object) -> bool: + if isinstance(other, BoostLibrary): + return self.name < other.name + return NotImplemented + + def __eq__(self, other: object) -> bool: + if isinstance(other, BoostLibrary): + return self.name == other.name + elif isinstance(other, str): + return self.name == other + return NotImplemented + + def __hash__(self) -> int: + return hash(self.name) + +@functools.total_ordering +class BoostModule(): + def __init__(self, name: str, key: str, desc: str, libs: T.List[BoostLibrary]): + self.name = name + self.key = key + self.desc = desc + self.libs = libs + + def __lt__(self, other: object) -> bool: + if isinstance(other, BoostModule): + return self.key < other.key + return NotImplemented + + +def get_boost_version() -> T.Optional[str]: + raw = jamroot.read_text(encoding='utf-8') + m = re.search(r'BOOST_VERSION\s*:\s*([0-9\.]+)\s*;', raw) + if m: + return m.group(1) + return None + + +def get_libraries(jamfile: Path) -> T.List[BoostLibrary]: + # Extract libraries from the boost Jamfiles. This includes: + # - library name + # - compiler flags + + libs: T.List[BoostLibrary] = [] + raw = jamfile.read_text(encoding='utf-8') + raw = re.sub(r'#.*\n', '\n', raw) # Remove comments + raw = re.sub(r'\s+', ' ', raw) # Force single space + raw = re.sub(r'}', ';', raw) # Cheat code blocks by converting } to ; + + cmds = raw.split(';') # Commands always terminate with a ; (I hope) + cmds = [x.strip() for x in cmds] # Some cleanup + + project_usage_requirements: T.List[str] = [] + + # "Parse" the relevant sections + for i in cmds: + parts = i.split(' ') + parts = [x for x in parts if x not in ['']] + if not parts: + continue + + # Parse project + if parts[0] in ['project']: + attributes: T.Dict[str, T.List[str]] = {} + curr: T.Optional[str] = None + + for j in parts: + if j == ':': + curr = None + elif curr is None: + curr = j + else: + if curr not in attributes: + attributes[curr] = [] + attributes[curr] += [j] + + if 'usage-requirements' in attributes: + project_usage_requirements = attributes['usage-requirements'] + + # Parse libraries + elif parts[0] in ['lib', 'boost-lib']: + assert len(parts) >= 2 + + # Get and check the library name + lname = parts[1] + if parts[0] == 'boost-lib': + lname = f'boost_{lname}' + if not lname.startswith('boost_'): + continue + + # Count `:` to only select the 'usage-requirements' + # See https://boostorg.github.io/build/manual/master/index.html#bbv2.main-target-rule-syntax + colon_counter = 0 + usage_requirements: T.List[str] = [] + for j in parts: + if j == ':': + colon_counter += 1 + elif colon_counter >= 4: + usage_requirements += [j] + + # Get shared / static defines + shared: T.List[str] = [] + static: T.List[str] = [] + single: T.List[str] = [] + multi: T.List[str] = [] + for j in usage_requirements + project_usage_requirements: + m1 = re.match(r'shared:(.*)', j) + m2 = re.match(r'static:(.*)', j) + m3 = re.match(r'single:(.*)', j) + m4 = re.match(r'multi:(.*)', j) + + if m1: + shared += [f'-D{m1.group(1)}'] + if m2: + static += [f'-D{m2.group(1)}'] + if m3: + single +=[f'-D{m3.group(1)}'] + if m4: + multi += [f'-D{m4.group(1)}'] + + libs += [BoostLibrary(lname, shared, static, single, multi)] + + return libs + + +def process_lib_dir(ldir: Path) -> T.List[BoostModule]: + meta_file = ldir / 'meta' / 'libraries.json' + bjam_file = ldir / 'build' / 'Jamfile.v2' + if not meta_file.exists(): + print(f'WARNING: Meta file {meta_file} does not exist') + return [] + + # Extract libs + libs: T.List[BoostLibrary] = [] + if bjam_file.exists(): + libs = get_libraries(bjam_file) + + # Extract metadata + data = json.loads(meta_file.read_text(encoding='utf-8')) + if not isinstance(data, list): + data = [data] + + modules: T.List[BoostModule] = [] + for i in data: + modules += [BoostModule(i['name'], i['key'], i['description'], libs)] + + return modules + + +def get_modules() -> T.List[BoostModule]: + modules: T.List[BoostModule] = [] + for i in lib_dir.iterdir(): + if not i.is_dir() or i.name in not_modules: + continue + + # numeric has sub libs + subdirs = i / 'sublibs' + metadir = i / 'meta' + if subdirs.exists() and not metadir.exists(): + for j in i.iterdir(): + if not j.is_dir(): + continue + modules += process_lib_dir(j) + else: + modules += process_lib_dir(i) + + return modules + + +def main() -> int: + if not lib_dir.is_dir() or not jamroot.exists(): + print("ERROR: script must be run in boost source directory") + return 1 + + vers = get_boost_version() + modules = get_modules() + modules = sorted(modules) + libraries = [x for y in modules for x in y.libs] + libraries = sorted(set(libraries)) + + print(textwrap.dedent(f'''\ + #### ---- BEGIN GENERATED ---- #### + # # + # Generated with tools/boost_names.py: + # - boost version: {vers} + # - modules found: {len(modules)} + # - libraries found: {len(libraries)} + # + + class BoostLibrary(): + def __init__(self, name: str, shared: T.List[str], static: T.List[str], single: T.List[str], multi: T.List[str]): + self.name = name + self.shared = shared + self.static = static + self.single = single + self.multi = multi + + class BoostModule(): + def __init__(self, name: str, key: str, desc: str, libs: T.List[str]): + self.name = name + self.key = key + self.desc = desc + self.libs = libs + + + # dict of all know libraries with additional compile options + boost_libraries = {{\ + ''')) + + for i in libraries: + print(textwrap.indent(textwrap.dedent(f"""\ + '{i.name}': BoostLibrary( + name='{i.name}', + shared={i.shared}, + static={i.static}, + single={i.single}, + multi={i.multi}, + ),\ + """), ' ')) + + if export_modules: + print(textwrap.dedent(f'''\ + }} + + + # dict of all modules with metadata + boost_modules = {{\ + ''')) + + for mod in modules: + desc_escaped = re.sub(r"'", "\\'", mod.desc) + print(textwrap.indent(textwrap.dedent(f"""\ + '{mod.key}': BoostModule( + name='{mod.name}', + key='{mod.key}', + desc='{desc_escaped}', + libs={[x.name for x in mod.libs]}, + ),\ + """), ' ')) + + print(textwrap.dedent(f'''\ + }} + + # # + #### ---- END GENERATED ---- ####\ + ''')) + + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/devtools/meson/tools/build_website.py b/devtools/meson/tools/build_website.py new file mode 100644 index 0000000..77a049c --- /dev/null +++ b/devtools/meson/tools/build_website.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import os, subprocess, shutil + +assert os.getcwd() == '/home/jpakkane' + +from glob import glob + +def purge(fname: str) -> None: + if not os.path.exists(fname): + return + if os.path.isdir(fname): + shutil.rmtree(fname) + os.unlink(fname) + +def update() -> None: + webdir = 'mesonweb' + repodir = 'mesonwebbuild' + docdir = os.path.join(repodir, 'docs') + builddir = os.path.join(docdir, 'builddir') + htmldir = os.path.join(builddir, 'Meson documentation-doc/html') +# subprocess.check_call(['git', 'pull'], cwd=webdir) + subprocess.check_call(['git', 'fetch', '-a'], cwd=repodir) + subprocess.check_call(['git', 'reset', '--hard', 'origin/master'], + cwd=repodir) + if os.path.isdir(htmldir): + shutil.rmtree(htmldir) + if os.path.isdir(builddir): + shutil.rmtree(builddir) + env = os.environ.copy() + env['PATH'] = env['PATH'] + ':/home/jpakkane/.local/bin' + subprocess.check_call(['../meson.py', '.', 'builddir'], cwd=docdir, env=env) + subprocess.check_call(['ninja'], cwd=builddir) + old_files = glob(os.path.join(webdir, '*')) + for f in old_files: + base = f[len(webdir)+1:] + if base == 'CNAME' or base == 'favicon.png': + continue + subprocess.check_call(['git', 'rm', '-rf', base], cwd=webdir) + assert os.path.isdir(webdir) + new_entries = glob(os.path.join(htmldir, '*')) + for e in new_entries: + shutil.move(e, webdir) + subprocess.check_call('git add *', shell=True, cwd=webdir) + subprocess.check_call(['git', 'commit', '-a', '-m', 'Bleep. Bloop. I am a bot.'], + cwd=webdir) + subprocess.check_call(['git', 'push'], cwd=webdir) + shutil.rmtree(builddir) + +if __name__ == '__main__': + update() diff --git a/devtools/meson/tools/cmake2meson.py b/devtools/meson/tools/cmake2meson.py new file mode 100644 index 0000000..a12d9cf --- /dev/null +++ b/devtools/meson/tools/cmake2meson.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python3 + +# Copyright 2014 Jussi Pakkanen + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import typing as T +from pathlib import Path +import sys +import re +import argparse + + +class Token: + def __init__(self, tid: str, value: str): + self.tid = tid + self.value = value + self.lineno = 0 + self.colno = 0 + +class Statement: + def __init__(self, name: str, args: list): + self.name = name.lower() + self.args = args + +class Lexer: + def __init__(self) -> None: + self.token_specification = [ + # Need to be sorted longest to shortest. + ('ignore', re.compile(r'[ \t]')), + ('string', re.compile(r'"([^\\]|(\\.))*?"', re.M)), + ('varexp', re.compile(r'\${[-_0-9a-z/A-Z.]+}')), + ('id', re.compile('''[,-><${}=+_0-9a-z/A-Z|@.*]+''')), + ('eol', re.compile(r'\n')), + ('comment', re.compile(r'#.*')), + ('lparen', re.compile(r'\(')), + ('rparen', re.compile(r'\)')), + ] + + def lex(self, code: str) -> T.Iterator[Token]: + lineno = 1 + line_start = 0 + loc = 0 + col = 0 + while loc < len(code): + matched = False + for (tid, reg) in self.token_specification: + mo = reg.match(code, loc) + if mo: + col = mo.start() - line_start + matched = True + loc = mo.end() + match_text = mo.group() + if tid == 'ignore': + continue + if tid == 'comment': + yield(Token('comment', match_text)) + elif tid == 'lparen': + yield(Token('lparen', '(')) + elif tid == 'rparen': + yield(Token('rparen', ')')) + elif tid == 'string': + yield(Token('string', match_text[1:-1])) + elif tid == 'id': + yield(Token('id', match_text)) + elif tid == 'eol': + # yield('eol') + lineno += 1 + col = 1 + line_start = mo.end() + elif tid == 'varexp': + yield(Token('varexp', match_text[2:-1])) + else: + raise ValueError(f'lex: unknown element {tid}') + break + if not matched: + raise ValueError('Lexer got confused line %d column %d' % (lineno, col)) + +class Parser: + def __init__(self, code: str) -> None: + self.stream = Lexer().lex(code) + self.getsym() + + def getsym(self) -> None: + try: + self.current = next(self.stream) + except StopIteration: + self.current = Token('eof', '') + + def accept(self, s: str) -> bool: + if self.current.tid == s: + self.getsym() + return True + return False + + def expect(self, s: str) -> bool: + if self.accept(s): + return True + raise ValueError(f'Expecting {s} got {self.current.tid}.', self.current.lineno, self.current.colno) + + def statement(self) -> Statement: + cur = self.current + if self.accept('comment'): + return Statement('_', [cur.value]) + self.accept('id') + self.expect('lparen') + args = self.arguments() + self.expect('rparen') + return Statement(cur.value, args) + + def arguments(self) -> T.List[T.Union[Token, T.Any]]: + args = [] # type: T.List[T.Union[Token, T.Any]] + if self.accept('lparen'): + args.append(self.arguments()) + self.expect('rparen') + arg = self.current + if self.accept('comment'): + rest = self.arguments() + args += rest + elif self.accept('string') \ + or self.accept('varexp') \ + or self.accept('id'): + args.append(arg) + rest = self.arguments() + args += rest + return args + + def parse(self) -> T.Iterator[Statement]: + while not self.accept('eof'): + yield(self.statement()) + +def token_or_group(arg: T.Union[Token, T.List[Token]]) -> str: + if isinstance(arg, Token): + return ' ' + arg.value + elif isinstance(arg, list): + line = ' (' + for a in arg: + line += ' ' + token_or_group(a) + line += ' )' + return line + raise RuntimeError('Conversion error in token_or_group') + +class Converter: + ignored_funcs = {'cmake_minimum_required': True, + 'enable_testing': True, + 'include': True} + + def __init__(self, cmake_root: str): + self.cmake_root = Path(cmake_root).expanduser() + self.indent_unit = ' ' + self.indent_level = 0 + self.options = [] # type: T.List[tuple] + + def convert_args(self, args: T.List[Token], as_array: bool = True) -> str: + res = [] + if as_array: + start = '[' + end = ']' + else: + start = '' + end = '' + for i in args: + if i.tid == 'id': + res.append("'%s'" % i.value) + elif i.tid == 'varexp': + res.append('%s' % i.value.lower()) + elif i.tid == 'string': + res.append("'%s'" % i.value) + else: + raise ValueError(f'Unknown arg type {i.tid}') + if len(res) > 1: + return start + ', '.join(res) + end + if len(res) == 1: + return res[0] + return '' + + def write_entry(self, outfile: T.TextIO, t: Statement) -> None: + if t.name in Converter.ignored_funcs: + return + preincrement = 0 + postincrement = 0 + if t.name == '_': + line = t.args[0] + elif t.name == 'add_subdirectory': + line = "subdir('" + t.args[0].value + "')" + elif t.name == 'pkg_search_module' or t.name == 'pkg_search_modules': + varname = t.args[0].value.lower() + mods = ["dependency('%s')" % i.value for i in t.args[1:]] + if len(mods) == 1: + line = '{} = {}'.format(varname, mods[0]) + else: + line = '{} = [{}]'.format(varname, ', '.join(["'%s'" % i for i in mods])) + elif t.name == 'find_package': + line = "{}_dep = dependency('{}')".format(t.args[0].value, t.args[0].value) + elif t.name == 'find_library': + line = "{} = find_library('{}')".format(t.args[0].value.lower(), t.args[0].value) + elif t.name == 'add_executable': + line = '{}_exe = executable({})'.format(t.args[0].value, self.convert_args(t.args, False)) + elif t.name == 'add_library': + if t.args[1].value == 'SHARED': + libcmd = 'shared_library' + args = [t.args[0]] + t.args[2:] + elif t.args[1].value == 'STATIC': + libcmd = 'static_library' + args = [t.args[0]] + t.args[2:] + else: + libcmd = 'library' + args = t.args + line = '{}_lib = {}({})'.format(t.args[0].value, libcmd, self.convert_args(args, False)) + elif t.name == 'add_test': + line = 'test(%s)' % self.convert_args(t.args, False) + elif t.name == 'option': + optname = t.args[0].value + description = t.args[1].value + if len(t.args) > 2: + default = t.args[2].value + else: + default = None + self.options.append((optname, description, default)) + return + elif t.name == 'project': + pname = t.args[0].value + args = [pname] + for l in t.args[1:]: + l = l.value.lower() + if l == 'cxx': + l = 'cpp' + args.append(l) + args = ["'%s'" % i for i in args] + line = 'project(' + ', '.join(args) + ", default_options : ['default_library=static'])" + elif t.name == 'set': + varname = t.args[0].value.lower() + line = '{} = {}\n'.format(varname, self.convert_args(t.args[1:])) + elif t.name == 'if': + postincrement = 1 + try: + line = 'if %s' % self.convert_args(t.args, False) + except AttributeError: # complex if statements + line = t.name + for arg in t.args: + line += token_or_group(arg) + elif t.name == 'elseif': + preincrement = -1 + postincrement = 1 + try: + line = 'elif %s' % self.convert_args(t.args, False) + except AttributeError: # complex if statements + line = t.name + for arg in t.args: + line += token_or_group(arg) + elif t.name == 'else': + preincrement = -1 + postincrement = 1 + line = 'else' + elif t.name == 'endif': + preincrement = -1 + line = 'endif' + else: + line = '''# {}({})'''.format(t.name, self.convert_args(t.args)) + self.indent_level += preincrement + indent = self.indent_level * self.indent_unit + outfile.write(indent) + outfile.write(line) + if not(line.endswith('\n')): + outfile.write('\n') + self.indent_level += postincrement + + def convert(self, subdir: Path = None) -> None: + if not subdir: + subdir = self.cmake_root + cfile = Path(subdir).expanduser() / 'CMakeLists.txt' + try: + with cfile.open(encoding='utf-8') as f: + cmakecode = f.read() + except FileNotFoundError: + print('\nWarning: No CMakeLists.txt in', subdir, '\n', file=sys.stderr) + return + p = Parser(cmakecode) + with (subdir / 'meson.build').open('w', encoding='utf-8') as outfile: + for t in p.parse(): + if t.name == 'add_subdirectory': + # print('\nRecursing to subdir', + # self.cmake_root / t.args[0].value, + # '\n') + self.convert(subdir / t.args[0].value) + # print('\nReturning to', self.cmake_root, '\n') + self.write_entry(outfile, t) + if subdir == self.cmake_root and len(self.options) > 0: + self.write_options() + + def write_options(self) -> None: + filename = self.cmake_root / 'meson_options.txt' + with filename.open('w', encoding='utf-8') as optfile: + for o in self.options: + (optname, description, default) = o + if default is None: + typestr = '' + defaultstr = '' + else: + if default == 'OFF': + typestr = ' type : \'boolean\',' + default = 'false' + elif default == 'ON': + default = 'true' + typestr = ' type : \'boolean\',' + else: + typestr = ' type : \'string\',' + defaultstr = ' value : %s,' % default + line = "option({!r},{}{} description : '{}')\n".format(optname, + typestr, + defaultstr, + description) + optfile.write(line) + +if __name__ == '__main__': + p = argparse.ArgumentParser(description='Convert CMakeLists.txt to meson.build and meson_options.txt') + p.add_argument('cmake_root', help='CMake project root (where top-level CMakeLists.txt is)') + P = p.parse_args() + + Converter(P.cmake_root).convert() diff --git a/devtools/meson/tools/copy_files.py b/devtools/meson/tools/copy_files.py new file mode 100644 index 0000000..de25189 --- /dev/null +++ b/devtools/meson/tools/copy_files.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + + +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +''' +Copy files +''' + +import argparse +import shutil +import typing as T +from pathlib import Path + +PathLike = T.Union[Path,str] + +def copy_files(files: T.List[str], input_dir: PathLike, output_dir: PathLike) -> None: + if not input_dir: + raise ValueError(f'Input directory value is not set') + if not output_dir: + raise ValueError(f'Output directory value is not set') + + input_dir = Path(input_dir).resolve() + output_dir = Path(output_dir).resolve() + output_dir.mkdir(parents=True, exist_ok=True) + + for f in files: + if (input_dir/f).is_dir(): + shutil.copytree(input_dir/f, output_dir/f) + else: + shutil.copy2(input_dir/f, output_dir/f) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Copy files') + parser.add_argument('files', metavar='FILE', nargs='*') + parser.add_argument('-C', dest='input_dir', required=True) + parser.add_argument('--output-dir', required=True) + + args = parser.parse_args() + + copy_files(files=args.files, + input_dir=args.input_dir, + output_dir=args.output_dir) diff --git a/devtools/meson/tools/dircondenser.py b/devtools/meson/tools/dircondenser.py new file mode 100644 index 0000000..fa299e9 --- /dev/null +++ b/devtools/meson/tools/dircondenser.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + + +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +'''Renames test case directories using Git from this: + +1 something +3 other +3 foo +3 bar + +to this: + +1 something +2 other +3 foo +4 bar + +This directory must be run from source root as it touches run_unittests.py. +''' + +import typing as T +import os +import sys +import subprocess + +from glob import glob + +def get_entries() -> T.List[T.Tuple[int, str]]: + entries = [] + for e in glob('*'): + if not os.path.isdir(e): + raise SystemExit('Current directory must not contain any files.') + (number, rest) = e.split(' ', 1) + try: + numstr = int(number) + except ValueError: + raise SystemExit(f'Dir name {e} does not start with a number.') + entries.append((numstr, rest)) + entries.sort() + return entries + +def replace_source(sourcefile: str, replacements: T.List[T.Tuple[str, str]]) -> None: + with open(sourcefile, encoding='utf-8') as f: + contents = f.read() + for old_name, new_name in replacements: + contents = contents.replace(old_name, new_name) + with open(sourcefile, 'w', encoding='utf-8') as f: + f.write(contents) + +def condense(dirname: str) -> None: + curdir = os.getcwd() + os.chdir(dirname) + entries = get_entries() + replacements = [] + for _i, e in enumerate(entries): + i = _i + 1 + if e[0] != i: + old_name = str(e[0]) + ' ' + e[1] + new_name = str(i) + ' ' + e[1] + #print('git mv "%s" "%s"' % (old_name, new_name)) + subprocess.check_call(['git', 'mv', old_name, new_name]) + replacements.append((old_name, new_name)) + # update any appearances of old_name in expected stdout in test.json + json = os.path.join(new_name, 'test.json') + if os.path.isfile(json): + replace_source(json, [(old_name, new_name)]) + os.chdir(curdir) + replace_source('run_unittests.py', replacements) + replace_source('run_project_tests.py', replacements) + for f in glob('unittests/*.py'): + replace_source(f, replacements) + +if __name__ == '__main__': + if len(sys.argv) != 1: + raise SystemExit('This script takes no arguments.') + for d in glob('test cases/*'): + condense(d) diff --git a/devtools/meson/tools/regenerate_docs.py b/devtools/meson/tools/regenerate_docs.py new file mode 100644 index 0000000..6e4d8f9 --- /dev/null +++ b/devtools/meson/tools/regenerate_docs.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 + + +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +''' +Regenerate markdown docs by using `meson.py` from the root dir +''' + +import argparse +import os +import re +import subprocess +import sys +import textwrap +import json +import typing as T +from pathlib import Path +from urllib.request import urlopen + +PathLike = T.Union[Path,str] + +def _get_meson_output(root_dir: Path, args: T.List) -> str: + env = os.environ.copy() + env['COLUMNS'] = '80' + return subprocess.run([str(sys.executable), str(root_dir/'meson.py')] + args, check=True, capture_output=True, text=True, env=env).stdout.strip() + +def get_commands(help_output: str) -> T.Set[str]: + # Python's argument parser might put the command list to its own line. Or it might not. + assert(help_output.startswith('usage: ')) + lines = help_output.split('\n') + line1 = lines[0] + line2 = lines[1] + if '{' in line1: + cmndline = line1 + else: + assert('{' in line2) + cmndline = line2 + cmndstr = cmndline.split('{')[1] + assert('}' in cmndstr) + help_commands = set(cmndstr.split('}')[0].split(',')) + assert(len(help_commands) > 0) + return {c.strip() for c in help_commands} + +def get_commands_data(root_dir: Path) -> T.Dict[str, T.Any]: + usage_start_pattern = re.compile(r'^usage: ', re.MULTILINE) + positional_start_pattern = re.compile(r'^positional arguments:[\t ]*[\r\n]+', re.MULTILINE) + options_start_pattern = re.compile(r'^(optional arguments|options):[\t ]*[\r\n]+', re.MULTILINE) + commands_start_pattern = re.compile(r'^[A-Za-z ]*[Cc]ommands:[\t ]*[\r\n]+', re.MULTILINE) + + def get_next_start(iterators: T.Sequence[T.Any], end: T.Optional[int]) -> int: + return next((i.start() for i in iterators if i), end) + + def normalize_text(text: str) -> str: + # clean up formatting + out = text + out = re.sub(r'\r\n', r'\r', out, flags=re.MULTILINE) # replace newlines with a linux EOL + out = re.sub(r'^ +$', '', out, flags=re.MULTILINE) # remove trailing whitespace + out = re.sub(r'(?:^\n+|\n+$)', '', out) # remove trailing empty lines + return out + + def parse_cmd(cmd: str) -> T.Dict[str, str]: + cmd_len = len(cmd) + usage = usage_start_pattern.search(cmd) + positionals = positional_start_pattern.search(cmd) + options = options_start_pattern.search(cmd) + commands = commands_start_pattern.search(cmd) + + arguments_start = get_next_start([positionals, options, commands], None) + assert arguments_start + + # replace `usage:` with `$` and dedent + dedent_size = (usage.end() - usage.start()) - len('$ ') + usage_text = textwrap.dedent(f'{dedent_size * " "}$ {normalize_text(cmd[usage.end():arguments_start])}') + + return { + 'usage': usage_text, + 'arguments': normalize_text(cmd[arguments_start:cmd_len]), + } + + def clean_dir_arguments(text: str) -> str: + # Remove platform specific defaults + args = [ + 'prefix', + 'bindir', + 'datadir', + 'includedir', + 'infodir', + 'libdir', + 'libexecdir', + 'localedir', + 'localstatedir', + 'mandir', + 'sbindir', + 'sharedstatedir', + 'sysconfdir' + ] + out = text + for a in args: + out = re.sub(r'(--' + a + r' .+?)\s+\(default:.+?\)(\.)?', r'\1\2', out, flags=re.MULTILINE|re.DOTALL) + return out + + output = _get_meson_output(root_dir, ['--help']) + commands = get_commands(output) + commands.remove('help') + + cmd_data = dict() + + for cmd in commands: + cmd_output = _get_meson_output(root_dir, [cmd, '--help']) + cmd_data[cmd] = parse_cmd(cmd_output) + if cmd in ['setup', 'configure']: + cmd_data[cmd]['arguments'] = clean_dir_arguments(cmd_data[cmd]['arguments']) + + return cmd_data + +def generate_hotdoc_includes(root_dir: Path, output_dir: Path) -> None: + cmd_data = get_commands_data(root_dir) + + for cmd, parsed in cmd_data.items(): + for typ in parsed.keys(): + with open(output_dir / (cmd+'_'+typ+'.inc'), 'w', encoding='utf-8') as f: + f.write(parsed[typ]) + +def generate_wrapdb_table(output_dir: Path) -> None: + url = urlopen('https://wrapdb.mesonbuild.com/v2/releases.json') + releases = json.loads(url.read().decode()) + with open(output_dir / 'wrapdb-table.md', 'w', encoding='utf-8') as f: + f.write('| Project | Versions | Provided dependencies | Provided programs |\n') + f.write('| ------- | -------- | --------------------- | ----------------- |\n') + for name, info in releases.items(): + versions = [] + added_tags = set() + for v in info['versions']: + tag, build = v.rsplit('-', 1) + if tag not in added_tags: + added_tags.add(tag) + versions.append(f'[{v}](https://wrapdb.mesonbuild.com/v2/{name}_{v}/{name}.wrap)') + # Highlight latest version. + versions_str = f'**{versions[0]}**
' + ', '.join(versions[1:]) + dependency_names = info.get('dependency_names', []) + dependency_names_str = ', '.join(dependency_names) + program_names = info.get('program_names', []) + program_names_str = ', '.join(program_names) + f.write(f'| {name} | {versions_str} | {dependency_names_str} | {program_names_str} |\n') + +def regenerate_docs(output_dir: PathLike, + dummy_output_file: T.Optional[PathLike]) -> None: + if not output_dir: + raise ValueError(f'Output directory value is not set') + + output_dir = Path(output_dir).resolve() + output_dir.mkdir(parents=True, exist_ok=True) + + root_dir = Path(__file__).resolve().parent.parent + + generate_hotdoc_includes(root_dir, output_dir) + generate_wrapdb_table(output_dir) + + if dummy_output_file: + with open(output_dir/dummy_output_file, 'w', encoding='utf-8') as f: + f.write('dummy file for custom_target output') + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Generate meson docs') + parser.add_argument('--output-dir', required=True) + parser.add_argument('--dummy-output-file', type=str) + + args = parser.parse_args() + + regenerate_docs(output_dir=args.output_dir, + dummy_output_file=args.dummy_output_file) diff --git a/devtools/meson/tools/run_with_cov.py b/devtools/meson/tools/run_with_cov.py new file mode 100644 index 0000000..3f78efc --- /dev/null +++ b/devtools/meson/tools/run_with_cov.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# Copyright 2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import coverage +import os +import sys +from pathlib import Path + +root_path = Path(__file__).parent.parent.absolute() + +# Python magic so we can import mesonlib +sys.path.append(root_path.as_posix()) +from mesonbuild import mesonlib + +def generate_coveragerc() -> Path: + i_file = (root_path / 'data' / '.coveragerc.in') + o_file = (root_path / '.coveragerc') + raw = i_file.read_text(encoding='utf-8') + raw = raw.replace('@ROOT@', root_path.as_posix()) + o_file.write_text(raw, encoding='utf-8') + return o_file + +def main() -> int: + # Remove old run data + out_dir = root_path / '.coverage' + mesonlib.windows_proof_rmtree(out_dir.as_posix()) + out_dir.mkdir(parents=True, exist_ok=True) + + # Setup coverage + python_path = (root_path / 'ci').as_posix() + os.environ['PYTHONPATH'] = os.pathsep.join([python_path, os.environ.get('PYTHONPATH', '')]) + os.environ['COVERAGE_PROCESS_START'] = generate_coveragerc().as_posix() + coverage.process_startup() + + # Run the actual command + cmd = mesonlib.python_command + sys.argv[1:] + return subprocess.run(cmd, env=os.environ.copy()).returncode + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/devtools/meson/unittests/__init__.py b/devtools/meson/unittests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/unittests/allplatformstests.py b/devtools/meson/unittests/allplatformstests.py new file mode 100644 index 0000000..82bfca9 --- /dev/null +++ b/devtools/meson/unittests/allplatformstests.py @@ -0,0 +1,4782 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import re +import json +import tempfile +import textwrap +import os +import shutil +import platform +import pickle +import zipfile, tarfile +import sys +from unittest import mock, SkipTest, skipIf, skipUnless +from contextlib import contextmanager +from glob import glob +from pathlib import (PurePath, Path) +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + BuildDirLock, MachineChoice, is_windows, is_osx, is_cygwin, is_dragonflybsd, + is_sunos, windows_proof_rmtree, python_command, version_compare, split_args, quote_arg, + relpath, is_linux, git, search_version, do_conf_file, do_conf_str, default_prefix, + MesonException, EnvironmentException, OptionKey, + windows_proof_rm +) +from mesonbuild.programs import ExternalProgram + +from mesonbuild.compilers.mixins.clang import ClangCompiler +from mesonbuild.compilers.mixins.gnu import GnuCompiler +from mesonbuild.compilers.mixins.intel import IntelGnuLikeCompiler +from mesonbuild.compilers.c import VisualStudioCCompiler, ClangClCCompiler +from mesonbuild.compilers.cpp import VisualStudioCPPCompiler, ClangClCPPCompiler +from mesonbuild.compilers import ( + detect_static_linker, detect_c_compiler, compiler_from_language, + detect_compiler_for +) +from mesonbuild.linkers import linkers + +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +from mesonbuild.build import Target, ConfigurationData, Executable, SharedLibrary, StaticLibrary +from mesonbuild import mtest +import mesonbuild.modules.pkgconfig +from mesonbuild.scripts import destdir_join + +from mesonbuild.wrap.wrap import PackageDefinition, WrapException + +from run_tests import ( + Backend, exe_suffix, get_fake_env, get_convincing_fake_env_and_cc +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@contextmanager +def temp_filename(): + '''A context manager which provides a filename to an empty temporary file. + + On exit the file will be deleted. + ''' + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + yield filename + finally: + try: + os.remove(filename) + except OSError: + pass + +def git_init(project_dir): + # If a user has git configuration init.defaultBranch set we want to override that + with tempfile.TemporaryDirectory() as d: + out = git(['--version'], str(d))[1] + if version_compare(search_version(out), '>= 2.28'): + extra_cmd = ['--initial-branch', 'master'] + else: + extra_cmd = [] + + subprocess.check_call(['git', 'init'] + extra_cmd, cwd=project_dir, stdout=subprocess.DEVNULL) + subprocess.check_call(['git', 'config', + 'user.name', 'Author Person'], cwd=project_dir) + subprocess.check_call(['git', 'config', + 'user.email', 'teh_coderz@example.com'], cwd=project_dir) + _git_add_all(project_dir) + +def _git_add_all(project_dir): + subprocess.check_call('git add *', cwd=project_dir, shell=True, + stdout=subprocess.DEVNULL) + subprocess.check_call(['git', 'commit', '--no-gpg-sign', '-a', '-m', 'I am a project'], cwd=project_dir, + stdout=subprocess.DEVNULL) + +class AllPlatformTests(BasePlatformTests): + ''' + Tests that should run on all platforms + ''' + + def test_default_options_prefix(self): + ''' + Tests that setting a prefix in default_options in project() works. + Can't be an ordinary test because we pass --prefix to meson there. + https://github.com/mesonbuild/meson/issues/1349 + ''' + testdir = os.path.join(self.common_test_dir, '87 default options') + self.init(testdir, default_args=False, inprocess=True) + opts = self.introspect('--buildoptions') + for opt in opts: + if opt['name'] == 'prefix': + prefix = opt['value'] + break + else: + raise self.fail('Did not find option "prefix"') + self.assertEqual(prefix, '/absoluteprefix') + + def test_do_conf_file_preserve_newlines(self): + + def conf_file(in_data, confdata): + with temp_filename() as fin: + with open(fin, 'wb') as fobj: + fobj.write(in_data.encode('utf-8')) + with temp_filename() as fout: + do_conf_file(fin, fout, confdata, 'meson') + with open(fout, 'rb') as fobj: + return fobj.read().decode('utf-8') + + confdata = {'VAR': ('foo', 'bar')} + self.assertEqual(conf_file('@VAR@\n@VAR@\n', confdata), 'foo\nfoo\n') + self.assertEqual(conf_file('@VAR@\r\n@VAR@\r\n', confdata), 'foo\r\nfoo\r\n') + + def test_do_conf_file_by_format(self): + def conf_str(in_data, confdata, vformat): + (result, missing_variables, confdata_useless) = do_conf_str('configuration_file', in_data, confdata, variable_format = vformat) + return '\n'.join(result) + + def check_formats(confdata, result): + self.assertEqual(conf_str(['#mesondefine VAR'], confdata, 'meson'), result) + self.assertEqual(conf_str(['#cmakedefine VAR ${VAR}'], confdata, 'cmake'), result) + self.assertEqual(conf_str(['#cmakedefine VAR @VAR@'], confdata, 'cmake@'), result) + + confdata = ConfigurationData() + # Key error as they do not exists + check_formats(confdata, '/* #undef VAR */\n') + + # Check boolean + confdata.values = {'VAR': (False, 'description')} + check_formats(confdata, '#undef VAR\n') + confdata.values = {'VAR': (True, 'description')} + check_formats(confdata, '#define VAR\n') + + # Check string + confdata.values = {'VAR': ('value', 'description')} + check_formats(confdata, '#define VAR value\n') + + # Check integer + confdata.values = {'VAR': (10, 'description')} + check_formats(confdata, '#define VAR 10\n') + + # Check multiple string with cmake formats + confdata.values = {'VAR': ('value', 'description')} + self.assertEqual(conf_str(['#cmakedefine VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'), '#define VAR xxx value yyy value\n') + self.assertEqual(conf_str(['#define VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'), '#define VAR xxx value yyy value') + self.assertEqual(conf_str(['#cmakedefine VAR xxx ${VAR} yyy ${VAR}'], confdata, 'cmake'), '#define VAR xxx value yyy value\n') + self.assertEqual(conf_str(['#define VAR xxx ${VAR} yyy ${VAR}'], confdata, 'cmake'), '#define VAR xxx value yyy value') + + # Handles meson format exceptions + # Unknown format + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR xxx'], confdata, 'unknown_format') + # More than 2 params in mesondefine + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR xxx'], confdata, 'meson') + # Mismatched line with format + self.assertRaises(MesonException, conf_str, ['#cmakedefine VAR'], confdata, 'meson') + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'cmake') + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'cmake@') + # Dict value in confdata + confdata.values = {'VAR': (['value'], 'description')} + self.assertRaises(MesonException, conf_str, ['#mesondefine VAR'], confdata, 'meson') + + def test_absolute_prefix_libdir(self): + ''' + Tests that setting absolute paths for --prefix and --libdir work. Can't + be an ordinary test because these are set via the command-line. + https://github.com/mesonbuild/meson/issues/1341 + https://github.com/mesonbuild/meson/issues/1345 + ''' + testdir = os.path.join(self.common_test_dir, '87 default options') + # on Windows, /someabs is *not* an absolute path + prefix = 'x:/someabs' if is_windows() else '/someabs' + libdir = 'libdir' + extra_args = ['--prefix=' + prefix, + # This can just be a relative path, but we want to test + # that passing this as an absolute path also works + '--libdir=' + prefix + '/' + libdir] + self.init(testdir, extra_args=extra_args, default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + if opt['name'] == 'prefix': + self.assertEqual(prefix, opt['value']) + elif opt['name'] == 'libdir': + self.assertEqual(libdir, opt['value']) + + def test_libdir_can_be_outside_prefix(self): + ''' + Tests that libdir is allowed to be outside prefix. + Must be a unit test for obvious reasons. + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + # libdir being inside prefix is ok + if is_windows(): + args = ['--prefix', 'x:/opt', '--libdir', 'x:/opt/lib32'] + else: + args = ['--prefix', '/opt', '--libdir', '/opt/lib32'] + self.init(testdir, extra_args=args) + self.wipe() + # libdir not being inside prefix is ok too + if is_windows(): + args = ['--prefix', 'x:/usr', '--libdir', 'x:/opt/lib32'] + else: + args = ['--prefix', '/usr', '--libdir', '/opt/lib32'] + self.init(testdir, extra_args=args) + self.wipe() + # libdir can be outside prefix even when set via mesonconf + self.init(testdir) + if is_windows(): + self.setconf('-Dlibdir=x:/opt', will_build=False) + else: + self.setconf('-Dlibdir=/opt', will_build=False) + + def test_prefix_dependent_defaults(self): + ''' + Tests that configured directory paths are set to prefix dependent + defaults. + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + expected = { + '/opt': {'prefix': '/opt', + 'bindir': 'bin', 'datadir': 'share', 'includedir': 'include', + 'infodir': 'share/info', + 'libexecdir': 'libexec', 'localedir': 'share/locale', + 'localstatedir': 'var', 'mandir': 'share/man', + 'sbindir': 'sbin', 'sharedstatedir': 'com', + 'sysconfdir': 'etc'}, + '/usr': {'prefix': '/usr', + 'bindir': 'bin', 'datadir': 'share', 'includedir': 'include', + 'infodir': 'share/info', + 'libexecdir': 'libexec', 'localedir': 'share/locale', + 'localstatedir': '/var', 'mandir': 'share/man', + 'sbindir': 'sbin', 'sharedstatedir': '/var/lib', + 'sysconfdir': '/etc'}, + '/usr/local': {'prefix': '/usr/local', + 'bindir': 'bin', 'datadir': 'share', + 'includedir': 'include', 'infodir': 'share/info', + 'libexecdir': 'libexec', + 'localedir': 'share/locale', + 'localstatedir': '/var/local', 'mandir': 'share/man', + 'sbindir': 'sbin', 'sharedstatedir': '/var/local/lib', + 'sysconfdir': 'etc'}, + # N.B. We don't check 'libdir' as it's platform dependent, see + # default_libdir(): + } + + if default_prefix() == '/usr/local': + expected[None] = expected['/usr/local'] + + for prefix in expected: + args = [] + if prefix: + args += ['--prefix', prefix] + self.init(testdir, extra_args=args, default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + name = opt['name'] + value = opt['value'] + if name in expected[prefix]: + self.assertEqual(value, expected[prefix][name]) + self.wipe() + + def test_default_options_prefix_dependent_defaults(self): + ''' + Tests that setting a prefix in default_options in project() sets prefix + dependent defaults for other options, and that those defaults can + be overridden in default_options or by the command line. + ''' + testdir = os.path.join(self.common_test_dir, '163 default options prefix dependent defaults') + expected = { + '': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/sharedstate'}, + '--prefix=/usr': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/sharedstate'}, + '--sharedstatedir=/var/state': + {'prefix': '/usr', + 'sysconfdir': '/etc', + 'localstatedir': '/var', + 'sharedstatedir': '/var/state'}, + '--sharedstatedir=/var/state --prefix=/usr --sysconfdir=sysconf': + {'prefix': '/usr', + 'sysconfdir': 'sysconf', + 'localstatedir': '/var', + 'sharedstatedir': '/var/state'}, + } + for args in expected: + self.init(testdir, extra_args=args.split(), default_args=False) + opts = self.introspect('--buildoptions') + for opt in opts: + name = opt['name'] + value = opt['value'] + if name in expected[args]: + self.assertEqual(value, expected[args][name]) + self.wipe() + + def test_clike_get_library_dirs(self): + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + for d in cc.get_library_dirs(env): + self.assertTrue(os.path.exists(d)) + self.assertTrue(os.path.isdir(d)) + self.assertTrue(os.path.isabs(d)) + + def test_static_library_overwrite(self): + ''' + Tests that static libraries are never appended to, always overwritten. + Has to be a unit test because this involves building a project, + reconfiguring, and building it again so that `ar` is run twice on the + same static library. + https://github.com/mesonbuild/meson/issues/1355 + ''' + testdir = os.path.join(self.common_test_dir, '3 static') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + static_linker = detect_static_linker(env, cc) + if is_windows(): + raise SkipTest('https://github.com/mesonbuild/meson/issues/1526') + if not isinstance(static_linker, linkers.ArLinker): + raise SkipTest('static linker is not `ar`') + # Configure + self.init(testdir) + # Get name of static library + targets = self.introspect('--targets') + self.assertEqual(len(targets), 1) + libname = targets[0]['filename'][0] + # Build and get contents of static library + self.build() + before = self._run(['ar', 't', os.path.join(self.builddir, libname)]).split() + # Filter out non-object-file contents + before = [f for f in before if f.endswith(('.o', '.obj'))] + # Static library should contain only one object + self.assertEqual(len(before), 1, msg=before) + # Change the source to be built into the static library + self.setconf('-Dsource=libfile2.c') + self.build() + after = self._run(['ar', 't', os.path.join(self.builddir, libname)]).split() + # Filter out non-object-file contents + after = [f for f in after if f.endswith(('.o', '.obj'))] + # Static library should contain only one object + self.assertEqual(len(after), 1, msg=after) + # and the object must have changed + self.assertNotEqual(before, after) + + def test_static_compile_order(self): + ''' + Test that the order of files in a compiler command-line while compiling + and linking statically is deterministic. This can't be an ordinary test + case because we need to inspect the compiler database. + https://github.com/mesonbuild/meson/pull/951 + ''' + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + self.init(testdir) + compdb = self.get_compdb() + # Rules will get written out in this order + self.assertTrue(compdb[0]['file'].endswith("libfile.c")) + self.assertTrue(compdb[1]['file'].endswith("libfile2.c")) + self.assertTrue(compdb[2]['file'].endswith("libfile3.c")) + self.assertTrue(compdb[3]['file'].endswith("libfile4.c")) + # FIXME: We don't have access to the linker command + + def test_replace_unencodable_xml_chars(self): + ''' + Test that unencodable xml chars are replaced with their + printable representation + https://github.com/mesonbuild/meson/issues/9894 + ''' + # Create base string(\nHello Meson\n) to see valid chars are not replaced + base_string_invalid = '\n\x48\x65\x6c\x6c\x6f\x20\x4d\x65\x73\x6f\x6e\n' + base_string_valid = '\nHello Meson\n' + # Create invalid input from all known unencodable chars + invalid_string = ( + '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11' + '\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f' + '\x80\x81\x82\x83\x84\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f' + '\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e' + '\x9f\ufdd0\ufdd1\ufdd2\ufdd3\ufdd4\ufdd5\ufdd6\ufdd7\ufdd8' + '\ufdd9\ufdda\ufddb\ufddc\ufddd\ufdde\ufddf\ufde0\ufde1' + '\ufde2\ufde3\ufde4\ufde5\ufde6\ufde7\ufde8\ufde9\ufdea' + '\ufdeb\ufdec\ufded\ufdee\ufdef\ufffe\uffff') + if sys.maxunicode >= 0x10000: + invalid_string = invalid_string + ( + '\U0001fffe\U0001ffff\U0002fffe\U0002ffff' + '\U0003fffe\U0003ffff\U0004fffe\U0004ffff' + '\U0005fffe\U0005ffff\U0006fffe\U0006ffff' + '\U0007fffe\U0007ffff\U0008fffe\U0008ffff' + '\U0009fffe\U0009ffff\U000afffe\U000affff' + '\U000bfffe\U000bffff\U000cfffe\U000cffff' + '\U000dfffe\U000dffff\U000efffe\U000effff' + '\U000ffffe\U000fffff\U0010fffe\U0010ffff') + + valid_string = base_string_valid + repr(invalid_string)[1:-1] + base_string_valid + invalid_string = base_string_invalid + invalid_string + base_string_invalid + fixed_string = mtest.replace_unencodable_xml_chars(invalid_string) + self.assertEqual(fixed_string, valid_string) + + def test_replace_unencodable_xml_chars_unit(self): + ''' + Test that unencodable xml chars are replaced with their + printable representation + https://github.com/mesonbuild/meson/issues/9894 + ''' + if not shutil.which('xmllint'): + raise SkipTest('xmllint not installed') + testdir = os.path.join(self.unit_test_dir, '110 replace unencodable xml chars') + self.init(testdir) + tests_command_output = self.run_tests() + junit_xml_logs = Path(self.logdir, 'testlog.junit.xml') + subprocess.run(['xmllint', junit_xml_logs], check=True) + # Ensure command output and JSON / text logs are not mangled. + raw_output_sample = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b' + assert raw_output_sample in tests_command_output + text_log = Path(self.logdir, 'testlog.txt').read_text() + assert raw_output_sample in text_log + json_log = json.loads(Path(self.logdir, 'testlog.json').read_bytes()) + assert raw_output_sample in json_log['stdout'] + + def test_run_target_files_path(self): + ''' + Test that run_targets are run from the correct directory + https://github.com/mesonbuild/meson/issues/957 + ''' + testdir = os.path.join(self.common_test_dir, '51 run target') + self.init(testdir) + self.run_target('check_exists') + self.run_target('check-env') + self.run_target('check-env-ct') + + def test_run_target_subdir(self): + ''' + Test that run_targets are run from the correct directory + https://github.com/mesonbuild/meson/issues/957 + ''' + testdir = os.path.join(self.common_test_dir, '51 run target') + self.init(testdir) + self.run_target('textprinter') + + def test_install_introspection(self): + ''' + Tests that the Meson introspection API exposes install filenames correctly + https://github.com/mesonbuild/meson/issues/829 + ''' + if self.backend is not Backend.ninja: + raise SkipTest(f'{self.backend.name!r} backend can\'t install files') + testdir = os.path.join(self.common_test_dir, '8 install') + self.init(testdir) + intro = self.introspect('--targets') + if intro[0]['type'] == 'executable': + intro = intro[::-1] + self.assertPathListEqual(intro[0]['install_filename'], ['/usr/lib/libstat.a']) + self.assertPathListEqual(intro[1]['install_filename'], ['/usr/bin/prog' + exe_suffix]) + + def test_install_subdir_introspection(self): + ''' + Test that the Meson introspection API also contains subdir install information + https://github.com/mesonbuild/meson/issues/5556 + ''' + testdir = os.path.join(self.common_test_dir, '59 install subdir') + self.init(testdir) + intro = self.introspect('--installed') + expected = { + 'nested_elided/sub': 'share', + 'new_directory': 'share/new_directory', + 'sub/sub1': 'share/sub1', + 'sub1': 'share/sub1', + 'sub2': 'share/sub2', + 'sub3': '/usr/share/sub3', + 'sub_elided': 'share', + 'subdir/sub1': 'share/sub1', + 'subdir/sub_elided': 'share', + } + + self.assertEqual(len(intro), len(expected)) + + # Convert expected to PurePath + expected_converted = {PurePath(os.path.join(testdir, key)): PurePath(os.path.join(self.prefix, val)) for key, val in expected.items()} + intro_converted = {PurePath(key): PurePath(val) for key, val in intro.items()} + + for src, dst in expected_converted.items(): + self.assertIn(src, intro_converted) + self.assertEqual(dst, intro_converted[src]) + + def test_install_introspection_multiple_outputs(self): + ''' + Tests that the Meson introspection API exposes multiple install filenames correctly without crashing + https://github.com/mesonbuild/meson/pull/4555 + + Reverted to the first file only because of https://github.com/mesonbuild/meson/pull/4547#discussion_r244173438 + TODO Change the format to a list officially in a followup PR + ''' + if self.backend is not Backend.ninja: + raise SkipTest(f'{self.backend.name!r} backend can\'t install files') + testdir = os.path.join(self.common_test_dir, '140 custom target multiple outputs') + self.init(testdir) + intro = self.introspect('--targets') + if intro[0]['type'] == 'executable': + intro = intro[::-1] + self.assertPathListEqual(intro[0]['install_filename'], ['/usr/include/diff.h', '/usr/bin/diff.sh']) + self.assertPathListEqual(intro[1]['install_filename'], ['/opt/same.h', '/opt/same.sh']) + self.assertPathListEqual(intro[2]['install_filename'], ['/usr/include/first.h', None]) + self.assertPathListEqual(intro[3]['install_filename'], [None, '/usr/bin/second.sh']) + + def read_install_logs(self): + # Find logged files and directories + with Path(self.builddir, 'meson-logs', 'install-log.txt').open(encoding='utf-8') as f: + return list(map(lambda l: Path(l.strip()), + filter(lambda l: not l.startswith('#'), + f.readlines()))) + + def test_install_log_content(self): + ''' + Tests that the install-log.txt is consistent with the installed files and directories. + Specifically checks that the log file only contains one entry per file/directory. + https://github.com/mesonbuild/meson/issues/4499 + ''' + testdir = os.path.join(self.common_test_dir, '59 install subdir') + self.init(testdir) + self.install() + installpath = Path(self.installdir) + # Find installed files and directories + expected = {installpath: 0} + for name in installpath.rglob('*'): + expected[name] = 0 + logged = self.read_install_logs() + for name in logged: + self.assertTrue(name in expected, f'Log contains extra entry {name}') + expected[name] += 1 + + for name, count in expected.items(): + self.assertGreater(count, 0, f'Log is missing entry for {name}') + self.assertLess(count, 2, f'Log has multiple entries for {name}') + + # Verify that with --dry-run we obtain the same logs but with nothing + # actually installed + windows_proof_rmtree(self.installdir) + self._run(self.meson_command + ['install', '--dry-run', '--destdir', self.installdir], workdir=self.builddir) + self.assertEqual(logged, self.read_install_logs()) + self.assertFalse(os.path.exists(self.installdir)) + + # If destdir is relative to build directory it should install + # exactly the same files. + rel_installpath = os.path.relpath(self.installdir, self.builddir) + self._run(self.meson_command + ['install', '--dry-run', '--destdir', rel_installpath, '-C', self.builddir]) + self.assertEqual(logged, self.read_install_logs()) + + def test_uninstall(self): + exename = os.path.join(self.installdir, 'usr/bin/prog' + exe_suffix) + dirname = os.path.join(self.installdir, 'usr/share/dir') + testdir = os.path.join(self.common_test_dir, '8 install') + self.init(testdir) + self.assertPathDoesNotExist(exename) + self.install() + self.assertPathExists(exename) + self.uninstall() + self.assertPathDoesNotExist(exename) + self.assertPathDoesNotExist(dirname) + + def test_forcefallback(self): + testdir = os.path.join(self.unit_test_dir, '31 forcefallback') + self.init(testdir, extra_args=['--wrap-mode=forcefallback']) + self.build() + self.run_tests() + + def test_implicit_forcefallback(self): + testdir = os.path.join(self.unit_test_dir, '96 implicit force fallback') + with self.assertRaises(subprocess.CalledProcessError): + self.init(testdir) + self.init(testdir, extra_args=['--wrap-mode=forcefallback']) + self.new_builddir() + self.init(testdir, extra_args=['--force-fallback-for=something']) + + def test_nopromote(self): + testdir = os.path.join(self.common_test_dir, '98 subproject subdir') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--wrap-mode=nopromote']) + self.assertIn('dependency subsub found: NO', cm.exception.stdout) + + def test_force_fallback_for(self): + testdir = os.path.join(self.unit_test_dir, '31 forcefallback') + self.init(testdir, extra_args=['--force-fallback-for=zlib,foo']) + self.build() + self.run_tests() + + def test_force_fallback_for_nofallback(self): + testdir = os.path.join(self.unit_test_dir, '31 forcefallback') + self.init(testdir, extra_args=['--force-fallback-for=zlib,foo', '--wrap-mode=nofallback']) + self.build() + self.run_tests() + + def test_testrepeat(self): + testdir = os.path.join(self.common_test_dir, '206 tap tests') + self.init(testdir) + self.build() + self._run(self.mtest_command + ['--repeat=2']) + + def test_verbose(self): + testdir = os.path.join(self.common_test_dir, '206 tap tests') + self.init(testdir) + self.build() + out = self._run(self.mtest_command + ['--suite', 'verbose']) + self.assertIn('1/1 subtest 1', out) + + def test_long_output(self): + testdir = os.path.join(self.common_test_dir, '254 long output') + self.init(testdir) + self.build() + self.run_tests() + + # Ensure lines are found from testlog.txt when not being verbose. + + i = 1 + with open(os.path.join(self.logdir, 'testlog.txt'), encoding='utf-8') as f: + line = f.readline() + while line and i < 100001: + if f'# Iteration {i} to stdout' in line: + i += 1 + line = f.readline() + self.assertEqual(i, 100001) + + i = 1 + while line: + if f'# Iteration {i} to stderr' in line: + i += 1 + line = f.readline() + self.assertEqual(i, 100001) + + # Ensure lines are found from both testlog.txt and console when being verbose. + + out = self._run(self.mtest_command + ['-v']) + i = 1 + with open(os.path.join(self.logdir, 'testlog.txt'), encoding='utf-8') as f: + line = f.readline() + while line and i < 100001: + if f'# Iteration {i} to stdout' in line: + i += 1 + line = f.readline() + self.assertEqual(i, 100001) + + i = 1 + while line: + if f'# Iteration {i} to stderr' in line: + i += 1 + line = f.readline() + self.assertEqual(i, 100001) + + lines = out.split('\n') + line_number = 0 + i = 1 + while line_number < len(lines) and i < 100001: + print('---> %s' % lines[line_number]) + if f'# Iteration {i} to stdout' in lines[line_number]: + i += 1 + line_number += 1 + self.assertEqual(i, 100001) + + line_number = 0 + i = 1 + while line_number < len(lines): + if f'# Iteration {i} to stderr' in lines[line_number]: + i += 1 + line_number += 1 + self.assertEqual(i, 100001) + + + def test_testsetups(self): + if not shutil.which('valgrind'): + raise SkipTest('Valgrind not installed.') + testdir = os.path.join(self.unit_test_dir, '2 testsetups') + self.init(testdir) + self.build() + # Run tests without setup + self.run_tests() + with open(os.path.join(self.logdir, 'testlog.txt'), encoding='utf-8') as f: + basic_log = f.read() + # Run buggy test with setup that has env that will make it fail + self.assertRaises(subprocess.CalledProcessError, + self._run, self.mtest_command + ['--setup=valgrind']) + with open(os.path.join(self.logdir, 'testlog-valgrind.txt'), encoding='utf-8') as f: + vg_log = f.read() + self.assertNotIn('TEST_ENV is set', basic_log) + self.assertNotIn('Memcheck', basic_log) + self.assertIn('TEST_ENV is set', vg_log) + self.assertIn('Memcheck', vg_log) + # Run buggy test with setup without env that will pass + self._run(self.mtest_command + ['--setup=wrapper']) + # Setup with no properties works + self._run(self.mtest_command + ['--setup=empty']) + # Setup with only env works + self._run(self.mtest_command + ['--setup=onlyenv']) + self._run(self.mtest_command + ['--setup=onlyenv2']) + self._run(self.mtest_command + ['--setup=onlyenv3']) + # Setup with only a timeout works + self._run(self.mtest_command + ['--setup=timeout']) + # Setup that does not define a wrapper works with --wrapper + self._run(self.mtest_command + ['--setup=timeout', '--wrapper', shutil.which('valgrind')]) + # Setup that skips test works + self._run(self.mtest_command + ['--setup=good']) + with open(os.path.join(self.logdir, 'testlog-good.txt'), encoding='utf-8') as f: + exclude_suites_log = f.read() + self.assertNotIn('buggy', exclude_suites_log) + # --suite overrides add_test_setup(exclude_suites) + self._run(self.mtest_command + ['--setup=good', '--suite', 'buggy']) + with open(os.path.join(self.logdir, 'testlog-good.txt'), encoding='utf-8') as f: + include_suites_log = f.read() + self.assertIn('buggy', include_suites_log) + + def test_testsetup_selection(self): + testdir = os.path.join(self.unit_test_dir, '14 testsetup selection') + self.init(testdir) + self.build() + + # Run tests without setup + self.run_tests() + + self.assertRaises(subprocess.CalledProcessError, self._run, self.mtest_command + ['--setup=missingfromfoo']) + self._run(self.mtest_command + ['--setup=missingfromfoo', '--no-suite=foo:']) + + self._run(self.mtest_command + ['--setup=worksforall']) + self._run(self.mtest_command + ['--setup=main:worksforall']) + + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=onlyinbar']) + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=onlyinbar', '--no-suite=main:']) + self._run(self.mtest_command + ['--setup=onlyinbar', '--no-suite=main:', '--no-suite=foo:']) + self._run(self.mtest_command + ['--setup=bar:onlyinbar']) + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=foo:onlyinbar']) + self.assertRaises(subprocess.CalledProcessError, self._run, + self.mtest_command + ['--setup=main:onlyinbar']) + + def test_testsetup_default(self): + testdir = os.path.join(self.unit_test_dir, '48 testsetup default') + self.init(testdir) + self.build() + + # Run tests without --setup will cause the default setup to be used + self.run_tests() + with open(os.path.join(self.logdir, 'testlog.txt'), encoding='utf-8') as f: + default_log = f.read() + + # Run tests with explicitly using the same setup that is set as default + self._run(self.mtest_command + ['--setup=mydefault']) + with open(os.path.join(self.logdir, 'testlog-mydefault.txt'), encoding='utf-8') as f: + mydefault_log = f.read() + + # Run tests with another setup + self._run(self.mtest_command + ['--setup=other']) + with open(os.path.join(self.logdir, 'testlog-other.txt'), encoding='utf-8') as f: + other_log = f.read() + + self.assertIn('ENV_A is 1', default_log) + self.assertIn('ENV_B is 2', default_log) + self.assertIn('ENV_C is 2', default_log) + + self.assertIn('ENV_A is 1', mydefault_log) + self.assertIn('ENV_B is 2', mydefault_log) + self.assertIn('ENV_C is 2', mydefault_log) + + self.assertIn('ENV_A is 1', other_log) + self.assertIn('ENV_B is 3', other_log) + self.assertIn('ENV_C is 2', other_log) + + def assertFailedTestCount(self, failure_count, command): + try: + self._run(command) + self.assertEqual(0, failure_count, 'Expected %d tests to fail.' % failure_count) + except subprocess.CalledProcessError as e: + self.assertEqual(e.returncode, failure_count) + + def test_suite_selection(self): + testdir = os.path.join(self.unit_test_dir, '4 suite selection') + self.init(testdir) + self.build() + + self.assertFailedTestCount(4, self.mtest_command) + + self.assertFailedTestCount(0, self.mtest_command + ['--suite', ':success']) + self.assertFailedTestCount(3, self.mtest_command + ['--suite', ':fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', ':success']) + self.assertFailedTestCount(1, self.mtest_command + ['--no-suite', ':fail']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc']) + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail']) + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'mainprj:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'mainprj:success']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'mainprj:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'mainprj:success']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjfail:success']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjfail:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjfail:success']) + + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjsucc:success']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjsucc:success']) + + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjmix:fail']) + self.assertFailedTestCount(0, self.mtest_command + ['--suite', 'subprjmix:success']) + self.assertFailedTestCount(3, self.mtest_command + ['--no-suite', 'subprjmix:fail']) + self.assertFailedTestCount(4, self.mtest_command + ['--no-suite', 'subprjmix:success']) + + self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix:fail']) + self.assertFailedTestCount(3, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj']) + self.assertFailedTestCount(2, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail']) + self.assertFailedTestCount(1, self.mtest_command + ['--suite', 'subprjfail', '--suite', 'subprjmix', '--suite', 'mainprj', '--no-suite', 'subprjmix:fail', 'mainprj-failing_test']) + + self.assertFailedTestCount(2, self.mtest_command + ['--no-suite', 'subprjfail:fail', '--no-suite', 'subprjmix:fail']) + + def test_mtest_reconfigure(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'mtest can\'t rebuild with {self.backend.name!r}') + + testdir = os.path.join(self.common_test_dir, '206 tap tests') + self.init(testdir) + self.utime(os.path.join(testdir, 'meson.build')) + o = self._run(self.mtest_command + ['--list']) + self.assertIn('Regenerating build files.', o) + self.assertIn('test_features / xfail', o) + o = self._run(self.mtest_command + ['--list']) + self.assertNotIn('Regenerating build files.', o) + # no real targets should have been built + tester = os.path.join(self.builddir, 'tester' + exe_suffix) + self.assertPathDoesNotExist(tester) + # check that we don't reconfigure if --no-rebuild is passed + self.utime(os.path.join(testdir, 'meson.build')) + o = self._run(self.mtest_command + ['--list', '--no-rebuild']) + self.assertNotIn('Regenerating build files.', o) + + def test_unexisting_test_name(self): + testdir = os.path.join(self.unit_test_dir, '4 suite selection') + self.init(testdir) + self.build() + + self.assertRaises(subprocess.CalledProcessError, self._run, self.mtest_command + ['notatest']) + + def test_select_test_using_wildcards(self): + testdir = os.path.join(self.unit_test_dir, '4 suite selection') + self.init(testdir) + self.build() + + o = self._run(self.mtest_command + ['--list', 'mainprj*']) + self.assertIn('mainprj-failing_test', o) + self.assertIn('mainprj-successful_test_no_suite', o) + self.assertNotIn('subprj', o) + + o = self._run(self.mtest_command + ['--list', '*succ*', 'subprjm*:']) + self.assertIn('mainprj-successful_test_no_suite', o) + self.assertIn('subprjmix-failing_test', o) + self.assertIn('subprjmix-successful_test', o) + self.assertIn('subprjsucc-successful_test_no_suite', o) + self.assertNotIn('subprjfail-failing_test', o) + + def test_build_by_default(self): + testdir = os.path.join(self.common_test_dir, '129 build by default') + self.init(testdir) + self.build() + genfile1 = os.path.join(self.builddir, 'generated1.dat') + genfile2 = os.path.join(self.builddir, 'generated2.dat') + exe1 = os.path.join(self.builddir, 'fooprog' + exe_suffix) + exe2 = os.path.join(self.builddir, 'barprog' + exe_suffix) + self.assertPathExists(genfile1) + self.assertPathExists(genfile2) + self.assertPathDoesNotExist(exe1) + self.assertPathDoesNotExist(exe2) + self.build(target=('fooprog' + exe_suffix)) + self.assertPathExists(exe1) + self.build(target=('barprog' + exe_suffix)) + self.assertPathExists(exe2) + + def test_build_generated_pyx_directly(self): + # Check that the transpile stage also includes + # dependencies for the compilation stage as dependencies + testdir = os.path.join("test cases/cython", '2 generated sources') + env = get_fake_env(testdir, self.builddir, self.prefix) + try: + detect_compiler_for(env, "cython", MachineChoice.HOST, True) + except EnvironmentException: + raise SkipTest("Cython is not installed") + self.init(testdir) + # Need to get the full target name of the pyx.c target + # (which is unfortunately not provided by introspection :( ) + # We'll need to dig into the generated sources + targets = self.introspect('--targets') + name = None + for target in targets: + for target_sources in target["target_sources"]: + for generated_source in target_sources.get("generated_sources", []): + if "includestuff.pyx.c" in generated_source: + name = generated_source + break + # Split the path (we only want the includestuff.cpython-blahblah.so.p/includestuff.pyx.c) + name = os.path.normpath(name).split(os.sep)[-2:] + name = os.sep.join(name) # Glue list into a string + self.build(target=name) + + def test_build_pyx_depfiles(self): + # building regularly and then touching a depfile dependency should rebuild + testdir = os.path.join("test cases/cython", '2 generated sources') + env = get_fake_env(testdir, self.builddir, self.prefix) + try: + cython = detect_compiler_for(env, "cython", MachineChoice.HOST, True) + if not version_compare(cython.version, '>=0.29.33'): + raise SkipTest('Cython is too old') + except EnvironmentException: + raise SkipTest("Cython is not installed") + self.init(testdir) + + targets = self.introspect('--targets') + for target in targets: + if target['name'].startswith('simpleinclude'): + name = target['name'] + self.build() + self.utime(os.path.join(testdir, 'simplestuff.pxi')) + self.assertBuildRelinkedOnlyTarget(name) + + + def test_internal_include_order(self): + if mesonbuild.environment.detect_msys2_arch() and ('MESON_RSP_THRESHOLD' in os.environ): + raise SkipTest('Test does not yet support gcc rsp files on msys2') + + testdir = os.path.join(self.common_test_dir, '130 include order') + self.init(testdir) + execmd = fxecmd = None + for cmd in self.get_compdb(): + if 'someexe' in cmd['command']: + execmd = cmd['command'] + continue + if 'somefxe' in cmd['command']: + fxecmd = cmd['command'] + continue + if not execmd or not fxecmd: + raise Exception('Could not find someexe and somfxe commands') + # Check include order for 'someexe' + incs = [a for a in split_args(execmd) if a.startswith("-I")] + self.assertEqual(len(incs), 9) + # Need to run the build so the private dir is created. + self.build() + pdirs = glob(os.path.join(self.builddir, 'sub4/someexe*.p')) + self.assertEqual(len(pdirs), 1) + privdir = pdirs[0][len(self.builddir)+1:] + self.assertPathEqual(incs[0], "-I" + privdir) + # target build subdir + self.assertPathEqual(incs[1], "-Isub4") + # target source subdir + self.assertPathBasenameEqual(incs[2], 'sub4') + # include paths added via per-target c_args: ['-I'...] + self.assertPathBasenameEqual(incs[3], 'sub3') + # target include_directories: build dir + self.assertPathEqual(incs[4], "-Isub2") + # target include_directories: source dir + self.assertPathBasenameEqual(incs[5], 'sub2') + # target internal dependency include_directories: build dir + self.assertPathEqual(incs[6], "-Isub1") + # target internal dependency include_directories: source dir + self.assertPathBasenameEqual(incs[7], 'sub1') + # custom target include dir + self.assertPathEqual(incs[8], '-Ictsub') + # Check include order for 'somefxe' + incs = [a for a in split_args(fxecmd) if a.startswith('-I')] + self.assertEqual(len(incs), 9) + # target private dir + pdirs = glob(os.path.join(self.builddir, 'somefxe*.p')) + self.assertEqual(len(pdirs), 1) + privdir = pdirs[0][len(self.builddir)+1:] + self.assertPathEqual(incs[0], '-I' + privdir) + # target build dir + self.assertPathEqual(incs[1], '-I.') + # target source dir + self.assertPathBasenameEqual(incs[2], os.path.basename(testdir)) + # target internal dependency correct include_directories: build dir + self.assertPathEqual(incs[3], "-Isub4") + # target internal dependency correct include_directories: source dir + self.assertPathBasenameEqual(incs[4], 'sub4') + # target internal dependency dep include_directories: build dir + self.assertPathEqual(incs[5], "-Isub1") + # target internal dependency dep include_directories: source dir + self.assertPathBasenameEqual(incs[6], 'sub1') + # target internal dependency wrong include_directories: build dir + self.assertPathEqual(incs[7], "-Isub2") + # target internal dependency wrong include_directories: source dir + self.assertPathBasenameEqual(incs[8], 'sub2') + + def test_compiler_detection(self): + ''' + Test that automatic compiler detection and setting from the environment + both work just fine. This is needed because while running project tests + and other unit tests, we always read CC/CXX/etc from the environment. + ''' + gnu = GnuCompiler + clang = ClangCompiler + intel = IntelGnuLikeCompiler + msvc = (VisualStudioCCompiler, VisualStudioCPPCompiler) + clangcl = (ClangClCCompiler, ClangClCPPCompiler) + ar = linkers.ArLinker + lib = linkers.VisualStudioLinker + langs = [('c', 'CC'), ('cpp', 'CXX')] + if not is_windows() and platform.machine().lower() != 'e2k': + langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')] + testdir = os.path.join(self.unit_test_dir, '5 compiler detection') + env = get_fake_env(testdir, self.builddir, self.prefix) + for lang, evar in langs: + # Detect with evar and do sanity checks on that + if evar in os.environ: + ecc = compiler_from_language(env, lang, MachineChoice.HOST) + self.assertTrue(ecc.version) + elinker = detect_static_linker(env, ecc) + # Pop it so we don't use it for the next detection + evalue = os.environ.pop(evar) + # Very rough/strict heuristics. Would never work for actual + # compiler detection, but should be ok for the tests. + ebase = os.path.basename(evalue) + if ebase.startswith('g') or ebase.endswith(('-gcc', '-g++')): + self.assertIsInstance(ecc, gnu) + self.assertIsInstance(elinker, ar) + elif 'clang-cl' in ebase: + self.assertIsInstance(ecc, clangcl) + self.assertIsInstance(elinker, lib) + elif 'clang' in ebase: + self.assertIsInstance(ecc, clang) + self.assertIsInstance(elinker, ar) + elif ebase.startswith('ic'): + self.assertIsInstance(ecc, intel) + self.assertIsInstance(elinker, ar) + elif ebase.startswith('cl'): + self.assertIsInstance(ecc, msvc) + self.assertIsInstance(elinker, lib) + else: + raise AssertionError(f'Unknown compiler {evalue!r}') + # Check that we actually used the evalue correctly as the compiler + self.assertEqual(ecc.get_exelist(), split_args(evalue)) + # Do auto-detection of compiler based on platform, PATH, etc. + cc = compiler_from_language(env, lang, MachineChoice.HOST) + self.assertTrue(cc.version) + linker = detect_static_linker(env, cc) + # Check compiler type + if isinstance(cc, gnu): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) + elif is_sunos(): + self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin)) + else: + self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin) + if isinstance(cc, clangcl): + self.assertIsInstance(linker, lib) + self.assertIsInstance(cc.linker, linkers.ClangClDynamicLinker) + if isinstance(cc, clang): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) + elif is_windows(): + # This is clang, not clang-cl. This can be either an + # ld-like linker of link.exe-like linker (usually the + # former for msys2, the latter otherwise) + self.assertIsInstance(cc.linker, (linkers.MSVCDynamicLinker, linkers.GnuLikeDynamicLinkerMixin)) + else: + self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin) + if isinstance(cc, intel): + self.assertIsInstance(linker, ar) + if is_osx(): + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) + elif is_windows(): + self.assertIsInstance(cc.linker, linkers.XilinkDynamicLinker) + else: + self.assertIsInstance(cc.linker, linkers.GnuDynamicLinker) + if isinstance(cc, msvc): + self.assertTrue(is_windows()) + self.assertIsInstance(linker, lib) + self.assertEqual(cc.id, 'msvc') + self.assertTrue(hasattr(cc, 'is_64')) + self.assertIsInstance(cc.linker, linkers.MSVCDynamicLinker) + # If we're on Windows CI, we know what the compiler will be + if 'arch' in os.environ: + if os.environ['arch'] == 'x64': + self.assertTrue(cc.is_64) + else: + self.assertFalse(cc.is_64) + # Set evar ourselves to a wrapper script that just calls the same + # exelist + some argument. This is meant to test that setting + # something like `ccache gcc -pipe` or `distcc ccache gcc` works. + wrapper = os.path.join(testdir, 'compiler wrapper.py') + wrappercc = python_command + [wrapper] + cc.get_exelist() + ['-DSOME_ARG'] + os.environ[evar] = ' '.join(quote_arg(w) for w in wrappercc) + + # Check static linker too + wrapperlinker = python_command + [wrapper] + linker.get_exelist() + linker.get_always_args() + os.environ['AR'] = ' '.join(quote_arg(w) for w in wrapperlinker) + + # Need a new env to re-run environment loading + env = get_fake_env(testdir, self.builddir, self.prefix) + + wcc = compiler_from_language(env, lang, MachineChoice.HOST) + wlinker = detect_static_linker(env, wcc) + # Pop it so we don't use it for the next detection + os.environ.pop('AR') + # Must be the same type since it's a wrapper around the same exelist + self.assertIs(type(cc), type(wcc)) + self.assertIs(type(linker), type(wlinker)) + # Ensure that the exelist is correct + self.assertEqual(wcc.get_exelist(), wrappercc) + self.assertEqual(wlinker.get_exelist(), wrapperlinker) + # Ensure that the version detection worked correctly + self.assertEqual(cc.version, wcc.version) + if hasattr(cc, 'is_64'): + self.assertEqual(cc.is_64, wcc.is_64) + + def test_always_prefer_c_compiler_for_asm(self): + testdir = os.path.join(self.common_test_dir, '133 c cpp and asm') + # Skip if building with MSVC + env = get_fake_env(testdir, self.builddir, self.prefix) + if detect_c_compiler(env, MachineChoice.HOST).get_id() == 'msvc': + raise SkipTest('MSVC can\'t compile assembly') + self.init(testdir) + commands = {'c-asm': {}, 'cpp-asm': {}, 'cpp-c-asm': {}, 'c-cpp-asm': {}} + for cmd in self.get_compdb(): + # Get compiler + split = split_args(cmd['command']) + if split[0] in ('ccache', 'sccache'): + compiler = split[1] + else: + compiler = split[0] + # Classify commands + if 'Ic-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['c-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['c-asm']['c'] = compiler + else: + raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) + elif 'Icpp-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['cpp-asm']['asm'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['cpp-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in cpp-asm?'.format(cmd['command'])) + elif 'Ic-cpp-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['c-cpp-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['c-cpp-asm']['c'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['c-cpp-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in c-cpp-asm?'.format(cmd['command'])) + elif 'Icpp-c-asm' in cmd['command']: + if cmd['file'].endswith('.S'): + commands['cpp-c-asm']['asm'] = compiler + elif cmd['file'].endswith('.c'): + commands['cpp-c-asm']['c'] = compiler + elif cmd['file'].endswith('.cpp'): + commands['cpp-c-asm']['cpp'] = compiler + else: + raise AssertionError('{!r} found in cpp-c-asm?'.format(cmd['command'])) + else: + raise AssertionError('Unknown command {!r} found'.format(cmd['command'])) + # Check that .S files are always built with the C compiler + self.assertEqual(commands['c-asm']['asm'], commands['c-asm']['c']) + self.assertEqual(commands['c-asm']['asm'], commands['cpp-asm']['asm']) + self.assertEqual(commands['cpp-asm']['asm'], commands['c-cpp-asm']['c']) + self.assertEqual(commands['c-cpp-asm']['asm'], commands['c-cpp-asm']['c']) + self.assertEqual(commands['cpp-c-asm']['asm'], commands['cpp-c-asm']['c']) + self.assertNotEqual(commands['cpp-asm']['asm'], commands['cpp-asm']['cpp']) + self.assertNotEqual(commands['c-cpp-asm']['c'], commands['c-cpp-asm']['cpp']) + self.assertNotEqual(commands['cpp-c-asm']['c'], commands['cpp-c-asm']['cpp']) + # Check that the c-asm target is always linked with the C linker + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('build c-asm.*: c_LINKER', contents) + self.assertIsNotNone(m, msg=contents) + + def test_preprocessor_checks_CPPFLAGS(self): + ''' + Test that preprocessor compiler checks read CPPFLAGS and also CFLAGS/CXXFLAGS but + not LDFLAGS. + ''' + testdir = os.path.join(self.common_test_dir, '132 get define') + define = 'MESON_TEST_DEFINE_VALUE' + # NOTE: this list can't have \n, ' or " + # \n is never substituted by the GNU pre-processor via a -D define + # ' and " confuse split_args() even when they are escaped + # % and # confuse the MSVC preprocessor + # !, ^, *, and < confuse lcc preprocessor + value = 'spaces and fun@$&()-=_+{}[]:;>?,./~`' + for env_var in [{'CPPFLAGS'}, {'CFLAGS', 'CXXFLAGS'}]: + env = {} + for i in env_var: + env[i] = f'-D{define}="{value}"' + env['LDFLAGS'] = '-DMESON_FAIL_VALUE=cflags-read' + self.init(testdir, extra_args=[f'-D{define}={value}'], override_envvars=env) + self.new_builddir() + + def test_custom_target_exe_data_deterministic(self): + testdir = os.path.join(self.common_test_dir, '109 custom target capture') + self.init(testdir) + meson_exe_dat1 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) + self.wipe() + self.init(testdir) + meson_exe_dat2 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) + self.assertListEqual(meson_exe_dat1, meson_exe_dat2) + + def test_noop_changes_cause_no_rebuilds(self): + ''' + Test that no-op changes to the build files such as mtime do not cause + a rebuild of anything. + ''' + testdir = os.path.join(self.common_test_dir, '6 linkshared') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of meson.build should not rebuild anything + self.utime(os.path.join(testdir, 'meson.build')) + self.assertReconfiguredBuildIsNoop() + # Changing mtime of libefile.c should rebuild the library, but not relink the executable + self.utime(os.path.join(testdir, 'libfile.c')) + self.assertBuildRelinkedOnlyTarget('mylib') + + def test_source_changes_cause_rebuild(self): + ''' + Test that changes to sources and headers cause rebuilds, but not + changes to unused files (as determined by the dependency file) in the + input files list. + ''' + testdir = os.path.join(self.common_test_dir, '19 header in file list') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of header.h should rebuild everything + self.utime(os.path.join(testdir, 'header.h')) + self.assertBuildRelinkedOnlyTarget('prog') + + def test_custom_target_changes_cause_rebuild(self): + ''' + Test that in a custom target, changes to the input files, the + ExternalProgram, and any File objects on the command-line cause + a rebuild. + ''' + testdir = os.path.join(self.common_test_dir, '57 custom header generator') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of these should rebuild everything + for f in ('input.def', 'makeheader.py', 'somefile.txt'): + self.utime(os.path.join(testdir, f)) + self.assertBuildRelinkedOnlyTarget('prog') + + def test_source_generator_program_cause_rebuild(self): + ''' + Test that changes to generator programs in the source tree cause + a rebuild. + ''' + testdir = os.path.join(self.common_test_dir, '90 gen extra') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of generator should rebuild the executable + self.utime(os.path.join(testdir, 'srcgen.py')) + self.assertRebuiltTarget('basic') + + def test_static_library_lto(self): + ''' + Test that static libraries can be built with LTO and linked to + executables. On Linux, this requires the use of gcc-ar. + https://github.com/mesonbuild/meson/issues/1646 + ''' + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + + env = get_fake_env(testdir, self.builddir, self.prefix) + if detect_c_compiler(env, MachineChoice.HOST).get_id() == 'clang' and is_windows(): + raise SkipTest('LTO not (yet) supported by windows clang') + + self.init(testdir, extra_args='-Db_lto=true') + self.build() + self.run_tests() + + @skip_if_not_base_option('b_lto_threads') + def test_lto_threads(self): + testdir = os.path.join(self.common_test_dir, '6 linkshared') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + extra_args: T.List[str] = [] + if cc.get_id() == 'clang': + if is_windows(): + raise SkipTest('LTO not (yet) supported by windows clang') + + self.init(testdir, extra_args=['-Db_lto=true', '-Db_lto_threads=8'] + extra_args) + self.build() + self.run_tests() + + expected = set(cc.get_lto_compile_args(threads=8)) + targets = self.introspect('--targets') + # This assumes all of the targets support lto + for t in targets: + for s in t['target_sources']: + if 'linker' in s: + continue + for e in expected: + self.assertIn(e, s['parameters']) + + @skip_if_not_base_option('b_lto_mode') + @skip_if_not_base_option('b_lto_threads') + def test_lto_mode(self): + testdir = os.path.join(self.common_test_dir, '6 linkshared') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() != 'clang': + raise SkipTest('Only clang currently supports thinLTO') + if cc.linker.id not in {'ld.lld', 'ld.gold', 'ld64', 'lld-link'}: + raise SkipTest('thinLTO requires ld.lld, ld.gold, ld64, or lld-link') + elif is_windows(): + raise SkipTest('LTO not (yet) supported by windows clang') + + self.init(testdir, extra_args=['-Db_lto=true', '-Db_lto_mode=thin', '-Db_lto_threads=8', '-Dc_args=-Werror=unused-command-line-argument']) + self.build() + self.run_tests() + + expected = set(cc.get_lto_compile_args(threads=8, mode='thin')) + targets = self.introspect('--targets') + # This assumes all of the targets support lto + for t in targets: + for s in t['target_sources']: + self.assertTrue(expected.issubset(set(s['parameters'])), f'Incorrect values for {t["name"]}') + + def test_dist_git(self): + if not shutil.which('git'): + raise SkipTest('Git not found') + if self.backend is not Backend.ninja: + raise SkipTest('Dist is only supported with Ninja') + + try: + self.dist_impl(git_init, _git_add_all) + except PermissionError: + # When run under Windows CI, something (virus scanner?) + # holds on to the git files so cleaning up the dir + # fails sometimes. + pass + + def has_working_hg(self): + if not shutil.which('hg'): + return False + try: + # This check should not be necessary, but + # CI under macOS passes the above test even + # though Mercurial is not installed. + if subprocess.call(['hg', '--version'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) != 0: + return False + return True + except FileNotFoundError: + return False + + def test_dist_hg(self): + if not self.has_working_hg(): + raise SkipTest('Mercurial not found or broken.') + if self.backend is not Backend.ninja: + raise SkipTest('Dist is only supported with Ninja') + + def hg_init(project_dir): + subprocess.check_call(['hg', 'init'], cwd=project_dir) + with open(os.path.join(project_dir, '.hg', 'hgrc'), 'w', encoding='utf-8') as f: + print('[ui]', file=f) + print('username=Author Person ', file=f) + subprocess.check_call(['hg', 'add', 'meson.build', 'distexe.c'], cwd=project_dir) + subprocess.check_call(['hg', 'commit', '-m', 'I am a project'], cwd=project_dir) + + try: + self.dist_impl(hg_init, include_subprojects=False) + except PermissionError: + # When run under Windows CI, something (virus scanner?) + # holds on to the hg files so cleaning up the dir + # fails sometimes. + pass + + def test_dist_git_script(self): + if not shutil.which('git'): + raise SkipTest('Git not found') + if self.backend is not Backend.ninja: + raise SkipTest('Dist is only supported with Ninja') + + try: + with tempfile.TemporaryDirectory() as tmpdir: + project_dir = os.path.join(tmpdir, 'a') + shutil.copytree(os.path.join(self.unit_test_dir, '35 dist script'), + project_dir) + git_init(project_dir) + self.init(project_dir) + self.build('dist') + + self.new_builddir() + self.init(project_dir, extra_args=['-Dsub:broken_dist_script=false']) + self._run(self.meson_command + ['dist', '--include-subprojects'], workdir=self.builddir) + except PermissionError: + # When run under Windows CI, something (virus scanner?) + # holds on to the git files so cleaning up the dir + # fails sometimes. + pass + + def create_dummy_subproject(self, project_dir, name): + path = os.path.join(project_dir, 'subprojects', name) + os.makedirs(path) + with open(os.path.join(path, 'meson.build'), 'w', encoding='utf-8') as ofile: + ofile.write(f"project('{name}', version: '1.0')") + return path + + def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): + # Create this on the fly because having rogue .git directories inside + # the source tree leads to all kinds of trouble. + with tempfile.TemporaryDirectory() as project_dir: + with open(os.path.join(project_dir, 'meson.build'), 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent('''\ + project('disttest', 'c', version : '1.4.3') + e = executable('distexe', 'distexe.c') + test('dist test', e) + subproject('vcssub', required : false) + subproject('tarballsub', required : false) + subproject('samerepo', required : false) + ''')) + with open(os.path.join(project_dir, 'distexe.c'), 'w', encoding='utf-8') as ofile: + ofile.write(textwrap.dedent('''\ + #include + + int main(int argc, char **argv) { + printf("I am a distribution test.\\n"); + return 0; + } + ''')) + xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') + xz_checksumfile = xz_distfile + '.sha256sum' + gz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.gz') + gz_checksumfile = gz_distfile + '.sha256sum' + zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') + zip_checksumfile = zip_distfile + '.sha256sum' + vcs_init(project_dir) + if include_subprojects: + vcs_init(self.create_dummy_subproject(project_dir, 'vcssub')) + self.create_dummy_subproject(project_dir, 'tarballsub') + self.create_dummy_subproject(project_dir, 'unusedsub') + if vcs_add_all: + vcs_add_all(self.create_dummy_subproject(project_dir, 'samerepo')) + self.init(project_dir) + self.build('dist') + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + self.assertPathDoesNotExist(gz_distfile) + self.assertPathDoesNotExist(gz_checksumfile) + self.assertPathDoesNotExist(zip_distfile) + self.assertPathDoesNotExist(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'gztar'], + workdir=self.builddir) + self.assertPathExists(gz_distfile) + self.assertPathExists(gz_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'zip'], + workdir=self.builddir) + self.assertPathExists(zip_distfile) + self.assertPathExists(zip_checksumfile) + os.remove(xz_distfile) + os.remove(xz_checksumfile) + os.remove(gz_distfile) + os.remove(gz_checksumfile) + os.remove(zip_distfile) + os.remove(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'xztar,gztar,zip'], + workdir=self.builddir) + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + self.assertPathExists(gz_distfile) + self.assertPathExists(gz_checksumfile) + self.assertPathExists(zip_distfile) + self.assertPathExists(zip_checksumfile) + + if include_subprojects: + # Verify that without --include-subprojects we have files from + # the main project and also files from subprojects part of the + # main vcs repository. + z = zipfile.ZipFile(zip_distfile) + expected = ['disttest-1.4.3/', + 'disttest-1.4.3/meson.build', + 'disttest-1.4.3/distexe.c'] + if vcs_add_all: + expected += ['disttest-1.4.3/subprojects/', + 'disttest-1.4.3/subprojects/samerepo/', + 'disttest-1.4.3/subprojects/samerepo/meson.build'] + self.assertEqual(sorted(expected), + sorted(z.namelist())) + # Verify that with --include-subprojects we now also have files + # from tarball and separate vcs subprojects. But not files from + # unused subprojects. + self._run(self.meson_command + ['dist', '--formats', 'zip', '--include-subprojects'], + workdir=self.builddir) + z = zipfile.ZipFile(zip_distfile) + expected += ['disttest-1.4.3/subprojects/tarballsub/', + 'disttest-1.4.3/subprojects/tarballsub/meson.build', + 'disttest-1.4.3/subprojects/vcssub/', + 'disttest-1.4.3/subprojects/vcssub/meson.build'] + self.assertEqual(sorted(expected), + sorted(z.namelist())) + if vcs_add_all: + # Verify we can distribute separately subprojects in the same vcs + # repository as the main project. + subproject_dir = os.path.join(project_dir, 'subprojects', 'samerepo') + self.new_builddir() + self.init(subproject_dir) + self.build('dist') + xz_distfile = os.path.join(self.distdir, 'samerepo-1.0.tar.xz') + xz_checksumfile = xz_distfile + '.sha256sum' + self.assertPathExists(xz_distfile) + self.assertPathExists(xz_checksumfile) + tar = tarfile.open(xz_distfile, "r:xz") # [ignore encoding] + self.assertEqual(sorted(['samerepo-1.0', + 'samerepo-1.0/meson.build']), + sorted(i.name for i in tar)) + + def test_rpath_uses_ORIGIN(self): + ''' + Test that built targets use $ORIGIN in rpath, which ensures that they + are relocatable and ensures that builds are reproducible since the + build directory won't get embedded into the built binaries. + ''' + if is_windows() or is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.common_test_dir, '39 library chain') + self.init(testdir) + self.build() + for each in ('prog', 'subdir/liblib1.so', ): + rpath = get_rpath(os.path.join(self.builddir, each)) + self.assertTrue(rpath, f'Rpath could not be determined for {each}.') + if is_dragonflybsd(): + # DragonflyBSD will prepend /usr/lib/gccVERSION to the rpath, + # so ignore that. + self.assertTrue(rpath.startswith('/usr/lib/gcc')) + rpaths = rpath.split(':')[1:] + else: + rpaths = rpath.split(':') + for path in rpaths: + self.assertTrue(path.startswith('$ORIGIN'), msg=(each, path)) + # These two don't link to anything else, so they do not need an rpath entry. + for each in ('subdir/subdir2/liblib2.so', 'subdir/subdir3/liblib3.so'): + rpath = get_rpath(os.path.join(self.builddir, each)) + if is_dragonflybsd(): + # The rpath should be equal to /usr/lib/gccVERSION + self.assertTrue(rpath.startswith('/usr/lib/gcc')) + self.assertEqual(len(rpath.split(':')), 1) + else: + self.assertIsNone(rpath) + + def test_dash_d_dedup(self): + testdir = os.path.join(self.unit_test_dir, '9 d dedup') + self.init(testdir) + cmd = self.get_compdb()[0]['command'] + self.assertTrue('-D FOO -D BAR' in cmd or + '"-D" "FOO" "-D" "BAR"' in cmd or + '/D FOO /D BAR' in cmd or + '"/D" "FOO" "/D" "BAR"' in cmd) + + def test_all_forbidden_targets_tested(self): + ''' + Test that all forbidden targets are tested in the '150 reserved targets' + test. Needs to be a unit test because it accesses Meson internals. + ''' + testdir = os.path.join(self.common_test_dir, '150 reserved targets') + targets = set(mesonbuild.coredata.FORBIDDEN_TARGET_NAMES) + # We don't actually define a target with this name + targets.remove('build.ninja') + # Remove this to avoid multiple entries with the same name + # but different case. + targets.remove('PHONY') + for i in targets: + self.assertPathExists(os.path.join(testdir, i)) + + def detect_prebuild_env(self): + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + stlinker = detect_static_linker(env, cc) + if is_windows(): + object_suffix = 'obj' + shared_suffix = 'dll' + elif is_cygwin(): + object_suffix = 'o' + shared_suffix = 'dll' + elif is_osx(): + object_suffix = 'o' + shared_suffix = 'dylib' + else: + object_suffix = 'o' + shared_suffix = 'so' + return (cc, stlinker, object_suffix, shared_suffix) + + def pbcompile(self, compiler, source, objectfile, extra_args=None): + cmd = compiler.get_exelist() + extra_args = extra_args or [] + if compiler.get_argument_syntax() == 'msvc': + cmd += ['/nologo', '/Fo' + objectfile, '/c', source] + extra_args + else: + cmd += ['-c', source, '-o', objectfile] + extra_args + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + def test_prebuilt_object(self): + (compiler, _, object_suffix, _) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '15 prebuilt object') + source = os.path.join(tdir, 'source.c') + objectfile = os.path.join(tdir, 'prebuilt.' + object_suffix) + self.pbcompile(compiler, source, objectfile) + try: + self.init(tdir) + self.build() + self.run_tests() + finally: + os.unlink(objectfile) + + def build_static_lib(self, compiler, linker, source, objectfile, outfile, extra_args=None): + if extra_args is None: + extra_args = [] + link_cmd = linker.get_exelist() + link_cmd += linker.get_always_args() + link_cmd += linker.get_std_link_args(get_fake_env(), False) + link_cmd += linker.get_output_args(outfile) + link_cmd += [objectfile] + self.pbcompile(compiler, source, objectfile, extra_args=extra_args) + try: + subprocess.check_call(link_cmd) + finally: + os.unlink(objectfile) + + def test_prebuilt_static_lib(self): + (cc, stlinker, object_suffix, _) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '16 prebuilt static') + source = os.path.join(tdir, 'libdir/best.c') + objectfile = os.path.join(tdir, 'libdir/best.' + object_suffix) + stlibfile = os.path.join(tdir, 'libdir/libbest.a') + self.build_static_lib(cc, stlinker, source, objectfile, stlibfile) + # Run the test + try: + self.init(tdir) + self.build() + self.run_tests() + finally: + os.unlink(stlibfile) + + def build_shared_lib(self, compiler, source, objectfile, outfile, impfile, extra_args=None): + if extra_args is None: + extra_args = [] + if compiler.get_argument_syntax() == 'msvc': + link_cmd = compiler.get_linker_exelist() + [ + '/NOLOGO', '/DLL', '/DEBUG', '/IMPLIB:' + impfile, + '/OUT:' + outfile, objectfile] + else: + if not (compiler.info.is_windows() or compiler.info.is_cygwin() or compiler.info.is_darwin()): + extra_args += ['-fPIC'] + link_cmd = compiler.get_exelist() + ['-shared', '-o', outfile, objectfile] + if not is_osx(): + link_cmd += ['-Wl,-soname=' + os.path.basename(outfile)] + self.pbcompile(compiler, source, objectfile, extra_args=extra_args) + try: + subprocess.check_call(link_cmd) + finally: + os.unlink(objectfile) + + def test_prebuilt_shared_lib(self): + (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + source = os.path.join(tdir, 'alexandria.c') + objectfile = os.path.join(tdir, 'alexandria.' + object_suffix) + impfile = os.path.join(tdir, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(tdir, 'alexandria.' + shared_suffix) + elif is_cygwin(): + shlibfile = os.path.join(tdir, 'cygalexandria.' + shared_suffix) + else: + shlibfile = os.path.join(tdir, 'libalexandria.' + shared_suffix) + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + if is_windows(): + def cleanup() -> None: + """Clean up all the garbage MSVC writes in the source tree.""" + + for fname in glob(os.path.join(tdir, 'alexandria.*')): + if os.path.splitext(fname)[1] not in {'.c', '.h'}: + os.unlink(fname) + self.addCleanup(cleanup) + else: + self.addCleanup(os.unlink, shlibfile) + + # Run the test + self.init(tdir) + self.build() + self.run_tests() + + def test_prebuilt_shared_lib_rpath(self) -> None: + (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() + tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + with tempfile.TemporaryDirectory() as d: + source = os.path.join(tdir, 'alexandria.c') + objectfile = os.path.join(d, 'alexandria.' + object_suffix) + impfile = os.path.join(d, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(d, 'alexandria.' + shared_suffix) + elif is_cygwin(): + shlibfile = os.path.join(d, 'cygalexandria.' + shared_suffix) + else: + shlibfile = os.path.join(d, 'libalexandria.' + shared_suffix) + # Ensure MSVC extra files end up in the directory that gets deleted + # at the end + with chdir(d): + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + # Run the test + self.init(tdir, extra_args=[f'-Dsearch_dir={d}']) + self.build() + self.run_tests() + + def test_prebuilt_shared_lib_rpath_same_prefix(self) -> None: + (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() + orig_tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + + # Put the shared library in a location that shares a common prefix with + # the source directory: + # + # .../ + # foo-lib/ + # libalexandria.so + # foo/ + # meson.build + # ... + # + # This allows us to check that the .../foo-lib/libalexandria.so path is + # preserved correctly when meson processes it. + with tempfile.TemporaryDirectory() as d: + libdir = os.path.join(d, 'foo-lib') + os.mkdir(libdir) + + source = os.path.join(orig_tdir, 'alexandria.c') + objectfile = os.path.join(libdir, 'alexandria.' + object_suffix) + impfile = os.path.join(libdir, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(libdir, 'alexandria.' + shared_suffix) + elif is_cygwin(): + shlibfile = os.path.join(libdir, 'cygalexandria.' + shared_suffix) + else: + shlibfile = os.path.join(libdir, 'libalexandria.' + shared_suffix) + # Ensure MSVC extra files end up in the directory that gets deleted + # at the end + with chdir(libdir): + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + tdir = os.path.join(d, 'foo') + shutil.copytree(orig_tdir, tdir) + + # Run the test + self.init(tdir, extra_args=[f'-Dsearch_dir={libdir}']) + self.build() + self.run_tests() + + def test_underscore_prefix_detection_list(self) -> None: + ''' + Test the underscore detection hardcoded lookup list + against what was detected in the binary. + ''' + env, cc = get_convincing_fake_env_and_cc(self.builddir, self.prefix) + expected_uscore = cc._symbols_have_underscore_prefix_searchbin(env) + list_uscore = cc._symbols_have_underscore_prefix_list(env) + if list_uscore is not None: + self.assertEqual(list_uscore, expected_uscore) + else: + raise SkipTest('No match in underscore prefix list for this platform.') + + def test_underscore_prefix_detection_define(self) -> None: + ''' + Test the underscore detection based on compiler-defined preprocessor macro + against what was detected in the binary. + ''' + env, cc = get_convincing_fake_env_and_cc(self.builddir, self.prefix) + expected_uscore = cc._symbols_have_underscore_prefix_searchbin(env) + define_uscore = cc._symbols_have_underscore_prefix_define(env) + if define_uscore is not None: + self.assertEqual(define_uscore, expected_uscore) + else: + raise SkipTest('Did not find the underscore prefix define __USER_LABEL_PREFIX__') + + @skipIfNoPkgconfig + def test_pkgconfig_static(self): + ''' + Test that the we prefer static libraries when `static: true` is + passed to dependency() with pkg-config. Can't be an ordinary test + because we need to build libs and try to find them from meson.build + + Also test that it's not a hard error to have unsatisfiable library deps + since system libraries -lm will never be found statically. + https://github.com/mesonbuild/meson/issues/2785 + ''' + (cc, stlinker, objext, shext) = self.detect_prebuild_env() + testdir = os.path.join(self.unit_test_dir, '18 pkgconfig static') + source = os.path.join(testdir, 'foo.c') + objectfile = os.path.join(testdir, 'foo.' + objext) + stlibfile = os.path.join(testdir, 'libfoo.a') + impfile = os.path.join(testdir, 'foo.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(testdir, 'foo.' + shext) + elif is_cygwin(): + shlibfile = os.path.join(testdir, 'cygfoo.' + shext) + else: + shlibfile = os.path.join(testdir, 'libfoo.' + shext) + # Build libs + self.build_static_lib(cc, stlinker, source, objectfile, stlibfile, extra_args=['-DFOO_STATIC']) + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + # Run test + try: + self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': self.builddir}) + self.build() + self.run_tests() + finally: + os.unlink(stlibfile) + os.unlink(shlibfile) + if is_windows(): + # Clean up all the garbage MSVC writes in the + # source tree. + for fname in glob(os.path.join(testdir, 'foo.*')): + if os.path.splitext(fname)[1] not in ['.c', '.h', '.in']: + os.unlink(fname) + + @skipIfNoPkgconfig + @mock.patch.dict(os.environ) + def test_pkgconfig_gen_escaping(self): + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + prefix = '/usr/with spaces' + libdir = 'lib' + self.init(testdir, extra_args=['--prefix=' + prefix, + '--libdir=' + libdir]) + # Find foo dependency + os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir + env = get_fake_env(testdir, self.builddir, self.prefix) + kwargs = {'required': True, 'silent': True} + foo_dep = PkgConfigDependency('libanswer', env, kwargs) + # Ensure link_args are properly quoted + libdir = PurePath(prefix) / PurePath(libdir) + link_args = ['-L' + libdir.as_posix(), '-lanswer'] + self.assertEqual(foo_dep.get_link_args(), link_args) + # Ensure include args are properly quoted + incdir = PurePath(prefix) / PurePath('include') + cargs = ['-I' + incdir.as_posix(), '-DLIBFOO'] + # pkg-config and pkgconf does not respect the same order + self.assertEqual(sorted(foo_dep.get_compile_args()), sorted(cargs)) + + @skipIfNoPkgconfig + def test_pkgconfig_relocatable(self): + ''' + Test that it generates relocatable pkgconfig when module + option pkgconfig.relocatable=true. + ''' + testdir_rel = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir_rel, extra_args=['-Dpkgconfig.relocatable=true']) + + def check_pcfile(name, *, relocatable, levels=2): + with open(os.path.join(self.privatedir, name), encoding='utf-8') as f: + pcfile = f.read() + # The pkgconfig module always uses posix path regardless of platform + prefix_rel = PurePath('${pcfiledir}', *(['..'] * levels)).as_posix() + (self.assertIn if relocatable else self.assertNotIn)( + f'prefix={prefix_rel}\n', + pcfile) + + check_pcfile('libvartest.pc', relocatable=True) + check_pcfile('libvartest2.pc', relocatable=True) + + self.wipe() + self.init(testdir_rel, extra_args=['-Dpkgconfig.relocatable=false']) + + check_pcfile('libvartest.pc', relocatable=False) + check_pcfile('libvartest2.pc', relocatable=False) + + self.wipe() + testdir_abs = os.path.join(self.unit_test_dir, '106 pkgconfig relocatable with absolute path') + self.init(testdir_abs) + + check_pcfile('libsimple.pc', relocatable=True, levels=3) + + def test_array_option_change(self): + def get_opt(): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == 'list': + return x + raise Exception(opts) + + expected = { + 'name': 'list', + 'description': 'list', + 'section': 'user', + 'type': 'array', + 'value': ['foo', 'bar'], + 'choices': ['foo', 'bar', 'oink', 'boink'], + 'machine': 'any', + } + tdir = os.path.join(self.unit_test_dir, '19 array option') + self.init(tdir) + original = get_opt() + self.assertDictEqual(original, expected) + + expected['value'] = ['oink', 'boink'] + self.setconf('-Dlist=oink,boink') + changed = get_opt() + self.assertEqual(changed, expected) + + def test_array_option_bad_change(self): + def get_opt(): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == 'list': + return x + raise Exception(opts) + + expected = { + 'name': 'list', + 'description': 'list', + 'section': 'user', + 'type': 'array', + 'value': ['foo', 'bar'], + 'choices': ['foo', 'bar', 'oink', 'boink'], + 'machine': 'any', + } + tdir = os.path.join(self.unit_test_dir, '19 array option') + self.init(tdir) + original = get_opt() + self.assertDictEqual(original, expected) + with self.assertRaises(subprocess.CalledProcessError): + self.setconf('-Dlist=bad') + changed = get_opt() + self.assertDictEqual(changed, expected) + + def test_array_option_empty_equivalents(self): + """Array options treat -Dopt=[] and -Dopt= as equivalent.""" + def get_opt(): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == 'list': + return x + raise Exception(opts) + + expected = { + 'name': 'list', + 'description': 'list', + 'section': 'user', + 'type': 'array', + 'value': [], + 'choices': ['foo', 'bar', 'oink', 'boink'], + 'machine': 'any', + } + tdir = os.path.join(self.unit_test_dir, '19 array option') + self.init(tdir, extra_args='-Dlist=') + original = get_opt() + self.assertDictEqual(original, expected) + + def opt_has(self, name, value): + res = self.introspect('--buildoptions') + found = False + for i in res: + if i['name'] == name: + self.assertEqual(i['value'], value) + found = True + break + self.assertTrue(found, "Array option not found in introspect data.") + + def test_free_stringarray_setting(self): + testdir = os.path.join(self.common_test_dir, '40 options') + self.init(testdir) + self.opt_has('free_array_opt', []) + self.setconf('-Dfree_array_opt=foo,bar', will_build=False) + self.opt_has('free_array_opt', ['foo', 'bar']) + self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False) + self.opt_has('free_array_opt', ['a,b', 'c,d']) + + # When running under Travis Mac CI, the file updates seem to happen + # too fast so the timestamps do not get properly updated. + # Call this method before file operations in appropriate places + # to make things work. + def mac_ci_delay(self): + if is_osx() and is_ci(): + import time + time.sleep(1) + + def test_options_with_choices_changing(self) -> None: + """Detect when options like arrays or combos have their choices change.""" + testdir = Path(os.path.join(self.unit_test_dir, '83 change option choices')) + options1 = str(testdir / 'meson_options.1.txt') + options2 = str(testdir / 'meson_options.2.txt') + + # Test that old options are changed to the new defaults if they are not valid + real_options = str(testdir / 'meson_options.txt') + self.addCleanup(os.unlink, real_options) + + shutil.copy(options1, real_options) + self.init(str(testdir)) + self.mac_ci_delay() + shutil.copy(options2, real_options) + + self.build() + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == 'combo': + self.assertEqual(item['value'], 'b') + self.assertEqual(item['choices'], ['b', 'c', 'd']) + elif item['name'] == 'array': + self.assertEqual(item['value'], ['b']) + self.assertEqual(item['choices'], ['b', 'c', 'd']) + + self.wipe() + self.mac_ci_delay() + + # When the old options are valid they should remain + shutil.copy(options1, real_options) + self.init(str(testdir), extra_args=['-Dcombo=c', '-Darray=b,c']) + self.mac_ci_delay() + shutil.copy(options2, real_options) + self.build() + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == 'combo': + self.assertEqual(item['value'], 'c') + self.assertEqual(item['choices'], ['b', 'c', 'd']) + elif item['name'] == 'array': + self.assertEqual(item['value'], ['b', 'c']) + self.assertEqual(item['choices'], ['b', 'c', 'd']) + + def test_options_listed_in_build_options(self) -> None: + """Detect when changed options become listed in build options.""" + testdir = os.path.join(self.unit_test_dir, '112 list build options') + + out = self.init(testdir) + for line in out.splitlines(): + if line.startswith('Message: Build options:'): + self.assertNotIn('-Dauto_features=auto', line) + self.assertNotIn('-Doptional=auto', line) + + self.wipe() + self.mac_ci_delay() + + out = self.init(testdir, extra_args=['-Dauto_features=disabled', '-Doptional=enabled']) + for line in out.splitlines(): + if line.startswith('Message: Build options:'): + self.assertIn('-Dauto_features=disabled', line) + self.assertIn('-Doptional=enabled', line) + + self.setconf('-Doptional=disabled') + out = self.build() + for line in out.splitlines(): + if line.startswith('Message: Build options:'): + self.assertIn('-Dauto_features=disabled', line) + self.assertNotIn('-Doptional=enabled', line) + self.assertIn('-Doptional=disabled', line) + + def test_subproject_promotion(self): + testdir = os.path.join(self.unit_test_dir, '12 promote') + workdir = os.path.join(self.builddir, 'work') + shutil.copytree(testdir, workdir) + spdir = os.path.join(workdir, 'subprojects') + s3dir = os.path.join(spdir, 's3') + scommondir = os.path.join(spdir, 'scommon') + self.assertFalse(os.path.isdir(s3dir)) + subprocess.check_call(self.wrap_command + ['promote', 's3'], + cwd=workdir, + stdout=subprocess.DEVNULL) + self.assertTrue(os.path.isdir(s3dir)) + self.assertFalse(os.path.isdir(scommondir)) + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'scommon'], + cwd=workdir, + stderr=subprocess.DEVNULL), 0) + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'invalid/path/to/scommon'], + cwd=workdir, + stderr=subprocess.DEVNULL), 0) + self.assertFalse(os.path.isdir(scommondir)) + subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/scommon'], cwd=workdir) + self.assertTrue(os.path.isdir(scommondir)) + promoted_wrap = os.path.join(spdir, 'athing.wrap') + self.assertFalse(os.path.isfile(promoted_wrap)) + subprocess.check_call(self.wrap_command + ['promote', 'athing'], cwd=workdir) + self.assertTrue(os.path.isfile(promoted_wrap)) + self.new_builddir() # Ensure builddir is not parent or workdir + self.init(workdir) + self.build() + + def test_subproject_promotion_wrap(self): + testdir = os.path.join(self.unit_test_dir, '43 promote wrap') + workdir = os.path.join(self.builddir, 'work') + shutil.copytree(testdir, workdir) + spdir = os.path.join(workdir, 'subprojects') + + ambiguous_wrap = os.path.join(spdir, 'ambiguous.wrap') + self.assertNotEqual(subprocess.call(self.wrap_command + ['promote', 'ambiguous'], + cwd=workdir, + stderr=subprocess.DEVNULL), 0) + self.assertFalse(os.path.isfile(ambiguous_wrap)) + subprocess.check_call(self.wrap_command + ['promote', 'subprojects/s2/subprojects/ambiguous.wrap'], cwd=workdir) + self.assertTrue(os.path.isfile(ambiguous_wrap)) + + def test_warning_location(self): + tdir = os.path.join(self.unit_test_dir, '22 warning location') + out = self.init(tdir) + for expected in [ + r'meson.build:4: WARNING: Keyword argument "link_with" defined multiple times.', + r'sub' + os.path.sep + r'meson.build:3: WARNING: Keyword argument "link_with" defined multiple times.', + r'meson.build:6: WARNING: a warning of some sort', + r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning', + r'meson.build:7: WARNING: Module SIMD has no backwards or forwards compatibility and might not exist in future releases.', + r"meson.build:11: WARNING: The variable(s) 'MISSING' in the input file 'conf.in' are not present in the given configuration data.", + ]: + with self.subTest(expected): + self.assertRegex(out, re.escape(expected)) + + for wd in [ + self.src_root, + self.builddir, + os.getcwd(), + ]: + with self.subTest(wd): + self.new_builddir() + out = self.init(tdir, workdir=wd) + expected = os.path.join(relpath(tdir, self.src_root), 'meson.build') + relwd = relpath(self.src_root, wd) + if relwd != '.': + expected = os.path.join(relwd, expected) + expected = '\n' + expected + ':' + self.assertIn(expected, out) + + def test_error_location_path(self): + '''Test locations in meson errors contain correct paths''' + # this list contains errors from all the different steps in the + # lexer/parser/interpreter we have tests for. + for (t, f) in [ + ('10 out of bounds', 'meson.build'), + ('18 wrong plusassign', 'meson.build'), + ('59 bad option argument', 'meson_options.txt'), + ('97 subdir parse error', os.path.join('subdir', 'meson.build')), + ('98 invalid option file', 'meson_options.txt'), + ]: + tdir = os.path.join(self.src_root, 'test cases', 'failing', t) + + for wd in [ + self.src_root, + self.builddir, + os.getcwd(), + ]: + try: + self.init(tdir, workdir=wd) + except subprocess.CalledProcessError as e: + expected = os.path.join('test cases', 'failing', t, f) + relwd = relpath(self.src_root, wd) + if relwd != '.': + expected = os.path.join(relwd, expected) + expected = '\n' + expected + ':' + self.assertIn(expected, e.output) + else: + self.fail('configure unexpectedly succeeded') + + def test_permitted_method_kwargs(self): + tdir = os.path.join(self.unit_test_dir, '25 non-permitted kwargs') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(tdir) + self.assertIn('ERROR: compiler.has_header_symbol got unknown keyword arguments "prefixxx"', cm.exception.output) + + def test_templates(self): + ninja = mesonbuild.environment.detect_ninja() + if ninja is None: + raise SkipTest('This test currently requires ninja. Fix this once "meson build" works.') + + langs = ['c'] + env = get_fake_env() + for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust']: + try: + comp = detect_compiler_for(env, l, MachineChoice.HOST, True) + with tempfile.TemporaryDirectory() as d: + comp.sanity_check(d, env) + langs.append(l) + except EnvironmentException: + pass + + # The D template fails under mac CI and we don't know why. + # Patches welcome + if is_osx(): + langs = [l for l in langs if l != 'd'] + + for lang in langs: + for target_type in ('executable', 'library'): + if is_windows() and lang == 'fortran' and target_type == 'library': + # non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way + # see "test cases/fortran/6 dynamic" + fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True) + if fc.get_id() in {'intel-cl', 'pgi'}: + continue + # test empty directory + with tempfile.TemporaryDirectory() as tmpdir: + self._run(self.meson_command + ['init', '--language', lang, '--type', target_type], + workdir=tmpdir) + self._run(self.setup_command + ['--backend=ninja', 'builddir'], + workdir=tmpdir) + self._run(ninja, + workdir=os.path.join(tmpdir, 'builddir')) + # test directory with existing code file + if lang in {'c', 'cpp', 'd'}: + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'foo.' + lang), 'w', encoding='utf-8') as f: + f.write('int main(void) {}') + self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) + elif lang in {'java'}: + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'Foo.' + lang), 'w', encoding='utf-8') as f: + f.write('public class Foo { public static void main() {} }') + self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) + + def test_compiler_run_command(self): + ''' + The test checks that the compiler object can be passed to + run_command(). + ''' + testdir = os.path.join(self.unit_test_dir, '24 compiler run_command') + self.init(testdir) + + def test_identical_target_name_in_subproject_flat_layout(self): + ''' + Test that identical targets in different subprojects do not collide + if layout is flat. + ''' + testdir = os.path.join(self.common_test_dir, '172 identical target name in subproject flat layout') + self.init(testdir, extra_args=['--layout=flat']) + self.build() + + def test_identical_target_name_in_subdir_flat_layout(self): + ''' + Test that identical targets in different subdirs do not collide + if layout is flat. + ''' + testdir = os.path.join(self.common_test_dir, '181 same target name flat layout') + self.init(testdir, extra_args=['--layout=flat']) + self.build() + + def test_flock(self): + exception_raised = False + with tempfile.TemporaryDirectory() as tdir: + os.mkdir(os.path.join(tdir, 'meson-private')) + with BuildDirLock(tdir): + try: + with BuildDirLock(tdir): + pass + except MesonException: + exception_raised = True + self.assertTrue(exception_raised, 'Double locking did not raise exception.') + + @skipIf(is_osx(), 'Test not applicable to OSX') + def test_check_module_linking(self): + """ + Test that link_with: a shared module issues a warning + https://github.com/mesonbuild/meson/issues/2865 + (That an error is raised on OSX is exercised by test failing/78) + """ + tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking') + out = self.init(tdir) + msg = ('''DEPRECATION: target prog links against shared module mymod, which is incorrect. + This will be an error in the future, so please use shared_library() for mymod instead. + If shared_module() was used for mymod because it has references to undefined symbols, + use shared_library() with `override_options: ['b_lundef=false']` instead.''') + self.assertIn(msg, out) + + def test_mixed_language_linker_check(self): + testdir = os.path.join(self.unit_test_dir, '97 compiler.links file arg') + self.init(testdir) + cmds = self.get_meson_log_compiler_checks() + self.assertEqual(len(cmds), 5) + # Path to the compilers, gleaned from cc.compiles tests + cc = cmds[0][0] + cxx = cmds[1][0] + # cc.links + self.assertEqual(cmds[2][0], cc) + # cxx.links with C source + self.assertEqual(cmds[3][0], cc) + self.assertEqual(cmds[4][0], cxx) + if self.backend is Backend.ninja: + # updating the file to check causes a reconfigure + # + # only the ninja backend is competent enough to detect reconfigured + # no-op builds without build targets + self.utime(os.path.join(testdir, 'test.c')) + self.assertReconfiguredBuildIsNoop() + + def test_ndebug_if_release_disabled(self): + testdir = os.path.join(self.unit_test_dir, '28 ndebug if-release') + self.init(testdir, extra_args=['--buildtype=release', '-Db_ndebug=if-release']) + self.build() + exe = os.path.join(self.builddir, 'main') + self.assertEqual(b'NDEBUG=1', subprocess.check_output(exe).strip()) + + def test_ndebug_if_release_enabled(self): + testdir = os.path.join(self.unit_test_dir, '28 ndebug if-release') + self.init(testdir, extra_args=['--buildtype=debugoptimized', '-Db_ndebug=if-release']) + self.build() + exe = os.path.join(self.builddir, 'main') + self.assertEqual(b'NDEBUG=0', subprocess.check_output(exe).strip()) + + def test_guessed_linker_dependencies(self): + ''' + Test that meson adds dependencies for libraries based on the final + linker command line. + ''' + testdirbase = os.path.join(self.unit_test_dir, '29 guessed linker dependencies') + testdirlib = os.path.join(testdirbase, 'lib') + + extra_args = None + libdir_flags = ['-L'] + env = get_fake_env(testdirlib, self.builddir, self.prefix) + if detect_c_compiler(env, MachineChoice.HOST).get_id() in {'msvc', 'clang-cl', 'intel-cl'}: + # msvc-like compiler, also test it with msvc-specific flags + libdir_flags += ['/LIBPATH:', '-LIBPATH:'] + else: + # static libraries are not linkable with -l with msvc because meson installs them + # as .a files which unix_args_to_native will not know as it expects libraries to use + # .lib as extension. For a DLL the import library is installed as .lib. Thus for msvc + # this tests needs to use shared libraries to test the path resolving logic in the + # dependency generation code path. + extra_args = ['--default-library', 'static'] + + initial_builddir = self.builddir + initial_installdir = self.installdir + + for libdir_flag in libdir_flags: + # build library + self.new_builddir() + self.init(testdirlib, extra_args=extra_args) + self.build() + self.install() + libbuilddir = self.builddir + installdir = self.installdir + libdir = os.path.join(self.installdir, self.prefix.lstrip('/').lstrip('\\'), 'lib') + + # build user of library + self.new_builddir() + # replace is needed because meson mangles platform paths passed via LDFLAGS + self.init(os.path.join(testdirbase, 'exe'), + override_envvars={"LDFLAGS": '{}{}'.format(libdir_flag, libdir.replace('\\', '/'))}) + self.build() + self.assertBuildIsNoop() + + # rebuild library + exebuilddir = self.builddir + self.installdir = installdir + self.builddir = libbuilddir + # Microsoft's compiler is quite smart about touching import libs on changes, + # so ensure that there is actually a change in symbols. + self.setconf('-Dmore_exports=true') + self.build() + self.install() + # no ensure_backend_detects_changes needed because self.setconf did that already + + # assert user of library will be rebuild + self.builddir = exebuilddir + self.assertRebuiltTarget('app') + + # restore dirs for the next test case + self.installdir = initial_builddir + self.builddir = initial_installdir + + def test_conflicting_d_dash_option(self): + testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as e: + self.init(testdir, extra_args=['-Dbindir=foo', '--bindir=bar']) + # Just to ensure that we caught the correct error + self.assertIn('as both', e.stderr) + + def _test_same_option_twice(self, arg, args): + testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') + self.init(testdir, extra_args=args) + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == arg: + self.assertEqual(item['value'], 'bar') + return + raise Exception(f'Missing {arg} value?') + + def test_same_dash_option_twice(self): + self._test_same_option_twice('bindir', ['--bindir=foo', '--bindir=bar']) + + def test_same_d_option_twice(self): + self._test_same_option_twice('bindir', ['-Dbindir=foo', '-Dbindir=bar']) + + def test_same_project_d_option_twice(self): + self._test_same_option_twice('one', ['-Done=foo', '-Done=bar']) + + def _test_same_option_twice_configure(self, arg, args): + testdir = os.path.join(self.unit_test_dir, '37 mixed command line args') + self.init(testdir) + self.setconf(args) + opts = self.introspect('--buildoptions') + for item in opts: + if item['name'] == arg: + self.assertEqual(item['value'], 'bar') + return + raise Exception(f'Missing {arg} value?') + + def test_same_dash_option_twice_configure(self): + self._test_same_option_twice_configure( + 'bindir', ['--bindir=foo', '--bindir=bar']) + + def test_same_d_option_twice_configure(self): + self._test_same_option_twice_configure( + 'bindir', ['-Dbindir=foo', '-Dbindir=bar']) + + def test_same_project_d_option_twice_configure(self): + self._test_same_option_twice_configure( + 'one', ['-Done=foo', '-Done=bar']) + + def test_command_line(self): + testdir = os.path.join(self.unit_test_dir, '34 command line') + + # Verify default values when passing no args that affect the + # configuration, and as a bonus, test that --profile-self works. + out = self.init(testdir, extra_args=['--profile-self', '--fatal-meson-warnings']) + self.assertNotIn('[default: true]', out) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'static') + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.assertEqual(obj.options[OptionKey('set_sub_opt')].value, True) + self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'default3') + self.wipe() + + # warning_level is special, it's --warnlevel instead of --warning-level + # for historical reasons + self.init(testdir, extra_args=['--warnlevel=2', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '2') + self.setconf('--warnlevel=3') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '3') + self.setconf('--warnlevel=everything') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, 'everything') + self.wipe() + + # But when using -D syntax, it should be 'warning_level' + self.init(testdir, extra_args=['-Dwarning_level=2', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '2') + self.setconf('-Dwarning_level=3') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '3') + self.setconf('-Dwarning_level=everything') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, 'everything') + self.wipe() + + # Mixing --option and -Doption is forbidden + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.init(testdir, extra_args=['--warnlevel=1', '-Dwarning_level=3']) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn('as both', cm.exception.output) + else: + self.assertIn('as both', str(cm.exception)) + self.init(testdir) + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.setconf(['--warnlevel=1', '-Dwarning_level=3']) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn('as both', cm.exception.output) + else: + self.assertIn('as both', str(cm.exception)) + self.wipe() + + # --default-library should override default value from project() + self.init(testdir, extra_args=['--default-library=both', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'both') + self.setconf('--default-library=shared') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared') + if self.backend is Backend.ninja: + # reconfigure target works only with ninja backend + self.build('reconfigure') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared') + self.wipe() + + # Should fail on unknown options + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.init(testdir, extra_args=['-Dbad=1', '-Dfoo=2', '-Dwrong_link_args=foo']) + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + self.wipe() + + # Should fail on malformed option + msg = "Option 'foo' must have a value separated by equals sign." + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.init(testdir, extra_args=['-Dfoo']) + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + else: + self.assertIn(msg, str(cm.exception)) + self.init(testdir) + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)) as cm: + self.setconf('-Dfoo') + if isinstance(cm.exception, subprocess.CalledProcessError): + self.assertNotEqual(0, cm.exception.returncode) + self.assertIn(msg, cm.exception.output) + else: + self.assertIn(msg, str(cm.exception)) + self.wipe() + + # It is not an error to set wrong option for unknown subprojects or + # language because we don't have control on which one will be selected. + self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1', '-Db_wrong=1']) + self.wipe() + + # Test we can set subproject option + self.init(testdir, extra_args=['-Dsubp:subp_opt=foo', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'foo') + self.wipe() + + # c_args value should be parsed with split_args + self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo', '-Dbar', '-Dthird=one two']) + + self.setconf('-Dc_args="foo bar" one two') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['foo bar', 'one', 'two']) + self.wipe() + + self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('set_percent_opt')].value, 'myoption%') + self.wipe() + + # Setting a 2nd time the same option should override the first value + try: + self.init(testdir, extra_args=['--bindir=foo', '--bindir=bar', + '-Dbuildtype=plain', '-Dbuildtype=release', + '-Db_sanitize=address', '-Db_sanitize=thread', + '-Dc_args=-Dfoo', '-Dc_args=-Dbar', + '-Db_lundef=false', '--fatal-meson-warnings']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('bindir')].value, 'bar') + self.assertEqual(obj.options[OptionKey('buildtype')].value, 'release') + self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'thread') + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dbar']) + self.setconf(['--bindir=bar', '--bindir=foo', + '-Dbuildtype=release', '-Dbuildtype=plain', + '-Db_sanitize=thread', '-Db_sanitize=address', + '-Dc_args=-Dbar', '-Dc_args=-Dfoo']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('bindir')].value, 'foo') + self.assertEqual(obj.options[OptionKey('buildtype')].value, 'plain') + self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'address') + self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo']) + self.wipe() + except KeyError: + # Ignore KeyError, it happens on CI for compilers that does not + # support b_sanitize. We have to test with a base option because + # they used to fail this test with Meson 0.46 an earlier versions. + pass + + def test_warning_level_0(self): + testdir = os.path.join(self.common_test_dir, '207 warning level 0') + + # Verify default values when passing no args + self.init(testdir) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') + self.wipe() + + # verify we can override w/ --warnlevel + self.init(testdir, extra_args=['--warnlevel=1']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.setconf('--warnlevel=0') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') + self.wipe() + + # verify we can override w/ -Dwarning_level + self.init(testdir, extra_args=['-Dwarning_level=1']) + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '1') + self.setconf('-Dwarning_level=0') + obj = mesonbuild.coredata.load(self.builddir) + self.assertEqual(obj.options[OptionKey('warning_level')].value, '0') + self.wipe() + + def test_feature_check_usage_subprojects(self): + testdir = os.path.join(self.unit_test_dir, '40 featurenew subprojects') + out = self.init(testdir) + # Parent project warns correctly + self.assertRegex(out, "WARNING: Project targets '>=0.45'.*'0.47.0': dict") + # Subprojects warn correctly + self.assertRegex(out, r"foo\| .*WARNING: Project targets '>=0.40'.*'0.44.0': disabler") + self.assertRegex(out, r"baz\| .*WARNING: Project targets '!=0.40'.*'0.44.0': disabler") + # Subproject has a new-enough meson_version, no warning + self.assertNotRegex(out, "WARNING: Project targets.*Python") + # Ensure a summary is printed in the subproject and the outer project + self.assertRegex(out, r"\| WARNING: Project specifies a minimum meson_version '>=0.40'") + self.assertRegex(out, r"\| \* 0.44.0: {'disabler'}") + self.assertRegex(out, "WARNING: Project specifies a minimum meson_version '>=0.45'") + self.assertRegex(out, " * 0.47.0: {'dict'}") + + def test_configure_file_warnings(self): + testdir = os.path.join(self.common_test_dir, "14 configure file") + out = self.init(testdir) + self.assertRegex(out, "WARNING:.*'empty'.*config.h.in.*not present.*") + self.assertRegex(out, "WARNING:.*'FOO_BAR'.*nosubst-nocopy2.txt.in.*not present.*") + self.assertRegex(out, "WARNING:.*'empty'.*config.h.in.*not present.*") + self.assertRegex(out, "WARNING:.*empty configuration_data.*test.py.in") + # Warnings for configuration files that are overwritten. + self.assertRegex(out, "WARNING:.*\"double_output.txt\".*overwrites") + self.assertRegex(out, "WARNING:.*\"subdir.double_output2.txt\".*overwrites") + self.assertNotRegex(out, "WARNING:.*no_write_conflict.txt.*overwrites") + self.assertNotRegex(out, "WARNING:.*@BASENAME@.*overwrites") + self.assertRegex(out, "WARNING:.*\"sameafterbasename\".*overwrites") + # No warnings about empty configuration data objects passed to files with substitutions + self.assertNotRegex(out, "WARNING:.*empty configuration_data.*nosubst-nocopy1.txt.in") + self.assertNotRegex(out, "WARNING:.*empty configuration_data.*nosubst-nocopy2.txt.in") + with open(os.path.join(self.builddir, 'nosubst-nocopy1.txt'), 'rb') as f: + self.assertEqual(f.read().strip(), b'/* #undef FOO_BAR */') + with open(os.path.join(self.builddir, 'nosubst-nocopy2.txt'), 'rb') as f: + self.assertEqual(f.read().strip(), b'') + + def test_dirs(self): + with tempfile.TemporaryDirectory() as containing: + with tempfile.TemporaryDirectory(dir=containing) as srcdir: + mfile = os.path.join(srcdir, 'meson.build') + of = open(mfile, 'w', encoding='utf-8') + of.write("project('foobar', 'c')\n") + of.close() + pc = subprocess.run(self.setup_command, + cwd=srcdir, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + self.assertIn(b'Must specify at least one directory name', pc.stdout) + with tempfile.TemporaryDirectory(dir=srcdir) as builddir: + subprocess.run(self.setup_command, + check=True, + cwd=builddir, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + + def get_opts_as_dict(self): + result = {} + for i in self.introspect('--buildoptions'): + result[i['name']] = i['value'] + return result + + def test_buildtype_setting(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + opts = self.get_opts_as_dict() + self.assertEqual(opts['buildtype'], 'debug') + self.assertEqual(opts['debug'], True) + self.setconf('-Ddebug=false') + opts = self.get_opts_as_dict() + self.assertEqual(opts['debug'], False) + self.assertEqual(opts['buildtype'], 'debug') + self.assertEqual(opts['optimization'], '0') + self.setconf('-Doptimization=g') + opts = self.get_opts_as_dict() + self.assertEqual(opts['debug'], False) + self.assertEqual(opts['buildtype'], 'debug') + self.assertEqual(opts['optimization'], 'g') + + @skipIfNoPkgconfig + @skipIf(is_windows(), 'Help needed with fixing this test on windows') + def test_native_dep_pkgconfig(self): + testdir = os.path.join(self.unit_test_dir, + '45 native dep pkgconfig var') + with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as crossfile: + crossfile.write(textwrap.dedent( + '''[binaries] + pkg-config = '{}' + + [properties] + + [host_machine] + system = 'linux' + cpu_family = 'arm' + cpu = 'armv7' + endian = 'little' + '''.format(os.path.join(testdir, 'cross_pkgconfig.py')))) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + + env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir, + 'native_pkgconfig')} + self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env) + self.wipe() + self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) + + @skipIfNoPkgconfig + @skipIf(is_windows(), 'Help needed with fixing this test on windows') + def test_pkg_config_libdir(self): + testdir = os.path.join(self.unit_test_dir, + '45 native dep pkgconfig var') + with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as crossfile: + crossfile.write(textwrap.dedent( + '''[binaries] + pkg-config = 'pkg-config' + + [properties] + pkg_config_libdir = ['{}'] + + [host_machine] + system = 'linux' + cpu_family = 'arm' + cpu = 'armv7' + endian = 'little' + '''.format(os.path.join(testdir, 'cross_pkgconfig')))) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + + env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir, + 'native_pkgconfig')} + self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env) + self.wipe() + self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) + + def __reconfigure(self): + # Set an older version to force a reconfigure from scratch + filename = os.path.join(self.privatedir, 'coredata.dat') + with open(filename, 'rb') as f: + obj = pickle.load(f) + obj.version = '0.47.0' + with open(filename, 'wb') as f: + pickle.dump(obj, f) + + def test_reconfigure(self): + testdir = os.path.join(self.unit_test_dir, '47 reconfigure') + self.init(testdir, extra_args=['-Dopt1=val1', '-Dsub1:werror=true']) + self.setconf('-Dopt2=val2') + + self.__reconfigure() + + out = self.init(testdir, extra_args=['--reconfigure', '-Dopt3=val3']) + self.assertRegex(out, 'Regenerating configuration from scratch') + self.assertRegex(out, 'opt1 val1') + self.assertRegex(out, 'opt2 val2') + self.assertRegex(out, 'opt3 val3') + self.assertRegex(out, 'opt4 default4') + self.assertRegex(out, 'sub1:werror true') + self.build() + self.run_tests() + + # Create a file in builddir and verify wipe command removes it + filename = os.path.join(self.builddir, 'something') + open(filename, 'w', encoding='utf-8').close() + self.assertTrue(os.path.exists(filename)) + out = self.init(testdir, extra_args=['--wipe', '-Dopt4=val4']) + self.assertFalse(os.path.exists(filename)) + self.assertRegex(out, 'opt1 val1') + self.assertRegex(out, 'opt2 val2') + self.assertRegex(out, 'opt3 val3') + self.assertRegex(out, 'opt4 val4') + self.assertRegex(out, 'sub1:werror true') + self.assertTrue(Path(self.builddir, '.gitignore').exists()) + self.build() + self.run_tests() + + def test_wipe_from_builddir(self): + testdir = os.path.join(self.common_test_dir, '157 custom target subdir depend files') + self.init(testdir) + self.__reconfigure() + self.init(testdir, extra_args=['--wipe'], workdir=self.builddir) + + def test_target_construct_id_from_path(self): + # This id is stable but not guessable. + # The test is supposed to prevent unintentional + # changes of target ID generation. + target_id = Target.construct_id_from_path('some/obscure/subdir', + 'target-id', '@suffix') + self.assertEqual('5e002d3@@target-id@suffix', target_id) + target_id = Target.construct_id_from_path('subproject/foo/subdir/bar', + 'target2-id', '@other') + self.assertEqual('81d46d1@@target2-id@other', target_id) + + def test_introspect_projectinfo_without_configured_build(self): + testfile = os.path.join(self.common_test_dir, '33 run program', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + self.assertEqual(set(res['buildsystem_files']), {'meson.build'}) + self.assertEqual(res['version'], 'undefined') + self.assertEqual(res['descriptive_name'], 'run command') + self.assertEqual(res['subprojects'], []) + + testfile = os.path.join(self.common_test_dir, '40 options', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + self.assertEqual(set(res['buildsystem_files']), {'meson_options.txt', 'meson.build'}) + self.assertEqual(res['version'], 'undefined') + self.assertEqual(res['descriptive_name'], 'options') + self.assertEqual(res['subprojects'], []) + + testfile = os.path.join(self.common_test_dir, '43 subproject options', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + self.assertEqual(set(res['buildsystem_files']), {'meson_options.txt', 'meson.build'}) + self.assertEqual(res['version'], 'undefined') + self.assertEqual(res['descriptive_name'], 'suboptions') + self.assertEqual(len(res['subprojects']), 1) + subproject_files = {f.replace('\\', '/') for f in res['subprojects'][0]['buildsystem_files']} + self.assertEqual(subproject_files, {'subprojects/subproject/meson_options.txt', 'subprojects/subproject/meson.build'}) + self.assertEqual(res['subprojects'][0]['name'], 'subproject') + self.assertEqual(res['subprojects'][0]['version'], 'undefined') + self.assertEqual(res['subprojects'][0]['descriptive_name'], 'subproject') + + def test_introspect_projectinfo_subprojects(self): + testdir = os.path.join(self.common_test_dir, '98 subproject subdir') + self.init(testdir) + res = self.introspect('--projectinfo') + expected = { + 'descriptive_name': 'proj', + 'version': 'undefined', + 'subproject_dir': 'subprojects', + 'subprojects': [ + { + 'descriptive_name': 'sub', + 'name': 'sub', + 'version': '1.0' + }, + { + 'descriptive_name': 'sub_implicit', + 'name': 'sub_implicit', + 'version': '1.0', + }, + { + 'descriptive_name': 'sub-novar', + 'name': 'sub_novar', + 'version': '1.0', + }, + { + 'descriptive_name': 'sub_static', + 'name': 'sub_static', + 'version': 'undefined' + }, + { + 'descriptive_name': 'subsub', + 'name': 'subsub', + 'version': 'undefined' + }, + { + 'descriptive_name': 'subsubsub', + 'name': 'subsubsub', + 'version': 'undefined' + }, + ] + } + res['subprojects'] = sorted(res['subprojects'], key=lambda i: i['name']) + self.assertDictEqual(expected, res) + + def test_introspection_target_subproject(self): + testdir = os.path.join(self.common_test_dir, '42 subproject') + self.init(testdir) + res = self.introspect('--targets') + + expected = { + 'sublib': 'sublib', + 'simpletest': 'sublib', + 'user': None + } + + for entry in res: + name = entry['name'] + self.assertEqual(entry['subproject'], expected[name]) + + def test_introspect_projectinfo_subproject_dir(self): + testdir = os.path.join(self.common_test_dir, '75 custom subproject dir') + self.init(testdir) + res = self.introspect('--projectinfo') + + self.assertEqual(res['subproject_dir'], 'custom_subproject_dir') + + def test_introspect_projectinfo_subproject_dir_from_source(self): + testfile = os.path.join(self.common_test_dir, '75 custom subproject dir', 'meson.build') + res = self.introspect_directory(testfile, '--projectinfo') + + self.assertEqual(res['subproject_dir'], 'custom_subproject_dir') + + @skipIfNoExecutable('clang-format') + def test_clang_format(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Clang-format is for now only supported on Ninja, not {self.backend.name}') + testdir = os.path.join(self.unit_test_dir, '53 clang-format') + + # Ensure that test project is in git even when running meson from tarball. + srcdir = os.path.join(self.builddir, 'src') + shutil.copytree(testdir, srcdir) + git_init(srcdir) + testdir = srcdir + self.new_builddir() + + testfile = os.path.join(testdir, 'prog.c') + badfile = os.path.join(testdir, 'prog_orig_c') + goodfile = os.path.join(testdir, 'prog_expected_c') + testheader = os.path.join(testdir, 'header.h') + badheader = os.path.join(testdir, 'header_orig_h') + goodheader = os.path.join(testdir, 'header_expected_h') + includefile = os.path.join(testdir, '.clang-format-include') + try: + shutil.copyfile(badfile, testfile) + shutil.copyfile(badheader, testheader) + self.init(testdir) + self.assertNotEqual(Path(testfile).read_text(encoding='utf-8'), + Path(goodfile).read_text(encoding='utf-8')) + self.assertNotEqual(Path(testheader).read_text(encoding='utf-8'), + Path(goodheader).read_text(encoding='utf-8')) + + # test files are not in git so this should do nothing + self.run_target('clang-format') + self.assertNotEqual(Path(testfile).read_text(encoding='utf-8'), + Path(goodfile).read_text(encoding='utf-8')) + self.assertNotEqual(Path(testheader).read_text(encoding='utf-8'), + Path(goodheader).read_text(encoding='utf-8')) + + # Add an include file to reformat everything + with open(includefile, 'w', encoding='utf-8') as f: + f.write('*') + self.run_target('clang-format') + self.assertEqual(Path(testheader).read_text(encoding='utf-8'), + Path(goodheader).read_text(encoding='utf-8')) + finally: + if os.path.exists(testfile): + os.unlink(testfile) + if os.path.exists(testheader): + os.unlink(testheader) + if os.path.exists(includefile): + os.unlink(includefile) + + @skipIfNoExecutable('clang-tidy') + def test_clang_tidy(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Clang-tidy is for now only supported on Ninja, not {self.backend.name}') + if shutil.which('c++') is None: + raise SkipTest('Clang-tidy breaks when ccache is used and "c++" not in path.') + if is_osx(): + raise SkipTest('Apple ships a broken clang-tidy that chokes on -pipe.') + testdir = os.path.join(self.unit_test_dir, '68 clang-tidy') + dummydir = os.path.join(testdir, 'dummydir.h') + self.init(testdir, override_envvars={'CXX': 'c++'}) + out = self.run_target('clang-tidy') + self.assertIn('cttest.cpp:4:20', out) + self.assertNotIn(dummydir, out) + + def test_identity_cross(self): + testdir = os.path.join(self.unit_test_dir, '69 cross') + # Do a build to generate a cross file where the host is this target + self.init(testdir, extra_args=['-Dgenerate=true']) + self.meson_cross_files = [os.path.join(self.builddir, "crossfile")] + self.assertTrue(os.path.exists(self.meson_cross_files[0])) + # Now verify that this is detected as cross + self.new_builddir() + self.init(testdir) + + def test_introspect_buildoptions_without_configured_build(self): + testdir = os.path.join(self.unit_test_dir, '58 introspect buildoptions') + testfile = os.path.join(testdir, 'meson.build') + res_nb = self.introspect_directory(testfile, ['--buildoptions'] + self.meson_args) + self.init(testdir, default_args=False) + res_wb = self.introspect('--buildoptions') + self.maxDiff = None + # XXX: These now generate in a different order, is that okay? + self.assertListEqual(sorted(res_nb, key=lambda x: x['name']), sorted(res_wb, key=lambda x: x['name'])) + + def test_meson_configure_from_source_does_not_crash(self): + testdir = os.path.join(self.unit_test_dir, '58 introspect buildoptions') + self._run(self.mconf_command + [testdir]) + + def test_introspect_buildoptions_cross_only(self): + testdir = os.path.join(self.unit_test_dir, '82 cross only introspect') + testfile = os.path.join(testdir, 'meson.build') + res = self.introspect_directory(testfile, ['--buildoptions'] + self.meson_args) + optnames = [o['name'] for o in res] + self.assertIn('c_args', optnames) + self.assertNotIn('build.c_args', optnames) + + def test_introspect_json_flat(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + self.init(testdir, extra_args=['-Dlayout=flat']) + infodir = os.path.join(self.builddir, 'meson-info') + self.assertPathExists(infodir) + + with open(os.path.join(infodir, 'intro-targets.json'), encoding='utf-8') as fp: + targets = json.load(fp) + + for i in targets: + for out in i['filename']: + assert os.path.relpath(out, self.builddir).startswith('meson-out') + + def test_introspect_json_dump(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + self.init(testdir) + infodir = os.path.join(self.builddir, 'meson-info') + self.assertPathExists(infodir) + + def assertKeyTypes(key_type_list, obj, strict: bool = True): + for i in key_type_list: + if isinstance(i[1], (list, tuple)) and None in i[1]: + i = (i[0], tuple(x for x in i[1] if x is not None)) + if i[0] not in obj or obj[i[0]] is None: + continue + self.assertIn(i[0], obj) + self.assertIsInstance(obj[i[0]], i[1]) + if strict: + for k in obj.keys(): + found = False + for i in key_type_list: + if k == i[0]: + found = True + break + self.assertTrue(found, f'Key "{k}" not in expected list') + + root_keylist = [ + ('benchmarks', list), + ('buildoptions', list), + ('buildsystem_files', list), + ('compilers', dict), + ('dependencies', list), + ('install_plan', dict), + ('installed', dict), + ('machines', dict), + ('projectinfo', dict), + ('targets', list), + ('tests', list), + ] + + test_keylist = [ + ('cmd', list), + ('env', dict), + ('name', str), + ('timeout', int), + ('suite', list), + ('is_parallel', bool), + ('protocol', str), + ('depends', list), + ('workdir', (str, None)), + ('priority', int), + ('extra_paths', list), + ] + + buildoptions_keylist = [ + ('name', str), + ('section', str), + ('type', str), + ('description', str), + ('machine', str), + ('choices', (list, None)), + ('value', (str, int, bool, list)), + ] + + buildoptions_typelist = [ + ('combo', str, [('choices', list)]), + ('string', str, []), + ('boolean', bool, []), + ('integer', int, []), + ('array', list, []), + ] + + buildoptions_sections = ['core', 'backend', 'base', 'compiler', 'directory', 'user', 'test'] + buildoptions_machines = ['any', 'build', 'host'] + + dependencies_typelist = [ + ('name', str), + ('type', str), + ('version', str), + ('compile_args', list), + ('link_args', list), + ('include_directories', list), + ('sources', list), + ('extra_files', list), + ('dependencies', list), + ('depends', list), + ('meson_variables', list), + ] + + targets_typelist = [ + ('name', str), + ('id', str), + ('type', str), + ('defined_in', str), + ('filename', list), + ('build_by_default', bool), + ('target_sources', list), + ('extra_files', list), + ('subproject', (str, None)), + ('dependencies', list), + ('depends', list), + ('install_filename', (list, None)), + ('installed', bool), + ('vs_module_defs', (str, None)), + ('win_subsystem', (str, None)), + ] + + targets_sources_typelist = [ + ('language', str), + ('compiler', list), + ('parameters', list), + ('sources', list), + ('generated_sources', list), + ('unity_sources', (list, None)), + ] + + target_sources_linker_typelist = [ + ('linker', list), + ('parameters', list), + ] + + # First load all files + res = {} + for i in root_keylist: + curr = os.path.join(infodir, 'intro-{}.json'.format(i[0])) + self.assertPathExists(curr) + with open(curr, encoding='utf-8') as fp: + res[i[0]] = json.load(fp) + + assertKeyTypes(root_keylist, res) + + # Match target ids to input and output files for ease of reference + src_to_id = {} + out_to_id = {} + name_to_out = {} + for i in res['targets']: + print(json.dump(i, sys.stdout)) + out_to_id.update({os.path.relpath(out, self.builddir): i['id'] + for out in i['filename']}) + name_to_out.update({i['name']: i['filename']}) + for group in i['target_sources']: + src_to_id.update({os.path.relpath(src, testdir): i['id'] + for src in group.get('sources', [])}) + + # Check Tests and benchmarks + tests_to_find = ['test case 1', 'test case 2', 'benchmark 1'] + deps_to_find = {'test case 1': [src_to_id['t1.cpp']], + 'test case 2': [src_to_id['t2.cpp'], src_to_id['t3.cpp']], + 'benchmark 1': [out_to_id['file2'], out_to_id['file3'], out_to_id['file4'], src_to_id['t3.cpp']]} + for i in res['benchmarks'] + res['tests']: + assertKeyTypes(test_keylist, i) + if i['name'] in tests_to_find: + tests_to_find.remove(i['name']) + self.assertEqual(sorted(i['depends']), + sorted(deps_to_find[i['name']])) + self.assertListEqual(tests_to_find, []) + + # Check buildoptions + buildopts_to_find = {'cpp_std': 'c++11'} + for i in res['buildoptions']: + assertKeyTypes(buildoptions_keylist, i) + valid_type = False + for j in buildoptions_typelist: + if i['type'] == j[0]: + self.assertIsInstance(i['value'], j[1]) + assertKeyTypes(j[2], i, strict=False) + valid_type = True + break + + self.assertIn(i['section'], buildoptions_sections) + self.assertIn(i['machine'], buildoptions_machines) + self.assertTrue(valid_type) + if i['name'] in buildopts_to_find: + self.assertEqual(i['value'], buildopts_to_find[i['name']]) + buildopts_to_find.pop(i['name'], None) + self.assertDictEqual(buildopts_to_find, {}) + + # Check buildsystem_files + bs_files = ['meson.build', 'meson_options.txt', 'sharedlib/meson.build', 'staticlib/meson.build'] + bs_files = [os.path.join(testdir, x) for x in bs_files] + self.assertPathListEqual(list(sorted(res['buildsystem_files'])), list(sorted(bs_files))) + + # Check dependencies + dependencies_to_find = ['threads'] + for i in res['dependencies']: + assertKeyTypes(dependencies_typelist, i) + if i['name'] in dependencies_to_find: + dependencies_to_find.remove(i['name']) + self.assertListEqual(dependencies_to_find, []) + + # Check projectinfo + self.assertDictEqual(res['projectinfo'], {'version': '1.2.3', 'descriptive_name': 'introspection', 'subproject_dir': 'subprojects', 'subprojects': []}) + + # Check targets + targets_to_find = { + 'sharedTestLib': ('shared library', True, False, 'sharedlib/meson.build', + [os.path.join(testdir, 'sharedlib', 'shared.cpp')]), + 'staticTestLib': ('static library', True, False, 'staticlib/meson.build', + [os.path.join(testdir, 'staticlib', 'static.c')]), + 'custom target test 1': ('custom', False, False, 'meson.build', + [os.path.join(testdir, 'cp.py')]), + 'custom target test 2': ('custom', False, False, 'meson.build', + name_to_out['custom target test 1']), + 'test1': ('executable', True, True, 'meson.build', + [os.path.join(testdir, 't1.cpp')]), + 'test2': ('executable', True, False, 'meson.build', + [os.path.join(testdir, 't2.cpp')]), + 'test3': ('executable', True, False, 'meson.build', + [os.path.join(testdir, 't3.cpp')]), + 'custom target test 3': ('custom', False, False, 'meson.build', + name_to_out['test3']), + } + for i in res['targets']: + assertKeyTypes(targets_typelist, i) + if i['name'] in targets_to_find: + tgt = targets_to_find[i['name']] + self.assertEqual(i['type'], tgt[0]) + self.assertEqual(i['build_by_default'], tgt[1]) + self.assertEqual(i['installed'], tgt[2]) + self.assertPathEqual(i['defined_in'], os.path.join(testdir, tgt[3])) + targets_to_find.pop(i['name'], None) + for j in i['target_sources']: + if 'compiler' in j: + assertKeyTypes(targets_sources_typelist, j) + self.assertEqual(j['sources'], [os.path.normpath(f) for f in tgt[4]]) + else: + assertKeyTypes(target_sources_linker_typelist, j) + self.assertDictEqual(targets_to_find, {}) + + def test_introspect_file_dump_equals_all(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + self.init(testdir) + res_all = self.introspect('--all') + res_file = {} + + root_keylist = [ + 'benchmarks', + 'buildoptions', + 'buildsystem_files', + 'compilers', + 'dependencies', + 'installed', + 'install_plan', + 'machines', + 'projectinfo', + 'targets', + 'tests', + ] + + infodir = os.path.join(self.builddir, 'meson-info') + self.assertPathExists(infodir) + for i in root_keylist: + curr = os.path.join(infodir, f'intro-{i}.json') + self.assertPathExists(curr) + with open(curr, encoding='utf-8') as fp: + res_file[i] = json.load(fp) + + self.assertEqual(res_all, res_file) + + def test_introspect_meson_info(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + introfile = os.path.join(self.builddir, 'meson-info', 'meson-info.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res1 = json.load(fp) + + for i in ['meson_version', 'directories', 'introspection', 'build_files_updated', 'error']: + self.assertIn(i, res1) + + self.assertEqual(res1['error'], False) + self.assertEqual(res1['build_files_updated'], True) + + def test_introspect_config_update(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + introfile = os.path.join(self.builddir, 'meson-info', 'intro-buildoptions.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res1 = json.load(fp) + + for i in res1: + if i['name'] == 'cpp_std': + i['value'] = 'c++14' + if i['name'] == 'build.cpp_std': + i['value'] = 'c++14' + if i['name'] == 'buildtype': + i['value'] = 'release' + if i['name'] == 'optimization': + i['value'] = '3' + if i['name'] == 'debug': + i['value'] = False + + self.setconf('-Dcpp_std=c++14') + self.setconf('-Dbuildtype=release') + + with open(introfile, encoding='utf-8') as fp: + res2 = json.load(fp) + + self.assertListEqual(res1, res2) + + def test_introspect_targets_from_source(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + testfile = os.path.join(testdir, 'meson.build') + introfile = os.path.join(self.builddir, 'meson-info', 'intro-targets.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res_wb = json.load(fp) + + res_nb = self.introspect_directory(testfile, ['--targets'] + self.meson_args) + + # Account for differences in output + res_wb = [i for i in res_wb if i['type'] != 'custom'] + for i in res_wb: + i['filename'] = [os.path.relpath(x, self.builddir) for x in i['filename']] + for k in ('install_filename', 'dependencies', 'win_subsystem'): + if k in i: + del i[k] + + sources = [] + for j in i['target_sources']: + sources += j.get('sources', []) + i['target_sources'] = [{ + 'language': 'unknown', + 'compiler': [], + 'parameters': [], + 'sources': sources, + 'generated_sources': [] + }] + + self.maxDiff = None + self.assertListEqual(res_nb, res_wb) + + def test_introspect_ast_source(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + testfile = os.path.join(testdir, 'meson.build') + res_nb = self.introspect_directory(testfile, ['--ast'] + self.meson_args) + + node_counter = {} + + def accept_node(json_node): + self.assertIsInstance(json_node, dict) + for i in ['lineno', 'colno', 'end_lineno', 'end_colno']: + self.assertIn(i, json_node) + self.assertIsInstance(json_node[i], int) + self.assertIn('node', json_node) + n = json_node['node'] + self.assertIsInstance(n, str) + self.assertIn(n, nodes) + if n not in node_counter: + node_counter[n] = 0 + node_counter[n] = node_counter[n] + 1 + for nodeDesc in nodes[n]: + key = nodeDesc[0] + func = nodeDesc[1] + self.assertIn(key, json_node) + if func is None: + tp = nodeDesc[2] + self.assertIsInstance(json_node[key], tp) + continue + func(json_node[key]) + + def accept_node_list(node_list): + self.assertIsInstance(node_list, list) + for i in node_list: + accept_node(i) + + def accept_kwargs(kwargs): + self.assertIsInstance(kwargs, list) + for i in kwargs: + self.assertIn('key', i) + self.assertIn('val', i) + accept_node(i['key']) + accept_node(i['val']) + + nodes = { + 'BooleanNode': [('value', None, bool)], + 'IdNode': [('value', None, str)], + 'NumberNode': [('value', None, int)], + 'StringNode': [('value', None, str)], + 'FormatStringNode': [('value', None, str)], + 'ContinueNode': [], + 'BreakNode': [], + 'ArgumentNode': [('positional', accept_node_list), ('kwargs', accept_kwargs)], + 'ArrayNode': [('args', accept_node)], + 'DictNode': [('args', accept_node)], + 'EmptyNode': [], + 'OrNode': [('left', accept_node), ('right', accept_node)], + 'AndNode': [('left', accept_node), ('right', accept_node)], + 'ComparisonNode': [('left', accept_node), ('right', accept_node), ('ctype', None, str)], + 'ArithmeticNode': [('left', accept_node), ('right', accept_node), ('op', None, str)], + 'NotNode': [('right', accept_node)], + 'CodeBlockNode': [('lines', accept_node_list)], + 'IndexNode': [('object', accept_node), ('index', accept_node)], + 'MethodNode': [('object', accept_node), ('args', accept_node), ('name', None, str)], + 'FunctionNode': [('args', accept_node), ('name', None, str)], + 'AssignmentNode': [('value', accept_node), ('var_name', None, str)], + 'PlusAssignmentNode': [('value', accept_node), ('var_name', None, str)], + 'ForeachClauseNode': [('items', accept_node), ('block', accept_node), ('varnames', None, list)], + 'IfClauseNode': [('ifs', accept_node_list), ('else', accept_node)], + 'IfNode': [('condition', accept_node), ('block', accept_node)], + 'UMinusNode': [('right', accept_node)], + 'TernaryNode': [('condition', accept_node), ('true', accept_node), ('false', accept_node)], + } + + accept_node(res_nb) + + for n, c in [('ContinueNode', 2), ('BreakNode', 1), ('NotNode', 3)]: + self.assertIn(n, node_counter) + self.assertEqual(node_counter[n], c) + + def test_introspect_dependencies_from_source(self): + testdir = os.path.join(self.unit_test_dir, '56 introspection') + testfile = os.path.join(testdir, 'meson.build') + res_nb = self.introspect_directory(testfile, ['--scan-dependencies'] + self.meson_args) + expected = [ + { + 'name': 'threads', + 'required': True, + 'version': [], + 'has_fallback': False, + 'conditional': False + }, + { + 'name': 'zlib', + 'required': False, + 'version': [], + 'has_fallback': False, + 'conditional': False + }, + { + 'name': 'bugDep1', + 'required': True, + 'version': [], + 'has_fallback': False, + 'conditional': False + }, + { + 'name': 'somethingthatdoesnotexist', + 'required': True, + 'version': ['>=1.2.3'], + 'has_fallback': False, + 'conditional': True + }, + { + 'name': 'look_i_have_a_fallback', + 'required': True, + 'version': ['>=1.0.0', '<=99.9.9'], + 'has_fallback': True, + 'conditional': True + } + ] + self.maxDiff = None + self.assertListEqual(res_nb, expected) + + def test_unstable_coredata(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + # just test that the command does not fail (e.g. because it throws an exception) + self._run([*self.meson_command, 'unstable-coredata', self.builddir]) + + @skip_if_no_cmake + def test_cmake_prefix_path(self): + testdir = os.path.join(self.unit_test_dir, '62 cmake_prefix_path') + self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')]) + + @skip_if_no_cmake + def test_cmake_parser(self): + testdir = os.path.join(self.unit_test_dir, '63 cmake parser') + self.init(testdir, extra_args=['-Dcmake_prefix_path=' + os.path.join(testdir, 'prefix')]) + + def test_alias_target(self): + testdir = os.path.join(self.unit_test_dir, '64 alias target') + self.init(testdir) + self.build() + self.assertPathDoesNotExist(os.path.join(self.builddir, 'prog' + exe_suffix)) + self.assertPathDoesNotExist(os.path.join(self.builddir, 'hello.txt')) + self.run_target('build-all') + self.assertPathExists(os.path.join(self.builddir, 'prog' + exe_suffix)) + self.assertPathExists(os.path.join(self.builddir, 'hello.txt')) + out = self.run_target('aliased-run') + self.assertIn('a run target was here', out) + + def test_configure(self): + testdir = os.path.join(self.common_test_dir, '2 cpp') + self.init(testdir) + self._run(self.mconf_command + [self.builddir]) + + def test_summary(self): + testdir = os.path.join(self.unit_test_dir, '71 summary') + out = self.init(testdir, extra_args=['-Denabled_opt=enabled', f'-Dpython={sys.executable}']) + expected = textwrap.dedent(r''' + Some Subproject 2.0 + + string : bar + integer: 1 + boolean: True + + subsub undefined + + Something: Some value + + My Project 1.0 + + Configuration + Some boolean : False + Another boolean: True + Some string : Hello World + A list : string + 1 + True + empty list : + enabled_opt : enabled + A number : 1 + yes : YES + no : NO + comma list : a, b, c + + Stuff + missing prog : NO + existing prog : ''' + ExternalProgram('python3', [sys.executable], silent=True).path + ''' + missing dep : NO + external dep : YES 1.2.3 + internal dep : YES + disabler : NO + + Plugins + long comma list: alpha, alphacolor, apetag, audiofx, audioparsers, auparse, + autodetect, avi + + Subprojects + sub : YES + sub2 : NO Problem encountered: This subproject failed + subsub : YES (from sub2) + + User defined options + backend : ''' + self.backend_name + ''' + libdir : lib + prefix : /usr + enabled_opt : enabled + python : ''' + sys.executable + ''' + ''') + expected_lines = expected.split('\n')[1:] + out_start = out.find(expected_lines[0]) + out_lines = out[out_start:].split('\n')[:len(expected_lines)] + for e, o in zip(expected_lines, out_lines): + if e.startswith(' external dep'): + self.assertRegex(o, r'^ external dep : (YES [0-9.]*|NO)$') + else: + self.assertEqual(o, e) + + def test_meson_compile(self): + """Test the meson compile command.""" + + def get_exe_name(basename: str) -> str: + if is_windows(): + return f'{basename}.exe' + else: + return basename + + def get_shared_lib_name(basename: str) -> str: + if mesonbuild.environment.detect_msys2_arch(): + return f'lib{basename}.dll' + elif is_windows(): + return f'{basename}.dll' + elif is_cygwin(): + return f'cyg{basename}.dll' + elif is_osx(): + return f'lib{basename}.dylib' + else: + return f'lib{basename}.so' + + def get_static_lib_name(basename: str) -> str: + return f'lib{basename}.a' + + # Base case (no targets or additional arguments) + + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + + self._run([*self.meson_command, 'compile', '-C', self.builddir]) + self.assertPathExists(os.path.join(self.builddir, get_exe_name('trivialprog'))) + + # `--clean` + + self._run([*self.meson_command, 'compile', '-C', self.builddir, '--clean']) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('trivialprog'))) + + # Target specified in a project with unique names + + testdir = os.path.join(self.common_test_dir, '6 linkshared') + self.init(testdir, extra_args=['--wipe']) + # Multiple targets and target type specified + self._run([*self.meson_command, 'compile', '-C', self.builddir, 'mylib', 'mycpplib:shared_library']) + # Check that we have a shared lib, but not an executable, i.e. check that target actually worked + self.assertPathExists(os.path.join(self.builddir, get_shared_lib_name('mylib'))) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('prog'))) + self.assertPathExists(os.path.join(self.builddir, get_shared_lib_name('mycpplib'))) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('cppprog'))) + + # Target specified in a project with non unique names + + testdir = os.path.join(self.common_test_dir, '185 same target name') + self.init(testdir, extra_args=['--wipe']) + self._run([*self.meson_command, 'compile', '-C', self.builddir, './foo']) + self.assertPathExists(os.path.join(self.builddir, get_static_lib_name('foo'))) + self._run([*self.meson_command, 'compile', '-C', self.builddir, 'sub/foo']) + self.assertPathExists(os.path.join(self.builddir, 'sub', get_static_lib_name('foo'))) + + # run_target + + testdir = os.path.join(self.common_test_dir, '51 run target') + self.init(testdir, extra_args=['--wipe']) + out = self._run([*self.meson_command, 'compile', '-C', self.builddir, 'py3hi']) + self.assertIn('I am Python3.', out) + + # `--$BACKEND-args` + + testdir = os.path.join(self.common_test_dir, '1 trivial') + if self.backend is Backend.ninja: + self.init(testdir, extra_args=['--wipe']) + # Dry run - should not create a program + self._run([*self.meson_command, 'compile', '-C', self.builddir, '--ninja-args=-n']) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('trivialprog'))) + elif self.backend is Backend.vs: + self.init(testdir, extra_args=['--wipe']) + self._run([*self.meson_command, 'compile', '-C', self.builddir]) + # Explicitly clean the target through msbuild interface + self._run([*self.meson_command, 'compile', '-C', self.builddir, '--vs-args=-t:{}:Clean'.format(re.sub(r'[\%\$\@\;\.\(\)\']', '_', get_exe_name('trivialprog')))]) + self.assertPathDoesNotExist(os.path.join(self.builddir, get_exe_name('trivialprog'))) + + def test_spurious_reconfigure_built_dep_file(self): + testdir = os.path.join(self.unit_test_dir, '73 dep files') + + # Regression test: Spurious reconfigure was happening when build + # directory is inside source directory. + # See https://gitlab.freedesktop.org/gstreamer/gst-build/-/issues/85. + srcdir = os.path.join(self.builddir, 'srctree') + shutil.copytree(testdir, srcdir) + builddir = os.path.join(srcdir, '_build') + self.change_builddir(builddir) + + self.init(srcdir) + self.build() + + # During first configure the file did not exist so no dependency should + # have been set. A rebuild should not trigger a reconfigure. + self.clean() + out = self.build() + self.assertNotIn('Project configured', out) + + self.init(srcdir, extra_args=['--reconfigure']) + + # During the reconfigure the file did exist, but is inside build + # directory, so no dependency should have been set. A rebuild should not + # trigger a reconfigure. + self.clean() + out = self.build() + self.assertNotIn('Project configured', out) + + def _test_junit(self, case: str) -> None: + try: + import lxml.etree as et + except ImportError: + raise SkipTest('lxml required, but not found.') + + schema = et.XMLSchema(et.parse(str(Path(self.src_root) / 'data' / 'schema.xsd'))) + + self.init(case) + self.run_tests() + + junit = et.parse(str(Path(self.builddir) / 'meson-logs' / 'testlog.junit.xml')) + try: + schema.assertValid(junit) + except et.DocumentInvalid as e: + self.fail(e.error_log) + + def test_junit_valid_tap(self): + self._test_junit(os.path.join(self.common_test_dir, '206 tap tests')) + + def test_junit_valid_exitcode(self): + self._test_junit(os.path.join(self.common_test_dir, '41 test args')) + + def test_junit_valid_gtest(self): + self._test_junit(os.path.join(self.framework_test_dir, '2 gtest')) + + def test_link_language_linker(self): + # TODO: there should be some way to query how we're linking things + # without resorting to reading the ninja.build file + if self.backend is not Backend.ninja: + raise SkipTest('This test reads the ninja file') + + testdir = os.path.join(self.common_test_dir, '225 link language') + self.init(testdir) + + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + + self.assertRegex(contents, r'build main(\.exe)?.*: c_LINKER') + self.assertRegex(contents, r'build (lib|cyg)?mylib.*: c_LINKER') + + def test_commands_documented(self): + ''' + Test that all listed meson commands are documented in Commands.md. + ''' + + # The docs directory is not in release tarballs. + if not os.path.isdir('docs'): + raise SkipTest('Doc directory does not exist.') + doc_path = 'docs/markdown/Commands.md' + + md = None + with open(doc_path, encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + + ## Get command sections + + section_pattern = re.compile(r'^### (.+)$', re.MULTILINE) + md_command_section_matches = [i for i in section_pattern.finditer(md)] + md_command_sections = dict() + for i, s in enumerate(md_command_section_matches): + section_end = len(md) if i == len(md_command_section_matches) - 1 else md_command_section_matches[i + 1].start() + md_command_sections[s.group(1)] = (s.start(), section_end) + + ## Validate commands + + md_commands = {k for k,v in md_command_sections.items()} + help_output = self._run(self.meson_command + ['--help']) + # Python's argument parser might put the command list to its own line. Or it might not. + self.assertTrue(help_output.startswith('usage: ')) + lines = help_output.split('\n') + line1 = lines[0] + line2 = lines[1] + if '{' in line1: + cmndline = line1 + else: + self.assertIn('{', line2) + cmndline = line2 + cmndstr = cmndline.split('{')[1] + self.assertIn('}', cmndstr) + help_commands = set(cmndstr.split('}')[0].split(',')) + self.assertTrue(len(help_commands) > 0, 'Must detect some command names.') + + self.assertEqual(md_commands | {'help'}, help_commands, f'Doc file: `{doc_path}`') + + ## Validate that each section has proper placeholders + + def get_data_pattern(command): + return re.compile( + r'{{ ' + command + r'_usage.inc }}[\r\n]' + r'.*?' + r'{{ ' + command + r'_arguments.inc }}[\r\n]', + flags = re.MULTILINE|re.DOTALL) + + for command in md_commands: + m = get_data_pattern(command).search(md, pos=md_command_sections[command][0], endpos=md_command_sections[command][1]) + self.assertIsNotNone(m, f'Command `{command}` is missing placeholders for dynamic data. Doc file: `{doc_path}`') + + def _check_coverage_files(self, types=('text', 'xml', 'html')): + covdir = Path(self.builddir) / 'meson-logs' + files = [] + if 'text' in types: + files.append('coverage.txt') + if 'xml' in types: + files.append('coverage.xml') + if 'html' in types: + files.append('coveragereport/index.html') + for f in files: + self.assertTrue((covdir / f).is_file(), msg=f'{f} is not a file') + + def test_coverage(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + self._check_coverage_files() + + def test_coverage_complex(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '105 generatorcustom') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + self._check_coverage_files() + + def test_coverage_html(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-html') + self._check_coverage_files(['html']) + + def test_coverage_text(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-text') + self._check_coverage_files(['text']) + + def test_coverage_xml(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage-xml') + self._check_coverage_files(['xml']) + + def test_coverage_escaping(self): + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with coverage on MSYS2') + gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() + if not gcovr_exe: + raise SkipTest('gcovr not found, or too old') + testdir = os.path.join(self.common_test_dir, '243 escape++') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'clang': + if not mesonbuild.environment.detect_llvm_cov(): + raise SkipTest('llvm-cov not found') + if cc.get_id() == 'msvc': + raise SkipTest('Test only applies to non-MSVC compilers') + self.init(testdir, extra_args=['-Db_coverage=true']) + self.build() + self.run_tests() + self.run_target('coverage') + self._check_coverage_files() + + def test_cross_file_constants(self): + with temp_filename() as crossfile1, temp_filename() as crossfile2: + with open(crossfile1, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + ''' + [constants] + compiler = 'gcc' + ''')) + with open(crossfile2, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + ''' + [constants] + toolchain = '/toolchain/' + common_flags = ['--sysroot=' + toolchain / 'sysroot'] + + [properties] + c_args = common_flags + ['-DSOMETHING'] + cpp_args = c_args + ['-DSOMETHING_ELSE'] + + [binaries] + c = toolchain / compiler + ''')) + + values = mesonbuild.coredata.parse_machine_files([crossfile1, crossfile2]) + self.assertEqual(values['binaries']['c'], '/toolchain/gcc') + self.assertEqual(values['properties']['c_args'], + ['--sysroot=/toolchain/sysroot', '-DSOMETHING']) + self.assertEqual(values['properties']['cpp_args'], + ['--sysroot=/toolchain/sysroot', '-DSOMETHING', '-DSOMETHING_ELSE']) + + @skipIf(is_windows(), 'Directory cleanup fails for some reason') + def test_wrap_git(self): + with tempfile.TemporaryDirectory() as tmpdir: + srcdir = os.path.join(tmpdir, 'src') + shutil.copytree(os.path.join(self.unit_test_dir, '80 wrap-git'), srcdir) + upstream = os.path.join(srcdir, 'subprojects', 'wrap_git_upstream') + upstream_uri = Path(upstream).as_uri() + git_init(upstream) + with open(os.path.join(srcdir, 'subprojects', 'wrap_git.wrap'), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-git] + url = {} + patch_directory = wrap_git_builddef + revision = master + '''.format(upstream_uri))) + out = self.init(srcdir) + self.build() + self.run_tests() + + # Make sure the warning does not occur on the first init. + out_of_date_warning = 'revision may be out of date' + self.assertNotIn(out_of_date_warning, out) + + # Change the wrap's revisions, reconfigure, and make sure it does + # warn on the reconfigure. + with open(os.path.join(srcdir, 'subprojects', 'wrap_git.wrap'), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-git] + url = {} + patch_directory = wrap_git_builddef + revision = not-master + '''.format(upstream_uri))) + out = self.init(srcdir, extra_args='--reconfigure') + self.assertIn(out_of_date_warning, out) + + def test_extract_objects_custom_target_no_warning(self): + testdir = os.path.join(self.common_test_dir, '22 object extraction') + + out = self.init(testdir) + self.assertNotRegex(out, "WARNING:.*can't be converted to File object") + + def test_multi_output_custom_target_no_warning(self): + testdir = os.path.join(self.common_test_dir, '228 custom_target source') + + out = self.init(testdir) + self.assertNotRegex(out, 'WARNING:.*Using the first one.') + self.build() + self.run_tests() + + @skipUnless(is_linux() and (re.search('^i.86$|^x86$|^x64$|^x86_64$|^amd64$', platform.processor()) is not None), + 'Requires ASM compiler for x86 or x86_64 platform currently only available on Linux CI runners') + def test_nostdlib(self): + testdir = os.path.join(self.unit_test_dir, '77 nostdlib') + machinefile = os.path.join(self.builddir, 'machine.txt') + with open(machinefile, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [properties] + c_stdlib = 'mylibc' + ''')) + + # Test native C stdlib + self.meson_native_files = [machinefile] + self.init(testdir) + self.build() + + # Test cross C stdlib + self.new_builddir() + self.meson_native_files = [] + self.meson_cross_files = [machinefile] + self.init(testdir) + self.build() + + def test_meson_version_compare(self): + testdir = os.path.join(self.unit_test_dir, '81 meson version compare') + out = self.init(testdir) + self.assertNotRegex(out, r'WARNING') + + def test_wrap_redirect(self): + redirect_wrap = os.path.join(self.builddir, 'redirect.wrap') + real_wrap = os.path.join(self.builddir, 'foo/subprojects/real.wrap') + os.makedirs(os.path.dirname(real_wrap)) + + # Invalid redirect, filename must have .wrap extension + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = foo/subprojects/real.wrapper + ''')) + with self.assertRaisesRegex(WrapException, 'wrap-redirect filename must be a .wrap file'): + PackageDefinition(redirect_wrap) + + # Invalid redirect, filename cannot be in parent directory + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = ../real.wrap + ''')) + with self.assertRaisesRegex(WrapException, 'wrap-redirect filename cannot contain ".."'): + PackageDefinition(redirect_wrap) + + # Invalid redirect, filename must be in foo/subprojects/real.wrap + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = foo/real.wrap + ''')) + with self.assertRaisesRegex(WrapException, 'wrap-redirect filename must be in the form foo/subprojects/bar.wrap'): + PackageDefinition(redirect_wrap) + + # Correct redirect + with open(redirect_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-redirect] + filename = foo/subprojects/real.wrap + ''')) + with open(real_wrap, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(''' + [wrap-git] + url = http://invalid + ''')) + wrap = PackageDefinition(redirect_wrap) + self.assertEqual(wrap.get('url'), 'http://invalid') + + @skip_if_no_cmake + def test_nested_cmake_rebuild(self) -> None: + # This checks a bug where if a non-meson project is used as a third + # level (or deeper) subproject it doesn't cause a rebuild if the build + # files for that project are changed + testdir = os.path.join(self.unit_test_dir, '84 nested subproject regenerate depends') + cmakefile = Path(testdir) / 'subprojects' / 'sub2' / 'CMakeLists.txt' + self.init(testdir) + self.build() + with cmakefile.open('a', encoding='utf-8'): + os.utime(str(cmakefile)) + self.assertReconfiguredBuildIsNoop() + + def test_version_file(self): + srcdir = os.path.join(self.common_test_dir, '2 cpp') + self.init(srcdir) + projinfo = self.introspect('--projectinfo') + self.assertEqual(projinfo['version'], '1.0.0') + + def test_cflags_cppflags(self): + envs = {'CPPFLAGS': '-DCPPFLAG', + 'CFLAGS': '-DCFLAG', + 'CXXFLAGS': '-DCXXFLAG'} + srcdir = os.path.join(self.unit_test_dir, '88 multiple envvars') + self.init(srcdir, override_envvars=envs) + self.build() + + def test_build_b_options(self) -> None: + # Currently (0.57) these do nothing, but they've always been allowed + srcdir = os.path.join(self.common_test_dir, '2 cpp') + self.init(srcdir, extra_args=['-Dbuild.b_lto=true']) + + def test_install_skip_subprojects(self): + testdir = os.path.join(self.unit_test_dir, '92 install skip subprojects') + self.init(testdir) + self.build() + + main_expected = [ + '', + 'share', + 'include', + 'foo', + 'bin', + 'share/foo', + 'share/foo/foo.dat', + 'include/foo.h', + 'foo/foofile', + 'bin/foo' + exe_suffix, + ] + bar_expected = [ + 'bar', + 'share/foo/bar.dat', + 'include/bar.h', + 'bin/bar' + exe_suffix, + 'bar/barfile' + ] + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() == 'msvc': + main_expected.append('bin/foo.pdb') + bar_expected.append('bin/bar.pdb') + prefix = destdir_join(self.installdir, self.prefix) + main_expected = [Path(prefix, p) for p in main_expected] + bar_expected = [Path(prefix, p) for p in bar_expected] + all_expected = main_expected + bar_expected + + def check_installed_files(extra_args, expected): + args = ['install', '--destdir', self.installdir] + extra_args + self._run(self.meson_command + args, workdir=self.builddir) + all_files = [p for p in Path(self.installdir).rglob('*')] + self.assertEqual(sorted(expected), sorted(all_files)) + windows_proof_rmtree(self.installdir) + + check_installed_files([], all_expected) + check_installed_files(['--skip-subprojects'], main_expected) + check_installed_files(['--skip-subprojects', 'bar'], main_expected) + check_installed_files(['--skip-subprojects', 'another'], all_expected) + + def test_adding_subproject_to_configure_project(self) -> None: + srcdir = os.path.join(self.unit_test_dir, '93 new subproject in configured project') + self.init(srcdir) + self.build() + self.setconf('-Duse-sub=true') + self.build() + + def test_devenv(self): + testdir = os.path.join(self.unit_test_dir, '90 devenv') + self.init(testdir) + self.build() + + cmd = self.meson_command + ['devenv', '-C', self.builddir] + script = os.path.join(testdir, 'test-devenv.py') + app = os.path.join(self.builddir, 'app') + self._run(cmd + python_command + [script]) + self.assertEqual('This is text.', self._run(cmd + [app]).strip()) + + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump'] + o = self._run(cmd) + expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertIn('export TEST_C', o) + + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', '--dump-format', 'sh'] + o = self._run(cmd) + expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertNotIn('export', o) + + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', '--dump-format', 'vscode'] + o = self._run(cmd) + expected = os.pathsep.join(['/prefix', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertNotIn('export', o) + + fname = os.path.join(self.builddir, 'dump.env') + cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', fname] + o = self._run(cmd) + self.assertEqual(o, '') + o = Path(fname).read_text(encoding='utf-8') + expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix']) + self.assertIn(f'TEST_C="{expected}"', o) + self.assertIn('export TEST_C', o) + + def test_clang_format_check(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Skipping clang-format tests with {self.backend.name} backend') + if not shutil.which('clang-format'): + raise SkipTest('clang-format not found') + + testdir = os.path.join(self.unit_test_dir, '94 clangformat') + newdir = os.path.join(self.builddir, 'testdir') + shutil.copytree(testdir, newdir) + self.new_builddir() + self.init(newdir) + + # Should reformat 1 file but not return error + output = self.build('clang-format') + self.assertEqual(1, output.count('File reformatted:')) + + # Reset source tree then try again with clang-format-check, it should + # return an error code this time. + windows_proof_rmtree(newdir) + shutil.copytree(testdir, newdir) + with self.assertRaises(subprocess.CalledProcessError): + output = self.build('clang-format-check') + self.assertEqual(1, output.count('File reformatted:')) + + # The check format should not touch any files. Thus + # running format again has some work to do. + output = self.build('clang-format') + self.assertEqual(1, output.count('File reformatted:')) + self.build('clang-format-check') + + def test_custom_target_implicit_include(self): + testdir = os.path.join(self.unit_test_dir, '95 custominc') + self.init(testdir) + self.build() + compdb = self.get_compdb() + matches = 0 + for c in compdb: + if 'prog.c' in c['file']: + self.assertNotIn('easytogrepfor', c['command']) + matches += 1 + self.assertEqual(matches, 1) + matches = 0 + for c in compdb: + if 'prog2.c' in c['file']: + self.assertIn('easytogrepfor', c['command']) + matches += 1 + self.assertEqual(matches, 1) + + def test_env_flags_to_linker(self) -> None: + # Compilers that act as drivers should add their compiler flags to the + # linker, those that do not shouldn't + with mock.patch.dict(os.environ, {'CFLAGS': '-DCFLAG', 'LDFLAGS': '-flto'}): + env = get_fake_env() + + # Get the compiler so we know which compiler class to mock. + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) + cc_type = type(cc) + + # Test a compiler that acts as a linker + with mock.patch.object(cc_type, 'INVOKES_LINKER', True): + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) + link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language) + self.assertEqual(sorted(link_args), sorted(['-DCFLAG', '-flto'])) + + # And one that doesn't + with mock.patch.object(cc_type, 'INVOKES_LINKER', False): + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) + link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language) + self.assertEqual(sorted(link_args), sorted(['-flto'])) + + def test_install_tag(self) -> None: + testdir = os.path.join(self.unit_test_dir, '99 install all targets') + self.init(testdir) + self.build() + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + + def shared_lib_name(name): + if cc.get_id() in {'msvc', 'clang-cl'}: + return f'bin/{name}.dll' + elif is_windows(): + return f'bin/lib{name}.dll' + elif is_cygwin(): + return f'bin/cyg{name}.dll' + elif is_osx(): + return f'lib/lib{name}.dylib' + return f'lib/lib{name}.so' + + def exe_name(name): + if is_windows() or is_cygwin(): + return f'{name}.exe' + return name + + installpath = Path(self.installdir) + + expected_common = { + installpath, + Path(installpath, 'usr'), + } + + expected_devel = expected_common | { + Path(installpath, 'usr/include'), + Path(installpath, 'usr/include/bar-devel.h'), + Path(installpath, 'usr/include/bar2-devel.h'), + Path(installpath, 'usr/include/foo1-devel.h'), + Path(installpath, 'usr/include/foo2-devel.h'), + Path(installpath, 'usr/include/foo3-devel.h'), + Path(installpath, 'usr/include/out-devel.h'), + Path(installpath, 'usr/lib'), + Path(installpath, 'usr/lib/libstatic.a'), + Path(installpath, 'usr/lib/libboth.a'), + Path(installpath, 'usr/lib/libboth2.a'), + Path(installpath, 'usr/include/ct-header1.h'), + Path(installpath, 'usr/include/ct-header3.h'), + Path(installpath, 'usr/include/subdir-devel'), + Path(installpath, 'usr/include/custom_files'), + Path(installpath, 'usr/include/custom_files/data.txt'), + } + + if cc.get_id() in {'msvc', 'clang-cl'}: + expected_devel |= { + Path(installpath, 'usr/bin'), + Path(installpath, 'usr/bin/app.pdb'), + Path(installpath, 'usr/bin/app2.pdb'), + Path(installpath, 'usr/bin/both.pdb'), + Path(installpath, 'usr/bin/both2.pdb'), + Path(installpath, 'usr/bin/bothcustom.pdb'), + Path(installpath, 'usr/bin/shared.pdb'), + Path(installpath, 'usr/bin/versioned_shared-1.pdb'), + Path(installpath, 'usr/lib/both.lib'), + Path(installpath, 'usr/lib/both2.lib'), + Path(installpath, 'usr/lib/bothcustom.lib'), + Path(installpath, 'usr/lib/shared.lib'), + Path(installpath, 'usr/lib/versioned_shared.lib'), + Path(installpath, 'usr/otherbin'), + Path(installpath, 'usr/otherbin/app-otherdir.pdb'), + } + elif is_windows() or is_cygwin(): + expected_devel |= { + Path(installpath, 'usr/lib/libboth.dll.a'), + Path(installpath, 'usr/lib/libboth2.dll.a'), + Path(installpath, 'usr/lib/libshared.dll.a'), + Path(installpath, 'usr/lib/libbothcustom.dll.a'), + Path(installpath, 'usr/lib/libversioned_shared.dll.a'), + } + else: + expected_devel |= { + Path(installpath, 'usr/' + shared_lib_name('versioned_shared')), + } + + expected_runtime = expected_common | { + Path(installpath, 'usr/bin'), + Path(installpath, 'usr/bin/' + exe_name('app')), + Path(installpath, 'usr/otherbin'), + Path(installpath, 'usr/otherbin/' + exe_name('app-otherdir')), + Path(installpath, 'usr/bin/' + exe_name('app2')), + Path(installpath, 'usr/' + shared_lib_name('shared')), + Path(installpath, 'usr/' + shared_lib_name('both')), + Path(installpath, 'usr/' + shared_lib_name('both2')), + } + + if is_windows() or is_cygwin(): + expected_runtime |= { + Path(installpath, 'usr/' + shared_lib_name('versioned_shared-1')), + } + elif is_osx(): + expected_runtime |= { + Path(installpath, 'usr/' + shared_lib_name('versioned_shared.1')), + } + else: + expected_runtime |= { + Path(installpath, 'usr/' + shared_lib_name('versioned_shared') + '.1'), + Path(installpath, 'usr/' + shared_lib_name('versioned_shared') + '.1.2.3'), + } + + expected_custom = expected_common | { + Path(installpath, 'usr/share'), + Path(installpath, 'usr/share/bar-custom.txt'), + Path(installpath, 'usr/share/foo-custom.h'), + Path(installpath, 'usr/share/out1-custom.txt'), + Path(installpath, 'usr/share/out2-custom.txt'), + Path(installpath, 'usr/share/out3-custom.txt'), + Path(installpath, 'usr/share/custom_files'), + Path(installpath, 'usr/share/custom_files/data.txt'), + Path(installpath, 'usr/share/excludes'), + Path(installpath, 'usr/share/excludes/installed.txt'), + Path(installpath, 'usr/lib'), + Path(installpath, 'usr/lib/libbothcustom.a'), + Path(installpath, 'usr/' + shared_lib_name('bothcustom')), + } + + if is_windows() or is_cygwin(): + expected_custom |= {Path(installpath, 'usr/bin')} + else: + expected_runtime |= {Path(installpath, 'usr/lib')} + + expected_runtime_custom = expected_runtime | expected_custom + + expected_all = expected_devel | expected_runtime | expected_custom | { + Path(installpath, 'usr/share/foo-notag.h'), + Path(installpath, 'usr/share/bar-notag.txt'), + Path(installpath, 'usr/share/out1-notag.txt'), + Path(installpath, 'usr/share/out2-notag.txt'), + Path(installpath, 'usr/share/out3-notag.txt'), + Path(installpath, 'usr/share/foo2.h'), + Path(installpath, 'usr/share/out1.txt'), + Path(installpath, 'usr/share/out2.txt'), + Path(installpath, 'usr/share/install tag'), + Path(installpath, 'usr/share/install tag/aaa.txt'), + Path(installpath, 'usr/share/install tag/bbb.txt'), + } + + def do_install(tags, expected_files, expected_scripts): + cmd = self.meson_command + ['install', '--dry-run', '--destdir', self.installdir] + cmd += ['--tags', tags] if tags else [] + stdout = self._run(cmd, workdir=self.builddir) + installed = self.read_install_logs() + self.assertEqual(sorted(expected_files), sorted(installed)) + self.assertEqual(expected_scripts, stdout.count('Running custom install script')) + + do_install('devel', expected_devel, 0) + do_install('runtime', expected_runtime, 0) + do_install('custom', expected_custom, 1) + do_install('runtime,custom', expected_runtime_custom, 1) + do_install(None, expected_all, 2) + + + def test_install_script_dry_run(self): + testdir = os.path.join(self.common_test_dir, '53 install script') + self.init(testdir) + self.build() + + cmd = self.meson_command + ['install', '--dry-run', '--destdir', self.installdir] + outputs = self._run(cmd, workdir=self.builddir) + + installpath = Path(self.installdir) + self.assertFalse((installpath / 'usr/diiba/daaba/file.dat').exists()) + self.assertIn("DRYRUN: Writing file file.dat", outputs) + + + def test_introspect_install_plan(self): + testdir = os.path.join(self.unit_test_dir, '99 install all targets') + introfile = os.path.join(self.builddir, 'meson-info', 'intro-install_plan.json') + self.init(testdir) + self.assertPathExists(introfile) + with open(introfile, encoding='utf-8') as fp: + res = json.load(fp) + + env = get_fake_env(testdir, self.builddir, self.prefix) + + def output_name(name, type_): + target = type_(name=name, subdir=None, subproject=None, + for_machine=MachineChoice.HOST, sources=[], + structured_sources=None, + objects=[], environment=env, compilers=env.coredata.compilers[MachineChoice.HOST], + kwargs={}) + target.process_compilers_late() + return target.filename + + shared_lib_name = lambda name: output_name(name, SharedLibrary) + static_lib_name = lambda name: output_name(name, StaticLibrary) + exe_name = lambda name: output_name(name, Executable) + + expected = { + 'targets': { + f'{self.builddir}/out1-notag.txt': { + 'destination': '{datadir}/out1-notag.txt', + 'tag': None, + 'subproject': None, + }, + f'{self.builddir}/out2-notag.txt': { + 'destination': '{datadir}/out2-notag.txt', + 'tag': None, + 'subproject': None, + }, + f'{self.builddir}/libstatic.a': { + 'destination': '{libdir_static}/libstatic.a', + 'tag': 'devel', + 'subproject': None, + }, + f'{self.builddir}/' + exe_name('app'): { + 'destination': '{bindir}/' + exe_name('app'), + 'tag': 'runtime', + 'subproject': None, + }, + f'{self.builddir}/' + exe_name('app-otherdir'): { + 'destination': '{prefix}/otherbin/' + exe_name('app-otherdir'), + 'tag': 'runtime', + 'subproject': None, + }, + f'{self.builddir}/subdir/' + exe_name('app2'): { + 'destination': '{bindir}/' + exe_name('app2'), + 'tag': 'runtime', + 'subproject': None, + }, + f'{self.builddir}/' + shared_lib_name('shared'): { + 'destination': '{libdir_shared}/' + shared_lib_name('shared'), + 'tag': 'runtime', + 'subproject': None, + }, + f'{self.builddir}/' + shared_lib_name('both'): { + 'destination': '{libdir_shared}/' + shared_lib_name('both'), + 'tag': 'runtime', + 'subproject': None, + }, + f'{self.builddir}/' + static_lib_name('both'): { + 'destination': '{libdir_static}/' + static_lib_name('both'), + 'tag': 'devel', + 'subproject': None, + }, + f'{self.builddir}/' + shared_lib_name('bothcustom'): { + 'destination': '{libdir_shared}/' + shared_lib_name('bothcustom'), + 'tag': 'custom', + 'subproject': None, + }, + f'{self.builddir}/' + static_lib_name('bothcustom'): { + 'destination': '{libdir_static}/' + static_lib_name('bothcustom'), + 'tag': 'custom', + 'subproject': None, + }, + f'{self.builddir}/subdir/' + shared_lib_name('both2'): { + 'destination': '{libdir_shared}/' + shared_lib_name('both2'), + 'tag': 'runtime', + 'subproject': None, + }, + f'{self.builddir}/subdir/' + static_lib_name('both2'): { + 'destination': '{libdir_static}/' + static_lib_name('both2'), + 'tag': 'devel', + 'subproject': None, + }, + f'{self.builddir}/out1-custom.txt': { + 'destination': '{datadir}/out1-custom.txt', + 'tag': 'custom', + 'subproject': None, + }, + f'{self.builddir}/out2-custom.txt': { + 'destination': '{datadir}/out2-custom.txt', + 'tag': 'custom', + 'subproject': None, + }, + f'{self.builddir}/out3-custom.txt': { + 'destination': '{datadir}/out3-custom.txt', + 'tag': 'custom', + 'subproject': None, + }, + f'{self.builddir}/subdir/out1.txt': { + 'destination': '{datadir}/out1.txt', + 'tag': None, + 'subproject': None, + }, + f'{self.builddir}/subdir/out2.txt': { + 'destination': '{datadir}/out2.txt', + 'tag': None, + 'subproject': None, + }, + f'{self.builddir}/out-devel.h': { + 'destination': '{includedir}/out-devel.h', + 'tag': 'devel', + 'subproject': None, + }, + f'{self.builddir}/out3-notag.txt': { + 'destination': '{datadir}/out3-notag.txt', + 'tag': None, + 'subproject': None, + }, + }, + 'configure': { + f'{self.builddir}/foo-notag.h': { + 'destination': '{datadir}/foo-notag.h', + 'tag': None, + 'subproject': None, + }, + f'{self.builddir}/foo2-devel.h': { + 'destination': '{includedir}/foo2-devel.h', + 'tag': 'devel', + 'subproject': None, + }, + f'{self.builddir}/foo-custom.h': { + 'destination': '{datadir}/foo-custom.h', + 'tag': 'custom', + 'subproject': None, + }, + f'{self.builddir}/subdir/foo2.h': { + 'destination': '{datadir}/foo2.h', + 'tag': None, + 'subproject': None, + }, + }, + 'data': { + f'{testdir}/bar-notag.txt': { + 'destination': '{datadir}/bar-notag.txt', + 'tag': None, + 'subproject': None, + }, + f'{testdir}/bar-devel.h': { + 'destination': '{includedir}/bar-devel.h', + 'tag': 'devel', + 'subproject': None, + }, + f'{testdir}/bar-custom.txt': { + 'destination': '{datadir}/bar-custom.txt', + 'tag': 'custom', + 'subproject': None, + }, + f'{testdir}/subdir/bar2-devel.h': { + 'destination': '{includedir}/bar2-devel.h', + 'tag': 'devel', + 'subproject': None, + }, + f'{testdir}/subprojects/subproject/aaa.txt': { + 'destination': '{datadir}/install tag/aaa.txt', + 'tag': None, + 'subproject': 'subproject', + }, + f'{testdir}/subprojects/subproject/bbb.txt': { + 'destination': '{datadir}/install tag/bbb.txt', + 'tag': 'data', + 'subproject': 'subproject', + }, + }, + 'headers': { + f'{testdir}/foo1-devel.h': { + 'destination': '{includedir}/foo1-devel.h', + 'tag': 'devel', + 'subproject': None, + }, + f'{testdir}/subdir/foo3-devel.h': { + 'destination': '{includedir}/foo3-devel.h', + 'tag': 'devel', + 'subproject': None, + }, + }, + 'install_subdirs': { + f'{testdir}/custom_files': { + 'destination': '{datadir}/custom_files', + 'tag': 'custom', + 'subproject': None, + 'exclude_dirs': [], + 'exclude_files': [], + }, + f'{testdir}/excludes': { + 'destination': '{datadir}/excludes', + 'tag': 'custom', + 'subproject': None, + 'exclude_dirs': ['excluded'], + 'exclude_files': ['excluded.txt'], + } + } + } + + fix_path = lambda path: os.path.sep.join(path.split('/')) + expected_fixed = { + data_type: { + fix_path(source): { + key: fix_path(value) if key == 'destination' else value + for key, value in attributes.items() + } + for source, attributes in files.items() + } + for data_type, files in expected.items() + } + + for data_type, files in expected_fixed.items(): + for file, details in files.items(): + with self.subTest(key='{}.{}'.format(data_type, file)): + self.assertEqual(res[data_type][file], details) + + @skip_if_not_language('rust') + @unittest.skipIf(not shutil.which('clippy-driver'), 'Test requires clippy-driver') + def test_rust_clippy(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + # When clippy is used, we should get an exception since a variable named + # "foo" is used, but is on our denylist + testdir = os.path.join(self.rust_test_dir, '1 basic') + self.init(testdir, extra_args=['--werror'], override_envvars={'RUSTC': 'clippy-driver'}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.build() + self.assertTrue('error: use of a blacklisted/placeholder name `foo`' in cm.exception.stdout or + 'error: use of a disallowed/placeholder name `foo`' in cm.exception.stdout) + + @skip_if_not_language('rust') + def test_rust_rlib_linkage(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + template = textwrap.dedent('''\ + use std::process::exit; + + pub fn fun() {{ + exit({}); + }} + ''') + + testdir = os.path.join(self.unit_test_dir, '102 rlib linkage') + gen_file = os.path.join(testdir, 'lib.rs') + with open(gen_file, 'w', encoding='utf-8') as f: + f.write(template.format(0)) + self.addCleanup(windows_proof_rm, gen_file) + + self.init(testdir) + self.build() + self.run_tests() + + with open(gen_file, 'w', encoding='utf-8') as f: + f.write(template.format(39)) + + self.build() + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.run_tests() + self.assertEqual(cm.exception.returncode, 1) + self.assertIn('exit status 39', cm.exception.stdout) + + def test_custom_target_name(self): + testdir = os.path.join(self.unit_test_dir, '100 custom target name') + self.init(testdir) + out = self.build() + if self.backend is Backend.ninja: + self.assertIn('Generating file.txt with a custom command', out) + self.assertIn('Generating subdir/file.txt with a custom command', out) + + def test_symlinked_subproject(self): + testdir = os.path.join(self.unit_test_dir, '107 subproject symlink') + subproject_dir = os.path.join(testdir, 'subprojects') + subproject = os.path.join(testdir, 'symlinked_subproject') + symlinked_subproject = os.path.join(testdir, 'subprojects', 'symlinked_subproject') + if not os.path.exists(subproject_dir): + os.mkdir(subproject_dir) + try: + os.symlink(subproject, symlinked_subproject) + except OSError: + raise SkipTest("Symlinks are not available on this machine") + self.addCleanup(os.remove, symlinked_subproject) + + self.init(testdir) + self.build() + + def test_configure_same_noop(self): + testdir = os.path.join(self.unit_test_dir, '109 configure same noop') + args = [ + '-Dstring=val', + '-Dboolean=true', + '-Dcombo=two', + '-Dinteger=7', + '-Darray=[\'three\']', + '-Dfeature=disabled', + '--buildtype=plain', + '--prefix=/abc', + ] + self.init(testdir, extra_args=args) + + filename = Path(self.privatedir) / 'coredata.dat' + + olddata = filename.read_bytes() + oldmtime = os.path.getmtime(filename) + + for opt in ('-Dstring=val', '--buildtype=plain', '-Dfeature=disabled', '-Dprefix=/abc'): + self.setconf([opt]) + newdata = filename.read_bytes() + newmtime = os.path.getmtime(filename) + self.assertEqual(oldmtime, newmtime) + self.assertEqual(olddata, newdata) + olddata = newdata + oldmtime = newmtime + + for opt in ('-Dstring=abc', '--buildtype=release', '-Dfeature=enabled', '-Dprefix=/def'): + self.setconf([opt]) + newdata = filename.read_bytes() + newmtime = os.path.getmtime(filename) + self.assertGreater(newmtime, oldmtime) + self.assertNotEqual(olddata, newdata) + olddata = newdata + oldmtime = newmtime diff --git a/devtools/meson/unittests/baseplatformtests.py b/devtools/meson/unittests/baseplatformtests.py new file mode 100644 index 0000000..4b16e7d --- /dev/null +++ b/devtools/meson/unittests/baseplatformtests.py @@ -0,0 +1,497 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import PurePath +from unittest import mock, TestCase, SkipTest +import json +import io +import os +import re +import subprocess +import sys +import tempfile +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.compilers +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + is_cygwin, join_args, split_args, windows_proof_rmtree, python_command +) +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + Backend, ensure_backend_detects_changes, get_backend_commands, + get_builddir_target_args, get_meson_script, run_configure_inprocess, + run_mtest_inprocess +) + + +# magic attribute used by unittest.result.TestResult._is_relevant_tb_level +# This causes tracebacks to hide these internal implementation details, +# e.g. for assertXXX helpers. +__unittest = True + +class BasePlatformTests(TestCase): + prefix = '/usr' + libdir = 'lib' + + def setUp(self): + super().setUp() + self.maxDiff = None + src_root = str(PurePath(__file__).parents[1]) + self.src_root = src_root + # Get the backend + self.backend_name = os.environ['MESON_UNIT_TEST_BACKEND'] + backend_type = 'vs' if self.backend_name.startswith('vs') else self.backend_name + self.backend = getattr(Backend, backend_type) + self.meson_args = ['--backend=' + self.backend_name] + self.meson_native_files = [] + self.meson_cross_files = [] + self.meson_command = python_command + [get_meson_script()] + self.setup_command = self.meson_command + ['setup'] + self.meson_args + self.mconf_command = self.meson_command + ['configure'] + self.mintro_command = self.meson_command + ['introspect'] + self.wrap_command = self.meson_command + ['wrap'] + self.rewrite_command = self.meson_command + ['rewrite'] + # Backend-specific build commands + self.build_command, self.clean_command, self.test_command, self.install_command, \ + self.uninstall_command = get_backend_commands(self.backend) + # Test directories + self.common_test_dir = os.path.join(src_root, 'test cases/common') + self.python_test_dir = os.path.join(src_root, 'test cases/python') + self.rust_test_dir = os.path.join(src_root, 'test cases/rust') + self.vala_test_dir = os.path.join(src_root, 'test cases/vala') + self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks') + self.unit_test_dir = os.path.join(src_root, 'test cases/unit') + self.rewrite_test_dir = os.path.join(src_root, 'test cases/rewrite') + self.linuxlike_test_dir = os.path.join(src_root, 'test cases/linuxlike') + self.objc_test_dir = os.path.join(src_root, 'test cases/objc') + self.objcpp_test_dir = os.path.join(src_root, 'test cases/objcpp') + + # Misc stuff + self.orig_env = os.environ.copy() + if self.backend is Backend.ninja: + self.no_rebuild_stdout = ['ninja: no work to do.', 'samu: nothing to do'] + else: + # VS doesn't have a stable output when no changes are done + # XCode backend is untested with unit tests, help welcome! + self.no_rebuild_stdout = [f'UNKNOWN BACKEND {self.backend.name!r}'] + os.environ['COLUMNS'] = '80' + + self.builddirs = [] + self.new_builddir() + + def change_builddir(self, newdir): + self.builddir = newdir + self.privatedir = os.path.join(self.builddir, 'meson-private') + self.logdir = os.path.join(self.builddir, 'meson-logs') + self.installdir = os.path.join(self.builddir, 'install') + self.distdir = os.path.join(self.builddir, 'meson-dist') + self.mtest_command = self.meson_command + ['test', '-C', self.builddir] + self.builddirs.append(self.builddir) + + def new_builddir(self): + # Keep builddirs inside the source tree so that virus scanners + # don't complain + newdir = tempfile.mkdtemp(dir=os.getcwd()) + # In case the directory is inside a symlinked directory, find the real + # path otherwise we might not find the srcdir from inside the builddir. + newdir = os.path.realpath(newdir) + self.change_builddir(newdir) + + def new_builddir_in_tempdir(self): + # Can't keep the builddir inside the source tree for the umask tests: + # https://github.com/mesonbuild/meson/pull/5546#issuecomment-509666523 + # And we can't do this for all tests because it causes the path to be + # a short-path which breaks other tests: + # https://github.com/mesonbuild/meson/pull/9497 + newdir = tempfile.mkdtemp() + # In case the directory is inside a symlinked directory, find the real + # path otherwise we might not find the srcdir from inside the builddir. + newdir = os.path.realpath(newdir) + self.change_builddir(newdir) + + def _open_meson_log(self) -> io.TextIOWrapper: + log = os.path.join(self.logdir, 'meson-log.txt') + return open(log, encoding='utf-8') + + def _get_meson_log(self) -> T.Optional[str]: + try: + with self._open_meson_log() as f: + return f.read() + except FileNotFoundError as e: + print(f"{e.filename!r} doesn't exist", file=sys.stderr) + return None + + def _print_meson_log(self) -> None: + log = self._get_meson_log() + if log: + print(log) + + def tearDown(self): + for path in self.builddirs: + try: + windows_proof_rmtree(path) + except FileNotFoundError: + pass + os.environ.clear() + os.environ.update(self.orig_env) + super().tearDown() + + def _run(self, command, *, workdir=None, override_envvars: T.Optional[T.Mapping[str, str]] = None, stderr=True): + ''' + Run a command while printing the stdout and stderr to stdout, + and also return a copy of it + ''' + # If this call hangs CI will just abort. It is very hard to distinguish + # between CI issue and test bug in that case. Set timeout and fail loud + # instead. + if override_envvars is None: + env = None + else: + env = os.environ.copy() + env.update(override_envvars) + + p = subprocess.run(command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if stderr else subprocess.PIPE, + env=env, + encoding='utf-8', + text=True, cwd=workdir, timeout=60 * 5) + print('$', join_args(command)) + print('stdout:') + print(p.stdout) + if not stderr: + print('stderr:') + print(p.stderr) + if p.returncode != 0: + if 'MESON_SKIP_TEST' in p.stdout: + raise SkipTest('Project requested skipping.') + raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) + return p.stdout + + def init(self, srcdir, *, + extra_args=None, + default_args=True, + inprocess=False, + override_envvars: T.Optional[T.Mapping[str, str]] = None, + workdir=None, + allow_fail: bool = False) -> str: + """Call `meson setup` + + :param allow_fail: If set to true initialization is allowed to fail. + When it does the log will be returned instead of stdout. + :return: the value of stdout on success, or the meson log on failure + when :param allow_fail: is true + """ + self.assertPathExists(srcdir) + if extra_args is None: + extra_args = [] + if not isinstance(extra_args, list): + extra_args = [extra_args] + build_and_src_dir_args = [self.builddir, srcdir] + args = [] + if default_args: + args += ['--prefix', self.prefix] + if self.libdir: + args += ['--libdir', self.libdir] + for f in self.meson_native_files: + args += ['--native-file', f] + for f in self.meson_cross_files: + args += ['--cross-file', f] + self.privatedir = os.path.join(self.builddir, 'meson-private') + if inprocess: + try: + returncode, out, err = run_configure_inprocess(['setup'] + self.meson_args + args + extra_args + build_and_src_dir_args, override_envvars) + except Exception as e: + if not allow_fail: + self._print_meson_log() + raise + out = self._get_meson_log() # Best we can do here + err = '' # type checkers can't figure out that on this path returncode will always be 0 + returncode = 0 + finally: + # Close log file to satisfy Windows file locking + mesonbuild.mlog.shutdown() + mesonbuild.mlog._logger.log_dir = None + mesonbuild.mlog._logger.log_file = None + + if 'MESON_SKIP_TEST' in out: + raise SkipTest('Project requested skipping.') + if returncode != 0: + self._print_meson_log() + print('Stdout:\n') + print(out) + print('Stderr:\n') + print(err) + if not allow_fail: + raise RuntimeError('Configure failed') + else: + try: + out = self._run(self.setup_command + args + extra_args + build_and_src_dir_args, override_envvars=override_envvars, workdir=workdir) + except SkipTest: + raise SkipTest('Project requested skipping: ' + srcdir) + except Exception: + if not allow_fail: + self._print_meson_log() + raise + out = self._get_meson_log() # best we can do here + return out + + def build(self, target=None, *, extra_args=None, override_envvars=None, stderr=True): + if extra_args is None: + extra_args = [] + # Add arguments for building the target (if specified), + # and using the build dir (if required, with VS) + args = get_builddir_target_args(self.backend, self.builddir, target) + return self._run(self.build_command + args + extra_args, workdir=self.builddir, override_envvars=override_envvars, stderr=stderr) + + def clean(self, *, override_envvars=None): + dir_args = get_builddir_target_args(self.backend, self.builddir, None) + self._run(self.clean_command + dir_args, workdir=self.builddir, override_envvars=override_envvars) + + def run_tests(self, *, inprocess=False, override_envvars=None): + if not inprocess: + return self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars) + else: + with mock.patch.dict(os.environ, override_envvars): + return run_mtest_inprocess(['-C', self.builddir])[1] + + def install(self, *, use_destdir=True, override_envvars=None): + if self.backend is not Backend.ninja: + raise SkipTest(f'{self.backend.name!r} backend can\'t install files') + if use_destdir: + destdir = {'DESTDIR': self.installdir} + if override_envvars is None: + override_envvars = destdir + else: + override_envvars.update(destdir) + return self._run(self.install_command, workdir=self.builddir, override_envvars=override_envvars) + + def uninstall(self, *, override_envvars=None): + self._run(self.uninstall_command, workdir=self.builddir, override_envvars=override_envvars) + + def run_target(self, target, *, override_envvars=None): + ''' + Run a Ninja target while printing the stdout and stderr to stdout, + and also return a copy of it + ''' + return self.build(target=target, override_envvars=override_envvars) + + def setconf(self, arg, will_build=True): + if not isinstance(arg, list): + arg = [arg] + if will_build: + ensure_backend_detects_changes(self.backend) + self._run(self.mconf_command + arg + [self.builddir]) + + def wipe(self): + windows_proof_rmtree(self.builddir) + + def utime(self, f): + ensure_backend_detects_changes(self.backend) + os.utime(f) + + def get_compdb(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Compiler db not available with {self.backend.name} backend') + try: + with open(os.path.join(self.builddir, 'compile_commands.json'), encoding='utf-8') as ifile: + contents = json.load(ifile) + except FileNotFoundError: + raise SkipTest('Compiler db not found') + # If Ninja is using .rsp files, generate them, read their contents, and + # replace it as the command for all compile commands in the parsed json. + if len(contents) > 0 and contents[0]['command'].endswith('.rsp'): + # Pretend to build so that the rsp files are generated + self.build(extra_args=['-d', 'keeprsp', '-n']) + for each in contents: + # Extract the actual command from the rsp file + compiler, rsp = each['command'].split(' @') + rsp = os.path.join(self.builddir, rsp) + # Replace the command with its contents + with open(rsp, encoding='utf-8') as f: + each['command'] = compiler + ' ' + f.read() + return contents + + def get_meson_log_raw(self): + with self._open_meson_log() as f: + return f.read() + + def get_meson_log(self): + with self._open_meson_log() as f: + return f.readlines() + + def get_meson_log_compiler_checks(self): + ''' + Fetch a list command-lines run by meson for compiler checks. + Each command-line is returned as a list of arguments. + ''' + prefix = 'Command line: `' + suffix = '` -> 0\n' + with self._open_meson_log() as log: + cmds = [split_args(l[len(prefix):-len(suffix)]) for l in log if l.startswith(prefix)] + return cmds + + def get_meson_log_sanitychecks(self): + ''' + Same as above, but for the sanity checks that were run + ''' + prefix = 'Sanity check compiler command line:' + with self._open_meson_log() as log: + cmds = [l[len(prefix):].split() for l in log if l.startswith(prefix)] + return cmds + + def introspect(self, args): + if isinstance(args, str): + args = [args] + out = subprocess.check_output(self.mintro_command + args + [self.builddir], + universal_newlines=True) + return json.loads(out) + + def introspect_directory(self, directory, args): + if isinstance(args, str): + args = [args] + out = subprocess.check_output(self.mintro_command + args + [directory], + universal_newlines=True) + try: + obj = json.loads(out) + except Exception as e: + print(out) + raise e + return obj + + def assertPathEqual(self, path1, path2): + ''' + Handles a lot of platform-specific quirks related to paths such as + separator, case-sensitivity, etc. + ''' + self.assertEqual(PurePath(path1), PurePath(path2)) + + def assertPathListEqual(self, pathlist1, pathlist2): + self.assertEqual(len(pathlist1), len(pathlist2)) + worklist = list(zip(pathlist1, pathlist2)) + for i in worklist: + if i[0] is None: + self.assertEqual(i[0], i[1]) + else: + self.assertPathEqual(i[0], i[1]) + + def assertPathBasenameEqual(self, path, basename): + msg = f'{path!r} does not end with {basename!r}' + # We cannot use os.path.basename because it returns '' when the path + # ends with '/' for some silly reason. This is not how the UNIX utility + # `basename` works. + path_basename = PurePath(path).parts[-1] + self.assertEqual(PurePath(path_basename), PurePath(basename), msg) + + def assertReconfiguredBuildIsNoop(self): + 'Assert that we reconfigured and then there was nothing to do' + ret = self.build(stderr=False) + self.assertIn('The Meson build system', ret) + if self.backend is Backend.ninja: + for line in ret.split('\n'): + if line in self.no_rebuild_stdout: + break + else: + raise AssertionError('build was reconfigured, but was not no-op') + elif self.backend is Backend.vs: + # Ensure that some target said that no rebuild was done + # XXX: Note CustomBuild did indeed rebuild, because of the regen checker! + self.assertIn('ClCompile:\n All outputs are up-to-date.', ret) + self.assertIn('Link:\n All outputs are up-to-date.', ret) + # Ensure that no targets were built + self.assertNotRegex(ret, re.compile('ClCompile:\n [^\n]*cl', flags=re.IGNORECASE)) + self.assertNotRegex(ret, re.compile('Link:\n [^\n]*link', flags=re.IGNORECASE)) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + def assertBuildIsNoop(self): + ret = self.build(stderr=False) + if self.backend is Backend.ninja: + self.assertIn(ret.split('\n')[-2], self.no_rebuild_stdout) + elif self.backend is Backend.vs: + # Ensure that some target of each type said that no rebuild was done + # We always have at least one CustomBuild target for the regen checker + self.assertIn('CustomBuild:\n All outputs are up-to-date.', ret) + self.assertIn('ClCompile:\n All outputs are up-to-date.', ret) + self.assertIn('Link:\n All outputs are up-to-date.', ret) + # Ensure that no targets were built + self.assertNotRegex(ret, re.compile('CustomBuild:\n [^\n]*cl', flags=re.IGNORECASE)) + self.assertNotRegex(ret, re.compile('ClCompile:\n [^\n]*cl', flags=re.IGNORECASE)) + self.assertNotRegex(ret, re.compile('Link:\n [^\n]*link', flags=re.IGNORECASE)) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + def assertRebuiltTarget(self, target): + ret = self.build() + if self.backend is Backend.ninja: + self.assertIn(f'Linking target {target}', ret) + elif self.backend is Backend.vs: + # Ensure that this target was rebuilt + linkre = re.compile('Link:\n [^\n]*link[^\n]*' + target, flags=re.IGNORECASE) + self.assertRegex(ret, linkre) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + @staticmethod + def get_target_from_filename(filename): + base = os.path.splitext(filename)[0] + if base.startswith(('lib', 'cyg')): + return base[3:] + return base + + def assertBuildRelinkedOnlyTarget(self, target): + ret = self.build() + if self.backend is Backend.ninja: + linked_targets = [] + for line in ret.split('\n'): + if 'Linking target' in line: + fname = line.rsplit('target ')[-1] + linked_targets.append(self.get_target_from_filename(fname)) + self.assertEqual(linked_targets, [target]) + elif self.backend is Backend.vs: + # Ensure that this target was rebuilt + linkre = re.compile(r'Link:\n [^\n]*link.exe[^\n]*/OUT:".\\([^"]*)"', flags=re.IGNORECASE) + matches = linkre.findall(ret) + self.assertEqual(len(matches), 1, msg=matches) + self.assertEqual(self.get_target_from_filename(matches[0]), target) + elif self.backend is Backend.xcode: + raise SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError(f'Invalid backend: {self.backend.name!r}') + + def assertPathExists(self, path): + m = f'Path {path!r} should exist' + self.assertTrue(os.path.exists(path), msg=m) + + def assertPathDoesNotExist(self, path): + m = f'Path {path!r} should not exist' + self.assertFalse(os.path.exists(path), msg=m) + + def assertLength(self, val, length): + assert len(val) == length, f'{val} is not length {length}' diff --git a/devtools/meson/unittests/cargotests.py b/devtools/meson/unittests/cargotests.py new file mode 100644 index 0000000..61b64b1 --- /dev/null +++ b/devtools/meson/unittests/cargotests.py @@ -0,0 +1,186 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2022-2023 Intel Corporation + +from __future__ import annotations +import unittest +import typing as T + +from mesonbuild.cargo import builder, cfg +from mesonbuild.cargo.cfg import TokenType +from mesonbuild.cargo.version import convert + + +class CargoVersionTest(unittest.TestCase): + + def test_cargo_to_meson(self) -> None: + cases: T.List[T.Tuple[str, T.List[str]]] = [ + # Basic requirements + ('>= 1', ['>= 1']), + ('> 1', ['> 1']), + ('= 1', ['= 1']), + ('< 1', ['< 1']), + ('<= 1', ['<= 1']), + + # tilde tests + ('~1', ['>= 1', '< 2']), + ('~1.1', ['>= 1.1', '< 1.2']), + ('~1.1.2', ['>= 1.1.2', '< 1.2.0']), + + # Wildcards + ('*', []), + ('1.*', ['>= 1', '< 2']), + ('2.3.*', ['>= 2.3', '< 2.4']), + + # Unqualified + ('2', ['>= 2', '< 3']), + ('2.4', ['>= 2.4', '< 3']), + ('2.4.5', ['>= 2.4.5', '< 3']), + ('0.0.0', ['< 1']), + ('0.0', ['< 1']), + ('0', ['< 1']), + ('0.0.5', ['>= 0.0.5', '< 0.0.6']), + ('0.5.0', ['>= 0.5', '< 0.6']), + ('0.5', ['>= 0.5', '< 0.6']), + + # Caret (Which is the same as unqualified) + ('^2', ['>= 2', '< 3']), + ('^2.4', ['>= 2.4', '< 3']), + ('^2.4.5', ['>= 2.4.5', '< 3']), + ('^0.0.0', ['< 1']), + ('^0.0', ['< 1']), + ('^0', ['< 1']), + ('^0.0.5', ['>= 0.0.5', '< 0.0.6']), + ('^0.5.0', ['>= 0.5', '< 0.6']), + ('^0.5', ['>= 0.5', '< 0.6']), + + # Multiple requirements + ('>= 1.2.3, < 1.4.7', ['>= 1.2.3', '< 1.4.7']), + ] + + for (data, expected) in cases: + with self.subTest(): + self.assertListEqual(convert(data), expected) + + +class CargoCfgTest(unittest.TestCase): + + def test_lex(self) -> None: + cases: T.List[T.Tuple[str, T.List[T.Tuple[TokenType, T.Optional[str]]]]] = [ + ('"unix"', [(TokenType.STRING, 'unix')]), + ('unix', [(TokenType.IDENTIFIER, 'unix')]), + ('not(unix)', [ + (TokenType.NOT, None), + (TokenType.LPAREN, None), + (TokenType.IDENTIFIER, 'unix'), + (TokenType.RPAREN, None), + ]), + ('any(unix, windows)', [ + (TokenType.ANY, None), + (TokenType.LPAREN, None), + (TokenType.IDENTIFIER, 'unix'), + (TokenType.COMMA, None), + (TokenType.IDENTIFIER, 'windows'), + (TokenType.RPAREN, None), + ]), + ('target_arch = "x86_64"', [ + (TokenType.IDENTIFIER, 'target_arch'), + (TokenType.EQUAL, None), + (TokenType.STRING, 'x86_64'), + ]), + ('all(target_arch = "x86_64", unix)', [ + (TokenType.ALL, None), + (TokenType.LPAREN, None), + (TokenType.IDENTIFIER, 'target_arch'), + (TokenType.EQUAL, None), + (TokenType.STRING, 'x86_64'), + (TokenType.COMMA, None), + (TokenType.IDENTIFIER, 'unix'), + (TokenType.RPAREN, None), + ]), + ] + for data, expected in cases: + with self.subTest(): + self.assertListEqual(list(cfg.lexer(data)), expected) + + def test_parse(self) -> None: + cases = [ + ('target_os = "windows"', cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "windows"))), + ('target_arch = "x86"', cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86"))), + ('target_family = "unix"', cfg.Equal('', cfg.Identifier('', "target_family"), cfg.String('', "unix"))), + ('any(target_arch = "x86", target_arch = "x86_64")', + cfg.Any( + '', [ + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86_64")), + ])), + ('all(target_arch = "x86", target_os = "linux")', + cfg.All( + '', [ + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), + cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "linux")), + ])), + ('not(all(target_arch = "x86", target_os = "linux"))', + cfg.Not( + '', + cfg.All( + '', [ + cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), + cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "linux")), + ]))), + ] + for data, expected in cases: + with self.subTest(): + self.assertEqual(cfg.parse(iter(cfg.lexer(data)), ''), expected) + + def test_ir_to_meson(self) -> None: + HOST_MACHINE = builder.identifier('host_machine', '') + + cases = [ + ('target_os = "windows"', + builder.equal(builder.method('system', HOST_MACHINE), + builder.string('windows', ''))), + ('target_arch = "x86"', + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', ''))), + ('target_family = "unix"', + builder.equal(builder.method('system', HOST_MACHINE), + builder.string('unix', ''))), + ('not(target_arch = "x86")', + builder.not_(builder.equal( + builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), '')), + ('any(target_arch = "x86", target_arch = "x86_64")', + builder.or_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')))), + ('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', + builder.or_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.or_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('aarch64', ''))))), + ('all(target_arch = "x86", target_arch = "x86_64")', + builder.and_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')))), + ('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', + builder.and_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86', '')), + builder.and_( + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('x86_64', '')), + builder.equal(builder.method('cpu_family', HOST_MACHINE), + builder.string('aarch64', ''))))), + ] + for data, expected in cases: + with self.subTest(): + value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data)), '')) + self.assertEqual(value, expected) diff --git a/devtools/meson/unittests/darwintests.py b/devtools/meson/unittests/darwintests.py new file mode 100644 index 0000000..1f17760 --- /dev/null +++ b/devtools/meson/unittests/darwintests.py @@ -0,0 +1,155 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import re +import os +import unittest + +from mesonbuild.mesonlib import ( + MachineChoice, is_osx +) +from mesonbuild.compilers import ( + detect_c_compiler +) + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@unittest.skipUnless(is_osx(), "requires Darwin") +class DarwinTests(BasePlatformTests): + ''' + Tests that should run on macOS + ''' + + def setUp(self): + super().setUp() + self.platform_test_dir = os.path.join(self.src_root, 'test cases/osx') + + def test_apple_bitcode(self): + ''' + Test that -fembed-bitcode is correctly added while compiling and + -bitcode_bundle is added while linking when b_bitcode is true and not + when it is false. This can't be an ordinary test case because we need + to inspect the compiler database. + ''' + testdir = os.path.join(self.platform_test_dir, '7 bitcode') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.id != 'clang': + raise unittest.SkipTest('Not using Clang on OSX') + # Try with bitcode enabled + out = self.init(testdir, extra_args='-Db_bitcode=true') + # Warning was printed + self.assertRegex(out, 'WARNING:.*b_bitcode') + # Compiler options were added + for compdb in self.get_compdb(): + if 'module' in compdb['file']: + self.assertNotIn('-fembed-bitcode', compdb['command']) + else: + self.assertIn('-fembed-bitcode', compdb['command']) + build_ninja = os.path.join(self.builddir, 'build.ninja') + # Linker options were added + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('LINK_ARGS =.*-bitcode_bundle', contents) + self.assertIsNotNone(m, msg=contents) + # Try with bitcode disabled + self.setconf('-Db_bitcode=false') + # Regenerate build + self.build() + for compdb in self.get_compdb(): + self.assertNotIn('-fembed-bitcode', compdb['command']) + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('LINK_ARGS =.*-bitcode_bundle', contents) + self.assertIsNone(m, msg=contents) + + def test_apple_bitcode_modules(self): + ''' + Same as above, just for shared_module() + ''' + testdir = os.path.join(self.common_test_dir, '148 shared module resolving symbol in executable') + # Ensure that it builds even with bitcode enabled + self.init(testdir, extra_args='-Db_bitcode=true') + self.build() + self.run_tests() + + def _get_darwin_versions(self, fname): + fname = os.path.join(self.builddir, fname) + out = subprocess.check_output(['otool', '-L', fname], universal_newlines=True) + m = re.match(r'.*version (.*), current version (.*)\)', out.split('\n')[1]) + self.assertIsNotNone(m, msg=out) + return m.groups() + + @skipIfNoPkgconfig + def test_library_versioning(self): + ''' + Ensure that compatibility_version and current_version are set correctly + ''' + testdir = os.path.join(self.platform_test_dir, '2 library versions') + self.init(testdir) + self.build() + targets = {} + for t in self.introspect('--targets'): + targets[t['name']] = t['filename'][0] if isinstance(t['filename'], list) else t['filename'] + self.assertEqual(self._get_darwin_versions(targets['some']), ('7.0.0', '7.0.0')) + self.assertEqual(self._get_darwin_versions(targets['noversion']), ('0.0.0', '0.0.0')) + self.assertEqual(self._get_darwin_versions(targets['onlyversion']), ('1.0.0', '1.0.0')) + self.assertEqual(self._get_darwin_versions(targets['onlysoversion']), ('5.0.0', '5.0.0')) + self.assertEqual(self._get_darwin_versions(targets['intver']), ('2.0.0', '2.0.0')) + self.assertEqual(self._get_darwin_versions(targets['stringver']), ('2.3.0', '2.3.0')) + self.assertEqual(self._get_darwin_versions(targets['stringlistver']), ('2.4.0', '2.4.0')) + self.assertEqual(self._get_darwin_versions(targets['intstringver']), ('1111.0.0', '2.5.0')) + self.assertEqual(self._get_darwin_versions(targets['stringlistvers']), ('2.6.0', '2.6.1')) + + def test_duplicate_rpath(self): + testdir = os.path.join(self.unit_test_dir, '10 build_rpath') + # We purposely pass a duplicate rpath to Meson, in order + # to ascertain that Meson does not call install_name_tool + # with duplicate -delete_rpath arguments, which would + # lead to erroring out on installation + env = {"LDFLAGS": "-Wl,-rpath,/foo/bar"} + self.init(testdir, override_envvars=env) + self.build() + self.install() + + def test_removing_unused_linker_args(self): + testdir = os.path.join(self.common_test_dir, '104 has arg') + env = {'CFLAGS': '-L/tmp -L /var/tmp -headerpad_max_install_names -Wl,-export_dynamic -framework Foundation'} + self.init(testdir, override_envvars=env) + + def test_objc_versions(self): + # Objective-C always uses the C standard version. + # Objective-C++ always uses the C++ standard version. + # This is what most people seem to want and in addition + # it is the only setup supported by Xcode. + testdir = os.path.join(self.objc_test_dir, '1 simple') + self.init(testdir) + self.assertIn('-std=c99', self.get_compdb()[0]['command']) + self.wipe() + testdir = os.path.join(self.objcpp_test_dir, '1 simple') + self.init(testdir) + self.assertIn('-std=c++14', self.get_compdb()[0]['command']) + + def test_darwin_get_object_archs(self): + from mesonbuild.mesonlib import darwin_get_object_archs + archs = darwin_get_object_archs('/System/Library/CoreServices/Encodings/libSymbolConverter.dylib') + self.assertEqual(archs, ['x86_64', 'aarch64']) diff --git a/devtools/meson/unittests/datatests.py b/devtools/meson/unittests/datatests.py new file mode 100644 index 0000000..70fdcba --- /dev/null +++ b/devtools/meson/unittests/datatests.py @@ -0,0 +1,248 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +import unittest +from itertools import chain +from pathlib import Path + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.interpreter import Interpreter +from mesonbuild.ast import AstInterpreter +from mesonbuild.mesonlib import ( + MachineChoice, OptionKey +) +from mesonbuild.compilers import ( + detect_c_compiler, detect_cpp_compiler +) +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + FakeBuild, get_fake_env +) + +from .helpers import * + +@unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release') +class DataTests(unittest.TestCase): + + def test_snippets(self): + hashcounter = re.compile('^ *(#)+') + snippet_dir = Path('docs/markdown/snippets') + self.assertTrue(snippet_dir.is_dir()) + for f in snippet_dir.glob('*'): + self.assertTrue(f.is_file()) + if f.parts[-1].endswith('~'): + continue + if f.suffix == '.md': + in_code_block = False + with f.open(encoding='utf-8') as snippet: + for line in snippet: + if line.startswith(' '): + continue + if line.startswith('```'): + in_code_block = not in_code_block + if in_code_block: + continue + m = re.match(hashcounter, line) + if m: + self.assertEqual(len(m.group(0)), 2, 'All headings in snippets must have two hash symbols: ' + f.name) + self.assertFalse(in_code_block, 'Unclosed code block.') + else: + if f.name != 'add_release_note_snippets_here': + self.assertTrue(False, 'A file without .md suffix in snippets dir: ' + f.name) + + def test_compiler_options_documented(self): + ''' + Test that C and C++ compiler options and base options are documented in + Builtin-Options.md. Only tests the default compiler for the current + platform on the CI. + ''' + md = None + with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + env = get_fake_env() + # FIXME: Support other compilers + cc = detect_c_compiler(env, MachineChoice.HOST) + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + for comp in (cc, cpp): + for opt in comp.get_options(): + self.assertIn(str(opt), md) + for opt in comp.base_options: + self.assertIn(str(opt), md) + self.assertNotIn('b_unknown', md) + + @staticmethod + def _get_section_content(name, sections, md): + for section in sections: + if section and section.group(1) == name: + try: + next_section = next(sections) + end = next_section.start() + except StopIteration: + end = len(md) + # Extract the content for this section + return md[section.end():end] + raise RuntimeError(f'Could not find "{name}" heading') + + def test_builtin_options_documented(self): + ''' + Test that universal options and base options are documented in + Builtin-Options.md. + ''' + from itertools import tee + md = None + with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + + found_entries = set() + sections = re.finditer(r"^## (.+)$", md, re.MULTILINE) + # Extract the content for this section + u_subcontents = [] + content = self._get_section_content("Universal options", sections, md) + subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE)) + u_subcontents.append(self._get_section_content("Directories", subsections[0], content)) + u_subcontents.append(self._get_section_content("Core options", subsections[1], content)) + + mod_subcontents = [] + content = self._get_section_content("Module options", sections, md) + subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE)) + for idx, mod in enumerate(['Pkgconfig', 'Python']): + mod_subcontents.append(self._get_section_content(f'{mod} module', subsections[idx], content)) + for subcontent in u_subcontents + mod_subcontents: + # Find the option names + options = set() + # Match either a table row or a table heading separator: | ------ | + rows = re.finditer(r"^\|(?: (\w+) .* | *-+ *)\|", subcontent, re.MULTILINE) + # Skip the header of the first table + next(rows) + # Skip the heading separator of the first table + next(rows) + for m in rows: + value = m.group(1) + # End when the `buildtype` table starts + if value is None: + break + options.add(value) + self.assertEqual(len(found_entries & options), 0) + found_entries |= options + + self.assertEqual(found_entries, { + *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS), + *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE), + }) + + # Check that `buildtype` table inside `Core options` matches how + # setting of builtin options behaves + # + # Find all tables inside this subsection + tables = re.finditer(r"^\| (\w+) .* \|\n\| *[-|\s]+ *\|$", u_subcontents[1], re.MULTILINE) + # Get the table we want using the header of the first column + table = self._get_section_content('buildtype', tables, u_subcontents[1]) + # Get table row data + rows = re.finditer(r"^\|(?: (\w+)\s+\| (\w+)\s+\| (\w+) .* | *-+ *)\|", table, re.MULTILINE) + env = get_fake_env() + for m in rows: + buildtype, debug, opt = m.groups() + if debug == 'true': + debug = True + elif debug == 'false': + debug = False + else: + raise RuntimeError(f'Invalid debug value {debug!r} in row:\n{m.group()}') + env.coredata.set_option(OptionKey('buildtype'), buildtype) + self.assertEqual(env.coredata.options[OptionKey('buildtype')].value, buildtype) + self.assertEqual(env.coredata.options[OptionKey('optimization')].value, opt) + self.assertEqual(env.coredata.options[OptionKey('debug')].value, debug) + + def test_cpu_families_documented(self): + with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + + sections = re.finditer(r"^## (.+)$", md, re.MULTILINE) + content = self._get_section_content("CPU families", sections, md) + # Find the list entries + arches = [m.group(1) for m in re.finditer(r"^\| (\w+) +\|", content, re.MULTILINE)] + # Drop the header + arches = set(arches[1:]) + self.assertEqual(arches, set(mesonbuild.environment.known_cpu_families)) + + def test_markdown_files_in_sitemap(self): + ''' + Test that each markdown files in docs/markdown is referenced in sitemap.txt + ''' + with open("docs/sitemap.txt", encoding='utf-8') as f: + md = f.read() + self.assertIsNotNone(md) + toc = list(m.group(1) for m in re.finditer(r"^\s*(\w.*)$", md, re.MULTILINE)) + markdownfiles = [f.name for f in Path("docs/markdown").iterdir() if f.is_file() and f.suffix == '.md'] + exceptions = ['_Sidebar.md'] + for f in markdownfiles: + if f not in exceptions and not f.startswith('_include'): + self.assertIn(f, toc) + + def test_modules_in_navbar(self): + ''' + Test that each module is referenced in navbar_links.html + ''' + with open("docs/theme/extra/templates/navbar_links.html", encoding='utf-8') as f: + html = f.read().lower() + self.assertIsNotNone(html) + for f in Path('mesonbuild/modules').glob('*.py'): + if f.name in {'modtest.py', 'qt.py', '__init__.py'}: + continue + name = f'{f.stem}-module.html' + name = name.replace('unstable_', '') + name = name.replace('python3', 'python-3') + name = name.replace('_', '-') + self.assertIn(name, html) + + @unittest.mock.patch.dict(os.environ) + def test_vim_syntax_highlighting(self): + ''' + Ensure that vim syntax highlighting files were updated for new + functions in the global namespace in build files. + ''' + # Disable unit test specific syntax + del os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] + env = get_fake_env() + interp = Interpreter(FakeBuild(env), mock=True) + with open('data/syntax-highlighting/vim/syntax/meson.vim', encoding='utf-8') as f: + res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE) + defined = set([a.strip() for a in res.group().split('\\')][1:]) + self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys()))) + + @unittest.mock.patch.dict(os.environ) + def test_all_functions_defined_in_ast_interpreter(self): + ''' + Ensure that the all functions defined in the Interpreter are also defined + in the AstInterpreter (and vice versa). + ''' + # Disable unit test specific syntax + del os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] + env = get_fake_env() + interp = Interpreter(FakeBuild(env), mock=True) + astint = AstInterpreter('.', '', '') + self.assertEqual(set(interp.funcs.keys()), set(astint.funcs.keys())) diff --git a/devtools/meson/unittests/failuretests.py b/devtools/meson/unittests/failuretests.py new file mode 100644 index 0000000..ce58f3f --- /dev/null +++ b/devtools/meson/unittests/failuretests.py @@ -0,0 +1,394 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import tempfile +import os +import shutil +import unittest +from contextlib import contextmanager + +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_osx, windows_proof_rmtree, windows_proof_rm +) +from mesonbuild.compilers import ( + detect_objc_compiler, detect_objcpp_compiler +) +from mesonbuild.mesonlib import EnvironmentException, MesonException +from mesonbuild.programs import ExternalProgram + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@contextmanager +def no_pkgconfig(): + ''' + A context manager that overrides shutil.which and ExternalProgram to force + them to return None for pkg-config to simulate it not existing. + ''' + old_which = shutil.which + old_search = ExternalProgram._search + + def new_search(self, name, search_dir): + if name == 'pkg-config': + return [None] + return old_search(self, name, search_dir) + + def new_which(cmd, *kwargs): + if cmd == 'pkg-config': + return None + return old_which(cmd, *kwargs) + + shutil.which = new_which + ExternalProgram._search = new_search + try: + yield + finally: + shutil.which = old_which + ExternalProgram._search = old_search + +class FailureTests(BasePlatformTests): + ''' + Tests that test failure conditions. Build files here should be dynamically + generated and static tests should go into `test cases/failing*`. + This is useful because there can be many ways in which a particular + function can fail, and creating failing tests for all of them is tedious + and slows down testing. + ''' + dnf = "[Dd]ependency.*not found(:.*)?" + nopkg = '[Pp]kg-config.*not found' + + def setUp(self): + super().setUp() + self.srcdir = os.path.realpath(tempfile.mkdtemp()) + self.mbuild = os.path.join(self.srcdir, 'meson.build') + self.moptions = os.path.join(self.srcdir, 'meson.options') + if not os.path.exists(self.moptions): + self.moptions = os.path.join(self.srcdir, 'meson_options.txt') + + def tearDown(self): + super().tearDown() + windows_proof_rmtree(self.srcdir) + + def assertMesonRaises(self, contents, match, *, + extra_args=None, + langs=None, + meson_version=None, + options=None, + override_envvars=None): + ''' + Assert that running meson configure on the specified @contents raises + a error message matching regex @match. + ''' + if langs is None: + langs = [] + with open(self.mbuild, 'w', encoding='utf-8') as f: + f.write("project('failure test', 'c', 'cpp'") + if meson_version: + f.write(f", meson_version: '{meson_version}'") + f.write(")\n") + for lang in langs: + f.write(f"add_languages('{lang}', required : false)\n") + f.write(contents) + if options is not None: + with open(self.moptions, 'w', encoding='utf-8') as f: + f.write(options) + o = {'MESON_FORCE_BACKTRACE': '1'} + if override_envvars is None: + override_envvars = o + else: + override_envvars.update(o) + # Force tracebacks so we can detect them properly + with self.assertRaisesRegex(MesonException, match, msg=contents): + # Must run in-process or we'll get a generic CalledProcessError + self.init(self.srcdir, extra_args=extra_args, + inprocess=True, + override_envvars = override_envvars) + + def obtainMesonOutput(self, contents, match, extra_args, langs, meson_version=None): + if langs is None: + langs = [] + with open(self.mbuild, 'w', encoding='utf-8') as f: + f.write("project('output test', 'c', 'cpp'") + if meson_version: + f.write(f", meson_version: '{meson_version}'") + f.write(")\n") + for lang in langs: + f.write(f"add_languages('{lang}', required : false)\n") + f.write(contents) + # Run in-process for speed and consistency with assertMesonRaises + return self.init(self.srcdir, extra_args=extra_args, inprocess=True) + + def assertMesonOutputs(self, contents, match, extra_args=None, langs=None, meson_version=None): + ''' + Assert that running meson configure on the specified @contents outputs + something that matches regex @match. + ''' + out = self.obtainMesonOutput(contents, match, extra_args, langs, meson_version) + self.assertRegex(out, match) + + def assertMesonDoesNotOutput(self, contents, match, extra_args=None, langs=None, meson_version=None): + ''' + Assert that running meson configure on the specified @contents does not output + something that matches regex @match. + ''' + out = self.obtainMesonOutput(contents, match, extra_args, langs, meson_version) + self.assertNotRegex(out, match) + + @skipIfNoPkgconfig + def test_dependency(self): + if subprocess.call(['pkg-config', '--exists', 'zlib']) != 0: + raise unittest.SkipTest('zlib not found with pkg-config') + a = (("dependency('zlib', method : 'fail')", "'fail' is invalid"), + ("dependency('zlib', static : '1')", "[Ss]tatic.*boolean"), + ("dependency('zlib', version : 1)", "Item must be a list or one of "), + ("dependency('zlib', required : 1)", "[Rr]equired.*boolean"), + ("dependency('zlib', method : 1)", "[Mm]ethod.*string"), + ("dependency('zlibfail')", self.dnf),) + for contents, match in a: + self.assertMesonRaises(contents, match) + + def test_apple_frameworks_dependency(self): + if not is_osx(): + raise unittest.SkipTest('only run on macOS') + self.assertMesonRaises("dependency('appleframeworks')", + "requires at least one module") + + def test_extraframework_dependency_method(self): + code = "dependency('metal', method : 'extraframework')" + if not is_osx(): + self.assertMesonRaises(code, self.dnf) + else: + # metal framework is always available on macOS + self.assertMesonOutputs(code, '[Dd]ependency.*metal.*found.*YES') + + def test_sdl2_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('sdl2-config'): + raise unittest.SkipTest('sdl2-config found') + self.assertMesonRaises("dependency('sdl2', method : 'sdlconfig')", self.dnf) + if shutil.which('pkg-config'): + self.assertMesonRaises("dependency('sdl2', method : 'pkg-config')", self.dnf) + with no_pkgconfig(): + # Look for pkg-config, cache it, then + # Use cached pkg-config without erroring out, then + # Use cached pkg-config to error out + code = "dependency('foobarrr', method : 'pkg-config', required : false)\n" \ + "dependency('foobarrr2', method : 'pkg-config', required : false)\n" \ + "dependency('sdl2', method : 'pkg-config')" + self.assertMesonRaises(code, self.nopkg) + + def test_gnustep_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('gnustep-config'): + raise unittest.SkipTest('gnustep-config found') + self.assertMesonRaises("dependency('gnustep')", + f"(requires a Objc compiler|{self.dnf})", + langs = ['objc']) + + def test_wx_notfound_dependency(self): + # Want to test failure, so skip if available + if shutil.which('wx-config-3.0') or shutil.which('wx-config') or shutil.which('wx-config-gtk3'): + raise unittest.SkipTest('wx-config, wx-config-3.0 or wx-config-gtk3 found') + self.assertMesonRaises("dependency('wxwidgets')", self.dnf) + self.assertMesonOutputs("dependency('wxwidgets', required : false)", + "Run-time dependency .*WxWidgets.* found: .*NO.*") + + def test_wx_dependency(self): + if not shutil.which('wx-config-3.0') and not shutil.which('wx-config') and not shutil.which('wx-config-gtk3'): + raise unittest.SkipTest('Neither wx-config, wx-config-3.0 nor wx-config-gtk3 found') + self.assertMesonRaises("dependency('wxwidgets', modules : 1)", + "module argument is not a string") + + def test_llvm_dependency(self): + self.assertMesonRaises("dependency('llvm', modules : 'fail')", + f"(required.*fail|{self.dnf})") + + def test_boost_notfound_dependency(self): + # Can be run even if Boost is found or not + self.assertMesonRaises("dependency('boost', modules : 1)", + "module.*not a string") + self.assertMesonRaises("dependency('boost', modules : 'fail')", + f"(fail.*not found|{self.dnf})") + + def test_boost_BOOST_ROOT_dependency(self): + # Test BOOST_ROOT; can be run even if Boost is found or not + self.assertMesonRaises("dependency('boost')", + f"(boost_root.*absolute|{self.dnf})", + override_envvars = {'BOOST_ROOT': 'relative/path'}) + + def test_dependency_invalid_method(self): + code = '''zlib_dep = dependency('zlib', required : false) + zlib_dep.get_configtool_variable('foo') + ''' + self.assertMesonRaises(code, ".* is not a config-tool dependency") + code = '''zlib_dep = dependency('zlib', required : false) + dep = declare_dependency(dependencies : zlib_dep) + dep.get_pkgconfig_variable('foo') + ''' + self.assertMesonRaises(code, "Method.*pkgconfig.*is invalid.*internal") + code = '''zlib_dep = dependency('zlib', required : false) + dep = declare_dependency(dependencies : zlib_dep) + dep.get_configtool_variable('foo') + ''' + self.assertMesonRaises(code, "Method.*configtool.*is invalid.*internal") + + def test_objc_cpp_detection(self): + ''' + Test that when we can't detect objc or objcpp, we fail gracefully. + ''' + env = get_fake_env() + try: + detect_objc_compiler(env, MachineChoice.HOST) + detect_objcpp_compiler(env, MachineChoice.HOST) + except EnvironmentException: + code = "add_languages('objc')\nadd_languages('objcpp')" + self.assertMesonRaises(code, "Unknown compiler") + return + raise unittest.SkipTest("objc and objcpp found, can't test detection failure") + + def test_subproject_variables(self): + ''' + Test that: + 1. The correct message is outputted when a not-required dep is not + found and the fallback subproject is also not found. + 2. A not-required fallback dependency is not found because the + subproject failed to parse. + 3. A not-found not-required dep with a fallback subproject outputs the + correct message when the fallback subproject is found but the + variable inside it is not. + 4. A fallback dependency is found from the subproject parsed in (3) + 5. A wrap file from a subproject is used but fails because it does not + contain required keys. + ''' + tdir = os.path.join(self.unit_test_dir, '20 subproj dep variables') + stray_file = os.path.join(tdir, 'subprojects/subsubproject.wrap') + if os.path.exists(stray_file): + windows_proof_rm(stray_file) + out = self.init(tdir, inprocess=True) + self.assertRegex(out, r"Neither a subproject directory nor a .*nosubproj.wrap.* file was found") + self.assertRegex(out, r'Function does not take positional arguments.') + self.assertRegex(out, r'Dependency .*somenotfounddep.* from subproject .*subprojects/somesubproj.* found: .*NO.*') + self.assertRegex(out, r'Dependency .*zlibproxy.* from subproject .*subprojects.*somesubproj.* found: .*YES.*') + self.assertRegex(out, r'Missing key .*source_filename.* in subsubproject.wrap') + windows_proof_rm(stray_file) + + def test_exception_exit_status(self): + ''' + Test exit status on python exception + ''' + tdir = os.path.join(self.unit_test_dir, '21 exit status') + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(tdir, inprocess=False, override_envvars = {'MESON_UNIT_TEST': '1', 'MESON_FORCE_BACKTRACE': ''}) + self.assertEqual(cm.exception.returncode, 2) + self.wipe() + + def test_dict_requires_key_value_pairs(self): + self.assertMesonRaises("dict = {3, 'foo': 'bar'}", + 'Only key:value pairs are valid in dict construction.') + self.assertMesonRaises("{'foo': 'bar', 3}", + 'Only key:value pairs are valid in dict construction.') + + def test_dict_forbids_duplicate_keys(self): + self.assertMesonRaises("dict = {'a': 41, 'a': 42}", + 'Duplicate dictionary key: a.*') + + def test_dict_forbids_integer_key(self): + self.assertMesonRaises("dict = {3: 'foo'}", + 'Key must be a string.*') + + def test_using_too_recent_feature(self): + # Here we use a dict, which was introduced in 0.47.0 + self.assertMesonOutputs("dict = {}", + ".*WARNING.*Project targets.*but.*", + meson_version='>= 0.46.0') + + def test_using_recent_feature(self): + # Same as above, except the meson version is now appropriate + self.assertMesonDoesNotOutput("dict = {}", + ".*WARNING.*Project targets.*but.*", + meson_version='>= 0.47') + + def test_using_too_recent_feature_dependency(self): + self.assertMesonOutputs("dependency('pcap', required: false)", + ".*WARNING.*Project targets.*but.*", + meson_version='>= 0.41.0') + + def test_vcs_tag_featurenew_build_always_stale(self): + 'https://github.com/mesonbuild/meson/issues/3904' + vcs_tag = '''version_data = configuration_data() + version_data.set('PROJVER', '@VCS_TAG@') + vf = configure_file(output : 'version.h.in', configuration: version_data) + f = vcs_tag(input : vf, output : 'version.h') + ''' + msg = '.*WARNING:.*feature.*build_always_stale.*custom_target.*' + self.assertMesonDoesNotOutput(vcs_tag, msg, meson_version='>=0.43') + + def test_missing_subproject_not_required_and_required(self): + self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" + + "sub2 = subproject('not-found-subproject', required: true)", + """.*Subproject "subprojects/not-found-subproject" required but not found.*""") + + def test_get_variable_on_not_found_project(self): + self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" + + "sub1.get_variable('naaa')", + """Subproject "subprojects/not-found-subproject" disabled can't get_variable on it.""") + + def test_version_checked_before_parsing_options(self): + ''' + https://github.com/mesonbuild/meson/issues/5281 + ''' + options = "option('some-option', type: 'foo', value: '')" + match = 'Meson version is.*but project requires >=2000' + self.assertMesonRaises("", match, meson_version='>=2000', options=options) + + def test_assert_default_message(self): + self.assertMesonRaises("k1 = 'a'\n" + + "assert({\n" + + " k1: 1,\n" + + "}['a'] == 2)\n", + r"Assert failed: {k1 : 1}\['a'\] == 2") + + def test_wrap_nofallback(self): + self.assertMesonRaises("dependency('notfound', fallback : ['foo', 'foo_dep'])", + r"Dependency 'notfound' is required but not found.", + extra_args=['--wrap-mode=nofallback']) + + def test_message(self): + self.assertMesonOutputs("message('Array:', ['a', 'b'])", + r"Message:.* Array: \['a', 'b'\]") + + def test_warning(self): + self.assertMesonOutputs("warning('Array:', ['a', 'b'])", + r"WARNING:.* Array: \['a', 'b'\]") + + def test_override_dependency_twice(self): + self.assertMesonRaises("meson.override_dependency('foo', declare_dependency())\n" + + "meson.override_dependency('foo', declare_dependency())", + """Tried to override dependency 'foo' which has already been resolved or overridden""") + + @unittest.skipIf(is_windows(), 'zlib is not available on Windows') + def test_override_resolved_dependency(self): + self.assertMesonRaises("dependency('zlib')\n" + + "meson.override_dependency('zlib', declare_dependency())", + """Tried to override dependency 'zlib' which has already been resolved or overridden""") + + def test_error_func(self): + self.assertMesonRaises("error('a', 'b', ['c', ['d', {'e': 'f'}]], 'g')", + r"Problem encountered: a b \['c', \['d', {'e' : 'f'}\]\] g") diff --git a/devtools/meson/unittests/helpers.py b/devtools/meson/unittests/helpers.py new file mode 100644 index 0000000..7483f51 --- /dev/null +++ b/devtools/meson/unittests/helpers.py @@ -0,0 +1,214 @@ +import subprocess +import os +import shutil +import unittest +import functools +import re +import typing as T +import zipfile +from pathlib import Path +from contextlib import contextmanager + +from mesonbuild.compilers import detect_c_compiler, compiler_from_language +from mesonbuild.mesonlib import ( + MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice, + OrderedSet +) +from run_tests import get_fake_env + + +def is_ci(): + if os.environ.get('MESON_CI_JOBNAME') not in {None, 'thirdparty'}: + return True + return False + +def skip_if_not_base_option(feature): + """Skip tests if The compiler does not support a given base option. + + for example, ICC doesn't currently support b_sanitize. + """ + def actual(f): + @functools.wraps(f) + def wrapped(*args, **kwargs): + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + key = OptionKey(feature) + if key not in cc.base_options: + raise unittest.SkipTest( + f'{feature} not available with {cc.id}') + return f(*args, **kwargs) + return wrapped + return actual + +def skipIfNoPkgconfig(f): + ''' + Skip this test if no pkg-config is found, unless we're on CI. + This allows users to run our test suite without having + pkg-config installed on, f.ex., macOS, while ensuring that our CI does not + silently skip the test because of misconfiguration. + + Note: Yes, we provide pkg-config even while running Windows CI + ''' + @functools.wraps(f) + def wrapped(*args, **kwargs): + if not is_ci() and shutil.which('pkg-config') is None: + raise unittest.SkipTest('pkg-config not found') + return f(*args, **kwargs) + return wrapped + +def skipIfNoPkgconfigDep(depname): + ''' + Skip this test if the given pkg-config dep is not found, unless we're on CI. + ''' + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + if not is_ci() and shutil.which('pkg-config') is None: + raise unittest.SkipTest('pkg-config not found') + if not is_ci() and subprocess.call(['pkg-config', '--exists', depname]) != 0: + raise unittest.SkipTest(f'pkg-config dependency {depname} not found.') + return func(*args, **kwargs) + return wrapped + return wrapper + +def skip_if_no_cmake(f): + ''' + Skip this test if no cmake is found, unless we're on CI. + This allows users to run our test suite without having + cmake installed on, f.ex., macOS, while ensuring that our CI does not + silently skip the test because of misconfiguration. + ''' + @functools.wraps(f) + def wrapped(*args, **kwargs): + if not is_ci() and shutil.which('cmake') is None: + raise unittest.SkipTest('cmake not found') + return f(*args, **kwargs) + return wrapped + +def skip_if_not_language(lang: str): + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + try: + compiler_from_language(get_fake_env(), lang, MachineChoice.HOST) + except EnvironmentException: + raise unittest.SkipTest(f'No {lang} compiler found.') + return func(*args, **kwargs) + return wrapped + return wrapper + +def skip_if_env_set(key): + ''' + Skip a test if a particular env is set, except when running under CI + ''' + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + old = None + if key in os.environ: + if not is_ci(): + raise unittest.SkipTest(f'Env var {key!r} set, skipping') + old = os.environ.pop(key) + try: + return func(*args, **kwargs) + finally: + if old is not None: + os.environ[key] = old + return wrapped + return wrapper + +def skipIfNoExecutable(exename): + ''' + Skip this test if the given executable is not found. + ''' + def wrapper(func): + @functools.wraps(func) + def wrapped(*args, **kwargs): + if shutil.which(exename) is None: + raise unittest.SkipTest(exename + ' not found') + return func(*args, **kwargs) + return wrapped + return wrapper + +def is_tarball(): + if not os.path.isdir('docs'): + return True + return False + +@contextmanager +def chdir(path: str): + curdir = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(curdir) + +def get_dynamic_section_entry(fname: str, entry: str) -> T.Optional[str]: + if is_cygwin() or is_osx(): + raise unittest.SkipTest('Test only applicable to ELF platforms') + + try: + raw_out = subprocess.check_output(['readelf', '-d', fname], + universal_newlines=True) + except FileNotFoundError: + # FIXME: Try using depfixer.py:Elf() as a fallback + raise unittest.SkipTest('readelf not found') + pattern = re.compile(entry + r': \[(.*?)\]') + for line in raw_out.split('\n'): + m = pattern.search(line) + if m is not None: + return str(m.group(1)) + return None # The file did not contain the specified entry. + +def get_soname(fname: str) -> T.Optional[str]: + return get_dynamic_section_entry(fname, 'soname') + +def get_rpath(fname: str) -> T.Optional[str]: + raw = get_dynamic_section_entry(fname, r'(?:rpath|runpath)') + # Get both '' and None here + if not raw: + return None + # nix/nixos adds a bunch of stuff to the rpath out of necessity that we + # don't check for, so clear those + final = ':'.join([e for e in raw.split(':') if not e.startswith('/nix')]) + # If we didn't end up anything but nix paths, return None here + if not final: + return None + return final + +def get_classpath(fname: str) -> T.Optional[str]: + with zipfile.ZipFile(fname) as zip: + with zip.open('META-INF/MANIFEST.MF') as member: + contents = member.read().decode().strip() + lines = [] + for line in contents.splitlines(): + if line.startswith(' '): + # continuation line + lines[-1] += line[1:] + else: + lines.append(line) + manifest = { + k.lower(): v.strip() for k, v in [l.split(':', 1) for l in lines] + } + return manifest.get('class-path') + +def get_path_without_cmd(cmd: str, path: str) -> str: + pathsep = os.pathsep + paths = OrderedSet([Path(p).resolve() for p in path.split(pathsep)]) + while True: + full_path = shutil.which(cmd, path=path) + if full_path is None: + break + dirname = Path(full_path).resolve().parent + paths.discard(dirname) + path = pathsep.join([str(p) for p in paths]) + return path + +def xfail_if_jobname(name: str): + if os.environ.get('MESON_CI_JOBNAME') == name: + return unittest.expectedFailure + + def wrapper(func): + return func + return wrapper diff --git a/devtools/meson/unittests/internaltests.py b/devtools/meson/unittests/internaltests.py new file mode 100644 index 0000000..e57dd6d --- /dev/null +++ b/devtools/meson/unittests/internaltests.py @@ -0,0 +1,1713 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from configparser import ConfigParser +from pathlib import Path +from unittest import mock +import contextlib +import io +import json +import operator +import os +import pickle +import stat +import subprocess +import tempfile +import typing as T +import unittest + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.modules.gnome +from mesonbuild import coredata +from mesonbuild.compilers.c import ClangCCompiler, GnuCCompiler +from mesonbuild.compilers.cpp import VisualStudioCPPCompiler +from mesonbuild.compilers.d import DmdDCompiler +from mesonbuild.linkers import linkers +from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, ObjectHolder +from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, typed_kwargs, ContainerTypeInfo, KwargInfo +from mesonbuild.mesonlib import ( + LibType, MachineChoice, PerMachine, Version, is_windows, is_osx, + is_cygwin, is_openbsd, search_version, MesonException, OptionKey, + OptionType +) +from mesonbuild.interpreter.type_checking import in_set_validator, NoneType +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +from mesonbuild.programs import ExternalProgram +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + FakeCompilerOptions, get_fake_env, get_fake_options +) + +from .helpers import * + +class InternalTests(unittest.TestCase): + + def test_version_number(self): + self.assertEqual(search_version('foobar 1.2.3'), '1.2.3') + self.assertEqual(search_version('1.2.3'), '1.2.3') + self.assertEqual(search_version('foobar 2016.10.28 1.2.3'), '1.2.3') + self.assertEqual(search_version('2016.10.28 1.2.3'), '1.2.3') + self.assertEqual(search_version('foobar 2016.10.128'), '2016.10.128') + self.assertEqual(search_version('2016.10.128'), '2016.10.128') + self.assertEqual(search_version('2016.10'), '2016.10') + self.assertEqual(search_version('2016.10 1.2.3'), '1.2.3') + self.assertEqual(search_version('oops v1.2.3'), '1.2.3') + self.assertEqual(search_version('2016.oops 1.2.3'), '1.2.3') + self.assertEqual(search_version('2016.x'), 'unknown version') + self.assertEqual(search_version(r'something version is \033[32;2m1.2.0\033[0m.'), '1.2.0') + + # Literal output of mvn + self.assertEqual(search_version(r'''\ + \033[1mApache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)\033[0m + Maven home: /nix/store/g84a9wnid2h1d3z2wfydy16dky73wh7i-apache-maven-3.8.1/maven + Java version: 11.0.10, vendor: Oracle Corporation, runtime: /nix/store/afsnl4ahmm9svvl7s1a0cj41vw4nkmz4-openjdk-11.0.10+9/lib/openjdk + Default locale: en_US, platform encoding: UTF-8 + OS name: "linux", version: "5.12.17", arch: "amd64", family: "unix"'''), + '3.8.1') + + def test_mode_symbolic_to_bits(self): + modefunc = mesonbuild.mesonlib.FileMode.perms_s_to_bits + self.assertEqual(modefunc('---------'), 0) + self.assertEqual(modefunc('r--------'), stat.S_IRUSR) + self.assertEqual(modefunc('---r-----'), stat.S_IRGRP) + self.assertEqual(modefunc('------r--'), stat.S_IROTH) + self.assertEqual(modefunc('-w-------'), stat.S_IWUSR) + self.assertEqual(modefunc('----w----'), stat.S_IWGRP) + self.assertEqual(modefunc('-------w-'), stat.S_IWOTH) + self.assertEqual(modefunc('--x------'), stat.S_IXUSR) + self.assertEqual(modefunc('-----x---'), stat.S_IXGRP) + self.assertEqual(modefunc('--------x'), stat.S_IXOTH) + self.assertEqual(modefunc('--S------'), stat.S_ISUID) + self.assertEqual(modefunc('-----S---'), stat.S_ISGID) + self.assertEqual(modefunc('--------T'), stat.S_ISVTX) + self.assertEqual(modefunc('--s------'), stat.S_ISUID | stat.S_IXUSR) + self.assertEqual(modefunc('-----s---'), stat.S_ISGID | stat.S_IXGRP) + self.assertEqual(modefunc('--------t'), stat.S_ISVTX | stat.S_IXOTH) + self.assertEqual(modefunc('rwx------'), stat.S_IRWXU) + self.assertEqual(modefunc('---rwx---'), stat.S_IRWXG) + self.assertEqual(modefunc('------rwx'), stat.S_IRWXO) + # We could keep listing combinations exhaustively but that seems + # tedious and pointless. Just test a few more. + self.assertEqual(modefunc('rwxr-xr-x'), + stat.S_IRWXU | + stat.S_IRGRP | stat.S_IXGRP | + stat.S_IROTH | stat.S_IXOTH) + self.assertEqual(modefunc('rw-r--r--'), + stat.S_IRUSR | stat.S_IWUSR | + stat.S_IRGRP | + stat.S_IROTH) + self.assertEqual(modefunc('rwsr-x---'), + stat.S_IRWXU | stat.S_ISUID | + stat.S_IRGRP | stat.S_IXGRP) + + def test_compiler_args_class_none_flush(self): + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + a = cc.compiler_args(['-I.']) + #first we are checking if the tree construction deduplicates the correct -I argument + a += ['-I..'] + a += ['-I./tests/'] + a += ['-I./tests2/'] + #think this here as assertion, we cannot apply it, otherwise the CompilerArgs would already flush the changes: + # assertEqual(a, ['-I.', '-I./tests2/', '-I./tests/', '-I..', '-I.']) + a += ['-I.'] + a += ['-I.', '-I./tests/'] + self.assertEqual(a, ['-I.', '-I./tests/', '-I./tests2/', '-I..']) + + #then we are checking that when CompilerArgs already have a build container list, that the deduplication is taking the correct one + a += ['-I.', '-I./tests2/'] + self.assertEqual(a, ['-I.', '-I./tests2/', '-I./tests/', '-I..']) + + def test_compiler_args_class_d(self): + d = DmdDCompiler([], 'fake', MachineChoice.HOST, 'info', 'arch') + # check include order is kept when deduplicating + a = d.compiler_args(['-Ifirst', '-Isecond', '-Ithird']) + a += ['-Ifirst'] + self.assertEqual(a, ['-Ifirst', '-Isecond', '-Ithird']) + + def test_compiler_args_class_clike(self): + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + # Test that empty initialization works + a = cc.compiler_args() + self.assertEqual(a, []) + # Test that list initialization works + a = cc.compiler_args(['-I.', '-I..']) + self.assertEqual(a, ['-I.', '-I..']) + # Test that there is no de-dup on initialization + self.assertEqual(cc.compiler_args(['-I.', '-I.']), ['-I.', '-I.']) + + ## Test that appending works + a.append('-I..') + self.assertEqual(a, ['-I..', '-I.']) + a.append('-O3') + self.assertEqual(a, ['-I..', '-I.', '-O3']) + + ## Test that in-place addition works + a += ['-O2', '-O2'] + self.assertEqual(a, ['-I..', '-I.', '-O3', '-O2', '-O2']) + # Test that removal works + a.remove('-O2') + self.assertEqual(a, ['-I..', '-I.', '-O3', '-O2']) + # Test that de-dup happens on addition + a += ['-Ifoo', '-Ifoo'] + self.assertEqual(a, ['-Ifoo', '-I..', '-I.', '-O3', '-O2']) + + # .extend() is just +=, so we don't test it + + ## Test that addition works + # Test that adding a list with just one old arg works and yields the same array + a = a + ['-Ifoo'] + self.assertEqual(a, ['-Ifoo', '-I..', '-I.', '-O3', '-O2']) + # Test that adding a list with one arg new and one old works + a = a + ['-Ifoo', '-Ibaz'] + self.assertEqual(a, ['-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2']) + # Test that adding args that must be prepended and appended works + a = a + ['-Ibar', '-Wall'] + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) + + ## Test that reflected addition works + # Test that adding to a list with just one old arg works and yields the same array + a = ['-Ifoo'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-O3', '-O2', '-Wall']) + # Test that adding to a list with just one new arg that is not pre-pended works + a = ['-Werror'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Werror', '-O3', '-O2', '-Wall']) + # Test that adding to a list with two new args preserves the order + a = ['-Ldir', '-Lbah'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) + # Test that adding to a list with old args does nothing + a = ['-Ibar', '-Ibaz', '-Ifoo'] + a + self.assertEqual(a, ['-Ibar', '-Ifoo', '-Ibaz', '-I..', '-I.', '-Ldir', '-Lbah', '-Werror', '-O3', '-O2', '-Wall']) + + ## Test that adding libraries works + l = cc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l, ['-Lfoodir', '-lfoo']) + # Adding a library and a libpath appends both correctly + l += ['-Lbardir', '-lbar'] + self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) + # Adding the same library again does nothing + l += ['-lbar'] + self.assertEqual(l, ['-Lbardir', '-Lfoodir', '-lfoo', '-lbar']) + + ## Test that 'direct' append and extend works + l = cc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l, ['-Lfoodir', '-lfoo']) + # Direct-adding a library and a libpath appends both correctly + l.extend_direct(['-Lbardir', '-lbar']) + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar']) + # Direct-adding the same library again still adds it + l.append_direct('-lbar') + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar']) + # Direct-adding with absolute path deduplicates + l.append_direct('/libbaz.a') + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a']) + # Adding libbaz again does nothing + l.append_direct('/libbaz.a') + self.assertEqual(l, ['-Lfoodir', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a']) + + + def test_compiler_args_class_visualstudio(self): + linker = linkers.MSVCDynamicLinker(MachineChoice.HOST, []) + # Version just needs to be > 19.0.0 + cc = VisualStudioCPPCompiler([], [], '20.00', MachineChoice.HOST, False, mock.Mock(), 'x64', linker=linker) + + a = cc.compiler_args(cc.get_always_args()) + self.assertEqual(a.to_native(copy=True), ['/nologo', '/showIncludes', '/utf-8', '/Zc:__cplusplus']) + + # Ensure /source-charset: removes /utf-8 + a.append('/source-charset:utf-8') + self.assertEqual(a.to_native(copy=True), ['/nologo', '/showIncludes', '/Zc:__cplusplus', '/source-charset:utf-8']) + + # Ensure /execution-charset: removes /utf-8 + a = cc.compiler_args(cc.get_always_args() + ['/execution-charset:utf-8']) + self.assertEqual(a.to_native(copy=True), ['/nologo', '/showIncludes', '/Zc:__cplusplus', '/execution-charset:utf-8']) + + # Ensure /validate-charset- removes /utf-8 + a = cc.compiler_args(cc.get_always_args() + ['/validate-charset-']) + self.assertEqual(a.to_native(copy=True), ['/nologo', '/showIncludes', '/Zc:__cplusplus', '/validate-charset-']) + + + def test_compiler_args_class_gnuld(self): + ## Test --start/end-group + linker = linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + gcc = GnuCCompiler([], [], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) + ## Ensure that the fake compiler is never called by overriding the relevant function + gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] + ## Test that 'direct' append and extend works + l = gcc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) + # Direct-adding a library and a libpath appends both correctly + l.extend_direct(['-Lbardir', '-lbar']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-Wl,--end-group']) + # Direct-adding the same library again still adds it + l.append_direct('-lbar') + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '-Wl,--end-group']) + # Direct-adding with absolute path deduplicates + l.append_direct('/libbaz.a') + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group']) + # Adding libbaz again does nothing + l.append_direct('/libbaz.a') + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group']) + # Adding a non-library argument doesn't include it in the group + l += ['-Lfoo', '-Wl,--export-dynamic'] + self.assertEqual(l.to_native(copy=True), ['-Lfoo', '-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--end-group', '-Wl,--export-dynamic']) + # -Wl,-lfoo is detected as a library and gets added to the group + l.append('-Wl,-ldl') + self.assertEqual(l.to_native(copy=True), ['-Lfoo', '-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-lbar', '/libbaz.a', '-Wl,--export-dynamic', '-Wl,-ldl', '-Wl,--end-group']) + + def test_compiler_args_remove_system(self): + ## Test --start/end-group + linker = linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + gcc = GnuCCompiler([], [], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) + ## Ensure that the fake compiler is never called by overriding the relevant function + gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] + ## Test that 'direct' append and extend works + l = gcc.compiler_args(['-Lfoodir', '-lfoo']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) + ## Test that to_native removes all system includes + l += ['-isystem/usr/include', '-isystem=/usr/share/include', '-DSOMETHING_IMPORTANT=1', '-isystem', '/usr/local/include'] + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group', '-DSOMETHING_IMPORTANT=1']) + + def test_string_templates_substitution(self): + dictfunc = mesonbuild.mesonlib.get_filenames_templates_dict + substfunc = mesonbuild.mesonlib.substitute_values + ME = mesonbuild.mesonlib.MesonException + + # Identity + self.assertEqual(dictfunc([], []), {}) + + # One input, no outputs + inputs = ['bar/foo.c.in'] + outputs = [] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out'] + cmd[1:]) + cmd = ['@INPUT0@.out', '@PLAINNAME@.ok', 'strings'] + self.assertEqual(substfunc(cmd, d), + [inputs[0] + '.out'] + [d['@PLAINNAME@'] + '.ok'] + cmd[2:]) + cmd = ['@INPUT@', '@BASENAME@.hah', 'strings'] + self.assertEqual(substfunc(cmd, d), + inputs + [d['@BASENAME@'] + '.hah'] + cmd[2:]) + cmd = ['@OUTPUT@'] + self.assertRaises(ME, substfunc, cmd, d) + + # One input, one output + inputs = ['bar/foo.c.in'] + outputs = ['out.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': '.'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@INPUT@.out', '@OUTPUT@', 'strings'] + self.assertEqual(substfunc(cmd, d), + [inputs[0] + '.out'] + outputs + cmd[2:]) + cmd = ['@INPUT0@.out', '@PLAINNAME@.ok', '@OUTPUT0@'] + self.assertEqual(substfunc(cmd, d), + [inputs[0] + '.out', d['@PLAINNAME@'] + '.ok'] + outputs) + cmd = ['@INPUT@', '@BASENAME@.hah', 'strings'] + self.assertEqual(substfunc(cmd, d), + inputs + [d['@BASENAME@'] + '.hah'] + cmd[2:]) + + # One input, one output with a subdir + outputs = ['dir/out.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} + # Check dictionary + self.assertEqual(ret, d) + + # Two inputs, no outputs + inputs = ['bar/foo.c.in', 'baz/foo.c.in'] + outputs = [] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1]} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@INPUT@', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), inputs + cmd[1:]) + cmd = ['@INPUT0@.out', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out'] + cmd[1:]) + cmd = ['@INPUT0@.out', '@INPUT1@.ok', 'strings'] + self.assertEqual(substfunc(cmd, d), [inputs[0] + '.out', inputs[1] + '.ok'] + cmd[2:]) + cmd = ['@INPUT0@', '@INPUT1@', 'strings'] + self.assertEqual(substfunc(cmd, d), inputs + cmd[2:]) + # Many inputs, can't use @INPUT@ like this + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough inputs + cmd = ['@INPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Too many inputs + cmd = ['@PLAINNAME@'] + self.assertRaises(ME, substfunc, cmd, d) + cmd = ['@BASENAME@'] + self.assertRaises(ME, substfunc, cmd, d) + # No outputs + cmd = ['@OUTPUT@'] + self.assertRaises(ME, substfunc, cmd, d) + cmd = ['@OUTPUT0@'] + self.assertRaises(ME, substfunc, cmd, d) + cmd = ['@OUTDIR@'] + self.assertRaises(ME, substfunc, cmd, d) + + # Two inputs, one output + outputs = ['dir/out.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@OUTPUT@', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), outputs + cmd[1:]) + cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out'] + cmd[1:]) + cmd = ['@OUTPUT0@.out', '@INPUT1@.ok', 'strings'] + self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out', inputs[1] + '.ok'] + cmd[2:]) + # Many inputs, can't use @INPUT@ like this + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough inputs + cmd = ['@INPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough outputs + cmd = ['@OUTPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + + # Two inputs, two outputs + outputs = ['dir/out.c', 'dir/out2.c'] + ret = dictfunc(inputs, outputs) + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTPUT1@': outputs[1], + '@OUTDIR@': 'dir'} + # Check dictionary + self.assertEqual(ret, d) + # Check substitutions + cmd = ['some', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), cmd) + cmd = ['@OUTPUT@', 'ordinary', 'strings'] + self.assertEqual(substfunc(cmd, d), outputs + cmd[1:]) + cmd = ['@OUTPUT0@', '@OUTPUT1@', 'strings'] + self.assertEqual(substfunc(cmd, d), outputs + cmd[2:]) + cmd = ['@OUTPUT0@.out', '@INPUT1@.ok', '@OUTDIR@'] + self.assertEqual(substfunc(cmd, d), [outputs[0] + '.out', inputs[1] + '.ok', 'dir']) + # Many inputs, can't use @INPUT@ like this + cmd = ['@INPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough inputs + cmd = ['@INPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Not enough outputs + cmd = ['@OUTPUT2@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + # Many outputs, can't use @OUTPUT@ like this + cmd = ['@OUTPUT@.out', 'ordinary', 'strings'] + self.assertRaises(ME, substfunc, cmd, d) + + def test_needs_exe_wrapper_override(self): + config = ConfigParser() + config['binaries'] = { + 'c': '\'/usr/bin/gcc\'', + } + config['host_machine'] = { + 'system': '\'linux\'', + 'cpu_family': '\'arm\'', + 'cpu': '\'armv7\'', + 'endian': '\'little\'', + } + # Can not be used as context manager because we need to + # open it a second time and this is not possible on + # Windows. + configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False, encoding='utf-8') + configfilename = configfile.name + config.write(configfile) + configfile.flush() + configfile.close() + opts = get_fake_options() + opts.cross_file = (configfilename,) + env = get_fake_env(opts=opts) + detected_value = env.need_exe_wrapper() + os.unlink(configfilename) + + desired_value = not detected_value + config['properties'] = { + 'needs_exe_wrapper': 'true' if desired_value else 'false' + } + + configfile = tempfile.NamedTemporaryFile(mode='w+', delete=False, encoding='utf-8') + configfilename = configfile.name + config.write(configfile) + configfile.close() + opts = get_fake_options() + opts.cross_file = (configfilename,) + env = get_fake_env(opts=opts) + forced_value = env.need_exe_wrapper() + os.unlink(configfilename) + + self.assertEqual(forced_value, desired_value) + + def test_listify(self): + listify = mesonbuild.mesonlib.listify + # Test sanity + self.assertEqual([1], listify(1)) + self.assertEqual([], listify([])) + self.assertEqual([1], listify([1])) + # Test flattening + self.assertEqual([1, 2, 3], listify([1, [2, 3]])) + self.assertEqual([1, 2, 3], listify([1, [2, [3]]])) + self.assertEqual([1, [2, [3]]], listify([1, [2, [3]]], flatten=False)) + # Test flattening and unholdering + class TestHeldObj(mesonbuild.mesonlib.HoldableObject): + def __init__(self, val: int) -> None: + self._val = val + class MockInterpreter: + def __init__(self) -> None: + self.subproject = '' + self.environment = None + heldObj1 = TestHeldObj(1) + holder1 = ObjectHolder(heldObj1, MockInterpreter()) + self.assertEqual([holder1], listify(holder1)) + self.assertEqual([holder1], listify([holder1])) + self.assertEqual([holder1, 2], listify([holder1, 2])) + self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]])) + + def test_extract_as_list(self): + extract = mesonbuild.mesonlib.extract_as_list + # Test sanity + kwargs = {'sources': [1, 2, 3]} + self.assertEqual([1, 2, 3], extract(kwargs, 'sources')) + self.assertEqual(kwargs, {'sources': [1, 2, 3]}) + self.assertEqual([1, 2, 3], extract(kwargs, 'sources', pop=True)) + self.assertEqual(kwargs, {}) + + class TestHeldObj(mesonbuild.mesonlib.HoldableObject): + pass + class MockInterpreter: + def __init__(self) -> None: + self.subproject = '' + self.environment = None + heldObj = TestHeldObj() + + # Test unholding + holder3 = ObjectHolder(heldObj, MockInterpreter()) + kwargs = {'sources': [1, 2, holder3]} + self.assertEqual(kwargs, {'sources': [1, 2, holder3]}) + + # flatten nested lists + kwargs = {'sources': [1, [2, [3]]]} + self.assertEqual([1, 2, 3], extract(kwargs, 'sources')) + + def _test_all_naming(self, cc, env, patterns, platform): + shr = patterns[platform]['shared'] + stc = patterns[platform]['static'] + shrstc = shr + tuple(x for x in stc if x not in shr) + stcshr = stc + tuple(x for x in shr if x not in stc) + p = cc.get_library_naming(env, LibType.SHARED) + self.assertEqual(p, shr) + p = cc.get_library_naming(env, LibType.STATIC) + self.assertEqual(p, stc) + p = cc.get_library_naming(env, LibType.PREFER_STATIC) + self.assertEqual(p, stcshr) + p = cc.get_library_naming(env, LibType.PREFER_SHARED) + self.assertEqual(p, shrstc) + # Test find library by mocking up openbsd + if platform != 'openbsd': + return + with tempfile.TemporaryDirectory() as tmpdir: + for i in ['libfoo.so.6.0', 'libfoo.so.5.0', 'libfoo.so.54.0', 'libfoo.so.66a.0b', 'libfoo.so.70.0.so.1', + 'libbar.so.7.10', 'libbar.so.7.9', 'libbar.so.7.9.3']: + libpath = Path(tmpdir) / i + libpath.write_text('', encoding='utf-8') + found = cc._find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED, lib_prefix_warning=True) + self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') + found = cc._find_library_real('bar', env, [tmpdir], '', LibType.PREFER_SHARED, lib_prefix_warning=True) + self.assertEqual(os.path.basename(found[0]), 'libbar.so.7.10') + + def test_find_library_patterns(self): + ''' + Unit test for the library search patterns used by find_library() + ''' + unix_static = ('lib{}.a', '{}.a') + msvc_static = ('lib{}.a', 'lib{}.lib', '{}.a', '{}.lib') + # This is the priority list of pattern matching for library searching + patterns = {'openbsd': {'shared': ('lib{}.so', '{}.so', 'lib{}.so.[0-9]*.[0-9]*', '{}.so.[0-9]*.[0-9]*'), + 'static': unix_static}, + 'linux': {'shared': ('lib{}.so', '{}.so'), + 'static': unix_static}, + 'darwin': {'shared': ('lib{}.dylib', 'lib{}.so', '{}.dylib', '{}.so'), + 'static': unix_static}, + 'cygwin': {'shared': ('cyg{}.dll', 'cyg{}.dll.a', 'lib{}.dll', + 'lib{}.dll.a', '{}.dll', '{}.dll.a'), + 'static': ('cyg{}.a',) + unix_static}, + 'windows-msvc': {'shared': ('lib{}.lib', '{}.lib'), + 'static': msvc_static}, + 'windows-mingw': {'shared': ('lib{}.dll.a', 'lib{}.lib', 'lib{}.dll', + '{}.dll.a', '{}.lib', '{}.dll'), + 'static': msvc_static}} + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if is_osx(): + self._test_all_naming(cc, env, patterns, 'darwin') + elif is_cygwin(): + self._test_all_naming(cc, env, patterns, 'cygwin') + elif is_windows(): + if cc.get_argument_syntax() == 'msvc': + self._test_all_naming(cc, env, patterns, 'windows-msvc') + else: + self._test_all_naming(cc, env, patterns, 'windows-mingw') + elif is_openbsd(): + self._test_all_naming(cc, env, patterns, 'openbsd') + else: + self._test_all_naming(cc, env, patterns, 'linux') + env.machines.host.system = 'openbsd' + self._test_all_naming(cc, env, patterns, 'openbsd') + env.machines.host.system = 'darwin' + self._test_all_naming(cc, env, patterns, 'darwin') + env.machines.host.system = 'cygwin' + self._test_all_naming(cc, env, patterns, 'cygwin') + env.machines.host.system = 'windows' + self._test_all_naming(cc, env, patterns, 'windows-mingw') + + @skipIfNoPkgconfig + def test_pkgconfig_parse_libs(self): + ''' + Unit test for parsing of pkg-config output to search for libraries + + https://github.com/mesonbuild/meson/issues/3951 + ''' + def create_static_lib(name): + if not is_osx(): + name.open('w', encoding='utf-8').close() + return + src = name.with_suffix('.c') + out = name.with_suffix('.o') + with src.open('w', encoding='utf-8') as f: + f.write('int meson_foobar (void) { return 0; }') + subprocess.check_call(['clang', '-c', str(src), '-o', str(out)]) + subprocess.check_call(['ar', 'csr', str(name), str(out)]) + + with tempfile.TemporaryDirectory() as tmpdir: + pkgbin = ExternalProgram('pkg-config', command=['pkg-config'], silent=True) + env = get_fake_env() + compiler = detect_c_compiler(env, MachineChoice.HOST) + env.coredata.compilers.host = {'c': compiler} + env.coredata.options[OptionKey('link_args', lang='c')] = FakeCompilerOptions() + p1 = Path(tmpdir) / '1' + p2 = Path(tmpdir) / '2' + p1.mkdir() + p2.mkdir() + # libfoo.a is in one prefix + create_static_lib(p1 / 'libfoo.a') + # libbar.a is in both prefixes + create_static_lib(p1 / 'libbar.a') + create_static_lib(p2 / 'libbar.a') + # Ensure that we never statically link to these + create_static_lib(p1 / 'libpthread.a') + create_static_lib(p1 / 'libm.a') + create_static_lib(p1 / 'libc.a') + create_static_lib(p1 / 'libdl.a') + create_static_lib(p1 / 'librt.a') + + def fake_call_pkgbin(self, args, env=None): + if '--libs' not in args: + return 0, '', '' + if args[-1] == 'foo': + return 0, f'-L{p2.as_posix()} -lfoo -L{p1.as_posix()} -lbar', '' + if args[-1] == 'bar': + return 0, f'-L{p2.as_posix()} -lbar', '' + if args[-1] == 'internal': + return 0, f'-L{p1.as_posix()} -lpthread -lm -lc -lrt -ldl', '' + + old_call = PkgConfigDependency._call_pkgbin + old_check = PkgConfigDependency.check_pkgconfig + PkgConfigDependency._call_pkgbin = fake_call_pkgbin + PkgConfigDependency.check_pkgconfig = lambda x, _: pkgbin + # Test begins + try: + kwargs = {'required': True, 'silent': True} + foo_dep = PkgConfigDependency('foo', env, kwargs) + self.assertEqual(foo_dep.get_link_args(), + [(p1 / 'libfoo.a').as_posix(), (p2 / 'libbar.a').as_posix()]) + bar_dep = PkgConfigDependency('bar', env, kwargs) + self.assertEqual(bar_dep.get_link_args(), [(p2 / 'libbar.a').as_posix()]) + internal_dep = PkgConfigDependency('internal', env, kwargs) + if compiler.get_argument_syntax() == 'msvc': + self.assertEqual(internal_dep.get_link_args(), []) + else: + link_args = internal_dep.get_link_args() + for link_arg in link_args: + for lib in ('pthread', 'm', 'c', 'dl', 'rt'): + self.assertNotIn(f'lib{lib}.a', link_arg, msg=link_args) + finally: + # Test ends + PkgConfigDependency._call_pkgbin = old_call + PkgConfigDependency.check_pkgconfig = old_check + # Reset dependency class to ensure that in-process configure doesn't mess up + PkgConfigDependency.pkgbin_cache = {} + PkgConfigDependency.class_pkgbin = PerMachine(None, None) + + def test_version_compare(self): + comparefunc = mesonbuild.mesonlib.version_compare_many + for (a, b, result) in [ + ('0.99.beta19', '>= 0.99.beta14', True), + ]: + self.assertEqual(comparefunc(a, b)[0], result) + + for (a, b, op) in [ + # examples from https://fedoraproject.org/wiki/Archive:Tools/RPM/VersionComparison + ("1.0010", "1.9", operator.gt), + ("1.05", "1.5", operator.eq), + ("1.0", "1", operator.gt), + ("2.50", "2.5", operator.gt), + ("fc4", "fc.4", operator.eq), + ("FC5", "fc4", operator.lt), + ("2a", "2.0", operator.lt), + ("1.0", "1.fc4", operator.gt), + ("3.0.0_fc", "3.0.0.fc", operator.eq), + # from RPM tests + ("1.0", "1.0", operator.eq), + ("1.0", "2.0", operator.lt), + ("2.0", "1.0", operator.gt), + ("2.0.1", "2.0.1", operator.eq), + ("2.0", "2.0.1", operator.lt), + ("2.0.1", "2.0", operator.gt), + ("2.0.1a", "2.0.1a", operator.eq), + ("2.0.1a", "2.0.1", operator.gt), + ("2.0.1", "2.0.1a", operator.lt), + ("5.5p1", "5.5p1", operator.eq), + ("5.5p1", "5.5p2", operator.lt), + ("5.5p2", "5.5p1", operator.gt), + ("5.5p10", "5.5p10", operator.eq), + ("5.5p1", "5.5p10", operator.lt), + ("5.5p10", "5.5p1", operator.gt), + ("10xyz", "10.1xyz", operator.lt), + ("10.1xyz", "10xyz", operator.gt), + ("xyz10", "xyz10", operator.eq), + ("xyz10", "xyz10.1", operator.lt), + ("xyz10.1", "xyz10", operator.gt), + ("xyz.4", "xyz.4", operator.eq), + ("xyz.4", "8", operator.lt), + ("8", "xyz.4", operator.gt), + ("xyz.4", "2", operator.lt), + ("2", "xyz.4", operator.gt), + ("5.5p2", "5.6p1", operator.lt), + ("5.6p1", "5.5p2", operator.gt), + ("5.6p1", "6.5p1", operator.lt), + ("6.5p1", "5.6p1", operator.gt), + ("6.0.rc1", "6.0", operator.gt), + ("6.0", "6.0.rc1", operator.lt), + ("10b2", "10a1", operator.gt), + ("10a2", "10b2", operator.lt), + ("1.0aa", "1.0aa", operator.eq), + ("1.0a", "1.0aa", operator.lt), + ("1.0aa", "1.0a", operator.gt), + ("10.0001", "10.0001", operator.eq), + ("10.0001", "10.1", operator.eq), + ("10.1", "10.0001", operator.eq), + ("10.0001", "10.0039", operator.lt), + ("10.0039", "10.0001", operator.gt), + ("4.999.9", "5.0", operator.lt), + ("5.0", "4.999.9", operator.gt), + ("20101121", "20101121", operator.eq), + ("20101121", "20101122", operator.lt), + ("20101122", "20101121", operator.gt), + ("2_0", "2_0", operator.eq), + ("2.0", "2_0", operator.eq), + ("2_0", "2.0", operator.eq), + ("a", "a", operator.eq), + ("a+", "a+", operator.eq), + ("a+", "a_", operator.eq), + ("a_", "a+", operator.eq), + ("+a", "+a", operator.eq), + ("+a", "_a", operator.eq), + ("_a", "+a", operator.eq), + ("+_", "+_", operator.eq), + ("_+", "+_", operator.eq), + ("_+", "_+", operator.eq), + ("+", "_", operator.eq), + ("_", "+", operator.eq), + # other tests + ('0.99.beta19', '0.99.beta14', operator.gt), + ("1.0.0", "2.0.0", operator.lt), + (".0.0", "2.0.0", operator.lt), + ("alpha", "beta", operator.lt), + ("1.0", "1.0.0", operator.lt), + ("2.456", "2.1000", operator.lt), + ("2.1000", "3.111", operator.lt), + ("2.001", "2.1", operator.eq), + ("2.34", "2.34", operator.eq), + ("6.1.2", "6.3.8", operator.lt), + ("1.7.3.0", "2.0.0", operator.lt), + ("2.24.51", "2.25", operator.lt), + ("2.1.5+20120813+gitdcbe778", "2.1.5", operator.gt), + ("3.4.1", "3.4b1", operator.gt), + ("041206", "200090325", operator.lt), + ("0.6.2+git20130413", "0.6.2", operator.gt), + ("2.6.0+bzr6602", "2.6.0", operator.gt), + ("2.6.0", "2.6b2", operator.gt), + ("2.6.0+bzr6602", "2.6b2x", operator.gt), + ("0.6.7+20150214+git3a710f9", "0.6.7", operator.gt), + ("15.8b", "15.8.0.1", operator.lt), + ("1.2rc1", "1.2.0", operator.lt), + ]: + ver_a = Version(a) + ver_b = Version(b) + if op is operator.eq: + for o, name in [(op, 'eq'), (operator.ge, 'ge'), (operator.le, 'le')]: + self.assertTrue(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + if op is operator.lt: + for o, name in [(op, 'lt'), (operator.le, 'le'), (operator.ne, 'ne')]: + self.assertTrue(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + for o, name in [(operator.gt, 'gt'), (operator.ge, 'ge'), (operator.eq, 'eq')]: + self.assertFalse(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + if op is operator.gt: + for o, name in [(op, 'gt'), (operator.ge, 'ge'), (operator.ne, 'ne')]: + self.assertTrue(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + for o, name in [(operator.lt, 'lt'), (operator.le, 'le'), (operator.eq, 'eq')]: + self.assertFalse(o(ver_a, ver_b), f'{ver_a} {name} {ver_b}') + + def test_msvc_toolset_version(self): + ''' + Ensure that the toolset version returns the correct value for this MSVC + ''' + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise unittest.SkipTest('Test only applies to MSVC-like compilers') + toolset_ver = cc.get_toolset_version() + self.assertIsNotNone(toolset_ver) + # Visual Studio 2015 and older versions do not define VCToolsVersion + # TODO: ICL doesn't set this in the VSC2015 profile either + if cc.id == 'msvc' and int(''.join(cc.version.split('.')[0:2])) < 1910: + return + if 'VCToolsVersion' in os.environ: + vctools_ver = os.environ['VCToolsVersion'] + else: + self.assertIn('VCINSTALLDIR', os.environ) + # See https://devblogs.microsoft.com/cppblog/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ + vctools_ver = (Path(os.environ['VCINSTALLDIR']) / 'Auxiliary' / 'Build' / 'Microsoft.VCToolsVersion.default.txt').read_text(encoding='utf-8') + self.assertTrue(vctools_ver.startswith(toolset_ver), + msg=f'{vctools_ver!r} does not start with {toolset_ver!r}') + + def test_split_args(self): + split_args = mesonbuild.mesonlib.split_args + join_args = mesonbuild.mesonlib.join_args + if is_windows(): + test_data = [ + # examples from https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments + (r'"a b c" d e', ['a b c', 'd', 'e'], True), + (r'"ab\"c" "\\" d', ['ab"c', '\\', 'd'], False), + (r'a\\\b d"e f"g h', [r'a\\\b', 'de fg', 'h'], False), + (r'a\\\"b c d', [r'a\"b', 'c', 'd'], False), + (r'a\\\\"b c" d e', [r'a\\b c', 'd', 'e'], False), + # other basics + (r'""', [''], True), + (r'a b c d "" e', ['a', 'b', 'c', 'd', '', 'e'], True), + (r"'a b c' d e", ["'a", 'b', "c'", 'd', 'e'], True), + (r"'a&b&c' d e", ["'a&b&c'", 'd', 'e'], True), + (r"a & b & c d e", ['a', '&', 'b', '&', 'c', 'd', 'e'], True), + (r"'a & b & c d e'", ["'a", '&', 'b', '&', 'c', 'd', "e'"], True), + ('a b\nc\rd \n\re', ['a', 'b', 'c', 'd', 'e'], False), + # more illustrative tests + (r'cl test.cpp /O1 /Fe:test.exe', ['cl', 'test.cpp', '/O1', '/Fe:test.exe'], True), + (r'cl "test.cpp /O1 /Fe:test.exe"', ['cl', 'test.cpp /O1 /Fe:test.exe'], True), + (r'cl /DNAME=\"Bob\" test.cpp', ['cl', '/DNAME="Bob"', 'test.cpp'], False), + (r'cl "/DNAME=\"Bob\"" test.cpp', ['cl', '/DNAME="Bob"', 'test.cpp'], True), + (r'cl /DNAME=\"Bob, Alice\" test.cpp', ['cl', '/DNAME="Bob,', 'Alice"', 'test.cpp'], False), + (r'cl "/DNAME=\"Bob, Alice\"" test.cpp', ['cl', '/DNAME="Bob, Alice"', 'test.cpp'], True), + (r'cl C:\path\with\backslashes.cpp', ['cl', r'C:\path\with\backslashes.cpp'], True), + (r'cl C:\\path\\with\\double\\backslashes.cpp', ['cl', r'C:\\path\\with\\double\\backslashes.cpp'], True), + (r'cl "C:\\path\\with\\double\\backslashes.cpp"', ['cl', r'C:\\path\\with\\double\\backslashes.cpp'], False), + (r'cl C:\path with spaces\test.cpp', ['cl', r'C:\path', 'with', r'spaces\test.cpp'], False), + (r'cl "C:\path with spaces\test.cpp"', ['cl', r'C:\path with spaces\test.cpp'], True), + (r'cl /DPATH="C:\path\with\backslashes test.cpp', ['cl', r'/DPATH=C:\path\with\backslashes test.cpp'], False), + (r'cl /DPATH=\"C:\\ends\\with\\backslashes\\\" test.cpp', ['cl', r'/DPATH="C:\\ends\\with\\backslashes\"', 'test.cpp'], False), + (r'cl /DPATH="C:\\ends\\with\\backslashes\\" test.cpp', ['cl', '/DPATH=C:\\\\ends\\\\with\\\\backslashes\\', 'test.cpp'], False), + (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\"', 'test.cpp'], True), + (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\\ test.cpp'], False), + (r'cl "/DNAME=\"C:\\ends\\with\\backslashes\\\\\"" test.cpp', ['cl', r'/DNAME="C:\\ends\\with\\backslashes\\"', 'test.cpp'], True), + ] + else: + test_data = [ + (r"'a b c' d e", ['a b c', 'd', 'e'], True), + (r"a/b/c d e", ['a/b/c', 'd', 'e'], True), + (r"a\b\c d e", [r'abc', 'd', 'e'], False), + (r"a\\b\\c d e", [r'a\b\c', 'd', 'e'], False), + (r'"a b c" d e', ['a b c', 'd', 'e'], False), + (r'"a\\b\\c\\" d e', ['a\\b\\c\\', 'd', 'e'], False), + (r"'a\b\c\' d e", ['a\\b\\c\\', 'd', 'e'], True), + (r"'a&b&c' d e", ['a&b&c', 'd', 'e'], True), + (r"a & b & c d e", ['a', '&', 'b', '&', 'c', 'd', 'e'], False), + (r"'a & b & c d e'", ['a & b & c d e'], True), + (r"abd'e f'g h", [r'abde fg', 'h'], False), + ('a b\nc\rd \n\re', ['a', 'b', 'c', 'd', 'e'], False), + + ('g++ -DNAME="Bob" test.cpp', ['g++', '-DNAME=Bob', 'test.cpp'], False), + ("g++ '-DNAME=\"Bob\"' test.cpp", ['g++', '-DNAME="Bob"', 'test.cpp'], True), + ('g++ -DNAME="Bob, Alice" test.cpp', ['g++', '-DNAME=Bob, Alice', 'test.cpp'], False), + ("g++ '-DNAME=\"Bob, Alice\"' test.cpp", ['g++', '-DNAME="Bob, Alice"', 'test.cpp'], True), + ] + + for (cmd, expected, roundtrip) in test_data: + self.assertEqual(split_args(cmd), expected) + if roundtrip: + self.assertEqual(join_args(expected), cmd) + + def test_quote_arg(self): + split_args = mesonbuild.mesonlib.split_args + quote_arg = mesonbuild.mesonlib.quote_arg + if is_windows(): + test_data = [ + ('', '""'), + ('arg1', 'arg1'), + ('/option1', '/option1'), + ('/Ovalue', '/Ovalue'), + ('/OBob&Alice', '/OBob&Alice'), + ('/Ovalue with spaces', r'"/Ovalue with spaces"'), + (r'/O"value with spaces"', r'"/O\"value with spaces\""'), + (r'/OC:\path with spaces\test.exe', r'"/OC:\path with spaces\test.exe"'), + ('/LIBPATH:C:\\path with spaces\\ends\\with\\backslashes\\', r'"/LIBPATH:C:\path with spaces\ends\with\backslashes\\"'), + ('/LIBPATH:"C:\\path with spaces\\ends\\with\\backslashes\\\\"', r'"/LIBPATH:\"C:\path with spaces\ends\with\backslashes\\\\\""'), + (r'/DMSG="Alice said: \"Let\'s go\""', r'"/DMSG=\"Alice said: \\\"Let\'s go\\\"\""'), + ] + else: + test_data = [ + ('arg1', 'arg1'), + ('--option1', '--option1'), + ('-O=value', '-O=value'), + ('-O=Bob&Alice', "'-O=Bob&Alice'"), + ('-O=value with spaces', "'-O=value with spaces'"), + ('-O="value with spaces"', '\'-O=\"value with spaces\"\''), + ('-O=/path with spaces/test', '\'-O=/path with spaces/test\''), + ('-DMSG="Alice said: \\"Let\'s go\\""', "'-DMSG=\"Alice said: \\\"Let'\"'\"'s go\\\"\"'"), + ] + + for (arg, expected) in test_data: + self.assertEqual(quote_arg(arg), expected) + self.assertEqual(split_args(expected)[0], arg) + + def test_depfile(self): + for (f, target, expdeps) in [ + # empty, unknown target + ([''], 'unknown', set()), + # simple target & deps + (['meson/foo.o : foo.c foo.h'], 'meson/foo.o', set({'foo.c', 'foo.h'})), + (['meson/foo.o: foo.c foo.h'], 'foo.c', set()), + # get all deps + (['meson/foo.o: foo.c foo.h', + 'foo.c: gen.py'], 'meson/foo.o', set({'foo.c', 'foo.h', 'gen.py'})), + (['meson/foo.o: foo.c foo.h', + 'foo.c: gen.py'], 'foo.c', set({'gen.py'})), + # linue continuation, multiple targets + (['foo.o \\', 'foo.h: bar'], 'foo.h', set({'bar'})), + (['foo.o \\', 'foo.h: bar'], 'foo.o', set({'bar'})), + # \\ handling + (['foo: Program\\ F\\iles\\\\X'], 'foo', set({'Program Files\\X'})), + # $ handling + (['f$o.o: c/b'], 'f$o.o', set({'c/b'})), + (['f$$o.o: c/b'], 'f$o.o', set({'c/b'})), + # cycles + (['a: b', 'b: a'], 'a', set({'a', 'b'})), + (['a: b', 'b: a'], 'b', set({'a', 'b'})), + ]: + d = mesonbuild.depfile.DepFile(f) + deps = d.get_all_dependencies(target) + self.assertEqual(sorted(deps), sorted(expdeps)) + + def test_log_once(self): + f = io.StringIO() + with mock.patch('mesonbuild.mlog._logger.log_file', f), \ + mock.patch('mesonbuild.mlog._logger.logged_once', set()): + mesonbuild.mlog.log('foo', once=True) + mesonbuild.mlog.log('foo', once=True) + actual = f.getvalue().strip() + self.assertEqual(actual, 'foo', actual) + + def test_log_once_ansi(self): + f = io.StringIO() + with mock.patch('mesonbuild.mlog._logger.log_file', f), \ + mock.patch('mesonbuild.mlog._logger.logged_once', set()): + mesonbuild.mlog.log(mesonbuild.mlog.bold('foo'), once=True) + mesonbuild.mlog.log(mesonbuild.mlog.bold('foo'), once=True) + actual = f.getvalue().strip() + self.assertEqual(actual.count('foo'), 1, actual) + + mesonbuild.mlog.log('foo', once=True) + actual = f.getvalue().strip() + self.assertEqual(actual.count('foo'), 1, actual) + + f.truncate() + + mesonbuild.mlog.warning('bar', once=True) + mesonbuild.mlog.warning('bar', once=True) + actual = f.getvalue().strip() + self.assertEqual(actual.count('bar'), 1, actual) + + def test_sort_libpaths(self): + sort_libpaths = mesonbuild.dependencies.base.sort_libpaths + self.assertEqual(sort_libpaths( + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + self.assertEqual(sort_libpaths( + ['/usr/local/lib', '/home/mesonuser/.local/lib', '/usr/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + self.assertEqual(sort_libpaths( + ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/lib/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + self.assertEqual(sort_libpaths( + ['/usr/lib', '/usr/local/lib', '/home/mesonuser/.local/lib'], + ['/home/mesonuser/.local/lib/pkgconfig', '/usr/local/libdata/pkgconfig']), + ['/home/mesonuser/.local/lib', '/usr/local/lib', '/usr/lib']) + + def test_dependency_factory_order(self): + b = mesonbuild.dependencies.base + F = mesonbuild.dependencies.factory + with tempfile.TemporaryDirectory() as tmpdir: + with chdir(tmpdir): + env = get_fake_env() + env.scratch_dir = tmpdir + + f = F.DependencyFactory( + 'test_dep', + methods=[b.DependencyMethods.PKGCONFIG, b.DependencyMethods.CMAKE] + ) + actual = [m() for m in f(env, MachineChoice.HOST, {'required': False})] + self.assertListEqual([m.type_name for m in actual], ['pkgconfig', 'cmake']) + + f = F.DependencyFactory( + 'test_dep', + methods=[b.DependencyMethods.CMAKE, b.DependencyMethods.PKGCONFIG] + ) + actual = [m() for m in f(env, MachineChoice.HOST, {'required': False})] + self.assertListEqual([m.type_name for m in actual], ['cmake', 'pkgconfig']) + + def test_validate_json(self) -> None: + """Validate the json schema for the test cases.""" + try: + from jsonschema import validate, ValidationError + except ImportError: + if is_ci(): + raise + raise unittest.SkipTest('Python jsonschema module not found.') + + schema = json.loads(Path('data/test.schema.json').read_text(encoding='utf-8')) + + errors = [] # type: T.Tuple[str, Exception] + for p in Path('test cases').glob('**/test.json'): + try: + validate(json.loads(p.read_text(encoding='utf-8')), schema=schema) + except ValidationError as e: + errors.append((p.resolve(), e)) + + for f, e in errors: + print(f'Failed to validate: "{f}"') + print(str(e)) + + self.assertFalse(errors) + + def test_typed_pos_args_types(self) -> None: + @typed_pos_args('foo', str, int, bool) + def _(obj, node, args: T.Tuple[str, int, bool], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], int) + self.assertIsInstance(args[2], bool) + + _(None, mock.Mock(), ['string', 1, False], None) + + def test_typed_pos_args_types_invalid(self) -> None: + @typed_pos_args('foo', str, int, bool) + def _(obj, node, args: T.Tuple[str, int, bool], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 1.0, False], None) + self.assertEqual(str(cm.exception), 'foo argument 2 was of type "float" but should have been "int"') + + def test_typed_pos_args_types_wrong_number(self) -> None: + @typed_pos_args('foo', str, int, bool) + def _(obj, node, args: T.Tuple[str, int, bool], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 1], None) + self.assertEqual(str(cm.exception), 'foo takes exactly 3 arguments, but got 2.') + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 1, True, True], None) + self.assertEqual(str(cm.exception), 'foo takes exactly 3 arguments, but got 4.') + + def test_typed_pos_args_varargs(self) -> None: + @typed_pos_args('foo', str, varargs=str) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], list) + self.assertIsInstance(args[1][0], str) + self.assertIsInstance(args[1][1], str) + + _(None, mock.Mock(), ['string', 'var', 'args'], None) + + def test_typed_pos_args_varargs_not_given(self) -> None: + @typed_pos_args('foo', str, varargs=str) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], list) + self.assertEqual(args[1], []) + + _(None, mock.Mock(), ['string'], None) + + def test_typed_pos_args_varargs_invalid(self) -> None: + @typed_pos_args('foo', str, varargs=str) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args', 0], None) + self.assertEqual(str(cm.exception), 'foo argument 4 was of type "int" but should have been "str"') + + def test_typed_pos_args_varargs_invalid_multiple_types(self) -> None: + @typed_pos_args('foo', str, varargs=(str, list)) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args', 0], None) + self.assertEqual(str(cm.exception), 'foo argument 4 was of type "int" but should have been one of: "str", "list"') + + def test_typed_pos_args_max_varargs(self) -> None: + @typed_pos_args('foo', str, varargs=str, max_varargs=5) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], str) + self.assertIsInstance(args[1], list) + self.assertIsInstance(args[1][0], str) + self.assertIsInstance(args[1][1], str) + + _(None, mock.Mock(), ['string', 'var', 'args'], None) + + def test_typed_pos_args_max_varargs_exceeded(self) -> None: + @typed_pos_args('foo', str, varargs=str, max_varargs=1) + def _(obj, node, args: T.Tuple[str, T.Tuple[str, ...]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args'], None) + self.assertEqual(str(cm.exception), 'foo takes between 1 and 2 arguments, but got 3.') + + def test_typed_pos_args_min_varargs(self) -> None: + @typed_pos_args('foo', varargs=str, max_varargs=2, min_varargs=1) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertIsInstance(args, tuple) + self.assertIsInstance(args[0], list) + self.assertIsInstance(args[0][0], str) + self.assertIsInstance(args[0][1], str) + + _(None, mock.Mock(), ['string', 'var'], None) + + def test_typed_pos_args_min_varargs_not_met(self) -> None: + @typed_pos_args('foo', str, varargs=str, min_varargs=1) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual(str(cm.exception), 'foo takes at least 2 arguments, but got 1.') + + def test_typed_pos_args_min_and_max_varargs_exceeded(self) -> None: + @typed_pos_args('foo', str, varargs=str, min_varargs=1, max_varargs=2) + def _(obj, node, args: T.Tuple[str, T.Tuple[str, ...]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', 'var', 'args', 'bar'], None) + self.assertEqual(str(cm.exception), 'foo takes between 2 and 3 arguments, but got 4.') + + def test_typed_pos_args_min_and_max_varargs_not_met(self) -> None: + @typed_pos_args('foo', str, varargs=str, min_varargs=1, max_varargs=2) + def _(obj, node, args: T.Tuple[str, T.Tuple[str, ...]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual(str(cm.exception), 'foo takes between 2 and 3 arguments, but got 1.') + + def test_typed_pos_args_variadic_and_optional(self) -> None: + @typed_pos_args('foo', str, optargs=[str], varargs=str, min_varargs=0) + def _(obj, node, args: T.Tuple[str, T.List[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(AssertionError) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual( + str(cm.exception), + 'varargs and optargs not supported together as this would be ambiguous') + + def test_typed_pos_args_min_optargs_not_met(self) -> None: + @typed_pos_args('foo', str, str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string'], None) + self.assertEqual(str(cm.exception), 'foo takes at least 2 arguments, but got 1.') + + def test_typed_pos_args_min_optargs_max_exceeded(self) -> None: + @typed_pos_args('foo', str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertTrue(False) # should not be reachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), ['string', '1', '2'], None) + self.assertEqual(str(cm.exception), 'foo takes at most 2 arguments, but got 3.') + + def test_typed_pos_args_optargs_not_given(self) -> None: + @typed_pos_args('foo', str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertEqual(len(args), 2) + self.assertIsInstance(args[0], str) + self.assertEqual(args[0], 'string') + self.assertIsNone(args[1]) + + _(None, mock.Mock(), ['string'], None) + + def test_typed_pos_args_optargs_some_given(self) -> None: + @typed_pos_args('foo', str, optargs=[str, int]) + def _(obj, node, args: T.Tuple[str, T.Optional[str], T.Optional[int]], kwargs) -> None: + self.assertEqual(len(args), 3) + self.assertIsInstance(args[0], str) + self.assertEqual(args[0], 'string') + self.assertIsInstance(args[1], str) + self.assertEqual(args[1], '1') + self.assertIsNone(args[2]) + + _(None, mock.Mock(), ['string', '1'], None) + + def test_typed_pos_args_optargs_all_given(self) -> None: + @typed_pos_args('foo', str, optargs=[str]) + def _(obj, node, args: T.Tuple[str, T.Optional[str]], kwargs) -> None: + self.assertEqual(len(args), 2) + self.assertIsInstance(args[0], str) + self.assertEqual(args[0], 'string') + self.assertIsInstance(args[1], str) + + _(None, mock.Mock(), ['string', '1'], None) + + def test_typed_kwarg_basic(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, default='') + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertIsInstance(kwargs['input'], str) + self.assertEqual(kwargs['input'], 'foo') + + _(None, mock.Mock(), [], {'input': 'foo'}) + + def test_typed_kwarg_missing_required(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertTrue(False) # should be unreachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), [], {}) + self.assertEqual(str(cm.exception), 'testfunc is missing required keyword argument "input"') + + def test_typed_kwarg_missing_optional(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', (str, type(None))), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.Optional[str]]) -> None: + self.assertIsNone(kwargs['input']) + + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_default(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, default='default'), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertEqual(kwargs['input'], 'default') + + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_container_valid(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), default=[], required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertEqual(kwargs['input'], ['str']) + + _(None, mock.Mock(), [], {'input': ['str']}) + + def test_typed_kwarg_container_invalid(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertTrue(False) # should be unreachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), [], {'input': {}}) + self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type dict[] but should have been array[str]") + + def test_typed_kwarg_contained_invalid(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(dict, str), required=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.Dict[str, str]]) -> None: + self.assertTrue(False) # should be unreachable + + with self.assertRaises(InvalidArguments) as cm: + _(None, mock.Mock(), [], {'input': {'key': 1, 'bar': 2}}) + self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type dict[int] but should have been dict[str]") + + def test_typed_kwarg_container_listify(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertEqual(kwargs['input'], ['str']) + + _(None, mock.Mock(), [], {'input': 'str'}) + + def test_typed_kwarg_container_default_copy(self) -> None: + default: T.List[str] = [] + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), listify=True, default=default), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertIsNot(kwargs['input'], default) + + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_container_pairs(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str, pairs=True), listify=True), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, T.List[str]]) -> None: + self.assertEqual(kwargs['input'], ['a', 'b']) + + _(None, mock.Mock(), [], {'input': ['a', 'b']}) + + with self.assertRaises(MesonException) as cm: + _(None, mock.Mock(), [], {'input': ['a']}) + self.assertEqual(str(cm.exception), "testfunc keyword argument 'input' was of type array[str] but should have been array[str] that has even size") + + def test_typed_kwarg_since(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, since='1.0', since_message='Its awesome, use it', + deprecated='2.0', deprecated_message='Its terrible, dont use it') + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertIsInstance(kwargs['input'], str) + self.assertEqual(kwargs['input'], 'foo') + + with self.subTest('use before available'), \ + mock.patch('sys.stdout', io.StringIO()) as out, \ + mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '0.1'}): + # With Meson 0.1 it should trigger the "introduced" warning but not the "deprecated" warning + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(out.getvalue(), r'WARNING:.*introduced.*input arg in testfunc. Its awesome, use it') + self.assertNotRegex(out.getvalue(), r'WARNING:.*deprecated.*input arg in testfunc. Its terrible, dont use it') + + with self.subTest('no warnings should be triggered'), \ + mock.patch('sys.stdout', io.StringIO()) as out, \ + mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '1.5'}): + # With Meson 1.5 it shouldn't trigger any warning + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertNotRegex(out.getvalue(), r'WARNING:.*') + + with self.subTest('use after deprecated'), \ + mock.patch('sys.stdout', io.StringIO()) as out, \ + mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '2.0'}): + # With Meson 2.0 it should trigger the "deprecated" warning but not the "introduced" warning + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(out.getvalue(), r'WARNING:.*deprecated.*input arg in testfunc. Its terrible, dont use it') + self.assertNotRegex(out.getvalue(), r'WARNING:.*introduced.*input arg in testfunc. Its awesome, use it') + + def test_typed_kwarg_validator(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', str, default='', validator=lambda x: 'invalid!' if x != 'foo' else None) + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + pass + + # Should be valid + _(None, mock.Mock(), tuple(), dict(input='foo')) + + with self.assertRaises(MesonException) as cm: + _(None, mock.Mock(), tuple(), dict(input='bar')) + self.assertEqual(str(cm.exception), "testfunc keyword argument \"input\" invalid!") + + def test_typed_kwarg_convertor(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('native', bool, default=False, convertor=lambda n: MachineChoice.BUILD if n else MachineChoice.HOST) + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, MachineChoice]) -> None: + assert isinstance(kwargs['native'], MachineChoice) + + _(None, mock.Mock(), tuple(), dict(native=True)) + + @mock.patch('mesonbuild.mesonlib.project_meson_versions', {'': '1.0'}) + def test_typed_kwarg_since_values(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', ContainerTypeInfo(list, str), listify=True, default=[], deprecated_values={'foo': '0.9'}, since_values={'bar': '1.1'}), + KwargInfo('output', ContainerTypeInfo(dict, str), default={}, deprecated_values={'foo': '0.9', 'foo2': ('0.9', 'dont use it')}, since_values={'bar': '1.1', 'bar2': ('1.1', 'use this')}), + KwargInfo('install_dir', (bool, str, NoneType), deprecated_values={False: '0.9'}), + KwargInfo( + 'mode', + (str, type(None)), + validator=in_set_validator({'clean', 'build', 'rebuild', 'deprecated', 'since'}), + deprecated_values={'deprecated': '1.0'}, + since_values={'since': '1.1'}), + KwargInfo('dict', (ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str)), default={}, + since_values={list: '1.9'}), + KwargInfo('new_dict', (ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str)), default={}, + since_values={dict: '1.1'}), + KwargInfo('foo', (str, int, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str), ContainerTypeInfo(list, int)), default={}, + since_values={str: '1.1', ContainerTypeInfo(list, str): '1.2', ContainerTypeInfo(dict, str): '1.3'}, + deprecated_values={int: '0.8', ContainerTypeInfo(list, int): '0.9'}), + KwargInfo('tuple', (ContainerTypeInfo(list, (str, int))), default=[], listify=True, + since_values={ContainerTypeInfo(list, str): '1.1', ContainerTypeInfo(list, int): '1.2'}), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + pass + + with self.subTest('deprecated array string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'input': ['foo']}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "input" value "foo".*""") + + with self.subTest('new array string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'input': ['bar']}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "input" value "bar".*""") + + with self.subTest('deprecated dict string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'foo': 'a'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo".*""") + + with self.subTest('deprecated dict string value with msg'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'foo2': 'a'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo2" in dict keys. dont use it.*""") + + with self.subTest('new dict string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'bar': 'b'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar".*""") + + with self.subTest('new dict string value with msg'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'output': {'bar2': 'a'}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar2" in dict keys. use this.*""") + + with self.subTest('new string type'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': 'foo'}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "foo" of type str.*""") + + with self.subTest('new array of string type'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': ['foo']}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.2': "testfunc" keyword argument "foo" of type array\[str\].*""") + + with self.subTest('new dict of string type'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': {'plop': 'foo'}}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.3': "testfunc" keyword argument "foo" of type dict\[str\].*""") + + with self.subTest('deprecated int value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': 1}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.8': "testfunc" keyword argument "foo" of type int.*""") + + with self.subTest('deprecated array int value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'foo': [1]}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "foo" of type array\[int\].*""") + + with self.subTest('new list[str] value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'tuple': ['foo', 42]}) + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "tuple" of type array\[str\].*""") + self.assertRegex(out.getvalue(), r"""WARNING: Project targets '1.0'.*introduced in '1.2': "testfunc" keyword argument "tuple" of type array\[int\].*""") + + with self.subTest('deprecated array string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'input': 'foo'}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "input" value "foo".*""") + + with self.subTest('new array string value'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'input': 'bar'}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "input" value "bar".*""") + + with self.subTest('non string union'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'install_dir': False}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '0.9': "testfunc" keyword argument "install_dir" value "False".*""") + + with self.subTest('deprecated string union'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'mode': 'deprecated'}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*deprecated since '1.0': "testfunc" keyword argument "mode" value "deprecated".*""") + + with self.subTest('new string union'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'mode': 'since'}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "mode" value "since".*""") + + with self.subTest('new container'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'dict': ['a=b']}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.9': "testfunc" keyword argument "dict" of type list.*""") + + with self.subTest('new container set to default'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {'new_dict': {}}) + self.assertRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "new_dict" of type dict.*""") + + with self.subTest('new container default'), mock.patch('sys.stdout', io.StringIO()) as out: + _(None, mock.Mock(subproject=''), [], {}) + self.assertNotRegex(out.getvalue(), r"""WARNING:.Project targets '1.0'.*introduced in '1.1': "testfunc" keyword argument "new_dict" of type dict.*""") + + def test_typed_kwarg_evolve(self) -> None: + k = KwargInfo('foo', str, required=True, default='foo') + v = k.evolve(default='bar') + self.assertEqual(k.name, 'foo') + self.assertEqual(k.name, v.name) + self.assertEqual(k.types, str) + self.assertEqual(k.types, v.types) + self.assertEqual(k.required, True) + self.assertEqual(k.required, v.required) + self.assertEqual(k.default, 'foo') + self.assertEqual(v.default, 'bar') + + def test_typed_kwarg_default_type(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('no_default', (str, ContainerTypeInfo(list, str), NoneType)), + KwargInfo('str_default', (str, ContainerTypeInfo(list, str)), default=''), + KwargInfo('list_default', (str, ContainerTypeInfo(list, str)), default=['']), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertEqual(kwargs['no_default'], None) + self.assertEqual(kwargs['str_default'], '') + self.assertEqual(kwargs['list_default'], ['']) + _(None, mock.Mock(), [], {}) + + def test_typed_kwarg_invalid_default_type(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('invalid_default', (str, ContainerTypeInfo(list, str), NoneType), default=42), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + pass + self.assertRaises(AssertionError, _, None, mock.Mock(), [], {}) + + def test_typed_kwarg_container_in_tuple(self) -> None: + @typed_kwargs( + 'testfunc', + KwargInfo('input', (str, ContainerTypeInfo(list, str))), + ) + def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None: + self.assertEqual(kwargs['input'], args[0]) + _(None, mock.Mock(), [''], {'input': ''}) + _(None, mock.Mock(), [['']], {'input': ['']}) + self.assertRaises(InvalidArguments, _, None, mock.Mock(), [], {'input': 42}) + + def test_detect_cpu_family(self) -> None: + """Test the various cpu families that we detect and normalize. + + This is particularly useful as both documentation, and to keep testing + platforms that are less common. + """ + + @contextlib.contextmanager + def mock_trial(value: str) -> T.Iterable[None]: + """Mock all of the ways we could get the trial at once.""" + mocked = mock.Mock(return_value=value) + + with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \ + mock.patch('mesonbuild.environment.platform.processor', mocked), \ + mock.patch('mesonbuild.environment.platform.machine', mocked): + yield + + cases = [ + ('x86', 'x86'), + ('i386', 'x86'), + ('bepc', 'x86'), # Haiku + ('earm', 'arm'), # NetBSD + ('arm', 'arm'), + ('ppc64', 'ppc64'), + ('powerpc64', 'ppc64'), + ('powerpc', 'ppc'), + ('ppc', 'ppc'), + ('macppc', 'ppc'), + ('power macintosh', 'ppc'), + ('mips64el', 'mips'), + ('mips64', 'mips'), + ('mips', 'mips'), + ('mipsel', 'mips'), + ('ip30', 'mips'), + ('ip35', 'mips'), + ('parisc64', 'parisc'), + ('sun4u', 'sparc64'), + ('sun4v', 'sparc64'), + ('amd64', 'x86_64'), + ('x64', 'x86_64'), + ('i86pc', 'x86_64'), # Solaris + ('aarch64', 'aarch64'), + ('aarch64_be', 'aarch64'), + ] + + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): + for test, expected in cases: + with self.subTest(test, has_define=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({'c': cc}) + self.assertEqual(actual, expected) + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): + for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: + with self.subTest(test, has_define=True), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({'c': cc}) + self.assertEqual(actual, expected) + + # machine_info_can_run calls detect_cpu_family with no compilers at all + with mock.patch( + 'mesonbuild.environment.any_compiler_has_define', + mock.Mock(side_effect=AssertionError('Should not be called')), + ): + for test, expected in [('mips64', 'mips64')]: + with self.subTest(test, has_compiler=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({}) + self.assertEqual(actual, expected) + + def test_detect_cpu(self) -> None: + + @contextlib.contextmanager + def mock_trial(value: str) -> T.Iterable[None]: + """Mock all of the ways we could get the trial at once.""" + mocked = mock.Mock(return_value=value) + + with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \ + mock.patch('mesonbuild.environment.platform.processor', mocked), \ + mock.patch('mesonbuild.environment.platform.machine', mocked): + yield + + cases = [ + ('amd64', 'x86_64'), + ('x64', 'x86_64'), + ('i86pc', 'x86_64'), + ('earm', 'arm'), + ('mips64el', 'mips'), + ('mips64', 'mips'), + ('mips', 'mips'), + ('mipsel', 'mips'), + ('aarch64', 'aarch64'), + ('aarch64_be', 'aarch64'), + ] + + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): + for test, expected in cases: + with self.subTest(test, has_define=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({'c': cc}) + self.assertEqual(actual, expected) + + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): + for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: + with self.subTest(test, has_define=True), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({'c': cc}) + self.assertEqual(actual, expected) + + with mock.patch( + 'mesonbuild.environment.any_compiler_has_define', + mock.Mock(side_effect=AssertionError('Should not be called')), + ): + for test, expected in [('mips64', 'mips64')]: + with self.subTest(test, has_compiler=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({}) + self.assertEqual(actual, expected) + + def test_interpreter_unpicklable(self) -> None: + build = mock.Mock() + build.environment = mock.Mock() + build.environment.get_source_dir = mock.Mock(return_value='') + with mock.patch('mesonbuild.interpreter.Interpreter._redetect_machines', mock.Mock()), \ + self.assertRaises(mesonbuild.mesonlib.MesonBugException): + i = mesonbuild.interpreter.Interpreter(build, mock=True) + pickle.dumps(i) + + def test_major_versions_differ(self) -> None: + # Return True when going to next major release, when going to dev cycle, + # when going to rc cycle or when going out of rc cycle. + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.60.0')) + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.59.99')) + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.60.0.rc1')) + self.assertTrue(coredata.major_versions_differ('0.59.99', '0.60.0.rc1')) + self.assertTrue(coredata.major_versions_differ('0.60.0.rc1', '0.60.0')) + # Return False when going to next point release or when staying in dev/rc cycle. + self.assertFalse(coredata.major_versions_differ('0.60.0', '0.60.0')) + self.assertFalse(coredata.major_versions_differ('0.60.0', '0.60.1')) + self.assertFalse(coredata.major_versions_differ('0.59.99', '0.59.99')) + self.assertFalse(coredata.major_versions_differ('0.60.0.rc1', '0.60.0.rc2')) + + def test_option_key_from_string(self) -> None: + cases = [ + ('c_args', OptionKey('args', lang='c', _type=OptionType.COMPILER)), + ('build.cpp_args', OptionKey('args', machine=MachineChoice.BUILD, lang='cpp', _type=OptionType.COMPILER)), + ('prefix', OptionKey('prefix', _type=OptionType.BUILTIN)), + ('made_up', OptionKey('made_up', _type=OptionType.PROJECT)), + + # TODO: the from_String method should be splitting the prefix off of + # these, as we have the type already, but it doesn't. For now have a + # test so that we don't change the behavior un-intentionally + ('b_lto', OptionKey('b_lto', _type=OptionType.BASE)), + ('backend_startup_project', OptionKey('backend_startup_project', _type=OptionType.BACKEND)), + ] + + for raw, expected in cases: + with self.subTest(raw): + self.assertEqual(OptionKey.from_string(raw), expected) diff --git a/devtools/meson/unittests/linuxcrosstests.py b/devtools/meson/unittests/linuxcrosstests.py new file mode 100644 index 0000000..28bf415 --- /dev/null +++ b/devtools/meson/unittests/linuxcrosstests.py @@ -0,0 +1,192 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import shutil +import unittest +import platform + +from mesonbuild.mesonlib import ( + is_windows, is_cygwin +) +from mesonbuild.mesonlib import MesonException + + + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +class BaseLinuxCrossTests(BasePlatformTests): + # Don't pass --libdir when cross-compiling. We have tests that + # check whether meson auto-detects it correctly. + libdir = None + + +def should_run_cross_arm_tests(): + return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm') + +@unittest.skipUnless(not is_windows() and should_run_cross_arm_tests(), "requires ability to cross compile to ARM") +class LinuxCrossArmTests(BaseLinuxCrossTests): + ''' + Tests that cross-compilation to Linux/ARM works + ''' + + def setUp(self): + super().setUp() + self.meson_cross_files = [os.path.join(self.src_root, 'cross', 'ubuntu-armhf.txt')] + + def test_cflags_cross_environment_pollution(self): + ''' + Test that the CFLAGS environment variable does not pollute the cross + environment. This can't be an ordinary test case because we need to + inspect the compiler database. + ''' + testdir = os.path.join(self.common_test_dir, '3 static') + self.init(testdir, override_envvars={'CFLAGS': '-DBUILD_ENVIRONMENT_ONLY'}) + compdb = self.get_compdb() + self.assertNotIn('-DBUILD_ENVIRONMENT_ONLY', compdb[0]['command']) + + def test_cross_file_overrides_always_args(self): + ''' + Test that $lang_args in cross files always override get_always_args(). + Needed for overriding the default -D_FILE_OFFSET_BITS=64 on some + architectures such as some Android versions and Raspbian. + https://github.com/mesonbuild/meson/issues/3049 + https://github.com/mesonbuild/meson/issues/3089 + ''' + testdir = os.path.join(self.unit_test_dir, '33 cross file overrides always args') + self.meson_cross_files = [os.path.join(testdir, 'ubuntu-armhf-overrides.txt')] + self.init(testdir) + compdb = self.get_compdb() + self.assertRegex(compdb[0]['command'], '-D_FILE_OFFSET_BITS=64.*-U_FILE_OFFSET_BITS') + self.build() + + def test_cross_libdir(self): + # When cross compiling "libdir" should default to "lib" + # rather than "lib/x86_64-linux-gnu" or something like that. + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + for i in self.introspect('--buildoptions'): + if i['name'] == 'libdir': + self.assertEqual(i['value'], 'lib') + return + self.assertTrue(False, 'Option libdir not in introspect data.') + + def test_cross_libdir_subproject(self): + # Guard against a regression where calling "subproject" + # would reset the value of libdir to its default value. + testdir = os.path.join(self.unit_test_dir, '75 subdir libdir') + self.init(testdir, extra_args=['--libdir=fuf']) + for i in self.introspect('--buildoptions'): + if i['name'] == 'libdir': + self.assertEqual(i['value'], 'fuf') + return + self.assertTrue(False, 'Libdir specified on command line gets reset.') + + def test_std_remains(self): + # C_std defined in project options must be in effect also when cross compiling. + testdir = os.path.join(self.unit_test_dir, '50 noncross options') + self.init(testdir) + compdb = self.get_compdb() + self.assertRegex(compdb[0]['command'], '-std=c99') + self.build() + + @skipIfNoPkgconfig + def test_pkg_config_option(self): + if not shutil.which('arm-linux-gnueabihf-pkg-config'): + raise unittest.SkipTest('Cross-pkgconfig not found.') + testdir = os.path.join(self.unit_test_dir, '57 pkg_config_path option') + self.init(testdir, extra_args=[ + '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'), + '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'), + ]) + + def test_run_native_test(self): + ''' + https://github.com/mesonbuild/meson/issues/7997 + check run native test in crossbuild without exe wrapper + ''' + testdir = os.path.join(self.unit_test_dir, '87 run native test') + stamp_file = os.path.join(self.builddir, 'native_test_has_run.stamp') + self.init(testdir) + self.build() + self.assertPathDoesNotExist(stamp_file) + self.run_tests() + self.assertPathExists(stamp_file) + + +def should_run_cross_mingw_tests(): + return shutil.which('x86_64-w64-mingw32-gcc') and not (is_windows() or is_cygwin()) + +@unittest.skipUnless(not is_windows() and should_run_cross_mingw_tests(), "requires ability to cross compile with MinGW") +class LinuxCrossMingwTests(BaseLinuxCrossTests): + ''' + Tests that cross-compilation to Windows/MinGW works + ''' + + def setUp(self): + super().setUp() + self.meson_cross_files = [os.path.join(self.src_root, 'cross', 'linux-mingw-w64-64bit.txt')] + + def test_exe_wrapper_behaviour(self): + ''' + Test that an exe wrapper that isn't found doesn't cause compiler sanity + checks and compiler checks to fail, but causes configure to fail if it + requires running a cross-built executable (custom_target or run_target) + and causes the tests to be skipped if they are run. + ''' + testdir = os.path.join(self.unit_test_dir, '36 exe_wrapper behaviour') + # Configures, builds, and tests fine by default + self.init(testdir) + self.build() + self.run_tests() + self.wipe() + os.mkdir(self.builddir) + # Change cross file to use a non-existing exe_wrapper and it should fail + self.meson_cross_files = [os.path.join(testdir, 'broken-cross.txt')] + # Force tracebacks so we can detect them properly + env = {'MESON_FORCE_BACKTRACE': '1'} + error_message = "An exe_wrapper is needed but was not found. Please define one in cross file and check the command and/or add it to PATH." + + with self.assertRaises(MesonException) as cm: + # Must run in-process or we'll get a generic CalledProcessError + self.init(testdir, extra_args='-Drun-target=false', + inprocess=True, + override_envvars=env) + self.assertEqual(str(cm.exception), error_message) + + with self.assertRaises(MesonException) as cm: + # Must run in-process or we'll get a generic CalledProcessError + self.init(testdir, extra_args='-Dcustom-target=false', + inprocess=True, + override_envvars=env) + self.assertEqual(str(cm.exception), error_message) + + self.init(testdir, extra_args=['-Dcustom-target=false', '-Drun-target=false'], + override_envvars=env) + self.build() + + with self.assertRaises(MesonException) as cm: + # Must run in-process or we'll get a generic CalledProcessError + self.run_tests(inprocess=True, override_envvars=env) + self.assertEqual(str(cm.exception), + "The exe_wrapper defined in the cross file 'broken' was not found. Please check the command and/or add it to PATH.") + + @skipIfNoPkgconfig + def test_cross_pkg_config_option(self): + testdir = os.path.join(self.unit_test_dir, '57 pkg_config_path option') + self.init(testdir, extra_args=[ + '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'), + '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'), + ]) diff --git a/devtools/meson/unittests/linuxliketests.py b/devtools/meson/unittests/linuxliketests.py new file mode 100644 index 0000000..b5c9b4e --- /dev/null +++ b/devtools/meson/unittests/linuxliketests.py @@ -0,0 +1,1852 @@ +# Copyright 2016-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import stat +import subprocess +import re +import tempfile +import textwrap +import os +import shutil +import hashlib +from unittest import mock, skipUnless, SkipTest +from glob import glob +from pathlib import Path +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.base +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_osx, is_cygwin, is_openbsd, is_haiku, + is_sunos, windows_proof_rmtree, version_compare, is_linux, + OptionKey, EnvironmentException +) +from mesonbuild.compilers import ( + detect_c_compiler, detect_cpp_compiler, compiler_from_language, +) +from mesonbuild.compilers.c import AppleClangCCompiler +from mesonbuild.compilers.cpp import AppleClangCPPCompiler +from mesonbuild.compilers.objc import AppleClangObjCCompiler +from mesonbuild.compilers.objcpp import AppleClangObjCPPCompiler +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +import mesonbuild.modules.pkgconfig + +PKG_CONFIG = os.environ.get('PKG_CONFIG', 'pkg-config') + + +from run_tests import ( + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +def _prepend_pkg_config_path(path: str) -> str: + """Prepend a string value to pkg_config_path + + :param path: The path to prepend + :return: The path, followed by any PKG_CONFIG_PATH already in the environment + """ + pkgconf = os.environ.get('PKG_CONFIG_PATH') + if pkgconf: + return f'{path}{os.path.pathsep}{pkgconf}' + return path + + +def _clang_at_least(compiler: 'Compiler', minver: str, apple_minver: T.Optional[str]) -> bool: + """ + check that Clang compiler is at least a specified version, whether AppleClang or regular Clang + + Parameters + ---------- + compiler: + Meson compiler object + minver: str + Clang minimum version + apple_minver: str + AppleCLang minimum version + + Returns + ------- + at_least: bool + Clang is at least the specified version + """ + if isinstance(compiler, (AppleClangCCompiler, AppleClangCPPCompiler)): + if apple_minver is None: + return False + return version_compare(compiler.version, apple_minver) + return version_compare(compiler.version, minver) + +@skipUnless(not is_windows(), "requires something Unix-like") +class LinuxlikeTests(BasePlatformTests): + ''' + Tests that should run on Linux, macOS, and *BSD + ''' + + def test_basic_soname(self): + ''' + Test that the soname is set correctly for shared libraries. This can't + be an ordinary test case because we need to run `readelf` and actually + check the soname. + https://github.com/mesonbuild/meson/issues/785 + ''' + testdir = os.path.join(self.common_test_dir, '4 shared') + self.init(testdir) + self.build() + lib1 = os.path.join(self.builddir, 'libmylib.so') + soname = get_soname(lib1) + self.assertEqual(soname, 'libmylib.so') + + def test_custom_soname(self): + ''' + Test that the soname is set correctly for shared libraries when + a custom prefix and/or suffix is used. This can't be an ordinary test + case because we need to run `readelf` and actually check the soname. + https://github.com/mesonbuild/meson/issues/785 + ''' + testdir = os.path.join(self.common_test_dir, '24 library versions') + self.init(testdir) + self.build() + lib1 = os.path.join(self.builddir, 'prefixsomelib.suffix') + soname = get_soname(lib1) + self.assertEqual(soname, 'prefixsomelib.suffix') + + def test_pic(self): + ''' + Test that -fPIC is correctly added to static libraries when b_staticpic + is true and not when it is false. This can't be an ordinary test case + because we need to inspect the compiler database. + ''' + if is_windows() or is_cygwin() or is_osx(): + raise SkipTest('PIC not relevant') + + testdir = os.path.join(self.common_test_dir, '3 static') + self.init(testdir) + compdb = self.get_compdb() + self.assertIn('-fPIC', compdb[0]['command']) + self.setconf('-Db_staticpic=false') + # Regenerate build + self.build() + compdb = self.get_compdb() + self.assertNotIn('-fPIC', compdb[0]['command']) + + @mock.patch.dict(os.environ) + def test_pkgconfig_gen(self): + ''' + Test that generated pkg-config files can be found and have the correct + version and link args. This can't be an ordinary test case because we + need to run pkg-config outside of a Meson build file. + https://github.com/mesonbuild/meson/issues/889 + ''' + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + env = get_fake_env(testdir, self.builddir, self.prefix) + kwargs = {'required': True, 'silent': True} + os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir + foo_dep = PkgConfigDependency('libfoo', env, kwargs) + self.assertTrue(foo_dep.found()) + self.assertEqual(foo_dep.get_version(), '1.0') + self.assertIn('-lfoo', foo_dep.get_link_args()) + self.assertEqual(foo_dep.get_pkgconfig_variable('foo', [], None), 'bar') + self.assertPathEqual(foo_dep.get_pkgconfig_variable('datadir', [], None), '/usr/data') + + libhello_nolib = PkgConfigDependency('libhello_nolib', env, kwargs) + self.assertTrue(libhello_nolib.found()) + self.assertEqual(libhello_nolib.get_link_args(), []) + self.assertEqual(libhello_nolib.get_compile_args(), []) + self.assertEqual(libhello_nolib.get_pkgconfig_variable('foo', [], None), 'bar') + self.assertEqual(libhello_nolib.get_pkgconfig_variable('prefix', [], None), self.prefix) + if version_compare(PkgConfigDependency.check_pkgconfig(env, libhello_nolib.pkgbin),">=0.29.1"): + self.assertEqual(libhello_nolib.get_pkgconfig_variable('escaped_var', [], None), r'hello\ world') + self.assertEqual(libhello_nolib.get_pkgconfig_variable('unescaped_var', [], None), 'hello world') + + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() in {'gcc', 'clang'}: + for name in {'ct', 'ct0'}: + ct_dep = PkgConfigDependency(name, env, kwargs) + self.assertTrue(ct_dep.found()) + self.assertIn('-lct', ct_dep.get_link_args(raw=True)) + + def test_pkgconfig_gen_deps(self): + ''' + Test that generated pkg-config files correctly handle dependencies + ''' + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + privatedir1 = self.privatedir + + self.new_builddir() + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen', 'dependencies') + self.init(testdir, override_envvars={'PKG_CONFIG_LIBDIR': privatedir1}) + privatedir2 = self.privatedir + + env = { + 'PKG_CONFIG_LIBDIR': os.pathsep.join([privatedir1, privatedir2]), + 'PKG_CONFIG_SYSTEM_LIBRARY_PATH': '/usr/lib', + } + self._run([PKG_CONFIG, 'dependency-test', '--validate'], override_envvars=env) + + # pkg-config strips some duplicated flags so we have to parse the + # generated file ourself. + expected = { + 'Requires': 'libexposed', + 'Requires.private': 'libfoo >= 1.0', + 'Libs': '-L${libdir} -llibmain -pthread -lcustom', + 'Libs.private': '-lcustom2 -L${libdir} -llibinternal', + 'Cflags': '-I${includedir} -pthread -DCUSTOM', + } + if is_osx() or is_haiku(): + expected['Cflags'] = expected['Cflags'].replace('-pthread ', '') + with open(os.path.join(privatedir2, 'dependency-test.pc'), encoding='utf-8') as f: + matched_lines = 0 + for line in f: + parts = line.split(':', 1) + if parts[0] in expected: + key = parts[0] + val = parts[1].strip() + expected_val = expected[key] + self.assertEqual(expected_val, val) + matched_lines += 1 + self.assertEqual(len(expected), matched_lines) + + cmd = [PKG_CONFIG, 'requires-test'] + out = self._run(cmd + ['--print-requires'], override_envvars=env).strip().split('\n') + if not is_openbsd(): + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) + else: + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) + + cmd = [PKG_CONFIG, 'requires-private-test'] + out = self._run(cmd + ['--print-requires-private'], override_envvars=env).strip().split('\n') + if not is_openbsd(): + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo >= 1.0', 'libhello'])) + else: + self.assertEqual(sorted(out), sorted(['libexposed', 'libfoo>=1.0', 'libhello'])) + + cmd = [PKG_CONFIG, 'pub-lib-order'] + out = self._run(cmd + ['--libs'], override_envvars=env).strip().split() + self.assertEqual(out, ['-llibmain2', '-llibinternal']) + + # See common/44 pkgconfig-gen/meson.build for description of the case this test + with open(os.path.join(privatedir1, 'simple2.pc'), encoding='utf-8') as f: + content = f.read() + self.assertIn('Libs: -L${libdir} -lsimple2 -lsimple1', content) + self.assertIn('Libs.private: -lz', content) + + with open(os.path.join(privatedir1, 'simple3.pc'), encoding='utf-8') as f: + content = f.read() + self.assertEqual(1, content.count('-lsimple3')) + + with open(os.path.join(privatedir1, 'simple5.pc'), encoding='utf-8') as f: + content = f.read() + self.assertNotIn('-lstat2', content) + + @mock.patch.dict(os.environ) + def test_pkgconfig_uninstalled(self): + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + self.build() + + os.environ['PKG_CONFIG_LIBDIR'] = os.path.join(self.builddir, 'meson-uninstalled') + if is_cygwin(): + os.environ['PATH'] += os.pathsep + self.builddir + + self.new_builddir() + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen', 'dependencies') + self.init(testdir) + self.build() + self.run_tests() + + def test_pkg_unfound(self): + testdir = os.path.join(self.unit_test_dir, '23 unfound pkgconfig') + self.init(testdir) + with open(os.path.join(self.privatedir, 'somename.pc'), encoding='utf-8') as f: + pcfile = f.read() + self.assertNotIn('blub_blob_blib', pcfile) + + def test_symlink_builddir(self) -> None: + ''' + Test using a symlink as either the builddir for "setup" or + the argument for "-C". + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + + symdir = f'{self.builddir}-symlink' + os.symlink(self.builddir, symdir) + self.addCleanup(os.unlink, symdir) + self.change_builddir(symdir) + + self.init(testdir) + self.build() + self._run(self.mtest_command) + + def test_vala_c_warnings(self): + ''' + Test that no warnings are emitted for C code generated by Vala. This + can't be an ordinary test case because we need to inspect the compiler + database. + https://github.com/mesonbuild/meson/issues/864 + ''' + if not shutil.which('valac'): + raise SkipTest('valac not installed.') + testdir = os.path.join(self.vala_test_dir, '5 target glib') + self.init(testdir) + compdb = self.get_compdb() + vala_command = None + c_command = None + for each in compdb: + if each['file'].endswith('GLib.Thread.c'): + vala_command = each['command'] + elif each['file'].endswith('GLib.Thread.vala'): + continue + elif each['file'].endswith('retcode.c'): + c_command = each['command'] + else: + m = 'Unknown file {!r} in vala_c_warnings test'.format(each['file']) + raise AssertionError(m) + self.assertIsNotNone(vala_command) + self.assertIsNotNone(c_command) + # -w suppresses all warnings, should be there in Vala but not in C + self.assertIn(" -w ", vala_command) + self.assertNotIn(" -w ", c_command) + # -Wall enables all warnings, should be there in C but not in Vala + self.assertNotIn(" -Wall ", vala_command) + self.assertIn(" -Wall ", c_command) + # -Werror converts warnings to errors, should always be there since it's + # injected by an unrelated piece of code and the project has werror=true + self.assertIn(" -Werror ", vala_command) + self.assertIn(" -Werror ", c_command) + + @skipIfNoPkgconfig + def test_qtdependency_pkgconfig_detection(self): + ''' + Test that qt4 and qt5 detection with pkgconfig works. + ''' + # Verify Qt4 or Qt5 can be found with pkg-config + qt4 = subprocess.call([PKG_CONFIG, '--exists', 'QtCore']) + qt5 = subprocess.call([PKG_CONFIG, '--exists', 'Qt5Core']) + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Dmethod=pkg-config']) + # Confirm that the dependency was found with pkg-config + mesonlog = self.get_meson_log_raw() + if qt4 == 0: + self.assertRegex(mesonlog, + r'Run-time dependency qt4 \(modules: Core\) found: YES 4.* \(pkg-config\)') + if qt5 == 0: + self.assertRegex(mesonlog, + r'Run-time dependency qt5 \(modules: Core\) found: YES 5.* \(pkg-config\)') + + @skip_if_not_base_option('b_sanitize') + def test_generate_gir_with_address_sanitizer(self): + if is_cygwin(): + raise SkipTest('asan not available on Cygwin') + if is_openbsd(): + raise SkipTest('-fsanitize=address is not supported on OpenBSD') + + testdir = os.path.join(self.framework_test_dir, '7 gnome') + self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) + self.build() + + def test_qt5dependency_qmake_detection(self): + ''' + Test that qt5 detection with qmake works. This can't be an ordinary + test case because it involves setting the environment. + ''' + # Verify that qmake is for Qt5 + if not shutil.which('qmake-qt5'): + if not shutil.which('qmake'): + raise SkipTest('QMake not found') + output = subprocess.getoutput('qmake --version') + if 'Qt version 5' not in output: + raise SkipTest('Qmake found, but it is not for Qt 5.') + # Disable pkg-config codepath and force searching with qmake/qmake-qt5 + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Dmethod=qmake']) + # Confirm that the dependency was found with qmake + mesonlog = self.get_meson_log_raw() + self.assertRegex(mesonlog, + r'Run-time dependency qt5 \(modules: Core\) found: YES .* \(qmake\)\n') + + def test_qt6dependency_qmake_detection(self): + ''' + Test that qt6 detection with qmake works. This can't be an ordinary + test case because it involves setting the environment. + ''' + # Verify that qmake is for Qt6 + if not shutil.which('qmake6'): + if not shutil.which('qmake'): + raise SkipTest('QMake not found') + output = subprocess.getoutput('qmake --version') + if 'Qt version 6' not in output: + raise SkipTest('Qmake found, but it is not for Qt 6.') + # Disable pkg-config codepath and force searching with qmake/qmake-qt6 + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Dmethod=qmake']) + # Confirm that the dependency was found with qmake + mesonlog = self.get_meson_log_raw() + self.assertRegex(mesonlog, + r'Run-time dependency qt6 \(modules: Core\) found: YES .* \(qmake\)\n') + + def glob_sofiles_without_privdir(self, g): + files = glob(g) + return [f for f in files if not f.endswith('.p')] + + def _test_soname_impl(self, libpath, install): + if is_cygwin() or is_osx(): + raise SkipTest('Test only applicable to ELF and linuxlike sonames') + + testdir = os.path.join(self.unit_test_dir, '1 soname') + self.init(testdir) + self.build() + if install: + self.install() + + # File without aliases set. + nover = os.path.join(libpath, 'libnover.so') + self.assertPathExists(nover) + self.assertFalse(os.path.islink(nover)) + self.assertEqual(get_soname(nover), 'libnover.so') + self.assertEqual(len(self.glob_sofiles_without_privdir(nover[:-3] + '*')), 1) + + # File with version set + verset = os.path.join(libpath, 'libverset.so') + self.assertPathExists(verset + '.4.5.6') + self.assertEqual(os.readlink(verset), 'libverset.so.4') + self.assertEqual(get_soname(verset), 'libverset.so.4') + self.assertEqual(len(self.glob_sofiles_without_privdir(verset[:-3] + '*')), 3) + + # File with soversion set + soverset = os.path.join(libpath, 'libsoverset.so') + self.assertPathExists(soverset + '.1.2.3') + self.assertEqual(os.readlink(soverset), 'libsoverset.so.1.2.3') + self.assertEqual(get_soname(soverset), 'libsoverset.so.1.2.3') + self.assertEqual(len(self.glob_sofiles_without_privdir(soverset[:-3] + '*')), 2) + + # File with version and soversion set to same values + settosame = os.path.join(libpath, 'libsettosame.so') + self.assertPathExists(settosame + '.7.8.9') + self.assertEqual(os.readlink(settosame), 'libsettosame.so.7.8.9') + self.assertEqual(get_soname(settosame), 'libsettosame.so.7.8.9') + self.assertEqual(len(self.glob_sofiles_without_privdir(settosame[:-3] + '*')), 2) + + # File with version and soversion set to different values + bothset = os.path.join(libpath, 'libbothset.so') + self.assertPathExists(bothset + '.1.2.3') + self.assertEqual(os.readlink(bothset), 'libbothset.so.1.2.3') + self.assertEqual(os.readlink(bothset + '.1.2.3'), 'libbothset.so.4.5.6') + self.assertEqual(get_soname(bothset), 'libbothset.so.1.2.3') + self.assertEqual(len(self.glob_sofiles_without_privdir(bothset[:-3] + '*')), 3) + + # A shared_module that is not linked to anything + module = os.path.join(libpath, 'libsome_module.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), None) + + # A shared_module that is not linked to an executable with link_with: + module = os.path.join(libpath, 'liblinked_module1.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), 'liblinked_module1.so') + + # A shared_module that is not linked to an executable with dependencies: + module = os.path.join(libpath, 'liblinked_module2.so') + self.assertPathExists(module) + self.assertFalse(os.path.islink(module)) + self.assertEqual(get_soname(module), 'liblinked_module2.so') + + def test_soname(self): + self._test_soname_impl(self.builddir, False) + + def test_installed_soname(self): + libdir = self.installdir + os.path.join(self.prefix, self.libdir) + self._test_soname_impl(libdir, True) + + def test_compiler_check_flags_order(self): + ''' + Test that compiler check flags override all other flags. This can't be + an ordinary test case because it needs the environment to be set. + ''' + testdir = os.path.join(self.common_test_dir, '36 has function') + env = get_fake_env(testdir, self.builddir, self.prefix) + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + Oflag = '-O3' + OflagCPP = Oflag + if cpp.get_id() in ('clang', 'gcc'): + # prevent developers from adding "int main(int argc, char **argv)" + # to small Meson checks unless these parameters are actually used + OflagCPP += ' -Werror=unused-parameter' + env = {'CFLAGS': Oflag, + 'CXXFLAGS': OflagCPP} + self.init(testdir, override_envvars=env) + cmds = self.get_meson_log_compiler_checks() + for cmd in cmds: + if cmd[0] == 'ccache': + cmd = cmd[1:] + # Verify that -I flags from the `args` kwarg are first + # This is set in the '36 has function' test case + self.assertEqual(cmd[1], '-I/tmp') + # Verify that -O3 set via the environment is overridden by -O0 + Oargs = [arg for arg in cmd if arg.startswith('-O')] + self.assertEqual(Oargs, [Oflag, '-O0']) + + def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: + has_cpp17 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=5.0.0', '>=9.1') or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=5.0.0')) + has_cpp2a_c17 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=6.0.0', '>=10.0') or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) + has_cpp20 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=10.0.0', None) or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=10.0.0')) + has_c18 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=8.0.0', '>=11.0') or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) + # Check that all the listed -std=xxx options for this compiler work just fine when used + # https://en.wikipedia.org/wiki/Xcode#Latest_versions + # https://www.gnu.org/software/gcc/projects/cxx-status.html + key = OptionKey('std', lang=compiler.language) + for v in compiler.get_options()[key].choices: + # we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly + # thus, C++ first + if '++17' in v and not has_cpp17: + continue + elif '++2a' in v and not has_cpp2a_c17: # https://en.cppreference.com/w/cpp/compiler_support + continue + elif '++20' in v and not has_cpp20: + continue + # now C + elif '17' in v and not has_cpp2a_c17: + continue + elif '18' in v and not has_c18: + continue + self.init(testdir, extra_args=[f'-D{key!s}={v}']) + cmd = self.get_compdb()[0]['command'] + # c++03 and gnu++03 are not understood by ICC, don't try to look for them + skiplist = frozenset([ + ('intel', 'c++03'), + ('intel', 'gnu++03')]) + if v != 'none' and not (compiler.get_id(), v) in skiplist: + cmd_std = f" -std={v} " + self.assertIn(cmd_std, cmd) + try: + self.build() + except Exception: + print(f'{key!s} was {v!r}') + raise + self.wipe() + # Check that an invalid std option in CFLAGS/CPPFLAGS fails + # Needed because by default ICC ignores invalid options + cmd_std = '-std=FAIL' + if compiler.language == 'c': + env_flag_name = 'CFLAGS' + elif compiler.language == 'cpp': + env_flag_name = 'CXXFLAGS' + else: + raise NotImplementedError(f'Language {compiler.language} not defined.') + env = {} + env[env_flag_name] = cmd_std + with self.assertRaises((subprocess.CalledProcessError, EnvironmentException), + msg='C compiler should have failed with -std=FAIL'): + self.init(testdir, override_envvars = env) + # ICC won't fail in the above because additional flags are needed to + # make unknown -std=... options errors. + self.build() + + def test_compiler_c_stds(self): + ''' + Test that C stds specified for this compiler can all be used. Can't be + an ordinary test because it requires passing options to meson. + ''' + testdir = os.path.join(self.common_test_dir, '1 trivial') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + self._test_stds_impl(testdir, cc) + + def test_compiler_cpp_stds(self): + ''' + Test that C++ stds specified for this compiler can all be used. Can't + be an ordinary test because it requires passing options to meson. + ''' + testdir = os.path.join(self.common_test_dir, '2 cpp') + env = get_fake_env(testdir, self.builddir, self.prefix) + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + self._test_stds_impl(testdir, cpp) + + def test_unity_subproj(self): + testdir = os.path.join(self.common_test_dir, '42 subproject') + self.init(testdir, extra_args='--unity=subprojects') + pdirs = glob(os.path.join(self.builddir, 'subprojects/sublib/simpletest*.p')) + self.assertEqual(len(pdirs), 1) + self.assertPathExists(os.path.join(pdirs[0], 'simpletest-unity0.c')) + sdirs = glob(os.path.join(self.builddir, 'subprojects/sublib/*sublib*.p')) + self.assertEqual(len(sdirs), 1) + self.assertPathExists(os.path.join(sdirs[0], 'sublib-unity0.c')) + self.assertPathDoesNotExist(os.path.join(self.builddir, 'user@exe/user-unity.c')) + self.build() + + def test_installed_modes(self): + ''' + Test that files installed by these tests have the correct permissions. + Can't be an ordinary test because our installed_files.txt is very basic. + ''' + if is_cygwin(): + self.new_builddir_in_tempdir() + # Test file modes + testdir = os.path.join(self.common_test_dir, '12 data') + self.init(testdir) + self.install() + + f = os.path.join(self.installdir, 'etc', 'etcfile.dat') + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = 'rw-------' + self.assertEqual(want_mode, found_mode[1:]) + + f = os.path.join(self.installdir, 'usr', 'bin', 'runscript.sh') + statf = os.stat(f) + found_mode = stat.filemode(statf.st_mode) + want_mode = 'rwxr-sr-x' + self.assertEqual(want_mode, found_mode[1:]) + if os.getuid() == 0: + # The chown failed nonfatally if we're not root + self.assertEqual(0, statf.st_uid) + self.assertEqual(0, statf.st_gid) + + f = os.path.join(self.installdir, 'usr', 'share', 'progname', + 'fileobject_datafile.dat') + orig = os.path.join(testdir, 'fileobject_datafile.dat') + statf = os.stat(f) + statorig = os.stat(orig) + found_mode = stat.filemode(statf.st_mode) + orig_mode = stat.filemode(statorig.st_mode) + self.assertEqual(orig_mode[1:], found_mode[1:]) + self.assertEqual(os.getuid(), statf.st_uid) + if os.getuid() == 0: + # The chown failed nonfatally if we're not root + self.assertEqual(0, statf.st_gid) + + self.wipe() + # Test directory modes + testdir = os.path.join(self.common_test_dir, '59 install subdir') + self.init(testdir) + self.install() + + f = os.path.join(self.installdir, 'usr', 'share', 'sub1', 'second.dat') + statf = os.stat(f) + found_mode = stat.filemode(statf.st_mode) + want_mode = 'rwxr-x--x' + self.assertEqual(want_mode, found_mode[1:]) + if os.getuid() == 0: + # The chown failed nonfatally if we're not root + self.assertEqual(0, statf.st_uid) + + def test_installed_modes_extended(self): + ''' + Test that files are installed with correct permissions using install_mode. + ''' + if is_cygwin(): + self.new_builddir_in_tempdir() + testdir = os.path.join(self.common_test_dir, '190 install_mode') + self.init(testdir) + self.build() + self.install() + + for fsobj, want_mode in [ + ('bin', 'drwxr-x---'), + ('bin/runscript.sh', '-rwxr-sr-x'), + ('bin/trivialprog', '-rwxr-sr-x'), + ('include', 'drwxr-x---'), + ('include/config.h', '-rw-rwSr--'), + ('include/rootdir.h', '-r--r--r--'), + ('lib', 'drwxr-x---'), + ('lib/libstat.a', '-rw---Sr--'), + ('share', 'drwxr-x---'), + ('share/man', 'drwxr-x---'), + ('share/man/man1', 'drwxr-x---'), + ('share/man/man1/foo.1', '-r--r--r--'), + ('share/sub1', 'drwxr-x---'), + ('share/sub1/second.dat', '-rwxr-x--x'), + ('subdir', 'drwxr-x---'), + ('subdir/data.dat', '-rw-rwSr--'), + ]: + f = os.path.join(self.installdir, 'usr', *fsobj.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + self.assertEqual(want_mode, found_mode, + msg=('Expected file %s to have mode %s but found %s instead.' % + (fsobj, want_mode, found_mode))) + # Ensure that introspect --installed works on all types of files + # FIXME: also verify the files list + self.introspect('--installed') + + def test_install_umask(self): + ''' + Test that files are installed with correct permissions using default + install umask of 022, regardless of the umask at time the worktree + was checked out or the build was executed. + ''' + if is_cygwin(): + self.new_builddir_in_tempdir() + # Copy source tree to a temporary directory and change permissions + # there to simulate a checkout with umask 002. + orig_testdir = os.path.join(self.unit_test_dir, '26 install umask') + # Create a new testdir under tmpdir. + tmpdir = os.path.realpath(tempfile.mkdtemp()) + self.addCleanup(windows_proof_rmtree, tmpdir) + testdir = os.path.join(tmpdir, '26 install umask') + # Copy the tree using shutil.copyfile, which will use the current umask + # instead of preserving permissions of the old tree. + save_umask = os.umask(0o002) + self.addCleanup(os.umask, save_umask) + shutil.copytree(orig_testdir, testdir, copy_function=shutil.copyfile) + # Preserve the executable status of subdir/sayhello though. + os.chmod(os.path.join(testdir, 'subdir', 'sayhello'), 0o775) + self.init(testdir) + # Run the build under a 027 umask now. + os.umask(0o027) + self.build() + # And keep umask 027 for the install step too. + self.install() + + for executable in [ + 'bin/prog', + 'share/subdir/sayhello', + ]: + f = os.path.join(self.installdir, 'usr', *executable.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = '-rwxr-xr-x' + self.assertEqual(want_mode, found_mode, + msg=('Expected file %s to have mode %s but found %s instead.' % + (executable, want_mode, found_mode))) + + for directory in [ + 'usr', + 'usr/bin', + 'usr/include', + 'usr/share', + 'usr/share/man', + 'usr/share/man/man1', + 'usr/share/subdir', + ]: + f = os.path.join(self.installdir, *directory.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = 'drwxr-xr-x' + self.assertEqual(want_mode, found_mode, + msg=('Expected directory %s to have mode %s but found %s instead.' % + (directory, want_mode, found_mode))) + + for datafile in [ + 'include/sample.h', + 'share/datafile.cat', + 'share/file.dat', + 'share/man/man1/prog.1', + 'share/subdir/datafile.dog', + ]: + f = os.path.join(self.installdir, 'usr', *datafile.split('/')) + found_mode = stat.filemode(os.stat(f).st_mode) + want_mode = '-rw-r--r--' + self.assertEqual(want_mode, found_mode, + msg=('Expected file %s to have mode %s but found %s instead.' % + (datafile, want_mode, found_mode))) + + def test_cpp_std_override(self): + testdir = os.path.join(self.unit_test_dir, '6 std override') + self.init(testdir) + compdb = self.get_compdb() + # Don't try to use -std=c++03 as a check for the + # presence of a compiler flag, as ICC does not + # support it. + for i in compdb: + if 'prog98' in i['file']: + c98_comp = i['command'] + if 'prog11' in i['file']: + c11_comp = i['command'] + if 'progp' in i['file']: + plain_comp = i['command'] + self.assertNotEqual(len(plain_comp), 0) + self.assertIn('-std=c++98', c98_comp) + self.assertNotIn('-std=c++11', c98_comp) + self.assertIn('-std=c++11', c11_comp) + self.assertNotIn('-std=c++98', c11_comp) + self.assertNotIn('-std=c++98', plain_comp) + self.assertNotIn('-std=c++11', plain_comp) + # Now werror + self.assertIn('-Werror', plain_comp) + self.assertNotIn('-Werror', c98_comp) + + def test_run_installed(self): + if is_cygwin() or is_osx(): + raise SkipTest('LD_LIBRARY_PATH and RPATH not applicable') + + testdir = os.path.join(self.unit_test_dir, '7 run installed') + self.init(testdir) + self.build() + self.install() + installed_exe = os.path.join(self.installdir, 'usr/bin/prog') + installed_libdir = os.path.join(self.installdir, 'usr/foo') + installed_lib = os.path.join(installed_libdir, 'libfoo.so') + self.assertTrue(os.path.isfile(installed_exe)) + self.assertTrue(os.path.isdir(installed_libdir)) + self.assertTrue(os.path.isfile(installed_lib)) + # Must fail when run without LD_LIBRARY_PATH to ensure that + # rpath has been properly stripped rather than pointing to the builddir. + self.assertNotEqual(subprocess.call(installed_exe, stderr=subprocess.DEVNULL), 0) + # When LD_LIBRARY_PATH is set it should start working. + # For some reason setting LD_LIBRARY_PATH in os.environ fails + # when all tests are run (but works when only this test is run), + # but doing this explicitly works. + env = os.environ.copy() + env['LD_LIBRARY_PATH'] = ':'.join([installed_libdir, env.get('LD_LIBRARY_PATH', '')]) + self.assertEqual(subprocess.call(installed_exe, env=env), 0) + # Ensure that introspect --installed works + installed = self.introspect('--installed') + for v in installed.values(): + self.assertTrue('prog' in v or 'foo' in v) + + @skipIfNoPkgconfig + def test_order_of_l_arguments(self): + testdir = os.path.join(self.unit_test_dir, '8 -L -l order') + self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir}) + # NOTE: .pc file has -Lfoo -lfoo -Lbar -lbar but pkg-config reorders + # the flags before returning them to -Lfoo -Lbar -lfoo -lbar + # but pkgconf seems to not do that. Sigh. Support both. + expected_order = [('-L/me/first', '-lfoo1'), + ('-L/me/second', '-lfoo2'), + ('-L/me/first', '-L/me/second'), + ('-lfoo1', '-lfoo2'), + ('-L/me/second', '-L/me/third'), + ('-L/me/third', '-L/me/fourth',), + ('-L/me/third', '-lfoo3'), + ('-L/me/fourth', '-lfoo4'), + ('-lfoo3', '-lfoo4'), + ] + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as ifile: + for line in ifile: + if expected_order[0][0] in line: + for first, second in expected_order: + self.assertLess(line.index(first), line.index(second)) + return + raise RuntimeError('Linker entries not found in the Ninja file.') + + def test_introspect_dependencies(self): + ''' + Tests that mesonintrospect --dependencies returns expected output. + ''' + testdir = os.path.join(self.framework_test_dir, '7 gnome') + self.init(testdir) + glib_found = False + gobject_found = False + deps = self.introspect('--dependencies') + self.assertIsInstance(deps, list) + for dep in deps: + self.assertIsInstance(dep, dict) + self.assertIn('name', dep) + self.assertIn('compile_args', dep) + self.assertIn('link_args', dep) + if dep['name'] == 'glib-2.0': + glib_found = True + elif dep['name'] == 'gobject-2.0': + gobject_found = True + self.assertTrue(glib_found) + self.assertTrue(gobject_found) + if subprocess.call([PKG_CONFIG, '--exists', 'glib-2.0 >= 2.56.2']) != 0: + raise SkipTest('glib >= 2.56.2 needed for the rest') + targets = self.introspect('--targets') + docbook_target = None + for t in targets: + if t['name'] == 'generated-gdbus-docbook': + docbook_target = t + break + self.assertIsInstance(docbook_target, dict) + self.assertEqual(os.path.basename(t['filename'][0]), 'generated-gdbus-doc-' + os.path.basename(t['target_sources'][0]['sources'][0])) + + def test_introspect_installed(self): + testdir = os.path.join(self.linuxlike_test_dir, '7 library versions') + self.init(testdir) + + install = self.introspect('--installed') + install = {os.path.basename(k): v for k, v in install.items()} + print(install) + if is_osx(): + the_truth = { + 'libmodule.dylib': '/usr/lib/libmodule.dylib', + 'libnoversion.dylib': '/usr/lib/libnoversion.dylib', + 'libonlysoversion.5.dylib': '/usr/lib/libonlysoversion.5.dylib', + 'libonlysoversion.dylib': '/usr/lib/libonlysoversion.dylib', + 'libonlyversion.1.dylib': '/usr/lib/libonlyversion.1.dylib', + 'libonlyversion.dylib': '/usr/lib/libonlyversion.dylib', + 'libsome.0.dylib': '/usr/lib/libsome.0.dylib', + 'libsome.dylib': '/usr/lib/libsome.dylib', + } + the_truth_2 = {'/usr/lib/libsome.dylib', + '/usr/lib/libsome.0.dylib', + } + else: + the_truth = { + 'libmodule.so': '/usr/lib/libmodule.so', + 'libnoversion.so': '/usr/lib/libnoversion.so', + 'libonlysoversion.so': '/usr/lib/libonlysoversion.so', + 'libonlysoversion.so.5': '/usr/lib/libonlysoversion.so.5', + 'libonlyversion.so': '/usr/lib/libonlyversion.so', + 'libonlyversion.so.1': '/usr/lib/libonlyversion.so.1', + 'libonlyversion.so.1.4.5': '/usr/lib/libonlyversion.so.1.4.5', + 'libsome.so': '/usr/lib/libsome.so', + 'libsome.so.0': '/usr/lib/libsome.so.0', + 'libsome.so.1.2.3': '/usr/lib/libsome.so.1.2.3', + } + the_truth_2 = {'/usr/lib/libsome.so', + '/usr/lib/libsome.so.0', + '/usr/lib/libsome.so.1.2.3'} + self.assertDictEqual(install, the_truth) + + targets = self.introspect('--targets') + for t in targets: + if t['name'] != 'some': + continue + self.assertSetEqual(the_truth_2, set(t['install_filename'])) + + def test_build_rpath(self): + if is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.unit_test_dir, '10 build_rpath') + self.init(testdir) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') + build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar') + self.install() + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) + self.assertEqual(install_rpath, '/baz') + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) + self.assertEqual(install_rpath, 'baz') + + @skipIfNoPkgconfig + def test_build_rpath_pkgconfig(self): + ''' + Test that current build artefacts (libs) are found first on the rpath, + manually specified rpath comes second and additional rpath elements (from + pkg-config files) come last + ''' + if is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + testdir = os.path.join(self.unit_test_dir, '89 pkgconfig build rpath order') + self.init(testdir, override_envvars={'PKG_CONFIG_PATH': testdir}) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy') + build_rpath = get_rpath(os.path.join(self.builddir, 'progcxx')) + self.assertEqual(build_rpath, '$ORIGIN/sub:/foo/bar:/foo/dummy') + self.install() + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/prog')) + self.assertEqual(install_rpath, '/baz:/foo/dummy') + install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) + self.assertEqual(install_rpath, 'baz:/foo/dummy') + + def test_global_rpath(self): + if is_cygwin(): + raise SkipTest('Windows PE/COFF binaries do not use RPATH') + if is_osx(): + raise SkipTest('Global RPATHs via LDFLAGS not yet supported on MacOS (does anybody need it?)') + + testdir = os.path.join(self.unit_test_dir, '79 global-rpath') + oldinstalldir = self.installdir + + # Build and install an external library without DESTDIR. + # The external library generates a .pc file without an rpath. + yonder_dir = os.path.join(testdir, 'yonder') + yonder_prefix = os.path.join(oldinstalldir, 'yonder') + yonder_libdir = os.path.join(yonder_prefix, self.libdir) + self.prefix = yonder_prefix + self.installdir = yonder_prefix + self.init(yonder_dir) + self.build() + self.install(use_destdir=False) + + # Since rpath has multiple valid formats we need to + # test that they are all properly used. + rpath_formats = [ + ('-Wl,-rpath=', False), + ('-Wl,-rpath,', False), + ('-Wl,--just-symbols=', True), + ('-Wl,--just-symbols,', True), + ('-Wl,-R', False), + ('-Wl,-R,', False) + ] + for rpath_format, exception in rpath_formats: + # Build an app that uses that installed library. + # Supply the rpath to the installed library via LDFLAGS + # (as systems like buildroot and guix are wont to do) + # and verify install preserves that rpath. + self.new_builddir() + env = {'LDFLAGS': rpath_format + yonder_libdir, + 'PKG_CONFIG_PATH': os.path.join(yonder_libdir, 'pkgconfig')} + if exception: + with self.assertRaises(subprocess.CalledProcessError): + self.init(testdir, override_envvars=env) + continue + self.init(testdir, override_envvars=env) + self.build() + self.install(use_destdir=False) + got_rpath = get_rpath(os.path.join(yonder_prefix, 'bin/rpathified')) + self.assertEqual(got_rpath, yonder_libdir, rpath_format) + + @skip_if_not_base_option('b_sanitize') + def test_pch_with_address_sanitizer(self): + if is_cygwin(): + raise SkipTest('asan not available on Cygwin') + if is_openbsd(): + raise SkipTest('-fsanitize=address is not supported on OpenBSD') + + testdir = os.path.join(self.common_test_dir, '13 pch') + self.init(testdir, extra_args=['-Db_sanitize=address', '-Db_lundef=false']) + self.build() + compdb = self.get_compdb() + for i in compdb: + self.assertIn("-fsanitize=address", i["command"]) + + def test_cross_find_program(self): + testdir = os.path.join(self.unit_test_dir, '11 cross prog') + crossfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') + print(os.path.join(testdir, 'some_cross_tool.py')) + + tool_path = os.path.join(testdir, 'some_cross_tool.py') + + crossfile.write(textwrap.dedent(f'''\ + [binaries] + c = '{shutil.which('gcc' if is_sunos() else 'cc')}' + ar = '{shutil.which('ar')}' + strip = '{shutil.which('strip')}' + sometool.py = ['{tool_path}'] + someothertool.py = '{tool_path}' + + [properties] + + [host_machine] + system = 'linux' + cpu_family = 'arm' + cpu = 'armv7' # Not sure if correct. + endian = 'little' + ''')) + crossfile.flush() + self.meson_cross_files = [crossfile.name] + self.init(testdir) + + def test_reconfigure(self): + testdir = os.path.join(self.unit_test_dir, '13 reconfigure') + self.init(testdir, extra_args=['-Db_coverage=true'], default_args=False) + self.build('reconfigure') + + def test_vala_generated_source_buildir_inside_source_tree(self): + ''' + Test that valac outputs generated C files in the expected location when + the builddir is a subdir of the source tree. + ''' + if not shutil.which('valac'): + raise SkipTest('valac not installed.') + + testdir = os.path.join(self.vala_test_dir, '8 generated sources') + newdir = os.path.join(self.builddir, 'srctree') + shutil.copytree(testdir, newdir) + testdir = newdir + # New builddir + builddir = os.path.join(testdir, 'subdir/_build') + os.makedirs(builddir, exist_ok=True) + self.change_builddir(builddir) + self.init(testdir) + self.build() + + def test_old_gnome_module_codepaths(self): + ''' + A lot of code in the GNOME module is conditional on the version of the + glib tools that are installed, and breakages in the old code can slip + by once the CI has a newer glib version. So we force the GNOME module + to pretend that it's running on an ancient glib so the fallback code is + also tested. + ''' + testdir = os.path.join(self.framework_test_dir, '7 gnome') + with mock.patch('mesonbuild.modules.gnome.GnomeModule._get_native_glib_version', mock.Mock(return_value='2.20')): + env = {'MESON_UNIT_TEST_PRETEND_GLIB_OLD': "1"} + self.init(testdir, + inprocess=True, + override_envvars=env) + self.build(override_envvars=env) + + @skipIfNoPkgconfig + def test_pkgconfig_usage(self): + testdir1 = os.path.join(self.unit_test_dir, '27 pkgconfig usage/dependency') + testdir2 = os.path.join(self.unit_test_dir, '27 pkgconfig usage/dependee') + if subprocess.call([PKG_CONFIG, '--cflags', 'glib-2.0'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) != 0: + raise SkipTest('Glib 2.0 dependency not available.') + with tempfile.TemporaryDirectory() as tempdirname: + self.init(testdir1, extra_args=['--prefix=' + tempdirname, '--libdir=lib'], default_args=False) + self.install(use_destdir=False) + shutil.rmtree(self.builddir) + os.mkdir(self.builddir) + pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') + self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'libpkgdep.pc'))) + lib_dir = os.path.join(tempdirname, 'lib') + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = pkg_dir + # Private internal libraries must not leak out. + pkg_out = subprocess.check_output([PKG_CONFIG, '--static', '--libs', 'libpkgdep'], env=myenv) + self.assertNotIn(b'libpkgdep-int', pkg_out, 'Internal library leaked out.') + # Dependencies must not leak to cflags when building only a shared library. + pkg_out = subprocess.check_output([PKG_CONFIG, '--cflags', 'libpkgdep'], env=myenv) + self.assertNotIn(b'glib', pkg_out, 'Internal dependency leaked to headers.') + # Test that the result is usable. + self.init(testdir2, override_envvars=myenv) + self.build(override_envvars=myenv) + myenv = os.environ.copy() + myenv['LD_LIBRARY_PATH'] = ':'.join([lib_dir, myenv.get('LD_LIBRARY_PATH', '')]) + if is_cygwin(): + bin_dir = os.path.join(tempdirname, 'bin') + myenv['PATH'] = bin_dir + os.pathsep + myenv['PATH'] + self.assertTrue(os.path.isdir(lib_dir)) + test_exe = os.path.join(self.builddir, 'pkguser') + self.assertTrue(os.path.isfile(test_exe)) + subprocess.check_call(test_exe, env=myenv) + + @skipIfNoPkgconfig + def test_pkgconfig_relative_paths(self): + testdir = os.path.join(self.unit_test_dir, '61 pkgconfig relative paths') + pkg_dir = os.path.join(testdir, 'pkgconfig') + self.assertPathExists(os.path.join(pkg_dir, 'librelativepath.pc')) + + env = get_fake_env(testdir, self.builddir, self.prefix) + env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') + kwargs = {'required': True, 'silent': True} + relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs) + self.assertTrue(relative_path_dep.found()) + + # Ensure link_args are properly quoted + libpath = Path(self.builddir) / '../relativepath/lib' + link_args = ['-L' + libpath.as_posix(), '-lrelativepath'] + self.assertEqual(relative_path_dep.get_link_args(), link_args) + + @skipIfNoPkgconfig + def test_pkgconfig_duplicate_path_entries(self): + testdir = os.path.join(self.unit_test_dir, '111 pkgconfig duplicate path entries') + pkg_dir = os.path.join(testdir, 'pkgconfig') + + env = get_fake_env(testdir, self.builddir, self.prefix) + env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='') + + # Regression test: This used to modify the value of `pkg_config_path` + # option, adding the meson-uninstalled directory to it. + PkgConfigDependency.setup_env({}, env, MachineChoice.HOST, uninstalled=True) + + pkg_config_path = env.coredata.options[OptionKey('pkg_config_path')].value + self.assertEqual(pkg_config_path, [pkg_dir]) + + @skipIfNoPkgconfig + def test_pkgconfig_internal_libraries(self): + ''' + ''' + with tempfile.TemporaryDirectory() as tempdirname: + # build library + testdirbase = os.path.join(self.unit_test_dir, '32 pkgconfig use libraries') + testdirlib = os.path.join(testdirbase, 'lib') + self.init(testdirlib, extra_args=['--prefix=' + tempdirname, + '--libdir=lib', + '--default-library=static'], default_args=False) + self.build() + self.install(use_destdir=False) + + # build user of library + pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig') + self.new_builddir() + self.init(os.path.join(testdirbase, 'app'), + override_envvars={'PKG_CONFIG_PATH': pkg_dir}) + self.build() + + @skipIfNoPkgconfig + def test_static_archive_stripping(self): + ''' + Check that Meson produces valid static archives with --strip enabled + ''' + with tempfile.TemporaryDirectory() as tempdirname: + testdirbase = os.path.join(self.unit_test_dir, '65 static archive stripping') + + # build lib + self.new_builddir() + testdirlib = os.path.join(testdirbase, 'lib') + testlibprefix = os.path.join(tempdirname, 'libprefix') + self.init(testdirlib, extra_args=['--prefix=' + testlibprefix, + '--libdir=lib', + '--default-library=static', + '--buildtype=debug', + '--strip'], default_args=False) + self.build() + self.install(use_destdir=False) + + # build executable (uses lib, fails if static archive has been stripped incorrectly) + pkg_dir = os.path.join(testlibprefix, 'lib/pkgconfig') + self.new_builddir() + self.init(os.path.join(testdirbase, 'app'), + override_envvars={'PKG_CONFIG_PATH': pkg_dir}) + self.build() + + @skipIfNoPkgconfig + def test_pkgconfig_formatting(self): + testdir = os.path.join(self.unit_test_dir, '38 pkgconfig format') + self.init(testdir) + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = _prepend_pkg_config_path(self.privatedir) + stdo = subprocess.check_output([PKG_CONFIG, '--libs-only-l', 'libsomething'], env=myenv) + deps = [b'-lgobject-2.0', b'-lgio-2.0', b'-lglib-2.0', b'-lsomething'] + if is_windows() or is_cygwin() or is_osx() or is_openbsd(): + # On Windows, libintl is a separate library + deps.append(b'-lintl') + self.assertEqual(set(deps), set(stdo.split())) + + @skipIfNoPkgconfig + @skip_if_not_language('cs') + def test_pkgconfig_csharp_library(self): + testdir = os.path.join(self.unit_test_dir, '49 pkgconfig csharp library') + self.init(testdir) + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = _prepend_pkg_config_path(self.privatedir) + stdo = subprocess.check_output([PKG_CONFIG, '--libs', 'libsomething'], env=myenv) + + self.assertEqual("-r/usr/lib/libsomething.dll", str(stdo.decode('ascii')).strip()) + + @skipIfNoPkgconfig + def test_pkgconfig_link_order(self): + ''' + Test that libraries are listed before their dependencies. + ''' + testdir = os.path.join(self.unit_test_dir, '52 pkgconfig static link order') + self.init(testdir) + myenv = os.environ.copy() + myenv['PKG_CONFIG_PATH'] = _prepend_pkg_config_path(self.privatedir) + stdo = subprocess.check_output([PKG_CONFIG, '--libs', 'libsomething'], env=myenv) + deps = stdo.split() + self.assertLess(deps.index(b'-lsomething'), deps.index(b'-ldependency')) + + def test_deterministic_dep_order(self): + ''' + Test that the dependencies are always listed in a deterministic order. + ''' + testdir = os.path.join(self.unit_test_dir, '42 dep order') + self.init(testdir) + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if 'build myexe:' in line or 'build myexe.exe:' in line: + self.assertIn('liblib1.a liblib2.a', line) + return + raise RuntimeError('Could not find the build rule') + + def test_deterministic_rpath_order(self): + ''' + Test that the rpaths are always listed in a deterministic order. + ''' + if is_cygwin(): + raise SkipTest('rpath are not used on Cygwin') + testdir = os.path.join(self.unit_test_dir, '41 rpath order') + self.init(testdir) + if is_osx(): + rpathre = re.compile(r'-rpath,.*/subprojects/sub1.*-rpath,.*/subprojects/sub2') + else: + rpathre = re.compile(r'-rpath,\$\$ORIGIN/subprojects/sub1:\$\$ORIGIN/subprojects/sub2') + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if '-rpath' in line: + self.assertRegex(line, rpathre) + return + raise RuntimeError('Could not find the rpath') + + def test_override_with_exe_dep(self): + ''' + Test that we produce the correct dependencies when a program is overridden with an executable. + ''' + testdir = os.path.join(self.src_root, 'test cases', 'native', '9 override with exe') + self.init(testdir) + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if 'main1.c:' in line or 'main2.c:' in line: + self.assertIn('| subprojects/sub/foobar', line) + + @skipIfNoPkgconfig + def test_usage_external_library(self): + ''' + Test that uninstalled usage of an external library (from the system or + PkgConfigDependency) works. On macOS, this workflow works out of the + box. On Linux, BSDs, Windows, etc, you need to set extra arguments such + as LD_LIBRARY_PATH, etc, so this test is skipped. + + The system library is found with cc.find_library() and pkg-config deps. + ''' + oldprefix = self.prefix + # Install external library so we can find it + testdir = os.path.join(self.unit_test_dir, '39 external, internal library rpath', 'external library') + # install into installdir without using DESTDIR + installdir = self.installdir + self.prefix = installdir + self.init(testdir) + self.prefix = oldprefix + self.build() + self.install(use_destdir=False) + ## New builddir for the consumer + self.new_builddir() + env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir), + 'PKG_CONFIG_PATH': _prepend_pkg_config_path(os.path.join(installdir, self.libdir, 'pkgconfig'))} + testdir = os.path.join(self.unit_test_dir, '39 external, internal library rpath', 'built library') + # install into installdir without using DESTDIR + self.prefix = self.installdir + self.init(testdir, override_envvars=env) + self.prefix = oldprefix + self.build(override_envvars=env) + # test uninstalled + self.run_tests(override_envvars=env) + if not (is_osx() or is_linux()): + return + # test running after installation + self.install(use_destdir=False) + prog = os.path.join(self.installdir, 'bin', 'prog') + self._run([prog]) + if not is_osx(): + # Rest of the workflow only works on macOS + return + out = self._run(['otool', '-L', prog]) + self.assertNotIn('@rpath', out) + ## New builddir for testing that DESTDIR is not added to install_name + self.new_builddir() + # install into installdir with DESTDIR + self.init(testdir, override_envvars=env) + self.build(override_envvars=env) + # test running after installation + self.install(override_envvars=env) + prog = self.installdir + os.path.join(self.prefix, 'bin', 'prog') + lib = self.installdir + os.path.join(self.prefix, 'lib', 'libbar_built.dylib') + for f in prog, lib: + out = self._run(['otool', '-L', f]) + # Ensure that the otool output does not contain self.installdir + self.assertNotRegex(out, self.installdir + '.*dylib ') + + @skipIfNoPkgconfig + def test_link_arg_fullname(self): + ''' + Test for support of -l:libfullname.a + see: https://github.com/mesonbuild/meson/issues/9000 + https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a + ''' + testdir = os.path.join(self.unit_test_dir, '98 link full name','libtestprovider') + oldprefix = self.prefix + # install into installdir without using DESTDIR + installdir = self.installdir + self.prefix = installdir + self.init(testdir) + self.prefix=oldprefix + self.build() + self.install(use_destdir=False) + + self.new_builddir() + env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir), + 'PKG_CONFIG_PATH': _prepend_pkg_config_path(os.path.join(installdir, self.libdir, 'pkgconfig'))} + testdir = os.path.join(self.unit_test_dir, '98 link full name','proguser') + self.init(testdir,override_envvars=env) + + # test for link with full path + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile: + for line in bfile: + if 'build dprovidertest:' in line: + self.assertIn('/libtestprovider.a', line) + + if is_osx(): + # macOS's ld do not supports `--whole-archive`, skip build & run + return + + self.build(override_envvars=env) + + # skip test if pkg-config is too old. + # before v0.28, Libs flags like -Wl will not kept in context order with -l flags. + # see https://gitlab.freedesktop.org/pkg-config/pkg-config/-/blob/master/NEWS + pkgconfigver = subprocess.check_output([PKG_CONFIG, '--version']) + if b'0.28' > pkgconfigver: + raise SkipTest('pkg-config is too old to be correctly done this.') + self.run_tests() + + @skipIfNoPkgconfig + def test_usage_pkgconfig_prefixes(self): + ''' + Build and install two external libraries, to different prefixes, + then build and install a client program that finds them via pkgconfig, + and verify the installed client program runs. + ''' + oldinstalldir = self.installdir + + # Build and install both external libraries without DESTDIR + val1dir = os.path.join(self.unit_test_dir, '74 pkgconfig prefixes', 'val1') + val1prefix = os.path.join(oldinstalldir, 'val1') + self.prefix = val1prefix + self.installdir = val1prefix + self.init(val1dir) + self.build() + self.install(use_destdir=False) + self.new_builddir() + + env1 = {} + env1['PKG_CONFIG_PATH'] = os.path.join(val1prefix, self.libdir, 'pkgconfig') + val2dir = os.path.join(self.unit_test_dir, '74 pkgconfig prefixes', 'val2') + val2prefix = os.path.join(oldinstalldir, 'val2') + self.prefix = val2prefix + self.installdir = val2prefix + self.init(val2dir, override_envvars=env1) + self.build() + self.install(use_destdir=False) + self.new_builddir() + + # Build, install, and run the client program + env2 = {} + env2['PKG_CONFIG_PATH'] = os.path.join(val2prefix, self.libdir, 'pkgconfig') + testdir = os.path.join(self.unit_test_dir, '74 pkgconfig prefixes', 'client') + testprefix = os.path.join(oldinstalldir, 'client') + self.prefix = testprefix + self.installdir = testprefix + self.init(testdir, override_envvars=env2) + self.build() + self.install(use_destdir=False) + prog = os.path.join(self.installdir, 'bin', 'client') + env3 = {} + if is_cygwin(): + env3['PATH'] = os.path.join(val1prefix, 'bin') + \ + os.pathsep + \ + os.path.join(val2prefix, 'bin') + \ + os.pathsep + os.environ['PATH'] + out = self._run([prog], override_envvars=env3).strip() + # Expected output is val1 + val2 = 3 + self.assertEqual(out, '3') + + def install_subdir_invalid_symlinks(self, testdir, subdir_path): + ''' + Test that installation of broken symlinks works fine. + https://github.com/mesonbuild/meson/issues/3914 + ''' + testdir = os.path.join(self.common_test_dir, testdir) + subdir = os.path.join(testdir, subdir_path) + with chdir(subdir): + # Can't distribute broken symlinks in the source tree because it breaks + # the creation of zipapps. Create it dynamically and run the test by + # hand. + src = '../../nonexistent.txt' + os.symlink(src, 'invalid-symlink.txt') + try: + self.init(testdir) + self.build() + self.install() + install_path = subdir_path.split(os.path.sep)[-1] + link = os.path.join(self.installdir, 'usr', 'share', install_path, 'invalid-symlink.txt') + self.assertTrue(os.path.islink(link), msg=link) + self.assertEqual(src, os.readlink(link)) + self.assertFalse(os.path.isfile(link), msg=link) + finally: + os.remove(os.path.join(subdir, 'invalid-symlink.txt')) + + def test_install_subdir_symlinks(self): + self.install_subdir_invalid_symlinks('59 install subdir', os.path.join('sub', 'sub1')) + + def test_install_subdir_symlinks_with_default_umask(self): + self.install_subdir_invalid_symlinks('190 install_mode', 'sub2') + + def test_install_subdir_symlinks_with_default_umask_and_mode(self): + self.install_subdir_invalid_symlinks('190 install_mode', 'sub1') + + @skipIfNoPkgconfigDep('gmodule-2.0') + def test_ldflag_dedup(self): + testdir = os.path.join(self.unit_test_dir, '51 ldflagdedup') + if is_cygwin() or is_osx(): + raise SkipTest('Not applicable on Cygwin or OSX.') + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + linker = cc.linker + if not linker.export_dynamic_args(env): + raise SkipTest('Not applicable for linkers without --export-dynamic') + self.init(testdir) + build_ninja = os.path.join(self.builddir, 'build.ninja') + max_count = 0 + search_term = '-Wl,--export-dynamic' + with open(build_ninja, encoding='utf-8') as f: + for line in f: + max_count = max(max_count, line.count(search_term)) + self.assertEqual(max_count, 1, 'Export dynamic incorrectly deduplicated.') + + def test_compiler_libs_static_dedup(self): + testdir = os.path.join(self.unit_test_dir, '55 dedup compiler libs') + self.init(testdir) + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + lines = f.readlines() + for lib in ('-ldl', '-lm', '-lc', '-lrt'): + for line in lines: + if lib not in line: + continue + # Assert that + self.assertEqual(len(line.split(lib)), 2, msg=(lib, line)) + + @skipIfNoPkgconfig + def test_noncross_options(self): + # C_std defined in project options must be in effect also when native compiling. + testdir = os.path.join(self.unit_test_dir, '50 noncross options') + self.init(testdir, extra_args=['-Dpkg_config_path=' + testdir]) + compdb = self.get_compdb() + self.assertEqual(len(compdb), 2) + self.assertRegex(compdb[0]['command'], '-std=c99') + self.assertRegex(compdb[1]['command'], '-std=c99') + self.build() + + def test_identity_cross(self): + testdir = os.path.join(self.unit_test_dir, '60 identity cross') + + constantsfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') + constantsfile.write(textwrap.dedent('''\ + [constants] + py_ext = '.py' + ''')) + constantsfile.flush() + + nativefile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') + nativefile.write(textwrap.dedent('''\ + [binaries] + c = ['{}' + py_ext] + '''.format(os.path.join(testdir, 'build_wrapper')))) + nativefile.flush() + self.meson_native_files = [constantsfile.name, nativefile.name] + + crossfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') + crossfile.write(textwrap.dedent('''\ + [binaries] + c = ['{}' + py_ext] + '''.format(os.path.join(testdir, 'host_wrapper')))) + crossfile.flush() + self.meson_cross_files = [constantsfile.name, crossfile.name] + + # TODO should someday be explicit about build platform only here + self.init(testdir) + + def test_identity_cross_env(self): + testdir = os.path.join(self.unit_test_dir, '60 identity cross') + env = { + 'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"', + 'CC': '"' + os.path.join(testdir, 'host_wrapper.py') + '"', + } + crossfile = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') + crossfile.write('') + crossfile.flush() + self.meson_cross_files = [crossfile.name] + # TODO should someday be explicit about build platform only here + self.init(testdir, override_envvars=env) + + @skipIfNoPkgconfig + def test_static_link(self): + if is_cygwin(): + raise SkipTest("Cygwin doesn't support LD_LIBRARY_PATH.") + + # Build some libraries and install them + testdir = os.path.join(self.unit_test_dir, '66 static link/lib') + libdir = os.path.join(self.installdir, self.libdir) + oldprefix = self.prefix + self.prefix = self.installdir + self.init(testdir) + self.install(use_destdir=False) + + # Test that installed libraries works + self.new_builddir() + self.prefix = oldprefix + meson_args = [f'-Dc_link_args=-L{libdir}', + '--fatal-meson-warnings'] + testdir = os.path.join(self.unit_test_dir, '66 static link') + env = {'PKG_CONFIG_LIBDIR': os.path.join(libdir, 'pkgconfig')} + self.init(testdir, extra_args=meson_args, override_envvars=env) + self.build() + self.run_tests() + + def _check_ld(self, check: str, name: str, lang: str, expected: str) -> None: + if is_sunos(): + raise SkipTest('Solaris currently cannot override the linker.') + if not shutil.which(check): + raise SkipTest(f'Could not find {check}.') + envvars = [mesonbuild.envconfig.ENV_VAR_PROG_MAP[f'{lang}_ld']] + + # Also test a deprecated variable if there is one. + if f'{lang}_ld' in mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP: + envvars.append( + mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP[f'{lang}_ld']) + + for envvar in envvars: + with mock.patch.dict(os.environ, {envvar: name}): + env = get_fake_env() + comp = compiler_from_language(env, lang, MachineChoice.HOST) + if isinstance(comp, (AppleClangCCompiler, AppleClangCPPCompiler, + AppleClangObjCCompiler, AppleClangObjCPPCompiler)): + raise SkipTest('AppleClang is currently only supported with ld64') + if lang != 'rust' and comp.use_linker_args('bfd', '') == []: + raise SkipTest( + f'Compiler {comp.id} does not support using alternative linkers') + self.assertEqual(comp.linker.id, expected) + + def test_ld_environment_variable_bfd(self): + self._check_ld('ld.bfd', 'bfd', 'c', 'ld.bfd') + + def test_ld_environment_variable_gold(self): + self._check_ld('ld.gold', 'gold', 'c', 'ld.gold') + + def test_ld_environment_variable_lld(self): + self._check_ld('ld.lld', 'lld', 'c', 'ld.lld') + + @skip_if_not_language('rust') + @skipIfNoExecutable('ld.gold') # need an additional check here because _check_ld checks for gcc + def test_ld_environment_variable_rust(self): + self._check_ld('gcc', 'gcc -fuse-ld=gold', 'rust', 'ld.gold') + + def test_ld_environment_variable_cpp(self): + self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold') + + @skip_if_not_language('objc') + def test_ld_environment_variable_objc(self): + self._check_ld('ld.gold', 'gold', 'objc', 'ld.gold') + + @skip_if_not_language('objcpp') + def test_ld_environment_variable_objcpp(self): + self._check_ld('ld.gold', 'gold', 'objcpp', 'ld.gold') + + @skip_if_not_language('fortran') + def test_ld_environment_variable_fortran(self): + self._check_ld('ld.gold', 'gold', 'fortran', 'ld.gold') + + @skip_if_not_language('d') + def test_ld_environment_variable_d(self): + # At least for me, ldc defaults to gold, and gdc defaults to bfd, so + # let's pick lld, which isn't the default for either (currently) + if is_osx(): + expected = 'ld64' + else: + expected = 'ld.lld' + self._check_ld('ld.lld', 'lld', 'd', expected) + + def compute_sha256(self, filename): + with open(filename, 'rb') as f: + return hashlib.sha256(f.read()).hexdigest() + + def test_wrap_with_file_url(self): + testdir = os.path.join(self.unit_test_dir, '72 wrap file url') + source_filename = os.path.join(testdir, 'subprojects', 'foo.tar.xz') + patch_filename = os.path.join(testdir, 'subprojects', 'foo-patch.tar.xz') + wrap_filename = os.path.join(testdir, 'subprojects', 'foo.wrap') + source_hash = self.compute_sha256(source_filename) + patch_hash = self.compute_sha256(patch_filename) + wrap = textwrap.dedent("""\ + [wrap-file] + directory = foo + + source_url = http://server.invalid/foo + source_fallback_url = file://{} + source_filename = foo.tar.xz + source_hash = {} + + patch_url = http://server.invalid/foo + patch_fallback_url = file://{} + patch_filename = foo-patch.tar.xz + patch_hash = {} + """.format(source_filename, source_hash, patch_filename, patch_hash)) + with open(wrap_filename, 'w', encoding='utf-8') as f: + f.write(wrap) + self.init(testdir) + self.build() + self.run_tests() + + windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'packagecache')) + windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'foo')) + os.unlink(wrap_filename) + + def test_no_rpath_for_static(self): + testdir = os.path.join(self.common_test_dir, '5 linkstatic') + self.init(testdir) + self.build() + build_rpath = get_rpath(os.path.join(self.builddir, 'prog')) + self.assertIsNone(build_rpath) + + def test_lookup_system_after_broken_fallback(self): + # Just to generate libfoo.pc so we can test system dependency lookup. + testdir = os.path.join(self.common_test_dir, '44 pkgconfig-gen') + self.init(testdir) + privatedir = self.privatedir + + # Write test project where the first dependency() returns not-found + # because 'broken' subproject does not exit, but that should not prevent + # the 2nd dependency() to lookup on system. + self.new_builddir() + with tempfile.TemporaryDirectory() as d: + with open(os.path.join(d, 'meson.build'), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + project('test') + dependency('notfound', fallback: 'broken', required: false) + dependency('libfoo', fallback: 'broken', required: true) + ''')) + self.init(d, override_envvars={'PKG_CONFIG_LIBDIR': privatedir}) + + def test_as_link_whole(self): + testdir = os.path.join(self.unit_test_dir, '76 as link whole') + self.init(testdir) + with open(os.path.join(self.privatedir, 'bar1.pc'), encoding='utf-8') as f: + content = f.read() + self.assertIn('-lfoo', content) + with open(os.path.join(self.privatedir, 'bar2.pc'), encoding='utf-8') as f: + content = f.read() + self.assertNotIn('-lfoo', content) + + def test_prelinking(self): + # Prelinking currently only works on recently new GNU toolchains. + # Skip everything else. When support for other toolchains is added, + # remove limitations as necessary. + if is_osx(): + raise SkipTest('Prelinking not supported on Darwin.') + if 'clang' in os.environ.get('CC', 'dummy'): + raise SkipTest('Prelinking not supported with Clang.') + testdir = os.path.join(self.unit_test_dir, '86 prelinking') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.id == "gcc" and not version_compare(cc.version, '>=9'): + raise SkipTest('Prelinking not supported with gcc 8 or older.') + self.init(testdir) + self.build() + outlib = os.path.join(self.builddir, 'libprelinked.a') + ar = shutil.which('ar') + self.assertPathExists(outlib) + self.assertIsNotNone(ar) + p = subprocess.run([ar, 't', outlib], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + text=True, timeout=1) + obj_files = p.stdout.strip().split('\n') + self.assertEqual(len(obj_files), 1) + self.assertTrue(obj_files[0].endswith('-prelink.o')) + + def do_one_test_with_nativefile(self, testdir, args): + testdir = os.path.join(self.common_test_dir, testdir) + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'nativefile' + with p.open('wt', encoding='utf-8') as f: + f.write(f'''[binaries] + c = {args} + ''') + self.init(testdir, extra_args=['--native-file=' + str(p)]) + self.build() + + def test_cmake_multilib(self): + ''' + Test that the cmake module handles multilib paths correctly. + ''' + # Verify that "gcc -m32" works + try: + self.do_one_test_with_nativefile('1 trivial', "['gcc', '-m32']") + except subprocess.CalledProcessError as e: + raise SkipTest('Not GCC, or GCC does not have the -m32 option') + self.wipe() + + # Verify that cmake works + try: + self.do_one_test_with_nativefile('../cmake/1 basic', "['gcc']") + except subprocess.CalledProcessError as e: + raise SkipTest('Could not build basic cmake project') + self.wipe() + + # If so, we can test that cmake works with "gcc -m32" + self.do_one_test_with_nativefile('../cmake/1 basic', "['gcc', '-m32']") + + @skipUnless(is_linux() or is_osx(), 'Test only applicable to Linux and macOS') + def test_install_strip(self): + testdir = os.path.join(self.unit_test_dir, '104 strip') + self.init(testdir) + self.build() + + destdir = self.installdir + self.prefix + if is_linux(): + lib = os.path.join(destdir, self.libdir, 'liba.so') + else: + lib = os.path.join(destdir, self.libdir, 'liba.dylib') + install_cmd = self.meson_command + ['install', '--destdir', self.installdir] + + # Check we have debug symbols by default + self._run(install_cmd, workdir=self.builddir) + if is_linux(): + # file can detect stripped libraries on linux + stdout = self._run(['file', '-b', lib]) + self.assertIn('not stripped', stdout) + else: + # on macOS we need to query dsymutil instead. + # Alternatively, check if __dyld_private is defined + # in the output of nm liba.dylib, but that is not + # 100% reliable, it needs linking to an external library + stdout = self._run(['dsymutil', '--dump-debug-map', lib]) + self.assertIn('symbols:', stdout) + + # Check debug symbols got removed with --strip + self._run(install_cmd + ['--strip'], workdir=self.builddir) + if is_linux(): + stdout = self._run(['file', '-b', lib]) + self.assertNotIn('not stripped', stdout) + else: + stdout = self._run(['dsymutil', '--dump-debug-map', lib]) + self.assertNotIn('symbols:', stdout) + + def test_isystem_default_removal_with_symlink(self): + env = get_fake_env() + cpp = detect_cpp_compiler(env, MachineChoice.HOST) + default_dirs = cpp.get_default_include_dirs() + default_symlinks = [] + with tempfile.TemporaryDirectory() as tmpdir: + for i in range(len(default_dirs)): + symlink = f'{tmpdir}/default_dir{i}' + default_symlinks.append(symlink) + os.symlink(default_dirs[i], symlink) + self.assertFalse(cpp.compiler_args([f'-isystem{symlink}' for symlink in default_symlinks]).to_native()) + + def test_freezing(self): + testdir = os.path.join(self.unit_test_dir, '110 freeze') + self.init(testdir) + self.build() + with self.assertRaises(subprocess.CalledProcessError) as e: + self.run_tests() + self.assertNotIn('Traceback', e.exception.output) + + @skipUnless(is_linux(), "Ninja file differs on different platforms") + def test_complex_link_cases(self): + testdir = os.path.join(self.unit_test_dir, '113 complex link cases') + self.init(testdir) + self.build() + with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as f: + content = f.read() + # Verify link dependencies, see comments in meson.build. + self.assertIn('build libt1-s3.a: STATIC_LINKER libt1-s2.a.p/s2.c.o libt1-s3.a.p/s3.c.o\n', content) + self.assertIn('build t1-e1: c_LINKER t1-e1.p/main.c.o | libt1-s1.a libt1-s3.a\n', content) + self.assertIn('build libt2-s3.a: STATIC_LINKER libt2-s2.a.p/s2.c.o libt2-s1.a.p/s1.c.o libt2-s3.a.p/s3.c.o\n', content) + self.assertIn('build t2-e1: c_LINKER t2-e1.p/main.c.o | libt2-s3.a\n', content) + self.assertIn('build t3-e1: c_LINKER t3-e1.p/main.c.o | libt3-s3.so.p/libt3-s3.so.symbols\n', content) + self.assertIn('build t4-e1: c_LINKER t4-e1.p/main.c.o | libt4-s2.so.p/libt4-s2.so.symbols libt4-s3.a\n', content) + self.assertIn('build t5-e1: c_LINKER t5-e1.p/main.c.o | libt5-s1.so.p/libt5-s1.so.symbols libt5-s3.a\n', content) + self.assertIn('build t6-e1: c_LINKER t6-e1.p/main.c.o | libt6-s2.a libt6-s3.a\n', content) + self.assertIn('build t7-e1: c_LINKER t7-e1.p/main.c.o | libt7-s3.a\n', content) + self.assertIn('build t8-e1: c_LINKER t8-e1.p/main.c.o | libt8-s1.a libt8-s2.a libt8-s3.a\n', content) + self.assertIn('build t9-e1: c_LINKER t9-e1.p/main.c.o | libt9-s1.a libt9-s2.a libt9-s3.a\n', content) + self.assertIn('build t12-e1: c_LINKER t12-e1.p/main.c.o | libt12-s1.a libt12-s2.a libt12-s3.a\n', content) + self.assertIn('build t13-e1: c_LINKER t13-e1.p/main.c.o | libt12-s1.a libt13-s3.a\n', content) diff --git a/devtools/meson/unittests/machinefiletests.py b/devtools/meson/unittests/machinefiletests.py new file mode 100644 index 0000000..9e71810 --- /dev/null +++ b/devtools/meson/unittests/machinefiletests.py @@ -0,0 +1,978 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +import subprocess +import tempfile +import textwrap +import os +import shutil +import functools +import threading +import sys +from itertools import chain +from unittest import mock, skipIf, SkipTest +from pathlib import Path +import typing as T + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_osx, is_cygwin, is_haiku, is_sunos +) +from mesonbuild.compilers import ( + detect_swift_compiler, compiler_from_language +) +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + Backend, + get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@functools.lru_cache() +def is_real_gnu_compiler(path): + ''' + Check if the gcc we have is a real gcc and not a macOS wrapper around clang + ''' + if not path: + return False + out = subprocess.check_output([path, '--version'], universal_newlines=True, stderr=subprocess.STDOUT) + return 'Free Software Foundation' in out + +class NativeFileTests(BasePlatformTests): + + def setUp(self): + super().setUp() + self.testcase = os.path.join(self.unit_test_dir, '46 native file binary') + self.current_config = 0 + self.current_wrapper = 0 + + def helper_create_native_file(self, values: T.Dict[str, T.Dict[str, T.Union[str, int, float, bool, T.Sequence[T.Union[str, int, float, bool]]]]]) -> str: + """Create a config file as a temporary file. + + values should be a nested dictionary structure of {section: {key: + value}} + """ + filename = os.path.join(self.builddir, f'generated{self.current_config}.config') + self.current_config += 1 + with open(filename, 'wt', encoding='utf-8') as f: + for section, entries in values.items(): + f.write(f'[{section}]\n') + for k, v in entries.items(): + if isinstance(v, (bool, int, float)): + f.write(f"{k}={v}\n") + elif isinstance(v, str): + f.write(f"{k}='{v}'\n") + else: + f.write("{}=[{}]\n".format(k, ', '.join([f"'{w}'" for w in v]))) + return filename + + def helper_create_binary_wrapper(self, binary, dir_=None, extra_args=None, **kwargs): + """Creates a wrapper around a binary that overrides specific values.""" + filename = os.path.join(dir_ or self.builddir, f'binary_wrapper{self.current_wrapper}.py') + extra_args = extra_args or {} + self.current_wrapper += 1 + if is_haiku(): + chbang = '#!/bin/env python3' + else: + chbang = '#!/usr/bin/env python3' + + with open(filename, 'wt', encoding='utf-8') as f: + f.write(textwrap.dedent('''\ + {} + import argparse + import subprocess + import sys + + def main(): + parser = argparse.ArgumentParser() + '''.format(chbang))) + for name in chain(extra_args, kwargs): + f.write(' parser.add_argument("-{0}", "--{0}", action="store_true")\n'.format(name)) + f.write(' args, extra_args = parser.parse_known_args()\n') + for name, value in chain(extra_args.items(), kwargs.items()): + f.write(f' if args.{name}:\n') + f.write(' print("{}", file=sys.{})\n'.format(value, kwargs.get('outfile', 'stdout'))) + f.write(' sys.exit(0)\n') + f.write(textwrap.dedent(''' + ret = subprocess.run( + ["{}"] + extra_args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + print(ret.stdout.decode('utf-8')) + print(ret.stderr.decode('utf-8'), file=sys.stderr) + sys.exit(ret.returncode) + + if __name__ == '__main__': + main() + '''.format(binary))) + + if not is_windows(): + os.chmod(filename, 0o755) + return filename + + # On windows we need yet another level of indirection, as cmd cannot + # invoke python files itself, so instead we generate a .bat file, which + # invokes our python wrapper + batfile = os.path.join(self.builddir, f'binary_wrapper{self.current_wrapper}.bat') + with open(batfile, 'wt', encoding='utf-8') as f: + f.write(fr'@{sys.executable} {filename} %*') + return batfile + + def helper_for_compiler(self, lang, cb, for_machine = MachineChoice.HOST): + """Helper for generating tests for overriding compilers for languages + with more than one implementation, such as C, C++, ObjC, ObjC++, and D. + """ + env = get_fake_env() + getter = lambda: compiler_from_language(env, lang, for_machine) + cc = getter() + binary, newid = cb(cc) + env.binaries[for_machine].binaries[lang] = binary + compiler = getter() + self.assertEqual(compiler.id, newid) + + def test_multiple_native_files_override(self): + wrapper = self.helper_create_binary_wrapper('bash', version='foo') + config = self.helper_create_native_file({'binaries': {'bash': wrapper}}) + wrapper = self.helper_create_binary_wrapper('bash', version='12345') + config2 = self.helper_create_native_file({'binaries': {'bash': wrapper}}) + self.init(self.testcase, extra_args=[ + '--native-file', config, '--native-file', config2, + '-Dcase=find_program']) + + # This test hangs on cygwin. + @skipIf(os.name != 'posix' or is_cygwin(), 'Uses fifos, which are not available on non Unix OSes.') + def test_native_file_is_pipe(self): + fifo = os.path.join(self.builddir, 'native.file') + os.mkfifo(fifo) + with tempfile.TemporaryDirectory() as d: + wrapper = self.helper_create_binary_wrapper('bash', d, version='12345') + + def filler(): + with open(fifo, 'w', encoding='utf-8') as f: + f.write('[binaries]\n') + f.write(f"bash = '{wrapper}'\n") + + thread = threading.Thread(target=filler) + thread.start() + + self.init(self.testcase, extra_args=['--native-file', fifo, '-Dcase=find_program']) + + thread.join() + os.unlink(fifo) + + self.init(self.testcase, extra_args=['--wipe']) + + def test_multiple_native_files(self): + wrapper = self.helper_create_binary_wrapper('bash', version='12345') + config = self.helper_create_native_file({'binaries': {'bash': wrapper}}) + wrapper = self.helper_create_binary_wrapper('python') + config2 = self.helper_create_native_file({'binaries': {'python': wrapper}}) + self.init(self.testcase, extra_args=[ + '--native-file', config, '--native-file', config2, + '-Dcase=find_program']) + + def _simple_test(self, case, binary, entry=None): + wrapper = self.helper_create_binary_wrapper(binary, version='12345') + config = self.helper_create_native_file({'binaries': {entry or binary: wrapper}}) + self.init(self.testcase, extra_args=['--native-file', config, f'-Dcase={case}']) + + def test_find_program(self): + self._simple_test('find_program', 'bash') + + def test_config_tool_dep(self): + # Do the skip at this level to avoid screwing up the cache + if mesonbuild.environment.detect_msys2_arch(): + raise SkipTest('Skipped due to problems with LLVM on MSYS2') + if not shutil.which('llvm-config'): + raise SkipTest('No llvm-installed, cannot test') + self._simple_test('config_dep', 'llvm-config') + + def test_python3_module(self): + self._simple_test('python3', 'python3') + + def test_python_module(self): + if is_windows(): + # Bat adds extra crap to stdout, so the version check logic in the + # python module breaks. This is fine on other OSes because they + # don't need the extra indirection. + raise SkipTest('bat indirection breaks internal sanity checks.') + elif is_osx(): + binary = 'python' + else: + binary = 'python2' + + # We not have python2, check for it + for v in ['2', '2.7', '-2.7']: + rc = subprocess.call(['pkg-config', '--cflags', f'python{v}'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + if rc == 0: + break + else: + raise SkipTest('Not running Python 2 tests because dev packages not installed.') + self._simple_test('python', binary, entry='python') + + @skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') + @skip_if_env_set('CC') + def test_c_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang', 'clang' + if not is_real_gnu_compiler(shutil.which('gcc')): + raise SkipTest('Only one compiler found, cannot test.') + return 'gcc', 'gcc' + self.helper_for_compiler('c', cb) + + @skipIf(is_windows(), 'Setting up multiple compilers on windows is hard') + @skip_if_env_set('CXX') + def test_cpp_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang++'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang++', 'clang' + if not is_real_gnu_compiler(shutil.which('g++')): + raise SkipTest('Only one compiler found, cannot test.') + return 'g++', 'gcc' + self.helper_for_compiler('cpp', cb) + + @skip_if_not_language('objc') + @skip_if_env_set('OBJC') + def test_objc_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang', 'clang' + if not is_real_gnu_compiler(shutil.which('gcc')): + raise SkipTest('Only one compiler found, cannot test.') + return 'gcc', 'gcc' + self.helper_for_compiler('objc', cb) + + @skip_if_not_language('objcpp') + @skip_if_env_set('OBJCXX') + def test_objcpp_compiler(self): + def cb(comp): + if comp.id == 'gcc': + if not shutil.which('clang++'): + raise SkipTest('Only one compiler found, cannot test.') + return 'clang++', 'clang' + if not is_real_gnu_compiler(shutil.which('g++')): + raise SkipTest('Only one compiler found, cannot test.') + return 'g++', 'gcc' + self.helper_for_compiler('objcpp', cb) + + @skip_if_not_language('d') + @skip_if_env_set('DC') + def test_d_compiler(self): + def cb(comp): + if comp.id == 'dmd': + if shutil.which('ldc'): + return 'ldc', 'ldc' + elif shutil.which('gdc'): + return 'gdc', 'gdc' + else: + raise SkipTest('No alternative dlang compiler found.') + if shutil.which('dmd'): + return 'dmd', 'dmd' + raise SkipTest('No alternative dlang compiler found.') + self.helper_for_compiler('d', cb) + + @skip_if_not_language('cs') + @skip_if_env_set('CSC') + def test_cs_compiler(self): + def cb(comp): + if comp.id == 'csc': + if not shutil.which('mcs'): + raise SkipTest('No alternate C# implementation.') + return 'mcs', 'mcs' + if not shutil.which('csc'): + raise SkipTest('No alternate C# implementation.') + return 'csc', 'csc' + self.helper_for_compiler('cs', cb) + + @skip_if_not_language('fortran') + @skip_if_env_set('FC') + def test_fortran_compiler(self): + def cb(comp): + if comp.id == 'lcc': + if shutil.which('lfortran'): + return 'lfortran', 'lcc' + raise SkipTest('No alternate Fortran implementation.') + elif comp.id == 'gcc': + if shutil.which('ifort'): + # There is an ICC for windows (windows build, linux host), + # but we don't support that ATM so lets not worry about it. + if is_windows(): + return 'ifort', 'intel-cl' + return 'ifort', 'intel' + elif shutil.which('flang'): + return 'flang', 'flang' + elif shutil.which('pgfortran'): + return 'pgfortran', 'pgi' + # XXX: there are several other fortran compilers meson + # supports, but I don't have any of them to test with + raise SkipTest('No alternate Fortran implementation.') + if not shutil.which('gfortran'): + raise SkipTest('No alternate Fortran implementation.') + return 'gfortran', 'gcc' + self.helper_for_compiler('fortran', cb) + + def _single_implementation_compiler(self, lang: str, binary: str, version_str: str, version: str) -> None: + """Helper for languages with a single (supported) implementation. + + Builds a wrapper around the compiler to override the version. + """ + wrapper = self.helper_create_binary_wrapper(binary, version=version_str) + env = get_fake_env() + env.binaries.host.binaries[lang] = [wrapper] + compiler = compiler_from_language(env, lang, MachineChoice.HOST) + self.assertEqual(compiler.version, version) + + @skip_if_not_language('vala') + @skip_if_env_set('VALAC') + def test_vala_compiler(self): + self._single_implementation_compiler( + 'vala', 'valac', 'Vala 1.2345', '1.2345') + + @skip_if_not_language('rust') + @skip_if_env_set('RUSTC') + def test_rust_compiler(self): + self._single_implementation_compiler( + 'rust', 'rustc', 'rustc 1.2345', '1.2345') + + @skip_if_not_language('java') + def test_java_compiler(self): + self._single_implementation_compiler( + 'java', 'javac', 'javac 9.99.77', '9.99.77') + + @skip_if_not_language('java') + def test_java_classpath(self): + if self.backend is not Backend.ninja: + raise SkipTest('Jar is only supported with Ninja') + testdir = os.path.join(self.unit_test_dir, '111 classpath') + self.init(testdir) + self.build() + one_build_path = get_classpath(os.path.join(self.builddir, 'one.jar')) + self.assertIsNone(one_build_path) + two_build_path = get_classpath(os.path.join(self.builddir, 'two.jar')) + self.assertEqual(two_build_path, 'one.jar') + self.install() + one_install_path = get_classpath(os.path.join(self.installdir, 'usr/bin/one.jar')) + self.assertIsNone(one_install_path) + two_install_path = get_classpath(os.path.join(self.installdir, 'usr/bin/two.jar')) + self.assertIsNone(two_install_path) + + @skip_if_not_language('swift') + def test_swift_compiler(self): + wrapper = self.helper_create_binary_wrapper( + 'swiftc', version='Swift 1.2345', outfile='stderr', + extra_args={'Xlinker': 'macosx_version. PROJECT:ld - 1.2.3'}) + env = get_fake_env() + env.binaries.host.binaries['swift'] = [wrapper] + compiler = detect_swift_compiler(env, MachineChoice.HOST) + self.assertEqual(compiler.version, '1.2345') + + def test_native_file_dirs(self): + testcase = os.path.join(self.unit_test_dir, '59 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile')]) + + def test_native_file_dirs_overridden(self): + testcase = os.path.join(self.unit_test_dir, '59 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '-Ddef_libdir=liblib', '-Dlibdir=liblib']) + + def test_compile_sys_path(self): + """Compiling with a native file stored in a system path works. + + There was a bug which caused the paths to be stored incorrectly and + would result in ninja invoking meson in an infinite loop. This tests + for that by actually invoking ninja. + """ + testcase = os.path.join(self.common_test_dir, '1 trivial') + + # It really doesn't matter what's in the native file, just that it exists + config = self.helper_create_native_file({'binaries': {'bash': 'false'}}) + + self.init(testcase, extra_args=['--native-file', config]) + self.build() + + def test_user_options(self): + testcase = os.path.join(self.common_test_dir, '40 options') + for opt, value in [('testoption', 'some other val'), ('other_one', True), + ('combo_opt', 'one'), ('array_opt', ['two']), + ('integer_opt', 0), + ('CaseSenSiTivE', 'SOME other Value'), + ('CASESENSITIVE', 'some other Value')]: + config = self.helper_create_native_file({'project options': {opt: value}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_user_options_command_line_overrides(self): + testcase = os.path.join(self.common_test_dir, '40 options') + config = self.helper_create_native_file({'project options': {'other_one': True}}) + self.init(testcase, extra_args=['--native-file', config, '-Dother_one=false']) + + def test_user_options_subproject(self): + testcase = os.path.join(self.unit_test_dir, '78 user options for subproject') + + s = os.path.join(testcase, 'subprojects') + if not os.path.exists(s): + os.mkdir(s) + s = os.path.join(s, 'sub') + if not os.path.exists(s): + sub = os.path.join(self.common_test_dir, '40 options') + shutil.copytree(sub, s) + + for opt, value in [('testoption', 'some other val'), ('other_one', True), + ('combo_opt', 'one'), ('array_opt', ['two']), + ('integer_opt', 0)]: + config = self.helper_create_native_file({'sub:project options': {opt: value}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_option_bool(self): + # Bools are allowed to be unquoted + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({'built-in options': {'werror': True}}) + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'werror' in each['name']: + self.assertEqual(each['value'], True) + break + else: + self.fail('Did not find werror in build options?') + + def test_option_integer(self): + # Bools are allowed to be unquoted + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({'built-in options': {'unity_size': 100}}) + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'unity_size' in each['name']: + self.assertEqual(each['value'], 100) + break + else: + self.fail('Did not find unity_size in build options?') + + def test_builtin_options(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_native_file({'built-in options': {'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++14') + break + else: + self.fail('Did not find werror in build options?') + + def test_builtin_options_conf_overrides_env(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_native_file({'built-in options': {'pkg_config_path': '/foo'}}) + + self.init(testcase, extra_args=['--native-file', config], override_envvars={'PKG_CONFIG_PATH': '/bar'}) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/foo']) + break + else: + self.fail('Did not find pkg_config_path in build options?') + + def test_builtin_options_subprojects(self): + testcase = os.path.join(self.common_test_dir, '98 subproject subdir') + config = self.helper_create_native_file({'built-in options': {'default_library': 'both', 'c_args': ['-Dfoo']}, 'sub:built-in options': {'default_library': 'static'}}) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'c_args' in each['name']: + # This path will be hit twice, once for build and once for host, + self.assertEqual(each['value'], ['-Dfoo']) + found += 1 + elif each['name'] == 'default_library': + self.assertEqual(each['value'], 'both') + found += 1 + elif each['name'] == 'sub:default_library': + self.assertEqual(each['value'], 'static') + found += 1 + self.assertEqual(found, 4, 'Did not find all three sections') + + def test_builtin_options_subprojects_overrides_buildfiles(self): + # If the buildfile says subproject(... default_library: shared), ensure that's overwritten + testcase = os.path.join(self.common_test_dir, '223 persubproject options') + config = self.helper_create_native_file({'sub2:built-in options': {'default_library': 'shared'}}) + + with self.assertRaises((RuntimeError, subprocess.CalledProcessError)) as cm: + self.init(testcase, extra_args=['--native-file', config]) + if isinstance(cm, RuntimeError): + check = str(cm.exception) + else: + check = cm.exception.stdout + self.assertIn(check, 'Parent should override default_library') + + def test_builtin_options_subprojects_dont_inherits_parent_override(self): + # If the buildfile says subproject(... default_library: shared), ensure that's overwritten + testcase = os.path.join(self.common_test_dir, '223 persubproject options') + config = self.helper_create_native_file({'built-in options': {'default_library': 'both'}}) + self.init(testcase, extra_args=['--native-file', config]) + + def test_builtin_options_compiler_properties(self): + # the properties section can have lang_args, and those need to be + # overwritten by the built-in options + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'c_args': ['-DFOO']}, + 'properties': {'c_args': ['-DBAR']}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'c_args': + self.assertEqual(each['value'], ['-DFOO']) + break + else: + self.fail('Did not find c_args in build options?') + + def test_builtin_options_compiler_properties_legacy(self): + # The legacy placement in properties is still valid if a 'built-in + # options' setting is present, but doesn't have the lang_args + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'default_library': 'static'}, + 'properties': {'c_args': ['-DBAR']}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'c_args': + self.assertEqual(each['value'], ['-DBAR']) + break + else: + self.fail('Did not find c_args in build options?') + + def test_builtin_options_paths(self): + # the properties section can have lang_args, and those need to be + # overwritten by the built-in options + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'bindir': 'foo'}, + 'paths': {'bindir': 'bar'}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'bindir': + self.assertEqual(each['value'], 'foo') + break + else: + self.fail('Did not find bindir in build options?') + + def test_builtin_options_paths_legacy(self): + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'default_library': 'static'}, + 'paths': {'bindir': 'bar'}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'bindir': + self.assertEqual(each['value'], 'bar') + break + else: + self.fail('Did not find bindir in build options?') + + @skip_if_not_language('rust') + def test_bindgen_clang_arguments(self) -> None: + if self.backend is not Backend.ninja: + raise SkipTest('Rust is only supported with Ninja') + + testcase = os.path.join(self.rust_test_dir, '12 bindgen') + config = self.helper_create_native_file({ + 'properties': {'bindgen_clang_arguments': 'sentinal'} + }) + + self.init(testcase, extra_args=['--native-file', config]) + targets: T.List[T.Dict[str, T.Any]] = self.introspect('--targets') + for t in targets: + if t['id'].startswith('rustmod-bindgen'): + args: T.List[str] = t['target_sources'][0]['compiler'] + self.assertIn('sentinal', args, msg="Did not find machine file value") + cargs_start = args.index('--') + sent_arg = args.index('sentinal') + self.assertLess(cargs_start, sent_arg, msg='sentinal argument does not come after "--"') + break + else: + self.fail('Did not find a bindgen target') + + +class CrossFileTests(BasePlatformTests): + + """Tests for cross file functionality not directly related to + cross compiling. + + This is mainly aimed to testing overrides from cross files. + """ + + def setUp(self): + super().setUp() + self.current_config = 0 + self.current_wrapper = 0 + + def _cross_file_generator(self, *, needs_exe_wrapper: bool = False, + exe_wrapper: T.Optional[T.List[str]] = None) -> str: + if is_windows(): + raise SkipTest('Cannot run this test on non-mingw/non-cygwin windows') + + return textwrap.dedent(f"""\ + [binaries] + c = '{shutil.which('gcc' if is_sunos() else 'cc')}' + ar = '{shutil.which('ar')}' + strip = '{shutil.which('strip')}' + exe_wrapper = {str(exe_wrapper) if exe_wrapper is not None else '[]'} + + [properties] + needs_exe_wrapper = {needs_exe_wrapper} + + [host_machine] + system = 'linux' + cpu_family = 'x86' + cpu = 'i686' + endian = 'little' + """) + + def _stub_exe_wrapper(self) -> str: + return textwrap.dedent('''\ + #!/usr/bin/env python3 + import subprocess + import sys + + sys.exit(subprocess.run(sys.argv[1:]).returncode) + ''') + + def test_needs_exe_wrapper_true(self): + testdir = os.path.join(self.unit_test_dir, '70 cross test passed') + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator(needs_exe_wrapper=True)) + self.init(testdir, extra_args=['--cross-file=' + str(p)]) + out = self.run_target('test') + self.assertRegex(out, r'Skipped:\s*1\s*\n') + + def test_needs_exe_wrapper_false(self): + testdir = os.path.join(self.unit_test_dir, '70 cross test passed') + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator(needs_exe_wrapper=False)) + self.init(testdir, extra_args=['--cross-file=' + str(p)]) + out = self.run_target('test') + self.assertNotRegex(out, r'Skipped:\s*1\n') + + def test_needs_exe_wrapper_true_wrapper(self): + testdir = os.path.join(self.unit_test_dir, '70 cross test passed') + with tempfile.TemporaryDirectory() as d: + s = Path(d) / 'wrapper.py' + with s.open('wt', encoding='utf-8') as f: + f.write(self._stub_exe_wrapper()) + s.chmod(0o774) + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator( + needs_exe_wrapper=True, + exe_wrapper=[str(s)])) + + self.init(testdir, extra_args=['--cross-file=' + str(p), '-Dexpect=true']) + out = self.run_target('test') + self.assertRegex(out, r'Ok:\s*3\s*\n') + + def test_cross_exe_passed_no_wrapper(self): + testdir = os.path.join(self.unit_test_dir, '70 cross test passed') + with tempfile.TemporaryDirectory() as d: + p = Path(d) / 'crossfile' + with p.open('wt', encoding='utf-8') as f: + f.write(self._cross_file_generator(needs_exe_wrapper=True)) + + self.init(testdir, extra_args=['--cross-file=' + str(p)]) + self.build() + out = self.run_target('test') + self.assertRegex(out, r'Skipped:\s*1\s*\n') + + # The test uses mocking and thus requires that the current process is the + # one to run the Meson steps. If we are using an external test executable + # (most commonly in Debian autopkgtests) then the mocking won't work. + @skipIf('MESON_EXE' in os.environ, 'MESON_EXE is defined, cannot use mocking.') + def test_cross_file_system_paths(self): + if is_windows(): + raise SkipTest('system crossfile paths not defined for Windows (yet)') + + testdir = os.path.join(self.common_test_dir, '1 trivial') + cross_content = self._cross_file_generator() + with tempfile.TemporaryDirectory() as d: + dir_ = os.path.join(d, 'meson', 'cross') + os.makedirs(dir_) + with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False, encoding='utf-8') as f: + f.write(cross_content) + name = os.path.basename(f.name) + + with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}): + self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) + self.wipe() + + with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}): + os.environ.pop('XDG_DATA_HOME', None) + self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) + self.wipe() + + with tempfile.TemporaryDirectory() as d: + dir_ = os.path.join(d, '.local', 'share', 'meson', 'cross') + os.makedirs(dir_) + with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False, encoding='utf-8') as f: + f.write(cross_content) + name = os.path.basename(f.name) + + # If XDG_DATA_HOME is set in the environment running the + # tests this test will fail, os mock the environment, pop + # it, then test + with mock.patch.dict(os.environ): + os.environ.pop('XDG_DATA_HOME', None) + with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)): + self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) + self.wipe() + + def helper_create_cross_file(self, values): + """Create a config file as a temporary file. + + values should be a nested dictionary structure of {section: {key: + value}} + """ + filename = os.path.join(self.builddir, f'generated{self.current_config}.config') + self.current_config += 1 + with open(filename, 'wt', encoding='utf-8') as f: + for section, entries in values.items(): + f.write(f'[{section}]\n') + for k, v in entries.items(): + f.write(f"{k}={v!r}\n") + return filename + + def test_cross_file_dirs(self): + testcase = os.path.join(self.unit_test_dir, '59 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '-Ddef_bindir=binbar', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libdir=libbar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) + + def test_cross_file_dirs_overridden(self): + testcase = os.path.join(self.unit_test_dir, '59 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '-Ddef_libdir=liblib', '-Dlibdir=liblib', + '-Ddef_bindir=binbar', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) + + def test_cross_file_dirs_chain(self): + # crossfile2 overrides crossfile overrides nativefile + testcase = os.path.join(self.unit_test_dir, '59 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '--cross-file', os.path.join(testcase, 'crossfile2'), + '-Ddef_bindir=binbar2', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libdir=libbar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) + + def test_user_options(self): + # This is just a touch test for cross file, since the implementation + # shares code after loading from the files + testcase = os.path.join(self.common_test_dir, '40 options') + config = self.helper_create_cross_file({'project options': {'testoption': 'some other value'}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--cross-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_builtin_options(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--cross-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++14') + break + else: + self.fail('No c++ standard set?') + + def test_builtin_options_per_machine(self): + """Test options that are allowed to be set on a per-machine basis. + + Such options could be passed twice, once for the build machine, and + once for the host machine. I've picked pkg-config path, but any would + do that can be set for both. + """ + testcase = os.path.join(self.common_test_dir, '2 cpp') + cross = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/cross/path', 'cpp_std': 'c++17'}}) + native = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/native/path', 'cpp_std': 'c++14'}}) + + # Ensure that PKG_CONFIG_PATH is not set in the environment + with mock.patch.dict('os.environ'): + for k in ['PKG_CONFIG_PATH', 'PKG_CONFIG_PATH_FOR_BUILD']: + try: + del os.environ[k] + except KeyError: + pass + self.init(testcase, extra_args=['--cross-file', cross, '--native-file', native]) + + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/cross/path']) + found += 1 + elif each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++17') + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/native/path']) + found += 1 + elif each['name'] == 'build.cpp_std': + self.assertEqual(each['value'], 'c++14') + found += 1 + + if found == 4: + break + self.assertEqual(found, 4, 'Did not find all sections.') + + def test_builtin_options_conf_overrides_env(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/native', 'cpp_args': '-DFILE'}}) + cross = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/cross', 'cpp_args': '-DFILE'}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross], + override_envvars={'PKG_CONFIG_PATH': '/bar', 'PKG_CONFIG_PATH_FOR_BUILD': '/dir', + 'CXXFLAGS': '-DENV', 'CXXFLAGS_FOR_BUILD': '-DENV'}) + configuration = self.introspect('--buildoptions') + found = 0 + expected = 4 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/cross']) + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/native']) + found += 1 + elif each['name'].endswith('cpp_args'): + self.assertEqual(each['value'], ['-DFILE']) + found += 1 + if found == expected: + break + self.assertEqual(found, expected, 'Did not find all sections.') + + def test_for_build_env_vars(self) -> None: + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {}}) + cross = self.helper_create_cross_file({'built-in options': {}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross], + override_envvars={'PKG_CONFIG_PATH': '/bar', 'PKG_CONFIG_PATH_FOR_BUILD': '/dir'}) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/bar']) + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/dir']) + found += 1 + if found == 2: + break + self.assertEqual(found, 2, 'Did not find all sections.') + + def test_project_options_native_only(self) -> None: + # Do not load project options from a native file when doing a cross + # build + testcase = os.path.join(self.unit_test_dir, '19 array option') + config = self.helper_create_cross_file({'project options': {'list': ['bar', 'foo']}}) + cross = self.helper_create_cross_file({'binaries': {}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'list': + self.assertEqual(each['value'], ['foo', 'bar']) + break + else: + self.fail('Did not find expected option.') diff --git a/devtools/meson/unittests/platformagnostictests.py b/devtools/meson/unittests/platformagnostictests.py new file mode 100644 index 0000000..cd2d319 --- /dev/null +++ b/devtools/meson/unittests/platformagnostictests.py @@ -0,0 +1,263 @@ +# Copyright 2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import pickle +import tempfile +import subprocess +import textwrap +from unittest import skipIf, SkipTest +from pathlib import Path + +from .baseplatformtests import BasePlatformTests +from .helpers import is_ci +from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, is_linux, python_command +from mesonbuild.optinterpreter import OptionInterpreter, OptionException +from run_tests import Backend + +@skipIf(is_ci() and not is_linux(), "Run only on fast platforms") +class PlatformAgnosticTests(BasePlatformTests): + ''' + Tests that does not need to run on all platforms during CI + ''' + + def test_relative_find_program(self): + ''' + Tests that find_program() with a relative path does not find the program + in current workdir. + ''' + testdir = os.path.join(self.unit_test_dir, '101 relative find program') + self.init(testdir, workdir=testdir) + + def test_invalid_option_names(self): + interp = OptionInterpreter('') + + def write_file(code: str): + with tempfile.NamedTemporaryFile('w', dir=self.builddir, encoding='utf-8', delete=False) as f: + f.write(code) + return f.name + + fname = write_file("option('default_library', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name default_library is reserved.', + interp.process, fname) + + fname = write_file("option('c_anything', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name c_anything is reserved.', + interp.process, fname) + + fname = write_file("option('b_anything', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name b_anything is reserved.', + interp.process, fname) + + fname = write_file("option('backend_anything', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option name backend_anything is reserved.', + interp.process, fname) + + fname = write_file("option('foo.bar', type: 'string')") + self.assertRaisesRegex(OptionException, 'Option names can only contain letters, numbers or dashes.', + interp.process, fname) + + # platlib is allowed, only python.platlib is reserved. + fname = write_file("option('platlib', type: 'string')") + interp.process(fname) + + def test_python_dependency_without_pkgconfig(self): + testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig') + self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'}) + + def test_debug_function_outputs_to_meson_log(self): + testdir = os.path.join(self.unit_test_dir, '105 debug function') + log_msg = 'This is an example debug output, should only end up in debug log' + output = self.init(testdir) + + # Check if message is not printed to stdout while configuring + self.assertNotIn(log_msg, output) + + # Check if message is written to the meson log + mesonlog = self.get_meson_log_raw() + self.assertIn(log_msg, mesonlog) + + def test_new_subproject_reconfigure(self): + testdir = os.path.join(self.unit_test_dir, '108 new subproject on reconfigure') + self.init(testdir) + self.build() + + # Enable the subproject "foo" and reconfigure, this is used to fail + # because per-subproject builtin options were not initialized: + # https://github.com/mesonbuild/meson/issues/10225. + self.setconf('-Dfoo=enabled') + self.build('reconfigure') + + def check_connectivity(self): + import urllib + try: + with urllib.request.urlopen('https://wrapdb.mesonbuild.com') as p: + pass + except urllib.error.URLError as e: + self.skipTest('No internet connectivity: ' + str(e)) + + def test_update_wrapdb(self): + self.check_connectivity() + # Write the project into a temporary directory because it will add files + # into subprojects/ and we don't want to pollute meson source tree. + with tempfile.TemporaryDirectory() as testdir: + with Path(testdir, 'meson.build').open('w', encoding='utf-8') as f: + f.write(textwrap.dedent( + ''' + project('wrap update-db', + default_options: ['wrap_mode=forcefallback']) + + zlib_dep = dependency('zlib') + assert(zlib_dep.type_name() == 'internal') + ''')) + subprocess.check_call(self.wrap_command + ['update-db'], cwd=testdir) + self.init(testdir, workdir=testdir) + + def test_none_backend(self): + testdir = os.path.join(self.python_test_dir, '7 install path') + + self.init(testdir, extra_args=['--backend=none'], override_envvars={'NINJA': 'absolutely false command'}) + self.assertPathDoesNotExist(os.path.join(self.builddir, 'build.ninja')) + + self.run_tests(inprocess=True, override_envvars={}) + + out = self._run(self.meson_command + ['install', f'--destdir={self.installdir}'], workdir=self.builddir) + self.assertNotIn('Only ninja backend is supported to rebuild the project before installation.', out) + + with open(os.path.join(testdir, 'test.json'), 'rb') as f: + dat = json.load(f) + for i in dat['installed']: + self.assertPathExists(os.path.join(self.installdir, i['file'])) + + def test_change_backend(self): + if self.backend != Backend.ninja: + raise SkipTest('Only useful to test if backend is ninja.') + + testdir = os.path.join(self.python_test_dir, '7 install path') + self.init(testdir) + + # no-op change works + self.setconf(f'--backend=ninja') + self.init(testdir, extra_args=['--reconfigure', '--backend=ninja']) + + # Change backend option is not allowed + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.setconf('-Dbackend=none') + self.assertIn("ERROR: Tried modify read only option 'backend'", cm.exception.stdout) + + # Reconfigure with a different backend is not allowed + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--reconfigure', '--backend=none']) + self.assertIn("ERROR: Tried modify read only option 'backend'", cm.exception.stdout) + + # Wipe with a different backend is allowed + self.init(testdir, extra_args=['--wipe', '--backend=none']) + + def test_validate_dirs(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + + # Using parent as builddir should fail + self.builddir = os.path.dirname(self.builddir) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir) + self.assertIn('cannot be a parent of source directory', cm.exception.stdout) + + # Reconfigure of empty builddir should work + self.new_builddir() + self.init(testdir, extra_args=['--reconfigure']) + + # Reconfigure of not empty builddir should work + self.new_builddir() + Path(self.builddir, 'dummy').touch() + self.init(testdir, extra_args=['--reconfigure']) + + # Wipe of empty builddir should work + self.new_builddir() + self.init(testdir, extra_args=['--wipe']) + + # Wipe of partial builddir should work + self.new_builddir() + Path(self.builddir, 'meson-private').mkdir() + Path(self.builddir, 'dummy').touch() + self.init(testdir, extra_args=['--wipe']) + + # Wipe of not empty builddir should fail + self.new_builddir() + Path(self.builddir, 'dummy').touch() + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--wipe']) + self.assertIn('Directory is not empty', cm.exception.stdout) + + def test_scripts_loaded_modules(self): + ''' + Simulate a wrapped command, as done for custom_target() that capture + output. The script will print all python modules loaded and we verify + that it contains only an acceptable subset. Loading too many modules + slows down the build when many custom targets get wrapped. + + This list must not be edited without a clear rationale for why it is + acceptable to do so! + ''' + es = ExecutableSerialisation(python_command + ['-c', 'exit(0)'], env=EnvironmentVariables()) + p = Path(self.builddir, 'exe.dat') + with p.open('wb') as f: + pickle.dump(es, f) + cmd = self.meson_command + ['--internal', 'test_loaded_modules', '--unpickle', str(p)] + p = subprocess.run(cmd, stdout=subprocess.PIPE) + all_modules = json.loads(p.stdout.splitlines()[0]) + meson_modules = [m for m in all_modules if m.startswith('mesonbuild')] + expected_meson_modules = [ + 'mesonbuild', + 'mesonbuild._pathlib', + 'mesonbuild.utils', + 'mesonbuild.utils.core', + 'mesonbuild.mesonmain', + 'mesonbuild.mlog', + 'mesonbuild.scripts', + 'mesonbuild.scripts.meson_exe', + 'mesonbuild.scripts.test_loaded_modules' + ] + self.assertEqual(sorted(expected_meson_modules), sorted(meson_modules)) + + def test_setup_loaded_modules(self): + ''' + Execute a very basic meson.build and capture a list of all python + modules loaded. We verify that it contains only an acceptable subset. + Loading too many modules slows down `meson setup` startup time and + gives a perception that meson is slow. + + Adding more modules to the default startup flow is not an unreasonable + thing to do as new features are added, but keeping track of them is + good. + ''' + testdir = os.path.join(self.unit_test_dir, '114 empty project') + + self.init(testdir) + self._run(self.meson_command + ['--internal', 'regenerate', '--profile-self', testdir, self.builddir]) + with open(os.path.join(self.builddir, 'meson-logs', 'profile-startup-modules.json'), encoding='utf-8') as f: + data = json.load(f)['meson'] + + with open(os.path.join(testdir, 'expected_mods.json'), encoding='utf-8') as f: + expected = json.load(f)['meson']['modules'] + + self.assertEqual(data['modules'], expected) + self.assertEqual(data['count'], 68) + + def test_cmake_openssl_not_found_bug(self): + """Issue #12098""" + testdir = os.path.join(self.unit_test_dir, '117 openssl cmake bug') + self.meson_native_files.append(os.path.join(testdir, 'nativefile.ini')) + out = self.init(testdir, allow_fail=True) + self.assertNotIn('Unhandled python exception', out) diff --git a/devtools/meson/unittests/pythontests.py b/devtools/meson/unittests/pythontests.py new file mode 100644 index 0000000..afcfec3 --- /dev/null +++ b/devtools/meson/unittests/pythontests.py @@ -0,0 +1,99 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import glob, os, pathlib, shutil, subprocess, unittest + +from run_tests import ( + Backend +) + +from .allplatformstests import git_init +from .baseplatformtests import BasePlatformTests +from .helpers import * + +from mesonbuild.mesonlib import MachineChoice, TemporaryDirectoryWinProof +from mesonbuild.modules.python import PythonModule + +class PythonTests(BasePlatformTests): + ''' + Tests that verify compilation of python extension modules + ''' + + def test_bad_versions(self): + if self.backend is not Backend.ninja: + raise unittest.SkipTest(f'Skipping python tests with {self.backend.name} backend') + + testdir = os.path.join(self.src_root, 'test cases', 'python', '8 different python versions') + + # The test is configured to error out with MESON_SKIP_TEST + # in case it could not find python + with self.assertRaises(unittest.SkipTest): + self.init(testdir, extra_args=['-Dpython=not-python']) + self.wipe() + + # While dir is an external command on both Windows and Linux, + # it certainly isn't python + with self.assertRaises(unittest.SkipTest): + self.init(testdir, extra_args=['-Dpython=dir']) + self.wipe() + + def test_dist(self): + with TemporaryDirectoryWinProof() as dirstr: + dirobj = pathlib.Path(dirstr) + mesonfile = dirobj / 'meson.build' + mesonfile.write_text('''project('test', 'c', version: '1') +pymod = import('python') +python = pymod.find_installation('python3', required: true) +''', encoding='utf-8') + git_init(dirstr) + self.init(dirstr) + subprocess.check_call(self.meson_command + ['dist', '-C', self.builddir], stdout=subprocess.DEVNULL) + + def _test_bytecompile(self, py2=False): + testdir = os.path.join(self.src_root, 'test cases', 'python', '2 extmodule') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + + self.init(testdir, extra_args=['-Dpython2=auto', '-Dpython.bytecompile=1']) + self.build() + self.install() + + count = 0 + for root, dirs, files in os.walk(self.installdir): + for file in files: + realfile = os.path.join(root, file) + if file.endswith('.py'): + cached = glob.glob(realfile+'?') + glob.glob(os.path.join(root, '__pycache__', os.path.splitext(file)[0] + '*.pyc')) + if py2 and cc.get_id() == 'msvc': + # MSVC python installs python2/python3 into the same directory + self.assertLength(cached, 4) + else: + self.assertLength(cached, 2) + count += 1 + # there are 5 files x 2 installations + if py2 and not cc.get_id() == 'msvc': + self.assertEqual(count, 10) + else: + self.assertEqual(count, 5) + + def test_bytecompile_multi(self): + if not shutil.which('python2') and not PythonModule._get_win_pythonpath('python2'): + raise self.skipTest('python2 not installed') + self._test_bytecompile(True) + + def test_bytecompile_single(self): + if shutil.which('python2') or PythonModule._get_win_pythonpath('python2'): + raise self.skipTest('python2 installed, already tested') + self._test_bytecompile() diff --git a/devtools/meson/unittests/rewritetests.py b/devtools/meson/unittests/rewritetests.py new file mode 100644 index 0000000..ca30fe9 --- /dev/null +++ b/devtools/meson/unittests/rewritetests.py @@ -0,0 +1,398 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import json +import os +import shutil +import unittest + +from mesonbuild.mesonlib import windows_proof_rmtree +from .baseplatformtests import BasePlatformTests + +class RewriterTests(BasePlatformTests): + def setUp(self): + super().setUp() + self.maxDiff = None + + def prime(self, dirname): + if os.path.exists(self.builddir): + windows_proof_rmtree(self.builddir) + shutil.copytree(os.path.join(self.rewrite_test_dir, dirname), self.builddir) + + def rewrite_raw(self, directory, args): + if isinstance(args, str): + args = [args] + command = self.rewrite_command + ['--verbose', '--skip', '--sourcedir', directory] + args + p = subprocess.run(command, capture_output=True, text=True, timeout=60) + print('STDOUT:') + print(p.stdout) + print('STDERR:') + print(p.stderr) + if p.returncode != 0: + if 'MESON_SKIP_TEST' in p.stdout: + raise unittest.SkipTest('Project requested skipping.') + raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) + if not p.stderr: + return {} + return json.loads(p.stderr) + + def rewrite(self, directory, args): + if isinstance(args, str): + args = [args] + return self.rewrite_raw(directory, ['command'] + args) + + def test_target_source_list(self): + self.prime('1 basic') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + def test_target_add_sources(self): + self.prime('1 basic') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['a5.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['a5.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['a3.cpp', 'main.cpp', 'a7.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp', 'a4.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_add_sources_abs(self): + self.prime('1 basic') + abs_src = [os.path.join(self.builddir, x) for x in ['a1.cpp', 'a2.cpp', 'a6.cpp']] + add = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "src_add", "sources": abs_src}]) + inf = json.dumps([{"type": "target", "target": "trivialprog1", "operation": "info"}]) + self.rewrite(self.builddir, add) + out = self.rewrite(self.builddir, inf) + expected = {'target': {'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['a1.cpp', 'a2.cpp', 'a6.cpp', 'fileA.cpp', 'main.cpp'], 'extra_files': []}}} + self.assertDictEqual(out, expected) + + def test_target_remove_sources(self): + self.prime('1 basic') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmSrc.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileC.cpp', 'main.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_subdir(self): + self.prime('2 subdirs') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) + expected = {'name': 'something', 'sources': ['first.c', 'second.c', 'third.c'], 'extra_files': []} + self.assertDictEqual(list(out['target'].values())[0], expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(list(out['target'].values())[0], expected) + + def test_target_remove(self): + self.prime('1 basic') + self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + + expected = { + 'target': { + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + def test_target_add(self): + self.prime('1 basic') + self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp', 'fileA.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp', 'fileB.cpp', 'fileC.cpp'], 'extra_files': []}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['fileB.cpp', 'fileC.cpp', 'main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp', 'fileA.cpp'], 'extra_files': []}, + 'trivialprog10@sha': {'name': 'trivialprog10', 'sources': ['new1.cpp', 'new2.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + def test_target_remove_subdir(self): + self.prime('2 subdirs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'rmTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, {}) + + def test_target_add_subdir(self): + self.prime('2 subdirs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'addTgt.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = {'name': 'something', 'sources': ['first.c', 'second.c'], 'extra_files': []} + self.assertDictEqual(out['target']['94b671c@@something@exe'], expected) + + def test_target_source_sorting(self): + self.prime('5 sorting') + add_json = json.dumps([{'type': 'target', 'target': 'exe1', 'operation': 'src_add', 'sources': ['a666.c']}]) + inf_json = json.dumps([{'type': 'target', 'target': 'exe1', 'operation': 'info'}]) + out = self.rewrite(self.builddir, add_json) + out = self.rewrite(self.builddir, inf_json) + expected = { + 'target': { + 'exe1@exe': { + 'name': 'exe1', + 'sources': [ + 'aaa/a/a1.c', + 'aaa/b/b1.c', + 'aaa/b/b2.c', + 'aaa/f1.c', + 'aaa/f2.c', + 'aaa/f3.c', + 'bbb/a/b1.c', + 'bbb/b/b2.c', + 'bbb/c1/b5.c', + 'bbb/c2/b7.c', + 'bbb/c10/b6.c', + 'bbb/a4.c', + 'bbb/b3.c', + 'bbb/b4.c', + 'bbb/b5.c', + 'a1.c', + 'a2.c', + 'a3.c', + 'a10.c', + 'a20.c', + 'a30.c', + 'a100.c', + 'a101.c', + 'a110.c', + 'a210.c', + 'a666.c', + 'b1.c', + 'c2.c' + ], + 'extra_files': [] + } + } + } + self.assertDictEqual(out, expected) + + def test_target_same_name_skip(self): + self.prime('4 same name targets') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addSrc.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = {'name': 'myExe', 'sources': ['main.cpp'], 'extra_files': []} + self.assertEqual(len(out['target']), 2) + for val in out['target'].values(): + self.assertDictEqual(expected, val) + + def test_kwargs_info(self): + self.prime('3 kwargs') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1'}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_set(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'set.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.2', 'meson_version': '0.50.0', 'license': ['GPL', 'MIT']}, + 'target#tgt1': {'build_by_default': False, 'build_rpath': '/usr/local', 'dependencies': 'dep1'}, + 'dependency#dep1': {'required': True, 'method': 'cmake'} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_add(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'add.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'license': ['GPL', 'MIT', 'BSD', 'Boost']}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_remove(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'remove.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'license': 'GPL'}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_remove_regex(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'remove_regex.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'default_options': 'debug=true'}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_kwargs_delete(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'delete.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {}, + 'target#tgt1': {}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_default_options_set(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'defopts_set.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'default_options': ['buildtype=release', 'debug=True', 'cpp_std=c++11']}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_default_options_delete(self): + self.prime('3 kwargs') + self.rewrite(self.builddir, os.path.join(self.builddir, 'defopts_delete.json')) + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + expected = { + 'kwargs': { + 'project#/': {'version': '0.0.1', 'default_options': ['cpp_std=c++14', 'debug=true']}, + 'target#tgt1': {'build_by_default': True}, + 'dependency#dep1': {'required': False} + } + } + self.assertDictEqual(out, expected) + + def test_target_add_extra_files(self): + self.prime('6 extra_files') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'addExtraFiles.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp', 'a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['main.cpp'], 'extra_files': ['a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': ['a5.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': ['a5.hpp', 'main.hpp', 'fileA.hpp']}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp'], 'extra_files': ['a3.hpp', 'main.hpp', 'a7.hpp', 'fileB.hpp', 'fileC.hpp']}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a2.hpp', 'a6.hpp', 'fileA.hpp', 'main.hpp']}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': ['a2.hpp', 'a7.hpp']}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': ['a8.hpp', 'a9.hpp']}, + 'trivialprog10@exe': {'name': 'trivialprog10', 'sources': ['main.cpp'], 'extra_files': ['a1.hpp', 'a4.hpp']}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) + + def test_target_remove_extra_files(self): + self.prime('6 extra_files') + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'rmExtraFiles.json')) + expected = { + 'target': { + 'trivialprog0@exe': {'name': 'trivialprog0', 'sources': ['main.cpp'], 'extra_files': ['main.hpp', 'fileC.hpp']}, + 'trivialprog1@exe': {'name': 'trivialprog1', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog2@exe': {'name': 'trivialprog2', 'sources': ['main.cpp'], 'extra_files': ['fileC.hpp']}, + 'trivialprog3@exe': {'name': 'trivialprog3', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog4@exe': {'name': 'trivialprog4', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog5@exe': {'name': 'trivialprog5', 'sources': ['main.cpp'], 'extra_files': ['main.hpp', 'fileC.hpp']}, + 'trivialprog6@exe': {'name': 'trivialprog6', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog7@exe': {'name': 'trivialprog7', 'sources': ['main.cpp'], 'extra_files': ['main.hpp']}, + 'trivialprog8@exe': {'name': 'trivialprog8', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog9@exe': {'name': 'trivialprog9', 'sources': ['main.cpp'], 'extra_files': []}, + 'trivialprog10@exe': {'name': 'trivialprog10', 'sources': ['main.cpp'], 'extra_files': []}, + } + } + self.assertDictEqual(out, expected) + + # Check the written file + out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) + self.assertDictEqual(out, expected) diff --git a/devtools/meson/unittests/subprojectscommandtests.py b/devtools/meson/unittests/subprojectscommandtests.py new file mode 100644 index 0000000..d50828b --- /dev/null +++ b/devtools/meson/unittests/subprojectscommandtests.py @@ -0,0 +1,311 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import tempfile +import textwrap +import os +from pathlib import Path +import typing as T + +from mesonbuild.mesonlib import ( + version_compare, git, search_version +) + + + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +class SubprojectsCommandTests(BasePlatformTests): + def setUp(self): + super().setUp() + self.root_dir = Path(self.builddir) + + self.project_dir = self.root_dir / 'src' + self._create_project(self.project_dir) + + self.subprojects_dir = self.project_dir / 'subprojects' + os.makedirs(str(self.subprojects_dir)) + self.packagecache_dir = self.subprojects_dir / 'packagecache' + os.makedirs(str(self.packagecache_dir)) + + def _create_project(self, path, project_name='dummy'): + os.makedirs(str(path), exist_ok=True) + with open(str(path / 'meson.build'), 'w', encoding='utf-8') as f: + f.write(f"project('{project_name}')") + + def _git(self, cmd, workdir): + return git(cmd, str(workdir), check=True)[1].strip() + + def _git_config(self, workdir): + self._git(['config', 'user.name', 'Meson Test'], workdir) + self._git(['config', 'user.email', 'meson.test@example.com'], workdir) + + def _git_remote(self, cmd, name): + return self._git(cmd, self.root_dir / name) + + def _git_local(self, cmd, name): + return self._git(cmd, self.subprojects_dir / name) + + def _git_local_branch(self, name): + # Same as `git branch --show-current` but compatible with older git version + branch = self._git_local(['rev-parse', '--abbrev-ref', 'HEAD'], name) + return branch if branch != 'HEAD' else '' + + def _git_local_commit(self, name, ref='HEAD'): + return self._git_local(['rev-parse', ref], name) + + def _git_remote_commit(self, name, ref='HEAD'): + return self._git_remote(['rev-parse', ref], name) + + def _git_create_repo(self, path): + # If a user has git configuration init.defaultBranch set we want to override that + with tempfile.TemporaryDirectory() as d: + out = git(['--version'], str(d))[1] + if version_compare(search_version(out), '>= 2.28'): + extra_cmd = ['--initial-branch', 'master'] + else: + extra_cmd = [] + + self._create_project(path) + self._git(['init'] + extra_cmd, path) + self._git_config(path) + self._git(['add', '.'], path) + self._git(['commit', '--no-gpg-sign', '-m', 'Initial commit'], path) + + def _git_create_remote_repo(self, name): + self._git_create_repo(self.root_dir / name) + + def _git_create_local_repo(self, name): + self._git_create_repo(self.subprojects_dir / name) + + def _git_create_remote_commit(self, name, branch): + self._git_remote(['checkout', branch], name) + self._git_remote(['commit', '--no-gpg-sign', '--allow-empty', '-m', f'initial {branch} commit'], name) + + def _git_create_remote_branch(self, name, branch): + self._git_remote(['checkout', '-b', branch], name) + self._git_remote(['commit', '--no-gpg-sign', '--allow-empty', '-m', f'initial {branch} commit'], name) + + def _git_create_remote_tag(self, name, tag): + self._git_remote(['commit', '--no-gpg-sign', '--allow-empty', '-m', f'tag {tag} commit'], name) + self._git_remote(['tag', '--no-sign', tag], name) + + def _wrap_create_git(self, name, revision='master', depth=None): + path = self.root_dir / name + with open(str((self.subprojects_dir / name).with_suffix('.wrap')), 'w', encoding='utf-8') as f: + if depth is None: + depth_line = '' + else: + depth_line = 'depth = {}'.format(depth) + f.write(textwrap.dedent( + ''' + [wrap-git] + url={} + revision={} + {} + '''.format(os.path.abspath(str(path)), revision, depth_line))) + + def _wrap_create_file(self, name, tarball='dummy.tar.gz'): + path = self.root_dir / tarball + with open(str((self.subprojects_dir / name).with_suffix('.wrap')), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + f''' + [wrap-file] + source_url={os.path.abspath(str(path))} + source_filename={tarball} + ''')) + Path(self.packagecache_dir / tarball).touch() + + def _subprojects_cmd(self, args): + return self._run(self.meson_command + ['subprojects'] + args, workdir=str(self.project_dir)) + + def test_git_update(self): + subp_name = 'sub1' + + # Create a fake remote git repository and a wrap file. Checks that + # "meson subprojects download" works. + self._git_create_remote_repo(subp_name) + self._wrap_create_git(subp_name) + self._subprojects_cmd(['download']) + self.assertPathExists(str(self.subprojects_dir / subp_name)) + self._git_config(self.subprojects_dir / subp_name) + + # Create a new remote branch and update the wrap file. Checks that + # "meson subprojects update --reset" checkout the new branch. + self._git_create_remote_branch(subp_name, 'newbranch') + self._wrap_create_git(subp_name, 'newbranch') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + + # Update remote newbranch. Checks the new commit is pulled into existing + # local newbranch. Make sure it does not print spurious 'git stash' message. + self._git_create_remote_commit(subp_name, 'newbranch') + out = self._subprojects_cmd(['update', '--reset']) + self.assertNotIn('No local changes to save', out) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + + # Update remote newbranch and switch to another branch. Checks that it + # switch current branch to newbranch and pull latest commit. + self._git_local(['checkout', 'master'], subp_name) + self._git_create_remote_commit(subp_name, 'newbranch') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + + # Stage some local changes then update. Checks that local changes got + # stashed. + self._create_project(self.subprojects_dir / subp_name, 'new_project_name') + self._git_local(['add', '.'], subp_name) + self._git_create_remote_commit(subp_name, 'newbranch') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), 'newbranch') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newbranch')) + self.assertTrue(self._git_local(['stash', 'list'], subp_name)) + + # Untracked files need to be stashed too, or (re-)applying a patch + # creating one of those untracked files will fail. + untracked = self.subprojects_dir / subp_name / 'untracked.c' + untracked.write_bytes(b'int main(void) { return 0; }') + self._subprojects_cmd(['update', '--reset']) + self.assertTrue(self._git_local(['stash', 'list'], subp_name)) + assert not untracked.exists() + # Ensure it was indeed stashed, and we can get it back. + self.assertTrue(self._git_local(['stash', 'pop'], subp_name)) + assert untracked.exists() + + # Create a new remote tag and update the wrap file. Checks that + # "meson subprojects update --reset" checkout the new tag in detached mode. + self._git_create_remote_tag(subp_name, 'newtag') + self._wrap_create_git(subp_name, 'newtag') + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), '') + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name, 'newtag')) + + # Create a new remote commit and update the wrap file with the commit id. + # Checks that "meson subprojects update --reset" checkout the new commit + # in detached mode. + self._git_local(['checkout', 'master'], subp_name) + self._git_create_remote_commit(subp_name, 'newbranch') + new_commit = self._git_remote(['rev-parse', 'HEAD'], subp_name) + self._wrap_create_git(subp_name, new_commit) + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_branch(subp_name), '') + self.assertEqual(self._git_local_commit(subp_name), new_commit) + + # Create a local project not in a git repository, then update it with + # a git wrap. Without --reset it should print error message and return + # failure. With --reset it should delete existing project and clone the + # new project. + subp_name = 'sub2' + self._create_project(self.subprojects_dir / subp_name) + self._git_create_remote_repo(subp_name) + self._wrap_create_git(subp_name) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self._subprojects_cmd(['update']) + self.assertIn('Not a git repository', cm.exception.output) + self._subprojects_cmd(['update', '--reset']) + self.assertEqual(self._git_local_commit(subp_name), self._git_remote_commit(subp_name)) + + # Create a fake remote git repository and a wrap file targeting + # HEAD and depth = 1. Checks that "meson subprojects download" works. + subp_name = 'sub3' + self._git_create_remote_repo(subp_name) + self._wrap_create_git(subp_name, revision='head', depth='1') + self._subprojects_cmd(['download']) + self.assertPathExists(str(self.subprojects_dir / subp_name)) + self._git_config(self.subprojects_dir / subp_name) + + @skipIfNoExecutable('true') + def test_foreach(self): + self._create_project(self.subprojects_dir / 'sub_file') + self._wrap_create_file('sub_file') + self._git_create_local_repo('sub_git') + self._wrap_create_git('sub_git') + self._git_create_local_repo('sub_git_no_wrap') + + def ran_in(s): + ret = [] + prefix = 'Executing command in ' + for l in s.splitlines(): + if l.startswith(prefix): + ret.append(l[len(prefix):]) + return sorted(ret) + + dummy_cmd = ['true'] + out = self._subprojects_cmd(['foreach'] + dummy_cmd) + self.assertEqual(ran_in(out), sorted(['subprojects/sub_file', 'subprojects/sub_git', 'subprojects/sub_git_no_wrap'])) + out = self._subprojects_cmd(['foreach', '--types', 'git,file'] + dummy_cmd) + self.assertEqual(ran_in(out), sorted(['subprojects/sub_file', 'subprojects/sub_git'])) + out = self._subprojects_cmd(['foreach', '--types', 'file'] + dummy_cmd) + self.assertEqual(ran_in(out), ['subprojects/sub_file']) + out = self._subprojects_cmd(['foreach', '--types', 'git'] + dummy_cmd) + self.assertEqual(ran_in(out), ['subprojects/sub_git']) + + def test_purge(self): + self._create_project(self.subprojects_dir / 'sub_file') + self._wrap_create_file('sub_file') + self._git_create_local_repo('sub_git') + self._wrap_create_git('sub_git') + + sub_file_subprojects_dir = self.subprojects_dir / 'sub_file' / 'subprojects' + sub_file_subprojects_dir.mkdir(exist_ok=True, parents=True) + real_dir = Path('sub_file') / 'subprojects' / 'real' + + self._wrap_create_file(real_dir, tarball='dummy2.tar.gz') + + with open(str((self.subprojects_dir / 'redirect').with_suffix('.wrap')), 'w', encoding='utf-8') as f: + f.write(textwrap.dedent( + f''' + [wrap-redirect] + filename = {real_dir}.wrap + ''')) + + def deleting(s: str) -> T.List[str]: + ret = [] + prefix = 'Deleting ' + for l in s.splitlines(): + if l.startswith(prefix): + ret.append(l[len(prefix):]) + return sorted(ret) + + out = self._subprojects_cmd(['purge']) + self.assertEqual(deleting(out), sorted([ + str(self.subprojects_dir / 'redirect.wrap'), + str(self.subprojects_dir / 'sub_file'), + str(self.subprojects_dir / 'sub_git'), + ])) + out = self._subprojects_cmd(['purge', '--include-cache']) + self.assertEqual(deleting(out), sorted([ + str(self.subprojects_dir / 'sub_git'), + str(self.subprojects_dir / 'redirect.wrap'), + str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), + str(self.subprojects_dir / 'packagecache' / 'dummy2.tar.gz'), + str(self.subprojects_dir / 'sub_file'), + ])) + out = self._subprojects_cmd(['purge', '--include-cache', '--confirm']) + self.assertEqual(deleting(out), sorted([ + str(self.subprojects_dir / 'sub_git'), + str(self.subprojects_dir / 'redirect.wrap'), + str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), + str(self.subprojects_dir / 'packagecache' / 'dummy2.tar.gz'), + str(self.subprojects_dir / 'sub_file'), + ])) + self.assertFalse(Path(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz').exists()) + self.assertFalse(Path(self.subprojects_dir / 'sub_file').exists()) + self.assertFalse(Path(self.subprojects_dir / 'sub_git').exists()) + self.assertFalse(Path(self.subprojects_dir / 'redirect.wrap').exists()) diff --git a/devtools/meson/unittests/taptests.py b/devtools/meson/unittests/taptests.py new file mode 100644 index 0000000..6c2ccb0 --- /dev/null +++ b/devtools/meson/unittests/taptests.py @@ -0,0 +1,294 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import io + +from mesonbuild.mtest import TAPParser, TestResult + + +class TAPParserTests(unittest.TestCase): + def assert_test(self, events, **kwargs): + if 'explanation' not in kwargs: + kwargs['explanation'] = None + self.assertEqual(next(events), TAPParser.Test(**kwargs)) + + def assert_plan(self, events, **kwargs): + if 'skipped' not in kwargs: + kwargs['skipped'] = False + if 'explanation' not in kwargs: + kwargs['explanation'] = None + self.assertEqual(next(events), TAPParser.Plan(**kwargs)) + + def assert_version(self, events, **kwargs): + self.assertEqual(next(events), TAPParser.Version(**kwargs)) + + def assert_error(self, events): + self.assertEqual(type(next(events)), TAPParser.Error) + + def assert_unexpected(self, events, **kwargs): + self.assertEqual(next(events), TAPParser.UnknownLine(**kwargs)) + + def assert_bailout(self, events, **kwargs): + self.assertEqual(next(events), TAPParser.Bailout(**kwargs)) + + def assert_last(self, events): + with self.assertRaises(StopIteration): + next(events) + + def parse_tap(self, s): + parser = TAPParser() + return iter(parser.parse(io.StringIO(s))) + + def parse_tap_v13(self, s): + events = self.parse_tap('TAP version 13\n' + s) + self.assert_version(events, version=13) + return events + + def test_empty(self): + events = self.parse_tap('') + self.assert_last(events) + + def test_empty_plan(self): + events = self.parse_tap('1..0') + self.assert_plan(events, num_tests=0, late=False, skipped=True) + self.assert_last(events) + + def test_plan_directive(self): + events = self.parse_tap('1..0 # skipped for some reason') + self.assert_plan(events, num_tests=0, late=False, skipped=True, + explanation='for some reason') + self.assert_last(events) + + events = self.parse_tap('1..1 # skipped for some reason\nok 1') + self.assert_error(events) + self.assert_plan(events, num_tests=1, late=False, skipped=True, + explanation='for some reason') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap('1..1 # todo not supported here\nok 1') + self.assert_error(events) + self.assert_plan(events, num_tests=1, late=False, skipped=False, + explanation='not supported here') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_ok(self): + events = self.parse_tap('ok') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_with_number(self): + events = self.parse_tap('ok 1') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_with_name(self): + events = self.parse_tap('ok 1 abc') + self.assert_test(events, number=1, name='abc', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_not_ok(self): + events = self.parse_tap('not ok') + self.assert_test(events, number=1, name='', result=TestResult.FAIL) + self.assert_last(events) + + def test_one_test_todo(self): + events = self.parse_tap('not ok 1 abc # TODO') + self.assert_test(events, number=1, name='abc', result=TestResult.EXPECTEDFAIL) + self.assert_last(events) + + events = self.parse_tap('ok 1 abc # TODO') + self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS) + self.assert_last(events) + + def test_one_test_skip(self): + events = self.parse_tap('ok 1 abc # SKIP') + self.assert_test(events, number=1, name='abc', result=TestResult.SKIP) + self.assert_last(events) + + def test_one_test_skip_failure(self): + events = self.parse_tap('not ok 1 abc # SKIP') + self.assert_test(events, number=1, name='abc', result=TestResult.FAIL) + self.assert_last(events) + + def test_many_early_plan(self): + events = self.parse_tap('1..4\nok 1\nnot ok 2\nok 3\nnot ok 4') + self.assert_plan(events, num_tests=4, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_test(events, number=3, name='', result=TestResult.OK) + self.assert_test(events, number=4, name='', result=TestResult.FAIL) + self.assert_last(events) + + def test_many_late_plan(self): + events = self.parse_tap('ok 1\nnot ok 2\nok 3\nnot ok 4\n1..4') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_test(events, number=3, name='', result=TestResult.OK) + self.assert_test(events, number=4, name='', result=TestResult.FAIL) + self.assert_plan(events, num_tests=4, late=True) + self.assert_last(events) + + def test_directive_case(self): + events = self.parse_tap('ok 1 abc # skip') + self.assert_test(events, number=1, name='abc', result=TestResult.SKIP) + self.assert_last(events) + + events = self.parse_tap('ok 1 abc # ToDo') + self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS) + self.assert_last(events) + + def test_directive_explanation(self): + events = self.parse_tap('ok 1 abc # skip why') + self.assert_test(events, number=1, name='abc', result=TestResult.SKIP, + explanation='why') + self.assert_last(events) + + events = self.parse_tap('ok 1 abc # ToDo Because') + self.assert_test(events, number=1, name='abc', result=TestResult.UNEXPECTEDPASS, + explanation='Because') + self.assert_last(events) + + def test_one_test_early_plan(self): + events = self.parse_tap('1..1\nok') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_one_test_late_plan(self): + events = self.parse_tap('ok\n1..1') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_plan(events, num_tests=1, late=True) + self.assert_last(events) + + def test_out_of_order(self): + events = self.parse_tap('ok 2') + self.assert_error(events) + self.assert_test(events, number=2, name='', result=TestResult.OK) + self.assert_last(events) + + def test_middle_plan(self): + events = self.parse_tap('ok 1\n1..2\nok 2') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_plan(events, num_tests=2, late=True) + self.assert_error(events) + self.assert_test(events, number=2, name='', result=TestResult.OK) + self.assert_last(events) + + def test_too_many_plans(self): + events = self.parse_tap('1..1\n1..2\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_error(events) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_too_many(self): + events = self.parse_tap('ok 1\nnot ok 2\n1..1') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_plan(events, num_tests=1, late=True) + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap('1..1\nok 1\nnot ok 2') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_error(events) + self.assert_last(events) + + def test_too_few(self): + events = self.parse_tap('ok 1\nnot ok 2\n1..3') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_plan(events, num_tests=3, late=True) + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap('1..3\nok 1\nnot ok 2') + self.assert_plan(events, num_tests=3, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_error(events) + self.assert_last(events) + + def test_too_few_bailout(self): + events = self.parse_tap('1..3\nok 1\nnot ok 2\nBail out! no third test') + self.assert_plan(events, num_tests=3, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_bailout(events, message='no third test') + self.assert_last(events) + + def test_diagnostics(self): + events = self.parse_tap('1..1\n# ignored\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap('# ignored\n1..1\nok 1\n# ignored too') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap('# ignored\nok 1\n1..1\n# ignored too') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_plan(events, num_tests=1, late=True) + self.assert_last(events) + + def test_empty_line(self): + events = self.parse_tap('1..1\n\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_unexpected(self): + events = self.parse_tap('1..1\ninvalid\nok 1') + self.assert_plan(events, num_tests=1, late=False) + self.assert_unexpected(events, message='invalid', lineno=2) + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_last(events) + + def test_version(self): + events = self.parse_tap('TAP version 13\n') + self.assert_version(events, version=13) + self.assert_last(events) + + events = self.parse_tap('TAP version 12\n') + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap('1..0\nTAP version 13\n') + self.assert_plan(events, num_tests=0, late=False, skipped=True) + self.assert_error(events) + self.assert_last(events) + + def test_yaml(self): + events = self.parse_tap_v13('ok\n ---\n foo: abc\n bar: def\n ...\nok 2') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_test(events, number=2, name='', result=TestResult.OK) + self.assert_last(events) + + events = self.parse_tap_v13('ok\n ---\n foo: abc\n bar: def') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_error(events) + self.assert_last(events) + + events = self.parse_tap_v13('ok 1\n ---\n foo: abc\n bar: def\nnot ok 2') + self.assert_test(events, number=1, name='', result=TestResult.OK) + self.assert_error(events) + self.assert_test(events, number=2, name='', result=TestResult.FAIL) + self.assert_last(events) diff --git a/devtools/meson/unittests/windowstests.py b/devtools/meson/unittests/windowstests.py new file mode 100644 index 0000000..c201953 --- /dev/null +++ b/devtools/meson/unittests/windowstests.py @@ -0,0 +1,490 @@ +# Copyright 2016-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import re +import os +import shutil +from unittest import mock, SkipTest, skipUnless, skipIf +from glob import glob + +import mesonbuild.mlog +import mesonbuild.depfile +import mesonbuild.dependencies.factory +import mesonbuild.envconfig +import mesonbuild.environment +import mesonbuild.coredata +import mesonbuild.modules.gnome +from mesonbuild.mesonlib import ( + MachineChoice, is_windows, is_cygwin, python_command, version_compare, + EnvironmentException, OptionKey +) +from mesonbuild.compilers import ( + detect_c_compiler, detect_d_compiler, compiler_from_language, +) +from mesonbuild.programs import ExternalProgram +import mesonbuild.dependencies.base +import mesonbuild.modules.pkgconfig + + +from run_tests import ( + Backend, get_fake_env +) + +from .baseplatformtests import BasePlatformTests +from .helpers import * + +@skipUnless(is_windows() or is_cygwin(), "requires Windows (or Windows via Cygwin)") +class WindowsTests(BasePlatformTests): + ''' + Tests that should run on Cygwin, MinGW, and MSVC + ''' + + def setUp(self): + super().setUp() + self.platform_test_dir = os.path.join(self.src_root, 'test cases/windows') + + @skipIf(is_cygwin(), 'Test only applicable to Windows') + @mock.patch.dict(os.environ) + def test_find_program(self): + ''' + Test that Windows-specific edge-cases in find_program are functioning + correctly. Cannot be an ordinary test because it involves manipulating + PATH to point to a directory with Python scripts. + ''' + testdir = os.path.join(self.platform_test_dir, '8 find program') + # Find `cmd` and `cmd.exe` + prog1 = ExternalProgram('cmd') + self.assertTrue(prog1.found(), msg='cmd not found') + prog2 = ExternalProgram('cmd.exe') + self.assertTrue(prog2.found(), msg='cmd.exe not found') + self.assertPathEqual(prog1.get_path(), prog2.get_path()) + # Find cmd.exe with args without searching + prog = ExternalProgram('cmd', command=['cmd', '/C']) + self.assertTrue(prog.found(), msg='cmd not found with args') + self.assertPathEqual(prog.get_command()[0], 'cmd') + # Find cmd with an absolute path that's missing the extension + cmd_path = prog2.get_path()[:-4] + prog = ExternalProgram(cmd_path) + self.assertTrue(prog.found(), msg=f'{cmd_path!r} not found') + # Finding a script with no extension inside a directory works + prog = ExternalProgram(os.path.join(testdir, 'test-script')) + self.assertTrue(prog.found(), msg='test-script not found') + # Finding a script with an extension inside a directory works + prog = ExternalProgram(os.path.join(testdir, 'test-script-ext.py')) + self.assertTrue(prog.found(), msg='test-script-ext.py not found') + # Finding a script in PATH + os.environ['PATH'] += os.pathsep + testdir + # If `.PY` is in PATHEXT, scripts can be found as programs + if '.PY' in [ext.upper() for ext in os.environ['PATHEXT'].split(';')]: + # Finding a script in PATH w/o extension works and adds the interpreter + prog = ExternalProgram('test-script-ext') + self.assertTrue(prog.found(), msg='test-script-ext not found in PATH') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') + # Finding a script in PATH with extension works and adds the interpreter + prog = ExternalProgram('test-script-ext.py') + self.assertTrue(prog.found(), msg='test-script-ext.py not found in PATH') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') + # Using a script with an extension directly via command= works and adds the interpreter + prog = ExternalProgram('test-script-ext.py', command=[os.path.join(testdir, 'test-script-ext.py'), '--help']) + self.assertTrue(prog.found(), msg='test-script-ext.py with full path not picked up via command=') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathEqual(prog.get_command()[2], '--help') + self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py') + # Using a script without an extension directly via command= works and adds the interpreter + prog = ExternalProgram('test-script', command=[os.path.join(testdir, 'test-script'), '--help']) + self.assertTrue(prog.found(), msg='test-script with full path not picked up via command=') + self.assertPathEqual(prog.get_command()[0], python_command[0]) + self.assertPathEqual(prog.get_command()[2], '--help') + self.assertPathBasenameEqual(prog.get_path(), 'test-script') + # Ensure that WindowsApps gets removed from PATH + path = os.environ['PATH'] + if 'WindowsApps' not in path: + username = os.environ['USERNAME'] + appstore_dir = fr'C:\Users\{username}\AppData\Local\Microsoft\WindowsApps' + path = os.pathsep + appstore_dir + path = ExternalProgram._windows_sanitize_path(path) + self.assertNotIn('WindowsApps', path) + + def test_ignore_libs(self): + ''' + Test that find_library on libs that are to be ignored returns an empty + array of arguments. Must be a unit test because we cannot inspect + ExternalLibraryHolder from build files. + ''' + testdir = os.path.join(self.platform_test_dir, '1 basic') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Not using MSVC') + # To force people to update this test, and also test + self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread', 'dl', 'rt', 'execinfo'}) + for l in cc.ignore_libs: + self.assertEqual(cc.find_library(l, env, []), []) + + def test_rc_depends_files(self): + testdir = os.path.join(self.platform_test_dir, '5 resources') + + # resource compiler depfile generation is not yet implemented for msvc + env = get_fake_env(testdir, self.builddir, self.prefix) + depfile_works = detect_c_compiler(env, MachineChoice.HOST).get_id() not in {'msvc', 'clang-cl', 'intel-cl'} + + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Test compile_resources(depend_file:) + # Changing mtime of sample.ico should rebuild prog + self.utime(os.path.join(testdir, 'res', 'sample.ico')) + self.assertRebuiltTarget('prog') + # Test depfile generation by compile_resources + # Changing mtime of resource.h should rebuild myres.rc and then prog + if depfile_works: + self.utime(os.path.join(testdir, 'inc', 'resource', 'resource.h')) + self.assertRebuiltTarget('prog') + self.wipe() + + if depfile_works: + testdir = os.path.join(self.platform_test_dir, '12 resources with custom targets') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of resource.h should rebuild myres_1.rc and then prog_1 + self.utime(os.path.join(testdir, 'res', 'resource.h')) + self.assertRebuiltTarget('prog_1') + + def test_msvc_cpp17(self): + testdir = os.path.join(self.unit_test_dir, '44 vscpp17') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Test only applies to MSVC-like compilers') + + try: + self.init(testdir) + except subprocess.CalledProcessError: + # According to Python docs, output is only stored when + # using check_output. We don't use it, so we can't check + # that the output is correct (i.e. that it failed due + # to the right reason). + return + self.build() + + @skipIf(is_cygwin(), 'Test only applicable to Windows') + def test_genvslite(self): + # The test framework itself might be forcing a specific, non-ninja backend across a set of tests, which + # includes this test. E.g. - + # > python.exe run_unittests.py --backend=vs WindowsTests + # Since that explicitly specifies a backend that's incompatible with (and essentially meaningless in + # conjunction with) 'genvslite', we should skip further genvslite testing. + if self.backend is not Backend.ninja: + raise SkipTest('Test only applies when using the Ninja backend') + + testdir = os.path.join(self.unit_test_dir, '115 genvslite') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Test only applies when MSVC tools are available.') + + # We want to run the genvslite setup. I.e. - + # meson setup --genvslite vs2022 ... + # which we should expect to generate the set of _debug/_debugoptimized/_release suffixed + # build directories. Then we want to check that the solution/project build hooks (like clean, + # build, and rebuild) end up ultimately invoking the 'meson compile ...' of the appropriately + # suffixed build dir, for which we need to use 'msbuild.exe' + + # Find 'msbuild.exe' + msbuildprog = ExternalProgram('msbuild.exe') + self.assertTrue(msbuildprog.found(), msg='msbuild.exe not found') + + # Setup with '--genvslite ...' + self.new_builddir() + + # Firstly, we'd like to check that meson errors if the user explicitly specifies a non-ninja backend + # during setup. + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testdir, extra_args=['--genvslite', 'vs2022', '--backend', 'vs']) + self.assertIn("specifying a non-ninja backend conflicts with a 'genvslite' setup", cm.exception.stdout) + + # Wrap the following bulk of setup and msbuild invocation testing in a try-finally because any exception, + # failure, or success must always clean up any of the suffixed build dir folders that may have been generated. + try: + # Since this + self.init(testdir, extra_args=['--genvslite', 'vs2022']) + # We need to bear in mind that the BasePlatformTests framework creates and cleans up its own temporary + # build directory. However, 'genvslite' creates a set of suffixed build directories which we'll have + # to clean up ourselves. See 'finally' block below. + + # We intentionally skip the - + # self.build() + # step because we're wanting to test compilation/building through the solution/project's interface. + + # Execute the debug and release builds through the projects 'Build' hooks + genvslite_vcxproj_path = str(os.path.join(self.builddir+'_vs', 'genvslite@exe.vcxproj')) + # This use-case of invoking the .sln/.vcxproj build hooks, not through Visual Studio itself, but through + # 'msbuild.exe', in a VS tools command prompt environment (e.g. "x64 Native Tools Command Prompt for VS 2022"), is a + # problem: Such an environment sets the 'VSINSTALLDIR' variable which, mysteriously, has the side-effect of causing + # the spawned 'meson compile' command to fail to find 'ninja' (and even when ninja can be found elsewhere, all the + # compiler binaries that ninja wants to run also fail to be found). The PATH environment variable in the child python + # (and ninja) processes are fundamentally stripped down of all the critical search paths required to run the ninja + # compile work ... ONLY when 'VSINSTALLDIR' is set; without 'VSINSTALLDIR' set, the meson compile command does search + # for and find ninja (ironically, it finds it under the path where VSINSTALLDIR pointed!). + # For the above reason, this testing works around this bizarre behaviour by temporarily removing any 'VSINSTALLDIR' + # variable, prior to invoking the builds - + current_env = os.environ.copy() + current_env.pop('VSINSTALLDIR', None) + subprocess.check_call( + ['msbuild', '-target:Build', '-property:Configuration=debug', genvslite_vcxproj_path], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + env=current_env) + subprocess.check_call( + ['msbuild', '-target:Build', '-property:Configuration=release', genvslite_vcxproj_path], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + env=current_env) + + # Check this has actually built the appropriate exes + output_debug = subprocess.check_output(str(os.path.join(self.builddir+'_debug', 'genvslite.exe'))) + self.assertEqual( output_debug, b'Debug\r\n' ) + output_release = subprocess.check_output(str(os.path.join(self.builddir+'_release', 'genvslite.exe'))) + self.assertEqual( output_release, b'Non-debug\r\n' ) + + finally: + # Clean up our special suffixed temporary build dirs + suffixed_build_dirs = glob(self.builddir+'_*', recursive=False) + for build_dir in suffixed_build_dirs: + shutil.rmtree(build_dir) + + def test_install_pdb_introspection(self): + testdir = os.path.join(self.platform_test_dir, '1 basic') + + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Test only applies to MSVC-like compilers') + + self.init(testdir) + installed = self.introspect('--installed') + files = [os.path.basename(path) for path in installed.values()] + + self.assertIn('prog.pdb', files) + + def _check_ld(self, name: str, lang: str, expected: str) -> None: + if not shutil.which(name): + raise SkipTest(f'Could not find {name}.') + envvars = [mesonbuild.envconfig.ENV_VAR_PROG_MAP[f'{lang}_ld']] + + # Also test a deprecated variable if there is one. + if f'{lang}_ld' in mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP: + envvars.append( + mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP[f'{lang}_ld']) + + for envvar in envvars: + with mock.patch.dict(os.environ, {envvar: name}): + env = get_fake_env() + try: + comp = compiler_from_language(env, lang, MachineChoice.HOST) + except EnvironmentException: + raise SkipTest(f'Could not find a compiler for {lang}') + self.assertEqual(comp.linker.id, expected) + + def test_link_environment_variable_lld_link(self): + env = get_fake_env() + comp = detect_c_compiler(env, MachineChoice.HOST) + if comp.get_argument_syntax() == 'gcc': + raise SkipTest('GCC cannot be used with link compatible linkers.') + self._check_ld('lld-link', 'c', 'lld-link') + + def test_link_environment_variable_link(self): + env = get_fake_env() + comp = detect_c_compiler(env, MachineChoice.HOST) + if comp.get_argument_syntax() == 'gcc': + raise SkipTest('GCC cannot be used with link compatible linkers.') + self._check_ld('link', 'c', 'link') + + def test_link_environment_variable_optlink(self): + env = get_fake_env() + comp = detect_c_compiler(env, MachineChoice.HOST) + if comp.get_argument_syntax() == 'gcc': + raise SkipTest('GCC cannot be used with link compatible linkers.') + self._check_ld('optlink', 'c', 'optlink') + + @skip_if_not_language('rust') + def test_link_environment_variable_rust(self): + self._check_ld('link', 'rust', 'link') + + @skip_if_not_language('d') + def test_link_environment_variable_d(self): + env = get_fake_env() + comp = detect_d_compiler(env, MachineChoice.HOST) + if comp.id == 'dmd': + raise SkipTest('meson cannot reliably make DMD use a different linker.') + self._check_ld('lld-link', 'd', 'lld-link') + + def test_pefile_checksum(self): + try: + import pefile + except ImportError: + if is_ci(): + raise + raise SkipTest('pefile module not found') + testdir = os.path.join(self.common_test_dir, '6 linkshared') + self.init(testdir, extra_args=['--buildtype=release']) + self.build() + # Test that binaries have a non-zero checksum + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + cc_id = cc.get_id() + ld_id = cc.get_linker_id() + dll = glob(os.path.join(self.builddir, '*mycpplib.dll'))[0] + exe = os.path.join(self.builddir, 'cppprog.exe') + for f in (dll, exe): + pe = pefile.PE(f) + msg = f'PE file: {f!r}, compiler: {cc_id!r}, linker: {ld_id!r}' + if cc_id == 'clang-cl': + # Latest clang-cl tested (7.0) does not write checksums out + self.assertFalse(pe.verify_checksum(), msg=msg) + else: + # Verify that a valid checksum was written by all other compilers + self.assertTrue(pe.verify_checksum(), msg=msg) + + def test_qt5dependency_vscrt(self): + ''' + Test that qt5 dependencies use the debug module suffix when b_vscrt is + set to 'mdd' + ''' + # Verify that the `b_vscrt` option is available + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if OptionKey('b_vscrt') not in cc.base_options: + raise SkipTest('Compiler does not support setting the VS CRT') + # Verify that qmake is for Qt5 + if not shutil.which('qmake-qt5'): + if not shutil.which('qmake') and not is_ci(): + raise SkipTest('QMake not found') + output = subprocess.getoutput('qmake --version') + if 'Qt version 5' not in output and not is_ci(): + raise SkipTest('Qmake found, but it is not for Qt 5.') + # Setup with /MDd + testdir = os.path.join(self.framework_test_dir, '4 qt') + self.init(testdir, extra_args=['-Db_vscrt=mdd']) + # Verify that we're linking to the debug versions of Qt DLLs + build_ninja = os.path.join(self.builddir, 'build.ninja') + with open(build_ninja, encoding='utf-8') as f: + contents = f.read() + m = re.search('build qt5core.exe: cpp_LINKER.*Qt5Cored.lib', contents) + self.assertIsNotNone(m, msg=contents) + + def test_compiler_checks_vscrt(self): + ''' + Test that the correct VS CRT is used when running compiler checks + ''' + # Verify that the `b_vscrt` option is available + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if OptionKey('b_vscrt') not in cc.base_options: + raise SkipTest('Compiler does not support setting the VS CRT') + + def sanitycheck_vscrt(vscrt): + checks = self.get_meson_log_sanitychecks() + self.assertGreater(len(checks), 0) + for check in checks: + self.assertIn(vscrt, check) + + testdir = os.path.join(self.common_test_dir, '1 trivial') + self.init(testdir) + sanitycheck_vscrt('/MDd') + + self.new_builddir() + self.init(testdir, extra_args=['-Dbuildtype=debugoptimized']) + sanitycheck_vscrt('/MD') + + self.new_builddir() + self.init(testdir, extra_args=['-Dbuildtype=release']) + sanitycheck_vscrt('/MD') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=md']) + sanitycheck_vscrt('/MD') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=mdd']) + sanitycheck_vscrt('/MDd') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=mt']) + sanitycheck_vscrt('/MT') + + self.new_builddir() + self.init(testdir, extra_args=['-Db_vscrt=mtd']) + sanitycheck_vscrt('/MTd') + + def test_modules(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'C++ modules only work with the Ninja backend (not {self.backend.name}).') + if 'VSCMD_VER' not in os.environ: + raise SkipTest('C++ modules is only supported with Visual Studio.') + if version_compare(os.environ['VSCMD_VER'], '<16.10.0'): + raise SkipTest('C++ modules are only supported with VS 2019 Preview or newer.') + self.init(os.path.join(self.unit_test_dir, '85 cpp modules')) + self.build() + + def test_non_utf8_fails(self): + # FIXME: VS backend does not use flags from compiler.get_always_args() + # and thus it's missing /utf-8 argument. Was that intentional? This needs + # to be revisited. + if self.backend is not Backend.ninja: + raise SkipTest(f'This test only pass with ninja backend (not {self.backend.name}).') + testdir = os.path.join(self.platform_test_dir, '18 msvc charset') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_argument_syntax() != 'msvc': + raise SkipTest('Not using MSVC') + self.init(testdir, extra_args=['-Dtest-failure=true']) + self.assertRaises(subprocess.CalledProcessError, self.build) + + @unittest.skipIf(is_cygwin(), "Needs visual studio") + def test_vsenv_option(self): + if mesonbuild.environment.detect_msys2_arch(): + # https://github.com/msys2-contrib/cpython-mingw/issues/141 + raise SkipTest('mingw python fails with /bin being removed from PATH') + if self.backend is not Backend.ninja: + raise SkipTest('Only ninja backend is valid for test') + env = os.environ.copy() + env['MESON_FORCE_VSENV_FOR_UNITTEST'] = '1' + # Remove ninja from PATH to ensure that the one provided by Visual + # Studio is picked, as a regression test for + # https://github.com/mesonbuild/meson/issues/9774 + env['PATH'] = get_path_without_cmd('ninja', env['PATH']) + testdir = os.path.join(self.common_test_dir, '1 trivial') + out = self.init(testdir, extra_args=['--vsenv'], override_envvars=env) + self.assertIn('Activating VS', out) + self.assertRegex(out, 'Visual Studio environment is needed to run Ninja') + # All these directly call ninja with the full path, so we need to patch + # it out to use meson subcommands + with mock.patch.object(self, 'build_command', self.meson_command + ['compile']): + out = self.build(override_envvars=env) + self.assertIn('Activating VS', out) + with mock.patch.object(self, 'test_command', self.meson_command + ['test']): + out = self.run_tests(override_envvars=env) + self.assertIn('Activating VS', out) + with mock.patch.object(self, 'install_command', self.meson_command + ['install']): + out = self.install(override_envvars=env) + self.assertIn('Activating VS', out) diff --git a/devtools/meson_set_outdir.bat b/devtools/meson_set_outdir.bat new file mode 100644 index 0000000..d60e4be --- /dev/null +++ b/devtools/meson_set_outdir.bat @@ -0,0 +1,11 @@ +@if "%overbose%" == "" echo off + +set "_PROJECT_=%1" +set "_PROJECT_PATH_=%2" +set "_PROJECT_OUTPUT_=%3" + +pushd +cd %_PROJECT_PATH_% +echo %_PROJECT_%=%_PROJECT_OUTPUT_% > OUTDIR + +popd diff --git a/devtools/vs_add_build_steps.py b/devtools/vs_add_build_steps.py new file mode 100644 index 0000000..d75255f --- /dev/null +++ b/devtools/vs_add_build_steps.py @@ -0,0 +1,149 @@ +import os +import sys + +skip_these_projects = ["REGEN", "RUN_INSTALL", "RUN_TESTS"] +valid_configs = ["all", "debugoptimized", "release"] + +def add_post_build_to_all(directory_path): + print(f"Adding post build for all vcxproj in {directory_path}") + + # Recursively find all .vcxproj files under the specified directory + for foldername, subfolders, filenames in os.walk(directory_path): + for filename in filenames: + if filename.endswith('.vcxproj'): + process = True + + for skip in skip_these_projects: + if skip in filename: + process = False + break + + if process: + file_path = os.path.join(foldername, filename) + add_post_build_to_vcxproj(file_path) + + +def add_post_build_to_vcxproj(file_path): + + # this script assumes the meson build process output a file named OUTDIR which has the info we need to generate the + # post_build_command below. + file_dir = os.path.dirname(file_path) + outdir_file_path = os.path.join(file_dir, "OUTDIR") + vcxproj = os.path.basename(file_path) + + if not os.path.exists(file_dir) or not os.path.exists(outdir_file_path): + print(f"Couldn't find OUTDIR file next to {file_path}") + return + + projectoutput = "" + dll_name = "" + + with open(outdir_file_path, 'r') as file: + line = file.readline().strip() + parts = line.split('=') + dll_name = parts[0] + projectoutput = parts[1] + + projectoutput = projectoutput.strip('/').strip('\\').replace('/', '\\') + + print(f"Adding post build for '{file_path}', dll_name='{dll_name}', projectoutput='{projectoutput}'") + + # Read the file contents + with open(file_path, 'r', encoding='utf-8') as f: + contents = f.read() + + # Check if the post-build step already exists to avoid adding it multiple times + if 'filecopy.bat' in contents: + print(f"Post build step already exists in {file_path}. Skipping.") + return + + relative_dir = "..\\..\\..\\" + + #the expected root dir is 3 back from where the vcxproj exists, but some projects are further nested. + # THIS IS NOT BULLET PROOF and if you're getting vstudio build errors during the filecopy.bat step it's probably here + # that caused the bug. + expected_root_dir = os.path.join(file_dir, "../../../game/") + if not os.path.exists(expected_root_dir): + relative_dir = "..\\..\\..\\..\\" + + command = '''call $(SolutionDir)..\\filecopy.bat $(TargetDir)$(TargetName).pdb $(ProjectDir)%RELATIVE_DIR%\\game\\%PROJECT_OUTPUT%\\$(TargetName).pdb + call $(SolutionDir)..\\filecopy.bat $(TargetPath) $(ProjectDir)%RELATIVE_DIR%\\game\\%PROJECT_OUTPUT%\\$(TargetFileName)''' + + ################################################################################# + # DUMB EXCEPTIONS !!!!!!!!!!!!!!!!! + # + # Some of the DLLs get copied to other mods or utilities after they are built. + # + + if( vcxproj == 'sw.vcxproj' ): + command += ''' + call $(SolutionDir)..\\filecopy.bat $(TargetPath) $(ProjectDir)%RELATIVE_DIR%\\game\\%PROJECT_OUTPUT%\\swds.dll''' + print("The software engine gets special handling.") + + if( 'cstrike' in file_dir ): + if( vcxproj == 'client.vcxproj' ): + command += ''' + call $(SolutionDir)..\\filecopy.bat $(TargetDir)$(TargetName).pdb $(ProjectDir)%RELATIVE_DIR%\\game\\czero\\cl_dlls\$(TargetName).pdb + call $(SolutionDir)..\\filecopy.bat $(TargetPath) $(ProjectDir)%RELATIVE_DIR%\\game\\czero\\cl_dlls\$(TargetFileName)''' + print("cstrike client DLL also going to czero/client.dll") + elif( vcxproj == 'mp.vcxproj' ): + command += ''' + call $(SolutionDir)..\\filecopy.bat $(TargetDir)$(TargetName).pdb $(ProjectDir)%RELATIVE_DIR%\\game\\czero\\dlls\\$(TargetName).pdb + call $(SolutionDir)..\\filecopy.bat $(TargetPath) $(ProjectDir)%RELATIVE_DIR%\\game\\czero\\dlls\\$(TargetFileName)''' + print("cstrike mp.dll also going to czero/mp.dll") + + # Define the post build command as text + post_build_command = f''' + {command} + + ''' + + post_build_command = post_build_command.replace("%PROJECT_OUTPUT%", projectoutput) + post_build_command = post_build_command.replace("%RELATIVE_DIR%", relative_dir) + + # Locate the position to insert the post build command after the node within + insert_after = '' + insert_position = contents.rfind(insert_after) + if insert_position == -1: + print(f"Couldn't find the {insert_after} tag in {file_path}!") + return + + # Insert the post build command into the contents + contents = contents[:insert_position + len(insert_after)] + post_build_command + contents[insert_position + len(insert_after):] + + # Write the updated contents back to the file + with open(file_path, 'w', encoding='utf-8') as f: + f.write(contents) + + + + +def usage(): + print("") + print(" Usage: TODO") + +if __name__ == "__main__": + + print_usage = False + + config = "all" + projectpath = "" + + if len(sys.argv) > 1: + config = sys.argv[1] + + if len(sys.argv) > 1 and not config in valid_configs: + print_usage = True + + if print_usage: + usage() + sys.exit(1) + + if config == "all": + add_post_build_to_all("build-debugoptimized-sln") + add_post_build_to_all("build-release-sln") + else: + add_post_build_to_all(f"build-{config}-sln") + + print("------------------------------------------------------------------") + print("done updating vcxprojs.") \ No newline at end of file diff --git a/devtools/vs_add_launch_config.py b/devtools/vs_add_launch_config.py new file mode 100644 index 0000000..14ad295 --- /dev/null +++ b/devtools/vs_add_launch_config.py @@ -0,0 +1,46 @@ +import os +import sys + +def usage(): + print("\nUsage: vs_add_launch_config.py optional(debug|release)\n") + sys.exit(1) + +# Check if the right number of arguments are provided +if len(sys.argv) < 3: + usage() + +contents = ''' + + + $(ProjectDir)..\..\..\game\%EXECUTABLE%.exe + +developer 2 -dev + $(ProjectDir)..\..\..\game + WindowsLocalDebugger + +''' + +exe = sys.argv[2] + +config = "debugoptimized" +if len(sys.argv) > 3: + config_arg = sys.argv[3] + + if config_arg != "debug": + config = config_arg + +if config != "debugoptimized" and config != "release": + print(f"\nInvalid build config specified: {config}") + usage() + +contents = contents.replace('%BUILD_CONFIG%', config) +contents = contents.replace('%EXECUTABLE%', exe) + +proj = sys.argv[1] + +# project comes from command-line argument +vs_project_path = (f"build-{config}-sln/{proj}") +target_filename = vs_project_path + ".user" + +# Write text to the file +with open(target_filename, 'w') as file: + file.write(contents) \ No newline at end of file diff --git a/dlls/aflock.cpp b/dlls/aflock.cpp index 147dc91..115cf2e 100644 --- a/dlls/aflock.cpp +++ b/dlls/aflock.cpp @@ -111,6 +111,7 @@ public: LINK_ENTITY_TO_CLASS( monster_flyer, CFlockingFlyer ); LINK_ENTITY_TO_CLASS( monster_flyer_flock, CFlockingFlyerFlock ); + TYPEDESCRIPTION CFlockingFlyer::m_SaveData[] = { DEFINE_FIELD( CFlockingFlyer, m_pSquadLeader, FIELD_CLASSPTR ), diff --git a/dlls/agrunt.cpp b/dlls/agrunt.cpp index 411e718..a2177d0 100644 --- a/dlls/agrunt.cpp +++ b/dlls/agrunt.cpp @@ -25,7 +25,7 @@ #include "weapons.h" #include "soundent.h" #include "hornet.h" - + //========================================================= // monster-specific schedule types //========================================================= diff --git a/dlls/airtank.cpp b/dlls/airtank.cpp index d0cfc02..ce2fe41 100644 --- a/dlls/airtank.cpp +++ b/dlls/airtank.cpp @@ -20,7 +20,7 @@ #include "nodes.h" #include "player.h" -class CAirtank : public CGrenade +class CAirtank : public CGrenade { void Spawn( void ); void Precache( void ); diff --git a/dlls/apache.cpp b/dlls/apache.cpp index 693184a..e8583a8 100644 --- a/dlls/apache.cpp +++ b/dlls/apache.cpp @@ -154,7 +154,7 @@ void CApache :: Spawn( void ) void CApache::Precache( void ) { - PRECACHE_MODEL("models/apache.mdl"); + PRECACHE_MODEL("models/apache.mdl"); PRECACHE_SOUND("apache/ap_rotor1.wav"); PRECACHE_SOUND("apache/ap_rotor2.wav"); diff --git a/dlls/barnacle.cpp b/dlls/barnacle.cpp index 18b1f58..b79b6a3 100644 --- a/dlls/barnacle.cpp +++ b/dlls/barnacle.cpp @@ -84,7 +84,7 @@ int CBarnacle :: Classify ( void ) // // Returns number of events handled, 0 if none. //========================================================= -void CBarnacle :: HandleAnimEvent( MonsterEvent_t *pEvent ) +void CBarnacle :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { diff --git a/dlls/barney.cpp b/dlls/barney.cpp index 20b39e0..4722dbd 100644 --- a/dlls/barney.cpp +++ b/dlls/barney.cpp @@ -791,7 +791,7 @@ class CDeadBarney : public CBaseMonster { public: void Spawn( void ); - int Classify ( void ) { return CLASS_PLAYER_ALLY; } + int Classify ( void ) { return CLASS_PLAYER_ALLY; } void KeyValue( KeyValueData *pkvd ); diff --git a/dlls/basemonster.h b/dlls/basemonster.h index bd29f34..638d9fb 100644 --- a/dlls/basemonster.h +++ b/dlls/basemonster.h @@ -108,6 +108,8 @@ public: SCRIPTSTATE m_scriptState; // internal cinematic state CCineMonster *m_pCine; + float m_flLastYawTime; // Last time yaw change was computed + virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); @@ -190,11 +192,8 @@ public: virtual void ScheduleChange( void ) {} // virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); } virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel ); - virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); } - virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); - virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ); - - virtual void SentenceStop( void ); + virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAllowedToSpeak(); } + virtual BOOL IsAllowedToSpeak() { return IsAlive(); } Task_t *GetTask ( void ); virtual MONSTERSTATE GetIdealState ( void ); diff --git a/dlls/bigmomma.cpp b/dlls/bigmomma.cpp index 096676f..c58019c 100644 --- a/dlls/bigmomma.cpp +++ b/dlls/bigmomma.cpp @@ -582,7 +582,7 @@ void CBigMomma :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector ve int CBigMomma :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { - // Don't take any acid damage -- BigMomma's mortar is acid + // Don't take any acid damage -- BigMomma's mortar is acid if ( bitsDamageType & DMG_ACID ) flDamage = 0; diff --git a/dlls/bloater.cpp b/dlls/bloater.cpp index eb0c734..1c4c0a1 100644 --- a/dlls/bloater.cpp +++ b/dlls/bloater.cpp @@ -166,7 +166,7 @@ void CBloater :: AttackSnd( void ) // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= -void CBloater :: HandleAnimEvent( MonsterEvent_t *pEvent ) +void CBloater :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { diff --git a/dlls/bullsquid.cpp b/dlls/bullsquid.cpp index b2a7ead..c9d8a54 100644 --- a/dlls/bullsquid.cpp +++ b/dlls/bullsquid.cpp @@ -44,7 +44,7 @@ enum SCHED_SQUID_SNIFF_AND_EAT, SCHED_SQUID_WALLOW, }; - + //========================================================= // monster-specific tasks //========================================================= diff --git a/dlls/cbase.h b/dlls/cbase.h index 3c7090b..4b7ad65 100644 --- a/dlls/cbase.h +++ b/dlls/cbase.h @@ -60,6 +60,10 @@ CBaseEntity #endif #endif +#if defined EXPORT +#undef EXPORT +#endif + #define EXPORT CBASE_DLLEXPORT extern "C" CBASE_DLLEXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); @@ -105,7 +109,10 @@ typedef void (CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCall #define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace #define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures. +#define CLASS_VEHICLE 14 + class CBaseEntity; +class CBaseToggle; class CBaseMonster; class CBasePlayerItem; class CSquadMonster; @@ -175,6 +182,7 @@ public: virtual int BloodColor( void ) { return DONT_BLEED; } virtual void TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ); virtual BOOL IsTriggered( CBaseEntity *pActivator ) {return TRUE;} + virtual CBaseToggle* MyTogglePointer(void) { return NULL; } virtual CBaseMonster *MyMonsterPointer( void ) { return NULL;} virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL;} virtual int GetToggleState( void ) { return TS_AT_TOP; } @@ -546,6 +554,14 @@ public: void EXPORT AngularMoveDone( void ); BOOL IsLockedByMaster( void ); + virtual CBaseToggle* MyTogglePointer(void) { return this; } + + // monsters use this, but so could buttons for instance + virtual void PlaySentence(const char* pszSentence, float duration, float volume, float attenuation); + virtual void PlayScriptedSentence(const char* pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity* pListener); + virtual void SentenceStop(void); + virtual BOOL IsAllowedToSpeak() { return FALSE; } + static float AxisValue( int flags, const Vector &angles ); static void AxisDir( entvars_t *pev ); static float AxisDelta( int flags, const Vector &angle1, const Vector &angle2 ); @@ -698,13 +714,14 @@ public: virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); - + enum BUTTON_CODE { BUTTON_NOTHING, BUTTON_ACTIVATE, BUTTON_RETURN }; BUTTON_CODE ButtonResponseToTouch( void ); static TYPEDESCRIPTION m_SaveData[]; // Buttons that don't take damage can be IMPULSE used virtual int ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); } + virtual BOOL IsAllowedToSpeak() { return TRUE; } BOOL m_fStayPushed; // button stays pushed in until touched again? BOOL m_fRotating; // a rotating button? default is a sliding button. diff --git a/dlls/client.cpp b/dlls/client.cpp index c1e5fb6..e2f30b7 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -495,8 +495,6 @@ ClientCommand called each time a player uses a "cmd" command ============ */ -extern float g_flWeaponCheat; - // Use CMD_ARGV, CMD_ARGV, and CMD_ARGC to get pointers the character string command. void ClientCommand( edict_t *pEntity ) { @@ -523,7 +521,7 @@ void ClientCommand( edict_t *pEntity ) } else if ( FStrEq(pcmd, "give" ) ) { - if ( g_flWeaponCheat != 0.0) + if ( CVAR_GET_FLOAT( "sv_cheats" ) != 0.0) { int iszItem = ALLOC_STRING( CMD_ARGV(1) ); // Make a copy of the classname GetClassPtr((CBasePlayer *)pev)->GiveNamedItem( STRING(iszItem) ); @@ -537,7 +535,7 @@ void ClientCommand( edict_t *pEntity ) } else if ( FStrEq(pcmd, "fov" ) ) { - if ( g_flWeaponCheat && CMD_ARGC() > 1) + if ( CVAR_GET_FLOAT( "sv_cheats" ) && CMD_ARGC() > 1) { GetClassPtr((CBasePlayer *)pev)->m_iFOV = atoi( CMD_ARGV(1) ); } @@ -607,6 +605,13 @@ void ClientCommand( edict_t *pEntity ) // max total length is 192 ...and we're adding a string below ("Unknown command: %s\n") strncpy( command, pcmd, 127 ); command[127] = '\0'; + // First parse the name and remove any %'s + for ( char *pApersand = command; pApersand != NULL && *pApersand != 0; pApersand++ ) + { + // Replace it with a space + if ( *pApersand == '%' ) + *pApersand = ' '; + } // tell the user they entered an unknown command ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", command ) ); @@ -870,6 +875,7 @@ void ClientPrecache( void ) PRECACHE_SOUND("debris/wood3.wav"); PRECACHE_SOUND("plats/train_use1.wav"); // use a train + PRECACHE_SOUND("plats/vehicle_ignition.wav"); PRECACHE_SOUND("buttons/spark5.wav"); // hit computer texture PRECACHE_SOUND("buttons/spark6.wav"); @@ -1268,6 +1274,12 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h state->health = ent->v.health; } + CBaseEntity *pEntity = static_cast( GET_PRIVATE( ent ) ); + if ( pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE ) + state->eflags |= EFLAG_FLESH_SOUND; + else + state->eflags &= ~EFLAG_FLESH_SOUND; + return 1; } @@ -1622,12 +1634,12 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info ) item->m_iId = II.iId; item->m_iClip = gun->m_iClip; - item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001 ); - item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001 ); - item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001 ); + item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001f ); + item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001f ); + item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001f ); item->m_fInReload = gun->m_fInReload; item->m_fInSpecialReload = gun->m_fInSpecialReload; - item->fuser1 = max( gun->pev->fuser1, -0.001 ); + item->fuser1 = max( gun->pev->fuser1, -0.001f ); item->fuser2 = gun->m_flStartThrow; item->fuser3 = gun->m_flReleaseThrow; item->iuser1 = gun->m_chargeReady; @@ -1635,7 +1647,7 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info ) item->iuser3 = gun->m_fireState; -// item->m_flPumpTime = max( gun->m_flPumpTime, -0.001 ); +// item->m_flPumpTime = max( gun->m_flPumpTime, -0.001f ); } } pPlayerItem = pPlayerItem->m_pNext; diff --git a/dlls/controller.cpp b/dlls/controller.cpp index 34253c0..d04b40e 100644 --- a/dlls/controller.cpp +++ b/dlls/controller.cpp @@ -38,7 +38,7 @@ #define CONTROLLER_FLINCH_DELAY 2 // at most one flinch every n secs -class CController : public CSquadMonster +class CController : public CSquadMonster { public: virtual int Save( CSave &save ); diff --git a/dlls/crowbar.cpp b/dlls/crowbar.cpp index 88d09df..64c08dc 100644 --- a/dlls/crowbar.cpp +++ b/dlls/crowbar.cpp @@ -193,9 +193,12 @@ int CCrowbar::Swing( int fFirst ) } #endif - PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar, - 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, - 0.0, 0, 0.0 ); + if ( fFirst ) + { + PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar, + 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0, + 0.0, 0, 0.0 ); + } if ( tr.flFraction >= 1.0 ) @@ -232,7 +235,9 @@ int CCrowbar::Swing( int fFirst ) ClearMultiDamage( ); - if ( (m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() ) + // JoshA: Changed from < -> <= to fix the full swing logic since client weapon prediction. + // -1.0f + 1.0f = 0.0f. UTIL_WeaponTimeBase is always 0 with client weapon prediction (0 time base vs curtime base) + if ( ( m_flNextPrimaryAttack + 1.0f <= UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() ) { // first swing does full damage pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB ); @@ -307,7 +312,7 @@ int CCrowbar::Swing( int fFirst ) m_flNextPrimaryAttack = GetNextAttackDelay(0.25); SetThink( &CCrowbar::Smack ); - pev->nextthink = UTIL_WeaponTimeBase() + 0.2; + pev->nextthink = gpGlobals->time + 0.2; } diff --git a/dlls/effects.cpp b/dlls/effects.cpp index 602f094..cebe5d9 100644 --- a/dlls/effects.cpp +++ b/dlls/effects.cpp @@ -427,7 +427,7 @@ LINK_ENTITY_TO_CLASS( trip_beam, CTripBeam ); void CTripBeam::Spawn( void ) { CLightning::Spawn(); - SetTouch( &CTripBeam::TriggerTouch ); + SetTouch( TriggerTouch ); pev->solid = SOLID_TRIGGER; RelinkBeam(); } diff --git a/dlls/egon.cpp b/dlls/egon.cpp index c1cdf9a..f9d4269 100644 --- a/dlls/egon.cpp +++ b/dlls/egon.cpp @@ -35,6 +35,10 @@ #define EGON_SWITCH_NARROW_TIME 0.75 // Time it takes to switch fire modes #define EGON_SWITCH_WIDE_TIME 1.5 +#ifndef CLIENT_DLL +extern bool IsBustingGame(); +#endif + enum egon_e { EGON_IDLE1 = 0, EGON_FIDGET1, @@ -51,11 +55,11 @@ enum egon_e { LINK_ENTITY_TO_CLASS( weapon_egon, CEgon ); -void CEgon::Spawn( ) +void CEgon::Spawn() { - Precache( ); + Precache(); m_iId = WEAPON_EGON; - SET_MODEL(ENT(pev), "models/w_egon.mdl"); + SET_MODEL( ENT( pev ), "models/w_egon.mdl" ); m_iDefaultAmmo = EGON_DEFAULT_GIVE; @@ -102,6 +106,7 @@ int CEgon::AddToPlayer( CBasePlayer *pPlayer ) MESSAGE_END(); return TRUE; } + return FALSE; } @@ -155,6 +160,12 @@ BOOL CEgon::HasAmmo( void ) void CEgon::UseAmmo( int count ) { + +#ifndef CLIENT_DLL + if ( IsBustingGame() ) + return; +#endif + if ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= count ) m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= count; else @@ -440,7 +451,9 @@ void CEgon::CreateEffect( void ) m_pSprite->pev->scale = 1.0; m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation ); m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY; - m_pSprite->pev->flags |= FL_SKIPLOCALHOST; + // Josh: This sprite is not predicted o the client, so was missing + // for many years after it got broken in an update. + //m_pSprite->pev->flags |= FL_SKIPLOCALHOST; m_pSprite->pev->owner = m_pPlayer->edict(); if ( m_fireMode == FIRE_WIDE ) @@ -519,7 +532,17 @@ void CEgon::WeaponIdle( void ) m_deployed = TRUE; } +BOOL CEgon::CanHolster( void ) +{ +#ifndef CLIENT_DLL + if ( IsBustingGame() ) + { + return FALSE; + } +#endif + return TRUE; +} void CEgon::EndAttack( void ) { diff --git a/dlls/explode.cpp b/dlls/explode.cpp index 4e5f1c1..845dd8b 100644 --- a/dlls/explode.cpp +++ b/dlls/explode.cpp @@ -32,7 +32,7 @@ class CShower : public CBaseEntity void Think( void ); void Touch( CBaseEntity *pOther ); int ObjectCaps( void ) { return FCAP_DONT_SAVE; } -}; +}; LINK_ENTITY_TO_CLASS( spark_shower, CShower ); diff --git a/dlls/extdll.h b/dlls/extdll.h index d42571b..8fa54a8 100644 --- a/dlls/extdll.h +++ b/dlls/extdll.h @@ -54,9 +54,6 @@ typedef int BOOL; #include #include #include // memset -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) @@ -66,6 +63,10 @@ typedef int BOOL; // Misc C-runtime library headers #include "stdio.h" #include "stdlib.h" +#include "minmax.h" +#ifndef _WIN32 +# define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) +#endif #include "math.h" // Header file containing definition of globalvars_t and entvars_t diff --git a/dlls/flyingmonster.cpp b/dlls/flyingmonster.cpp index 4fae59e..9f82f5f 100644 --- a/dlls/flyingmonster.cpp +++ b/dlls/flyingmonster.cpp @@ -33,7 +33,7 @@ int CFlyingMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vec // ALERT(at_aiconsole, "can't swim out of water\n"); return FALSE; } - + TraceResult tr; UTIL_TraceHull( vecStart + Vector( 0, 0, 32 ), vecEnd + Vector( 0, 0, 32 ), dont_ignore_monsters, large_hull, edict(), &tr ); @@ -87,13 +87,18 @@ void CFlyingMonster :: Stop( void ) } -float CFlyingMonster :: ChangeYaw( int speed ) +float CFlyingMonster :: ChangeYaw( int yawSpeed ) { if ( pev->movetype == MOVETYPE_FLY ) { float diff = FlYawDiff(); float target = 0; + if ( m_flLastZYawTime == 0.f ) + { + m_flLastZYawTime = gpGlobals->time - gpGlobals->frametime; + } + if ( m_IdealActivity != GetStoppedActivity() ) { if ( diff < -20 ) @@ -101,9 +106,18 @@ float CFlyingMonster :: ChangeYaw( int speed ) else if ( diff > 20 ) target = -90; } - pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * gpGlobals->frametime ); + + float delta = gpGlobals->time - m_flLastZYawTime; + m_flLastZYawTime = gpGlobals->time; + + // Clamp delta like the engine does with frametime + if ( delta > 0.25f ) + delta = 0.25f; + + float speed = 220.f * delta; + pev->angles.z = UTIL_Approach( target, pev->angles.z, speed ); } - return CBaseMonster::ChangeYaw( speed ); + return CBaseMonster::ChangeYaw( yawSpeed ); } diff --git a/dlls/flyingmonster.h b/dlls/flyingmonster.h index 85ef61a..73b088c 100644 --- a/dlls/flyingmonster.h +++ b/dlls/flyingmonster.h @@ -25,7 +25,7 @@ public: Activity GetStoppedActivity( void ); void Killed( entvars_t *pevAttacker, int iGib ); void Stop( void ); - float ChangeYaw( int speed ); + float ChangeYaw( int yawSpeed ); void HandleAnimEvent( MonsterEvent_t *pEvent ); void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval ); void Move( float flInterval = 0.1 ); @@ -46,6 +46,7 @@ protected: float m_stopTime; // Last time we stopped (to avoid switching states too soon) float m_momentum; // Weight for desired vs. momentum velocity const char *m_pFlapSound; + float m_flLastZYawTime; // Last frame time Z was changed when yaw was changed }; diff --git a/dlls/func_break.cpp b/dlls/func_break.cpp index fb33522..0e39a2e 100644 --- a/dlls/func_break.cpp +++ b/dlls/func_break.cpp @@ -934,7 +934,11 @@ void CPushable :: Move( CBaseEntity *pOther, int push ) if ( pOther->IsPlayer() ) { - if ( push && !(pevToucher->button & (IN_FORWARD|IN_USE)) ) // Don't push unless the player is pushing forward and NOT use (pull) + // JoshA: Used to check for FORWARD too and logic was inverted + // from comment which seems wrong. + // Fixed to just check for USE being not set for PUSH. + // Should have the right effect. + if ( push && !!(pevToucher->button & IN_USE) ) // Don't push unless the player is not useing (pull) return; playerTouch = 1; } @@ -956,19 +960,39 @@ void CPushable :: Move( CBaseEntity *pOther, int push ) else factor = 0.25; - pev->velocity.x += pevToucher->velocity.x * factor; - pev->velocity.y += pevToucher->velocity.y * factor; + // This used to be added every 'frame', but to be consistent at high fps, + // now act as if it's added at a constant rate with a fudge factor. + extern cvar_t sv_pushable_fixed_tick_fudge; + + if ( !push && sv_pushable_fixed_tick_fudge.value >= 0.0f ) + { + factor *= gpGlobals->frametime * sv_pushable_fixed_tick_fudge.value; + } + + // JoshA: Always apply this if pushing, or if under the player's velocity. + if ( push || ( abs(pev->velocity.x) < abs(pevToucher->velocity.x - pevToucher->velocity.x * factor) ) ) + pev->velocity.x += pevToucher->velocity.x * factor; + if ( push || ( abs(pev->velocity.y) < abs(pevToucher->velocity.y - pevToucher->velocity.y * factor) ) ) + pev->velocity.y += pevToucher->velocity.y * factor; float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y ); - if ( push && (length > MaxSpeed()) ) + if ( length > MaxSpeed() ) { pev->velocity.x = (pev->velocity.x * MaxSpeed() / length ); pev->velocity.y = (pev->velocity.y * MaxSpeed() / length ); } if ( playerTouch ) { - pevToucher->velocity.x = pev->velocity.x; - pevToucher->velocity.y = pev->velocity.y; + // JoshA: Match the player to our pushable's velocity. + // Previously this always happened, but it should only + // happen if the player is pushing (or rather, being pushed.) + // This either stops the player in their tracks or nudges them along. + if ( push ) + { + pevToucher->velocity.x = pev->velocity.x; + pevToucher->velocity.y = pev->velocity.y; + } + if ( (gpGlobals->time - m_soundTime) > 0.7 ) { m_soundTime = gpGlobals->time; diff --git a/dlls/game.cpp b/dlls/game.cpp index 77624bd..6f2db09 100644 --- a/dlls/game.cpp +++ b/dlls/game.cpp @@ -46,6 +46,7 @@ cvar_t mp_chattime = {"mp_chattime","10", FCVAR_SERVER }; // Engine Cvars cvar_t *g_psv_gravity = NULL; cvar_t *g_psv_aim = NULL; +cvar_t *g_psv_allow_autoaim = NULL; cvar_t *g_footsteps = NULL; //CVARS FOR SKILL LEVEL SETTINGS @@ -450,6 +451,10 @@ cvar_t sk_player_leg3 = { "sk_player_leg3","1" }; // END Cvars for Skill Level settings +cvar_t sv_pushable_fixed_tick_fudge = { "sv_pushable_fixed_tick_fudge", "15" }; + +cvar_t sv_busters = { "sv_busters", "0" }; + // Register your console variables here // This gets called one time when the game is initialied void GameDLLInit( void ) @@ -458,6 +463,7 @@ void GameDLLInit( void ) g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" ); g_psv_aim = CVAR_GET_POINTER( "sv_aim" ); + g_psv_allow_autoaim = CVAR_GET_POINTER( "sv_allow_autoaim" ); g_footsteps = CVAR_GET_POINTER( "mp_footsteps" ); CVAR_REGISTER (&displaysoundlist); @@ -484,6 +490,8 @@ void GameDLLInit( void ) CVAR_REGISTER (&mp_chattime); + CVAR_REGISTER( &sv_busters ); + // REGISTER CVARS FOR SKILL LEVEL STUFF // Agrunt CVAR_REGISTER ( &sk_agrunt_health1 );// {"sk_agrunt_health1","0"}; @@ -885,6 +893,8 @@ void GameDLLInit( void ) CVAR_REGISTER ( &sk_player_leg3 ); // END REGISTER CVARS FOR SKILL LEVEL STUFF + CVAR_REGISTER ( &sv_pushable_fixed_tick_fudge ); + SERVER_COMMAND( "exec skill.cfg\n" ); } diff --git a/dlls/game.h b/dlls/game.h index df82f00..93d3f15 100644 --- a/dlls/game.h +++ b/dlls/game.h @@ -40,6 +40,7 @@ extern cvar_t allowmonsters; // Engine Cvars extern cvar_t *g_psv_gravity; extern cvar_t *g_psv_aim; +extern cvar_t *g_psv_allow_autoaim; extern cvar_t *g_footsteps; #endif // GAME_H diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index dd406c0..3fab62a 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -34,6 +34,7 @@ extern int gmsgDeathMsg; // client dll messages extern int gmsgMOTD; int g_teamplay = 0; +extern cvar_t sv_busters; //========================================================= //========================================================= @@ -328,7 +329,13 @@ CGameRules *InstallGameRules( void ) g_teamplay = 1; return new CHalfLifeTeamplay; } - if ((int)gpGlobals->deathmatch == 1) + + if ( sv_busters.value == 1 ) + { + g_teamplay = 0; + return new CMultiplayBusters; + } + else if ((int)gpGlobals->deathmatch == 1) { // vanilla deathmatch g_teamplay = 0; diff --git a/dlls/gamerules.h b/dlls/gamerules.h index 37a0e5f..b327d40 100644 --- a/dlls/gamerules.h +++ b/dlls/gamerules.h @@ -293,6 +293,7 @@ public: virtual BOOL AllowAutoTargetCrosshair( void ); virtual BOOL ClientCommand( CBasePlayer *pPlayer, const char *pcmd ); + virtual void ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer ); // Client kills/scoring virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ); @@ -357,4 +358,32 @@ protected: void SendMOTDToClient( edict_t *client ); }; +//========================================================= +// CMultiplayBusters +// Rules for a multiplayer mode that makes you feel good +//========================================================= +class CMultiplayBusters : public CHalfLifeMultiplay +{ +public: + CMultiplayBusters(); + + virtual void Think( void ); + virtual int IPointsForKill( CBasePlayer* pAttacker, CBasePlayer* pKilled ); + virtual void PlayerKilled( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor ); + virtual void DeathNotice( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor ); + virtual int WeaponShouldRespawn( CBasePlayerItem* pWeapon ); + virtual BOOL CanHavePlayerItem( CBasePlayer* pPlayer, CBasePlayerItem* pWeapon ); + virtual BOOL CanHaveItem( CBasePlayer* pPlayer, CItem* pItem ); + virtual void PlayerGotWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pWeapon ); + virtual void ClientUserInfoChanged( CBasePlayer* pPlayer, char* infobuffer ); + virtual void PlayerSpawn( CBasePlayer* pPlayer ); + + void SetPlayerModel( CBasePlayer* pPlayer ); + +protected: + + float m_flEgonBustingCheckTime = -1.0f; + void CheckForEgons( void ); +}; + extern DLL_GLOBAL CGameRules* g_pGameRules; diff --git a/dlls/gargantua.cpp b/dlls/gargantua.cpp index e8103e2..5e3047e 100644 --- a/dlls/gargantua.cpp +++ b/dlls/gargantua.cpp @@ -12,7 +12,7 @@ * use or distribution of this code by or to any unlicensed person is illegal. * ****/ -#ifndef OEM_BUILD +#ifndef OEM_BUILD //========================================================= // Gargantua diff --git a/dlls/gauss.cpp b/dlls/gauss.cpp index 213ae5d..740c21b 100644 --- a/dlls/gauss.cpp +++ b/dlls/gauss.cpp @@ -171,6 +171,10 @@ void CGauss::PrimaryAttack() void CGauss::SecondaryAttack() { + // JoshA: Sanitize this so it's not total garbage on level transition + // and we end up ear blasting the player! + m_pPlayer->m_flStartCharge = min( m_pPlayer->m_flStartCharge, gpGlobals->time ); + // don't fire underwater if ( m_pPlayer->pev->waterlevel == 3 ) { @@ -308,6 +312,10 @@ void CGauss::SecondaryAttack() void CGauss::StartFire( void ) { float flDamage; + + // JoshA: Sanitize this so it's not total garbage on level transition + // and we end up ear blasting the player! + m_pPlayer->m_flStartCharge = min( m_pPlayer->m_flStartCharge, gpGlobals->time ); UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); Vector vecAiming = gpGlobals->v_forward; @@ -375,7 +383,7 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage ) int fFirstBeam = 1; int nMaxHits = 10; - pentIgnore = ENT( m_pPlayer->pev ); + pentIgnore = m_pPlayer->edict(); #ifdef CLIENT_DLL if ( m_fPrimaryFire == false ) @@ -426,6 +434,13 @@ void CGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage ) if (pEntity->pev->takedamage) { ClearMultiDamage(); + + // if you hurt yourself clear the headshot bit + if (m_pPlayer->pev == pEntity->pev) + { + tr.iHitgroup = 0; + } + pEntity->TraceAttack( m_pPlayer->pev, flDamage, vecDir, &tr, DMG_BULLET ); ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev); } diff --git a/dlls/genericmonster.cpp b/dlls/genericmonster.cpp index 69bb130..bbf954b 100644 --- a/dlls/genericmonster.cpp +++ b/dlls/genericmonster.cpp @@ -20,7 +20,7 @@ #include "cbase.h" #include "monsters.h" #include "schedule.h" - + // For holograms, make them not solid so the player can walk through them #define SF_GENERICMONSTER_NOTSOLID 4 diff --git a/dlls/ggrenade.cpp b/dlls/ggrenade.cpp index 35bf556..42bdf7c 100644 --- a/dlls/ggrenade.cpp +++ b/dlls/ggrenade.cpp @@ -13,7 +13,7 @@ * ****/ /* - + ===== generic grenade.cpp ======================================================== */ @@ -454,7 +454,7 @@ CGrenade * CGrenade :: ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, -void CGrenade :: UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code ) +void CGrenade :: UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code ) { edict_t *pentFind; edict_t *pentOwner; diff --git a/dlls/glock.cpp b/dlls/glock.cpp index 9799c2b..5df88a4 100644 --- a/dlls/glock.cpp +++ b/dlls/glock.cpp @@ -228,13 +228,7 @@ void CGlock::GlockFire( float flSpread , float flCycleTime, BOOL fUseAutoAim ) void CGlock::Reload( void ) { - int iResult; - - if (m_iClip == 0) - iResult = DefaultReload( 17, GLOCK_RELOAD, 1.5 ); - else - iResult = DefaultReload( 18, GLOCK_RELOAD_NOT_EMPTY, 1.5 ); - + int iResult = DefaultReload( GLOCK_MAX_CLIP, m_iClip > 0 ? GLOCK_RELOAD_NOT_EMPTY : GLOCK_RELOAD, 1.5 ); if (iResult) { m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 ); diff --git a/dlls/gman.cpp b/dlls/gman.cpp index 7549fac..0d0365b 100644 --- a/dlls/gman.cpp +++ b/dlls/gman.cpp @@ -4,7 +4,7 @@ * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. +* All Rights Reserved. * * This source code contains proprietary and confidential information of * Valve LLC and its suppliers. Access to this code is restricted to diff --git a/dlls/h_cine.cpp b/dlls/h_cine.cpp index d13aba6..d606bd8 100644 --- a/dlls/h_cine.cpp +++ b/dlls/h_cine.cpp @@ -1,6 +1,6 @@ /*** * -* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. diff --git a/dlls/h_cycler.cpp b/dlls/h_cycler.cpp index 4449805..6a182c8 100644 --- a/dlls/h_cycler.cpp +++ b/dlls/h_cycler.cpp @@ -1,6 +1,6 @@ /*** * -* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. @@ -45,6 +45,7 @@ public: // Don't treat as a live target virtual BOOL IsAlive( void ) { return FALSE; } + virtual BOOL IsAllowedToSpeak() { return TRUE; } virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); diff --git a/dlls/handgrenade.cpp b/dlls/handgrenade.cpp index a854763..55903e9 100644 --- a/dlls/handgrenade.cpp +++ b/dlls/handgrenade.cpp @@ -130,7 +130,7 @@ void CHandGrenade::WeaponIdle( void ) if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() ) return; - + if ( m_flStartThrow ) { Vector angThrow = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; @@ -140,9 +140,10 @@ void CHandGrenade::WeaponIdle( void ) else angThrow.x = -10 + angThrow.x * ( ( 90 + 10 ) / 90.0 ); - float flVel = ( 90 - angThrow.x ) * 4; - if ( flVel > 500 ) - flVel = 500; + static float flMultiplier = 6.5f; + float flVel = ( 90 - angThrow.x ) * flMultiplier; + if ( flVel > 1000 ) + flVel = 1000; UTIL_MakeVectors( angThrow ); diff --git a/dlls/hassassin.cpp b/dlls/hassassin.cpp index 0ab2591..08ab702 100644 --- a/dlls/hassassin.cpp +++ b/dlls/hassassin.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -728,12 +728,12 @@ void CHAssassin :: RunAI( void ) EMIT_SOUND (ENT(pev), CHAN_BODY, "debris/beamstart1.wav", 0.2, ATTN_NORM ); } - pev->renderamt = max( pev->renderamt - 50, m_iTargetRanderamt ); + pev->renderamt = max( pev->renderamt - 50, m_iTargetRanderamt ); pev->rendermode = kRenderTransTexture; } else if (pev->renderamt < m_iTargetRanderamt) { - pev->renderamt = min( pev->renderamt + 50, m_iTargetRanderamt ); + pev->renderamt = min( pev->renderamt + 50, m_iTargetRanderamt ); if (pev->renderamt == 255) pev->rendermode = kRenderNormal; } diff --git a/dlls/headcrab.cpp b/dlls/headcrab.cpp index 41f72fa..9988c3b 100644 --- a/dlls/headcrab.cpp +++ b/dlls/headcrab.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * diff --git a/dlls/hgrunt.cpp b/dlls/hgrunt.cpp index e58bbef..62ec743 100644 --- a/dlls/hgrunt.cpp +++ b/dlls/hgrunt.cpp @@ -2377,7 +2377,7 @@ Schedule_t* CHGrunt :: GetScheduleOfType ( int Type ) // repelling down a line. //========================================================= -class CHGruntRepel : public CBaseMonster +class CHGruntRepel : public CBaseMonster { public: void Spawn( void ); diff --git a/dlls/hornet.cpp b/dlls/hornet.cpp index 7efeaa6..7cfd9c7 100644 --- a/dlls/hornet.cpp +++ b/dlls/hornet.cpp @@ -188,7 +188,7 @@ void CHornet :: StartDart ( void ) pev->nextthink = gpGlobals->time + 4; } -void CHornet::IgniteTrail( void ) +void CHornet::IgniteTrail( void ) { /* diff --git a/dlls/hornetgun.cpp b/dlls/hornetgun.cpp index a23aa41..ce92f35 100644 --- a/dlls/hornetgun.cpp +++ b/dlls/hornetgun.cpp @@ -24,6 +24,14 @@ #include "hornet.h" #include "gamerules.h" +static float GetRechargeTime() +{ + if (gpGlobals->maxClients > 1) + { + return 0.3f; + } + return 0.5f; +} enum hgun_e { HGUN_IDLE1 = 0, @@ -144,7 +152,7 @@ void CHgun::PrimaryAttack() CBaseEntity *pHornet = CBaseEntity::Create( "hornet", m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -12, m_pPlayer->pev->v_angle, m_pPlayer->edict() ); pHornet->pev->velocity = gpGlobals->v_forward * 300; - m_flRechargeTime = gpGlobals->time + 0.5; + m_flRechargeTime = gpGlobals->time + GetRechargeTime(); #endif m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; @@ -173,6 +181,10 @@ void CHgun::PrimaryAttack() { m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25; } + if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) + { + m_flNextPrimaryAttack += GetRechargeTime(); + } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); } @@ -237,7 +249,7 @@ void CHgun::SecondaryAttack( void ) pHornet->SetThink( &CHornet::StartDart ); - m_flRechargeTime = gpGlobals->time + 0.5; + m_flRechargeTime = gpGlobals->time + GetRechargeTime(); #endif int flags; @@ -257,7 +269,14 @@ void CHgun::SecondaryAttack( void ) // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1; + if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) + { + m_flRechargeTime = gpGlobals->time + 0.5; + m_flNextSecondaryAttack += 0.5; + m_flNextPrimaryAttack += 0.5; + } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); } @@ -270,7 +289,7 @@ void CHgun::Reload( void ) while (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < HORNET_MAX_CARRY && m_flRechargeTime < gpGlobals->time) { m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]++; - m_flRechargeTime += 0.5; + m_flRechargeTime += GetRechargeTime(); } } diff --git a/dlls/houndeye.cpp b/dlls/houndeye.cpp index 9b7cbe0..0b7c780 100644 --- a/dlls/houndeye.cpp +++ b/dlls/houndeye.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * diff --git a/dlls/ichthyosaur.cpp b/dlls/ichthyosaur.cpp index 0a7ade5..aeb03fe 100644 --- a/dlls/ichthyosaur.cpp +++ b/dlls/ichthyosaur.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -78,7 +78,7 @@ public: BOOL CheckMeleeAttack1 ( float flDot, float flDist ); BOOL CheckRangeAttack1 ( float flDot, float flDist ); - float ChangeYaw( int speed ); + float ChangeYaw( int yawSpeed ); Activity GetStoppedActivity( void ); void Move( float flInterval ); @@ -90,7 +90,7 @@ public: float VectorToPitch( const Vector &vec); float FlPitchDiff( void ); - float ChangePitch( int speed ); + float ChangePitch( int pitchSpeed ); Vector m_SaveVelocity; float m_idealDist; @@ -108,6 +108,9 @@ public: float m_flNextAlert; + float m_flLastPitchTime; // Last frame time pitch was changed + float m_flLastZYawTime; // Last frame time Z was changed when yaw was changed + static const char *pIdleSounds[]; static const char *pAlertSounds[]; static const char *pAttackSounds[]; @@ -795,12 +798,18 @@ float CIchthyosaur::FlPitchDiff( void ) return flPitchDiff; } -float CIchthyosaur :: ChangePitch( int speed ) +float CIchthyosaur :: ChangePitch( int pitchSpeed ) { if ( pev->movetype == MOVETYPE_FLY ) { float diff = FlPitchDiff(); float target = 0; + + if ( m_flLastPitchTime == 0.f ) + { + m_flLastPitchTime = gpGlobals->time - gpGlobals->frametime; + } + if ( m_IdealActivity != GetStoppedActivity() ) { if (diff < -20) @@ -808,18 +817,32 @@ float CIchthyosaur :: ChangePitch( int speed ) else if (diff > 20) target = -45; } - pev->angles.x = UTIL_Approach(target, pev->angles.x, 220.0 * 0.1 ); + + float delta = gpGlobals->time - m_flLastPitchTime; + m_flLastPitchTime = gpGlobals->time; + + // Clamp delta like the engine does with frametime + if ( delta > 0.25f ) + delta = 0.25f; + + float speed = 220.f * delta; + pev->angles.x = UTIL_Approach(target, pev->angles.x, speed ); } return 0; } -float CIchthyosaur::ChangeYaw( int speed ) +float CIchthyosaur::ChangeYaw( int yawSpeed ) { if ( pev->movetype == MOVETYPE_FLY ) { float diff = FlYawDiff(); float target = 0; + if ( m_flLastZYawTime == 0.f ) + { + m_flLastZYawTime = gpGlobals->time - gpGlobals->frametime; + } + if ( m_IdealActivity != GetStoppedActivity() ) { if ( diff < -20 ) @@ -827,9 +850,18 @@ float CIchthyosaur::ChangeYaw( int speed ) else if ( diff > 20 ) target = -20; } - pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * 0.1 ); + + float delta = gpGlobals->time - m_flLastZYawTime; + m_flLastZYawTime = gpGlobals->time; + + // Clamp delta like the engine does with frametime + if ( delta > 0.25f ) + delta = 0.25f; + + float speed = 220.f * delta; + pev->angles.z = UTIL_Approach( target, pev->angles.z, speed ); } - return CFlyingMonster::ChangeYaw( speed ); + return CFlyingMonster::ChangeYaw( yawSpeed ); } diff --git a/dlls/islave.cpp b/dlls/islave.cpp index 53e6446..3cc2daf 100644 --- a/dlls/islave.cpp +++ b/dlls/islave.cpp @@ -12,7 +12,7 @@ * use or distribution of this code by or to any unlicensed person is illegal. * ****/ -//========================================================= +//========================================================= // Alien slave monster //========================================================= diff --git a/dlls/items.cpp b/dlls/items.cpp index 00825a8..988d3cb 100644 --- a/dlls/items.cpp +++ b/dlls/items.cpp @@ -229,7 +229,7 @@ class CItemBattery : public CItem char szcharge[64]; pPlayer->pev->armorvalue += gSkillData.batteryCapacity; - pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY); + pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY); EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); diff --git a/dlls/leech.cpp b/dlls/leech.cpp index 9201a9d..bd2d209 100644 --- a/dlls/leech.cpp +++ b/dlls/leech.cpp @@ -557,7 +557,7 @@ void CLeech::UpdateMotion( void ) void CLeech::SwimThink( void ) { TraceResult tr; - float flLeftSide; + float flLeftSide; float flRightSide; float targetSpeed; float targetYaw = 0; diff --git a/dlls/maprules.cpp b/dlls/maprules.cpp index c57905a..785bec6 100644 --- a/dlls/maprules.cpp +++ b/dlls/maprules.cpp @@ -799,7 +799,7 @@ void CGamePlayerEquip::KeyValue( KeyValueData *pkvd ) { char tmp[128]; - UTIL_StripToken( pkvd->szKeyName, tmp ); + UTIL_StripToken( pkvd->szKeyName, tmp, sizeof( tmp ) ); m_weaponNames[i] = ALLOC_STRING(tmp); m_weaponCount[i] = atoi(pkvd->szValue); diff --git a/dlls/meson.build b/dlls/meson.build new file mode 100644 index 0000000..458ce1b --- /dev/null +++ b/dlls/meson.build @@ -0,0 +1,183 @@ +hl_server_src = [ + 'aflock.cpp', + 'agrunt.cpp', + 'airtank.cpp', + 'animating.cpp', + 'animation.cpp', + 'apache.cpp', + 'barnacle.cpp', + 'barney.cpp', + 'bigmomma.cpp', + 'bloater.cpp', + 'bmodels.cpp', + 'bullsquid.cpp', + 'buttons.cpp', + 'cbase.cpp', + 'client.cpp', + 'combat.cpp', + 'controller.cpp', + 'crossbow.cpp', + 'crowbar.cpp', + 'defaultai.cpp', + 'doors.cpp', + 'effects.cpp', + 'egon.cpp', + 'explode.cpp', + 'flyingmonster.cpp', + 'func_break.cpp', + 'func_tank.cpp', + 'game.cpp', + 'gamerules.cpp', + 'gargantua.cpp', + 'gauss.cpp', + 'genericmonster.cpp', + 'ggrenade.cpp', + 'globals.cpp', + 'gman.cpp', + 'h_ai.cpp', + 'h_battery.cpp', + 'h_cine.cpp', + 'h_cycler.cpp', + 'h_export.cpp', + 'handgrenade.cpp', + 'hassassin.cpp', + 'headcrab.cpp', + 'healthkit.cpp', + 'hgrunt.cpp', + 'wpn_shared/hl_wpn_glock.cpp', + 'hornet.cpp', + 'hornetgun.cpp', + 'houndeye.cpp', + 'ichthyosaur.cpp', + 'islave.cpp', + 'items.cpp', + 'leech.cpp', + 'lights.cpp', + 'maprules.cpp', + 'monstermaker.cpp', + 'monsters.cpp', + 'monsterstate.cpp', + 'mortar.cpp', + 'mp5.cpp', + 'multiplay_gamerules.cpp', + 'nihilanth.cpp', + 'nodes.cpp', + 'observer.cpp', + 'osprey.cpp', + 'pathcorner.cpp', + 'plane.cpp', + 'plats.cpp', + 'player.cpp', + '../pm_shared/pm_debug.c', + '../pm_shared/pm_math.c', + '../pm_shared/pm_shared.c', + 'python.cpp', + 'rat.cpp', + 'roach.cpp', + 'rpg.cpp', + 'satchel.cpp', + 'schedule.cpp', + 'scientist.cpp', + 'scripted.cpp', + 'shotgun.cpp', + 'singleplay_gamerules.cpp', + 'skill.cpp', + 'sound.cpp', + 'soundent.cpp', + 'spectator.cpp', + 'squadmonster.cpp', + 'squeakgrenade.cpp', + 'subs.cpp', + 'talkmonster.cpp', + 'teamplay_gamerules.cpp', + 'tempmonster.cpp', + 'tentacle.cpp', + 'triggers.cpp', + 'tripmine.cpp', + 'turret.cpp', + 'util.cpp', + '../game_shared/voice_gamemgr.cpp', + 'weapons.cpp', + 'world.cpp', + 'xen.cpp', + 'zombie.cpp', + 'activity.h', + 'activitymap.h', + 'animation.h', + 'basemonster.h', + 'cbase.h', + 'cdll_dll.h', + 'client.h', + 'decals.h', + 'defaultai.h', + 'doors.h', + 'effects.h', + '../engine/eiface.h', + 'enginecallback.h', + 'explode.h', + 'extdll.h', + 'flyingmonster.h', + 'func_break.h', + 'gamerules.h', + 'hornet.h', + 'items.h', + 'monsterevent.h', + 'monsters.h', + 'nodes.h', + 'plane.h', + 'player.h', + '../pm_shared/pm_debug.h', + '../pm_shared/pm_defs.h', + '../pm_shared/pm_info.h', + '../pm_shared/pm_materials.h', + '../pm_shared/pm_movevars.h', + '../pm_shared/pm_shared.h', + 'saverestore.h', + 'schedule.h', + 'scripted.h', + 'scriptevent.h', + 'skill.h', + 'soundent.h', + 'spectator.h', + 'squadmonster.h', + 'talkmonster.h', + 'teamplay_gamerules.h', + 'trains.h', + 'util.h', + 'vector.h', + 'weapons.h', + 'vehicle.cpp', +] + +hl_server_defines = [ + '-DVOXEL', + '-DQUAKE2', + '-DCLIENT_WEAPONS', + '-DVALVE_DLL', +] + +hl_server_includes = include_directories([ + '.', + '../engine', + '../pm_shared', + '../game_shared', +]) + +install_dir = '/valve/dlls' +target_name = 'hl' +hl_server_lib = shared_library(target_name, hl_server_src, + cpp_args : hl_server_defines, + c_args : hl_server_defines, + include_directories : [ hl_server_includes, goldsrc_includes ], + vs_module_defs : 'hl.def', + install : true, + install_dir : output_dir + install_dir, +) + +hl_server_dep = declare_dependency( + link_with : [ hl_server_lib ], +) + +cmd = join_paths(meson.current_build_dir(), '..\..\devtools\meson_set_outdir.bat') +cs = run_command(cmd, [target_name, meson.current_build_dir(), install_dir], check: false) +message(cs.stdout()) \ No newline at end of file diff --git a/dlls/monstermaker.cpp b/dlls/monstermaker.cpp index 8fa7e44..3681178 100644 --- a/dlls/monstermaker.cpp +++ b/dlls/monstermaker.cpp @@ -31,7 +31,7 @@ //========================================================= // MonsterMaker - this ent creates monsters during the game. //========================================================= -class CMonsterMaker : public CBaseMonster +class CMonsterMaker : public CBaseMonster { public: void Spawn( void ); diff --git a/dlls/monsters.cpp b/dlls/monsters.cpp index 7395c45..19e0e23 100644 --- a/dlls/monsters.cpp +++ b/dlls/monsters.cpp @@ -1989,7 +1989,7 @@ void CBaseMonster::MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, f while (flTotal > 0.001) { // don't walk more than 16 units or stairs stop working - flStep = min( 16.0, flTotal ); + flStep = min( 16.0f, flTotal ); UTIL_MoveToOrigin ( ENT(pev), m_Route[ m_iRouteIndex ].vecLocation, flStep, MOVE_NORMAL ); flTotal -= flStep; } @@ -2537,7 +2537,19 @@ float CBaseMonster::ChangeYaw ( int yawSpeed ) ideal = pev->ideal_yaw; if (current != ideal) { - speed = (float)yawSpeed * gpGlobals->frametime * 10; + if ( m_flLastYawTime == 0.f ) + { + m_flLastYawTime = gpGlobals->time - gpGlobals->frametime; + } + + float delta = gpGlobals->time - m_flLastYawTime; + m_flLastYawTime = gpGlobals->time; + + // Clamp delta like the engine does with frametime + if ( delta > 0.25f ) + delta = 0.25f; + + speed = (float)yawSpeed * delta * 2; move = ideal - current; if (ideal > current) @@ -2561,7 +2573,7 @@ float CBaseMonster::ChangeYaw ( int yawSpeed ) if (move < -speed) move = -speed; } - + pev->angles.y = UTIL_AngleMod (current + move); // turn head in desired direction only if they have a turnable head @@ -3231,30 +3243,6 @@ BOOL CBaseMonster :: FCanActiveIdle ( void ) } -void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) -{ - if ( pszSentence && IsAlive() ) - { - if ( pszSentence[0] == '!' ) - EMIT_SOUND_DYN( edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, PITCH_NORM ); - else - SENTENCEG_PlayRndSz( edict(), pszSentence, volume, attenuation, 0, PITCH_NORM ); - } -} - - -void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) -{ - PlaySentence( pszSentence, duration, volume, attenuation ); -} - - -void CBaseMonster::SentenceStop( void ) -{ - EMIT_SOUND( edict(), CHAN_VOICE, "common/null.wav", 1.0, ATTN_IDLE ); -} - - void CBaseMonster::CorpseFallThink( void ) { if ( pev->flags & FL_ONGROUND ) diff --git a/dlls/mortar.cpp b/dlls/mortar.cpp index d275f38..a1ae794 100644 --- a/dlls/mortar.cpp +++ b/dlls/mortar.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * diff --git a/dlls/mp5.cpp b/dlls/mp5.cpp index 6771f82..b0f2ae8 100644 --- a/dlls/mp5.cpp +++ b/dlls/mp5.cpp @@ -55,7 +55,7 @@ void CMP5::Spawn( ) SET_MODEL(ENT(pev), "models/w_9mmAR.mdl"); m_iId = WEAPON_MP5; - m_iDefaultAmmo = MP5_DEFAULT_GIVE; + m_iDefaultAmmo = gpGlobals->maxClients > 1 ? MP5_MAX_CLIP : MP5_DEFAULT_GIVE; FallInit();// get ready to fall down. } @@ -158,9 +158,9 @@ void CMP5::PrimaryAttack() Vector vecDir; #ifdef CLIENT_DLL - if ( !bIsMultiplayer() ) + if ( bIsMultiplayer() ) #else - if ( !g_pGameRules->IsMultiplayer() ) + if ( g_pGameRules->IsMultiplayer() ) #endif { // optimized multiplayer. Widened to make it easier to hit a moving player diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index 9362067..b26fe66 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -27,6 +27,7 @@ #include "items.h" #include "voice_gamemgr.h" #include "hltv.h" +#include "trains.h" #if !defined ( _WIN32 ) #include @@ -47,6 +48,15 @@ extern int g_teamplay; float g_flIntermissionStartTime = 0; + +// longest the intermission can last, in seconds +#define MAX_INTERMISSION_TIME 120 + +extern cvar_t timeleft, fragsleft, sv_busters; + +extern cvar_t mp_chattime; + + CVoiceGameMgr g_VoiceGameMgr; class CMultiplayGameMgrHelper : public IVoiceGameMgrHelper @@ -135,7 +145,7 @@ void CHalfLifeMultiplay::RefreshSkillData( void ) gSkillData.plrDmg9MM = 12; // 357 Round - gSkillData.plrDmg357 = 40; + gSkillData.plrDmg357 = 50; // MP5 Round gSkillData.plrDmgMP5 = 12; @@ -169,19 +179,12 @@ void CHalfLifeMultiplay::RefreshSkillData( void ) gSkillData.plrDmgHornet = 10; } -// longest the intermission can last, in seconds -#define MAX_INTERMISSION_TIME 120 - -extern cvar_t timeleft, fragsleft; - -extern cvar_t mp_chattime; - //========================================================= //========================================================= void CHalfLifeMultiplay :: Think ( void ) { g_VoiceGameMgr.Update(gpGlobals->frametime); - + ///// Check game rules ///// static int last_frags; static int last_time; @@ -306,6 +309,18 @@ BOOL CHalfLifeMultiplay::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerI return TRUE; } + if ( pPlayer->m_iAutoWepSwitch == 0 ) + { + return FALSE; + } + else if ( pPlayer->m_iAutoWepSwitch == 2 ) + { + if ( pPlayer->m_afButtonLast & ( IN_ATTACK | IN_ATTACK2 ) ) + { + return FALSE; + } + } + if ( !pPlayer->m_pActiveItem->CanHolster() ) { // can't put away the active item. @@ -320,71 +335,11 @@ BOOL CHalfLifeMultiplay::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerI return FALSE; } +extern BOOL HLGetNextBestWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pCurrentWeapon ); + BOOL CHalfLifeMultiplay :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) { - - CBasePlayerItem *pCheck; - CBasePlayerItem *pBest;// this will be used in the event that we don't find a weapon in the same category. - int iBestWeight; - int i; - - iBestWeight = -1;// no weapon lower than -1 can be autoswitched to - pBest = NULL; - - if ( !pCurrentWeapon->CanHolster() ) - { - // can't put this gun away right now, so can't switch. - return FALSE; - } - - for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ ) - { - pCheck = pPlayer->m_rgpPlayerItems[ i ]; - - while ( pCheck ) - { - if ( pCheck->iWeight() > -1 && pCheck->iWeight() == pCurrentWeapon->iWeight() && pCheck != pCurrentWeapon ) - { - // this weapon is from the same category. - if ( pCheck->CanDeploy() ) - { - if ( pPlayer->SwitchWeapon( pCheck ) ) - { - return TRUE; - } - } - } - else if ( pCheck->iWeight() > iBestWeight && pCheck != pCurrentWeapon )// don't reselect the weapon we're trying to get rid of - { - //ALERT ( at_console, "Considering %s\n", STRING( pCheck->pev->classname ) ); - // we keep updating the 'best' weapon just in case we can't find a weapon of the same weight - // that the player was using. This will end up leaving the player with his heaviest-weighted - // weapon. - if ( pCheck->CanDeploy() ) - { - // if this weapon is useable, flag it as the best - iBestWeight = pCheck->iWeight(); - pBest = pCheck; - } - } - - pCheck = pCheck->m_pNext; - } - } - - // if we make it here, we've checked all the weapons and found no useable - // weapon in the same catagory as the current weapon. - - // if pBest is null, we didn't find ANYTHING. Shouldn't be possible- should always - // at least get the crowbar, but ya never know. - if ( !pBest ) - { - return FALSE; - } - - pPlayer->SwitchWeapon( pBest ); - - return TRUE; + return HLGetNextBestWeapon( pPlayer, pCurrentWeapon ); } //========================================================= @@ -553,6 +508,9 @@ void CHalfLifeMultiplay :: PlayerSpawn( CBasePlayer *pPlayer ) BOOL addDefault; CBaseEntity *pWeaponEntity = NULL; + int iAutoWepSwitch = pPlayer->m_iAutoWepSwitch; + pPlayer->m_iAutoWepSwitch = 1; + pPlayer->pev->weapons |= (1<GiveNamedItem( "weapon_9mmhandgun" ); pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads } + + pPlayer->m_iAutoWepSwitch = iAutoWepSwitch; } //========================================================= @@ -605,16 +565,27 @@ int CHalfLifeMultiplay :: IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *p //========================================================= void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) { + CBasePlayer* peKiller = NULL; + CBaseEntity* ktmp = CBaseEntity::Instance( pKiller ); + if ( ktmp && ( ktmp->Classify() == CLASS_PLAYER ) ) + peKiller = (CBasePlayer*)ktmp; + else if ( ktmp && ( ktmp->Classify() == CLASS_VEHICLE ) ) + { + CBasePlayer* pDriver = ( (CFuncVehicle*)ktmp )->m_pDriver; + if ( pDriver != NULL ) + { + peKiller = pDriver; + ktmp = pDriver; + pKiller = pDriver->pev; + } + } + DeathNotice( pVictim, pKiller, pInflictor ); pVictim->m_iDeaths += 1; - FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 ); - CBasePlayer *peKiller = NULL; - CBaseEntity *ktmp = CBaseEntity::Instance( pKiller ); - if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) ) - peKiller = (CBasePlayer*)ktmp; + if ( pVictim->pev == pKiller ) { // killed self @@ -819,6 +790,7 @@ void CHalfLifeMultiplay::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, WRITE_LONG( 7 | DRC_FLAG_DRAMATIC); // eventflags (priority and flags) MESSAGE_END(); + // Print a standard message // TODO: make this go direct to console return; // just remove for now @@ -1332,7 +1304,8 @@ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle ) if ( strlen( com_token ) <= 0 ) break; - strcpy( szMap, com_token ); + strncpy( szMap, com_token, sizeof( szMap ) ); + szMap[ sizeof( szMap ) - 1 ] = '\0'; // Any more tokens on this line? if ( COM_TokenWaiting( pFileList ) ) @@ -1341,7 +1314,8 @@ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle ) if ( strlen( com_token ) > 0 ) { hasbuffer = 1; - strcpy( szBuffer, com_token ); + strncpy( szBuffer, com_token, sizeof( szBuffer ) ); + szBuffer[ sizeof( szBuffer ) - 1 ] = '\0'; } } @@ -1689,4 +1663,291 @@ void CHalfLifeMultiplay :: SendMOTDToClient( edict_t *client ) FREE_FILE( aFileList ); } +void CHalfLifeMultiplay :: ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer ) +{ + // Set preferences + pPlayer->SetPrefsFromUserinfo( infobuffer ); +} +//========================================================= +//========================================================= +// Busters Gamerules +//========================================================= +//========================================================= + +#define EGON_BUSTING_TIME 10 + +bool IsBustingGame() +{ + return sv_busters.value == 1; +} + +bool IsPlayerBusting( CBaseEntity* pPlayer ) +{ + if ( !pPlayer || !pPlayer->IsPlayer() || !IsBustingGame() ) + return FALSE; + + return ( (CBasePlayer*)pPlayer )->HasPlayerItemFromID( WEAPON_EGON ); +} + +BOOL BustingCanHaveItem( CBasePlayer* pPlayer, CBaseEntity* pItem ) +{ + BOOL bIsWeaponOrAmmo = FALSE; + + if ( strstr( STRING( pItem->pev->classname ), "weapon_" ) || strstr( STRING( pItem->pev->classname ), "ammo_" ) ) + { + bIsWeaponOrAmmo = TRUE; + } + + //Busting players can't have ammo nor weapons + if ( IsPlayerBusting( pPlayer ) && bIsWeaponOrAmmo ) + return FALSE; + + return TRUE; +} + +//========================================================= +CMultiplayBusters::CMultiplayBusters() +{ + m_flEgonBustingCheckTime = -1; +} + +//========================================================= +void CMultiplayBusters::Think() +{ + CheckForEgons(); + + CHalfLifeMultiplay::Think(); +} + +//========================================================= +int CMultiplayBusters::IPointsForKill( CBasePlayer* pAttacker, CBasePlayer* pKilled ) +{ + //If the attacker is busting, they get a point per kill + if ( IsPlayerBusting( pAttacker ) ) + return 1; + + //If the victim is busting, then the attacker gets a point + if ( IsPlayerBusting( pKilled ) ) + return 2; + + return 0; +} + +//========================================================= +void CMultiplayBusters::PlayerKilled( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pInflictor ) +{ + if ( IsPlayerBusting( pVictim ) ) + { + UTIL_ClientPrintAll( HUD_PRINTCENTER, "The Buster is dead!!" ); + + //Reset egon check time + m_flEgonBustingCheckTime = -1; + + CBasePlayer *peKiller = NULL; + CBaseEntity *ktmp = CBaseEntity::Instance( pKiller ); + + if ( ktmp && ( ktmp->Classify() == CLASS_PLAYER ) ) + { + peKiller = (CBasePlayer*)ktmp; + } + else if ( ktmp && ( ktmp->Classify() == CLASS_VEHICLE ) ) + { + CBasePlayer *pDriver = ( (CFuncVehicle*)ktmp )->m_pDriver; + + if ( pDriver != NULL ) + { + peKiller = pDriver; + ktmp = pDriver; + pKiller = pDriver->pev; + } + } + + if ( peKiller ) + { + UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s has has killed the Buster!\n", STRING( (CBasePlayer*)peKiller->pev->netname ) ) ); + } + + pVictim->pev->renderfx = kRenderFxNone; + pVictim->pev->rendercolor = g_vecZero; + //pVictim->pev->effects &= ~EF_BRIGHTFIELD; + } + + CHalfLifeMultiplay::PlayerKilled( pVictim, pKiller, pInflictor ); +} + +//========================================================= +void CMultiplayBusters::DeathNotice( CBasePlayer* pVictim, entvars_t* pKiller, entvars_t* pevInflictor ) +{ + //Only death notices that the Buster was involved in in Busting game mode + if ( !IsPlayerBusting( pVictim ) && !IsPlayerBusting( CBaseEntity::Instance( pKiller ) ) ) + return; + + CHalfLifeMultiplay::DeathNotice( pVictim, pKiller, pevInflictor ); +} + +//========================================================= +int CMultiplayBusters::WeaponShouldRespawn( CBasePlayerItem* pWeapon ) +{ + if ( pWeapon->m_iId == WEAPON_EGON ) + return GR_WEAPON_RESPAWN_NO; + + return CHalfLifeMultiplay::WeaponShouldRespawn( pWeapon ); +} + + +//========================================================= +// CheckForEgons: +//Check to see if any player has an egon +//If they don't then get the lowest player on the scoreboard and give them one +//Then check to see if any weapon boxes out there has an egon, and delete it +//========================================================= +void CMultiplayBusters::CheckForEgons() +{ + if ( m_flEgonBustingCheckTime <= 0.0f ) + { + m_flEgonBustingCheckTime = gpGlobals->time + EGON_BUSTING_TIME; + return; + } + + if ( m_flEgonBustingCheckTime <= gpGlobals->time ) + { + m_flEgonBustingCheckTime = -1.0f; + + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer* pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i ); + + //Someone is busting, no need to continue + if ( IsPlayerBusting( pPlayer ) ) + return; + } + + int bBestFrags = 9999; + CBasePlayer* pBestPlayer = NULL; + + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer* pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i ); + + if ( pPlayer && pPlayer->pev->frags <= bBestFrags ) + { + bBestFrags = pPlayer->pev->frags; + pBestPlayer = pPlayer; + } + } + + if ( pBestPlayer ) + { + pBestPlayer->GiveNamedItem( "weapon_egon" ); + + CBaseEntity* pEntity = NULL; + + //Find a weaponbox that includes an Egon, then destroy it + while ( ( pEntity = UTIL_FindEntityByClassname( pEntity, "weaponbox" ) ) != NULL ) + { + CWeaponBox* pWeaponBox = (CWeaponBox*)pEntity; + + if ( pWeaponBox ) + { + CBasePlayerItem* pWeapon; + + for ( int i = 0; i < MAX_ITEM_TYPES; i++ ) + { + pWeapon = pWeaponBox->m_rgpPlayerItems[i]; + + while ( pWeapon ) + { + //There you are, bye box + if ( pWeapon->m_iId == WEAPON_EGON ) + { + pWeaponBox->Kill(); + break; + } + + pWeapon = pWeapon->m_pNext; + } + } + } + } + } + } +} + +//========================================================= +BOOL CMultiplayBusters::CanHavePlayerItem( CBasePlayer* pPlayer, CBasePlayerItem* pItem ) +{ + //Buster cannot have more weapons nor ammo + if ( BustingCanHaveItem( pPlayer, pItem ) == FALSE ) + { + return FALSE; + } + + return CHalfLifeMultiplay::CanHavePlayerItem( pPlayer, pItem ); +} + +//========================================================= +BOOL CMultiplayBusters::CanHaveItem( CBasePlayer* pPlayer, CItem* pItem ) +{ + //Buster cannot have more weapons nor ammo + if (BustingCanHaveItem( pPlayer, pItem ) == FALSE ) + { + return FALSE; + } + + return CHalfLifeMultiplay::CanHaveItem( pPlayer, pItem ); +} + +//========================================================= +void CMultiplayBusters::PlayerGotWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pWeapon ) +{ + if ( pWeapon->m_iId == WEAPON_EGON ) + { + pPlayer->RemoveAllItems( false ); + + UTIL_ClientPrintAll( HUD_PRINTCENTER, "Long live the new Buster!" ); + UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s is busting!\n", STRING( (CBasePlayer*)pPlayer->pev->netname ) ) ); + + SetPlayerModel( pPlayer ); + + pPlayer->pev->health = pPlayer->pev->max_health; + pPlayer->pev->armorvalue = 100; + + pPlayer->pev->renderfx = kRenderFxGlowShell; + pPlayer->pev->renderamt = 25; + pPlayer->pev->rendercolor = Vector( 0, 75, 250 ); + + CBasePlayerWeapon *pEgon = (CBasePlayerWeapon*)pWeapon; + + pEgon->m_iDefaultAmmo = 100; + pPlayer->m_rgAmmo[pEgon->m_iPrimaryAmmoType] = pEgon->m_iDefaultAmmo; + + g_engfuncs.pfnSetClientKeyValue( pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", "ivan" ); + } +} + +void CMultiplayBusters::ClientUserInfoChanged( CBasePlayer* pPlayer, char* infobuffer ) +{ + SetPlayerModel( pPlayer ); + + // Set preferences + pPlayer->SetPrefsFromUserinfo( infobuffer ); +} + +void CMultiplayBusters::PlayerSpawn( CBasePlayer* pPlayer ) +{ + CHalfLifeMultiplay::PlayerSpawn( pPlayer ); + SetPlayerModel( pPlayer ); +} + +void CMultiplayBusters::SetPlayerModel( CBasePlayer* pPlayer ) +{ + if ( IsPlayerBusting( pPlayer ) ) + { + g_engfuncs.pfnSetClientKeyValue( pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", "ivan" ); + } + else + { + g_engfuncs.pfnSetClientKeyValue( pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", "skeleton" ); + } +} diff --git a/dlls/nihilanth.cpp b/dlls/nihilanth.cpp index 6c0a500..10979c4 100644 --- a/dlls/nihilanth.cpp +++ b/dlls/nihilanth.cpp @@ -28,7 +28,7 @@ class CNihilanth : public CBaseMonster { public: - int Save( CSave &save ); + int Save( CSave &save ); int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; @@ -462,7 +462,7 @@ void CNihilanth :: DyingThink( void ) { if (m_pBall->pev->renderamt > 0) { - m_pBall->pev->renderamt = max( 0, m_pBall->pev->renderamt - 2); + m_pBall->pev->renderamt = max( 0, m_pBall->pev->renderamt - 2); } else { @@ -884,7 +884,7 @@ void CNihilanth :: HuntThink( void ) } else { - m_flAdj = min( m_flAdj + 10, 1000 ); + m_flAdj = min( m_flAdj + 10.0f, 1000.0f ); } } diff --git a/dlls/nodes.cpp b/dlls/nodes.cpp index 2755590..2fcf407 100644 --- a/dlls/nodes.cpp +++ b/dlls/nodes.cpp @@ -1433,7 +1433,7 @@ int CGraph :: RejectInlineLinks ( CLink *pLinkPool, FILE *file ) // TestHull is a modelless clip hull that verifies reachable // nodes by walking from every node to each of it's connections //========================================================= -class CTestHull : public CBaseMonster +class CTestHull : public CBaseMonster { public: diff --git a/dlls/observer.cpp b/dlls/observer.cpp index 0ca466d..2b6d3cb 100644 --- a/dlls/observer.cpp +++ b/dlls/observer.cpp @@ -223,7 +223,7 @@ void CBasePlayer::Observer_CheckProperties() } // Attempt to change the observer mode -void CBasePlayer::Observer_SetMode( int iMode ) +void CBasePlayer::Observer_SetMode( int iMode ) { // Just abort if we're changing to the mode we're already in diff --git a/dlls/osprey.cpp b/dlls/osprey.cpp index 8694203..211d9ef 100644 --- a/dlls/osprey.cpp +++ b/dlls/osprey.cpp @@ -37,7 +37,7 @@ typedef struct #define MAX_CARRY 24 -class COsprey : public CBaseMonster +class COsprey : public CBaseMonster { public: int Save( CSave &save ); diff --git a/dlls/plats.cpp b/dlls/plats.cpp index 8207b76..eacfd2c 100644 --- a/dlls/plats.cpp +++ b/dlls/plats.cpp @@ -2103,7 +2103,7 @@ void CFuncTrackAuto :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T #define FGUNTARGET_START_ON 0x0001 -class CGunTarget : public CBaseMonster +class CGunTarget : public CBaseMonster { public: void Spawn( void ); diff --git a/dlls/player.cpp b/dlls/player.cpp index b3d9161..1e6fc61 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -44,15 +44,17 @@ extern DLL_GLOBAL BOOL g_fGameOver; extern DLL_GLOBAL BOOL g_fDrawLines; int gEvilImpulse101; extern DLL_GLOBAL int g_iSkillLevel, gDisplayTitle; + - -BOOL gInitHUD = TRUE; +BOOL gInitHUD = TRUE; extern void CopyToBodyQue(entvars_t* pev); extern void respawn(entvars_t *pev, BOOL fCopyCorpse); extern Vector VecBModelOrigin(entvars_t *pevBModel ); extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer ); +extern bool IsBustingGame(); + // the world node graph extern CGraph WorldGraph; @@ -718,8 +720,20 @@ void CBasePlayer::PackDeadPlayerItems( void ) case GR_PLR_DROP_GUN_ACTIVE: if ( m_pActiveItem && pPlayerItem == m_pActiveItem ) { + CBasePlayerWeapon *pWeapon = (CBasePlayerWeapon*)pPlayerItem; + int nIndex = iPW++; + // this is the active item. Pack it. - rgpPackWeapons[ iPW++ ] = (CBasePlayerWeapon *)pPlayerItem; + rgpPackWeapons[nIndex] = pWeapon; + + //Reload the weapon before dropping it if we have ammo + int j = min( pWeapon->iMaxClip() - pWeapon->m_iClip, m_rgAmmo[pWeapon->m_iPrimaryAmmoType] ); + + // Add them to the clip + pWeapon->m_iClip += j; + m_rgAmmo[pWeapon->m_iPrimaryAmmoType] -= j; + + TabulateAmmo(); } break; @@ -783,24 +797,69 @@ void CBasePlayer::PackDeadPlayerItems( void ) iPA = 0; iPW = 0; -// pack the ammo - while ( iPackAmmo[ iPA ] != -1 ) + if ( IsBustingGame() ) { - pWeaponBox->PackAmmo( MAKE_STRING( CBasePlayerItem::AmmoInfoArray[ iPackAmmo[ iPA ] ].pszName ), m_rgAmmo[ iPackAmmo[ iPA ] ] ); - iPA++; - } + if ( HasNamedPlayerItem( "weapon_egon" ) ) + { + for ( i = 0; i < MAX_ITEM_TYPES; i++ ) + { + CBasePlayerItem *pItem = m_rgpPlayerItems[i]; -// now pack all of the items in the lists - while ( rgpPackWeapons[ iPW ] ) + if ( pItem ) + { + if ( !strcmp( "weapon_egon", STRING( pItem->pev->classname ) ) ) + { + pWeaponBox->PackWeapon( pItem ); + + SET_MODEL( ENT( pWeaponBox->pev ), "models/w_egon.mdl" ); + + pWeaponBox->pev->velocity = vec3_t( 0, 0, 0 ); + pWeaponBox->pev->renderfx = kRenderFxGlowShell; + pWeaponBox->pev->renderamt = 25; + pWeaponBox->pev->rendercolor = Vector( 0, 75, 250 ); + + break; + } + } + } + } + + + } + else { - // weapon unhooked from the player. Pack it into der box. - pWeaponBox->PackWeapon( rgpPackWeapons[ iPW ] ); + bool bPackItems = TRUE; - iPW++; + if ( iAmmoRules == GR_PLR_DROP_AMMO_ACTIVE && iWeaponRules == GR_PLR_DROP_GUN_ACTIVE ) + { + if ( FClassnameIs( rgpPackWeapons[0]->pev, "weapon_satchel" ) && ( iPackAmmo[0] == -1 || ( m_rgAmmo[iPackAmmo[0]] == 0 ) ) ) + { + bPackItems = FALSE; + } + } + + if ( bPackItems ) + { + // pack the ammo + while ( iPackAmmo[iPA] != -1 ) + { + pWeaponBox->PackAmmo( MAKE_STRING( CBasePlayerItem::AmmoInfoArray[iPackAmmo[iPA]].pszName ), m_rgAmmo[iPackAmmo[iPA]] ); + iPA++; + } + + // now pack all of the items in the lists + while ( rgpPackWeapons[iPW] ) + { + // weapon unhooked from the player. Pack it into der box. + pWeaponBox->PackWeapon( rgpPackWeapons[iPW] ); + + iPW++; + } + } + + pWeaponBox->pev->velocity = pev->velocity * 1.2;// weaponbox has player's velocity, then some. } - - pWeaponBox->pev->velocity = pev->velocity * 1.2;// weaponbox has player's velocity, then some. - + RemoveAllItems( TRUE );// now strip off everything that wasn't handled by the code above. } @@ -891,7 +950,7 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib ) SetAnimation( PLAYER_DIE ); - m_iRespawnFrames = 0; + m_flRespawnTimer = 0.0f; pev->modelindex = g_ulModelIndexPlayer; // don't use eyes @@ -924,13 +983,19 @@ void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib ) WRITE_BYTE(0); MESSAGE_END(); - + //Adrian: always make the players non-solid in multiplayer when they die + if ( g_pGameRules->IsMultiplayer() ) + { + pev->solid = SOLID_NOT; + } + // UNDONE: Put this in, but add FFADE_PERMANENT and make fade time 8.8 instead of 4.12 // UTIL_ScreenFade( edict(), Vector(128,0,0), 6, 15, 255, FFADE_OUT | FFADE_MODULATE ); if ( ( pev->health < -40 && iGib != GIB_NEVER ) || iGib == GIB_ALWAYS ) { - pev->solid = SOLID_NOT; + pev->solid = SOLID_NOT; + GibMonster(); // This clears pev->model pev->effects |= EF_NODRAW; return; @@ -1028,6 +1093,9 @@ void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) if (pev->sequence == animDesired) return; + + //ALERT(at_console, "Set die animation to %d\n", animDesired); + pev->gaitsequence = 0; pev->sequence = animDesired; pev->frame = 0; @@ -1111,6 +1179,7 @@ void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) return; //ALERT( at_console, "Set animation to %d\n", animDesired ); + // Reset to first frame of desired animation pev->sequence = animDesired; pev->frame = 0; @@ -1292,18 +1361,29 @@ void CBasePlayer::PlayerDeathThink(void) { StudioFrameAdvance( ); - m_iRespawnFrames++; // Note, these aren't necessarily real "frames", so behavior is dependent on # of client movement commands - if ( m_iRespawnFrames < 120 ) // Animations should be no longer than this + m_flRespawnTimer += gpGlobals->frametime; + if ( m_flRespawnTimer < 4.0f ) // 120 frames at 30fps -- animations should be no longer than this return; } + if ( pev->deadflag == DEAD_DYING ) + { + //Once we finish animating, if we're in multiplayer just make a copy of our body right away. + if ( m_fSequenceFinished && g_pGameRules->IsMultiplayer() && pev->movetype == MOVETYPE_NONE ) + { + CopyToBodyQue( pev ); + pev->modelindex = 0; + } + + pev->deadflag = DEAD_DEAD; + } + // once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore // this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn if ( pev->movetype != MOVETYPE_NONE && FBitSet(pev->flags, FL_ONGROUND) ) pev->movetype = MOVETYPE_NONE; - if (pev->deadflag == DEAD_DYING) - pev->deadflag = DEAD_DEAD; + StopAnimation(); @@ -1330,7 +1410,7 @@ void CBasePlayer::PlayerDeathThink(void) // if the player has been dead for one second longer than allowed by forcerespawn, // forcerespawn isn't on. Send the player off to an intermission camera until they // choose to respawn. - if ( g_pGameRules->IsMultiplayer() && ( gpGlobals->time > (m_fDeadTime + 6) ) && !(m_afPhysicsFlags & PFLAG_OBSERVER) ) + if ( g_pGameRules->IsMultiplayer() && ( gpGlobals->time > (m_fDeadTime + 6) ) && !(m_afPhysicsFlags & PFLAG_OBSERVER) ) { // go to dead camera. StartDeathCam(); @@ -1345,7 +1425,7 @@ void CBasePlayer::PlayerDeathThink(void) return; pev->button = 0; - m_iRespawnFrames = 0; + m_flRespawnTimer = 0.0f; //ALERT(at_console, "Respawn\n"); @@ -1515,6 +1595,9 @@ void CBasePlayer::PlayerUse ( void ) { m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_iTrain = TRAIN_NEW|TRAIN_OFF; + CBaseEntity *pTrain = CBaseEntity::Instance( pev->groundentity ); + if (pTrain && (pTrain->Classify() == CLASS_VEHICLE)) + ((CFuncVehicle*)pTrain)->m_pDriver = NULL; return; } else @@ -1526,7 +1609,13 @@ void CBasePlayer::PlayerUse ( void ) m_afPhysicsFlags |= PFLAG_ONTRAIN; m_iTrain = TrainSpeed(pTrain->pev->speed, pTrain->pev->impulse); m_iTrain |= TRAIN_NEW; - EMIT_SOUND( ENT(pev), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM); + if (pTrain->Classify() == CLASS_VEHICLE) + { + EMIT_SOUND( ENT(pev), CHAN_ITEM, "plats/vehicle_ignition.wav", 0.8, ATTN_NORM); + ((CFuncVehicle*)pTrain)->m_pDriver = this; + } + else + EMIT_SOUND( ENT(pev), CHAN_ITEM, "plats/train_use1.wav", 0.8, ATTN_NORM); return; } } @@ -1646,6 +1735,16 @@ void CBasePlayer::Jump() { pev->velocity = pev->velocity + pev->basevelocity; } + + + // JoshA: CS behaviour does this for tracktrain + train as well, + // but let's just do this for func_vehicle to avoid breaking existing content. + // + // If you're standing on a moving train... then add the velocity of the train to yours. + if ( pevGround && ( /*(!strcmp( "func_tracktrain", STRING(pevGround->classname))) || + (!strcmp( "func_train", STRING(pevGround->classname))) ) ||*/ + (!strcmp( "func_vehicle", STRING(pevGround->classname)))) ) + pev->velocity = pev->velocity + pevGround->velocity; } @@ -1923,28 +2022,59 @@ void CBasePlayer::PreThink(void) //ALERT( at_error, "In train mode with no train!\n" ); m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_iTrain = TRAIN_NEW|TRAIN_OFF; + if (pTrain->Classify() == CLASS_VEHICLE) + ((CFuncVehicle*)pTrain)->m_pDriver = NULL; return; } } - else if ( !FBitSet( pev->flags, FL_ONGROUND ) || FBitSet( pTrain->pev->spawnflags, SF_TRACKTRAIN_NOCONTROL ) || (pev->button & (IN_MOVELEFT|IN_MOVERIGHT) ) ) + else if ( !FBitSet( pev->flags, FL_ONGROUND ) || FBitSet( pTrain->pev->spawnflags, SF_TRACKTRAIN_NOCONTROL ) || ((pev->button & (IN_MOVELEFT|IN_MOVERIGHT) ) && pTrain->Classify() != CLASS_VEHICLE) ) { // Turn off the train if you jump, strafe, or the train controls go dead + // and it isn't a func_vehicle. m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_iTrain = TRAIN_NEW|TRAIN_OFF; + if (pTrain->Classify() == CLASS_VEHICLE) + ((CFuncVehicle*)pTrain)->m_pDriver = NULL; return; } pev->velocity = g_vecZero; vel = 0; - if ( m_afButtonPressed & IN_FORWARD ) + if (pTrain->Classify() == CLASS_VEHICLE) { - vel = 1; - pTrain->Use( this, this, USE_SET, (float)vel ); + if ( pev->button & IN_FORWARD ) + { + vel = 1; + pTrain->Use( this, this, USE_SET, (float)vel ); + } + if ( pev->button & IN_BACK ) + { + vel = -1; + pTrain->Use( this, this, USE_SET, (float)vel ); + } + if ( pev->button & IN_MOVELEFT) + { + vel = 20; + pTrain->Use( this, this, USE_SET, (float)vel ); + } + if ( pev->button & IN_MOVERIGHT) + { + vel = 30; + pTrain->Use( this, this, USE_SET, (float)vel ); + } } - else if ( m_afButtonPressed & IN_BACK ) + else { - vel = -1; - pTrain->Use( this, this, USE_SET, (float)vel ); + if ( m_afButtonPressed & IN_FORWARD ) + { + vel = 1; + pTrain->Use( this, this, USE_SET, (float)vel ); + } + else if ( m_afButtonPressed & IN_BACK ) + { + vel = -1; + pTrain->Use( this, this, USE_SET, (float)vel ); + } } if (vel) @@ -2674,23 +2804,23 @@ pt_end: if ( gun && gun->UseDecrement() ) { - gun->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0 ); - gun->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001 ); + gun->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0f ); + gun->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001f ); if ( gun->m_flTimeWeaponIdle != 1000 ) { - gun->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001 ); + gun->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001f ); } if ( gun->pev->fuser1 != 1000 ) { - gun->pev->fuser1 = max( gun->pev->fuser1 - gpGlobals->frametime, -0.001 ); + gun->pev->fuser1 = max( gun->pev->fuser1 - gpGlobals->frametime, -0.001f ); } // Only decrement if not flagged as NO_DECREMENT // if ( gun->m_flPumpTime != 1000 ) // { - // gun->m_flPumpTime = max( gun->m_flPumpTime - gpGlobals->frametime, -0.001 ); + // gun->m_flPumpTime = max( gun->m_flPumpTime - gpGlobals->frametime, -0.001f ); // } } @@ -2764,6 +2894,8 @@ edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer ) CBaseEntity *pSpot; edict_t *player; + int nNumRandomSpawnsToTry = 10; + player = pPlayer->edict(); // choose a info_player_deathmatch point @@ -2778,9 +2910,21 @@ edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer ) } else if ( g_pGameRules->IsDeathmatch() ) { + if (NULL == g_pLastSpawn) + { + int nNumSpawnPoints = 0; + CBaseEntity* pEnt = UTIL_FindEntityByClassname(NULL, "info_player_deathmatch"); + while (NULL != pEnt) + { + nNumSpawnPoints++; + pEnt = UTIL_FindEntityByClassname(pEnt, "info_player_deathmatch"); + } + nNumRandomSpawnsToTry = nNumSpawnPoints; + } + pSpot = g_pLastSpawn; // Randomize the start spot - for ( int i = RANDOM_LONG(1,5); i > 0; i-- ) + for ( int i = RANDOM_LONG(1, nNumRandomSpawnsToTry - 1); i > 0; i-- ) pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" ); if ( FNullEnt( pSpot ) ) // skip over the null point pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" ); @@ -2849,6 +2993,8 @@ ReturnSpot: void CBasePlayer::Spawn( void ) { + m_flStartCharge = gpGlobals->time; + pev->classname = MAKE_STRING("player"); pev->health = 100; pev->armorvalue = 0; @@ -3056,6 +3202,9 @@ int CBasePlayer::Restore( CRestore &restore ) RenewItems(); + //Resync ammo data so you can reload - Solokiller + TabulateAmmo(); + #if defined( CLIENT_WEAPONS ) // HACK: This variable is saved/restored in CBaseMonster as a time variable, but we're using it // as just a counter. Ideally, this needs its own variable that's saved as a plain float. @@ -3063,6 +3212,12 @@ int CBasePlayer::Restore( CRestore &restore ) m_flNextAttack = UTIL_WeaponTimeBase(); #endif + // Force a flashlight update for the HUD + if ( m_flFlashLightTime == 0 ) + { + m_flFlashLightTime = 1; + } + return status; } @@ -3424,8 +3579,6 @@ void CBasePlayer :: ForceClientDllUpdate( void ) ImpulseCommands ============ */ -extern float g_flWeaponCheat; - void CBasePlayer::ImpulseCommands( ) { TraceResult tr;// UNDONE: kill me! This is temporary for PreAlpha CDs @@ -3507,7 +3660,7 @@ void CBasePlayer::ImpulseCommands( ) void CBasePlayer::CheatImpulseCommands( int iImpulse ) { #if !defined( HLDEMO_BUILD ) - if ( g_flWeaponCheat == 0.0 ) + if ( CVAR_GET_FLOAT( "sv_cheats" ) == 0.0 ) { return; } @@ -3755,7 +3908,7 @@ int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem ) pev->viewmodel = 0; pev->weaponmodel = 0; } - else if ( m_pLastItem == pItem ) + if ( m_pLastItem == pItem ) m_pLastItem = NULL; CBasePlayerItem *pPrev = m_rgpPlayerItems[pItem->iItemSlot()]; @@ -4180,6 +4333,22 @@ void CBasePlayer :: UpdateClientData( void ) } } +void CBasePlayer :: SetPrefsFromUserinfo( char * infobuffer ) +{ + const char * pszKeyVal; + + // Set autoswitch preference + pszKeyVal = g_engfuncs.pfnInfoKeyValue( infobuffer, "cl_autowepswitch" ); + if ( FStrEq( pszKeyVal, "" ) ) + { + m_iAutoWepSwitch = 1; + } + else + { + m_iAutoWepSwitch = atoi( pszKeyVal ); + } +} + //========================================================= // FBecomeProne - Overridden for the player to set the proper @@ -4317,7 +4486,7 @@ Vector CBasePlayer :: GetAutoaimVector( float flDelta ) // m_vecAutoAim = m_vecAutoAim * 0.99; // Don't send across network if sv_aim is 0 - if ( g_psv_aim->value != 0 ) + if ( g_psv_aim->value != 0 && g_psv_allow_autoaim->value != 0 ) { if ( m_vecAutoAim.x != m_lastx || m_vecAutoAim.y != m_lasty ) @@ -4345,7 +4514,7 @@ Vector CBasePlayer :: AutoaimDeflection( Vector &vecSrc, float flDist, float flD edict_t *bestent; TraceResult tr; - if ( g_psv_aim->value == 0 ) + if ( g_psv_aim->value == 0 || g_psv_allow_autoaim->value == 0 ) { m_fOnTarget = FALSE; return g_vecZero; @@ -4642,6 +4811,33 @@ BOOL CBasePlayer::HasNamedPlayerItem( const char *pszItemName ) return FALSE; } +//========================================================= +// HasPlayerItemFromID +// Just compare IDs, rather than classnames +//========================================================= +BOOL CBasePlayer::HasPlayerItemFromID( int nID ) +{ + CBasePlayerItem* pItem; + int i; + + for ( i = 0; i < MAX_ITEM_TYPES; i++ ) + { + pItem = m_rgpPlayerItems[i]; + + while ( pItem ) + { + if ( pItem->m_iId == nID ) + { + return TRUE; + } + + pItem = pItem->m_pNext; + } + } + + return FALSE; +} + //========================================================= // //========================================================= @@ -4668,7 +4864,7 @@ BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) //========================================================= // Dead HEV suit prop //========================================================= -class CDeadHEV : public CBaseMonster +class CDeadHEV : public CBaseMonster { public: void Spawn( void ); diff --git a/dlls/player.h b/dlls/player.h index 0181509..e7c7ced 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -189,7 +189,7 @@ public: Vector m_vecAutoAim; BOOL m_fOnTarget; int m_iDeaths; - float m_iRespawnFrames; // used in PlayerDeathThink() to make sure players can always respawn + float m_flRespawnTimer; // used in PlayerDeathThink() to make sure players can always respawn int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE @@ -232,6 +232,8 @@ public: // JOHN: sends custom messages if player HUD data has changed (eg health, ammo) virtual void UpdateClientData( void ); + + void SetPrefsFromUserinfo( char * infobuffer ); static TYPEDESCRIPTION m_playerSaveData[]; @@ -265,6 +267,7 @@ public: void DropPlayerItem ( char *pszItemName ); BOOL HasPlayerItem( CBasePlayerItem *pCheckItem ); BOOL HasNamedPlayerItem( const char *pszItemName ); + BOOL HasPlayerItemFromID( int nID ); BOOL HasWeapons( void );// do I have ANY weapons? void SelectPrevItem( int iItem ); void SelectNextItem( int iItem ); @@ -323,6 +326,7 @@ public: float m_flNextChatTime; + int m_iAutoWepSwitch; }; #define AUTOAIM_2DEGREES 0.0348994967025 diff --git a/dlls/python.cpp b/dlls/python.cpp index 4e019ef..a5c56dd 100644 --- a/dlls/python.cpp +++ b/dlls/python.cpp @@ -171,7 +171,7 @@ void CPython::PrimaryAttack() Reload( ); else { - EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/357_cock1.wav", 0.8, ATTN_NORM); + PlayEmptySound(); m_flNextPrimaryAttack = 0.15; } @@ -306,4 +306,4 @@ class CPythonAmmo : public CBasePlayerAmmo LINK_ENTITY_TO_CLASS( ammo_357, CPythonAmmo ); -#endif \ No newline at end of file +#endif diff --git a/dlls/rat.cpp b/dlls/rat.cpp index ba858eb..bab2573 100644 --- a/dlls/rat.cpp +++ b/dlls/rat.cpp @@ -26,7 +26,7 @@ // Monster's Anim Events Go Here //========================================================= -class CRat : public CBaseMonster +class CRat : public CBaseMonster { public: void Spawn( void ); diff --git a/dlls/roach.cpp b/dlls/roach.cpp index 6a0aca9..d048720 100644 --- a/dlls/roach.cpp +++ b/dlls/roach.cpp @@ -38,7 +38,7 @@ class CRoach : public CBaseMonster { public: void Spawn( void ); - void Precache( void ); + void Precache( void ); void SetYawSpeed( void ); void EXPORT MonsterThink ( void ); void Move ( float flInterval ); diff --git a/dlls/rpg.cpp b/dlls/rpg.cpp index fe9c53c..ed17f6f 100644 --- a/dlls/rpg.cpp +++ b/dlls/rpg.cpp @@ -111,8 +111,9 @@ CRpgRocket *CRpgRocket::CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBa pRocket->pev->angles = vecAngles; pRocket->Spawn(); pRocket->SetTouch( &CRpgRocket::RocketTouch ); - pRocket->m_pLauncher = pLauncher;// remember what RPG fired me. - pRocket->m_pLauncher->m_cActiveRockets++;// register this missile as active for the launcher + + pLauncher->m_cActiveRockets++; + pRocket->m_hLauncher = pLauncher;// remember what RPG fired me. pRocket->pev->owner = pOwner->edict(); return pRocket; @@ -152,16 +153,36 @@ void CRpgRocket :: Spawn( void ) //========================================================= void CRpgRocket :: RocketTouch ( CBaseEntity *pOther ) { - if ( m_pLauncher ) + //ALERT( at_console, "RpgRocket RocketTouch, m_pLauncher: %u\n", GetLauncher() ); + + if ( GetLauncher() ) { // my launcher is still around, tell it I'm dead. - m_pLauncher->m_cActiveRockets--; - } + GetLauncher()->m_cActiveRockets--; + m_hLauncher = NULL; + } STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" ); ExplodeTouch( pOther ); } +//========================================================= +void CRpgRocket::Explode( TraceResult *pTrace, int bitsDamageType ) +{ + //ALERT( at_console, "RpgRocket Explode, m_pLauncher: %u\n", GetLauncher() ); + + STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav"); + + if ( GetLauncher() ) + { + // my launcher is still around, tell it I'm dead. + GetLauncher()->m_cActiveRockets--; + m_hLauncher = NULL; + } + + CGrenade::Explode( pTrace, bitsDamageType ); +} + //========================================================= //========================================================= void CRpgRocket :: Precache( void ) @@ -205,6 +226,14 @@ void CRpgRocket :: IgniteThink( void ) } +CRpg* CRpgRocket::GetLauncher() +{ + if ( !m_hLauncher ) + return NULL; + + return (CRpg*)( (CBaseEntity*)m_hLauncher ); +} + void CRpgRocket :: FollowThink( void ) { CBaseEntity *pOther = NULL; @@ -217,16 +246,25 @@ void CRpgRocket :: FollowThink( void ) vecTarget = gpGlobals->v_forward; flMax = 4096; - + // Examine all entities within a reasonable radius while ((pOther = UTIL_FindEntityByClassname( pOther, "laser_spot" )) != NULL) { - UTIL_TraceLine ( pev->origin, pOther->pev->origin, dont_ignore_monsters, ENT(pev), &tr ); - // ALERT( at_console, "%f\n", tr.flFraction ); + Vector vSpotLocation = pOther->pev->origin; + + if( UTIL_PointContents( vSpotLocation ) == CONTENTS_SKY ) + { + //ALERT( at_console, "laser spot is in the sky...\n"); + } + + UTIL_TraceLine ( pev->origin, vSpotLocation, dont_ignore_monsters, ENT(pev), &tr ); + + //ALERT( at_console, "fraction: %f\n", tr.flFraction ); + if (tr.flFraction >= 0.90) { vecDir = pOther->pev->origin - pev->origin; - flDist = vecDir.Length( ); + flDist = vecDir.Length( ); vecDir = vecDir.Normalize( ); flDot = DotProduct( gpGlobals->v_forward, vecDir ); if ((flDot > 0) && (flDist * (1 - flDot) < flMax)) @@ -274,7 +312,27 @@ void CRpgRocket :: FollowThink( void ) Detonate( ); } } - // ALERT( at_console, "%.0f\n", flSpeed ); + + if( GetLauncher() ) + { + float flDistance = ( pev->origin - GetLauncher()->pev->origin ).Length(); + + // if we've travelled more than max distance the player can send a spot, stop tracking the original launcher (allow it to reload) + if( flDistance > 8192.0f || gpGlobals->time - m_flIgniteTime > 6.0f ) + { + //ALERT( at_console, "RPG too far (%f)!\n", flDistance ); + GetLauncher()->m_cActiveRockets--; + m_hLauncher = NULL; + } + + //ALERT( at_console, "%.0f, m_pLauncher: %u, flDistance: %f\n", flSpeed, GetLauncher(), flDistance ); + } + + if( (UTIL_PointContents(pev->origin) == CONTENTS_SKY ) ) + { + //ALERT( at_console, "Rocket is in the sky, detonating...\n"); + Detonate(); + } pev->nextthink = gpGlobals->time + 0.1; } @@ -284,6 +342,8 @@ void CRpgRocket :: FollowThink( void ) void CRpg::Reload( void ) { + //ALERT( at_console, "RPG Reload, m_cActiveRockets: %d, m_fSpotActive: %d\n", m_cActiveRockets, m_fSpotActive ); + int iResult; if ( m_iClip == 1 ) @@ -309,6 +369,8 @@ void CRpg::Reload( void ) if ( m_cActiveRockets && m_fSpotActive ) { + //ALERT( at_console, "RPG reload failed, m_cActiveRockets: %d, m_fSpotActive: %d\n", m_cActiveRockets, m_fSpotActive ); + // no reloading when there are active missiles tracking the designator. // ward off future autoreload attempts by setting next attack time into the future for a bit. return; @@ -385,7 +447,7 @@ int CRpg::GetItemInfo(ItemInfo *p) p->iSlot = 3; p->iPosition = 0; p->iId = m_iId = WEAPON_RPG; - p->iFlags = 0; + p->iFlags = ITEM_FLAG_NOAUTOSWITCHTO; p->iWeight = RPG_WEIGHT; return 1; @@ -481,6 +543,8 @@ void CRpg::PrimaryAttack() m_flNextPrimaryAttack = GetNextAttackDelay(1.5); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 1.5; + + ResetEmptySound(); } else { @@ -510,8 +574,6 @@ void CRpg::WeaponIdle( void ) { UpdateSpot( ); - ResetEmptySound( ); - if ( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() ) return; @@ -538,6 +600,7 @@ void CRpg::WeaponIdle( void ) m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0; } + ResetEmptySound( ); SendWeaponAnim( iAnim ); } else diff --git a/dlls/satchel.cpp b/dlls/satchel.cpp index 983f431..10f7b6b 100644 --- a/dlls/satchel.cpp +++ b/dlls/satchel.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -176,7 +176,7 @@ LINK_ENTITY_TO_CLASS( weapon_satchel, CSatchel ); //========================================================= int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal ) { - CSatchel *pSatchel; + CSatchel* pSatchel = NULL; #ifdef CLIENT_DLL if ( bIsMultiplayer() ) @@ -186,7 +186,26 @@ int CSatchel::AddDuplicate( CBasePlayerItem *pOriginal ) { pSatchel = (CSatchel *)pOriginal; - if ( pSatchel->m_chargeReady != 0 ) + if ( pOriginal->m_pPlayer == NULL ) + return TRUE; + + int nSatchelsInPocket = pSatchel->m_pPlayer->m_rgAmmo[ pSatchel->PrimaryAmmoIndex() ]; + int nNumSatchels = 0; + CBaseEntity* pLiveSatchel = NULL; + + + while ( ( pLiveSatchel = UTIL_FindEntityInSphere( pLiveSatchel, pOriginal->m_pPlayer->pev->origin, 4096 ) ) != NULL ) + { + if ( FClassnameIs( pLiveSatchel->pev, "monster_satchel" ) ) + { + if ( pLiveSatchel->pev->owner == pOriginal->m_pPlayer->edict() ) + { + nNumSatchels++; + } + } + } + + if ( pSatchel->m_chargeReady != 0 && ( nSatchelsInPocket + nNumSatchels ) >= SATCHEL_MAX_CARRY ) { // player has some satchels deployed. Refuse to add more. return FALSE; @@ -331,15 +350,18 @@ void CSatchel::Holster( int skiplocal /* = 0 */ ) void CSatchel::PrimaryAttack() { - switch (m_chargeReady) + // we're reloading, don't allow fire + if( m_chargeReady != 2 ) + { + Throw(); + } +} + + +void CSatchel::SecondaryAttack( void ) +{ + if ( m_chargeReady == 1 ) { - case 0: - { - Throw( ); - } - break; - case 1: - { SendWeaponAnim( SATCHEL_RADIO_FIRE ); edict_t *pPlayer = m_pPlayer->edict( ); @@ -362,23 +384,6 @@ void CSatchel::PrimaryAttack() m_flNextPrimaryAttack = GetNextAttackDelay(0.5); m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5; - break; - } - - case 2: - // we're reloading, don't allow fire - { - } - break; - } -} - - -void CSatchel::SecondaryAttack( void ) -{ - if ( m_chargeReady != 2 ) - { - Throw( ); } } diff --git a/dlls/scientist.cpp b/dlls/scientist.cpp index a27e52f..540ebc3 100644 --- a/dlls/scientist.cpp +++ b/dlls/scientist.cpp @@ -99,6 +99,8 @@ public: void TalkInit( void ); + char* GetScientistModel() const; + void Killed( entvars_t *pevAttacker, int iGib ); virtual int Save( CSave &save ); @@ -424,6 +426,17 @@ DEFINE_CUSTOM_SCHEDULES( CScientist ) IMPLEMENT_CUSTOM_SCHEDULES( CScientist, CTalkMonster ); +char* CScientist::GetScientistModel() const +{ + char* pszOverride = (char*)CVAR_GET_STRING("_sv_override_scientist_mdl"); + if (pszOverride && strlen(pszOverride) > 5) // at least requires ".mdl" + { + return pszOverride; + } + + return "models/scientist.mdl"; +} + void CScientist::DeclineFollowing( void ) { Talk( 10 ); @@ -658,7 +671,7 @@ void CScientist :: Spawn( void ) { Precache( ); - SET_MODEL(ENT(pev), "models/scientist.mdl"); + SET_MODEL(ENT(pev), GetScientistModel()); UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); pev->solid = SOLID_SLIDEBOX; @@ -694,7 +707,7 @@ void CScientist :: Spawn( void ) //========================================================= void CScientist :: Precache( void ) { - PRECACHE_MODEL("models/scientist.mdl"); + PRECACHE_MODEL(GetScientistModel()); PRECACHE_SOUND("scientist/sci_pain1.wav"); PRECACHE_SOUND("scientist/sci_pain2.wav"); PRECACHE_SOUND("scientist/sci_pain3.wav"); @@ -1098,18 +1111,32 @@ int CScientist::FriendNumber( int arrayNumber ) //========================================================= // Dead Scientist PROP //========================================================= -class CDeadScientist : public CBaseMonster +class CDeadScientist : public CBaseMonster { public: void Spawn( void ); int Classify ( void ) { return CLASS_HUMAN_PASSIVE; } + // passed into Precache which is non-const + char* GetScientistModel() const; + void KeyValue( KeyValueData *pkvd ); int m_iPose;// which sequence to display static char *m_szPoses[7]; }; char *CDeadScientist::m_szPoses[] = { "lying_on_back", "lying_on_stomach", "dead_sitting", "dead_hang", "dead_table1", "dead_table2", "dead_table3" }; +char* CDeadScientist::GetScientistModel() const +{ + char* pszOverride = (char*)CVAR_GET_STRING("_sv_override_scientist_mdl"); + if (pszOverride && strlen(pszOverride) > 5) // at least requires ".mdl" + { + return pszOverride; + } + + return "models/scientist.mdl"; +} + void CDeadScientist::KeyValue( KeyValueData *pkvd ) { if (FStrEq(pkvd->szKeyName, "pose")) @@ -1127,8 +1154,8 @@ LINK_ENTITY_TO_CLASS( monster_scientist_dead, CDeadScientist ); // void CDeadScientist :: Spawn( ) { - PRECACHE_MODEL("models/scientist.mdl"); - SET_MODEL(ENT(pev), "models/scientist.mdl"); + PRECACHE_MODEL(GetScientistModel()); + SET_MODEL(ENT(pev), GetScientistModel()); pev->effects = 0; pev->sequence = 0; @@ -1209,8 +1236,8 @@ SITTING_ANIM_sitting3 // void CSittingScientist :: Spawn( ) { - PRECACHE_MODEL("models/scientist.mdl"); - SET_MODEL(ENT(pev), "models/scientist.mdl"); + PRECACHE_MODEL(GetScientistModel()); + SET_MODEL(ENT(pev), GetScientistModel()); Precache(); InitBoneControllers(); diff --git a/dlls/scripted.cpp b/dlls/scripted.cpp index 651af70..008e129 100644 --- a/dlls/scripted.cpp +++ b/dlls/scripted.cpp @@ -934,9 +934,9 @@ public: static TYPEDESCRIPTION m_SaveData[]; - CBaseMonster *FindEntity( void ); - BOOL AcceptableSpeaker( CBaseMonster *pMonster ); - BOOL StartSentence( CBaseMonster *pTarget ); + CBaseToggle *FindEntity( void ); + BOOL AcceptableSpeaker( CBaseToggle *pTarget ); + BOOL StartSentence( CBaseToggle *pTarget ); private: @@ -1072,10 +1072,10 @@ void CScriptedSentence :: Spawn( void ) void CScriptedSentence :: FindThink( void ) { - CBaseMonster *pMonster = FindEntity(); - if ( pMonster ) + CBaseToggle *pEnt = FindEntity(); + if (pEnt) { - StartSentence( pMonster ); + StartSentence(pEnt); if ( pev->spawnflags & SF_SENTENCE_ONCE ) UTIL_Remove( this ); SetThink( &CScriptedSentence::DelayThink ); @@ -1100,8 +1100,16 @@ void CScriptedSentence :: DelayThink( void ) } -BOOL CScriptedSentence :: AcceptableSpeaker( CBaseMonster *pMonster ) +BOOL CScriptedSentence :: AcceptableSpeaker( CBaseToggle *pTarget ) { + CBaseMonster *pMonster; + pMonster = NULL; + + if (pTarget) + { + pMonster = pTarget->MyMonsterPointer(); + } + if ( pMonster ) { if ( pev->spawnflags & SF_SENTENCE_FOLLOWERS ) @@ -1117,27 +1125,40 @@ BOOL CScriptedSentence :: AcceptableSpeaker( CBaseMonster *pMonster ) if ( pMonster->CanPlaySentence( override ) ) return TRUE; } + else + { + // targeting something other than a monster, sure it can speak + if( pTarget && pTarget->IsAllowedToSpeak() ) + return TRUE; + } + + return FALSE; } -CBaseMonster *CScriptedSentence :: FindEntity( void ) +CBaseToggle *CScriptedSentence :: FindEntity( void ) { edict_t *pentTarget; - CBaseMonster *pMonster; + CBaseToggle *pSpeakingEnt; pentTarget = FIND_ENTITY_BY_TARGETNAME(NULL, STRING(m_iszEntity)); - pMonster = NULL; + pSpeakingEnt = NULL; while (!FNullEnt(pentTarget)) { - pMonster = GetMonsterPointer( pentTarget ); - if ( pMonster != NULL ) + CBaseEntity *pEnt = Instance(pentTarget); + pSpeakingEnt = pEnt ? pEnt->MyTogglePointer() : NULL; + + if (pSpeakingEnt != NULL ) { - if ( AcceptableSpeaker( pMonster ) ) - return pMonster; -// ALERT( at_console, "%s (%s), not acceptable\n", STRING(pMonster->pev->classname), STRING(pMonster->pev->targetname) ); + if (AcceptableSpeaker(pSpeakingEnt)) + { + //ALERT(at_console, "acceptable speaker\n"); + return pSpeakingEnt; + } + //ALERT(at_console, "found unacceptable speaker\n"); } pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, STRING(m_iszEntity)); } @@ -1149,9 +1170,9 @@ CBaseMonster *CScriptedSentence :: FindEntity( void ) { if ( FBitSet( pEntity->pev->flags, FL_MONSTER )) { - pMonster = pEntity->MyMonsterPointer( ); - if ( AcceptableSpeaker( pMonster ) ) - return pMonster; + pSpeakingEnt = pEntity->MyTogglePointer( ); + if ( AcceptableSpeaker( pSpeakingEnt ) ) + return pSpeakingEnt; } } } @@ -1160,7 +1181,7 @@ CBaseMonster *CScriptedSentence :: FindEntity( void ) } -BOOL CScriptedSentence :: StartSentence( CBaseMonster *pTarget ) +BOOL CScriptedSentence :: StartSentence( CBaseToggle *pTarget ) { if ( !pTarget ) { @@ -1201,7 +1222,7 @@ BOOL CScriptedSentence :: StartSentence( CBaseMonster *pTarget ) //========================================================= // Furniture - this is the cool comment I cut-and-pasted //========================================================= -class CFurniture : public CBaseMonster +class CFurniture : public CBaseMonster { public: void Spawn ( void ); diff --git a/dlls/shotgun.cpp b/dlls/shotgun.cpp index 604f12b..2fc90af 100644 --- a/dlls/shotgun.cpp +++ b/dlls/shotgun.cpp @@ -175,8 +175,7 @@ void CShotgun::PrimaryAttack() // HEV suit - indicate out of ammo condition m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - if (m_iClip != 0) - m_flPumpTime = gpGlobals->time + 0.5; + m_flPumpTime = gpGlobals->time + 0.5; m_flNextPrimaryAttack = GetNextAttackDelay(0.75); m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75; @@ -249,8 +248,7 @@ void CShotgun::SecondaryAttack( void ) // HEV suit - indicate out of ammo condition m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - if (m_iClip != 0) - m_flPumpTime = gpGlobals->time + 0.95; + m_flPumpTime = gpGlobals->time + 0.95; m_flNextPrimaryAttack = GetNextAttackDelay(1.5); m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.5; @@ -317,13 +315,6 @@ void CShotgun::WeaponIdle( void ) m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - if ( m_flPumpTime && m_flPumpTime < gpGlobals->time ) - { - // play pumping sound - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); - m_flPumpTime = 0; - } - if (m_flTimeWeaponIdle < UTIL_WeaponTimeBase() ) { if (m_iClip == 0 && m_fInSpecialReload == 0 && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) @@ -371,6 +362,18 @@ void CShotgun::WeaponIdle( void ) } } +void CShotgun::ItemPostFrame( void ) +{ + if ( m_flPumpTime && m_flPumpTime < gpGlobals->time ) + { + // play pumping sound + EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/scock1.wav", 1, ATTN_NORM, 0, 95 + RANDOM_LONG(0,0x1f)); + m_flPumpTime = 0; + } + + CBasePlayerWeapon::ItemPostFrame(); +} + class CShotgunAmmo : public CBasePlayerAmmo diff --git a/dlls/singleplay_gamerules.cpp b/dlls/singleplay_gamerules.cpp index 78c86ef..3438f7c 100644 --- a/dlls/singleplay_gamerules.cpp +++ b/dlls/singleplay_gamerules.cpp @@ -34,6 +34,8 @@ extern int gmsgMOTD; //========================================================= CHalfLifeRules::CHalfLifeRules( void ) { + SERVER_COMMAND( "exec spserver.cfg\n" ); + RefreshSkillData(); } @@ -83,10 +85,88 @@ BOOL CHalfLifeRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem return TRUE; } + +BOOL HLGetNextBestWeapon( CBasePlayer* pPlayer, CBasePlayerItem* pCurrentWeapon ) +{ + CBasePlayerItem* pCheck; + CBasePlayerItem* pBest;// this will be used in the event that we don't find a weapon in the same category. + int iBestWeight; + int i; + + iBestWeight = -1;// no weapon lower than -1 can be autoswitched to + pBest = NULL; + + if ( !pCurrentWeapon->CanHolster() ) + { + // can't put this gun away right now, so can't switch. + return FALSE; + } + + for ( i = 0; i < MAX_ITEM_TYPES; i++ ) + { + pCheck = pPlayer->m_rgpPlayerItems[i]; + + while ( pCheck ) + { + if ( (pCheck->iFlags() & ITEM_FLAG_NOAUTOSWITCHTO ) != 0 ) + { + pCheck = pCheck->m_pNext; + continue; + } + + if ( pCheck->iWeight() > -1 && pCheck->iWeight() == pCurrentWeapon->iWeight() && pCheck != pCurrentWeapon ) + { + // this weapon is from the same category. + if ( pCheck->CanDeploy() ) + { + if ( pPlayer->SwitchWeapon( pCheck ) ) + { + return TRUE; + } + } + } + else if ( pCheck->iWeight() > iBestWeight && pCheck != pCurrentWeapon )// don't reselect the weapon we're trying to get rid of + { + //ALERT ( at_console, "Considering %s\n", STRING( pCheck->pev->classname ) ); + // we keep updating the 'best' weapon just in case we can't find a weapon of the same weight + // that the player was using. This will end up leaving the player with his heaviest-weighted + // weapon. + if ( pCheck->CanDeploy() ) + { + // if this weapon is useable, flag it as the best + iBestWeight = pCheck->iWeight(); + pBest = pCheck; + } + } + + pCheck = pCheck->m_pNext; + } + } + + // if we make it here, we've checked all the weapons and found no useable + // weapon in the same catagory as the current weapon. + + // if pBest is null, we didn't find ANYTHING. Shouldn't be possible- should always + // at least get the crowbar, but ya never know. + if ( !pBest ) + { + return FALSE; + } + + pPlayer->SwitchWeapon( pBest ); + + return TRUE; +} + //========================================================= //========================================================= BOOL CHalfLifeRules :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) { + if ( pCurrentWeapon && pCurrentWeapon->iFlags() & ITEM_FLAG_EXHAUSTIBLE ) + { + return HLGetNextBestWeapon( pPlayer, pCurrentWeapon ); + } + return FALSE; } diff --git a/dlls/squadmonster.cpp b/dlls/squadmonster.cpp index a95ea9f..dad8694 100644 --- a/dlls/squadmonster.cpp +++ b/dlls/squadmonster.cpp @@ -385,7 +385,7 @@ int CSquadMonster :: SquadRecruit( int searchRadius, int maxMembers ) //========================================================= // CheckEnemy //========================================================= -int CSquadMonster :: CheckEnemy ( CBaseEntity *pEnemy ) +int CSquadMonster :: CheckEnemy ( CBaseEntity *pEnemy ) { int iUpdatedLKP; diff --git a/dlls/squeakgrenade.cpp b/dlls/squeakgrenade.cpp index 2084d79..40f34a4 100644 --- a/dlls/squeakgrenade.cpp +++ b/dlls/squeakgrenade.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -340,7 +340,7 @@ void CSqueakGrenade::SuperBounceTouch( CBaseEntity *pOther ) // higher pitch as squeeker gets closer to detonation time flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY); - if ( pOther->pev->takedamage && m_flNextAttack < gpGlobals->time ) + if ( pOther->pev->takedamage && m_flNextAttack < gpGlobals->time && ( pOther->pev->flags & FL_WORLDBRUSH ) == 0) { // attack! @@ -492,25 +492,66 @@ void CSqueak::Holster( int skiplocal /* = 0 */ ) EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "common/null.wav", 1.0, ATTN_NORM); } +// up / down +#define PITCH 0 +// left / right +#define YAW 1 +// fall over +#define ROLL 2 + +void AngleVectors(const vec3_t angles, vec3_t& forward, vec3_t& right, vec3_t& up) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI * 2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI * 2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI * 2 / 360); + sr = sin(angle); + cr = cos(angle); + + forward[0] = cp * cy; + forward[1] = cp * sy; + forward[2] = -sp; + right[0] = (-1 * sr * sp * cy + -1 * cr * -sy); + right[1] = (-1 * sr * sp * sy + -1 * cr * cy); + right[2] = -1 * sr * cp; + up[0] = (cr * sp * cy + -sr * -sy); + up[1] = (cr * sp * sy + -sr * cy); + up[2] = cr * cp; +} void CSqueak::PrimaryAttack() { if ( m_pPlayer->m_rgAmmo[ m_iPrimaryAmmoType ] ) { - UTIL_MakeVectors( m_pPlayer->pev->v_angle ); + vec3_t forward, right, up; + vec3_t vEntityForward = m_pPlayer->pev->v_angle; + vEntityForward[0] = 0; + AngleVectors(vEntityForward, forward, right, up); + vEntityForward = forward; + + AngleVectors(m_pPlayer->pev->v_angle, forward, right, up); TraceResult tr; Vector trace_origin; // HACK HACK: Ugly hacks to handle change in origin based on new physics code for players // Move origin up if crouched and start trace a bit outside of body ( 20 units instead of 16 ) + float flAimDownFraction = m_pPlayer->pev->v_angle[0] > 0 ? m_pPlayer->pev->v_angle[0] / 90.f : 0; trace_origin = m_pPlayer->pev->origin; if ( m_pPlayer->pev->flags & FL_DUCKING ) { - trace_origin = trace_origin - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN ); + trace_origin = trace_origin - (flAimDownFraction + 1) * ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN ); } + + Vector vTraceForward = (flAimDownFraction * vEntityForward) + (1 - flAimDownFraction) * forward; // find place to toss monster - UTIL_TraceLine( trace_origin + gpGlobals->v_forward * 20, trace_origin + gpGlobals->v_forward * 64, dont_ignore_monsters, NULL, &tr ); + UTIL_TraceLine(trace_origin + vTraceForward * 24, trace_origin + forward * 60, dont_ignore_monsters, NULL, &tr); int flags; #ifdef CLIENT_WEAPONS @@ -519,16 +560,16 @@ void CSqueak::PrimaryAttack() flags = 0; #endif - PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 ); + PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usSnarkFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 ); - if ( tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0.25 ) + if (tr.fAllSolid == 0 && tr.fStartSolid == 0 && tr.flFraction > 0 ) { // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); #ifndef CLIENT_DLL CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", tr.vecEndPos, m_pPlayer->pev->v_angle, m_pPlayer->edict() ); - pSqueak->pev->velocity = gpGlobals->v_forward * 200 + m_pPlayer->pev->velocity; + pSqueak->pev->velocity = vTraceForward * 200 + m_pPlayer->pev->velocity; #endif // play hunt sound diff --git a/dlls/subs.cpp b/dlls/subs.cpp index 0fa7c44..288d78a 100644 --- a/dlls/subs.cpp +++ b/dlls/subs.cpp @@ -450,6 +450,31 @@ BOOL CBaseToggle :: IsLockedByMaster( void ) return FALSE; } + +void CBaseToggle::PlaySentence(const char* pszSentence, float duration, float volume, float attenuation) +{ + if ( pszSentence && IsAllowedToSpeak() ) + { + if (pszSentence[0] == '!') + EMIT_SOUND_DYN(edict(), CHAN_VOICE, pszSentence, volume, attenuation, 0, PITCH_NORM); + else + SENTENCEG_PlayRndSz(edict(), pszSentence, volume, attenuation, 0, PITCH_NORM); + } +} + +void CBaseToggle::PlayScriptedSentence(const char* pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity* pListener) +{ + PlaySentence(pszSentence, duration, volume, attenuation); +} + +void CBaseToggle::SentenceStop(void) +{ + EMIT_SOUND(edict(), CHAN_VOICE, "common/null.wav", 1.0, ATTN_IDLE); +} + + + + /* ============= AngularMove diff --git a/dlls/talkmonster.cpp b/dlls/talkmonster.cpp index 36dbf69..027d7fc 100644 --- a/dlls/talkmonster.cpp +++ b/dlls/talkmonster.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -423,11 +423,11 @@ void CTalkMonster :: StartTask( Task_t *pTask ) if (yaw < 0) { - pev->ideal_yaw = min( yaw + 45, 0 ) + pev->angles.y; + pev->ideal_yaw = min( yaw + 45.0f, 0.0f ) + pev->angles.y; } else { - pev->ideal_yaw = max( yaw - 45, 0 ) + pev->angles.y; + pev->ideal_yaw = max( yaw - 45.0f, 0.0f ) + pev->angles.y; } } TaskComplete(); @@ -1402,7 +1402,7 @@ BOOL CTalkMonster::CanFollow( void ) { if ( m_MonsterState == MONSTERSTATE_SCRIPT ) { - if ( !m_pCine->CanInterrupt() ) + if ( !m_pCine || !m_pCine->CanInterrupt() ) return FALSE; } diff --git a/dlls/talkmonster.h b/dlls/talkmonster.h index 52e5d6a..3c1ff87 100644 --- a/dlls/talkmonster.h +++ b/dlls/talkmonster.h @@ -111,7 +111,7 @@ public: int IRelationship ( CBaseEntity *pTarget ); virtual int CanPlaySentence( BOOL fDisregardState ); virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); - void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ); + virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ); void KeyValue( KeyValueData *pkvd ); // AI functions diff --git a/dlls/tempmonster.cpp b/dlls/tempmonster.cpp index 052ce6f..65e07c0 100644 --- a/dlls/tempmonster.cpp +++ b/dlls/tempmonster.cpp @@ -27,7 +27,7 @@ // Monster's Anim Events Go Here //========================================================= -class CMyMonster : public CBaseMonster +class CMyMonster : public CBaseMonster { public: void Spawn( void ); diff --git a/dlls/tentacle.cpp b/dlls/tentacle.cpp index abb0e43..08538c2 100644 --- a/dlls/tentacle.cpp +++ b/dlls/tentacle.cpp @@ -33,7 +33,7 @@ #define ACT_T_STRIKE 1030 #define ACT_T_REARIDLE 1040 -class CTentacle : public CBaseMonster +class CTentacle : public CBaseMonster { public: CTentacle( void ); diff --git a/dlls/trains.h b/dlls/trains.h index 4ca1cf7..acf91c9 100644 --- a/dlls/trains.h +++ b/dlls/trains.h @@ -124,4 +124,82 @@ private: unsigned short m_usAdjustPitch; }; +class CFuncVehicle : public CBaseEntity +{ +public: + void Spawn( void ); + void Precache( void ); + + void Blocked( CBaseEntity *pOther ); + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + void KeyValue( KeyValueData* pkvd ); + + void EXPORT Next( void ); + void EXPORT Find( void ); + void EXPORT NearestPath( void ); + void EXPORT DeadEnd( void ); + + void NextThink( float thinkTime, BOOL alwaysThink ); + int Classify (void); + void CollisionDetection(void); + void TerrainFollowing(void); + void CheckTurning(void); + + void SetTrack( CPathTrack *track ) { m_ppath = track->Nearest(pev->origin); } + void SetControls( entvars_t *pevControls ); + BOOL OnControls( entvars_t *pev ); + + void StopSound ( void ); + void UpdateSound ( void ); + + static CFuncVehicle *Instance( edict_t *pent ); + + virtual int Save( CSave &save ); + virtual int Restore( CRestore &restore ); + + static TYPEDESCRIPTION m_SaveData[]; + virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DIRECTIONAL_USE; } + + virtual void OverrideReset( void ); + + CPathTrack *m_ppath; + float m_length; + float m_width; + float m_height; + float m_speed; + float m_dir; + float m_startSpeed; + Vector m_controlMins; + Vector m_controlMaxs; + int m_soundPlaying; + int m_sounds; + int m_acceleration; + float m_flVolume; + float m_flBank; + float m_oldSpeed; + int m_iTurnAngle; + float m_flSteeringWheelDecay; + float m_flAcceleratorDecay; + float m_flTurnStartTime; + float m_flLaunchTime; //Time at which the vehicle has become airborne + float m_flLastNormalZ; + float m_flCanTurnNow; + float m_flUpdateSound; + Vector m_vFrontLeft; + Vector m_vFront; + Vector m_vFrontRight; + Vector m_vBackLeft; + Vector m_vBack; + Vector m_vBackRight; + Vector m_vSurfaceNormal; + Vector m_vVehicleDirection; + CBasePlayer *m_pDriver; + + // GOOSEMAN + void Restart(); + +private: + unsigned short m_usAdjustPitch; +}; + #endif diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index 2f94673..1f9ea5b 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -331,7 +331,7 @@ void CMultiManager :: KeyValue( KeyValueData *pkvd ) { char tmp[128]; - UTIL_StripToken( pkvd->szKeyName, tmp ); + UTIL_StripToken( pkvd->szKeyName, tmp, sizeof( tmp ) ); m_iTargetName [ m_cTargets ] = ALLOC_STRING( tmp ); m_flTargetDelay [ m_cTargets ] = atof (pkvd->szValue); m_cTargets++; @@ -1002,7 +1002,19 @@ void CBaseTrigger :: HurtTouch ( CBaseEntity *pOther ) #endif if ( fldmg < 0 ) - pOther->TakeHealth( -fldmg, m_bitsDamageInflict ); + { + BOOL bApplyHeal = TRUE; + + if ( g_pGameRules->IsMultiplayer() && pOther->IsPlayer() ) + { + bApplyHeal = pOther->pev->deadflag == DEAD_NO; + } + + if ( bApplyHeal ) + { + pOther->TakeHealth( -fldmg, m_bitsDamageInflict ); + } + } else pOther->TakeDamage( pev, pev, fldmg, m_bitsDamageInflict ); diff --git a/dlls/tripmine.cpp b/dlls/tripmine.cpp index 4b558e0..0f89bb5 100644 --- a/dlls/tripmine.cpp +++ b/dlls/tripmine.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -407,7 +407,7 @@ int CTripmine::GetItemInfo(ItemInfo *p) BOOL CTripmine::Deploy( ) { - //pev->body = 0; + pev->body = 0; return DefaultDeploy( "models/v_tripmine.mdl", "models/p_tripmine.mdl", TRIPMINE_DRAW, "trip" ); } diff --git a/dlls/turret.cpp b/dlls/turret.cpp index 45afa75..6e384f9 100644 --- a/dlls/turret.cpp +++ b/dlls/turret.cpp @@ -51,7 +51,7 @@ typedef enum TURRET_ANIM_DIE, } TURRET_ANIM; -class CBaseTurret : public CBaseMonster +class CBaseTurret : public CBaseMonster { public: void Spawn(void); diff --git a/dlls/util.cpp b/dlls/util.cpp index cee80d4..d18a776 100644 --- a/dlls/util.cpp +++ b/dlls/util.cpp @@ -1384,7 +1384,8 @@ void UTIL_StringToVector( float *pVector, const char *pString ) char *pstr, *pfront, tempString[128]; int j; - strcpy( tempString, pString ); + strncpy( tempString, pString, sizeof( tempString ) ); + tempString[ sizeof( tempString ) - 1 ] = '\0'; pstr = pfront = tempString; for ( j = 0; j < 3; j++ ) // lifted from pr_edict.c @@ -1415,7 +1416,8 @@ void UTIL_StringToIntArray( int *pVector, int count, const char *pString ) char *pstr, *pfront, tempString[128]; int j; - strcpy( tempString, pString ); + strncpy( tempString, pString, sizeof( tempString ) ); + tempString[ sizeof( tempString ) - 1 ] = '\0'; pstr = pfront = tempString; for ( j = 0; j < count; j++ ) // lifted from pr_edict.c @@ -1626,11 +1628,11 @@ float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vecto //========================================================= // UTIL_StripToken - for redundant keynames //========================================================= -void UTIL_StripToken( const char *pKey, char *pDest ) +void UTIL_StripToken( const char *pKey, char *pDest, int nLen ) { int i = 0; - while ( pKey[i] && pKey[i] != '#' ) + while ( i < nLen - 1 && pKey[i] && pKey[i] != '#' ) { pDest[i] = pKey[i]; i++; @@ -2235,7 +2237,7 @@ int CRestore::ReadField( void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCou { fieldNumber = (i+startField)%fieldCount; pTest = &pFields[ fieldNumber ]; - if ( !stricmp( pTest->fieldName, pName ) ) + if ( pTest->fieldName && !stricmp( pTest->fieldName, pName ) ) { if ( !m_global || !(pTest->flags & FTYPEDESC_GLOBAL) ) { diff --git a/dlls/util.h b/dlls/util.h index bbc3c67..ccf02cc 100644 --- a/dlls/util.h +++ b/dlls/util.h @@ -341,7 +341,7 @@ extern void UTIL_LogPrintf( char *fmt, ... ); // Sorta like FInViewCone, but for nonmonsters. extern float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir ); -extern void UTIL_StripToken( const char *pKey, char *pDest );// for redundant keynames +extern void UTIL_StripToken( const char *pKey, char *pDest, int nLen );// for redundant keynames // Misc functions extern void SetMovedir(entvars_t* pev); @@ -464,7 +464,7 @@ extern DLL_GLOBAL int g_Language; // sentence groups #define CBSENTENCENAME_MAX 16 -#define CVOXFILESENTENCEMAX 1536 // max number of sentences in game. NOTE: this must match +#define CVOXFILESENTENCEMAX 2048 // max number of sentences in game. NOTE: this must match // CVOXFILESENTENCEMAX in engine\sound.h!!! extern char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX]; diff --git a/dlls/vector.h b/dlls/vector.h index 9f475b0..e9b14c2 100644 --- a/dlls/vector.h +++ b/dlls/vector.h @@ -106,7 +106,23 @@ public: inline Vector operator*(float fl, const Vector& v) { return v * fl; } inline float DotProduct(const Vector& a, const Vector& b) { return(a.x*b.x+a.y*b.y+a.z*b.z); } inline Vector CrossProduct(const Vector& a, const Vector& b) { return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); } +inline Vector RotateVectorZ(const Vector& a, int angle) +{ + float x_old, y_old, R_angle; + Vector new_vector; + x_old = a.x; + y_old = a.y; + + R_angle = (float)(angle * (3.141517 / 180)); + + new_vector.x = (float)(x_old * cos(R_angle) - y_old * sin(R_angle)); + new_vector.y = (float)(y_old * cos(R_angle) + x_old * sin(R_angle)); + new_vector.z = 0; + return new_vector; +} + +#define vec3_t Vector #endif diff --git a/dlls/vehicle.cpp b/dlls/vehicle.cpp new file mode 100644 index 0000000..65091db --- /dev/null +++ b/dlls/vehicle.cpp @@ -0,0 +1,1100 @@ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "trains.h" +#include "saverestore.h" +#include "weapons.h" +#include "minmax.h" + +static float Fix2( float angle ) +{ + while ( angle < 0 ) + angle += 360; + while ( angle > 360 ) + angle -= 360; + + return angle; +} + + +static void FixupAngles2( Vector &v ) +{ + v.x = Fix2( v.x ); + v.y = Fix2( v.y ); + v.z = Fix2( v.z ); +} + +// --------------------------------------------------------------------- +// +// Counter-Strike drivable vehicles. +// +// --------------------------------------------------------------------- + +#define VEHICLE_STARTPITCH 60 +#define VEHICLE_MAXPITCH 200 +#define VEHICLE_MAXSPEED 1500 // approx max speed for sound pitch calculation + + +TYPEDESCRIPTION CFuncVehicle::m_SaveData[] = +{ + DEFINE_FIELD( CFuncVehicle, m_ppath, FIELD_CLASSPTR ), + DEFINE_FIELD( CFuncVehicle, m_length, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_height, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_speed, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_dir, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_startSpeed, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_controlMins, FIELD_VECTOR ), + DEFINE_FIELD( CFuncVehicle, m_controlMaxs, FIELD_VECTOR ), + DEFINE_FIELD( CFuncVehicle, m_sounds, FIELD_INTEGER ), + DEFINE_FIELD( CFuncVehicle, m_flVolume, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_flBank, FIELD_FLOAT ), + DEFINE_FIELD( CFuncVehicle, m_oldSpeed, FIELD_FLOAT ), +}; + +IMPLEMENT_SAVERESTORE( CFuncVehicle, CBaseEntity ); +LINK_ENTITY_TO_CLASS( func_vehicle, CFuncVehicle ); + +void CFuncVehicle :: KeyValue( KeyValueData *pkvd ) +{ + if (FStrEq(pkvd->szKeyName, "length")) + { + m_length = atof(pkvd->szValue); + pkvd->fHandled = TRUE; + } + if (FStrEq(pkvd->szKeyName, "width")) + { + m_width = atof(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "height")) + { + m_height = atof(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "startspeed")) + { + m_startSpeed = atof(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "sounds")) + { + m_sounds = atoi(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "volume")) + { + m_flVolume = (float) (atoi(pkvd->szValue)); + m_flVolume *= 0.1; + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "bank")) + { + m_flBank = atof(pkvd->szValue); + pkvd->fHandled = TRUE; + } + else if (FStrEq(pkvd->szKeyName, "acceleration")) + { + m_acceleration = atoi(pkvd->szValue); + if (m_acceleration < 1) + m_acceleration = 1; + else if (m_acceleration > 10) + m_acceleration = 10; + pkvd->fHandled = TRUE; + } + else + CBaseEntity::KeyValue( pkvd ); +} + + +void CFuncVehicle :: NextThink( float thinkTime, BOOL alwaysThink ) +{ + if ( alwaysThink ) + pev->flags |= FL_ALWAYSTHINK; + else + pev->flags &= ~FL_ALWAYSTHINK; + + pev->nextthink = thinkTime; +} + + +void CFuncVehicle :: Blocked( CBaseEntity *pOther ) +{ + entvars_t *pevOther = pOther->pev; + + // Blocker is on-ground on the train + if ( FBitSet( pevOther->flags, FL_ONGROUND ) && VARS(pevOther->groundentity) == pev ) + { + pevOther->velocity = pev->velocity; + return; + + float deltaSpeed = fabs(pev->speed); + if ( deltaSpeed > 50 ) + deltaSpeed = 50; + if ( !pevOther->velocity.z ) + pevOther->velocity.z += deltaSpeed; + return; + } + else + { + pevOther->velocity = (pevOther->origin - pev->origin ).Normalize() * pev->dmg; + pevOther->velocity.z += 300; + + //slow down vehicle + pev->velocity = pev->velocity * 0.85; + } + + ALERT( at_console, "TRAIN(%s): Blocked by %s (dmg:%.2f)\n", STRING(pev->targetname), STRING(pOther->pev->classname), pev->dmg ); + // we can't hurt this thing, so we're not concerned with it + + UTIL_MakeVectors( pev->angles ); + Vector vFrontLeft, vFrontRight, vBackLeft, vBackRight; + Vector forward = (gpGlobals->v_forward * -1) * (m_length/2); //for some stupid reason I have to invert this... + Vector right = (gpGlobals->v_right * -1) * (m_width/2); + + vFrontLeft = pev->origin + forward - right; + vFrontRight = pev->origin + forward + right; + vBackLeft = pev->origin - forward - right; + vBackRight = pev->origin - forward + right; + + Vector vOrigin = pOther->pev->origin; + + float minx, miny, minz; + float maxx, maxy, maxz; + + minx = min(vFrontLeft.x, vBackRight.x); + maxx = max(vFrontLeft.x, vBackRight.x); + miny = min(vFrontLeft.y, vBackRight.y); + maxy = max(vFrontLeft.y, vBackRight.y); + minz = pev->origin.z; + maxz = pev->origin.z + abs(pev->mins.z - pev->maxs.z) * 2; + + // Check if the target is out of the bounds of the vehicle... + if ( ((vOrigin.x < minx) || (vOrigin.x > maxx)) + || ((vOrigin.y < miny) || (vOrigin.y > maxy)) + || ((vOrigin.z < minz) || (vOrigin.z > maxz)) ) + pOther->TakeDamage(pev, pev, 150, DMG_CRUSH); +} + + +void CFuncVehicle :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +{ + if ( useType != USE_SET ) + { + if ( !ShouldToggle( useType, (pev->speed != 0) ) ) + return; + + if ( pev->speed == 0 ) + { + pev->speed = m_speed * m_dir; + + Next(); + } + else + { + pev->speed = 0; + pev->velocity = g_vecZero; + pev->avelocity = g_vecZero; + StopSound(); + SetThink( NULL ); + } + } + else + { + if (value < 10) // It's either forward or backward + { + if ( (value < 0) && (pev->speed > 145) ) + { + StopSound(); + } + + float delta = value; + float flSpeedRatio; + + if (delta > 0) // accelerating + { + flSpeedRatio = (pev->speed / m_speed); + + if (pev->speed < 0) + delta = flSpeedRatio + (0.015/3) + (m_acceleration * 0.0005); + else if (pev->speed < 10) + delta = flSpeedRatio + (0.015/7) + (m_acceleration * 0.0006); + else if (pev->speed < 20) + delta = flSpeedRatio + (0.02/6) + (m_acceleration * 0.0007); + else if (pev->speed < 30) + delta = flSpeedRatio + (0.025/6) + (m_acceleration * 0.0007); + else if (pev->speed < 45) + delta = flSpeedRatio + (0.02/5) + (m_acceleration * 0.0007); + else if (pev->speed < 60) + delta = flSpeedRatio + (0.019/5) + (m_acceleration * 0.0008); + else if (pev->speed < 80) + delta = flSpeedRatio + (0.018/4) + (m_acceleration * 0.0008); + else if (pev->speed < 100) + delta = flSpeedRatio + (0.017/4) + (m_acceleration * 0.0009); + else if (pev->speed < 150) + delta = flSpeedRatio + (0.016/6) + (m_acceleration * 0.0008); + else if (pev->speed < 225) + delta = flSpeedRatio + (0.016/7) + (m_acceleration * 0.0007); + else if (pev->speed < 300) + delta = flSpeedRatio + (0.015/8) + (m_acceleration * 0.0006); + else if (pev->speed < 400) + delta = flSpeedRatio + (0.013/9) + (m_acceleration * 0.0005); + else if (pev->speed < 550) + delta = flSpeedRatio + (0.012/10) + (m_acceleration * 0.0005); + else if (pev->speed < 800) + delta = flSpeedRatio + (0.011/12) + (m_acceleration * 0.0005); + } + else if (delta < 0) // braking + { + flSpeedRatio = pev->speed / m_speed; + + if (flSpeedRatio > 0) + delta = flSpeedRatio - 0.05 / 4; + else if ( (flSpeedRatio <= 0) && (flSpeedRatio > -0.05) ) // Just started accelerating + delta = flSpeedRatio - 0.03 / 4; + else if ( (flSpeedRatio <= 0.05) && (flSpeedRatio > -0.1) ) + delta = flSpeedRatio - 0.04 / 4; + else if ( (flSpeedRatio <= 0.15) && (flSpeedRatio > -0.15) ) + delta = flSpeedRatio - 0.05 / 4; + else if ( (flSpeedRatio <= 0.15) && (flSpeedRatio > -0.22) ) + delta = flSpeedRatio - 0.055 / 4; + else if ( (flSpeedRatio <= 0.22) && (flSpeedRatio > -0.3) ) + delta = flSpeedRatio - 0.07 / 4; + else if (flSpeedRatio <= 0.3) + delta = flSpeedRatio - 0.05 / 4; + } + + if (delta > 1) + delta = 1; + else if (delta < -0.35) + delta = -0.35; + + pev->speed = m_speed * delta; + + Next(); + + m_flAcceleratorDecay = gpGlobals->time + 0.25; + } + else + { + if (m_flCanTurnNow < gpGlobals->time) + { + if (value == 20) // turn left! + { + m_iTurnAngle += 1; + m_flSteeringWheelDecay = gpGlobals->time + 0.075; + if (m_iTurnAngle > 8) + m_iTurnAngle = 8; + } + else if (value == 30) // turn right + { + m_iTurnAngle -= 1; + m_flSteeringWheelDecay = gpGlobals->time + 0.075; + if (m_iTurnAngle < -8) + m_iTurnAngle = -8; + } + + m_flCanTurnNow = gpGlobals->time + 0.05; + } + } + } +} + + +void CFuncVehicle :: StopSound( void ) +{ + // if sound playing, stop it + if (m_soundPlaying && pev->noise) + { + unsigned short us_encode; + unsigned short us_sound = ( ( unsigned short )( m_sounds ) & 0x0007 ) << 12; + + us_encode = us_sound; + + PLAYBACK_EVENT_FULL( FEV_RELIABLE | FEV_UPDATE, edict(), m_usAdjustPitch, 0.0, + (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, us_encode, 0, 1, 0 ); + } + + m_soundPlaying = 0; +} + +// update pitch based on speed, start sound if not playing +// NOTE: when train goes through transition, m_soundPlaying should go to 0, +// which will cause the looped sound to restart. + +void CFuncVehicle :: UpdateSound( void ) +{ + float flpitch; + + if (!pev->noise) + return; + + flpitch = VEHICLE_STARTPITCH + (abs(pev->speed) * (VEHICLE_MAXPITCH - VEHICLE_STARTPITCH) / VEHICLE_MAXSPEED); + + if (flpitch > VEHICLE_MAXPITCH) + flpitch = VEHICLE_MAXPITCH; + + if (!m_soundPlaying) + { + // play startup sound for train + if (m_sounds < 5) + EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, "plats/vehicle_brake1.wav", m_flVolume, ATTN_NORM, 0, 100); + EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char*)STRING(pev->noise), m_flVolume, ATTN_NORM, 0, (int) flpitch); + m_soundPlaying = 1; + } + else + { +/* + // update pitch + EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char*)STRING(pev->noise), m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, (int) flpitch); +*/ + // volume 0.0 - 1.0 - 6 bits + // m_sounds 3 bits + // flpitch = 6 bits + // 15 bits total + + unsigned short us_encode; + unsigned short us_sound = ( ( unsigned short )( m_sounds ) & 0x0007 ) << 12; + unsigned short us_pitch = ( ( unsigned short )( flpitch / 10.0 ) & 0x003f ) << 6; + unsigned short us_volume = ( ( unsigned short )( m_flVolume * 40.0 ) & 0x003f ); + + us_encode = us_sound | us_pitch | us_volume; + + PLAYBACK_EVENT_FULL( FEV_UPDATE, edict(), m_usAdjustPitch, 0.0, + (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, us_encode, 0, 0, 0 ); + + } +} + +void CFuncVehicle :: CheckTurning (void) +{ + float maxspeed; + TraceResult tr; + + bool bTurnIntoWall = false; + // Check to see if he's trying to turn into a wall + if (m_iTurnAngle < 0) // He's trying to turn right + { + if (pev->speed > 0) + { + UTIL_TraceLine ( m_vFrontRight, m_vFrontRight - (gpGlobals->v_right * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + m_iTurnAngle = 1; + } + } + else if (pev->speed < 0) + { + UTIL_TraceLine ( m_vBackLeft, m_vBackLeft + (gpGlobals->v_right * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + m_iTurnAngle = 1; + } + } + } + else if (m_iTurnAngle > 0) + { + if (pev->speed > 0) + { + UTIL_TraceLine ( m_vFrontLeft, m_vFrontLeft + (gpGlobals->v_right * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + m_iTurnAngle = -1; + } + } + else if (pev->speed < 0) + { + UTIL_TraceLine ( m_vBackRight, m_vBackRight - (gpGlobals->v_right * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + m_iTurnAngle = -1; + } + } + } + + if (pev->speed > 0) + { + if ( abs(m_iTurnAngle) > 4 ) // Doing a hard turn + { + if (m_flTurnStartTime == -1) //just started turning + { + m_flTurnStartTime = gpGlobals->time; + maxspeed = (float)m_speed; + } + else if ( (gpGlobals->time - m_flTurnStartTime) >= 0.0 ) + { + maxspeed = (float)m_speed * 0.98; + } + else if ( (gpGlobals->time - m_flTurnStartTime) > 0.3 ) + { + maxspeed = (float)m_speed * 0.95; + } + else if ( (gpGlobals->time - m_flTurnStartTime) > 0.6 ) + { + maxspeed = (float)m_speed * 0.9; + } + else if ( (gpGlobals->time - m_flTurnStartTime) > 0.8 ) + { + maxspeed = (float)m_speed * 0.8; + } + else if ( (gpGlobals->time - m_flTurnStartTime) > 1 ) + { + maxspeed = (float)m_speed * 0.7; + } + else if ( (gpGlobals->time - m_flTurnStartTime) > 1.2 ) + { + maxspeed = (float)m_speed * 0.5; + } + } + else if ( abs(m_iTurnAngle) > 2 ) + { + m_flTurnStartTime = -1; + maxspeed = (float)m_speed * 0.9; + } + else + { + maxspeed = (float)m_speed; + m_flTurnStartTime = -1; + } + + if (pev->speed > maxspeed) + { + pev->speed -= m_speed / 10; + } + } +} + +void CFuncVehicle :: CollisionDetection (void) +{ + TraceResult tr; + bool bHitSomething = false; + + // Check to see if there's anything in front of us + if (pev->speed < 0) // We're going backwards + { + // Check back left portion of vehicle if we hit a wall + UTIL_TraceLine ( m_vBackLeft, m_vBackLeft + (gpGlobals->v_forward * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + bHitSomething = true; + if ( ( DotProduct(tr.vecPlaneNormal,gpGlobals->v_forward*-1) < 0.7) && (tr.vecPlaneNormal.z < 0.1) ) // slightly vertical wall... skid along it + { + m_vSurfaceNormal = tr.vecPlaneNormal; + m_vSurfaceNormal.z = 0; + pev->speed = pev->speed * 0.99; + } + else if ( (tr.vecPlaneNormal.z < 0.65) || (tr.fStartSolid) ) + pev->speed = pev->speed * -1; + else + m_vSurfaceNormal = tr.vecPlaneNormal; + + CBaseEntity *pHit = CBaseEntity::Instance(tr.pHit); + if (pHit && (pHit->Classify() == CLASS_VEHICLE)) + ALERT(at_console, "I hit another vehicle\n"); + } + if (bHitSomething == false) + { + UTIL_TraceLine ( m_vBackRight, m_vBackRight + (gpGlobals->v_forward * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + bHitSomething = true; + if ( ( DotProduct(tr.vecPlaneNormal,gpGlobals->v_forward*-1) < 0.7) && (tr.vecPlaneNormal.z < 0.1) ) // slightly vertical wall... skid along it + { + m_vSurfaceNormal = tr.vecPlaneNormal; + m_vSurfaceNormal.z = 0; + pev->speed = pev->speed * 0.99; + } + else if ( (tr.vecPlaneNormal.z < 0.65) || (tr.fStartSolid) ) + pev->speed = pev->speed * -1; + else + m_vSurfaceNormal = tr.vecPlaneNormal; + } + } + if (bHitSomething == false) + { + UTIL_TraceLine ( m_vBack, m_vBack + (gpGlobals->v_forward * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + if ( ( DotProduct(tr.vecPlaneNormal,gpGlobals->v_forward*-1) < 0.7) && (tr.vecPlaneNormal.z < 0.1) ) // slightly vertical wall... skid along it + { + m_vSurfaceNormal = tr.vecPlaneNormal; + m_vSurfaceNormal.z = 0; + pev->speed = pev->speed * 0.99; + } + else if ( (tr.vecPlaneNormal.z < 0.65) || (tr.fStartSolid) ) + pev->speed = pev->speed * -1; + else + m_vSurfaceNormal = tr.vecPlaneNormal; + } + } + } + else if (pev->speed > 0) + { + // Check front left portion of vehicle + UTIL_TraceLine ( m_vFrontLeft, m_vFrontLeft - (gpGlobals->v_forward * 16), dont_ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + bHitSomething = true; + if ( ( DotProduct(tr.vecPlaneNormal,gpGlobals->v_forward*-1) > -0.7) && (tr.vecPlaneNormal.z < 0.1) ) // slightly vertical wall... skid along it + { + m_vSurfaceNormal = tr.vecPlaneNormal; + m_vSurfaceNormal.z = 0; + pev->speed = pev->speed * 0.99; + } + else if ( (tr.vecPlaneNormal.z < 0.65) || (tr.fStartSolid) ) + pev->speed = pev->speed * -1; + else + m_vSurfaceNormal = tr.vecPlaneNormal; + + } + if (bHitSomething == false) + { + UTIL_TraceLine ( m_vFrontRight, m_vFrontRight - (gpGlobals->v_forward * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + bHitSomething = true; + if ( ( DotProduct(tr.vecPlaneNormal,gpGlobals->v_forward*-1) > -0.7) && (tr.vecPlaneNormal.z < 0.1) ) // slightly vertical wall... skid along it + { + m_vSurfaceNormal = tr.vecPlaneNormal; + m_vSurfaceNormal.z = 0; + pev->speed = pev->speed * 0.99; + } + else if ( (tr.vecPlaneNormal.z < 0.65) || (tr.fStartSolid) ) + pev->speed = pev->speed * -1; + else + m_vSurfaceNormal = tr.vecPlaneNormal; + } + } + if (bHitSomething == false) + { + UTIL_TraceLine ( m_vFront, m_vFront - (gpGlobals->v_forward * 16), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) + { + bHitSomething = true; + if ( ( DotProduct(tr.vecPlaneNormal,gpGlobals->v_forward*-1) > -0.7) && (tr.vecPlaneNormal.z < 0.1) ) // slightly vertical wall... skid along it + { + m_vSurfaceNormal = tr.vecPlaneNormal; + m_vSurfaceNormal.z = 0; + pev->speed = pev->speed * 0.99; + } + else if ( (tr.vecPlaneNormal.z < 0.65) || (tr.fStartSolid) ) + pev->speed = pev->speed * -1; + else + m_vSurfaceNormal = tr.vecPlaneNormal; + } + } + } +} + +void CFuncVehicle :: TerrainFollowing (void) +{ + TraceResult tr; + + //Get the normal of the surface we're right on top of + UTIL_TraceLine ( pev->origin, pev->origin + Vector(0,0,-1 * (m_height + 48) ), ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + if (tr.flFraction != 1.0) // we hit something + { + m_vSurfaceNormal = tr.vecPlaneNormal; + } + else if (tr.fInWater) + { + m_vSurfaceNormal = Vector(0,0,1); + } + else if (tr.fStartSolid) + { +// ALERT(at_console,"I'm underground\n!"); + } +} + + +void CFuncVehicle :: Next( void ) +{ + Vector vGravityVector = g_vecZero; + + UTIL_MakeVectors( pev->angles ); + + Vector forward = (gpGlobals->v_forward * -1) * (m_length/2); //for some stupid reason I have to invert this... + Vector right = (gpGlobals->v_right * -1) * (m_width/2); + Vector up = (gpGlobals->v_up) * 16; + + m_vFrontLeft = pev->origin + forward - right + up; + m_vFrontRight = pev->origin + forward + right + up; + m_vFront = pev->origin + forward + up; + m_vBackLeft = pev->origin - forward - right + up; + m_vBackRight = pev->origin - forward + right + up; + m_vBack = pev->origin - forward + up; + + m_vSurfaceNormal = g_vecZero; + + + // Check to see if we're hitting something...and alter the vehicles velocity. + CheckTurning (); + + + float time = 0.1; + + if (m_flSteeringWheelDecay < gpGlobals->time) + { + m_flSteeringWheelDecay = gpGlobals->time + 0.1; + if (m_iTurnAngle < 0) + m_iTurnAngle++; + else if (m_iTurnAngle > 0) + m_iTurnAngle--; + } + + if (m_flAcceleratorDecay < gpGlobals->time) + { + m_flAcceleratorDecay = gpGlobals->time + 0.1; + if (pev->speed < 0) + { + pev->speed += 20; + if (pev->speed > 0) + pev->speed = 0; + } + else if (pev->speed > 0) + { + pev->speed -= 20; + if (pev->speed < 0) + pev->speed = 0; + } + + } + + if ( !pev->speed ) + { + m_iTurnAngle = 0; + pev->avelocity = g_vecZero; + pev->velocity = g_vecZero; +// StopSound(); + + SetThink( &CFuncVehicle::Next ); + NextThink( pev->ltime + time, TRUE ); + return; + } + else + { + TerrainFollowing(); + CollisionDetection(); + + if (m_vSurfaceNormal != g_vecZero) + { + m_vVehicleDirection = CrossProduct(m_vSurfaceNormal, (gpGlobals->v_forward)); + m_vVehicleDirection = CrossProduct(m_vSurfaceNormal, m_vVehicleDirection); + + Vector vTargetAngle, vAngle; + float vx,vy; + + vTargetAngle = UTIL_VecToAngles (m_vVehicleDirection); + vTargetAngle.y += 180; + vAngle = pev->angles; + + if (m_iTurnAngle != 0) + vTargetAngle.y += m_iTurnAngle; + + FixupAngles2(vTargetAngle); + FixupAngles2(vAngle); + + vx = UTIL_AngleDistance( vTargetAngle.x, vAngle.x ); + vy = UTIL_AngleDistance( vTargetAngle.y, vAngle.y ); + + if (vx > 10) + vx = 10; + else if (vx < -10) + vx = -10; + if (vy > 10) + vy = 10; + else if (vy < -10) + vy = -10; + pev->avelocity.y = (int)(vy * 10); + pev->avelocity.x = (int)(vx * 10); + + // reset launch time to -1 + m_flLaunchTime = -1; + m_flLastNormalZ = m_vSurfaceNormal.z; + } + else + { + time = 0.1; + if (m_flLaunchTime == -1) + { + m_flLaunchTime = gpGlobals->time; + vGravityVector = Vector (0,0,0); + pev->velocity = pev->velocity * 1.5; + } + else + { + float flAirTime; + + flAirTime = gpGlobals->time - m_flLaunchTime; + + vGravityVector = Vector (0,0, flAirTime * -35); + if (vGravityVector.z < -400) + vGravityVector.z = -400; + } + + m_vVehicleDirection = gpGlobals->v_forward * -1; + } + + Vector temp; + temp = UTIL_VecToAngles (m_vVehicleDirection); + + if (m_flUpdateSound < gpGlobals->time) + { + UpdateSound(); + m_flUpdateSound = gpGlobals->time + 1; + } + + if (m_vSurfaceNormal != g_vecZero) + { + pev->velocity = pev->speed * m_vVehicleDirection.Normalize(); + } + else + { + pev->velocity = pev->velocity + vGravityVector; + } + SetThink( &CFuncVehicle::Next ); + NextThink( pev->ltime + time, TRUE ); + return; + } + +/************************************************/ + +} + + +void CFuncVehicle::DeadEnd( void ) +{ + // Fire the dead-end target if there is one + CPathTrack *pTrack, *pNext; + + pTrack = m_ppath; + + ALERT( at_aiconsole, "TRAIN(%s): Dead end ", STRING(pev->targetname) ); + // Find the dead end path node + // HACKHACK -- This is bugly, but the train can actually stop moving at a different node depending on it's speed + // so we have to traverse the list to it's end. + if ( pTrack ) + { + if ( m_oldSpeed < 0 ) + { + do + { + pNext = pTrack->ValidPath( pTrack->GetPrevious(), TRUE ); + if ( pNext ) + pTrack = pNext; + } while ( pNext ); + } + else + { + do + { + pNext = pTrack->ValidPath( pTrack->GetNext(), TRUE ); + if ( pNext ) + pTrack = pNext; + } while ( pNext ); + } + } + + pev->velocity = g_vecZero; + pev->avelocity = g_vecZero; + if ( pTrack ) + { + ALERT( at_aiconsole, "at %s\n", STRING(pTrack->pev->targetname) ); + if ( pTrack->pev->netname ) + FireTargets( STRING(pTrack->pev->netname), this, this, USE_TOGGLE, 0 ); + } + else + ALERT( at_aiconsole, "\n" ); +} + + +void CFuncVehicle :: SetControls( entvars_t *pevControls ) +{ + Vector offset = pevControls->origin - pev->oldorigin; + + m_controlMins = pevControls->mins + offset; + m_controlMaxs = pevControls->maxs + offset; +} + + +BOOL CFuncVehicle :: OnControls( entvars_t *pevTest ) +{ + Vector offset = pevTest->origin - pev->origin; + + if ( pev->spawnflags & SF_TRACKTRAIN_NOCONTROL ) + return FALSE; + + // Transform offset into local coordinates + UTIL_MakeVectors( pev->angles ); + Vector local; + local.x = DotProduct( offset, gpGlobals->v_forward ); + local.y = -DotProduct( offset, gpGlobals->v_right ); + local.z = DotProduct( offset, gpGlobals->v_up ); + + if ( local.x >= m_controlMins.x && local.y >= m_controlMins.y && local.z >= m_controlMins.z && + local.x <= m_controlMaxs.x && local.y <= m_controlMaxs.y && local.z <= m_controlMaxs.z ) + return TRUE; + + return FALSE; +} + + +void CFuncVehicle :: Find( void ) +{ + m_ppath = CPathTrack::Instance(FIND_ENTITY_BY_TARGETNAME( NULL, STRING(pev->target) )); + if ( !m_ppath ) + return; + + entvars_t *pevTarget = m_ppath->pev; + if ( !FClassnameIs( pevTarget, "path_track" ) ) + { + ALERT( at_console, "func_track_train must be on a path of path_track\n" ); + m_ppath = NULL; + return; + } + + Vector nextPos = pevTarget->origin; + nextPos.z += m_height; + + Vector look = nextPos; + look.z -= m_height; + m_ppath->LookAhead( &look, m_length, 0 ); + look.z += m_height; + + pev->angles = UTIL_VecToAngles( look - nextPos ); + // The train actually points west + pev->angles.y += 180; + + if ( pev->spawnflags & SF_TRACKTRAIN_NOPITCH ) + pev->angles.x = 0; + UTIL_SetOrigin( pev, nextPos ); + NextThink( pev->ltime + 0.1, FALSE ); + SetThink( &CFuncVehicle::Next ); + pev->speed = m_startSpeed; + + UpdateSound(); +} + + +void CFuncVehicle :: NearestPath( void ) +{ + CBaseEntity *pTrack = NULL; + CBaseEntity *pNearest = NULL; + float dist, closest; + + closest = 1024; + + while ((pTrack = UTIL_FindEntityInSphere( pTrack, pev->origin, 1024 )) != NULL) + { + // filter out non-tracks + if ( !(pTrack->pev->flags & (FL_CLIENT|FL_MONSTER)) && FClassnameIs( pTrack->pev, "path_track" ) ) + { + dist = (pev->origin - pTrack->pev->origin).Length(); + if ( dist < closest ) + { + closest = dist; + pNearest = pTrack; + } + } + } + + if ( !pNearest ) + { + ALERT( at_console, "Can't find a nearby track !!!\n" ); + SetThink(NULL); + return; + } + + ALERT( at_aiconsole, "TRAIN: %s, Nearest track is %s\n", STRING(pev->targetname), STRING(pNearest->pev->targetname) ); + // If I'm closer to the next path_track on this path, then it's my real path + pTrack = ((CPathTrack *)pNearest)->GetNext(); + if ( pTrack ) + { + if ( (pev->origin - pTrack->pev->origin).Length() < (pev->origin - pNearest->pev->origin).Length() ) + pNearest = pTrack; + } + + m_ppath = (CPathTrack *)pNearest; + + if ( pev->speed != 0 ) + { + NextThink( pev->ltime + 0.1, FALSE ); + SetThink( &CFuncVehicle::Next ); + } +} + + +void CFuncVehicle::OverrideReset( void ) +{ + NextThink( pev->ltime + 0.1, FALSE ); + SetThink( &CFuncVehicle::NearestPath ); +} + + +CFuncVehicle *CFuncVehicle::Instance( edict_t *pent ) +{ + if ( FClassnameIs( pent, "func_vehicle" ) ) + return (CFuncVehicle *)GET_PRIVATE(pent); + return NULL; +} + +/*QUAKED func_train (0 .5 .8) ? +Trains are moving platforms that players can ride. +The targets origin specifies the min point of the train at each corner. +The train spawns at the first target it is pointing at. +If the train is the target of a button or trigger, it will not begin moving until activated. +speed default 100 +dmg default 2 +sounds +1) ratchet metal +*/ + +int CFuncVehicle::Classify(void) +{ + return CLASS_VEHICLE; +} + +void CFuncVehicle :: Spawn( void ) +{ + if ( pev->speed == 0 ) + m_speed = 165; + else + m_speed = pev->speed; + + if (m_sounds == 0) + m_sounds = 3; + + ALERT (at_console, "M_speed = %f\n", m_speed); + + pev->speed = 0; + pev->velocity = g_vecZero; + pev->avelocity = g_vecZero; + pev->impulse = m_speed; + m_acceleration = 5; + + m_dir = 1; + m_flTurnStartTime = -1; + + if ( FStringNull(pev->target) ) + ALERT( at_console, "Vehicle with no target" ); + + if ( pev->spawnflags & SF_TRACKTRAIN_PASSABLE ) + pev->solid = SOLID_NOT; + else + pev->solid = SOLID_BSP; + pev->movetype = MOVETYPE_PUSH; + + SET_MODEL( ENT(pev), STRING(pev->model) ); + + UTIL_SetSize( pev, pev->mins, pev->maxs ); + UTIL_SetOrigin( pev, pev->origin ); + + // Cache off placed origin for train controls + pev->oldorigin = pev->origin; + + m_controlMins = pev->mins; + m_controlMaxs = pev->maxs; + m_controlMaxs.z += 72; +// start trains on the next frame, to make sure their targets have had +// a chance to spawn/activate + NextThink( pev->ltime + 0.1, FALSE ); + SetThink( &CFuncVehicle::Find ); + Precache(); +} + +// GOOSEMAN +void CFuncVehicle :: Restart( void ) +{ + ALERT (at_console, "M_speed = %f\n", m_speed); + + pev->speed = 0; + pev->velocity = g_vecZero; + pev->avelocity = g_vecZero; + pev->impulse = m_speed; + + m_dir = 1; + m_flTurnStartTime = -1; + m_flUpdateSound = -1; + m_pDriver = NULL; + + if ( FStringNull(pev->target) ) + ALERT( at_console, "Vehicle with no target" ); + + UTIL_SetOrigin( pev, pev->oldorigin ); + + STOP_SOUND(ENT(pev), CHAN_STATIC, (char*)STRING(pev->noise)); +// start trains on the next frame, to make sure their targets have had +// a chance to spawn/activate + NextThink( pev->ltime + 0.1, FALSE ); + SetThink( &CFuncVehicle::Find ); +} + + +void CFuncVehicle :: Precache( void ) +{ + if (m_flVolume == 0.0) + m_flVolume = 1.0; + + switch (m_sounds) + { + case 1: PRECACHE_SOUND("plats/vehicle1.wav"); pev->noise = MAKE_STRING("plats/vehicle1.wav");break; + case 2: PRECACHE_SOUND("plats/vehicle2.wav"); pev->noise = MAKE_STRING("plats/vehicle2.wav");break; + case 3: PRECACHE_SOUND("plats/vehicle3.wav"); pev->noise = MAKE_STRING("plats/vehicle3.wav");break; + case 4: PRECACHE_SOUND("plats/vehicle4.wav"); pev->noise = MAKE_STRING("plats/vehicle4.wav");break; + case 5: PRECACHE_SOUND("plats/vehicle6.wav"); pev->noise = MAKE_STRING("plats/vehicle6.wav");break; + case 6: PRECACHE_SOUND("plats/vehicle7.wav"); pev->noise = MAKE_STRING("plats/vehicle7.wav");break; + default: PRECACHE_SOUND("plats/vehicle7.wav"); pev->noise = MAKE_STRING("plats/vehicle7.wav");break; + } + + PRECACHE_SOUND("plats/vehicle_brake1.wav"); + PRECACHE_SOUND("plats/vehicle_start1.wav"); + + m_usAdjustPitch = PRECACHE_EVENT( 1, "events/vehicle.sc" ); +} + + + +// This class defines the volume of space that the player must stand in to control the vehicle +class CFuncVehicleControls : public CBaseEntity +{ +public: + virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } + void Spawn( void ); + void EXPORT Find( void ); +}; +LINK_ENTITY_TO_CLASS( func_vehiclecontrols, CFuncVehicleControls ); + + +void CFuncVehicleControls :: Find( void ) +{ + edict_t *pTarget = NULL; + + do + { + pTarget = FIND_ENTITY_BY_TARGETNAME( pTarget, STRING(pev->target) ); + } while ( !FNullEnt(pTarget) && !FClassnameIs(pTarget, "func_vehicle") ); + + if ( FNullEnt( pTarget ) ) + { + ALERT( at_console, "No vehicle %s\n", STRING(pev->target) ); + return; + } + + CFuncVehicle *pvehicle = CFuncVehicle::Instance(pTarget); + pvehicle->SetControls( pev ); + UTIL_Remove( this ); +} + + +void CFuncVehicleControls :: Spawn( void ) +{ + pev->solid = SOLID_NOT; + pev->movetype = MOVETYPE_NONE; + SET_MODEL( ENT(pev), STRING(pev->model) ); + + UTIL_SetSize( pev, pev->mins, pev->maxs ); + UTIL_SetOrigin( pev, pev->origin ); + + SetThink( &CFuncVehicleControls::Find ); + pev->nextthink = gpGlobals->time; +} + diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index f136374..e98b6da 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -1,4 +1,4 @@ -/*** +/*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. * @@ -56,6 +56,8 @@ MULTIDAMAGE gMultiDamage; #define TRACER_FREQ 4 // Tracers fire every fourth bullet +extern bool IsBustingGame(); +extern bool IsPlayerBusting( CBaseEntity *pPlayer ); //========================================================= // MaxAmmoCarry - pass in a name and this function will tell @@ -510,6 +512,19 @@ void CBasePlayerItem::FallThink ( void ) Materialize(); } + else if ( m_pPlayer != NULL ) + { + SetThink( NULL ); + } + + //This weapon is an egon, it has no owner and we're in busting mode, so just remove it when it hits the ground + if ( IsBustingGame() && FNullEnt( pev->owner ) ) + { + if ( !strcmp( "weapon_egon", STRING( pev->classname ) ) ) + { + UTIL_Remove( this ); + } + } } //========================================================= @@ -950,7 +965,7 @@ BOOL CBasePlayerWeapon :: IsUseable( void ) if ( m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] <= 0 && iMaxAmmo1() != -1 ) { // clip is empty (or nonexistant) and the player has no more ammo of this type. - return FALSE; + return CanDeploy(); } } @@ -1107,6 +1122,9 @@ void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther ) return; } + if ( IsPlayerBusting( pOther ) ) + return; + if (AddAmmo( pOther )) { if ( g_pGameRules->AmmoShouldRespawn( this ) == GR_AMMO_RESPAWN_YES ) @@ -1139,7 +1157,7 @@ void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther ) //========================================================= int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { - int iReturn = 0; + int iReturn; if ( pszAmmo1() != NULL ) { @@ -1572,8 +1590,10 @@ IMPLEMENT_SAVERESTORE( CRpg, CBasePlayerWeapon ); TYPEDESCRIPTION CRpgRocket::m_SaveData[] = { DEFINE_FIELD( CRpgRocket, m_flIgniteTime, FIELD_TIME ), - DEFINE_FIELD( CRpgRocket, m_pLauncher, FIELD_CLASSPTR ), + DEFINE_FIELD( CRpgRocket, m_hLauncher, FIELD_EHANDLE ), }; + + IMPLEMENT_SAVERESTORE( CRpgRocket, CGrenade ); TYPEDESCRIPTION CShotgun::m_SaveData[] = diff --git a/dlls/weapons.h b/dlls/weapons.h index 4a34326..ab2d2e7 100644 --- a/dlls/weapons.h +++ b/dlls/weapons.h @@ -36,7 +36,7 @@ public: static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code ); void Explode( Vector vecSrc, Vector vecAim ); - void Explode( TraceResult *pTrace, int bitsDamageType ); + virtual void Explode( TraceResult *pTrace, int bitsDamageType ); void EXPORT Smoke( void ); void EXPORT BounceTouch( CBaseEntity *pOther ); @@ -99,7 +99,7 @@ public: #define RPG_WEIGHT 20 #define GAUSS_WEIGHT 20 #define EGON_WEIGHT 20 -#define HORNETGUN_WEIGHT 10 +#define HORNETGUN_WEIGHT 15 #define HANDGRENADE_WEIGHT 5 #define SNARK_WEIGHT 5 #define SATCHEL_WEIGHT -10 @@ -191,6 +191,7 @@ typedef enum #define ITEM_FLAG_NOAUTOSWITCHEMPTY 4 #define ITEM_FLAG_LIMITINWORLD 8 #define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon +#define ITEM_FLAG_NOAUTOSWITCHTO 32 #define WEAPON_IS_ONTARGET 0x40 @@ -647,6 +648,7 @@ public: BOOL Deploy( ); void Reload( void ); void WeaponIdle( void ); + void ItemPostFrame( void ); int m_fInReload; float m_flNextReload; int m_iShell; @@ -736,11 +738,17 @@ public: void EXPORT FollowThink( void ); void EXPORT IgniteThink( void ); void EXPORT RocketTouch( CBaseEntity *pOther ); + + virtual void Explode( TraceResult *pTrace, int bitsDamageType ); + static CRpgRocket *CreateRpgRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CRpg *pLauncher ); + CRpg* GetLauncher(); + int m_iTrail; float m_flIgniteTime; - CRpg *m_pLauncher;// pointer back to the launcher that fired me. + + EHANDLE m_hLauncher; // pointer back to the launcher that fired me. }; class CGauss : public CBasePlayerWeapon @@ -828,6 +836,7 @@ public: void Fire( const Vector &vecOrigSrc, const Vector &vecDir ); BOOL HasAmmo( void ); + BOOL CanHolster(); void UseAmmo( int count ); diff --git a/dlls/world.cpp b/dlls/world.cpp index 945be75..5e1d634 100644 --- a/dlls/world.cpp +++ b/dlls/world.cpp @@ -230,7 +230,7 @@ static void InitBodyQue(void) // void CopyToBodyQue(entvars_t *pev) { - if (pev->effects & EF_NODRAW) + if (pev->effects & EF_NODRAW || pev->modelindex == 0 ) return; entvars_t *pevHead = VARS(g_pBodyQueueHead); @@ -467,13 +467,11 @@ LINK_ENTITY_TO_CLASS( worldspawn, CWorld ); #define SF_WORLD_FORCETEAM 0x0004 // Force teams extern DLL_GLOBAL BOOL g_fGameOver; -float g_flWeaponCheat; void CWorld :: Spawn( void ) { g_fGameOver = FALSE; Precache( ); - g_flWeaponCheat = CVAR_GET_FLOAT( "sv_cheats" ); // Is the impulse 101 command allowed? } void CWorld :: Precache( void ) diff --git a/dlls/wpn_shared/hl_wpn_glock.cpp b/dlls/wpn_shared/hl_wpn_glock.cpp index a72d52c..a113103 100644 --- a/dlls/wpn_shared/hl_wpn_glock.cpp +++ b/dlls/wpn_shared/hl_wpn_glock.cpp @@ -176,13 +176,7 @@ void CGlock::Reload( void ) if ( m_pPlayer->ammo_9mm <= 0 ) return; - int iResult; - - if (m_iClip == 0) - iResult = DefaultReload( 17, GLOCK_RELOAD, 1.5 ); - else - iResult = DefaultReload( 17, GLOCK_RELOAD_NOT_EMPTY, 1.5 ); - + int iResult = DefaultReload( GLOCK_MAX_CLIP, m_iClip > 0 ? GLOCK_RELOAD_NOT_EMPTY : GLOCK_RELOAD, 1.5 ); if (iResult) { m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); diff --git a/dlls/zombie.cpp b/dlls/zombie.cpp index 8c5ddd6..0086272 100644 --- a/dlls/zombie.cpp +++ b/dlls/zombie.cpp @@ -37,7 +37,7 @@ class CZombie : public CBaseMonster { public: - void Spawn( void ); + void Spawn( void ); void Precache( void ); void SetYawSpeed( void ); int Classify ( void ); @@ -169,18 +169,16 @@ void CZombie :: AlertSound( void ) void CZombie :: IdleSound( void ) { - int pitch = 100 + RANDOM_LONG(-5,5); + int pitch = 95 + RANDOM_LONG(0,9); // Play a random idle sound - EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pIdleSounds[ RANDOM_LONG(0,ARRAYSIZE(pIdleSounds)-1) ], 1.0, ATTN_NORM, 0, pitch ); + EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pIdleSounds[ RANDOM_LONG(0,ARRAYSIZE(pIdleSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); } void CZombie :: AttackSound( void ) { - int pitch = 100 + RANDOM_LONG(-5,5); - // Play a random attack sound - EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAttackSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, pitch ); + EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAttackSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) ); } diff --git a/dmc/cl_dll/ammo.cpp b/dmc/cl_dll/ammo.cpp index a607739..88e8063 100644 --- a/dmc/cl_dll/ammo.cpp +++ b/dmc/cl_dll/ammo.cpp @@ -611,14 +611,16 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf ) WEAPON Weapon; - strcpy( Weapon.szName, READ_STRING() ); + strncpy( Weapon.szName, READ_STRING(), sizeof(Weapon.szName) ); + Weapon.szName[ sizeof(Weapon.szName) - 1 ] = '\0'; + Weapon.iAmmoType = (int)READ_CHAR(); Weapon.iMax1 = READ_BYTE(); if (Weapon.iMax1 == 255) Weapon.iMax1 = -1; - Weapon.iAmmo2Type = READ_BYTE(); + Weapon.iAmmo2Type = READ_CHAR(); Weapon.iMax2 = READ_BYTE(); if (Weapon.iMax2 == 255) Weapon.iMax2 = -1; @@ -631,6 +633,27 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf ) Weapon.iClip = 0; + if (Weapon.iId < 0 || Weapon.iId >= MAX_WEAPONS) + return 0; + + if (Weapon.iSlot < 0 || Weapon.iSlot >= MAX_WEAPON_SLOTS+1) + return 0; + + if (Weapon.iSlotPos < 0 || Weapon.iSlotPos >= MAX_WEAPON_POSITIONS+1) + return 0; + + if (Weapon.iAmmoType < -1 || Weapon.iAmmoType >= MAX_AMMO_TYPES) + return 0; + + if (Weapon.iAmmo2Type < -1 || Weapon.iAmmo2Type >= MAX_AMMO_TYPES) + return 0; + + if (Weapon.iAmmoType >= 0 && Weapon.iMax1 == 0) + return 0; + + if (Weapon.iAmmo2Type >= 0 && Weapon.iMax2 == 0) + return 0; + gWR.AddWeapon( &Weapon ); return 1; @@ -831,7 +854,7 @@ int CHudAmmo::Draw(float flTime) AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; - a = (int) max( MIN_ALPHA, m_fFade ); + a = max( MIN_ALPHA, m_fFade ); if (m_fFade > 0) m_fFade -= (gHUD.m_flTimeDelta * 20); diff --git a/dmc/cl_dll/ammo_secondary.cpp b/dmc/cl_dll/ammo_secondary.cpp index e2a2f59..f4cc316 100644 --- a/dmc/cl_dll/ammo_secondary.cpp +++ b/dmc/cl_dll/ammo_secondary.cpp @@ -61,7 +61,7 @@ int CHudAmmoSecondary :: Draw(float flTime) // draw secondary ammo icons above normal ammo readout int a, x, y, r, g, b, AmmoWidth; UnpackRGB( r, g, b, RGB_YELLOWISH ); - a = (int) max( MIN_ALPHA, m_fFade ); + a = max( MIN_ALPHA, m_fFade ); if (m_fFade > 0) m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons ScaleColors( r, g, b, a ); diff --git a/dmc/cl_dll/ammohistory.cpp b/dmc/cl_dll/ammohistory.cpp index bc78dad..864ec17 100644 --- a/dmc/cl_dll/ammohistory.cpp +++ b/dmc/cl_dll/ammohistory.cpp @@ -126,7 +126,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime ) int r, g, b; UnpackRGB(r,g,b, RGB_YELLOWISH); float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - ScaleColors(r, g, b, min(scale, 255) ); + ScaleColors(r, g, b, min(scale, 255) ); // Draw the pic int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); @@ -154,7 +154,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime ) UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - ScaleColors(r, g, b, min(scale, 255) ); + ScaleColors(r, g, b, min(scale, 255) ); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); @@ -172,7 +172,7 @@ int HistoryResource :: DrawAmmoHistory( float flTime ) UnpackRGB(r,g,b, RGB_YELLOWISH); float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - ScaleColors(r, g, b, min(scale, 255) ); + ScaleColors(r, g, b, min(scale, 255) ); int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); int xpos = ScreenWidth - (rect.right - rect.left) - 10; diff --git a/dmc/cl_dll/cl_util.h b/dmc/cl_dll/cl_util.h index 33162ec..a14d29c 100644 --- a/dmc/cl_dll/cl_util.h +++ b/dmc/cl_dll/cl_util.h @@ -83,6 +83,7 @@ inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int fl #define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) #define ServerCmd (*gEngfuncs.pfnServerCmd) #define ClientCmd (*gEngfuncs.pfnClientCmd) +#define FilteredClientCmd (*gEngfuncs.pfnFilteredClientCmd) #define SetCrosshair (*gEngfuncs.pfnSetCrosshair) #define AngleVectors (*gEngfuncs.pfnAngleVectors) @@ -165,8 +166,6 @@ inline int safe_sprintf( char *dst, int len_dst, const char *format, ...) inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); } inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); } -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) #define fabs(x) ((x) > 0 ? (x) : 0 - (x)) void ScaleColors( int &r, int &g, int &b, int a ); diff --git a/dmc/cl_dll/death.cpp b/dmc/cl_dll/death.cpp index 086a539..6f8dcad 100644 --- a/dmc/cl_dll/death.cpp +++ b/dmc/cl_dll/death.cpp @@ -93,7 +93,7 @@ int CHudDeathNotice :: Init( void ) HOOK_MESSAGE( DeathMsg ); - CVAR_CREATE( "hud_deathnotice_time", "6", 0 ); + CVAR_CREATE( "hud_deathnotice_time", "6", FCVAR_ARCHIVE ); return 1; } diff --git a/dmc/cl_dll/ev_hldm.cpp b/dmc/cl_dll/ev_hldm.cpp index 2a9b2e4..81652f6 100644 --- a/dmc/cl_dll/ev_hldm.cpp +++ b/dmc/cl_dll/ev_hldm.cpp @@ -83,6 +83,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v { // hit the world, try to play sound based on texture material type char chTextureType = CHAR_TEX_CONCRETE; + cl_entity_t *cl_entity = NULL; float fvol; float fvolbar; char *rgsz[4]; @@ -101,12 +102,7 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v chTextureType = 0; // Player - if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) - { - // hit body - chTextureType = CHAR_TEX_FLESH; - } - else if ( entity == 0 ) + if ( entity == 0 ) { // get texture from entity or world (world is ent(0)) pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); @@ -135,6 +131,20 @@ float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *v chTextureType = PM_FindTextureType( szbuffer ); } } + else + { + // JoshA: Look up the entity and find the EFLAG_FLESH_SOUND flag. + // This broke at some point then TF:C added prediction. + // + // It used to use Classify of pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE + // to determine what sound to play, but that's server side and isn't available on the client + // and got lost in the translation to that. + // Now the server will replicate that state via an eflag. + cl_entity = gEngfuncs.GetEntityByIndex( entity ); + + if ( cl_entity && !!( cl_entity->curstate.eflags & EFLAG_FLESH_SOUND ) ) + chTextureType = CHAR_TEX_FLESH; + } switch (chTextureType) { diff --git a/dmc/cl_dll/geiger.cpp b/dmc/cl_dll/geiger.cpp index 9944267..8fa1407 100644 --- a/dmc/cl_dll/geiger.cpp +++ b/dmc/cl_dll/geiger.cpp @@ -68,10 +68,14 @@ int CHudGeiger::Draw (float flTime) int rg[3]; int i; - if (m_iGeigerRange <= 800 && m_iGeigerRange > 0) + if (m_iGeigerRange < 1000 && m_iGeigerRange > 0) { // peicewise linear is better than continuous formula for this - if (m_iGeigerRange > 600) + if (m_iGeigerRange > 800) + { + pct = 0; //Con_Printf ( "range > 800\n"); + } + else if (m_iGeigerRange > 600) { pct = 2; flvol = 0.4; //Con_Printf ( "range > 600\n"); diff --git a/dmc/cl_dll/health.cpp b/dmc/cl_dll/health.cpp index 8d7f6df..4d7eceb 100644 --- a/dmc/cl_dll/health.cpp +++ b/dmc/cl_dll/health.cpp @@ -309,49 +309,49 @@ int CHudHealth::DrawPain(float flTime) if (m_fAttackFront > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackFront, 0.5 ); + shade = a * max( m_fAttackFront, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2; y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3; SPR_DrawAdditive(0, x, y, NULL); - m_fAttackFront = max( 0, m_fAttackFront - fFade ); + m_fAttackFront = max( 0.0f, m_fAttackFront - fFade ); } else m_fAttackFront = 0; if (m_fAttackRight > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackRight, 0.5 ); + shade = a * max( m_fAttackRight, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2; y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2; SPR_DrawAdditive(1, x, y, NULL); - m_fAttackRight = max( 0, m_fAttackRight - fFade ); + m_fAttackRight = max( 0.0f, m_fAttackRight - fFade ); } else m_fAttackRight = 0; if (m_fAttackRear > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackRear, 0.5 ); + shade = a * max( m_fAttackRear, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2; y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2; SPR_DrawAdditive(2, x, y, NULL); - m_fAttackRear = max( 0, m_fAttackRear - fFade ); + m_fAttackRear = max( 0.0f, m_fAttackRear - fFade ); } else m_fAttackRear = 0; if (m_fAttackLeft > 0.4) { GetPainColor(r,g,b); - shade = a * max( m_fAttackLeft, 0.5 ); + shade = a * max( m_fAttackLeft, 0.5f ); ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b ); @@ -359,7 +359,7 @@ int CHudHealth::DrawPain(float flTime) y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2; SPR_DrawAdditive(3, x, y, NULL); - m_fAttackLeft = max( 0, m_fAttackLeft - fFade ); + m_fAttackLeft = max( 0.0f, m_fAttackLeft - fFade ); } else m_fAttackLeft = 0; diff --git a/dmc/cl_dll/hud.cpp b/dmc/cl_dll/hud.cpp index 65fa852..3ce79c6 100644 --- a/dmc/cl_dll/hud.cpp +++ b/dmc/cl_dll/hud.cpp @@ -211,8 +211,8 @@ void CHud :: Init( void ) m_iLogo = 0; m_iFOV = 0; - CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 ); - default_fov = CVAR_CREATE( "default_fov", "90", 0 ); + CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", FCVAR_ARCHIVE ); + default_fov = CVAR_CREATE( "default_fov", "90", FCVAR_ARCHIVE ); cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); diff --git a/dmc/cl_dll/hud_redraw.cpp b/dmc/cl_dll/hud_redraw.cpp index 444343a..1b8089f 100644 --- a/dmc/cl_dll/hud_redraw.cpp +++ b/dmc/cl_dll/hud_redraw.cpp @@ -50,7 +50,7 @@ void CHud::Think(void) // think about default fov if ( m_iFOV == 0 ) { // only let players adjust up in fov, and only if they are not overriden by something else - m_iFOV = max( default_fov->value, 90 ); + m_iFOV = max( default_fov->value, 90 );; } diff --git a/dmc/cl_dll/hud_spectator.cpp b/dmc/cl_dll/hud_spectator.cpp index c043b9e..105cce9 100644 --- a/dmc/cl_dll/hud_spectator.cpp +++ b/dmc/cl_dll/hud_spectator.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ +//========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============ // // Purpose: // @@ -162,7 +162,8 @@ void UTIL_StringToVector( float * pVector, const char *pString ) char *pstr, *pfront, tempString[128]; int j; - strcpy( tempString, pString ); + strncpy( tempString, pString, sizeof( tempString ) ); + tempString[ sizeof( tempString ) - 1 ] = '\0'; pstr = pfront = tempString; for ( j = 0; j < 3; j++ ) @@ -578,7 +579,7 @@ void CHudSpectator::DirectorMessage( int iSize, void *pbuf ) */ case DRC_CMD_STUFFTEXT: - ClientCmd( READ_STRING() ); + FilteredClientCmd( READ_STRING() ); break; default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd ); diff --git a/dmc/cl_dll/inputw32.cpp b/dmc/cl_dll/inputw32.cpp index c8a0f7c..be3d1bb 100644 --- a/dmc/cl_dll/inputw32.cpp +++ b/dmc/cl_dll/inputw32.cpp @@ -9,6 +9,7 @@ // 02/21/97 JCB Added extended DirectInput code to support external controllers. #include "port.h" +#include #include #include @@ -111,7 +112,7 @@ enum _ControlList DWORD dwAxisMap[ JOY_MAX_AXES ]; DWORD dwControlMap[ JOY_MAX_AXES ]; -DWORD pdwRawValue[ JOY_MAX_AXES ]; +int pdwRawValue[ JOY_MAX_AXES ]; DWORD joy_oldbuttonstate, joy_oldpovstate; int joy_id; @@ -134,6 +135,7 @@ cvar_t *joy_advaxisz; cvar_t *joy_advaxisr; cvar_t *joy_advaxisu; cvar_t *joy_advaxisv; +cvar_t *joy_supported; cvar_t *joy_forwardthreshold; cvar_t *joy_sidethreshold; cvar_t *joy_pitchthreshold; @@ -269,6 +271,18 @@ void IN_ResetMouse( void ) { } +/* +=========== +IN_ResetRelativeMouseState +=========== +*/ +void IN_ResetRelativeMouseState(void) +{ + SDL_PumpEvents(); + int deltaX, deltaY; + SDL_GetRelativeMouseState(&deltaX, &deltaY); +} + /* =========== IN_MouseEvent @@ -742,8 +756,6 @@ void IN_JoyMove ( float frametime, usercmd_t *cmd ) { // get the floating point zero-centered, potentially-inverted data for the current axis fAxisValue = (float) pdwRawValue[i]; - // move centerpoint to zero - fAxisValue -= 32768.0; if (joy_wwhack2->value != 0.0) { @@ -907,7 +919,7 @@ IN_Init void IN_Init (void) { m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE ); - sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE ); // user mouse sensitivity setting. + sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE | FCVAR_FILTERSTUFFTEXT ); // user mouse sensitivity setting. in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE ); joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 ); @@ -918,6 +930,7 @@ void IN_Init (void) joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 ); joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 ); joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 ); + joy_supported = gEngfuncs.pfnRegisterVariable ( "joysupported", "1", 0 ); joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 ); joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 ); joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 ); diff --git a/dmc/cl_dll/menu.cpp b/dmc/cl_dll/menu.cpp index 47ed242..9f5aab3 100644 --- a/dmc/cl_dll/menu.cpp +++ b/dmc/cl_dll/menu.cpp @@ -138,6 +138,10 @@ int CHudMenu :: Draw( float flTime ) } } + SCREENINFO screenInfo; + screenInfo.iSize = sizeof(SCREENINFO); + gEngfuncs.pfnGetScreenInfo(&screenInfo); + // don't draw the menu if the scoreboard is being shown if ( gViewPort && gViewPort->IsScoreBoardVisible() ) return 1; @@ -153,8 +157,10 @@ int CHudMenu :: Draw( float flTime ) nlc++; } + int nFontHeight = max(12, screenInfo.iCharHeight); + // center it - int y = (ScreenHeight/2) - ((nlc/2)*12) - 40; // make sure it is above the say text + int y = (ScreenHeight / 2) - ((nlc / 2) * nFontHeight) - (3 * nFontHeight + nFontHeight / 3); // make sure it is above the say text menu_r = 255; menu_g = 255; @@ -174,7 +180,7 @@ int CHudMenu :: Draw( float flTime ) { menu_ralign = FALSE; menu_x = 20; - y += (12); + y += nFontHeight; sptr++; } diff --git a/dmc/cl_dll/meson.build b/dmc/cl_dll/meson.build new file mode 100644 index 0000000..2befe1d --- /dev/null +++ b/dmc/cl_dll/meson.build @@ -0,0 +1,165 @@ +dmc_client_src = [ + 'CTF_FlagStatus.cpp', + 'CTF_HudMessage.cpp', + 'DMC_Teleporters.cpp', + 'ev_hldm.cpp', + 'quake/quake_baseentity.cpp', + 'quake/quake_events.cpp', + '../dlls/quake_gun.cpp', + 'quake/quake_objects.cpp', + 'quake/quake_weapons.cpp', + '../dlls/quake_weapons_all.cpp', + 'studio_util.cpp', + 'vgui_SpectatorPanel.cpp', + 'ammo.cpp', + 'ammo_secondary.cpp', + 'ammohistory.cpp', + 'battery.cpp', + 'cdll_int.cpp', + 'com_weapons.cpp', + 'death.cpp', + 'demo.cpp', + 'entity.cpp', + 'ev_common.cpp', + 'events.cpp', + 'GameStudioModelRenderer.cpp', + 'geiger.cpp', + 'health.cpp', + 'hud.cpp', + 'hud_msg.cpp', + 'hud_redraw.cpp', + 'hud_servers.cpp', + 'hud_spectator.cpp', + 'hud_update.cpp', + 'in_camera.cpp', + 'input.cpp', + 'inputw32.cpp', + '../../public/interface.cpp', + 'menu.cpp', + 'message.cpp', + '../../common/parsemsg.cpp', + '../pm_shared/pm_debug.c', + '../pm_shared/pm_math.c', + '../pm_shared/pm_shared.c', + 'saytext.cpp', + #'scoreboard.cpp', <-- tagged as excluded from build in old .dsp + 'status_icons.cpp', + 'statusbar.cpp', + 'StudioModelRenderer.cpp', + 'text_message.cpp', + 'train.cpp', + 'tri.cpp', + 'util.cpp', + '../../game_shared/vgui_checkbutton2.cpp', + '../../game_shared/vgui_grid.cpp', + '../../game_shared/vgui_helpers.cpp', + 'vgui_int.cpp', + '../../game_shared/vgui_listbox.cpp', + '../../game_shared/vgui_loadtga.cpp', + 'vgui_ScorePanel.cpp', + '../../game_shared/vgui_scrollbar2.cpp', + 'vgui_ServerBrowser.cpp', + '../../game_shared/vgui_slider2.cpp', + 'vgui_viewport.cpp', + 'view.cpp', + '../../game_shared/voice_banmgr.cpp', + 'voice_status.cpp', + 'ammo.h', + 'ammohistory.h', + 'camera.h', + 'cl_dll.h', + 'cl_util.h', + 'com_weapons.h', + 'demo.h', + 'DMC_BSPFile.h', + 'DMC_Teleporters.h', + 'ev_hldm.h', + 'eventscripts.h', + 'GameStudioModelRenderer.h', + 'health.h', + 'hud.h', + 'hud_iface.h', + 'hud_servers.h', + 'hud_servers_priv.h', + 'hud_spectator.h', + 'in_defs.h', + 'kbutton.h', + '../../common/parsemsg.h', + '../pm_shared/pm_debug.h', + '../pm_shared/pm_defs.h', + '../pm_shared/pm_info.h', + '../pm_shared/pm_materials.h', + '../pm_shared/pm_movevars.h', + '../pm_shared/pm_shared.h', + '../dlls/quake_gun.h', + 'StudioModelRenderer.h', + '../dlls/util.h', + 'util_vector.h', + '../../game_shared/vgui_checkbutton2.h', + 'vgui_ControlConfigPanel.h', + '../../game_shared/vgui_grid.h', + '../../game_shared/vgui_helpers.h', + 'vgui_int.h', + '../../game_shared/vgui_listbox.h', + '../../game_shared/vgui_loadtga.h', + 'vgui_SchemeManager.h', + 'vgui_ScorePanel.h', + 'vgui_ServerBrowser.h', + 'vgui_SpectatorPanel.h', + 'vgui_viewport.h', + 'view.h', + 'voice_status.h', + 'wrect.h', + 'vgui_CustomObjects.cpp', + 'vgui_MOTDWindow.cpp', + 'vgui_SchemeManager.cpp', +] + +dmc_client_defines = [ + '-DVOXEL', + '-DQUAKE2', + '-DVALVE_DLL', + '-DCLIENT_DLL', + '-DDMC_BUILD', +] + +dmc_client_includes = include_directories([ + '../../public', + '../dlls', + '../../engine', + '../../common', + '../pm_shared', + '../../utils/vgui/include', + '.', + '../../game_shared', + '../../external', +]) + +dmc_client_deps = [ + vgui2_dep, + vgui_dep, + SDL2_dep, + ws2_32_dep, + vgui_controls_dep, + game_controls_dep, + steam_api_dep, +] + +install_dir = '/dmc/cl_dlls' +target_name = 'client' +dmc_client_lib = shared_library(target_name, dmc_client_src, + dependencies : dmc_client_deps, + cpp_args : dmc_client_defines, + c_args : dmc_client_defines, + include_directories : [ dmc_client_includes ], + install : true, + install_dir : output_dir + install_dir, +) + +dmc_client_dep = declare_dependency( + link_with : [ dmc_client_lib ], +) + +cmd = join_paths(meson.current_build_dir(), '..\..\..\devtools\meson_set_outdir.bat') +cs = run_command(cmd, [target_name, meson.current_build_dir(), install_dir], check: false) +#message(cs.stdout()) \ No newline at end of file diff --git a/dmc/cl_dll/message.cpp b/dmc/cl_dll/message.cpp index b4d8118..936754c 100644 --- a/dmc/cl_dll/message.cpp +++ b/dmc/cl_dll/message.cpp @@ -20,6 +20,7 @@ #include "hud.h" #include "cl_util.h" +#include "commonmacros.h" #include #include #include "parsemsg.h" @@ -143,13 +144,13 @@ void CHudMessage::MessageScanNextChar( void ) srcGreen = m_parms.pMessage->g1; srcBlue = m_parms.pMessage->b1; blend = 0; // Pure source - destRed = destGreen = destBlue = 0; switch( m_parms.pMessage->effect ) { // Fade-in / Fade-out case 0: case 1: + destRed = destGreen = destBlue = 0; blend = m_parms.fadeBlend; break; @@ -164,6 +165,7 @@ void CHudMessage::MessageScanNextChar( void ) { float deltaTime = m_parms.time - m_parms.charTime; + destRed = destGreen = destBlue = 0; if ( m_parms.time > m_parms.fadeTime ) { blend = m_parms.fadeBlend; @@ -281,7 +283,7 @@ void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time ) { m_parms.lineLength = 0; m_parms.width = 0; - while ( *pText && *pText != '\n' ) + while ( *pText && *pText != '\n' && m_parms.lineLength < ARRAYSIZE( line ) - 1 ) { unsigned char c = *pText; line[m_parms.lineLength] = c; diff --git a/dmc/cl_dll/text_message.cpp b/dmc/cl_dll/text_message.cpp index 721c245..b6f4942 100644 --- a/dmc/cl_dll/text_message.cpp +++ b/dmc/cl_dll/text_message.cpp @@ -44,6 +44,7 @@ int CHudTextMessage::Init(void) // the new value is pushed into dst_buffer char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ) { + int len = buffer_size; char *dst = dst_buffer; for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- ) { @@ -83,7 +84,7 @@ char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, in } } - dst_buffer[buffer_size-1] = 0; // ensure null termination + dst_buffer[len-1] = 0; // ensure null termination return dst_buffer; } @@ -189,7 +190,7 @@ int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf case HUD_PRINTNOTIFY: psz[0] = 1; // mark this message to go into the notify buffer - safe_sprintf( psz+1, MSG_BUF_SIZE, msg_text, sstr1, sstr2, sstr3, sstr4 ); + safe_sprintf( psz+1, MSG_BUF_SIZE - 1, msg_text, sstr1, sstr2, sstr3, sstr4 ); ConsolePrint( ConvertCRtoNL( psz ) ); break; diff --git a/dmc/cl_dll/vgui_viewport.cpp b/dmc/cl_dll/vgui_viewport.cpp index a7c8746..aa00123 100644 --- a/dmc/cl_dll/vgui_viewport.cpp +++ b/dmc/cl_dll/vgui_viewport.cpp @@ -78,6 +78,7 @@ int g_iUser3 = 0; void IN_ResetMouse( void ); +void IN_ResetRelativeMouseState(void); extern CMenuPanel* CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ); extern float * GetClientColor( int clientIndex ); @@ -1537,6 +1538,13 @@ void TeamFortressViewport::UpdateCursorState() } IN_ResetMouse(); + + if (g_iVisibleMouse) + { + //Clear any residual input so our camera doesn't jerk when dismissing the UI + IN_ResetRelativeMouseState(); + } + g_iVisibleMouse = false; App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::scu_none) ); } diff --git a/dmc/cl_dll/view.cpp b/dmc/cl_dll/view.cpp index 13dfc86..db8b263 100644 --- a/dmc/cl_dll/view.cpp +++ b/dmc/cl_dll/view.cpp @@ -200,8 +200,8 @@ float V_CalcBob ( struct ref_params_s *pparams ) bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value; bob = bob * 0.3 + bob * 0.7 * sin(cycle); - bob = min( bob, 4 ); - bob = max( bob, -7 ); + bob = min( bob, 4.0f ); + bob = max( bob, -7.0f ); return bob; } @@ -368,9 +368,6 @@ void V_CalcGunAngle ( struct ref_params_s *pparams ) // don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view. viewent->angles[PITCH] -= v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * (v_ipitch_level.value * 0.5); viewent->angles[YAW] -= v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; - - VectorCopy( viewent->angles, viewent->curstate.angles ); - VectorCopy( viewent->angles, viewent->latched.prevangles ); } /* @@ -818,6 +815,15 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams ) } } + // Update the latched view origin/angles here, this was + // previously done in V_CalcGunAngle but that happens + // before a bunch of other stuff happens, which nukes + // a bunch of the viewbob fx. + VectorCopy( view->origin, view->curstate.origin ); + VectorCopy( view->origin, view->latched.prevorigin ); + VectorCopy( view->angles, view->curstate.angles ); + VectorCopy( view->angles, view->latched.prevangles ); + lasttime = pparams->time; v_origin = pparams->vieworg; @@ -1554,7 +1560,7 @@ void V_DropPunchAngle ( float frametime, float *ev_punchangle ) len = VectorNormalize ( ev_punchangle ); len -= (10.0 + len * 0.5) * frametime; - len = max( len, 0.0 ); + len = max( len, 0.0f ); VectorScale ( ev_punchangle, len, ev_punchangle ); } @@ -1587,7 +1593,7 @@ void V_Init (void) v_centerspeed = gEngfuncs.pfnRegisterVariable( "v_centerspeed","500", 0 ); cl_bobcycle = gEngfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0 );// best default for my experimental gun wag (sjb) - cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", 0 );// best default for my experimental gun wag (sjb) + cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", FCVAR_ARCHIVE );// best default for my experimental gun wag (sjb) cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 ); cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 ); cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 ); diff --git a/dmc/dlls/basemonster.h b/dmc/dlls/basemonster.h index 190965d..6728b5c 100644 --- a/dmc/dlls/basemonster.h +++ b/dmc/dlls/basemonster.h @@ -108,6 +108,8 @@ public: SCRIPTSTATE m_scriptState; // internal cinematic state CCineMonster *m_pCine; + float m_flLastYawTime; // Last time yaw change was computed + virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); diff --git a/dmc/dlls/cbase.h b/dmc/dlls/cbase.h index a26595b..de43446 100644 --- a/dmc/dlls/cbase.h +++ b/dmc/dlls/cbase.h @@ -59,6 +59,9 @@ CBaseEntity #endif #endif +#if defined EXPORT + #undef EXPORT +#endif #define EXPORT CBASE_DLLEXPORT extern "C" CBASE_DLLEXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); diff --git a/dmc/dlls/client.cpp b/dmc/dlls/client.cpp index a248f37..724b53f 100644 --- a/dmc/dlls/client.cpp +++ b/dmc/dlls/client.cpp @@ -374,8 +374,6 @@ ClientCommand called each time a player uses a "cmd" command ============ */ -extern float g_flWeaponCheat; - // Use CMD_ARGV, CMD_ARGV, and CMD_ARGC to get pointers the character string command. void ClientCommand( edict_t *pEntity ) { @@ -401,7 +399,7 @@ void ClientCommand( edict_t *pEntity ) } else if ( FStrEq(pcmd, "give" ) ) { - if ( g_flWeaponCheat != 0.0) + if ( CVAR_GET_FLOAT( "sv_cheats" ) != 0.0) { int iszItem = ALLOC_STRING( CMD_ARGV(1) ); // Make a copy of the classname GetClassPtr((CBasePlayer *)pev)->GiveNamedItem( STRING(iszItem) ); @@ -467,7 +465,23 @@ void ClientCommand( edict_t *pEntity ) else { // tell the user they entered an unknown command - ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", pcmd ) ); + char command[128]; + + // check the length of the command (prevents crash) + // max total length is 192 ...and we're adding a string below ("Unknown command: %s\n") + strncpy( command, pcmd, 127 ); + command[127] = '\0'; + + // First parse the name and remove any %'s + for ( char *pApersand = command; pApersand != NULL && *pApersand != 0; pApersand++ ) + { + // Replace it with a space + if ( *pApersand == '%' ) + *pApersand = ' '; + } + + // tell the user they entered an unknown command + ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", command ) ); } } @@ -1199,6 +1213,12 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h state->health = ent->v.health; } + CBaseEntity *pEntity = static_cast( GET_PRIVATE( ent ) ); + if ( pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE ) + state->eflags |= EFLAG_FLESH_SOUND; + else + state->eflags &= ~EFLAG_FLESH_SOUND; + return 1; } @@ -1553,9 +1573,9 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info ) item->m_iId = II.iId; item->m_iClip = gun->m_iClip; - item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001 ); - item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001 ); - item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001 ); + item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001f ); + item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001f ); + item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001f ); item->m_fInReload = gun->m_fInReload; } } diff --git a/dmc/dlls/effects.cpp b/dmc/dlls/effects.cpp index 7c02b40..76fbc65 100644 --- a/dmc/dlls/effects.cpp +++ b/dmc/dlls/effects.cpp @@ -427,7 +427,7 @@ LINK_ENTITY_TO_CLASS( trip_beam, CTripBeam ); void CTripBeam::Spawn( void ) { CLightning::Spawn(); - SetTouch( &CTripBeam::TriggerTouch ); + SetTouch( TriggerTouch ); pev->solid = SOLID_TRIGGER; RelinkBeam(); } diff --git a/dmc/dlls/extdll.h b/dmc/dlls/extdll.h index b9488cd..b3302d8 100644 --- a/dmc/dlls/extdll.h +++ b/dmc/dlls/extdll.h @@ -58,13 +58,7 @@ typedef int BOOL; #include #include -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif #define itoa(a,b,c) sprintf(b, "%d", a) #define _snprintf snprintf @@ -74,6 +68,10 @@ typedef int BOOL; // Misc C-runtime library headers #include "stdio.h" #include "stdlib.h" +#include "minmax.h" +#ifndef _WIN32 +# define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) +#endif #include "math.h" // Header file containing definition of globalvars_t and entvars_t diff --git a/dmc/dlls/func_break.cpp b/dmc/dlls/func_break.cpp index 393c86c..53740c4 100644 --- a/dmc/dlls/func_break.cpp +++ b/dmc/dlls/func_break.cpp @@ -928,7 +928,11 @@ void CPushable :: Move( CBaseEntity *pOther, int push ) if ( pOther->IsPlayer() ) { - if ( push && !(pevToucher->button & (IN_FORWARD|IN_USE)) ) // Don't push unless the player is pushing forward and NOT use (pull) + // JoshA: Used to check for FORWARD too and logic was inverted + // from comment which seems wrong. + // Fixed to just check for USE being not set for PUSH. + // Should have the right effect. + if ( push && !!(pevToucher->button & IN_USE) ) // Don't push unless the player is not useing (pull) return; playerTouch = 1; } @@ -950,19 +954,40 @@ void CPushable :: Move( CBaseEntity *pOther, int push ) else factor = 0.25; - pev->velocity.x += pevToucher->velocity.x * factor; - pev->velocity.y += pevToucher->velocity.y * factor; + // This used to be added every 'frame', but to be consistent at high fps, + // now act as if it's added at a constant rate with a fudge factor. + extern cvar_t sv_pushable_fixed_tick_fudge; + + if ( !push && sv_pushable_fixed_tick_fudge.value >= 0.0f ) + { + factor *= gpGlobals->frametime * sv_pushable_fixed_tick_fudge.value; + } + + // JoshA: Always apply this if pushing, or if under the player's velocity. + if ( push || ( abs(pev->velocity.x) < abs(pevToucher->velocity.x - pevToucher->velocity.x * factor) ) ) + pev->velocity.x += pevToucher->velocity.x * factor; + if ( push || ( abs(pev->velocity.y) < abs(pevToucher->velocity.y - pevToucher->velocity.y * factor) ) ) + pev->velocity.y += pevToucher->velocity.y * factor; + float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y ); - if ( push && (length > MaxSpeed()) ) + if ( length > MaxSpeed() ) { pev->velocity.x = (pev->velocity.x * MaxSpeed() / length ); pev->velocity.y = (pev->velocity.y * MaxSpeed() / length ); } if ( playerTouch ) { - pevToucher->velocity.x = pev->velocity.x; - pevToucher->velocity.y = pev->velocity.y; + // JoshA: Match the player to our pushable's velocity. + // Previously this always happened, but it should only + // happen if the player is pushing (or rather, being pushed.) + // This either stops the player in their tracks or nudges them along. + if ( push ) + { + pevToucher->velocity.x = pev->velocity.x; + pevToucher->velocity.y = pev->velocity.y; + } + if ( (gpGlobals->time - m_soundTime) > 0.7 ) { m_soundTime = gpGlobals->time; diff --git a/dmc/dlls/game.cpp b/dmc/dlls/game.cpp index e514815..b56f13d 100644 --- a/dmc/dlls/game.cpp +++ b/dmc/dlls/game.cpp @@ -451,6 +451,8 @@ cvar_t sk_player_leg3 = { "sk_player_leg3","1" }; // END Cvars for Skill Level settings +cvar_t sv_pushable_fixed_tick_fudge = { "sv_pushable_fixed_tick_fudge", "15" }; + // Register your console variables here // This gets called one time when the game is initialied void GameDLLInit( void ) @@ -887,6 +889,8 @@ void GameDLLInit( void ) CVAR_REGISTER ( &sk_player_leg3 ); // END REGISTER CVARS FOR SKILL LEVEL STUFF + CVAR_REGISTER ( &sv_pushable_fixed_tick_fudge ); + SERVER_COMMAND( "exec skill.cfg\n" ); } diff --git a/dmc/dlls/items.cpp b/dmc/dlls/items.cpp index 6458eeb..4858aef 100644 --- a/dmc/dlls/items.cpp +++ b/dmc/dlls/items.cpp @@ -224,7 +224,7 @@ class CItemBattery : public CItem char szcharge[64]; pPlayer->pev->armorvalue += gSkillData.batteryCapacity; - pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY); + pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY); EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); diff --git a/dmc/dlls/maprules.cpp b/dmc/dlls/maprules.cpp index f6d1334..664dd01 100644 --- a/dmc/dlls/maprules.cpp +++ b/dmc/dlls/maprules.cpp @@ -799,7 +799,7 @@ void CGamePlayerEquip::KeyValue( KeyValueData *pkvd ) { char tmp[128]; - UTIL_StripToken( pkvd->szKeyName, tmp ); + UTIL_StripToken( pkvd->szKeyName, tmp, sizeof( tmp ) ); m_weaponNames[i] = ALLOC_STRING(tmp); m_weaponCount[i] = atoi(pkvd->szValue); diff --git a/dmc/dlls/meson.build b/dmc/dlls/meson.build new file mode 100644 index 0000000..c75b1a3 --- /dev/null +++ b/dmc/dlls/meson.build @@ -0,0 +1,133 @@ +dmc_server_src = [ + 'quake_gun.cpp', + 'quake_weapons_all.cpp', + 'animating.cpp', + 'animation.cpp', + 'bmodels.cpp', + 'buttons.cpp', + 'cbase.cpp', + 'client.cpp', + 'combat.cpp', + 'doors.cpp', + 'effects.cpp', + 'explode.cpp', + 'func_break.cpp', + 'func_tank.cpp', + 'game.cpp', + 'gamerules.cpp', + 'globals.cpp', + 'h_ai.cpp', + 'h_export.cpp', + 'lights.cpp', + 'maprules.cpp', + 'monsters.cpp', + 'monsterstate.cpp', + 'multiplay_gamerules.cpp', + 'nodes.cpp', + 'observer.cpp', + 'pathcorner.cpp', + 'plane.cpp', + 'plats.cpp', + 'player.cpp', + '../pm_shared/pm_debug.c', + '../pm_shared/pm_math.c', + '../pm_shared/pm_shared.c', + 'quake_items.cpp', + 'quake_nail.cpp', + 'quake_player.cpp', + 'quake_rocket.cpp', + 'schedule.cpp', + 'singleplay_gamerules.cpp', + 'skill.cpp', + 'sound.cpp', + 'spectator.cpp', + 'subs.cpp', + 'teamplay_gamerules.cpp', + 'threewave_gamerules.cpp', + 'triggers.cpp', + 'util.cpp', + '../../game_shared/voice_gamemgr.cpp', + 'weapons.cpp', + 'world.cpp', + 'activity.h', + 'activitymap.h', + 'animation.h', + 'basemonster.h', + 'cbase.h', + 'cdll_dll.h', + 'client.h', + 'decals.h', + 'defaultai.h', + 'doors.h', + 'effects.h', + 'enginecallback.h', + 'explode.h', + 'extdll.h', + 'func_break.h', + 'gamerules.h', + 'items.h', + 'monsterevent.h', + 'monsters.h', + 'nodes.h', + 'plane.h', + 'player.h', + '../pm_shared/pm_debug.h', + '../pm_shared/pm_defs.h', + '../pm_shared/pm_info.h', + '../pm_shared/pm_materials.h', + '../pm_shared/pm_movevars.h', + '../pm_shared/pm_shared.h', + 'quake_gun.h', + 'saverestore.h', + 'schedule.h', + 'scripted.h', + 'scriptevent.h', + 'skill.h', + 'soundent.h', + 'spectator.h', + 'teamplay_gamerules.h', + 'threewave_gamerules.h', + 'trains.h', + 'util.h', + 'vector.h', + '../../game_shared/voice_gamemgr.h', + 'weapons.h', +] + + +dmc_server_defines = [ + '-DVOXEL', + '-DQUAKE2', + '-DQUIVER', + '-DVALVE_DLL', +] + +dmc_server_includes = include_directories([ + '.', + '../../game_shared', + '../dlls', + '../../engine', + '../../common', + '../pm_shared', + '../', + '../../public', +]) + +install_dir = '/dmc/dlls' +target_name = 'dmc' +dmc_server_lib = shared_library(target_name, dmc_server_src, + cpp_args : dmc_server_defines, + c_args : dmc_server_defines, + include_directories : [ dmc_server_includes ], + vs_module_defs : 'hl.def', + install : true, + install_dir : output_dir + install_dir, +) + +dmc_server_dep = declare_dependency( + link_with : [ dmc_server_lib ], +) + +cmd = join_paths(meson.current_build_dir(), '..\..\..\devtools\meson_set_outdir.bat') +cs = run_command(cmd, [target_name, meson.current_build_dir(), install_dir], check: false) +#message(cs.stdout()) \ No newline at end of file diff --git a/dmc/dlls/multiplay_gamerules.cpp b/dmc/dlls/multiplay_gamerules.cpp index cae23d1..841f167 100644 --- a/dmc/dlls/multiplay_gamerules.cpp +++ b/dmc/dlls/multiplay_gamerules.cpp @@ -564,6 +564,9 @@ void CHalfLifeMultiplay :: PlayerSpawn( CBasePlayer *pPlayer ) BOOL addDefault; CBaseEntity *pWeaponEntity = NULL; + int nAutoWepSwitch = pPlayer->m_iAutoWepSwitch; + pPlayer->m_iAutoWepSwitch = 2; + pPlayer->pev->weapons |= (1<m_iQuakeWeapon = pPlayer->W_BestWeapon(); pPlayer->W_SetCurrentAmmo(); } + + pPlayer->m_iAutoWepSwitch = nAutoWepSwitch; } //========================================================= @@ -1304,14 +1309,12 @@ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle ) hasbuffer = 0; memset( szBuffer, 0, MAX_RULE_BUFFER ); - pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) <= 0 ) - - break; - strcpy( szMap, com_token ); + strncpy( szMap, com_token, sizeof( szMap ) ); + szMap[ sizeof( szMap ) - 1 ] = '\0'; // Any more tokens on this line? if ( COM_TokenWaiting( pFileList ) ) @@ -1320,7 +1323,8 @@ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle ) if ( strlen( com_token ) > 0 ) { hasbuffer = 1; - strcpy( szBuffer, com_token ); + strncpy( szBuffer, com_token, sizeof( szBuffer ) ); + szBuffer[ sizeof( szBuffer ) - 1 ] = '\0'; } } diff --git a/dmc/dlls/player.cpp b/dmc/dlls/player.cpp index 58b0d80..fd16a50 100644 --- a/dmc/dlls/player.cpp +++ b/dmc/dlls/player.cpp @@ -2647,12 +2647,12 @@ pt_end: if ( gun && gun->UseDecrement() ) { - gun->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0 ); - gun->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001 ); + gun->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack - gpGlobals->frametime, -1.0f ); + gun->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack - gpGlobals->frametime, -0.001f ); if ( gun->m_flTimeWeaponIdle != 1000 ) { - gun->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001 ); + gun->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle - gpGlobals->frametime, -0.001f ); } } @@ -3375,8 +3375,6 @@ void CBasePlayer :: ForceClientDllUpdate( void ) ImpulseCommands ============ */ -extern float g_flWeaponCheat; - void CBasePlayer::ImpulseCommands( ) { TraceResult tr;// UNDONE: kill me! This is temporary for PreAlpha CDs @@ -3477,7 +3475,7 @@ void CBasePlayer::ImpulseCommands( ) void CBasePlayer::CheatImpulseCommands( int iImpulse ) { #if !defined( HLDEMO_BUILD ) - if ( g_flWeaponCheat == 0.0 ) + if ( CVAR_GET_FLOAT( "sv_cheats" ) == 0.0 ) { return; } @@ -3706,7 +3704,7 @@ int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem ) pev->viewmodel = 0; pev->weaponmodel = 0; } - else if ( m_pLastItem == pItem ) + if ( m_pLastItem == pItem ) m_pLastItem = NULL; CBasePlayerItem *pPrev = m_rgpPlayerItems[pItem->iItemSlot()]; diff --git a/dmc/dlls/threewave_gamerules.cpp b/dmc/dlls/threewave_gamerules.cpp index e235322..565a2b7 100644 --- a/dmc/dlls/threewave_gamerules.cpp +++ b/dmc/dlls/threewave_gamerules.cpp @@ -1659,8 +1659,8 @@ void CItemFlag::Spawn ( void ) UTIL_SetOrigin( pev, pev->origin ); UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 16)); - SetThink( FlagThink ); - SetTouch( FlagTouch ); + SetThink( &CItemFlag::FlagThink ); + SetTouch( &CItemFlag::FlagTouch ); pev->nextthink = gpGlobals->time + 0.3; @@ -2016,8 +2016,8 @@ void CItemFlag::Materialize( void ) Dropped = FALSE; - SetTouch( FlagTouch ); - SetThink( FlagThink ); + SetTouch( &CItemFlag::FlagTouch ); + SetThink( &CItemFlag::FlagThink ); } @@ -2137,7 +2137,7 @@ void CCarriedFlag ::Spawn( ) m_iOwnerOldVel = 0; - SetThink( FlagThink ); + SetThink( &CCarriedFlag::FlagThink ); pev->nextthink = gpGlobals->time + 0.1; } @@ -2472,7 +2472,7 @@ void CResistRune::MakeTouchable ( void ) pev->nextthink = gpGlobals->time + 120; // if no one touches it in two minutes, // respawn it somewhere else, so inaccessible // ones will come 'back' - SetThink ( RuneRespawn ); + SetThink ( &CResistRune::RuneRespawn ); } void CResistRune::Spawn ( void ) @@ -2513,10 +2513,10 @@ void CResistRune::Spawn ( void ) pev->owner = NULL; - SetTouch( RuneTouch ); + SetTouch( &CResistRune::RuneTouch ); pev->nextthink = gpGlobals->time + 1; - SetThink ( MakeTouchable ); + SetThink ( &CResistRune::MakeTouchable ); } @@ -2529,7 +2529,7 @@ void CStrengthRune::MakeTouchable ( void ) pev->nextthink = gpGlobals->time + 120; // if no one touches it in two minutes, // respawn it somewhere else, so inaccessible // ones will come 'back' - SetThink ( RuneRespawn ); + SetThink ( &CStrengthRune::RuneRespawn ); } void CStrengthRune::RuneTouch ( CBaseEntity *pOther ) @@ -2636,10 +2636,10 @@ void CStrengthRune::Spawn ( void ) pev->owner = NULL; - SetTouch( RuneTouch ); + SetTouch( &CStrengthRune::RuneTouch ); pev->nextthink = gpGlobals->time + 1; - SetThink ( MakeTouchable ); + SetThink ( &CStrengthRune::MakeTouchable ); } @@ -2651,7 +2651,7 @@ void CHasteRune::MakeTouchable ( void ) pev->nextthink = gpGlobals->time + 120; // if no one touches it in two minutes, // respawn it somewhere else, so inaccessible // ones will come 'back' - SetThink ( RuneRespawn ); + SetThink ( &CHasteRune::RuneRespawn ); } @@ -2761,12 +2761,12 @@ void CHasteRune::Spawn ( void ) pev->owner = NULL; - SetTouch( RuneTouch ); + SetTouch( &CHasteRune::RuneTouch ); pev->nextthink = gpGlobals->time + 1; // if no one touches it in two minutes, // respawn it somewhere else, so inaccessible // ones will come 'back' - SetThink ( MakeTouchable ); + SetThink ( &CHasteRune::MakeTouchable ); } @@ -2779,7 +2779,7 @@ void CRegenRune::MakeTouchable ( void ) pev->nextthink = gpGlobals->time + 120; // if no one touches it in two minutes, // respawn it somewhere else, so inaccessible // ones will come 'back' - SetThink ( RuneRespawn ); + SetThink ( &CRegenRune::RuneRespawn ); } void CRegenRune::RuneTouch ( CBaseEntity *pOther ) @@ -2887,12 +2887,12 @@ void CRegenRune::Spawn ( void ) pev->owner = NULL; - SetTouch( RuneTouch ); + SetTouch( &CRegenRune::RuneTouch ); pev->nextthink = gpGlobals->time + 1; // if no one touches it in two minutes, // respawn it somewhere else, so inaccessible // ones will come 'back' - SetThink ( MakeTouchable ); + SetThink ( &CRegenRune::MakeTouchable ); } @@ -3044,7 +3044,7 @@ void CGrapple::GrappleTouch ( CBaseEntity *pOther ) STOP_SOUND( ((CBasePlayer *)pOwner)->edict(), CHAN_WEAPON, "weapons/grfire.wav" ); pev->enemy = pOther->edict();// remember this guy! - SetThink ( Grapple_Track ); + SetThink ( &CGrapple::Grapple_Track ); pev->nextthink = gpGlobals->time; m_flNextIdleTime = gpGlobals->time + 0.1; pev->solid = SOLID_NOT; @@ -3225,8 +3225,8 @@ void CGrapple::Spawn ( void ) SET_MODEL ( ENT(pev),"models/hook.mdl"); - SetTouch ( GrappleTouch ); - SetThink ( OnAirThink ); + SetTouch ( &CGrapple::GrappleTouch ); + SetThink ( &CGrapple::OnAirThink ); pev->nextthink = gpGlobals->time + 0.1; } diff --git a/dmc/dlls/triggers.cpp b/dmc/dlls/triggers.cpp index 8fbf734..4b8d756 100644 --- a/dmc/dlls/triggers.cpp +++ b/dmc/dlls/triggers.cpp @@ -337,7 +337,7 @@ void CMultiManager :: KeyValue( KeyValueData *pkvd ) { char tmp[128]; - UTIL_StripToken( pkvd->szKeyName, tmp ); + UTIL_StripToken( pkvd->szKeyName, tmp, sizeof( tmp ) ); m_iTargetName [ m_cTargets ] = ALLOC_STRING( tmp ); m_flTargetDelay [ m_cTargets ] = atof (pkvd->szValue); m_cTargets++; @@ -2003,7 +2003,10 @@ void CTriggerPush :: Touch( CBaseEntity *pOther ) } else { // Push field, transfer to base velocity - Vector vecPush = (pev->speed * pev->movedir); + // JoshA: This is multiplied by gpGlobals->frametime later on when + // it is integrated into velocity in the gravity/physics system. + // To keep it consistent, multiply by gpGlobals->frametime. + Vector vecPush = (pev->speed * pev->movedir) / (gpGlobals->frametime ? gpGlobals->frametime : 1.0f); if ( pevToucher->flags & FL_BASEVELOCITY ) vecPush = vecPush + pevToucher->basevelocity; diff --git a/dmc/dlls/util.cpp b/dmc/dlls/util.cpp index 4a1d347..c0df0ff 100644 --- a/dmc/dlls/util.cpp +++ b/dmc/dlls/util.cpp @@ -1552,7 +1552,8 @@ void UTIL_StringToVector( float *pVector, const char *pString ) char *pstr, *pfront, tempString[128]; int j; - strcpy( tempString, pString ); + strncpy( tempString, pString, sizeof( tempString ) ); + tempString[ sizeof( tempString ) - 1 ] = '\0'; pstr = pfront = tempString; for ( j = 0; j < 3; j++ ) // lifted from pr_edict.c @@ -1583,7 +1584,8 @@ void UTIL_StringToIntArray( int *pVector, int count, const char *pString ) char *pstr, *pfront, tempString[128]; int j; - strcpy( tempString, pString ); + strncpy( tempString, pString, sizeof( tempString ) ); + tempString[ sizeof( tempString ) - 1 ] = '\0'; pstr = pfront = tempString; for ( j = 0; j < count; j++ ) // lifted from pr_edict.c @@ -1795,11 +1797,11 @@ float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vecto //========================================================= // UTIL_StripToken - for redundant keynames //========================================================= -void UTIL_StripToken( const char *pKey, char *pDest ) +void UTIL_StripToken( const char *pKey, char *pDest, int nLen ) { int i = 0; - while ( pKey[i] && pKey[i] != '#' ) + while ( i < nLen - 1 && pKey[i] && pKey[i] != '#' ) { pDest[i] = pKey[i]; i++; @@ -2400,7 +2402,7 @@ int CRestore::ReadField( void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCou { fieldNumber = (i+startField)%fieldCount; pTest = &pFields[ fieldNumber ]; - if ( !stricmp( pTest->fieldName, pName ) ) + if ( pTest->fieldName && !stricmp( pTest->fieldName, pName ) ) { if ( !m_global || !(pTest->flags & FTYPEDESC_GLOBAL) ) { diff --git a/dmc/dlls/util.h b/dmc/dlls/util.h index b492386..a86a9f0 100644 --- a/dmc/dlls/util.h +++ b/dmc/dlls/util.h @@ -347,7 +347,7 @@ extern void UTIL_LogPrintf( char *fmt, ... ); // Sorta like FInViewCone, but for nonmonsters. extern float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir ); -extern void UTIL_StripToken( const char *pKey, char *pDest );// for redundant keynames +extern void UTIL_StripToken( const char *pKey, char *pDest, int nLen );// for redundant keynames // Misc functions extern void SetMovedir(entvars_t* pev); diff --git a/dmc/dlls/weapons.cpp b/dmc/dlls/weapons.cpp index 13ff03f..413dfb8 100644 --- a/dmc/dlls/weapons.cpp +++ b/dmc/dlls/weapons.cpp @@ -1036,7 +1036,7 @@ void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther ) //========================================================= int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { - int iReturn = 0; + int iReturn; if ( pszAmmo1() != NULL ) { diff --git a/dmc/dlls/world.cpp b/dmc/dlls/world.cpp index 49f8eda..5b764b7 100644 --- a/dmc/dlls/world.cpp +++ b/dmc/dlls/world.cpp @@ -466,13 +466,11 @@ LINK_ENTITY_TO_CLASS( worldspawn, CWorld ); #define SF_WORLD_FORCETEAM 0x0004 // Force teams extern DLL_GLOBAL BOOL g_fGameOver; -float g_flWeaponCheat; void CWorld :: Spawn( void ) { g_fGameOver = FALSE; Precache( ); - g_flWeaponCheat = CVAR_GET_FLOAT( "sv_cheats" ); // Is the impulse 101 command allowed? } void CWorld :: Precache( void ) diff --git a/dmc/meson.build b/dmc/meson.build new file mode 100644 index 0000000..c6446b9 --- /dev/null +++ b/dmc/meson.build @@ -0,0 +1,2 @@ +subdir('dlls') +subdir('cl_dll') diff --git a/dmc/pm_shared/pm_shared.c b/dmc/pm_shared/pm_shared.c index bf1c491..e01ec34 100644 --- a/dmc/pm_shared/pm_shared.c +++ b/dmc/pm_shared/pm_shared.c @@ -16,6 +16,7 @@ #include #include "mathlib.h" #include "const.h" +#include "minmax.h" #include "usercmd.h" #include "pm_defs.h" #include "pm_shared.h" @@ -121,8 +122,6 @@ typedef struct hull_s // double to float warning #pragma warning(disable : 4244) -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) // up / down #define PITCH 0 // left / right @@ -731,8 +730,12 @@ int PM_FlyMove (void) // modify original_velocity so it parallels all of the clip planes // - if ( pmove->movetype == MOVETYPE_WALK && - ((pmove->onground == -1) || (pmove->friction != 1)) ) // relfect player velocity + // relfect player velocity + // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place + // and pressing forward and nobody was really using this bounce/reflection feature anyway... + if ( numplanes == 1 && + pmove->movetype == MOVETYPE_WALK && + ((pmove->onground == -1) || (pmove->friction != 1)) ) { for ( i = 0; i < numplanes; i++ ) { @@ -2276,7 +2279,7 @@ void PM_DropPunchAngle ( vec3_t punchangle ) len = VectorNormalize ( punchangle ); len -= (10.0 + len * 0.5) * pmove->frametime; - len = max( len, 0.0 ); + len = max( len, 0.0f ); VectorScale ( punchangle, len, punchangle); } diff --git a/engine/APIProxy.h b/engine/APIProxy.h index b4a07f8..e506dca 100644 --- a/engine/APIProxy.h +++ b/engine/APIProxy.h @@ -353,6 +353,7 @@ typedef void (*pfnEngSrc_pfnFillRGBABlend_t ) ( int x, int y, int width, typedef int (*pfnEngSrc_pfnGetAppID_t) ( void ); typedef cmdalias_t* (*pfnEngSrc_pfnGetAliases_t) ( void ); typedef void (*pfnEngSrc_pfnVguiWrap2_GetMouseDelta_t) ( int *x, int *y ); +typedef int (*pfnEngSrc_pfnFilteredClientCmd_t) ( char *szCmdString ); // Pointers to the exported engine functions themselves typedef struct cl_enginefuncs_s @@ -491,6 +492,7 @@ typedef struct cl_enginefuncs_s pfnEngSrc_pfnGetAppID_t pfnGetAppID; pfnEngSrc_pfnGetAliases_t pfnGetAliasList; pfnEngSrc_pfnVguiWrap2_GetMouseDelta_t pfnVguiWrap2_GetMouseDelta; + pfnEngSrc_pfnFilteredClientCmd_t pfnFilteredClientCmd; } cl_enginefunc_t; // Function type declarations for engine destination functions @@ -610,6 +612,7 @@ typedef void (*pfnEngDst_pfnFillRGBABlend_t ) ( int *, int *, int *, int *, i typedef void (*pfnEngDst_pfnGetAppID_t ) ( void ); typedef void (*pfnEngDst_pfnGetAliases_t ) ( void ); typedef void (*pfnEngDst_pfnVguiWrap2_GetMouseDelta_t) ( int *x, int *y ); +typedef void (*pfnEngDst_pfnFilteredClientCmd_t ) ( char ** ); // Pointers to the engine destination functions @@ -737,6 +740,7 @@ typedef struct pfnEngDst_pfnGetAppID_t pfnGetAppID; pfnEngDst_pfnGetAliases_t pfnGetAliasList; pfnEngDst_pfnVguiWrap2_GetMouseDelta_t pfnVguiWrap2_GetMouseDelta; + pfnEngDst_pfnFilteredClientCmd_t pfnFilteredClientCmd; } cl_enginefunc_dst_t; diff --git a/engine/cdll_int.h b/engine/cdll_int.h index 555800f..ccf75d8 100644 --- a/engine/cdll_int.h +++ b/engine/cdll_int.h @@ -31,11 +31,17 @@ extern "C" { #include "ref_params.h" #include "r_efx.h" #include "studio_event.h" +#include "minmax.h" + +#ifdef _WIN32 +#include +#endif // this file is included by both the engine and the client-dll, // so make sure engine declarations aren't done twice -typedef int HSPRITE; // handle to a graphic +typedef int HANDLE_SPRITE; // handle to a graphic +#define HSPRITE HANDLE_SPRITE #define SCRINFO_SCREENFLASH 1 #define SCRINFO_STRETCHED 2 @@ -193,6 +199,7 @@ extern module_t g_module; #define RecEnghudHookUserMsg(a, b) (g_engdstAddrs.pfnHookUserMsg(&a, &b)) #define RecEnghudServerCmd(a) (g_engdstAddrs.pfnServerCmd(&a)) #define RecEnghudClientCmd(a) (g_engdstAddrs.pfnClientCmd(&a)) +#define RecEnghudFilteredClientCmd(a) (g_engdstAddrs.pfnFilteredClientCmd(&a)) #define RecEngPrimeMusicStream(a, b) (g_engdstAddrs.pfnPrimeMusicStream(&a, &b)) #define RecEnghudGetPlayerInfo(a, b) (g_engdstAddrs.pfnGetPlayerInfo(&a, &b)) #define RecEnghudPlaySoundByName(a, b) (g_engdstAddrs.pfnPlaySoundByName(&a, &b)) @@ -410,6 +417,7 @@ extern void NullDst(void); (pfnEngDst_pfnGetAppID_t) NullDst, \ (pfnEngDst_pfnGetAliases_t) NullDst, \ (pfnEngDst_pfnVguiWrap2_GetMouseDelta_t) NullDst, \ + (pfnEngDst_pfnFilteredClientCmd_t) NullDst, \ }; // Use this to init a cldll_func_dst structure to point to NullDst @@ -464,4 +472,4 @@ extern void NullDst(void); #endif #endif // CDLL_INT_H - \ No newline at end of file + diff --git a/engine/eiface.h b/engine/eiface.h index 9184c54..98d82df 100644 --- a/engine/eiface.h +++ b/engine/eiface.h @@ -296,6 +296,8 @@ typedef struct enginefuncs_s void (*pfnQueryClientCvarValue)( const edict_t *player, const char *cvarName ); void (*pfnQueryClientCvarValue2)( const edict_t *player, const char *cvarName, int requestID ); int (*pfnCheckParm)( const char *pchCmdLineToken, char **ppnext ); + + edict_t* (*pfnPEntityOfEntIndexAllEntities) (int iEntIndex); } enginefuncs_t; @@ -417,7 +419,10 @@ typedef struct short flags; } TYPEDESCRIPTION; +#ifndef ARRAYSIZE #define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) +#endif // ARRAYSIZE + typedef struct { diff --git a/external/SDL2/SDL.h b/external/SDL2/SDL.h index 0cfcdc7..7cdd324 100644 --- a/external/SDL2/SDL.h +++ b/external/SDL2/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,46 +21,13 @@ /** * \file SDL.h - * + * * Main include header for the SDL library */ -/** - * \mainpage Simple DirectMedia Layer (SDL) - * - * http://www.libsdl.org/ - * - * \section intro_sec Introduction - * - * This is the Simple DirectMedia Layer, a general API that provides low - * level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, - * and 2D framebuffer across multiple platforms. - * - * SDL is written in C, but works with C++ natively, and has bindings to - * several other languages, including Ada, C#, Eiffel, Erlang, Euphoria, - * Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP, - * Pike, Pliant, Python, Ruby, and Smalltalk. - * - * This library is distributed under the zlib license, which can be - * found in the file "COPYING". This license allows you to use SDL - * freely for any purpose as long as you retain the copyright notice. - * - * The best way to learn how to use SDL is to check out the header files in - * the "include" subdirectory and the programs in the "test" subdirectory. - * The header files and test programs are well commented and always up to date. - * More documentation and FAQs are available online at: - * http://wiki.libsdl.org/ - * - * If you need help with the library, or just want to discuss SDL related - * issues, you can join the developers mailing list: - * http://www.libsdl.org/mailing-list.php - * - * Enjoy! - * Sam Lantinga (slouken@libsdl.org) - */ -#ifndef _SDL_H -#define _SDL_H +#ifndef SDL_h_ +#define SDL_h_ #include "SDL_main.h" #include "SDL_stdinc.h" @@ -72,92 +39,194 @@ #include "SDL_endian.h" #include "SDL_error.h" #include "SDL_events.h" -#include "SDL_joystick.h" +#include "SDL_filesystem.h" #include "SDL_gamecontroller.h" #include "SDL_haptic.h" +#include "SDL_hidapi.h" #include "SDL_hints.h" +#include "SDL_joystick.h" #include "SDL_loadso.h" #include "SDL_log.h" #include "SDL_messagebox.h" +#include "SDL_metal.h" #include "SDL_mutex.h" #include "SDL_power.h" #include "SDL_render.h" #include "SDL_rwops.h" +#include "SDL_sensor.h" +#include "SDL_shape.h" #include "SDL_system.h" #include "SDL_thread.h" #include "SDL_timer.h" #include "SDL_version.h" #include "SDL_video.h" +#include "SDL_locale.h" +#include "SDL_misc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* As of version 0.5, SDL is loaded dynamically into the application */ /** * \name SDL_INIT_* - * + * * These are the flags which may be passed to SDL_Init(). You should * specify the subsystems which you will be using in your application. */ -/*@{*/ -#define SDL_INIT_TIMER 0x00000001 -#define SDL_INIT_AUDIO 0x00000010 -#define SDL_INIT_VIDEO 0x00000020 -#define SDL_INIT_JOYSTICK 0x00000200 -#define SDL_INIT_HAPTIC 0x00001000 -#define SDL_INIT_GAMECONTROLLER 0x00002000 /**< turn on game controller also implicitly does JOYSTICK */ -#define SDL_INIT_NOPARACHUTE 0x00100000 /**< Don't catch fatal signals */ +/* @{ */ +#define SDL_INIT_TIMER 0x00000001u +#define SDL_INIT_AUDIO 0x00000010u +#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ +#define SDL_INIT_JOYSTICK 0x00000200u /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */ +#define SDL_INIT_HAPTIC 0x00001000u +#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */ +#define SDL_INIT_EVENTS 0x00004000u +#define SDL_INIT_SENSOR 0x00008000u +#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */ #define SDL_INIT_EVERYTHING ( \ - SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | \ - SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \ + SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \ + SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \ ) -/*@}*/ +/* @} */ /** - * This function initializes the subsystems specified by \c flags - * Unless the ::SDL_INIT_NOPARACHUTE flag is set, it will install cleanup - * signal handlers for some commonly ignored fatal signals (like SIGSEGV). + * Initialize the SDL library. + * + * SDL_Init() simply forwards to calling SDL_InitSubSystem(). Therefore, the + * two may be used interchangeably. Though for readability of your code + * SDL_InitSubSystem() might be preferred. + * + * The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread) + * subsystems are initialized by default. Message boxes + * (SDL_ShowSimpleMessageBox) also attempt to work without initializing the + * video subsystem, in hopes of being useful in showing an error dialog when + * SDL_Init fails. You must specifically initialize other subsystems if you + * use them in your application. + * + * Logging (such as SDL_Log) works without initialization, too. + * + * `flags` may be any of the following OR'd together: + * + * - `SDL_INIT_TIMER`: timer subsystem + * - `SDL_INIT_AUDIO`: audio subsystem + * - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events + * subsystem + * - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the + * events subsystem + * - `SDL_INIT_HAPTIC`: haptic (force feedback) subsystem + * - `SDL_INIT_GAMECONTROLLER`: controller subsystem; automatically + * initializes the joystick subsystem + * - `SDL_INIT_EVENTS`: events subsystem + * - `SDL_INIT_EVERYTHING`: all of the above subsystems + * - `SDL_INIT_NOPARACHUTE`: compatibility; this flag is ignored + * + * Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem() + * for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or + * call SDL_Quit() to force shutdown). If a subsystem is already loaded then + * this call will increase the ref-count and return. + * + * \param flags subsystem initialization flags + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_InitSubSystem + * \sa SDL_Quit + * \sa SDL_SetMainReady + * \sa SDL_WasInit */ extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags); /** - * This function initializes specific SDL subsystems + * Compatibility function to initialize the SDL library. + * + * In SDL2, this function and SDL_Init() are interchangeable. + * + * \param flags any of the flags used by SDL_Init(); see SDL_Init for details. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Init + * \sa SDL_Quit + * \sa SDL_QuitSubSystem */ extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags); /** - * This function cleans up specific SDL subsystems + * Shut down specific SDL subsystems. + * + * If you start a subsystem using a call to that subsystem's init function + * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(), + * SDL_QuitSubSystem() and SDL_WasInit() will not work. You will need to use + * that subsystem's quit function (SDL_VideoQuit()) directly instead. But + * generally, you should not be using those functions directly anyhow; use + * SDL_Init() instead. + * + * You still need to call SDL_Quit() even if you close all open subsystems + * with SDL_QuitSubSystem(). + * + * \param flags any of the flags used by SDL_Init(); see SDL_Init for details. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_InitSubSystem + * \sa SDL_Quit */ extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags); /** - * This function returns a mask of the specified subsystems which have - * previously been initialized. - * - * If \c flags is 0, it returns a mask of all initialized subsystems. + * Get a mask of the specified subsystems which are currently initialized. + * + * \param flags any of the flags used by SDL_Init(); see SDL_Init for details. + * \returns a mask of all initialized subsystems if `flags` is 0, otherwise it + * returns the initialization status of the specified subsystems. + * + * The return value does not include SDL_INIT_NOPARACHUTE. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Init + * \sa SDL_InitSubSystem */ extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags); /** - * This function cleans up all initialized subsystems. You should - * call it upon all exit conditions. + * Clean up all initialized subsystems. + * + * You should call this function even if you have already shutdown each + * initialized subsystem with SDL_QuitSubSystem(). It is safe to call this + * function even in the case of errors in initialization. + * + * If you start a subsystem using a call to that subsystem's init function + * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(), + * then you must use that subsystem's quit function (SDL_VideoQuit()) to shut + * it down before calling SDL_Quit(). But generally, you should not be using + * those functions directly anyhow; use SDL_Init() instead. + * + * You can use this function with atexit() to ensure that it is run when your + * application is shutdown, but it is not wise to do this from a library or + * other dynamically loaded code. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Init + * \sa SDL_QuitSubSystem */ extern DECLSPEC void SDLCALL SDL_Quit(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_H */ +#endif /* SDL_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_assert.h b/external/SDL2/SDL_assert.h index e4620ae..defadf1 100644 --- a/external/SDL2/SDL_assert.h +++ b/external/SDL2/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,17 +19,15 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_assert_h -#define _SDL_assert_h +#ifndef SDL_assert_h_ +#define SDL_assert_h_ #include "SDL_config.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif #ifndef SDL_ASSERT_LEVEL @@ -53,9 +51,15 @@ assert can have unique static variables associated with it. /* Don't include intrin.h here because it contains C++ code */ extern void __cdecl __debugbreak(void); #define SDL_TriggerBreakpoint() __debugbreak() -#elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) +#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) ) #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" ) -#elif defined(HAVE_SIGNAL_H) +#elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */ + #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" ) +#elif defined(__APPLE__) && defined(__arm__) + #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" ) +#elif defined(__386__) && defined(__WATCOMC__) + #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } +#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__) #include #define SDL_TriggerBreakpoint() raise(SIGTRAP) #else @@ -65,7 +69,7 @@ assert can have unique static variables associated with it. #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ # define SDL_FUNCTION __func__ -#elif ((__GNUC__ >= 2) || defined(_MSC_VER)) +#elif ((__GNUC__ >= 2) || defined(_MSC_VER) || defined (__WATCOMC__)) # define SDL_FUNCTION __FUNCTION__ #else # define SDL_FUNCTION "???" @@ -88,8 +92,16 @@ This also solves the problem of... disable assertions. */ +/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking + this condition isn't constant. And looks like an owl's face! */ +#ifdef _MSC_VER /* stupid /W4 warnings. */ +#define SDL_NULL_WHILE_LOOP_CONDITION (0,0) +#else +#define SDL_NULL_WHILE_LOOP_CONDITION (0) +#endif + #define SDL_disabled_assert(condition) \ - do { (void) sizeof ((condition)); } while (0) + do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION) typedef enum { @@ -98,9 +110,9 @@ typedef enum SDL_ASSERTION_ABORT, /**< Terminate the program. */ SDL_ASSERTION_IGNORE, /**< Ignore the assert. */ SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */ -} SDL_assert_state; +} SDL_AssertState; -typedef struct SDL_assert_data +typedef struct SDL_AssertData { int always_ignore; unsigned int trigger_count; @@ -108,15 +120,24 @@ typedef struct SDL_assert_data const char *filename; int linenum; const char *function; - const struct SDL_assert_data *next; -} SDL_assert_data; + const struct SDL_AssertData *next; +} SDL_AssertData; #if (SDL_ASSERT_LEVEL > 0) /* Never call this directly. Use the SDL_assert* macros. */ -extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, +extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *, const char *, - const char *, int); + const char *, int) +#if defined(__clang__) +#if __has_feature(attribute_analyzer_noreturn) +/* this tells Clang's static analysis that we're a custom assert function, + and that the analyzer should assume the condition was always true past this + SDL_assert test. */ + __attribute__((analyzer_noreturn)) +#endif +#endif +; /* the do {} while(0) avoids dangling else problems: if (x) SDL_assert(y); else blah(); @@ -128,21 +149,18 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, #define SDL_enabled_assert(condition) \ do { \ while ( !(condition) ) { \ - static struct SDL_assert_data assert_data = { \ + static struct SDL_AssertData sdl_assert_data = { \ 0, 0, #condition, 0, 0, 0, 0 \ }; \ - const SDL_assert_state state = SDL_ReportAssertion(&assert_data, \ - SDL_FUNCTION, \ - SDL_FILE, \ - SDL_LINE); \ - if (state == SDL_ASSERTION_RETRY) { \ + const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ + if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ continue; /* go again. */ \ - } else if (state == SDL_ASSERTION_BREAK) { \ + } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \ SDL_TriggerBreakpoint(); \ } \ break; /* not retrying. */ \ } \ - } while (0) + } while (SDL_NULL_WHILE_LOOP_CONDITION) #endif /* enabled assertions support code */ @@ -167,75 +185,140 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, # error Unknown assertion level. #endif +/* this assertion is never disabled at any level. */ +#define SDL_assert_always(condition) SDL_enabled_assert(condition) -typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)( - const SDL_assert_data* data, void* userdata); /** - * \brief Set an application-defined assertion handler. + * A callback that fires when an SDL assertion fails. * - * This allows an app to show its own assertion UI and/or force the - * response to an assertion failure. If the app doesn't provide this, SDL - * will try to do the right thing, popping up a system-specific GUI dialog, - * and probably minimizing any fullscreen windows. + * \param data a pointer to the SDL_AssertData structure corresponding to the + * current assertion + * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler() + * \returns an SDL_AssertState value indicating how to handle the failure. + */ +typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)( + const SDL_AssertData* data, void* userdata); + +/** + * Set an application-defined assertion handler. * - * This callback may fire from any thread, but it runs wrapped in a mutex, so - * it will only fire from one thread at a time. + * This function allows an application to show its own assertion UI and/or + * force the response to an assertion failure. If the application doesn't + * provide this, SDL will try to do the right thing, popping up a + * system-specific GUI dialog, and probably minimizing any fullscreen windows. * - * Setting the callback to NULL restores SDL's original internal handler. + * This callback may fire from any thread, but it runs wrapped in a mutex, so + * it will only fire from one thread at a time. * - * This callback is NOT reset to SDL's internal handler upon SDL_Quit()! + * This callback is NOT reset to SDL's internal handler upon SDL_Quit()! * - * \return SDL_assert_state value of how to handle the assertion failure. - * - * \param handler Callback function, called when an assertion fails. - * \param userdata A pointer passed to the callback as-is. + * \param handler the SDL_AssertionHandler function to call when an assertion + * fails or NULL for the default handler + * \param userdata a pointer that is passed to `handler` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetAssertionHandler */ extern DECLSPEC void SDLCALL SDL_SetAssertionHandler( SDL_AssertionHandler handler, void *userdata); /** - * \brief Get a list of all assertion failures. + * Get the default assertion handler. * - * Get all assertions triggered since last call to SDL_ResetAssertionReport(), - * or the start of the program. + * This returns the function pointer that is called by default when an + * assertion is triggered. This is an internal function provided by SDL, that + * is used for assertions when SDL_SetAssertionHandler() hasn't been used to + * provide a different function. * - * The proper way to examine this data looks something like this: + * \returns the default SDL_AssertionHandler that is called when an assert + * triggers. * - * - * const SDL_assert_data *item = SDL_GetAssertionReport(); - * while (item) { - * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n", - * item->condition, item->function, item->filename, - * item->linenum, item->trigger_count, - * item->always_ignore ? "yes" : "no"); - * item = item->next; - * } - * + * \since This function is available since SDL 2.0.2. * - * \return List of all assertions. - * \sa SDL_ResetAssertionReport + * \sa SDL_GetAssertionHandler */ -extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void); +extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void); /** - * \brief Reset the list of all assertion failures. + * Get the current assertion handler. * - * Reset list of all assertions triggered. + * This returns the function pointer that is called when an assertion is + * triggered. This is either the value last passed to + * SDL_SetAssertionHandler(), or if no application-specified function is set, + * is equivalent to calling SDL_GetDefaultAssertionHandler(). * - * \sa SDL_GetAssertionReport + * The parameter `puserdata` is a pointer to a void*, which will store the + * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value + * will always be NULL for the default handler. If you don't care about this + * data, it is safe to pass a NULL pointer to this function to ignore it. + * + * \param puserdata pointer which is filled with the "userdata" pointer that + * was passed to SDL_SetAssertionHandler() + * \returns the SDL_AssertionHandler that is called when an assert triggers. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_SetAssertionHandler + */ +extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata); + +/** + * Get a list of all assertion failures. + * + * This function gets all assertions triggered since the last call to + * SDL_ResetAssertionReport(), or the start of the program. + * + * The proper way to examine this data looks something like this: + * + * ```c + * const SDL_AssertData *item = SDL_GetAssertionReport(); + * while (item) { + * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n", + * item->condition, item->function, item->filename, + * item->linenum, item->trigger_count, + * item->always_ignore ? "yes" : "no"); + * item = item->next; + * } + * ``` + * + * \returns a list of all failed assertions or NULL if the list is empty. This + * memory should not be modified or freed by the application. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ResetAssertionReport + */ +extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void); + +/** + * Clear the list of all assertion failures. + * + * This function will clear the list of all assertions triggered up to that + * point. Immediately following this call, SDL_GetAssertionReport will return + * no items. In addition, any previously-triggered assertions will be reset to + * a trigger_count of zero, and their always_ignore state will be false. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetAssertionReport */ extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void); + +/* these had wrong naming conventions until 2.0.4. Please update your app! */ +#define SDL_assert_state SDL_AssertState +#define SDL_assert_data SDL_AssertData + + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_assert_h */ +#endif /* SDL_assert_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_atomic.h b/external/SDL2/SDL_atomic.h index be60f99..b29ceea 100644 --- a/external/SDL2/SDL_atomic.h +++ b/external/SDL2/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,30 +21,31 @@ /** * \file SDL_atomic.h - * + * * Atomic operations. - * + * * IMPORTANT: * If you are not an expert in concurrent lockless programming, you should * only be using the atomic lock and reference counting functions in this * file. In all other cases you should be protecting your data structures * with full mutexes. - * + * * The list of "safe" functions to use are: * SDL_AtomicLock() * SDL_AtomicUnlock() * SDL_AtomicIncRef() * SDL_AtomicDecRef() - * + * * Seriously, here be dragons! * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - * You can find out a little more about lockless programming and the + * You can find out a little more about lockless programming and the * subtle issues that can arise here: * http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx * * There's also lots of good information here: * http://www.1024cores.net/home/lock-free-algorithms + * http://preshing.com/ * * These operations may or may not actually be implemented using * processor specific atomic operations. When possible they are @@ -55,31 +56,22 @@ * All of the atomic operations that modify memory are full memory barriers. */ -#ifndef _SDL_atomic_h_ -#define _SDL_atomic_h_ +#ifndef SDL_atomic_h_ +#define SDL_atomic_h_ #include "SDL_stdinc.h" #include "SDL_platform.h" #include "begin_code.h" -/* Need to do this here because intrin.h has C++ code in it */ -/* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */ -#if defined(_MSC_VER) && (_MSC_VER >= 1500) -#include -#define HAVE_MSC_ATOMICS 1 -#endif - /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \name SDL AtomicLock - * + * * The atomic locks are efficient spinlocks using CPU instructions, * but are vulnerable to starvation and can spin forever if a thread * holding a lock has been terminated. For this reason you should @@ -92,158 +84,235 @@ extern "C" { * The spin lock functions and type are required and can not be * emulated because they are used in the atomic emulation code. */ -/*@{*/ +/* @{ */ typedef int SDL_SpinLock; /** - * \brief Try to lock a spin lock by setting it to a non-zero value. - * - * \param lock Points to the lock. + * Try to lock a spin lock by setting it to a non-zero value. * - * \return SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already held. + * ***Please note that spinlocks are dangerous if you don't know what you're + * doing. Please be careful using any sort of spinlock!*** + * + * \param lock a pointer to a lock variable + * \returns SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already + * held. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AtomicLock + * \sa SDL_AtomicUnlock */ extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock); /** - * \brief Lock a spin lock by setting it to a non-zero value. - * - * \param lock Points to the lock. + * Lock a spin lock by setting it to a non-zero value. + * + * ***Please note that spinlocks are dangerous if you don't know what you're + * doing. Please be careful using any sort of spinlock!*** + * + * \param lock a pointer to a lock variable + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AtomicTryLock + * \sa SDL_AtomicUnlock */ extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock); /** - * \brief Unlock a spin lock by setting it to 0. Always returns immediately + * Unlock a spin lock by setting it to 0. * - * \param lock Points to the lock. + * Always returns immediately. + * + * ***Please note that spinlocks are dangerous if you don't know what you're + * doing. Please be careful using any sort of spinlock!*** + * + * \param lock a pointer to a lock variable + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AtomicLock + * \sa SDL_AtomicTryLock */ extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock); -/*@}*//*SDL AtomicLock*/ +/* @} *//* SDL AtomicLock */ /** * The compiler barrier prevents the compiler from reordering * reads and writes to globally visible variables across the call. */ -#if defined(_MSC_VER) && (_MSC_VER > 1200) +#if defined(_MSC_VER) && (_MSC_VER > 1200) && !defined(__clang__) void _ReadWriteBarrier(void); #pragma intrinsic(_ReadWriteBarrier) #define SDL_CompilerBarrier() _ReadWriteBarrier() -#elif defined(__GNUC__) +#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) +/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */ #define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory") +#elif defined(__WATCOMC__) +extern __inline void SDL_CompilerBarrier(void); +#pragma aux SDL_CompilerBarrier = "" parm [] modify exact []; #else #define SDL_CompilerBarrier() \ { SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); } #endif -/* Platform specific optimized versions of the atomic functions, - * you can disable these by defining SDL_DISABLE_ATOMIC_INLINE +/** + * Memory barriers are designed to prevent reads and writes from being + * reordered by the compiler and being seen out of order on multi-core CPUs. + * + * A typical pattern would be for thread A to write some data and a flag, and + * for thread B to read the flag and get the data. In this case you would + * insert a release barrier between writing the data and the flag, + * guaranteeing that the data write completes no later than the flag is + * written, and you would insert an acquire barrier between reading the flag + * and reading the data, to ensure that all the reads associated with the flag + * have completed. + * + * In this pattern you should always see a release barrier paired with an + * acquire barrier and you should gate the data reads/writes with a single + * flag variable. + * + * For more information on these semantics, take a look at the blog post: + * http://preshing.com/20120913/acquire-and-release-semantics + * + * \since This function is available since SDL 2.0.6. */ -#if defined(SDL_ATOMIC_DISABLED) && SDL_ATOMIC_DISABLED -#define SDL_DISABLE_ATOMIC_INLINE -#endif -#ifndef SDL_DISABLE_ATOMIC_INLINE +extern DECLSPEC void SDLCALL SDL_MemoryBarrierReleaseFunction(void); +extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); -#ifdef HAVE_MSC_ATOMICS +#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory") +#elif defined(__GNUC__) && defined(__aarch64__) +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") +#elif defined(__GNUC__) && defined(__arm__) +#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */ +/* Information from: + https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19 -#define SDL_AtomicSet(a, v) _InterlockedExchange((long*)&(a)->value, (v)) -#define SDL_AtomicAdd(a, v) _InterlockedExchangeAdd((long*)&(a)->value, (v)) -#define SDL_AtomicCAS(a, oldval, newval) (_InterlockedCompareExchange((long*)&(a)->value, (newval), (oldval)) == (oldval)) -#define SDL_AtomicSetPtr(a, v) _InterlockedExchangePointer((a), (v)) -#if _M_IX86 -#define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchange((long*)(a), (long)(newval), (long)(oldval)) == (long)(oldval)) + The Linux kernel provides a helper function which provides the right code for a memory barrier, + hard-coded at address 0xffff0fa0 +*/ +typedef void (*SDL_KernelMemoryBarrierFunc)(); +#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#elif 0 /* defined(__QNXNTO__) */ +#include + +#define SDL_MemoryBarrierRelease() __cpu_membarrier() +#define SDL_MemoryBarrierAcquire() __cpu_membarrier() #else -#define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchangePointer((a), (newval), (oldval)) == (oldval)) -#endif - -#elif defined(__MACOSX__) -#include - -#define SDL_AtomicCAS(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((oldval), (newval), &(a)->value) -#ifdef __LP64__ -#define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap64Barrier((int64_t)(oldval), (int64_t)(newval), (int64_t*)(a)) +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) +#ifdef __thumb__ +/* The mcr instruction isn't available in thumb mode, use real functions */ +#define SDL_MEMORY_BARRIER_USES_FUNCTION +#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction() +#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction() #else -#define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((int32_t)(oldval), (int32_t)(newval), (int32_t*)(a)) +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory") +#endif /* __thumb__ */ +#else +#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") +#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") +#endif /* __LINUX__ || __ANDROID__ */ +#endif /* __GNUC__ && __arm__ */ +#else +#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) +/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */ +#include +#define SDL_MemoryBarrierRelease() __machine_rel_barrier() +#define SDL_MemoryBarrierAcquire() __machine_acq_barrier() +#else +/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */ +#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier() +#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier() #endif - -#elif defined(HAVE_GCC_ATOMICS) - -#define SDL_AtomicSet(a, v) __sync_lock_test_and_set(&(a)->value, v) -#define SDL_AtomicAdd(a, v) __sync_fetch_and_add(&(a)->value, v) -#define SDL_AtomicSetPtr(a, v) __sync_lock_test_and_set(a, v) -#define SDL_AtomicCAS(a, oldval, newval) __sync_bool_compare_and_swap(&(a)->value, oldval, newval) -#define SDL_AtomicCASPtr(a, oldval, newval) __sync_bool_compare_and_swap(a, oldval, newval) - #endif -#endif /* !SDL_DISABLE_ATOMIC_INLINE */ - - /** * \brief A type representing an atomic integer value. It is a struct * so people don't accidentally use numeric operations on it. */ -#ifndef SDL_atomic_t_defined typedef struct { int value; } SDL_atomic_t; -#endif /** - * \brief Set an atomic variable to a new value if it is currently an old value. + * Set an atomic variable to a new value if it is currently an old value. * - * \return SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise. + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** * - * \note If you don't know what this function is for, you shouldn't use it! -*/ -#ifndef SDL_AtomicCAS + * \param a a pointer to an SDL_atomic_t variable to be modified + * \param oldval the old value + * \param newval the new value + * \returns SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AtomicCASPtr + * \sa SDL_AtomicGet + * \sa SDL_AtomicSet + */ extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval); -#endif /** - * \brief Set an atomic variable to a value. + * Set an atomic variable to a value. * - * \return The previous value of the atomic variable. + * This function also acts as a full memory barrier. + * + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to an SDL_atomic_t variable to be modified + * \param v the desired value + * \returns the previous value of the atomic variable. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_AtomicGet */ -#ifndef SDL_AtomicSet -SDL_FORCE_INLINE int SDL_AtomicSet(SDL_atomic_t *a, int v) -{ - int value; - do { - value = a->value; - } while (!SDL_AtomicCAS(a, value, v)); - return value; -} -#endif +extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int v); /** - * \brief Get the value of an atomic variable + * Get the value of an atomic variable. + * + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to an SDL_atomic_t variable + * \returns the current value of an atomic variable. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_AtomicSet */ -#ifndef SDL_AtomicGet -SDL_FORCE_INLINE int SDL_AtomicGet(SDL_atomic_t *a) -{ - int value = a->value; - SDL_CompilerBarrier(); - return value; -} -#endif +extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a); /** - * \brief Add to an atomic variable. + * Add to an atomic variable. * - * \return The previous value of the atomic variable. + * This function also acts as a full memory barrier. * - * \note This same style can be used for any number operation + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to an SDL_atomic_t variable to be modified + * \param v the desired value to add + * \returns the previous value of the atomic variable. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_AtomicDecRef + * \sa SDL_AtomicIncRef */ -#ifndef SDL_AtomicAdd -SDL_FORCE_INLINE int SDL_AtomicAdd(SDL_atomic_t *a, int v) -{ - int value; - do { - value = a->value; - } while (!SDL_AtomicCAS(a, value, (value + v))); - return value; -} -#endif +extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int v); /** * \brief Increment an atomic variable used as a reference count. @@ -263,54 +332,64 @@ SDL_FORCE_INLINE int SDL_AtomicAdd(SDL_atomic_t *a, int v) #endif /** - * \brief Set a pointer to a new value if it is currently an old value. + * Set a pointer to a new value if it is currently an old value. * - * \return SDL_TRUE if the pointer was set, SDL_FALSE otherwise. + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** * - * \note If you don't know what this function is for, you shouldn't use it! -*/ -#ifndef SDL_AtomicCASPtr -extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void* *a, void *oldval, void *newval); -#endif + * \param a a pointer to a pointer + * \param oldval the old pointer value + * \param newval the new pointer value + * \returns SDL_TRUE if the pointer was set, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AtomicCAS + * \sa SDL_AtomicGetPtr + * \sa SDL_AtomicSetPtr + */ +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval); /** - * \brief Set a pointer to a value atomically. + * Set a pointer to a value atomically. * - * \return The previous value of the pointer. + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to a pointer + * \param v the desired pointer value + * \returns the previous value of the pointer. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_AtomicCASPtr + * \sa SDL_AtomicGetPtr */ -#ifndef SDL_AtomicSetPtr -SDL_FORCE_INLINE void* SDL_AtomicSetPtr(void* *a, void* v) -{ - void* value; - do { - value = *a; - } while (!SDL_AtomicCASPtr(a, value, v)); - return value; -} -#endif +extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v); /** - * \brief Get the value of a pointer atomically. + * Get the value of a pointer atomically. + * + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to a pointer + * \returns the current value of a pointer. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_AtomicCASPtr + * \sa SDL_AtomicSetPtr */ -#ifndef SDL_AtomicGetPtr -SDL_FORCE_INLINE void* SDL_AtomicGetPtr(void* *a) -{ - void* value = *a; - SDL_CompilerBarrier(); - return value; -} -#endif - +extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_atomic_h_ */ +#endif /* SDL_atomic_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_audio.h b/external/SDL2/SDL_audio.h index 8a1bb70..181f66c 100644 --- a/external/SDL2/SDL_audio.h +++ b/external/SDL2/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,14 +19,16 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* !!! FIXME: several functions in here need Doxygen comments. */ + /** * \file SDL_audio.h - * + * * Access to the raw audio mixing buffer for the SDL library. */ -#ifndef _SDL_audio_h -#define _SDL_audio_h +#ifndef SDL_audio_h_ +#define SDL_audio_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -38,17 +40,15 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \brief Audio format flags. - * + * * These are what the 16 bits in SDL_AudioFormat currently mean... * (Unspecified bits are always zero). - * + * * \verbatim ++-----------------------sample is signed if set || @@ -60,7 +60,7 @@ extern "C" { || || || | | 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 \endverbatim - * + * * There are macros in SDL 2.0 and later to query these bits. */ typedef Uint16 SDL_AudioFormat; @@ -68,7 +68,7 @@ typedef Uint16 SDL_AudioFormat; /** * \name Audio flags */ -/*@{*/ +/* @{ */ #define SDL_AUDIO_MASK_BITSIZE (0xFF) #define SDL_AUDIO_MASK_DATATYPE (1<<8) @@ -82,74 +82,71 @@ typedef Uint16 SDL_AudioFormat; #define SDL_AUDIO_ISLITTLEENDIAN(x) (!SDL_AUDIO_ISBIGENDIAN(x)) #define SDL_AUDIO_ISUNSIGNED(x) (!SDL_AUDIO_ISSIGNED(x)) -/** +/** * \name Audio format flags * * Defaults to LSB byte order. */ -/*@{*/ -#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */ -#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */ -#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */ -#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */ -#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */ -#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */ -#define AUDIO_U16 AUDIO_U16LSB -#define AUDIO_S16 AUDIO_S16LSB -/*@}*/ +/* @{ */ +#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */ +#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */ +#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */ +#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */ +#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */ +#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */ +#define AUDIO_U16 AUDIO_U16LSB +#define AUDIO_S16 AUDIO_S16LSB +/* @} */ /** * \name int32 support - * - * New to SDL 1.3. */ -/*@{*/ -#define AUDIO_S32LSB 0x8020 /**< 32-bit integer samples */ -#define AUDIO_S32MSB 0x9020 /**< As above, but big-endian byte order */ -#define AUDIO_S32 AUDIO_S32LSB -/*@}*/ +/* @{ */ +#define AUDIO_S32LSB 0x8020 /**< 32-bit integer samples */ +#define AUDIO_S32MSB 0x9020 /**< As above, but big-endian byte order */ +#define AUDIO_S32 AUDIO_S32LSB +/* @} */ /** * \name float32 support - * - * New to SDL 1.3. */ -/*@{*/ -#define AUDIO_F32LSB 0x8120 /**< 32-bit floating point samples */ -#define AUDIO_F32MSB 0x9120 /**< As above, but big-endian byte order */ -#define AUDIO_F32 AUDIO_F32LSB -/*@}*/ +/* @{ */ +#define AUDIO_F32LSB 0x8120 /**< 32-bit floating point samples */ +#define AUDIO_F32MSB 0x9120 /**< As above, but big-endian byte order */ +#define AUDIO_F32 AUDIO_F32LSB +/* @} */ /** * \name Native audio byte ordering */ -/*@{*/ +/* @{ */ #if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define AUDIO_U16SYS AUDIO_U16LSB -#define AUDIO_S16SYS AUDIO_S16LSB -#define AUDIO_S32SYS AUDIO_S32LSB -#define AUDIO_F32SYS AUDIO_F32LSB +#define AUDIO_U16SYS AUDIO_U16LSB +#define AUDIO_S16SYS AUDIO_S16LSB +#define AUDIO_S32SYS AUDIO_S32LSB +#define AUDIO_F32SYS AUDIO_F32LSB #else -#define AUDIO_U16SYS AUDIO_U16MSB -#define AUDIO_S16SYS AUDIO_S16MSB -#define AUDIO_S32SYS AUDIO_S32MSB -#define AUDIO_F32SYS AUDIO_F32MSB +#define AUDIO_U16SYS AUDIO_U16MSB +#define AUDIO_S16SYS AUDIO_S16MSB +#define AUDIO_S32SYS AUDIO_S32MSB +#define AUDIO_F32SYS AUDIO_F32MSB #endif -/*@}*/ +/* @} */ -/** +/** * \name Allow change flags - * + * * Which audio format changes are allowed when opening a device. */ -/*@{*/ +/* @{ */ #define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001 #define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002 #define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004 -#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE) -/*@}*/ +#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0x00000008 +#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE) +/* @} */ -/*@}*//*Audio flags*/ +/* @} *//* Audio flags */ /** * This function is called when the audio device needs more data. @@ -161,12 +158,24 @@ typedef Uint16 SDL_AudioFormat; * * Once the callback returns, the buffer will no longer be valid. * Stereo samples are stored in a LRLRLR ordering. + * + * You can choose to avoid callbacks and use SDL_QueueAudio() instead, if + * you like. Just open your audio device with a NULL callback. */ typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream, int len); /** * The calculated values in this structure are calculated by SDL_OpenAudio(). + * + * For multi-channel audio, the default SDL channel mapping is: + * 2: FL FR (stereo) + * 3: FL FR LFE (2.1 surround) + * 4: FL FR BL BR (quad) + * 5: FL FR FC BL BR (quad + center) + * 6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR) + * 7: FL FR FC LFE BC SL SR (6.1 surround) + * 8: FL FR FC LFE BL BR SL SR (7.1 surround) */ typedef struct SDL_AudioSpec { @@ -174,11 +183,11 @@ typedef struct SDL_AudioSpec SDL_AudioFormat format; /**< Audio data format */ Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */ Uint8 silence; /**< Audio buffer silence value (calculated) */ - Uint16 samples; /**< Audio buffer size in samples (power of 2) */ + Uint16 samples; /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */ Uint16 padding; /**< Necessary for some compile environments */ Uint32 size; /**< Audio buffer size in bytes (calculated) */ - SDL_AudioCallback callback; - void *userdata; + SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */ + void *userdata; /**< Userdata passed to callback (ignored for NULL callbacks). */ } SDL_AudioSpec; @@ -187,8 +196,38 @@ typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt, SDL_AudioFormat format); /** - * A structure to hold a set of audio conversion filters and buffers. + * \brief Upper limit of filters in SDL_AudioCVT + * + * The maximum number of SDL_AudioFilter functions in SDL_AudioCVT is + * currently limited to 9. The SDL_AudioCVT.filters array has 10 pointers, + * one of which is the terminating NULL pointer. */ +#define SDL_AUDIOCVT_MAX_FILTERS 9 + +/** + * \struct SDL_AudioCVT + * \brief A structure to hold a set of audio conversion filters and buffers. + * + * Note that various parts of the conversion pipeline can take advantage + * of SIMD operations (like SSE2, for example). SDL_AudioCVT doesn't require + * you to pass it aligned data, but can possibly run much faster if you + * set both its (buf) field to a pointer that is aligned to 16 bytes, and its + * (len) field to something that's a multiple of 16, if possible. + */ +#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__) +/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't + pad it out to 88 bytes to guarantee ABI compatibility between compilers. + This is not a concern on CHERI architectures, where pointers must be stored + at aligned locations otherwise they will become invalid, and thus structs + containing pointers cannot be packed without giving a warning or error. + vvv + The next time we rev the ABI, make sure to size the ints and add padding. +*/ +#define SDL_AUDIOCVT_PACKED __attribute__((packed)) +#else +#define SDL_AUDIOCVT_PACKED +#endif +/* */ typedef struct SDL_AudioCVT { int needed; /**< Set to 1 if conversion possible */ @@ -200,90 +239,177 @@ typedef struct SDL_AudioCVT int len_cvt; /**< Length of converted audio buffer */ int len_mult; /**< buffer must be len*len_mult big */ double len_ratio; /**< Given len, final size is len*len_ratio */ - SDL_AudioFilter filters[10]; /**< Filter list */ + SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */ int filter_index; /**< Current audio conversion function */ -} SDL_AudioCVT; +} SDL_AUDIOCVT_PACKED SDL_AudioCVT; /* Function prototypes */ /** * \name Driver discovery functions - * + * * These functions return the list of built in audio drivers, in the * order that they are normally initialized by default. */ -/*@{*/ +/* @{ */ + +/** + * Use this function to get the number of built-in audio drivers. + * + * This function returns a hardcoded number. This never returns a negative + * value; if there are no drivers compiled into this build of SDL, this + * function returns zero. The presence of a driver in this list does not mean + * it will function, it just means SDL is capable of interacting with that + * interface. For example, a build of SDL might have esound support, but if + * there's no esound server available, SDL's esound driver would fail if used. + * + * By default, SDL tries all drivers, in its preferred order, until one is + * found to be usable. + * + * \returns the number of built-in audio drivers. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetAudioDriver + */ extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void); + +/** + * Use this function to get the name of a built in audio driver. + * + * The list of audio drivers is given in the order that they are normally + * initialized by default; the drivers that seem more reasonable to choose + * first (as far as the SDL developers believe) are earlier in the list. + * + * The names of drivers are all simple, low-ASCII identifiers, like "alsa", + * "coreaudio" or "xaudio2". These never have Unicode characters, and are not + * meant to be proper names. + * + * \param index the index of the audio driver; the value ranges from 0 to + * SDL_GetNumAudioDrivers() - 1 + * \returns the name of the audio driver at the requested index, or NULL if an + * invalid index was specified. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumAudioDrivers + */ extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index); -/*@}*/ +/* @} */ /** * \name Initialization and cleanup - * + * * \internal These functions are used internally, and should not be used unless - * you have a specific need to specify the audio driver you want to + * you have a specific need to specify the audio driver you want to * use. You should normally use SDL_Init() or SDL_InitSubSystem(). */ -/*@{*/ -extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name); -extern DECLSPEC void SDLCALL SDL_AudioQuit(void); -/*@}*/ +/* @{ */ /** - * This function returns the name of the current audio driver, or NULL - * if no driver has been initialized. + * Use this function to initialize a particular audio driver. + * + * This function is used internally, and should not be used unless you have a + * specific need to designate the audio driver you want to use. You should + * normally use SDL_Init() or SDL_InitSubSystem(). + * + * \param driver_name the name of the desired audio driver + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AudioQuit + */ +extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name); + +/** + * Use this function to shut down audio if you initialized it with + * SDL_AudioInit(). + * + * This function is used internally, and should not be used unless you have a + * specific need to specify the audio driver you want to use. You should + * normally use SDL_Quit() or SDL_QuitSubSystem(). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AudioInit + */ +extern DECLSPEC void SDLCALL SDL_AudioQuit(void); +/* @} */ + +/** + * Get the name of the current audio driver. + * + * The returned string points to internal static memory and thus never becomes + * invalid, even if you quit the audio subsystem and initialize a new driver + * (although such a case would return a different static string from another + * call to this function, of course). As such, you should not modify or free + * the returned string. + * + * \returns the name of the current audio driver or NULL if no driver has been + * initialized. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AudioInit */ extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void); /** - * This function opens the audio device with the desired parameters, and - * returns 0 if successful, placing the actual hardware parameters in the - * structure pointed to by \c obtained. If \c obtained is NULL, the audio - * data passed to the callback function will be guaranteed to be in the - * requested format, and will be automatically converted to the hardware - * audio format if necessary. This function returns -1 if it failed - * to open the audio device, or couldn't set up the audio thread. - * - * When filling in the desired audio spec structure, - * - \c desired->freq should be the desired audio frequency in samples-per- - * second. - * - \c desired->format should be the desired audio format. - * - \c desired->samples is the desired size of the audio buffer, in - * samples. This number should be a power of two, and may be adjusted by - * the audio driver to a value more suitable for the hardware. Good values - * seem to range between 512 and 8096 inclusive, depending on the - * application and CPU speed. Smaller values yield faster response time, - * but can lead to underflow if the application is doing heavy processing - * and cannot fill the audio buffer in time. A stereo sample consists of - * both right and left channels in LR ordering. - * Note that the number of samples is directly related to time by the - * following formula: \code ms = (samples*1000)/freq \endcode - * - \c desired->size is the size in bytes of the audio buffer, and is - * calculated by SDL_OpenAudio(). - * - \c desired->silence is the value used to set the buffer to silence, - * and is calculated by SDL_OpenAudio(). - * - \c desired->callback should be set to a function that will be called - * when the audio device is ready for more data. It is passed a pointer - * to the audio buffer, and the length in bytes of the audio buffer. - * This function usually runs in a separate thread, and so you should - * protect data structures that it accesses by calling SDL_LockAudio() - * and SDL_UnlockAudio() in your code. - * - \c desired->userdata is passed as the first parameter to your callback - * function. - * - * The audio device starts out playing silence when it's opened, and should - * be enabled for playing by calling \c SDL_PauseAudio(0) when you are ready - * for your audio callback function to be called. Since the audio driver - * may modify the requested size of the audio buffer, you should allocate - * any local mixing buffers after you open the audio device. + * This function is a legacy means of opening the audio device. + * + * This function remains for compatibility with SDL 1.2, but also because it's + * slightly easier to use than the new functions in SDL 2.0. The new, more + * powerful, and preferred way to do this is SDL_OpenAudioDevice(). + * + * This function is roughly equivalent to: + * + * ```c + * SDL_OpenAudioDevice(NULL, 0, desired, obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); + * ``` + * + * With two notable exceptions: + * + * - If `obtained` is NULL, we use `desired` (and allow no changes), which + * means desired will be modified to have the correct values for silence, + * etc, and SDL will convert any differences between your app's specific + * request and the hardware behind the scenes. + * - The return value is always success or failure, and not a device ID, which + * means you can only have one device open at a time with this function. + * + * \param desired an SDL_AudioSpec structure representing the desired output + * format. Please refer to the SDL_OpenAudioDevice + * documentation for details on how to prepare this structure. + * \param obtained an SDL_AudioSpec structure filled in with the actual + * parameters, or NULL. + * \returns 0 if successful, placing the actual hardware parameters in the + * structure pointed to by `obtained`. + * + * If `obtained` is NULL, the audio data passed to the callback + * function will be guaranteed to be in the requested format, and + * will be automatically converted to the actual hardware audio + * format if necessary. If `obtained` is NULL, `desired` will have + * fields modified. + * + * This function returns a negative error code on failure to open the + * audio device or failure to set up the audio thread; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CloseAudio + * \sa SDL_LockAudio + * \sa SDL_PauseAudio + * \sa SDL_UnlockAudio */ extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained); /** * SDL Audio Device IDs. - * + * * A successful call to SDL_OpenAudio() is always device id 1, and legacy * SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls * always returns devices >= 2 on success. The legacy calls are good both @@ -293,113 +419,417 @@ extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, typedef Uint32 SDL_AudioDeviceID; /** - * Get the number of available devices exposed by the current driver. - * Only valid after a successfully initializing the audio subsystem. - * Returns -1 if an explicit list of devices can't be determined; this is - * not an error. For example, if SDL is set up to talk to a remote audio - * server, it can't list every one available on the Internet, but it will - * still allow a specific host to be specified to SDL_OpenAudioDevice(). - * - * In many common cases, when this function returns a value <= 0, it can still - * successfully open the default device (NULL for first argument of - * SDL_OpenAudioDevice()). + * Get the number of built-in audio devices. + * + * This function is only valid after successfully initializing the audio + * subsystem. + * + * Note that audio capture support is not implemented as of SDL 2.0.4, so the + * `iscapture` parameter is for future expansion and should always be zero for + * now. + * + * This function will return -1 if an explicit list of devices can't be + * determined. Returning -1 is not an error. For example, if SDL is set up to + * talk to a remote audio server, it can't list every one available on the + * Internet, but it will still allow a specific host to be specified in + * SDL_OpenAudioDevice(). + * + * In many common cases, when this function returns a value <= 0, it can still + * successfully open the default device (NULL for first argument of + * SDL_OpenAudioDevice()). + * + * This function may trigger a complete redetect of available hardware. It + * should not be called for each iteration of a loop, but rather once at the + * start of a loop: + * + * ```c + * // Don't do this: + * for (int i = 0; i < SDL_GetNumAudioDevices(0); i++) + * + * // do this instead: + * const int count = SDL_GetNumAudioDevices(0); + * for (int i = 0; i < count; ++i) { do_something_here(); } + * ``` + * + * \param iscapture zero to request playback devices, non-zero to request + * recording devices + * \returns the number of available devices exposed by the current driver or + * -1 if an explicit list of devices can't be determined. A return + * value of -1 does not necessarily mean an error condition. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetAudioDeviceName + * \sa SDL_OpenAudioDevice */ extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture); /** - * Get the human-readable name of a specific audio device. - * Must be a value between 0 and (number of audio devices-1). - * Only valid after a successfully initializing the audio subsystem. - * The values returned by this function reflect the latest call to - * SDL_GetNumAudioDevices(); recall that function to redetect available - * hardware. - * - * The string returned by this function is UTF-8 encoded, read-only, and - * managed internally. You are not to free it. If you need to keep the - * string for any length of time, you should make your own copy of it, as it - * will be invalid next time any of several other SDL functions is called. + * Get the human-readable name of a specific audio device. + * + * This function is only valid after successfully initializing the audio + * subsystem. The values returned by this function reflect the latest call to + * SDL_GetNumAudioDevices(); re-call that function to redetect available + * hardware. + * + * The string returned by this function is UTF-8 encoded, read-only, and + * managed internally. You are not to free it. If you need to keep the string + * for any length of time, you should make your own copy of it, as it will be + * invalid next time any of several other SDL functions are called. + * + * \param index the index of the audio device; valid values range from 0 to + * SDL_GetNumAudioDevices() - 1 + * \param iscapture non-zero to query the list of recording devices, zero to + * query the list of output devices. + * \returns the name of the audio device at the requested index, or NULL on + * error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumAudioDevices */ extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index, int iscapture); +/** + * Get the preferred audio format of a specific audio device. + * + * This function is only valid after a successfully initializing the audio + * subsystem. The values returned by this function reflect the latest call to + * SDL_GetNumAudioDevices(); re-call that function to redetect available + * hardware. + * + * `spec` will be filled with the sample rate, sample format, and channel + * count. All other values in the structure are filled with 0. When the + * supported struct members are 0, SDL was unable to get the property from the + * backend. + * + * \param index the index of the audio device; valid values range from 0 to + * SDL_GetNumAudioDevices() - 1 + * \param iscapture non-zero to query the list of recording devices, zero to + * query the list of output devices. + * \param spec The SDL_AudioSpec to be initialized by this function. + * \returns 0 on success, nonzero on error + * + * \since This function is available since SDL 2.0.16. + * + * \sa SDL_GetNumAudioDevices + */ +extern DECLSPEC int SDLCALL SDL_GetAudioDeviceSpec(int index, + int iscapture, + SDL_AudioSpec *spec); + /** - * Open a specific audio device. Passing in a device name of NULL requests - * the most reasonable default (and is equivalent to calling SDL_OpenAudio()). - * - * The device name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but - * some drivers allow arbitrary and driver-specific strings, such as a - * hostname/IP address for a remote audio server, or a filename in the - * diskaudio driver. - * - * \return 0 on error, a valid device ID that is >= 2 on success. - * - * SDL_OpenAudio(), unlike this function, always acts on device ID 1. + * Open a specific audio device. + * + * SDL_OpenAudio(), unlike this function, always acts on device ID 1. As such, + * this function will never return a 1 so as not to conflict with the legacy + * function. + * + * Please note that SDL 2.0 before 2.0.5 did not support recording; as such, + * this function would fail if `iscapture` was not zero. Starting with SDL + * 2.0.5, recording is implemented and this value can be non-zero. + * + * Passing in a `device` name of NULL requests the most reasonable default + * (and is equivalent to what SDL_OpenAudio() does to choose a device). The + * `device` name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but + * some drivers allow arbitrary and driver-specific strings, such as a + * hostname/IP address for a remote audio server, or a filename in the + * diskaudio driver. + * + * An opened audio device starts out paused, and should be enabled for playing + * by calling SDL_PauseAudioDevice(devid, 0) when you are ready for your audio + * callback function to be called. Since the audio driver may modify the + * requested size of the audio buffer, you should allocate any local mixing + * buffers after you open the audio device. + * + * The audio callback runs in a separate thread in most cases; you can prevent + * race conditions between your callback and other threads without fully + * pausing playback with SDL_LockAudioDevice(). For more information about the + * callback, see SDL_AudioSpec. + * + * Managing the audio spec via 'desired' and 'obtained': + * + * When filling in the desired audio spec structure: + * + * - `desired->freq` should be the frequency in sample-frames-per-second (Hz). + * - `desired->format` should be the audio format (`AUDIO_S16SYS`, etc). + * - `desired->samples` is the desired size of the audio buffer, in _sample + * frames_ (with stereo output, two samples--left and right--would make a + * single sample frame). This number should be a power of two, and may be + * adjusted by the audio driver to a value more suitable for the hardware. + * Good values seem to range between 512 and 8096 inclusive, depending on + * the application and CPU speed. Smaller values reduce latency, but can + * lead to underflow if the application is doing heavy processing and cannot + * fill the audio buffer in time. Note that the number of sample frames is + * directly related to time by the following formula: `ms = + * (sampleframes*1000)/freq` + * - `desired->size` is the size in _bytes_ of the audio buffer, and is + * calculated by SDL_OpenAudioDevice(). You don't initialize this. + * - `desired->silence` is the value used to set the buffer to silence, and is + * calculated by SDL_OpenAudioDevice(). You don't initialize this. + * - `desired->callback` should be set to a function that will be called when + * the audio device is ready for more data. It is passed a pointer to the + * audio buffer, and the length in bytes of the audio buffer. This function + * usually runs in a separate thread, and so you should protect data + * structures that it accesses by calling SDL_LockAudioDevice() and + * SDL_UnlockAudioDevice() in your code. Alternately, you may pass a NULL + * pointer here, and call SDL_QueueAudio() with some frequency, to queue + * more audio samples to be played (or for capture devices, call + * SDL_DequeueAudio() with some frequency, to obtain audio samples). + * - `desired->userdata` is passed as the first parameter to your callback + * function. If you passed a NULL callback, this value is ignored. + * + * `allowed_changes` can have the following flags OR'd together: + * + * - `SDL_AUDIO_ALLOW_FREQUENCY_CHANGE` + * - `SDL_AUDIO_ALLOW_FORMAT_CHANGE` + * - `SDL_AUDIO_ALLOW_CHANNELS_CHANGE` + * - `SDL_AUDIO_ALLOW_ANY_CHANGE` + * + * These flags specify how SDL should behave when a device cannot offer a + * specific feature. If the application requests a feature that the hardware + * doesn't offer, SDL will always try to get the closest equivalent. + * + * For example, if you ask for float32 audio format, but the sound card only + * supports int16, SDL will set the hardware to int16. If you had set + * SDL_AUDIO_ALLOW_FORMAT_CHANGE, SDL will change the format in the `obtained` + * structure. If that flag was *not* set, SDL will prepare to convert your + * callback's float32 audio to int16 before feeding it to the hardware and + * will keep the originally requested format in the `obtained` structure. + * + * The resulting audio specs, varying depending on hardware and on what + * changes were allowed, will then be written back to `obtained`. + * + * If your application can only handle one specific data format, pass a zero + * for `allowed_changes` and let SDL transparently handle any differences. + * + * \param device a UTF-8 string reported by SDL_GetAudioDeviceName() or a + * driver-specific name as appropriate. NULL requests the most + * reasonable default device. + * \param iscapture non-zero to specify a device should be opened for + * recording, not playback + * \param desired an SDL_AudioSpec structure representing the desired output + * format; see SDL_OpenAudio() for more information + * \param obtained an SDL_AudioSpec structure filled in with the actual output + * format; see SDL_OpenAudio() for more information + * \param allowed_changes 0, or one or more flags OR'd together + * \returns a valid device ID that is > 0 on success or 0 on failure; call + * SDL_GetError() for more information. + * + * For compatibility with SDL 1.2, this will never return 1, since + * SDL reserves that ID for the legacy SDL_OpenAudio() function. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CloseAudioDevice + * \sa SDL_GetAudioDeviceName + * \sa SDL_LockAudioDevice + * \sa SDL_OpenAudio + * \sa SDL_PauseAudioDevice + * \sa SDL_UnlockAudioDevice */ -extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char - *device, - int iscapture, - const - SDL_AudioSpec * - desired, - SDL_AudioSpec * - obtained, - int - allowed_changes); +extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice( + const char *device, + int iscapture, + const SDL_AudioSpec *desired, + SDL_AudioSpec *obtained, + int allowed_changes); /** * \name Audio state - * + * * Get the current audio state. */ -/*@{*/ +/* @{ */ typedef enum { SDL_AUDIO_STOPPED = 0, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED } SDL_AudioStatus; + +/** + * This function is a legacy means of querying the audio device. + * + * New programs might want to use SDL_GetAudioDeviceStatus() instead. This + * function is equivalent to calling... + * + * ```c + * SDL_GetAudioDeviceStatus(1); + * ``` + * + * ...and is only useful if you used the legacy SDL_OpenAudio() function. + * + * \returns the SDL_AudioStatus of the audio device opened by SDL_OpenAudio(). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetAudioDeviceStatus + */ extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioStatus(void); -extern DECLSPEC SDL_AudioStatus SDLCALL -SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev); -/*@}*//*Audio State*/ +/** + * Use this function to get the current audio state of an audio device. + * + * \param dev the ID of an audio device previously opened with + * SDL_OpenAudioDevice() + * \returns the SDL_AudioStatus of the specified audio device. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PauseAudioDevice + */ +extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev); +/* @} *//* Audio State */ /** * \name Pause audio functions - * + * * These functions pause and unpause the audio callback processing. * They should be called with a parameter of 0 after opening the audio * device to start playing sound. This is so you can safely initialize * data for your callback function after opening the audio device. * Silence will be written to the audio device during the pause. */ -/*@{*/ -extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on); -extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, - int pause_on); -/*@}*//*Pause audio functions*/ +/* @{ */ /** - * This function loads a WAVE from the data source, automatically freeing - * that source if \c freesrc is non-zero. For example, to load a WAVE file, - * you could do: - * \code - * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); - * \endcode + * This function is a legacy means of pausing the audio device. * - * If this function succeeds, it returns the given SDL_AudioSpec, - * filled with the audio data format of the wave data, and sets - * \c *audio_buf to a malloc()'d buffer containing the audio data, - * and sets \c *audio_len to the length of that audio buffer, in bytes. - * You need to free the audio buffer with SDL_FreeWAV() when you are - * done with it. + * New programs might want to use SDL_PauseAudioDevice() instead. This + * function is equivalent to calling... * - * This function returns NULL and sets the SDL error message if the - * wave file cannot be opened, uses an unknown data format, or is - * corrupt. Currently raw and MS-ADPCM WAVE files are supported. + * ```c + * SDL_PauseAudioDevice(1, pause_on); + * ``` + * + * ...and is only useful if you used the legacy SDL_OpenAudio() function. + * + * \param pause_on non-zero to pause, 0 to unpause + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetAudioStatus + * \sa SDL_PauseAudioDevice + */ +extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on); + +/** + * Use this function to pause and unpause audio playback on a specified + * device. + * + * This function pauses and unpauses the audio callback processing for a given + * device. Newly-opened audio devices start in the paused state, so you must + * call this function with **pause_on**=0 after opening the specified audio + * device to start playing sound. This allows you to safely initialize data + * for your callback function after opening the audio device. Silence will be + * written to the audio device while paused, and the audio callback is + * guaranteed to not be called. Pausing one device does not prevent other + * unpaused devices from running their callbacks. + * + * Pausing state does not stack; even if you pause a device several times, a + * single unpause will start the device playing again, and vice versa. This is + * different from how SDL_LockAudioDevice() works. + * + * If you just need to protect a few variables from race conditions vs your + * callback, you shouldn't pause the audio device, as it will lead to dropouts + * in the audio playback. Instead, you should use SDL_LockAudioDevice(). + * + * \param dev a device opened by SDL_OpenAudioDevice() + * \param pause_on non-zero to pause, 0 to unpause + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LockAudioDevice + */ +extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, + int pause_on); +/* @} *//* Pause audio functions */ + +/** + * Load the audio data of a WAVE file into memory. + * + * Loading a WAVE file requires `src`, `spec`, `audio_buf` and `audio_len` to + * be valid pointers. The entire data portion of the file is then loaded into + * memory and decoded if necessary. + * + * If `freesrc` is non-zero, the data source gets automatically closed and + * freed before the function returns. + * + * Supported formats are RIFF WAVE files with the formats PCM (8, 16, 24, and + * 32 bits), IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and + * A-law and mu-law (8 bits). Other formats are currently unsupported and + * cause an error. + * + * If this function succeeds, the pointer returned by it is equal to `spec` + * and the pointer to the audio data allocated by the function is written to + * `audio_buf` and its length in bytes to `audio_len`. The SDL_AudioSpec + * members `freq`, `channels`, and `format` are set to the values of the audio + * data in the buffer. The `samples` member is set to a sane default and all + * others are set to zero. + * + * It's necessary to use SDL_FreeWAV() to free the audio data returned in + * `audio_buf` when it is no longer used. + * + * Because of the underspecification of the .WAV format, there are many + * problematic files in the wild that cause issues with strict decoders. To + * provide compatibility with these files, this decoder is lenient in regards + * to the truncation of the file, the fact chunk, and the size of the RIFF + * chunk. The hints `SDL_HINT_WAVE_RIFF_CHUNK_SIZE`, + * `SDL_HINT_WAVE_TRUNCATION`, and `SDL_HINT_WAVE_FACT_CHUNK` can be used to + * tune the behavior of the loading process. + * + * Any file that is invalid (due to truncation, corruption, or wrong values in + * the headers), too big, or unsupported causes an error. Additionally, any + * critical I/O error from the data source will terminate the loading process + * with an error. The function returns NULL on error and in all cases (with + * the exception of `src` being NULL), an appropriate error message will be + * set. + * + * It is required that the data source supports seeking. + * + * Example: + * + * ```c + * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, &spec, &buf, &len); + * ``` + * + * Note that the SDL_LoadWAV macro does this same thing for you, but in a less + * messy way: + * + * ```c + * SDL_LoadWAV("sample.wav", &spec, &buf, &len); + * ``` + * + * \param src The data source for the WAVE data + * \param freesrc If non-zero, SDL will _always_ free the data source + * \param spec An SDL_AudioSpec that will be filled in with the wave file's + * format details + * \param audio_buf A pointer filled with the audio data, allocated by the + * function. + * \param audio_len A pointer filled with the length of the audio data buffer + * in bytes + * \returns This function, if successfully called, returns `spec`, which will + * be filled with the audio data format of the wave source data. + * `audio_buf` will be filled with a pointer to an allocated buffer + * containing the audio data, and `audio_len` is filled with the + * length of that audio buffer in bytes. + * + * This function returns NULL if the .WAV file cannot be opened, uses + * an unknown data format, or is corrupt; call SDL_GetError() for + * more information. + * + * When the application is done with the data returned in + * `audio_buf`, it should call SDL_FreeWAV() to dispose of it. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreeWAV + * \sa SDL_LoadWAV */ extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, @@ -407,26 +837,61 @@ extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, Uint8 ** audio_buf, Uint32 * audio_len); -/** +/** * Loads a WAV from a file. * Compatibility convenience function. */ #define SDL_LoadWAV(file, spec, audio_buf, audio_len) \ - SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) + SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) /** - * This function frees data previously allocated with SDL_LoadWAV_RW() + * Free data previously allocated with SDL_LoadWAV() or SDL_LoadWAV_RW(). + * + * After a WAVE file has been opened with SDL_LoadWAV() or SDL_LoadWAV_RW() + * its data can eventually be freed with SDL_FreeWAV(). It is safe to call + * this function with a NULL pointer. + * + * \param audio_buf a pointer to the buffer created by SDL_LoadWAV() or + * SDL_LoadWAV_RW() + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadWAV + * \sa SDL_LoadWAV_RW */ extern DECLSPEC void SDLCALL SDL_FreeWAV(Uint8 * audio_buf); /** - * This function takes a source format and rate and a destination format - * and rate, and initializes the \c cvt structure with information needed - * by SDL_ConvertAudio() to convert a buffer of audio data from one format - * to the other. - * - * \return -1 if the format conversion is not supported, 0 if there's - * no conversion needed, or 1 if the audio filter is set up. + * Initialize an SDL_AudioCVT structure for conversion. + * + * Before an SDL_AudioCVT structure can be used to convert audio data it must + * be initialized with source and destination information. + * + * This function will zero out every field of the SDL_AudioCVT, so it must be + * called before the application fills in the final buffer information. + * + * Once this function has returned successfully, and reported that a + * conversion is necessary, the application fills in the rest of the fields in + * SDL_AudioCVT, now that it knows how large a buffer it needs to allocate, + * and then can call SDL_ConvertAudio() to complete the conversion. + * + * \param cvt an SDL_AudioCVT structure filled in with audio conversion + * information + * \param src_format the source format of the audio data; for more info see + * SDL_AudioFormat + * \param src_channels the number of channels in the source + * \param src_rate the frequency (sample-frames-per-second) of the source + * \param dst_format the destination format of the audio data; for more info + * see SDL_AudioFormat + * \param dst_channels the number of channels in the destination + * \param dst_rate the frequency (sample-frames-per-second) of the destination + * \returns 1 if the audio filter is prepared, 0 if no conversion is needed, + * or a negative error code on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ConvertAudio */ extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt, SDL_AudioFormat src_format, @@ -437,73 +902,563 @@ extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt, int dst_rate); /** - * Once you have initialized the \c cvt structure using SDL_BuildAudioCVT(), - * created an audio buffer \c cvt->buf, and filled it with \c cvt->len bytes of - * audio data in the source format, this function will convert it in-place - * to the desired format. - * - * The data conversion may expand the size of the audio data, so the buffer - * \c cvt->buf should be allocated after the \c cvt structure is initialized by - * SDL_BuildAudioCVT(), and should be \c cvt->len*cvt->len_mult bytes long. + * Convert audio data to a desired audio format. + * + * This function does the actual audio data conversion, after the application + * has called SDL_BuildAudioCVT() to prepare the conversion information and + * then filled in the buffer details. + * + * Once the application has initialized the `cvt` structure using + * SDL_BuildAudioCVT(), allocated an audio buffer and filled it with audio + * data in the source format, this function will convert the buffer, in-place, + * to the desired format. + * + * The data conversion may go through several passes; any given pass may + * possibly temporarily increase the size of the data. For example, SDL might + * expand 16-bit data to 32 bits before resampling to a lower frequency, + * shrinking the data size after having grown it briefly. Since the supplied + * buffer will be both the source and destination, converting as necessary + * in-place, the application must allocate a buffer that will fully contain + * the data during its largest conversion pass. After SDL_BuildAudioCVT() + * returns, the application should set the `cvt->len` field to the size, in + * bytes, of the source data, and allocate a buffer that is `cvt->len * + * cvt->len_mult` bytes long for the `buf` field. + * + * The source data should be copied into this buffer before the call to + * SDL_ConvertAudio(). Upon successful return, this buffer will contain the + * converted audio, and `cvt->len_cvt` will be the size of the converted data, + * in bytes. Any bytes in the buffer past `cvt->len_cvt` are undefined once + * this function returns. + * + * \param cvt an SDL_AudioCVT structure that was previously set up by + * SDL_BuildAudioCVT(). + * \returns 0 if the conversion was completed successfully or a negative error + * code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BuildAudioCVT */ extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt); -#define SDL_MIX_MAXVOLUME 128 +/* SDL_AudioStream is a new audio conversion interface. + The benefits vs SDL_AudioCVT: + - it can handle resampling data in chunks without generating + artifacts, when it doesn't have the complete buffer available. + - it can handle incoming data in any variable size. + - You push data as you have it, and pull it when you need it + */ +/* this is opaque to the outside world. */ +struct _SDL_AudioStream; +typedef struct _SDL_AudioStream SDL_AudioStream; + /** - * This takes two audio buffers of the playing audio format and mixes - * them, performing addition, volume adjustment, and overflow clipping. - * The volume ranges from 0 - 128, and should be set to ::SDL_MIX_MAXVOLUME - * for full audio volume. Note this does not change hardware volume. - * This is provided for convenience -- you can mix your own audio data. + * Create a new audio stream. + * + * \param src_format The format of the source audio + * \param src_channels The number of channels of the source audio + * \param src_rate The sampling rate of the source audio + * \param dst_format The format of the desired audio output + * \param dst_channels The number of channels of the desired audio output + * \param dst_rate The sampling rate of the desired audio output + * \returns 0 on success, or -1 on error. + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamFlush + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC SDL_AudioStream * SDLCALL SDL_NewAudioStream(const SDL_AudioFormat src_format, + const Uint8 src_channels, + const int src_rate, + const SDL_AudioFormat dst_format, + const Uint8 dst_channels, + const int dst_rate); + +/** + * Add data to be converted/resampled to the stream. + * + * \param stream The stream the audio data is being added to + * \param buf A pointer to the audio data to add + * \param len The number of bytes to write to the stream + * \returns 0 on success, or -1 on error. + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamFlush + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len); + +/** + * Get converted/resampled data from the stream + * + * \param stream The stream the audio is being requested from + * \param buf A buffer to fill with audio data + * \param len The maximum number of bytes to fill + * \returns the number of bytes read from the stream, or -1 on error + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamFlush + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len); + +/** + * Get the number of converted/resampled bytes available. + * + * The stream may be buffering data behind the scenes until it has enough to + * resample correctly, so this number might be lower than what you expect, or + * even be zero. Add more data or flush the stream if you need the data now. + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamFlush + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamAvailable(SDL_AudioStream *stream); + +/** + * Tell the stream that you're done sending data, and anything being buffered + * should be converted/resampled and made available immediately. + * + * It is legal to add more data to a stream after flushing, but there will be + * audio gaps in the output. Generally this is intended to signal the end of + * input, so the complete output becomes available. + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamFlush(SDL_AudioStream *stream); + +/** + * Clear any pending data in the stream without converting it + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamFlush + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC void SDLCALL SDL_AudioStreamClear(SDL_AudioStream *stream); + +/** + * Free an audio stream + * + * \since This function is available since SDL 2.0.7. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamFlush + * \sa SDL_AudioStreamClear + */ +extern DECLSPEC void SDLCALL SDL_FreeAudioStream(SDL_AudioStream *stream); + +#define SDL_MIX_MAXVOLUME 128 + +/** + * This function is a legacy means of mixing audio. + * + * This function is equivalent to calling... + * + * ```c + * SDL_MixAudioFormat(dst, src, format, len, volume); + * ``` + * + * ...where `format` is the obtained format of the audio device from the + * legacy SDL_OpenAudio() function. + * + * \param dst the destination for the mixed audio + * \param src the source audio buffer to be mixed + * \param len the length of the audio buffer in bytes + * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME + * for full audio volume + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_MixAudioFormat */ extern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume); /** - * This works like SDL_MixAudio(), but you specify the audio format instead of - * using the format of audio device 1. Thus it can be used when no audio - * device is open at all. + * Mix audio data in a specified format. + * + * This takes an audio buffer `src` of `len` bytes of `format` data and mixes + * it into `dst`, performing addition, volume adjustment, and overflow + * clipping. The buffer pointed to by `dst` must also be `len` bytes of + * `format` data. + * + * This is provided for convenience -- you can mix your own audio data. + * + * Do not use this function for mixing together more than two streams of + * sample data. The output from repeated application of this function may be + * distorted by clipping, because there is no accumulator with greater range + * than the input (not to mention this being an inefficient way of doing it). + * + * It is a common misconception that this function is required to write audio + * data to an output stream in an audio callback. While you can do that, + * SDL_MixAudioFormat() is really only needed when you're mixing a single + * audio stream with a volume adjustment. + * + * \param dst the destination for the mixed audio + * \param src the source audio buffer to be mixed + * \param format the SDL_AudioFormat structure representing the desired audio + * format + * \param len the length of the audio buffer in bytes + * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME + * for full audio volume + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format, Uint32 len, int volume); +/** + * Queue more audio on non-callback devices. + * + * If you are looking to retrieve queued audio from a non-callback capture + * device, you want SDL_DequeueAudio() instead. SDL_QueueAudio() will return + * -1 to signify an error if you use it with capture devices. + * + * SDL offers two ways to feed audio to the device: you can either supply a + * callback that SDL triggers with some frequency to obtain more audio (pull + * method), or you can supply no callback, and then SDL will expect you to + * supply data at regular intervals (push method) with this function. + * + * There are no limits on the amount of data you can queue, short of + * exhaustion of address space. Queued data will drain to the device as + * necessary without further intervention from you. If the device needs audio + * but there is not enough queued, it will play silence to make up the + * difference. This means you will have skips in your audio playback if you + * aren't routinely queueing sufficient data. + * + * This function copies the supplied data, so you are safe to free it when the + * function returns. This function is thread-safe, but queueing to the same + * device from two threads at once does not promise which buffer will be + * queued first. + * + * You may not queue audio on a device that is using an application-supplied + * callback; doing so returns an error. You have to use the audio callback or + * queue audio with this function, but not both. + * + * You should not call SDL_LockAudio() on the device before queueing; SDL + * handles locking internally for this function. + * + * Note that SDL2 does not support planar audio. You will need to resample + * from planar audio formats into a non-planar one (see SDL_AudioFormat) + * before queuing audio. + * + * \param dev the device ID to which we will queue audio + * \param data the data to queue to the device for later playback + * \param len the number of bytes (not samples!) to which `data` points + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_ClearQueuedAudio + * \sa SDL_GetQueuedAudioSize + */ +extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len); + +/** + * Dequeue more audio on non-callback devices. + * + * If you are looking to queue audio for output on a non-callback playback + * device, you want SDL_QueueAudio() instead. SDL_DequeueAudio() will always + * return 0 if you use it with playback devices. + * + * SDL offers two ways to retrieve audio from a capture device: you can either + * supply a callback that SDL triggers with some frequency as the device + * records more audio data, (push method), or you can supply no callback, and + * then SDL will expect you to retrieve data at regular intervals (pull + * method) with this function. + * + * There are no limits on the amount of data you can queue, short of + * exhaustion of address space. Data from the device will keep queuing as + * necessary without further intervention from you. This means you will + * eventually run out of memory if you aren't routinely dequeueing data. + * + * Capture devices will not queue data when paused; if you are expecting to + * not need captured audio for some length of time, use SDL_PauseAudioDevice() + * to stop the capture device from queueing more data. This can be useful + * during, say, level loading times. When unpaused, capture devices will start + * queueing data from that point, having flushed any capturable data available + * while paused. + * + * This function is thread-safe, but dequeueing from the same device from two + * threads at once does not promise which thread will dequeue data first. + * + * You may not dequeue audio from a device that is using an + * application-supplied callback; doing so returns an error. You have to use + * the audio callback, or dequeue audio with this function, but not both. + * + * You should not call SDL_LockAudio() on the device before dequeueing; SDL + * handles locking internally for this function. + * + * \param dev the device ID from which we will dequeue audio + * \param data a pointer into where audio data should be copied + * \param len the number of bytes (not samples!) to which (data) points + * \returns the number of bytes dequeued, which could be less than requested; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_ClearQueuedAudio + * \sa SDL_GetQueuedAudioSize + */ +extern DECLSPEC Uint32 SDLCALL SDL_DequeueAudio(SDL_AudioDeviceID dev, void *data, Uint32 len); + +/** + * Get the number of bytes of still-queued audio. + * + * For playback devices: this is the number of bytes that have been queued for + * playback with SDL_QueueAudio(), but have not yet been sent to the hardware. + * + * Once we've sent it to the hardware, this function can not decide the exact + * byte boundary of what has been played. It's possible that we just gave the + * hardware several kilobytes right before you called this function, but it + * hasn't played any of it yet, or maybe half of it, etc. + * + * For capture devices, this is the number of bytes that have been captured by + * the device and are waiting for you to dequeue. This number may grow at any + * time, so this only informs of the lower-bound of available data. + * + * You may not queue or dequeue audio on a device that is using an + * application-supplied callback; calling this function on such a device + * always returns 0. You have to use the audio callback or queue audio, but + * not both. + * + * You should not call SDL_LockAudio() on the device before querying; SDL + * handles locking internally for this function. + * + * \param dev the device ID of which we will query queued audio size + * \returns the number of bytes (not samples!) of queued audio. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_ClearQueuedAudio + * \sa SDL_QueueAudio + * \sa SDL_DequeueAudio + */ +extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev); + +/** + * Drop any queued audio data waiting to be sent to the hardware. + * + * Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For + * output devices, the hardware will start playing silence if more audio isn't + * queued. For capture devices, the hardware will start filling the empty + * queue with new data if the capture device isn't paused. + * + * This will not prevent playback of queued audio that's already been sent to + * the hardware, as we can not undo that, so expect there to be some fraction + * of a second of audio that might still be heard. This can be useful if you + * want to, say, drop any pending music or any unprocessed microphone input + * during a level change in your game. + * + * You may not queue or dequeue audio on a device that is using an + * application-supplied callback; calling this function on such a device + * always returns 0. You have to use the audio callback or queue audio, but + * not both. + * + * You should not call SDL_LockAudio() on the device before clearing the + * queue; SDL handles locking internally for this function. + * + * This function always succeeds and thus returns void. + * + * \param dev the device ID of which to clear the audio queue + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_GetQueuedAudioSize + * \sa SDL_QueueAudio + * \sa SDL_DequeueAudio + */ +extern DECLSPEC void SDLCALL SDL_ClearQueuedAudio(SDL_AudioDeviceID dev); + + /** * \name Audio lock functions - * + * * The lock manipulated by these functions protects the callback function. - * During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that + * During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that * the callback function is not running. Do not call these from the callback * function or you will cause deadlock. */ -/*@{*/ -extern DECLSPEC void SDLCALL SDL_LockAudio(void); -extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev); -extern DECLSPEC void SDLCALL SDL_UnlockAudio(void); -extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev); -/*@}*//*Audio lock functions*/ +/* @{ */ /** - * This function shuts down audio processing and closes the audio device. + * This function is a legacy means of locking the audio device. + * + * New programs might want to use SDL_LockAudioDevice() instead. This function + * is equivalent to calling... + * + * ```c + * SDL_LockAudioDevice(1); + * ``` + * + * ...and is only useful if you used the legacy SDL_OpenAudio() function. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LockAudioDevice + * \sa SDL_UnlockAudio + * \sa SDL_UnlockAudioDevice + */ +extern DECLSPEC void SDLCALL SDL_LockAudio(void); + +/** + * Use this function to lock out the audio callback function for a specified + * device. + * + * The lock manipulated by these functions protects the audio callback + * function specified in SDL_OpenAudioDevice(). During a + * SDL_LockAudioDevice()/SDL_UnlockAudioDevice() pair, you can be guaranteed + * that the callback function for that device is not running, even if the + * device is not paused. While a device is locked, any other unpaused, + * unlocked devices may still run their callbacks. + * + * Calling this function from inside your audio callback is unnecessary. SDL + * obtains this lock before calling your function, and releases it when the + * function returns. + * + * You should not hold the lock longer than absolutely necessary. If you hold + * it too long, you'll experience dropouts in your audio playback. Ideally, + * your application locks the device, sets a few variables and unlocks again. + * Do not do heavy work while holding the lock for a device. + * + * It is safe to lock the audio device multiple times, as long as you unlock + * it an equivalent number of times. The callback will not run until the + * device has been unlocked completely in this way. If your application fails + * to unlock the device appropriately, your callback will never run, you might + * hear repeating bursts of audio, and SDL_CloseAudioDevice() will probably + * deadlock. + * + * Internally, the audio device lock is a mutex; if you lock from two threads + * at once, not only will you block the audio callback, you'll block the other + * thread. + * + * \param dev the ID of the device to be locked + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_UnlockAudioDevice + */ +extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev); + +/** + * This function is a legacy means of unlocking the audio device. + * + * New programs might want to use SDL_UnlockAudioDevice() instead. This + * function is equivalent to calling... + * + * ```c + * SDL_UnlockAudioDevice(1); + * ``` + * + * ...and is only useful if you used the legacy SDL_OpenAudio() function. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LockAudio + * \sa SDL_UnlockAudioDevice + */ +extern DECLSPEC void SDLCALL SDL_UnlockAudio(void); + +/** + * Use this function to unlock the audio callback function for a specified + * device. + * + * This function should be paired with a previous SDL_LockAudioDevice() call. + * + * \param dev the ID of the device to be unlocked + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LockAudioDevice + */ +extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev); +/* @} *//* Audio lock functions */ + +/** + * This function is a legacy means of closing the audio device. + * + * This function is equivalent to calling... + * + * ```c + * SDL_CloseAudioDevice(1); + * ``` + * + * ...and is only useful if you used the legacy SDL_OpenAudio() function. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_OpenAudio */ extern DECLSPEC void SDLCALL SDL_CloseAudio(void); -extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev); /** - * \return 1 if audio device is still functioning, zero if not, -1 on error. + * Use this function to shut down audio processing and close the audio device. + * + * The application should close open audio devices once they are no longer + * needed. Calling this function will wait until the device's audio callback + * is not running, release the audio hardware and then clean up internal + * state. No further audio will play from this device once this function + * returns. + * + * This function may block briefly while pending audio data is played by the + * hardware, so that applications don't drop the last buffer of data they + * supplied. + * + * The device ID is invalid as soon as the device is closed, and is eligible + * for reuse in a new SDL_OpenAudioDevice() call immediately. + * + * \param dev an audio device previously opened with SDL_OpenAudioDevice() + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_OpenAudioDevice */ -extern DECLSPEC int SDLCALL SDL_AudioDeviceConnected(SDL_AudioDeviceID dev); - +extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_audio_h */ +#endif /* SDL_audio_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_bits.h b/external/SDL2/SDL_bits.h index d678b78..22cb853 100644 --- a/external/SDL2/SDL_bits.h +++ b/external/SDL2/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -25,17 +25,15 @@ * Functions for fiddling with bits and bitmasks. */ -#ifndef _SDL_bits_h -#define _SDL_bits_h +#ifndef SDL_bits_h_ +#define SDL_bits_h_ #include "SDL_stdinc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** @@ -47,27 +45,54 @@ extern "C" { * with 0. This operation can also be stated as "count leading zeroes" and * "log base 2". * - * \return Index of the most significant bit. + * \return the index of the most significant bit, or -1 if the value is 0. */ -SDL_FORCE_INLINE Sint8 +#if defined(__WATCOMC__) && defined(__386__) +extern __inline int _SDL_bsr_watcom(Uint32); +#pragma aux _SDL_bsr_watcom = \ + "bsr eax, eax" \ + parm [eax] nomemory \ + value [eax] \ + modify exact [eax] nomemory; +#endif + +SDL_FORCE_INLINE int SDL_MostSignificantBitIndex32(Uint32 x) { -#if defined(__GNUC__) && __GNUC__ >= 4 +#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) /* Count Leading Zeroes builtin in GCC. * http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html */ + if (x == 0) { + return -1; + } return 31 - __builtin_clz(x); +#elif defined(__WATCOMC__) && defined(__386__) + if (x == 0) { + return -1; + } + return _SDL_bsr_watcom(x); +#elif defined(_MSC_VER) + unsigned long index; + if (_BitScanReverse(&index, x)) { + return index; + } + return -1; #else /* Based off of Bit Twiddling Hacks by Sean Eron Anderson * , released in the public domain. * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog */ const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000}; - const Uint8 S[] = {1, 2, 4, 8, 16}; + const int S[] = {1, 2, 4, 8, 16}; - Uint8 msbIndex = 0; + int msbIndex = 0; int i; + if (x == 0) { + return -1; + } + for (i = 4; i >= 0; i--) { if (x & b[i]) @@ -81,14 +106,21 @@ SDL_MostSignificantBitIndex32(Uint32 x) #endif } +SDL_FORCE_INLINE SDL_bool +SDL_HasExactlyOneBitSet32(Uint32 x) +{ + if (x && !(x & (x - 1))) { + return SDL_TRUE; + } + return SDL_FALSE; +} + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_bits_h */ +#endif /* SDL_bits_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_blendmode.h b/external/SDL2/SDL_blendmode.h index 64a3530..b6d140d 100644 --- a/external/SDL2/SDL_blendmode.h +++ b/external/SDL2/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,19 +21,17 @@ /** * \file SDL_blendmode.h - * + * * Header file declaring the SDL_BlendMode enumeration */ -#ifndef _SDL_blendmode_h -#define _SDL_blendmode_h +#ifndef SDL_blendmode_h_ +#define SDL_blendmode_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** @@ -41,20 +39,162 @@ extern "C" { */ typedef enum { - SDL_BLENDMODE_NONE = 0x00000000, /**< No blending */ - SDL_BLENDMODE_BLEND = 0x00000001, /**< dst = (src * A) + (dst * (1-A)) */ - SDL_BLENDMODE_ADD = 0x00000002, /**< dst = (src * A) + dst */ - SDL_BLENDMODE_MOD = 0x00000004 /**< dst = src * dst */ + SDL_BLENDMODE_NONE = 0x00000000, /**< no blending + dstRGBA = srcRGBA */ + SDL_BLENDMODE_BLEND = 0x00000001, /**< alpha blending + dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA)) + dstA = srcA + (dstA * (1-srcA)) */ + SDL_BLENDMODE_ADD = 0x00000002, /**< additive blending + dstRGB = (srcRGB * srcA) + dstRGB + dstA = dstA */ + SDL_BLENDMODE_MOD = 0x00000004, /**< color modulate + dstRGB = srcRGB * dstRGB + dstA = dstA */ + SDL_BLENDMODE_MUL = 0x00000008, /**< color multiply + dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA)) + dstA = (srcA * dstA) + (dstA * (1-srcA)) */ + SDL_BLENDMODE_INVALID = 0x7FFFFFFF + + /* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */ + } SDL_BlendMode; +/** + * \brief The blend operation used when combining source and destination pixel components + */ +typedef enum +{ + SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */ + SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D11 */ + SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D11 */ + +} SDL_BlendOperation; + +/** + * \brief The normalized factor used to multiply pixel components + */ +typedef enum +{ + SDL_BLENDFACTOR_ZERO = 0x1, /**< 0, 0, 0, 0 */ + SDL_BLENDFACTOR_ONE = 0x2, /**< 1, 1, 1, 1 */ + SDL_BLENDFACTOR_SRC_COLOR = 0x3, /**< srcR, srcG, srcB, srcA */ + SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4, /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */ + SDL_BLENDFACTOR_SRC_ALPHA = 0x5, /**< srcA, srcA, srcA, srcA */ + SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6, /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */ + SDL_BLENDFACTOR_DST_COLOR = 0x7, /**< dstR, dstG, dstB, dstA */ + SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */ + SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */ + SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */ + +} SDL_BlendFactor; + +/** + * Compose a custom blend mode for renderers. + * + * The functions SDL_SetRenderDrawBlendMode and SDL_SetTextureBlendMode accept + * the SDL_BlendMode returned by this function if the renderer supports it. + * + * A blend mode controls how the pixels from a drawing operation (source) get + * combined with the pixels from the render target (destination). First, the + * components of the source and destination pixels get multiplied with their + * blend factors. Then, the blend operation takes the two products and + * calculates the result that will get stored in the render target. + * + * Expressed in pseudocode, it would look like this: + * + * ```c + * dstRGB = colorOperation(srcRGB * srcColorFactor, dstRGB * dstColorFactor); + * dstA = alphaOperation(srcA * srcAlphaFactor, dstA * dstAlphaFactor); + * ``` + * + * Where the functions `colorOperation(src, dst)` and `alphaOperation(src, + * dst)` can return one of the following: + * + * - `src + dst` + * - `src - dst` + * - `dst - src` + * - `min(src, dst)` + * - `max(src, dst)` + * + * The red, green, and blue components are always multiplied with the first, + * second, and third components of the SDL_BlendFactor, respectively. The + * fourth component is not used. + * + * The alpha component is always multiplied with the fourth component of the + * SDL_BlendFactor. The other components are not used in the alpha + * calculation. + * + * Support for these blend modes varies for each renderer. To check if a + * specific SDL_BlendMode is supported, create a renderer and pass it to + * either SDL_SetRenderDrawBlendMode or SDL_SetTextureBlendMode. They will + * return with an error if the blend mode is not supported. + * + * This list describes the support of custom blend modes for each renderer in + * SDL 2.0.6. All renderers support the four blend modes listed in the + * SDL_BlendMode enumeration. + * + * - **direct3d**: Supports `SDL_BLENDOPERATION_ADD` with all factors. + * - **direct3d11**: Supports all operations with all factors. However, some + * factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and + * `SDL_BLENDOPERATION_MAXIMUM`. + * - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all + * factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL + * 2.0.6. + * - **opengles**: Supports the `SDL_BLENDOPERATION_ADD` operation with all + * factors. Color and alpha factors need to be the same. OpenGL ES 1 + * implementation specific: May also support `SDL_BLENDOPERATION_SUBTRACT` + * and `SDL_BLENDOPERATION_REV_SUBTRACT`. May support color and alpha + * operations being different from each other. May support color and alpha + * factors being different from each other. + * - **opengles2**: Supports the `SDL_BLENDOPERATION_ADD`, + * `SDL_BLENDOPERATION_SUBTRACT`, `SDL_BLENDOPERATION_REV_SUBTRACT` + * operations with all factors. + * - **psp**: No custom blend mode support. + * - **software**: No custom blend mode support. + * + * Some renderers do not provide an alpha component for the default render + * target. The `SDL_BLENDFACTOR_DST_ALPHA` and + * `SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA` factors do not have an effect in this + * case. + * + * \param srcColorFactor the SDL_BlendFactor applied to the red, green, and + * blue components of the source pixels + * \param dstColorFactor the SDL_BlendFactor applied to the red, green, and + * blue components of the destination pixels + * \param colorOperation the SDL_BlendOperation used to combine the red, + * green, and blue components of the source and + * destination pixels + * \param srcAlphaFactor the SDL_BlendFactor applied to the alpha component of + * the source pixels + * \param dstAlphaFactor the SDL_BlendFactor applied to the alpha component of + * the destination pixels + * \param alphaOperation the SDL_BlendOperation used to combine the alpha + * component of the source and destination pixels + * \returns an SDL_BlendMode that represents the chosen factors and + * operations. + * + * \since This function is available since SDL 2.0.6. + * + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_GetRenderDrawBlendMode + * \sa SDL_SetTextureBlendMode + * \sa SDL_GetTextureBlendMode + */ +extern DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, + SDL_BlendFactor dstColorFactor, + SDL_BlendOperation colorOperation, + SDL_BlendFactor srcAlphaFactor, + SDL_BlendFactor dstAlphaFactor, + SDL_BlendOperation alphaOperation); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_video_h */ +#endif /* SDL_blendmode_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_clipboard.h b/external/SDL2/SDL_clipboard.h index 9d86b6b..9351363 100644 --- a/external/SDL2/SDL_clipboard.h +++ b/external/SDL2/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -25,51 +25,70 @@ * Include file for SDL clipboard handling */ -#ifndef _SDL_clipboard_h -#define _SDL_clipboard_h +#ifndef SDL_clipboard_h_ +#define SDL_clipboard_h_ #include "SDL_stdinc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* Function prototypes */ /** - * \brief Put UTF-8 text into the clipboard + * Put UTF-8 text into the clipboard. * - * \sa SDL_GetClipboardText() + * \param text the text to store in the clipboard + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetClipboardText + * \sa SDL_HasClipboardText */ extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text); /** - * \brief Get UTF-8 text from the clipboard, which must be freed with SDL_free() + * Get UTF-8 text from the clipboard, which must be freed with SDL_free(). * - * \sa SDL_SetClipboardText() + * This functions returns empty string if there was not enough memory left for + * a copy of the clipboard's content. + * + * \returns the clipboard text on success or an empty string on failure; call + * SDL_GetError() for more information. Caller must call SDL_free() + * on the returned pointer when done with it (even if there was an + * error). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HasClipboardText + * \sa SDL_SetClipboardText */ extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void); /** - * \brief Returns a flag indicating whether the clipboard exists and contains a text string that is non-empty + * Query whether the clipboard exists and contains a non-empty text string. * - * \sa SDL_GetClipboardText() + * \returns SDL_TRUE if the clipboard has text, or SDL_FALSE if it does not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetClipboardText + * \sa SDL_SetClipboardText */ extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_clipboard_h */ +#endif /* SDL_clipboard_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_config.h.cmake b/external/SDL2/SDL_config.h.cmake new file mode 100644 index 0000000..c57266c --- /dev/null +++ b/external/SDL2/SDL_config.h.cmake @@ -0,0 +1,445 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_h_ +#define SDL_config_h_ + +/** + * \file SDL_config.h.in + * + * This is a set of defines to configure the SDL features + */ + +/* General platform specific identifiers */ +#include "SDL_platform.h" + +/* C language features */ +#cmakedefine const @HAVE_CONST@ +#cmakedefine inline @HAVE_INLINE@ +#cmakedefine volatile @HAVE_VOLATILE@ + +/* C datatypes */ +/* Define SIZEOF_VOIDP for 64/32 architectures */ +#ifdef __LP64__ +#define SIZEOF_VOIDP 8 +#else +#define SIZEOF_VOIDP 4 +#endif + +#cmakedefine HAVE_GCC_ATOMICS @HAVE_GCC_ATOMICS@ +#cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET @HAVE_GCC_SYNC_LOCK_TEST_AND_SET@ + +#cmakedefine HAVE_D3D_H @HAVE_D3D_H@ +#cmakedefine HAVE_D3D11_H @HAVE_D3D11_H@ +#cmakedefine HAVE_DDRAW_H @HAVE_DDRAW_H@ +#cmakedefine HAVE_DSOUND_H @HAVE_DSOUND_H@ +#cmakedefine HAVE_DINPUT_H @HAVE_DINPUT_H@ +#cmakedefine HAVE_XAUDIO2_H @HAVE_XAUDIO2_H@ +#cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@ +#cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@ +#cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@ +#cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@ + +/* Comment this if you want to build without any C library requirements */ +#cmakedefine HAVE_LIBC 1 +#if HAVE_LIBC + +/* Useful headers */ +#cmakedefine HAVE_ALLOCA_H 1 +#cmakedefine HAVE_SYS_TYPES_H 1 +#cmakedefine HAVE_STDIO_H 1 +#cmakedefine STDC_HEADERS 1 +#cmakedefine HAVE_STDLIB_H 1 +#cmakedefine HAVE_STDARG_H 1 +#cmakedefine HAVE_MALLOC_H 1 +#cmakedefine HAVE_MEMORY_H 1 +#cmakedefine HAVE_STRING_H 1 +#cmakedefine HAVE_STRINGS_H 1 +#cmakedefine HAVE_WCHAR_H 1 +#cmakedefine HAVE_INTTYPES_H 1 +#cmakedefine HAVE_STDINT_H 1 +#cmakedefine HAVE_CTYPE_H 1 +#cmakedefine HAVE_MATH_H 1 +#cmakedefine HAVE_ICONV_H 1 +#cmakedefine HAVE_SIGNAL_H 1 +#cmakedefine HAVE_ALTIVEC_H 1 +#cmakedefine HAVE_PTHREAD_NP_H 1 +#cmakedefine HAVE_LIBUDEV_H 1 +#cmakedefine HAVE_DBUS_DBUS_H 1 +#cmakedefine HAVE_IBUS_IBUS_H 1 +#cmakedefine HAVE_FCITX_FRONTEND_H 1 +#cmakedefine HAVE_LIBSAMPLERATE_H 1 + +/* C library functions */ +#cmakedefine HAVE_MALLOC 1 +#cmakedefine HAVE_CALLOC 1 +#cmakedefine HAVE_REALLOC 1 +#cmakedefine HAVE_FREE 1 +#cmakedefine HAVE_ALLOCA 1 +#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */ +#cmakedefine HAVE_GETENV 1 +#cmakedefine HAVE_SETENV 1 +#cmakedefine HAVE_PUTENV 1 +#cmakedefine HAVE_UNSETENV 1 +#endif +#cmakedefine HAVE_QSORT 1 +#cmakedefine HAVE_ABS 1 +#cmakedefine HAVE_BCOPY 1 +#cmakedefine HAVE_MEMSET 1 +#cmakedefine HAVE_MEMCPY 1 +#cmakedefine HAVE_MEMMOVE 1 +#cmakedefine HAVE_MEMCMP 1 +#cmakedefine HAVE_WCSLEN 1 +#cmakedefine HAVE_WCSLCPY 1 +#cmakedefine HAVE_WCSLCAT 1 +#cmakedefine HAVE_WCSCMP 1 +#cmakedefine HAVE_STRLEN 1 +#cmakedefine HAVE_STRLCPY 1 +#cmakedefine HAVE_STRLCAT 1 +#cmakedefine HAVE_STRDUP 1 +#cmakedefine HAVE__STRREV 1 +#cmakedefine HAVE__STRUPR 1 +#cmakedefine HAVE__STRLWR 1 +#cmakedefine HAVE_INDEX 1 +#cmakedefine HAVE_RINDEX 1 +#cmakedefine HAVE_STRCHR 1 +#cmakedefine HAVE_STRRCHR 1 +#cmakedefine HAVE_STRSTR 1 +#cmakedefine HAVE_ITOA 1 +#cmakedefine HAVE__LTOA 1 +#cmakedefine HAVE__UITOA 1 +#cmakedefine HAVE__ULTOA 1 +#cmakedefine HAVE_STRTOL 1 +#cmakedefine HAVE_STRTOUL 1 +#cmakedefine HAVE__I64TOA 1 +#cmakedefine HAVE__UI64TOA 1 +#cmakedefine HAVE_STRTOLL 1 +#cmakedefine HAVE_STRTOULL 1 +#cmakedefine HAVE_STRTOD 1 +#cmakedefine HAVE_ATOI 1 +#cmakedefine HAVE_ATOF 1 +#cmakedefine HAVE_STRCMP 1 +#cmakedefine HAVE_STRNCMP 1 +#cmakedefine HAVE__STRICMP 1 +#cmakedefine HAVE_STRCASECMP 1 +#cmakedefine HAVE__STRNICMP 1 +#cmakedefine HAVE_STRNCASECMP 1 +#cmakedefine HAVE_VSSCANF 1 +#cmakedefine HAVE_VSNPRINTF 1 +#cmakedefine HAVE_M_PI 1 +#cmakedefine HAVE_ATAN 1 +#cmakedefine HAVE_ATAN2 1 +#cmakedefine HAVE_ACOS 1 +#cmakedefine HAVE_ASIN 1 +#cmakedefine HAVE_CEIL 1 +#cmakedefine HAVE_COPYSIGN 1 +#cmakedefine HAVE_COS 1 +#cmakedefine HAVE_COSF 1 +#cmakedefine HAVE_FABS 1 +#cmakedefine HAVE_FLOOR 1 +#cmakedefine HAVE_LOG 1 +#cmakedefine HAVE_POW 1 +#cmakedefine HAVE_SCALBN 1 +#cmakedefine HAVE_SIN 1 +#cmakedefine HAVE_SINF 1 +#cmakedefine HAVE_SQRT 1 +#cmakedefine HAVE_SQRTF 1 +#cmakedefine HAVE_TAN 1 +#cmakedefine HAVE_TANF 1 +#cmakedefine HAVE_FOPEN64 1 +#cmakedefine HAVE_FSEEKO 1 +#cmakedefine HAVE_FSEEKO64 1 +#cmakedefine HAVE_SIGACTION 1 +#cmakedefine HAVE_SA_SIGACTION 1 +#cmakedefine HAVE_SETJMP 1 +#cmakedefine HAVE_NANOSLEEP 1 +#cmakedefine HAVE_SYSCONF 1 +#cmakedefine HAVE_SYSCTLBYNAME 1 +#cmakedefine HAVE_CLOCK_GETTIME 1 +#cmakedefine HAVE_GETPAGESIZE 1 +#cmakedefine HAVE_MPROTECT 1 +#cmakedefine HAVE_ICONV 1 +#cmakedefine HAVE_PTHREAD_SETNAME_NP 1 +#cmakedefine HAVE_PTHREAD_SET_NAME_NP 1 +#cmakedefine HAVE_SEM_TIMEDWAIT 1 +#cmakedefine HAVE_GETAUXVAL 1 +#cmakedefine HAVE_POLL 1 + +#elif __WIN32__ +#cmakedefine HAVE_STDARG_H 1 +#cmakedefine HAVE_STDDEF_H 1 +#else +/* We may need some replacement for stdarg.h here */ +#include +#endif /* HAVE_LIBC */ + +/* SDL internal assertion support */ +#cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@ + +/* Allow disabling of core subsystems */ +#cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@ +#cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@ +#cmakedefine SDL_CPUINFO_DISABLED @SDL_CPUINFO_DISABLED@ +#cmakedefine SDL_EVENTS_DISABLED @SDL_EVENTS_DISABLED@ +#cmakedefine SDL_FILE_DISABLED @SDL_FILE_DISABLED@ +#cmakedefine SDL_JOYSTICK_DISABLED @SDL_JOYSTICK_DISABLED@ +#cmakedefine SDL_HAPTIC_DISABLED @SDL_HAPTIC_DISABLED@ +#cmakedefine SDL_LOADSO_DISABLED @SDL_LOADSO_DISABLED@ +#cmakedefine SDL_RENDER_DISABLED @SDL_RENDER_DISABLED@ +#cmakedefine SDL_THREADS_DISABLED @SDL_THREADS_DISABLED@ +#cmakedefine SDL_TIMERS_DISABLED @SDL_TIMERS_DISABLED@ +#cmakedefine SDL_VIDEO_DISABLED @SDL_VIDEO_DISABLED@ +#cmakedefine SDL_POWER_DISABLED @SDL_POWER_DISABLED@ +#cmakedefine SDL_FILESYSTEM_DISABLED @SDL_FILESYSTEM_DISABLED@ + +/* Enable various audio drivers */ +#cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@ +#cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@ +#cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@ +#cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@ +#cmakedefine SDL_AUDIO_DRIVER_DISK @SDL_AUDIO_DRIVER_DISK@ +#cmakedefine SDL_AUDIO_DRIVER_DSOUND @SDL_AUDIO_DRIVER_DSOUND@ +#cmakedefine SDL_AUDIO_DRIVER_DUMMY @SDL_AUDIO_DRIVER_DUMMY@ +#cmakedefine SDL_AUDIO_DRIVER_EMSCRIPTEN @SDL_AUDIO_DRIVER_EMSCRIPTEN@ +#cmakedefine SDL_AUDIO_DRIVER_ESD @SDL_AUDIO_DRIVER_ESD@ +#cmakedefine SDL_AUDIO_DRIVER_ESD_DYNAMIC @SDL_AUDIO_DRIVER_ESD_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@ +#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_HAIKU @SDL_AUDIO_DRIVER_HAIKU@ +#cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@ +#cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@ +#cmakedefine SDL_AUDIO_DRIVER_NAS_DYNAMIC @SDL_AUDIO_DRIVER_NAS_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_NETBSD @SDL_AUDIO_DRIVER_NETBSD@ +#cmakedefine SDL_AUDIO_DRIVER_OSS @SDL_AUDIO_DRIVER_OSS@ +#cmakedefine SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H @SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H@ +#cmakedefine SDL_AUDIO_DRIVER_PAUDIO @SDL_AUDIO_DRIVER_PAUDIO@ +#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@ +#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_QSA @SDL_AUDIO_DRIVER_QSA@ +#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@ +#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_SUNAUDIO @SDL_AUDIO_DRIVER_SUNAUDIO@ +#cmakedefine SDL_AUDIO_DRIVER_WASAPI @SDL_AUDIO_DRIVER_WASAPI@ +#cmakedefine SDL_AUDIO_DRIVER_WINMM @SDL_AUDIO_DRIVER_WINMM@ +#cmakedefine SDL_AUDIO_DRIVER_XAUDIO2 @SDL_AUDIO_DRIVER_XAUDIO2@ + +/* Enable various input drivers */ +#cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@ +#cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@ +#cmakedefine SDL_INPUT_TSLIB @SDL_INPUT_TSLIB@ +#cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@ +#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@ +#cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@ +#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@ +#cmakedefine SDL_JOYSTICK_DUMMY @SDL_JOYSTICK_DUMMY@ +#cmakedefine SDL_JOYSTICK_IOKIT @SDL_JOYSTICK_IOKIT@ +#cmakedefine SDL_JOYSTICK_MFI @SDL_JOYSTICK_MFI@ +#cmakedefine SDL_JOYSTICK_LINUX @SDL_JOYSTICK_LINUX@ +#cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@ +#cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@ +#cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@ +#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@ +#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@ +#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@ +#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@ +#cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@ +#cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@ +#cmakedefine SDL_HAPTIC_ANDROID @SDL_HAPTIC_ANDROID@ + +/* Enable various shared object loading systems */ +#cmakedefine SDL_LOADSO_DLOPEN @SDL_LOADSO_DLOPEN@ +#cmakedefine SDL_LOADSO_DUMMY @SDL_LOADSO_DUMMY@ +#cmakedefine SDL_LOADSO_LDG @SDL_LOADSO_LDG@ +#cmakedefine SDL_LOADSO_WINDOWS @SDL_LOADSO_WINDOWS@ + +/* Enable various threading systems */ +#cmakedefine SDL_THREAD_PTHREAD @SDL_THREAD_PTHREAD@ +#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX@ +#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP@ +#cmakedefine SDL_THREAD_WINDOWS @SDL_THREAD_WINDOWS@ + +/* Enable various timer systems */ +#cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@ +#cmakedefine SDL_TIMER_DUMMY @SDL_TIMER_DUMMY@ +#cmakedefine SDL_TIMER_UNIX @SDL_TIMER_UNIX@ +#cmakedefine SDL_TIMER_WINDOWS @SDL_TIMER_WINDOWS@ +#cmakedefine SDL_TIMER_WINCE @SDL_TIMER_WINCE@ + +/* Enable various video drivers */ +#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@ +#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@ +#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@ +#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@ +#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@ +#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@ +#cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@ +#cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@ +#cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@ + +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@ +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM@ + +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@ + +#cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@ +#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON@ +#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@ +#cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@ +#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE @SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XINERAMA @SDL_VIDEO_DRIVER_X11_XINERAMA@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 @SDL_VIDEO_DRIVER_X11_XINPUT2@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR @SDL_VIDEO_DRIVER_X11_XRANDR@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER @SDL_VIDEO_DRIVER_X11_XSCRNSAVER@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@ +#cmakedefine SDL_VIDEO_DRIVER_X11_XVIDMODE @SDL_VIDEO_DRIVER_X11_XVIDMODE@ +#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@ +#cmakedefine SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY @SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY@ +#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@ + +#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@ +#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@ +#cmakedefine SDL_VIDEO_RENDER_OGL @SDL_VIDEO_RENDER_OGL@ +#cmakedefine SDL_VIDEO_RENDER_OGL_ES @SDL_VIDEO_RENDER_OGL_ES@ +#cmakedefine SDL_VIDEO_RENDER_OGL_ES2 @SDL_VIDEO_RENDER_OGL_ES2@ +#cmakedefine SDL_VIDEO_RENDER_DIRECTFB @SDL_VIDEO_RENDER_DIRECTFB@ + +/* Enable OpenGL support */ +#cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@ +#cmakedefine SDL_VIDEO_OPENGL_ES @SDL_VIDEO_OPENGL_ES@ +#cmakedefine SDL_VIDEO_OPENGL_ES2 @SDL_VIDEO_OPENGL_ES2@ +#cmakedefine SDL_VIDEO_OPENGL_BGL @SDL_VIDEO_OPENGL_BGL@ +#cmakedefine SDL_VIDEO_OPENGL_CGL @SDL_VIDEO_OPENGL_CGL@ +#cmakedefine SDL_VIDEO_OPENGL_GLX @SDL_VIDEO_OPENGL_GLX@ +#cmakedefine SDL_VIDEO_OPENGL_WGL @SDL_VIDEO_OPENGL_WGL@ +#cmakedefine SDL_VIDEO_OPENGL_EGL @SDL_VIDEO_OPENGL_EGL@ +#cmakedefine SDL_VIDEO_OPENGL_OSMESA @SDL_VIDEO_OPENGL_OSMESA@ +#cmakedefine SDL_VIDEO_OPENGL_OSMESA_DYNAMIC @SDL_VIDEO_OPENGL_OSMESA_DYNAMIC@ + +/* Enable Vulkan support */ +#cmakedefine SDL_VIDEO_VULKAN @SDL_VIDEO_VULKAN@ + +/* Enable system power support */ +#cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@ +#cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@ +#cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@ +#cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@ +#cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@ +#cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@ +#cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@ + +/* Enable system filesystem support */ +#cmakedefine SDL_FILESYSTEM_ANDROID @SDL_FILESYSTEM_ANDROID@ +#cmakedefine SDL_FILESYSTEM_HAIKU @SDL_FILESYSTEM_HAIKU@ +#cmakedefine SDL_FILESYSTEM_COCOA @SDL_FILESYSTEM_COCOA@ +#cmakedefine SDL_FILESYSTEM_DUMMY @SDL_FILESYSTEM_DUMMY@ +#cmakedefine SDL_FILESYSTEM_UNIX @SDL_FILESYSTEM_UNIX@ +#cmakedefine SDL_FILESYSTEM_WINDOWS @SDL_FILESYSTEM_WINDOWS@ +#cmakedefine SDL_FILESYSTEM_EMSCRIPTEN @SDL_FILESYSTEM_EMSCRIPTEN@ + +/* Enable assembly routines */ +#cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@ +#cmakedefine SDL_ALTIVEC_BLITTERS @SDL_ALTIVEC_BLITTERS@ + +/* Enable dynamic libsamplerate support */ +#cmakedefine SDL_LIBSAMPLERATE_DYNAMIC @SDL_LIBSAMPLERATE_DYNAMIC@ + +/* Platform specific definitions */ +#if !defined(__WIN32__) +# if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H) +typedef unsigned int size_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +typedef unsigned long uintptr_t; +# endif /* if (stdint.h isn't available) */ +#else /* __WIN32__ */ +# if !defined(_STDINT_H_) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H) +# if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__) +#define HAVE_STDINT_H 1 +# elif defined(_MSC_VER) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +# ifndef _UINTPTR_T_DEFINED +# ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +# else +typedef unsigned int uintptr_t; +# endif +#define _UINTPTR_T_DEFINED +# endif +/* Older Visual C++ headers don't have the Win64-compatible typedefs... */ +# if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR))) +#define DWORD_PTR DWORD +# endif +# if ((_MSC_VER <= 1200) && (!defined(LONG_PTR))) +#define LONG_PTR LONG +# endif +# else /* !__GNUC__ && !_MSC_VER */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +# ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef unsigned int size_t; +# endif +typedef unsigned int uintptr_t; +# endif /* __GNUC__ || _MSC_VER */ +# endif /* !_STDINT_H_ && !HAVE_STDINT_H */ +#endif /* __WIN32__ */ + +#endif /* SDL_config_h_ */ diff --git a/external/SDL2/SDL_config.h.in b/external/SDL2/SDL_config.h.in new file mode 100644 index 0000000..8b3d208 --- /dev/null +++ b/external/SDL2/SDL_config.h.in @@ -0,0 +1,389 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_h_ +#define SDL_config_h_ + +/** + * \file SDL_config.h.in + * + * This is a set of defines to configure the SDL features + */ + +/* General platform specific identifiers */ +#include "SDL_platform.h" + +/* Make sure that this isn't included by Visual C++ */ +#ifdef _MSC_VER +#error You should run hg revert SDL_config.h +#endif + +/* C language features */ +#undef const +#undef inline +#undef volatile + +/* C datatypes */ +#ifdef __LP64__ +#define SIZEOF_VOIDP 8 +#else +#define SIZEOF_VOIDP 4 +#endif +#undef HAVE_GCC_ATOMICS +#undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET + +#undef HAVE_DDRAW_H +#undef HAVE_DINPUT_H +#undef HAVE_DSOUND_H +#undef HAVE_DXGI_H +#undef HAVE_XINPUT_H +#undef HAVE_XINPUT_GAMEPAD_EX +#undef HAVE_XINPUT_STATE_EX + +/* Comment this if you want to build without any C library requirements */ +#undef HAVE_LIBC +#if HAVE_LIBC + +/* Useful headers */ +#undef HAVE_ALLOCA_H +#undef HAVE_SYS_TYPES_H +#undef HAVE_STDIO_H +#undef STDC_HEADERS +#undef HAVE_STDLIB_H +#undef HAVE_STDARG_H +#undef HAVE_MALLOC_H +#undef HAVE_MEMORY_H +#undef HAVE_STRING_H +#undef HAVE_STRINGS_H +#undef HAVE_WCHAR_H +#undef HAVE_INTTYPES_H +#undef HAVE_STDINT_H +#undef HAVE_CTYPE_H +#undef HAVE_MATH_H +#undef HAVE_ICONV_H +#undef HAVE_SIGNAL_H +#undef HAVE_ALTIVEC_H +#undef HAVE_PTHREAD_NP_H +#undef HAVE_LIBUDEV_H +#undef HAVE_DBUS_DBUS_H +#undef HAVE_IBUS_IBUS_H +#undef HAVE_FCITX_FRONTEND_H +#undef HAVE_LIBSAMPLERATE_H + +/* C library functions */ +#undef HAVE_MALLOC +#undef HAVE_CALLOC +#undef HAVE_REALLOC +#undef HAVE_FREE +#undef HAVE_ALLOCA +#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */ +#undef HAVE_GETENV +#undef HAVE_SETENV +#undef HAVE_PUTENV +#undef HAVE_UNSETENV +#endif +#undef HAVE_QSORT +#undef HAVE_ABS +#undef HAVE_BCOPY +#undef HAVE_MEMSET +#undef HAVE_MEMCPY +#undef HAVE_MEMMOVE +#undef HAVE_MEMCMP +#undef HAVE_WCSLEN +#undef HAVE_WCSLCPY +#undef HAVE_WCSLCAT +#undef HAVE_WCSCMP +#undef HAVE_STRLEN +#undef HAVE_STRLCPY +#undef HAVE_STRLCAT +#undef HAVE_STRDUP +#undef HAVE__STRREV +#undef HAVE__STRUPR +#undef HAVE__STRLWR +#undef HAVE_INDEX +#undef HAVE_RINDEX +#undef HAVE_STRCHR +#undef HAVE_STRRCHR +#undef HAVE_STRSTR +#undef HAVE_ITOA +#undef HAVE__LTOA +#undef HAVE__UITOA +#undef HAVE__ULTOA +#undef HAVE_STRTOL +#undef HAVE_STRTOUL +#undef HAVE__I64TOA +#undef HAVE__UI64TOA +#undef HAVE_STRTOLL +#undef HAVE_STRTOULL +#undef HAVE_STRTOD +#undef HAVE_ATOI +#undef HAVE_ATOF +#undef HAVE_STRCMP +#undef HAVE_STRNCMP +#undef HAVE__STRICMP +#undef HAVE_STRCASECMP +#undef HAVE__STRNICMP +#undef HAVE_STRNCASECMP +#undef HAVE_SSCANF +#undef HAVE_VSSCANF +#undef HAVE_SNPRINTF +#undef HAVE_VSNPRINTF +#undef HAVE_M_PI +#undef HAVE_ATAN +#undef HAVE_ATAN2 +#undef HAVE_ACOS +#undef HAVE_ASIN +#undef HAVE_CEIL +#undef HAVE_COPYSIGN +#undef HAVE_COS +#undef HAVE_COSF +#undef HAVE_FABS +#undef HAVE_FLOOR +#undef HAVE_LOG +#undef HAVE_POW +#undef HAVE_SCALBN +#undef HAVE_SIN +#undef HAVE_SINF +#undef HAVE_SQRT +#undef HAVE_SQRTF +#undef HAVE_TAN +#undef HAVE_TANF +#undef HAVE_FOPEN64 +#undef HAVE_FSEEKO +#undef HAVE_FSEEKO64 +#undef HAVE_SIGACTION +#undef HAVE_SA_SIGACTION +#undef HAVE_SETJMP +#undef HAVE_NANOSLEEP +#undef HAVE_SYSCONF +#undef HAVE_SYSCTLBYNAME +#undef HAVE_CLOCK_GETTIME +#undef HAVE_GETPAGESIZE +#undef HAVE_MPROTECT +#undef HAVE_ICONV +#undef HAVE_PTHREAD_SETNAME_NP +#undef HAVE_PTHREAD_SET_NAME_NP +#undef HAVE_SEM_TIMEDWAIT +#undef HAVE_GETAUXVAL +#undef HAVE_POLL + +#else +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_STDINT_H 1 +#endif /* HAVE_LIBC */ + +/* SDL internal assertion support */ +#undef SDL_DEFAULT_ASSERT_LEVEL + +/* Allow disabling of core subsystems */ +#undef SDL_ATOMIC_DISABLED +#undef SDL_AUDIO_DISABLED +#undef SDL_CPUINFO_DISABLED +#undef SDL_EVENTS_DISABLED +#undef SDL_FILE_DISABLED +#undef SDL_JOYSTICK_DISABLED +#undef SDL_HAPTIC_DISABLED +#undef SDL_LOADSO_DISABLED +#undef SDL_RENDER_DISABLED +#undef SDL_THREADS_DISABLED +#undef SDL_TIMERS_DISABLED +#undef SDL_VIDEO_DISABLED +#undef SDL_POWER_DISABLED +#undef SDL_FILESYSTEM_DISABLED + +/* Enable various audio drivers */ +#undef SDL_AUDIO_DRIVER_ALSA +#undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC +#undef SDL_AUDIO_DRIVER_ANDROID +#undef SDL_AUDIO_DRIVER_ARTS +#undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC +#undef SDL_AUDIO_DRIVER_COREAUDIO +#undef SDL_AUDIO_DRIVER_DISK +#undef SDL_AUDIO_DRIVER_DSOUND +#undef SDL_AUDIO_DRIVER_DUMMY +#undef SDL_AUDIO_DRIVER_EMSCRIPTEN +#undef SDL_AUDIO_DRIVER_ESD +#undef SDL_AUDIO_DRIVER_ESD_DYNAMIC +#undef SDL_AUDIO_DRIVER_FUSIONSOUND +#undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC +#undef SDL_AUDIO_DRIVER_HAIKU +#undef SDL_AUDIO_DRIVER_JACK +#undef SDL_AUDIO_DRIVER_JACK_DYNAMIC +#undef SDL_AUDIO_DRIVER_NACL +#undef SDL_AUDIO_DRIVER_NAS +#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC +#undef SDL_AUDIO_DRIVER_NETBSD +#undef SDL_AUDIO_DRIVER_OSS +#undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H +#undef SDL_AUDIO_DRIVER_PAUDIO +#undef SDL_AUDIO_DRIVER_PULSEAUDIO +#undef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC +#undef SDL_AUDIO_DRIVER_QSA +#undef SDL_AUDIO_DRIVER_SNDIO +#undef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC +#undef SDL_AUDIO_DRIVER_SUNAUDIO +#undef SDL_AUDIO_DRIVER_WASAPI +#undef SDL_AUDIO_DRIVER_WINMM +#undef SDL_AUDIO_DRIVER_XAUDIO2 + +/* Enable various input drivers */ +#undef SDL_INPUT_LINUXEV +#undef SDL_INPUT_LINUXKD +#undef SDL_INPUT_TSLIB +#undef SDL_JOYSTICK_HAIKU +#undef SDL_JOYSTICK_DINPUT +#undef SDL_JOYSTICK_XINPUT +#undef SDL_JOYSTICK_DUMMY +#undef SDL_JOYSTICK_IOKIT +#undef SDL_JOYSTICK_LINUX +#undef SDL_JOYSTICK_ANDROID +#undef SDL_JOYSTICK_WINMM +#undef SDL_JOYSTICK_USBHID +#undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H +#undef SDL_JOYSTICK_EMSCRIPTEN +#undef SDL_HAPTIC_DUMMY +#undef SDL_HAPTIC_LINUX +#undef SDL_HAPTIC_IOKIT +#undef SDL_HAPTIC_DINPUT +#undef SDL_HAPTIC_XINPUT + +/* Enable various shared object loading systems */ +#undef SDL_LOADSO_DLOPEN +#undef SDL_LOADSO_DUMMY +#undef SDL_LOADSO_LDG +#undef SDL_LOADSO_WINDOWS + +/* Enable various threading systems */ +#undef SDL_THREAD_PTHREAD +#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX +#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP +#undef SDL_THREAD_WINDOWS + +/* Enable various timer systems */ +#undef SDL_TIMER_HAIKU +#undef SDL_TIMER_DUMMY +#undef SDL_TIMER_UNIX +#undef SDL_TIMER_WINDOWS + +/* Enable various video drivers */ +#undef SDL_VIDEO_DRIVER_HAIKU +#undef SDL_VIDEO_DRIVER_COCOA +#undef SDL_VIDEO_DRIVER_DIRECTFB +#undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC +#undef SDL_VIDEO_DRIVER_DUMMY +#undef SDL_VIDEO_DRIVER_WINDOWS +#undef SDL_VIDEO_DRIVER_WAYLAND +#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH +#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC +#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL +#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR +#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON +#undef SDL_VIDEO_DRIVER_MIR +#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC +#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON +#undef SDL_VIDEO_DRIVER_X11 +#undef SDL_VIDEO_DRIVER_RPI +#undef SDL_VIDEO_DRIVER_KMSDRM +#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC +#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM +#undef SDL_VIDEO_DRIVER_ANDROID +#undef SDL_VIDEO_DRIVER_EMSCRIPTEN +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS +#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE +#undef SDL_VIDEO_DRIVER_X11_XCURSOR +#undef SDL_VIDEO_DRIVER_X11_XDBE +#undef SDL_VIDEO_DRIVER_X11_XINERAMA +#undef SDL_VIDEO_DRIVER_X11_XINPUT2 +#undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH +#undef SDL_VIDEO_DRIVER_X11_XRANDR +#undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER +#undef SDL_VIDEO_DRIVER_X11_XSHAPE +#undef SDL_VIDEO_DRIVER_X11_XVIDMODE +#undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS +#undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY +#undef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM +#undef SDL_VIDEO_DRIVER_NACL +#undef SDL_VIDEO_DRIVER_VIVANTE +#undef SDL_VIDEO_DRIVER_VIVANTE_VDK +#undef SDL_VIDEO_DRIVER_QNX + +#undef SDL_VIDEO_RENDER_D3D +#undef SDL_VIDEO_RENDER_D3D11 +#undef SDL_VIDEO_RENDER_OGL +#undef SDL_VIDEO_RENDER_OGL_ES +#undef SDL_VIDEO_RENDER_OGL_ES2 +#undef SDL_VIDEO_RENDER_DIRECTFB + +/* Enable OpenGL support */ +#undef SDL_VIDEO_OPENGL +#undef SDL_VIDEO_OPENGL_ES +#undef SDL_VIDEO_OPENGL_ES2 +#undef SDL_VIDEO_OPENGL_BGL +#undef SDL_VIDEO_OPENGL_CGL +#undef SDL_VIDEO_OPENGL_EGL +#undef SDL_VIDEO_OPENGL_GLX +#undef SDL_VIDEO_OPENGL_WGL +#undef SDL_VIDEO_OPENGL_OSMESA +#undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC + +/* Enable Vulkan support */ +#undef SDL_VIDEO_VULKAN + +/* Enable system power support */ +#undef SDL_POWER_LINUX +#undef SDL_POWER_WINDOWS +#undef SDL_POWER_MACOSX +#undef SDL_POWER_HAIKU +#undef SDL_POWER_ANDROID +#undef SDL_POWER_EMSCRIPTEN +#undef SDL_POWER_HARDWIRED + +/* Enable system filesystem support */ +#undef SDL_FILESYSTEM_HAIKU +#undef SDL_FILESYSTEM_COCOA +#undef SDL_FILESYSTEM_DUMMY +#undef SDL_FILESYSTEM_UNIX +#undef SDL_FILESYSTEM_WINDOWS +#undef SDL_FILESYSTEM_NACL +#undef SDL_FILESYSTEM_ANDROID +#undef SDL_FILESYSTEM_EMSCRIPTEN + +/* Enable assembly routines */ +#undef SDL_ASSEMBLY_ROUTINES +#undef SDL_ALTIVEC_BLITTERS + +/* Enable ime support */ +#undef SDL_USE_IME + +/* Enable dynamic udev support */ +#undef SDL_UDEV_DYNAMIC + +/* Enable dynamic libsamplerate support */ +#undef SDL_LIBSAMPLERATE_DYNAMIC + +#endif /* SDL_config_h_ */ diff --git a/external/SDL2/SDL_config_android.h b/external/SDL2/SDL_config_android.h index 1676eb4..361bad8 100644 --- a/external/SDL2/SDL_config_android.h +++ b/external/SDL2/SDL_config_android.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,118 +19,139 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_android_h -#define _SDL_config_android_h +#ifndef SDL_config_android_h_ +#define SDL_config_android_h_ +#define SDL_config_h_ #include "SDL_platform.h" /** * \file SDL_config_android.h - * + * * This is a configuration that can be used to build SDL for Android */ #include -#define HAVE_ALLOCA_H 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_STDIO_H 1 -#define STDC_HEADERS 1 -#define HAVE_STRING_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_CTYPE_H 1 -#define HAVE_MATH_H 1 -#define HAVE_SIGNAL_H 1 +#define HAVE_GCC_ATOMICS 1 + +#define HAVE_ALLOCA_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_SIGNAL_H 1 /* C library functions */ -#define HAVE_MALLOC 1 -#define HAVE_CALLOC 1 -#define HAVE_REALLOC 1 -#define HAVE_FREE 1 -#define HAVE_ALLOCA 1 -#define HAVE_GETENV 1 -#define HAVE_SETENV 1 -#define HAVE_PUTENV 1 -#define HAVE_SETENV 1 -#define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_ABS 1 -#define HAVE_BCOPY 1 -#define HAVE_MEMSET 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMCMP 1 -#define HAVE_STRLEN 1 -#define HAVE_STRLCPY 1 -#define HAVE_STRLCAT 1 -#define HAVE_STRDUP 1 -#define HAVE_STRCHR 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRSTR 1 -#define HAVE_STRTOL 1 -#define HAVE_STRTOUL 1 -#define HAVE_STRTOLL 1 -#define HAVE_STRTOULL 1 -#define HAVE_STRTOD 1 -#define HAVE_ATOI 1 -#define HAVE_ATOF 1 -#define HAVE_STRCMP 1 -#define HAVE_STRNCMP 1 -#define HAVE_STRCASECMP 1 +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_SETENV 1 +#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 #define HAVE_STRNCASECMP 1 -#define HAVE_SSCANF 1 -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -#define HAVE_M_PI 1 -#define HAVE_ATAN 1 -#define HAVE_ATAN2 1 -#define HAVE_CEIL 1 -#define HAVE_COPYSIGN 1 -#define HAVE_COS 1 -#define HAVE_COSF 1 -#define HAVE_FABS 1 -#define HAVE_FLOOR 1 -#define HAVE_LOG 1 -#define HAVE_POW 1 -#define HAVE_SCALBN 1 -#define HAVE_SIN 1 -#define HAVE_SINF 1 -#define HAVE_SQRT 1 -#define HAVE_SIGACTION 1 -#define HAVE_SETJMP 1 -#define HAVE_NANOSLEEP 1 -#define HAVE_SYSCONF 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI 1 +#define HAVE_ATAN 1 +#define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 +#define HAVE_CEIL 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +#define HAVE_SCALBN 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SIGACTION 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +#define HAVE_SYSCONF 1 +#define HAVE_CLOCK_GETTIME 1 #define SIZEOF_VOIDP 4 /* Enable various audio drivers */ -#define SDL_AUDIO_DRIVER_ANDROID 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 +#define SDL_AUDIO_DRIVER_ANDROID 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable various input drivers */ -#define SDL_JOYSTICK_ANDROID 1 -#define SDL_HAPTIC_DUMMY 1 +#define SDL_JOYSTICK_ANDROID 1 +#define SDL_HAPTIC_ANDROID 1 /* Enable various shared object loading systems */ -#define SDL_LOADSO_DLOPEN 1 +#define SDL_LOADSO_DLOPEN 1 /* Enable various threading systems */ -#define SDL_THREAD_PTHREAD 1 -#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 +#define SDL_THREAD_PTHREAD 1 +#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 /* Enable various timer systems */ -#define SDL_TIMER_UNIX 1 +#define SDL_TIMER_UNIX 1 /* Enable various video drivers */ #define SDL_VIDEO_DRIVER_ANDROID 1 /* Enable OpenGL ES */ -#define SDL_VIDEO_OPENGL_ES 1 -#define SDL_VIDEO_RENDER_OGL_ES 1 -#define SDL_VIDEO_RENDER_OGL_ES2 1 +#define SDL_VIDEO_OPENGL_ES 1 +#define SDL_VIDEO_OPENGL_ES2 1 +#define SDL_VIDEO_OPENGL_EGL 1 +#define SDL_VIDEO_RENDER_OGL_ES 1 +#define SDL_VIDEO_RENDER_OGL_ES2 1 + +/* Enable Vulkan support */ +/* Android does not support Vulkan in native code using the "armeabi" ABI. */ +#if defined(__ARM_ARCH) && __ARM_ARCH < 7 +#define SDL_VIDEO_VULKAN 0 +#else +#define SDL_VIDEO_VULKAN 1 +#endif /* Enable system power support */ #define SDL_POWER_ANDROID 1 -#endif /* _SDL_config_android_h */ +/* Enable the filesystem driver */ +#define SDL_FILESYSTEM_ANDROID 1 + +#endif /* SDL_config_android_h_ */ diff --git a/external/SDL2/SDL_config_iphoneos.h b/external/SDL2/SDL_config_iphoneos.h index f7925d4..deea030 100644 --- a/external/SDL2/SDL_config_iphoneos.h +++ b/external/SDL2/SDL_config_iphoneos.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_iphoneos_h -#define _SDL_config_iphoneos_h +#ifndef SDL_config_iphoneos_h_ +#define SDL_config_iphoneos_h_ +#define SDL_config_h_ #include "SDL_platform.h" @@ -30,109 +31,120 @@ #define SIZEOF_VOIDP 4 #endif -#define HAVE_GCC_ATOMICS 1 +#define HAVE_GCC_ATOMICS 1 -#define HAVE_ALLOCA_H 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_STDIO_H 1 -#define STDC_HEADERS 1 -#define HAVE_STRING_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_CTYPE_H 1 -#define HAVE_MATH_H 1 -#define HAVE_SIGNAL_H 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_SIGNAL_H 1 /* C library functions */ -#define HAVE_MALLOC 1 -#define HAVE_CALLOC 1 -#define HAVE_REALLOC 1 -#define HAVE_FREE 1 -#define HAVE_ALLOCA 1 -#define HAVE_GETENV 1 -#define HAVE_SETENV 1 -#define HAVE_PUTENV 1 -#define HAVE_SETENV 1 -#define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_ABS 1 -#define HAVE_BCOPY 1 -#define HAVE_MEMSET 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMCMP 1 -#define HAVE_STRLEN 1 -#define HAVE_STRLCPY 1 -#define HAVE_STRLCAT 1 -#define HAVE_STRDUP 1 -#define HAVE_STRCHR 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRSTR 1 -#define HAVE_STRTOL 1 -#define HAVE_STRTOUL 1 -#define HAVE_STRTOLL 1 -#define HAVE_STRTOULL 1 -#define HAVE_STRTOD 1 -#define HAVE_ATOI 1 -#define HAVE_ATOF 1 -#define HAVE_STRCMP 1 -#define HAVE_STRNCMP 1 -#define HAVE_STRCASECMP 1 +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_SETENV 1 +#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 #define HAVE_STRNCASECMP 1 -#define HAVE_SSCANF 1 -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -#define HAVE_M_PI 1 -#define HAVE_ATAN 1 -#define HAVE_ATAN2 1 -#define HAVE_CEIL 1 -#define HAVE_COPYSIGN 1 -#define HAVE_COS 1 -#define HAVE_COSF 1 -#define HAVE_FABS 1 -#define HAVE_FLOOR 1 -#define HAVE_LOG 1 -#define HAVE_POW 1 -#define HAVE_SCALBN 1 -#define HAVE_SIN 1 -#define HAVE_SINF 1 -#define HAVE_SQRT 1 -#define HAVE_SIGACTION 1 -#define HAVE_SETJMP 1 -#define HAVE_NANOSLEEP 1 -#define HAVE_SYSCONF 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI 1 +#define HAVE_ATAN 1 +#define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 +#define HAVE_CEIL 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +#define HAVE_SCALBN 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SIGACTION 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +#define HAVE_SYSCONF 1 #define HAVE_SYSCTLBYNAME 1 /* enable iPhone version of Core Audio driver */ #define SDL_AUDIO_DRIVER_COREAUDIO 1 /* Enable the dummy audio driver (src/audio/dummy/\*.c) */ -#define SDL_AUDIO_DRIVER_DUMMY 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable the stub haptic driver (src/haptic/dummy/\*.c) */ -#define SDL_HAPTIC_DISABLED 1 +#define SDL_HAPTIC_DUMMY 1 + +/* Enable MFi joystick support */ +#define SDL_JOYSTICK_MFI 1 /* Enable Unix style SO loading */ -/* Technically this works, but it violates the iPhone developer agreement */ -/* #define SDL_LOADSO_DLOPEN 1 */ - -/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */ -#define SDL_LOADSO_DISABLED 1 +#define SDL_LOADSO_DLOPEN 1 /* Enable various threading systems */ -#define SDL_THREAD_PTHREAD 1 -#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 +#define SDL_THREAD_PTHREAD 1 +#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 /* Enable various timer systems */ -#define SDL_TIMER_UNIX 1 +#define SDL_TIMER_UNIX 1 /* Supported video drivers */ -#define SDL_VIDEO_DRIVER_UIKIT 1 -#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_UIKIT 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 /* enable OpenGL ES */ -#define SDL_VIDEO_OPENGL_ES 1 -#define SDL_VIDEO_RENDER_OGL_ES 1 -#define SDL_VIDEO_RENDER_OGL_ES2 1 +#define SDL_VIDEO_OPENGL_ES2 1 +#define SDL_VIDEO_OPENGL_ES 1 +#define SDL_VIDEO_RENDER_OGL_ES 1 +#define SDL_VIDEO_RENDER_OGL_ES2 1 + +/* Enable Vulkan support */ +#if !TARGET_OS_SIMULATOR && !TARGET_CPU_ARM // Only 64-bit devices have Metal +#define SDL_VIDEO_VULKAN 1 +#else +#define SDL_VIDEO_VULKAN 0 +#endif /* Enable system power support */ #define SDL_POWER_UIKIT 1 @@ -140,12 +152,15 @@ /* enable iPhone keyboard support */ #define SDL_IPHONE_KEYBOARD 1 -/* enable joystick subsystem */ -#define SDL_JOYSTICK_DISABLED 0 +/* enable iOS extended launch screen */ +#define SDL_IPHONE_LAUNCHSCREEN 1 /* Set max recognized G-force from accelerometer - See src/joystick/uikit/SDLUIAccelerationDelegate.m for notes on why this is needed + See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed */ #define SDL_IPHONE_MAX_GFORCE 5.0 -#endif /* _SDL_config_iphoneos_h */ +/* enable filesystem support */ +#define SDL_FILESYSTEM_COCOA 1 + +#endif /* SDL_config_iphoneos_h_ */ diff --git a/external/SDL2/SDL_config_macosx.h b/external/SDL2/SDL_config_macosx.h index fece7fb..9b09899 100644 --- a/external/SDL2/SDL_config_macosx.h +++ b/external/SDL2/SDL_config_macosx.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_macosx_h -#define _SDL_config_macosx_h +#ifndef SDL_config_macosx_h_ +#define SDL_config_macosx_h_ +#define SDL_config_h_ #include "SDL_platform.h" @@ -30,106 +31,107 @@ /* This is a set of defines to configure the SDL features */ #ifdef __LP64__ - #define SIZEOF_VOIDP 8 + #define SIZEOF_VOIDP 8 #else - #define SIZEOF_VOIDP 4 + #define SIZEOF_VOIDP 4 #endif /* Useful headers */ -/* If we specified an SDK or have a post-PowerPC chip, then alloca.h exists. */ -#if ( (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030) || (!defined(__POWERPC__)) ) -#define HAVE_ALLOCA_H 1 -#endif -#define HAVE_SYS_TYPES_H 1 -#define HAVE_STDIO_H 1 -#define STDC_HEADERS 1 -#define HAVE_STRING_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_CTYPE_H 1 -#define HAVE_MATH_H 1 -#define HAVE_SIGNAL_H 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_SIGNAL_H 1 /* C library functions */ -#define HAVE_MALLOC 1 -#define HAVE_CALLOC 1 -#define HAVE_REALLOC 1 -#define HAVE_FREE 1 -#define HAVE_ALLOCA 1 -#define HAVE_GETENV 1 -#define HAVE_SETENV 1 -#define HAVE_PUTENV 1 -#define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_ABS 1 -#define HAVE_BCOPY 1 -#define HAVE_MEMSET 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMCMP 1 -#define HAVE_STRLEN 1 -#define HAVE_STRLCPY 1 -#define HAVE_STRLCAT 1 -#define HAVE_STRDUP 1 -#define HAVE_STRCHR 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRSTR 1 -#define HAVE_STRTOL 1 -#define HAVE_STRTOUL 1 -#define HAVE_STRTOLL 1 -#define HAVE_STRTOULL 1 -#define HAVE_STRTOD 1 -#define HAVE_ATOI 1 -#define HAVE_ATOF 1 -#define HAVE_STRCMP 1 -#define HAVE_STRNCMP 1 -#define HAVE_STRCASECMP 1 +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 #define HAVE_STRNCASECMP 1 -#define HAVE_SSCANF 1 -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -#define HAVE_CEIL 1 -#define HAVE_COPYSIGN 1 -#define HAVE_COS 1 -#define HAVE_COSF 1 -#define HAVE_FABS 1 -#define HAVE_FLOOR 1 -#define HAVE_LOG 1 -#define HAVE_POW 1 -#define HAVE_SCALBN 1 -#define HAVE_SIN 1 -#define HAVE_SINF 1 -#define HAVE_SQRT 1 -#define HAVE_SIGACTION 1 -#define HAVE_SETJMP 1 -#define HAVE_NANOSLEEP 1 -#define HAVE_SYSCONF 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_CEIL 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +#define HAVE_SCALBN 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SIGACTION 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +#define HAVE_SYSCONF 1 #define HAVE_SYSCTLBYNAME 1 #define HAVE_ATAN 1 #define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 /* Enable various audio drivers */ -#define SDL_AUDIO_DRIVER_COREAUDIO 1 -#define SDL_AUDIO_DRIVER_DISK 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 +#define SDL_AUDIO_DRIVER_COREAUDIO 1 +#define SDL_AUDIO_DRIVER_DISK 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable various input drivers */ -#define SDL_JOYSTICK_IOKIT 1 -#define SDL_HAPTIC_IOKIT 1 +#define SDL_JOYSTICK_IOKIT 1 +#define SDL_HAPTIC_IOKIT 1 /* Enable various shared object loading systems */ -#define SDL_LOADSO_DLOPEN 1 +#define SDL_LOADSO_DLOPEN 1 /* Enable various threading systems */ -#define SDL_THREAD_PTHREAD 1 -#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 +#define SDL_THREAD_PTHREAD 1 +#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 /* Enable various timer systems */ -#define SDL_TIMER_UNIX 1 +#define SDL_TIMER_UNIX 1 /* Enable various video drivers */ -#define SDL_VIDEO_DRIVER_COCOA 1 -#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_COCOA 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 #undef SDL_VIDEO_DRIVER_X11 #define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib" #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib" @@ -138,6 +140,7 @@ #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib" #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib" #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib" +#define SDL_VIDEO_DRIVER_X11_XDBE 1 #define SDL_VIDEO_DRIVER_X11_XINERAMA 1 #define SDL_VIDEO_DRIVER_X11_XRANDR 1 #define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1 @@ -157,27 +160,38 @@ #endif #ifndef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 1 +#define SDL_VIDEO_RENDER_OGL 1 #endif /* Enable OpenGL support */ #ifndef SDL_VIDEO_OPENGL -#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL 1 #endif #ifndef SDL_VIDEO_OPENGL_CGL -#define SDL_VIDEO_OPENGL_CGL 1 +#define SDL_VIDEO_OPENGL_CGL 1 #endif #ifndef SDL_VIDEO_OPENGL_GLX -#define SDL_VIDEO_OPENGL_GLX 1 +#define SDL_VIDEO_OPENGL_GLX 1 +#endif + +/* Enable Vulkan support */ +/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures with 10.11+ */ +#if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100) +#define SDL_VIDEO_VULKAN 1 +#else +#define SDL_VIDEO_VULKAN 0 #endif /* Enable system power support */ #define SDL_POWER_MACOSX 1 +/* enable filesystem support */ +#define SDL_FILESYSTEM_COCOA 1 + /* Enable assembly routines */ -#define SDL_ASSEMBLY_ROUTINES 1 +#define SDL_ASSEMBLY_ROUTINES 1 #ifdef __ppc__ -#define SDL_ALTIVEC_BLITTERS 1 +#define SDL_ALTIVEC_BLITTERS 1 #endif -#endif /* _SDL_config_macosx_h */ +#endif /* SDL_config_macosx_h_ */ diff --git a/external/SDL2/SDL_config_macosx.h.orig b/external/SDL2/SDL_config_macosx.h.orig new file mode 100644 index 0000000..f03f1ae --- /dev/null +++ b/external/SDL2/SDL_config_macosx.h.orig @@ -0,0 +1,197 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_macosx_h_ +#define SDL_config_macosx_h_ +#define SDL_config_h_ + +#include "SDL_platform.h" + +/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */ +#include + +/* This is a set of defines to configure the SDL features */ + +#ifdef __LP64__ + #define SIZEOF_VOIDP 8 +#else + #define SIZEOF_VOIDP 4 +#endif + +/* Useful headers */ +#define HAVE_ALLOCA_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_SIGNAL_H 1 + +/* C library functions */ +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRNCASECMP 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_CEIL 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +#define HAVE_SCALBN 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SIGACTION 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +#define HAVE_SYSCONF 1 +#define HAVE_SYSCTLBYNAME 1 +#define HAVE_ATAN 1 +#define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 + +/* Enable various audio drivers */ +#define SDL_AUDIO_DRIVER_COREAUDIO 1 +#define SDL_AUDIO_DRIVER_DISK 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 + +/* Enable various input drivers */ +#define SDL_JOYSTICK_IOKIT 1 +#define SDL_HAPTIC_IOKIT 1 + +/* Enable various shared object loading systems */ +#define SDL_LOADSO_DLOPEN 1 + +/* Enable various threading systems */ +#define SDL_THREAD_PTHREAD 1 +#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 + +/* Enable various timer systems */ +#define SDL_TIMER_UNIX 1 + +/* Enable various video drivers */ +#define SDL_VIDEO_DRIVER_COCOA 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 +#undef SDL_VIDEO_DRIVER_X11 +#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib" +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib" +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib" +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib" +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib" +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib" +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib" +#define SDL_VIDEO_DRIVER_X11_XDBE 1 +#define SDL_VIDEO_DRIVER_X11_XINERAMA 1 +#define SDL_VIDEO_DRIVER_X11_XRANDR 1 +#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1 +#define SDL_VIDEO_DRIVER_X11_XSHAPE 1 +#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1 +#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1 + +#ifdef MAC_OS_X_VERSION_10_8 +/* + * No matter the versions targeted, this is the 10.8 or later SDK, so you have + * to use the external Xquartz, which is a more modern Xlib. Previous SDKs + * used an older Xlib. + */ +#define SDL_VIDEO_DRIVER_X11_XINPUT2 1 +#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1 +#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 1 +#endif + +#ifndef SDL_VIDEO_RENDER_OGL +#define SDL_VIDEO_RENDER_OGL 1 +#endif + +/* Enable OpenGL support */ +#ifndef SDL_VIDEO_OPENGL +#define SDL_VIDEO_OPENGL 1 +#endif +#ifndef SDL_VIDEO_OPENGL_CGL +#define SDL_VIDEO_OPENGL_CGL 1 +#endif +#ifndef SDL_VIDEO_OPENGL_GLX +#define SDL_VIDEO_OPENGL_GLX 1 +#endif + +/* Enable Vulkan support */ +/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures and 10.11+ */ +#if TARGET_CPU_X86_64 +#define SDL_VIDEO_VULKAN 1 +#else +#define SDL_VIDEO_VULKAN 0 +#endif + +/* Enable system power support */ +#define SDL_POWER_MACOSX 1 + +/* enable filesystem support */ +#define SDL_FILESYSTEM_COCOA 1 + +/* Enable assembly routines */ +#define SDL_ASSEMBLY_ROUTINES 1 +#ifdef __ppc__ +#define SDL_ALTIVEC_BLITTERS 1 +#endif + +#endif /* SDL_config_macosx_h_ */ diff --git a/external/SDL2/SDL_config_minimal.h b/external/SDL2/SDL_config_minimal.h index cb6f0a5..3112700 100644 --- a/external/SDL2/SDL_config_minimal.h +++ b/external/SDL2/SDL_config_minimal.h @@ -1,7 +1,6 @@ -/* include/SDL_config.h. Generated from SDL_config.h.in by configure. */ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -20,283 +19,64 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_minimal_h -#define _SDL_config_minimal_h +#ifndef SDL_config_minimal_h_ +#define SDL_config_minimal_h_ +#define SDL_config_h_ -/** - * \file SDL_config.h.in - * - * This is a set of defines to configure the SDL features - */ - -/* General platform specific identifiers */ #include "SDL_platform.h" -/* Make sure that this isn't included by Visual C++ */ -#ifdef _MSC_VER -#error You should run hg revert SDL_config.h -#endif +/** + * \file SDL_config_minimal.h + * + * This is the minimal configuration that can be used to build SDL. + */ -/* C language features */ -/* #undef const */ -/* #undef inline */ -/* #undef volatile */ - -/* C datatypes */ -#define SIZEOF_VOIDP 4 -#define HAVE_GCC_ATOMICS 1 -/* #undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET */ -#define HAVE_PTHREAD_SPINLOCK 1 - -/* Comment this if you want to build without any C library requirements */ -#define HAVE_LIBC 1 -#if HAVE_LIBC - -/* Useful headers */ -#define HAVE_ALLOCA_H 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_STDIO_H 1 -#define STDC_HEADERS 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STDARG_H 1 -#define HAVE_MALLOC_H 1 -#define HAVE_MEMORY_H 1 -#define HAVE_STRING_H 1 -#define HAVE_STRINGS_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_CTYPE_H 1 -#define HAVE_MATH_H 1 -#define HAVE_ICONV_H 1 -#define HAVE_SIGNAL_H 1 -/* #undef HAVE_ALTIVEC_H */ -/* #undef HAVE_PTHREAD_NP_H */ -#define HAVE_LIBUDEV_H 1 -#define HAVE_DBUS_DBUS_H 1 - -/* C library functions */ -#define HAVE_MALLOC 1 -#define HAVE_CALLOC 1 -#define HAVE_REALLOC 1 -#define HAVE_FREE 1 -#define HAVE_ALLOCA 1 -#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */ -#define HAVE_GETENV 1 -#define HAVE_SETENV 1 -#define HAVE_PUTENV 1 -#define HAVE_UNSETENV 1 -#endif -#define HAVE_QSORT 1 -#define HAVE_ABS 1 -#define HAVE_BCOPY 1 -#define HAVE_MEMSET 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMCMP 1 -#define HAVE_STRLEN 1 -/* #undef HAVE_STRLCPY */ -/* #undef HAVE_STRLCAT */ -#define HAVE_STRDUP 1 -/* #undef HAVE__STRREV */ -/* #undef HAVE__STRUPR */ -/* #undef HAVE__STRLWR */ -/* #undef HAVE_INDEX */ -/* #undef HAVE_RINDEX */ -#define HAVE_STRCHR 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRSTR 1 -/* #undef HAVE_ITOA */ -/* #undef HAVE__LTOA */ -/* #undef HAVE__UITOA */ -/* #undef HAVE__ULTOA */ -#define HAVE_STRTOL 1 -#define HAVE_STRTOUL 1 -/* #undef HAVE__I64TOA */ -/* #undef HAVE__UI64TOA */ -#define HAVE_STRTOLL 1 -#define HAVE_STRTOULL 1 -#define HAVE_STRTOD 1 -#define HAVE_ATOI 1 -#define HAVE_ATOF 1 -#define HAVE_STRCMP 1 -#define HAVE_STRNCMP 1 -/* #undef HAVE__STRICMP */ -#define HAVE_STRCASECMP 1 -/* #undef HAVE__STRNICMP */ -#define HAVE_STRNCASECMP 1 -#define HAVE_SSCANF 1 -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -#define HAVE_M_PI /**/ -#define HAVE_ATAN 1 -#define HAVE_ATAN2 1 -#define HAVE_CEIL 1 -#define HAVE_COPYSIGN 1 -#define HAVE_COS 1 -#define HAVE_COSF 1 -#define HAVE_FABS 1 -#define HAVE_FLOOR 1 -#define HAVE_LOG 1 -#define HAVE_POW 1 -#define HAVE_SCALBN 1 -#define HAVE_SIN 1 -#define HAVE_SINF 1 -#define HAVE_SQRT 1 -#define HAVE_FSEEKO 1 -#define HAVE_FSEEKO64 1 -#define HAVE_SIGACTION 1 -#define HAVE_SA_SIGACTION 1 -#define HAVE_SETJMP 1 -#define HAVE_NANOSLEEP 1 -#define HAVE_SYSCONF 1 -/* #undef HAVE_SYSCTLBYNAME */ -/* #undef HAVE_CLOCK_GETTIME */ -/* #undef HAVE_GETPAGESIZE */ -#define HAVE_MPROTECT 1 -#define HAVE_ICONV 1 -#define HAVE_PTHREAD_SETNAME_NP 1 -/* #undef HAVE_PTHREAD_SET_NAME_NP */ -#define HAVE_SEM_TIMEDWAIT 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 +/* Most everything except Visual Studio 2008 and earlier has stdint.h now */ +#if defined(_MSC_VER) && (_MSC_VER < 1600) +/* Here are some reasonable defaults */ +typedef unsigned int size_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +typedef unsigned long uintptr_t; #else -/* We may need some replacement for stdarg.h here */ -#include -#endif /* HAVE_LIBC */ +#define HAVE_STDINT_H 1 +#endif /* Visual Studio 2008 */ -/* SDL internal assertion support */ -/* #undef SDL_DEFAULT_ASSERT_LEVEL */ +#ifdef __GNUC__ +#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1 +#endif -/* Allow disabling of core subsystems */ -/* #undef SDL_ATOMIC_DISABLED */ -/* #undef SDL_AUDIO_DISABLED */ -/* #undef SDL_CPUINFO_DISABLED */ -/* #undef SDL_EVENTS_DISABLED */ -/* #undef SDL_FILE_DISABLED */ -/* #undef SDL_JOYSTICK_DISABLED */ -/* #undef SDL_HAPTIC_DISABLED */ -/* #undef SDL_LOADSO_DISABLED */ -/* #undef SDL_RENDER_DISABLED */ -/* #undef SDL_THREADS_DISABLED */ -/* #undef SDL_TIMERS_DISABLED */ -/* #undef SDL_VIDEO_DISABLED */ -/* #undef SDL_POWER_DISABLED */ +/* Enable the dummy audio driver (src/audio/dummy/\*.c) */ +#define SDL_AUDIO_DRIVER_DUMMY 1 -/* Enable various audio drivers */ -#define SDL_AUDIO_DRIVER_ALSA 1 -#define SDL_AUDIO_DRIVER_ALSA_DYNAMIC "libasound.so.2" -/* #undef SDL_AUDIO_DRIVER_ARTS */ -/* #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC */ -#define SDL_AUDIO_DRIVER_PULSEAUDIO 1 -#define SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC "libpulse-simple.so.0" -/* #undef SDL_AUDIO_DRIVER_BEOSAUDIO */ -/* #undef SDL_AUDIO_DRIVER_BSD */ -/* #undef SDL_AUDIO_DRIVER_COREAUDIO */ -#define SDL_AUDIO_DRIVER_DISK 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 -/* #undef SDL_AUDIO_DRIVER_XAUDIO2 */ -/* #undef SDL_AUDIO_DRIVER_DSOUND */ -/* #undef SDL_AUDIO_DRIVER_ESD */ -/* #undef SDL_AUDIO_DRIVER_ESD_DYNAMIC */ -/* #undef SDL_AUDIO_DRIVER_NAS */ -/* #undef SDL_AUDIO_DRIVER_NAS_DYNAMIC */ -#define SDL_AUDIO_DRIVER_OSS 1 -/* #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H */ -/* #undef SDL_AUDIO_DRIVER_PAUDIO */ -/* #undef SDL_AUDIO_DRIVER_QSA */ -/* #undef SDL_AUDIO_DRIVER_SUNAUDIO */ -/* #undef SDL_AUDIO_DRIVER_WINMM */ -/* #undef SDL_AUDIO_DRIVER_FUSIONSOUND */ -/* #undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */ +/* Enable the stub joystick driver (src/joystick/dummy/\*.c) */ +#define SDL_JOYSTICK_DISABLED 1 -/* Enable various input drivers */ -#define SDL_INPUT_LINUXEV 1 -/* #undef SDL_INPUT_TSLIB */ -/* #undef SDL_JOYSTICK_BEOS */ -/* #undef SDL_JOYSTICK_DINPUT */ -/* #undef SDL_JOYSTICK_DUMMY */ -/* #undef SDL_JOYSTICK_IOKIT */ -#define SDL_JOYSTICK_LINUX 1 -/* #undef SDL_JOYSTICK_WINMM */ -/* #undef SDL_JOYSTICK_USBHID */ -/* #undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */ -/* #undef SDL_HAPTIC_DUMMY */ -#define SDL_HAPTIC_LINUX 1 -/* #undef SDL_HAPTIC_IOKIT */ -/* #undef SDL_HAPTIC_DINPUT */ +/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */ +#define SDL_HAPTIC_DISABLED 1 -/* Enable various shared object loading systems */ -/* #undef SDL_LOADSO_BEOS */ -#define SDL_LOADSO_DLOPEN 1 -/* #undef SDL_LOADSO_DUMMY */ -/* #undef SDL_LOADSO_LDG */ -/* #undef SDL_LOADSO_WINDOWS */ +/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DISABLED 1 -/* Enable various threading systems */ -/* #undef SDL_THREAD_BEOS */ -#define SDL_THREAD_PTHREAD 1 -#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 -/* #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP */ -/* #undef SDL_THREAD_WINDOWS */ +/* Enable the stub thread support (src/thread/generic/\*.c) */ +#define SDL_THREADS_DISABLED 1 -/* Enable various timer systems */ -/* #undef SDL_TIMER_BEOS */ -/* #undef SDL_TIMER_DUMMY */ -#define SDL_TIMER_UNIX 1 -/* #undef SDL_TIMER_WINDOWS */ +/* Enable the stub timer support (src/timer/dummy/\*.c) */ +#define SDL_TIMERS_DISABLED 1 -/* Enable various video drivers */ -/* #undef SDL_VIDEO_DRIVER_BWINDOW */ -/* #undef SDL_VIDEO_DRIVER_COCOA */ -/* #undef SDL_VIDEO_DRIVER_DIRECTFB */ -/* #undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC */ -#define SDL_VIDEO_DRIVER_DUMMY 1 -/* #undef SDL_VIDEO_DRIVER_WINDOWS */ -#define SDL_VIDEO_DRIVER_X11 1 -#define SDL_VIDEO_DRIVER_X11_DYNAMIC "libX11.so.6" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "libXext.so.6" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR "libXcursor.so.1" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "libXinerama.so.1" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "libXi.so.6" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "libXrandr.so.2" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "libXss.so.1" -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "libXxf86vm.so.1" -#define SDL_VIDEO_DRIVER_X11_XCURSOR 1 -#define SDL_VIDEO_DRIVER_X11_XINERAMA 1 -#define SDL_VIDEO_DRIVER_X11_XINPUT2 1 -#define SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1 -#define SDL_VIDEO_DRIVER_X11_XRANDR 1 -#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1 -#define SDL_VIDEO_DRIVER_X11_XSHAPE 1 -#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1 -#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1 -/* #undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY */ -#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1 +/* Enable the dummy video driver (src/video/dummy/\*.c) */ +#define SDL_VIDEO_DRIVER_DUMMY 1 -/* #undef SDL_VIDEO_RENDER_D3D */ -#define SDL_VIDEO_RENDER_OGL 1 -/* #undef SDL_VIDEO_RENDER_OGL_ES */ -/* #undef SDL_VIDEO_RENDER_OGL_ES2 */ -/* #undef SDL_VIDEO_RENDER_DIRECTFB */ +/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */ +#define SDL_FILESYSTEM_DUMMY 1 -/* Enable OpenGL support */ -#define SDL_VIDEO_OPENGL 1 -/* #undef SDL_VIDEO_OPENGL_ES */ -/* #undef SDL_VIDEO_OPENGL_BGL */ -/* #undef SDL_VIDEO_OPENGL_CGL */ -#define SDL_VIDEO_OPENGL_GLX 1 -/* #undef SDL_VIDEO_OPENGL_WGL */ -/* #undef SDL_VIDEO_OPENGL_OSMESA */ -/* #undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC */ - -/* Enable system power support */ -#define SDL_POWER_LINUX 1 -/* #undef SDL_POWER_WINDOWS */ -/* #undef SDL_POWER_MACOSX */ -/* #undef SDL_POWER_BEOS */ -/* #undef SDL_POWER_HARDWIRED */ - -/* Enable assembly routines */ -#define SDL_ASSEMBLY_ROUTINES 1 -/* #undef SDL_ALTIVEC_BLITTERS */ - -#endif /* _SDL_config_minimal_h */ +#endif /* SDL_config_minimal_h_ */ diff --git a/external/SDL2/SDL_config_pandora.h b/external/SDL2/SDL_config_pandora.h index ebd9b67..ea62fe5 100644 --- a/external/SDL2/SDL_config_pandora.h +++ b/external/SDL2/SDL_config_pandora.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_h -#define _SDL_config_h +#ifndef SDL_config_pandora_h_ +#define SDL_config_pandora_h_ +#define SDL_config_h_ /* This is a set of defines to configure the SDL features */ @@ -57,7 +58,7 @@ #define HAVE_FREE 1 #define HAVE_ALLOCA 1 #define HAVE_GETENV 1 -#define HAVE_SETENV 1 +#define HAVE_SETENV 1 #define HAVE_PUTENV 1 #define HAVE_UNSETENV 1 #define HAVE_QSORT 1 @@ -81,8 +82,7 @@ #define HAVE_STRNCMP 1 #define HAVE_STRCASECMP 1 #define HAVE_STRNCASECMP 1 -#define HAVE_SSCANF 1 -#define HAVE_SNPRINTF 1 +#define HAVE_VSSCANF 1 #define HAVE_VSNPRINTF 1 #define HAVE_M_PI 1 #define HAVE_CEIL 1 @@ -96,6 +96,9 @@ #define HAVE_SIN 1 #define HAVE_SINF 1 #define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 #define HAVE_SIGACTION 1 #define HAVE_SETJMP 1 #define HAVE_NANOSLEEP 1 @@ -114,6 +117,7 @@ #define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1 #define SDL_TIMER_UNIX 1 +#define SDL_FILESYSTEM_UNIX 1 #define SDL_VIDEO_DRIVER_DUMMY 1 #define SDL_VIDEO_DRIVER_X11 1 @@ -121,4 +125,4 @@ #define SDL_VIDEO_RENDER_OGL_ES 1 #define SDL_VIDEO_OPENGL_ES 1 -#endif /* _SDL_config_h */ +#endif /* SDL_config_pandora_h_ */ diff --git a/external/SDL2/SDL_config_psp.h b/external/SDL2/SDL_config_psp.h new file mode 100644 index 0000000..28efb4c --- /dev/null +++ b/external/SDL2/SDL_config_psp.h @@ -0,0 +1,144 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_psp_h_ +#define SDL_config_psp_h_ +#define SDL_config_h_ + +#include "SDL_platform.h" + + + +#ifdef __GNUC__ +#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1 +#endif + +#define HAVE_GCC_ATOMICS 1 + +#define HAVE_ALLOCA_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_SIGNAL_H 1 + +/* C library functions */ +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_SETENV 1 +#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRNCASECMP 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI 1 +#define HAVE_ATAN 1 +#define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 +#define HAVE_CEIL 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +#define HAVE_SCALBN 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +/* #define HAVE_SYSCONF 1 */ +/* #define HAVE_SIGACTION 1 */ + + +/* PSP isn't that sophisticated */ +#define LACKS_SYS_MMAN_H 1 + +/* Enable the stub thread support (src/thread/psp/\*.c) */ +#define SDL_THREAD_PSP 1 + +/* Enable the stub timer support (src/timer/psp/\*.c) */ +#define SDL_TIMERS_PSP 1 + +/* Enable the stub joystick driver (src/joystick/psp/\*.c) */ +#define SDL_JOYSTICK_PSP 1 + +/* Enable the stub audio driver (src/audio/psp/\*.c) */ +#define SDL_AUDIO_DRIVER_PSP 1 + +/* PSP video dirver */ +#define SDL_VIDEO_DRIVER_PSP 1 + +/* PSP render dirver */ +#define SDL_VIDEO_RENDER_PSP 1 + +#define SDL_POWER_PSP 1 + +/* !!! FIXME: what does PSP do for filesystem stuff? */ +#define SDL_FILESYSTEM_DUMMY 1 + +/* PSP doesn't have haptic device (src/haptic/dummy/\*.c) */ +#define SDL_HAPTIC_DISABLED 1 + +/* PSP can't load shared object (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DISABLED 1 + + +#endif /* SDL_config_psp_h_ */ diff --git a/external/SDL2/SDL_config_windows.h b/external/SDL2/SDL_config_windows.h index c3f229f..36b0180 100644 --- a/external/SDL2/SDL_config_windows.h +++ b/external/SDL2/SDL_config_windows.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_windows_h -#define _SDL_config_windows_h +#ifndef SDL_config_windows_h_ +#define SDL_config_windows_h_ +#define SDL_config_h_ #include "SDL_platform.h" @@ -28,7 +29,7 @@ #if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H) #if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__) -#define HAVE_STDINT_H 1 +#define HAVE_STDINT_H 1 #elif defined(_MSC_VER) typedef signed __int8 int8_t; typedef unsigned __int8 uint8_t; @@ -76,8 +77,13 @@ typedef unsigned int uintptr_t; # define SIZEOF_VOIDP 4 #endif -/* Enabled for SDL 1.2 (binary compatibility) */ -//#define HAVE_LIBC 1 +#define HAVE_DDRAW_H 1 +#define HAVE_DINPUT_H 1 +#define HAVE_DSOUND_H 1 +#define HAVE_DXGI_H 0 +#define HAVE_XINPUT_H 1 + +/* This is disabled by default to avoid C runtime dependencies and manifest requirements */ #ifdef HAVE_LIBC /* Useful headers */ #define HAVE_STDIO_H 1 @@ -106,12 +112,10 @@ typedef unsigned int uintptr_t; #define HAVE_STRCHR 1 #define HAVE_STRRCHR 1 #define HAVE_STRSTR 1 -#define HAVE_ITOA 1 #define HAVE__LTOA 1 #define HAVE__ULTOA 1 #define HAVE_STRTOL 1 #define HAVE_STRTOUL 1 -#define HAVE_STRTOLL 1 #define HAVE_STRTOD 1 #define HAVE_ATOI 1 #define HAVE_ATOF 1 @@ -119,74 +123,103 @@ typedef unsigned int uintptr_t; #define HAVE_STRNCMP 1 #define HAVE__STRICMP 1 #define HAVE__STRNICMP 1 -#define HAVE_SSCANF 1 -#define HAVE_M_PI 1 #define HAVE_ATAN 1 #define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 #define HAVE_CEIL 1 -#define HAVE_COPYSIGN 1 #define HAVE_COS 1 #define HAVE_COSF 1 #define HAVE_FABS 1 #define HAVE_FLOOR 1 #define HAVE_LOG 1 #define HAVE_POW 1 -#define HAVE_SCALBN 1 #define HAVE_SIN 1 #define HAVE_SINF 1 #define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#if _MSC_VER >= 1800 +#define HAVE_STRTOLL 1 +#define HAVE_VSSCANF 1 +#define HAVE_COPYSIGN 1 +#define HAVE_SCALBN 1 +#endif +#if !defined(_MSC_VER) || defined(_USE_MATH_DEFINES) +#define HAVE_M_PI 1 +#endif #else -#define HAVE_STDARG_H 1 -#define HAVE_STDDEF_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 #endif /* Enable various audio drivers */ -#define SDL_AUDIO_DRIVER_DSOUND 1 -#ifndef __GNUC__ -#define SDL_AUDIO_DRIVER_XAUDIO2 1 -#endif -#define SDL_AUDIO_DRIVER_WINMM 1 -#define SDL_AUDIO_DRIVER_DISK 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 +#define SDL_AUDIO_DRIVER_WASAPI 1 +#define SDL_AUDIO_DRIVER_DSOUND 1 +#define SDL_AUDIO_DRIVER_XAUDIO2 0 +#define SDL_AUDIO_DRIVER_WINMM 1 +#define SDL_AUDIO_DRIVER_DISK 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable various input drivers */ -#define SDL_JOYSTICK_DINPUT 1 -#define SDL_HAPTIC_DINPUT 1 +#define SDL_JOYSTICK_DINPUT 1 +#define SDL_JOYSTICK_XINPUT 1 +#define SDL_HAPTIC_DINPUT 1 +#define SDL_HAPTIC_XINPUT 1 /* Enable various shared object loading systems */ -#define SDL_LOADSO_WINDOWS 1 +#define SDL_LOADSO_WINDOWS 1 /* Enable various threading systems */ -#define SDL_THREAD_WINDOWS 1 +#define SDL_THREAD_WINDOWS 1 /* Enable various timer systems */ -#define SDL_TIMER_WINDOWS 1 +#define SDL_TIMER_WINDOWS 1 /* Enable various video drivers */ -#define SDL_VIDEO_DRIVER_DUMMY 1 -#define SDL_VIDEO_DRIVER_WINDOWS 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_WINDOWS 1 #ifndef SDL_VIDEO_RENDER_D3D -#define SDL_VIDEO_RENDER_D3D 1 +#define SDL_VIDEO_RENDER_D3D 1 +#endif +#ifndef SDL_VIDEO_RENDER_D3D11 +#define SDL_VIDEO_RENDER_D3D11 0 #endif /* Enable OpenGL support */ #ifndef SDL_VIDEO_OPENGL -#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL 1 #endif #ifndef SDL_VIDEO_OPENGL_WGL -#define SDL_VIDEO_OPENGL_WGL 1 +#define SDL_VIDEO_OPENGL_WGL 1 #endif #ifndef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 1 +#define SDL_VIDEO_RENDER_OGL 1 #endif +#ifndef SDL_VIDEO_RENDER_OGL_ES2 +#define SDL_VIDEO_RENDER_OGL_ES2 0 +#endif +#ifndef SDL_VIDEO_OPENGL_ES2 +#define SDL_VIDEO_OPENGL_ES2 0 +#endif +#ifndef SDL_VIDEO_OPENGL_EGL +#define SDL_VIDEO_OPENGL_EGL 0 +#endif + +/* Enable Vulkan support */ +#define SDL_VIDEO_VULKAN 0 /* Enable system power support */ #define SDL_POWER_WINDOWS 1 +/* Enable filesystem support */ +#define SDL_FILESYSTEM_WINDOWS 0 + /* Enable assembly routines (Win64 doesn't have inline asm) */ #ifndef _WIN64 -#define SDL_ASSEMBLY_ROUTINES 1 +#define SDL_ASSEMBLY_ROUTINES 1 #endif -#endif /* _SDL_config_windows_h */ +#endif /* SDL_config_windows_h_ */ diff --git a/external/SDL2/SDL_config_winrt.h b/external/SDL2/SDL_config_winrt.h new file mode 100644 index 0000000..24f9e17 --- /dev/null +++ b/external/SDL2/SDL_config_winrt.h @@ -0,0 +1,215 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_winrt_h_ +#define SDL_config_winrt_h_ +#define SDL_config_h_ + +#include "SDL_platform.h" + +/* Make sure the Windows SDK's NTDDI_VERSION macro gets defined. This is used + by SDL to determine which version of the Windows SDK is being used. +*/ +#include + +/* Define possibly-undefined NTDDI values (used when compiling SDL against + older versions of the Windows SDK. +*/ +#ifndef NTDDI_WINBLUE +#define NTDDI_WINBLUE 0x06030000 +#endif +#ifndef NTDDI_WIN10 +#define NTDDI_WIN10 0x0A000000 +#endif + +/* This is a set of defines to configure the SDL features */ + +#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H) +#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__) +#define HAVE_STDINT_H 1 +#elif defined(_MSC_VER) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else +typedef unsigned int uintptr_t; +#endif +#define _UINTPTR_T_DEFINED +#endif +/* Older Visual C++ headers don't have the Win64-compatible typedefs... */ +#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR))) +#define DWORD_PTR DWORD +#endif +#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR))) +#define LONG_PTR LONG +#endif +#else /* !__GNUC__ && !_MSC_VER */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef unsigned int size_t; +#endif +typedef unsigned int uintptr_t; +#endif /* __GNUC__ || _MSC_VER */ +#endif /* !_STDINT_H_ && !HAVE_STDINT_H */ + +#ifdef _WIN64 +# define SIZEOF_VOIDP 8 +#else +# define SIZEOF_VOIDP 4 +#endif + +/* Useful headers */ +#define HAVE_DXGI_H 1 +#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP +#define HAVE_XINPUT_H 1 +#endif +#define HAVE_LIBC 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_FLOAT_H 1 +#define HAVE_SIGNAL_H 1 + +/* C library functions */ +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE__STRREV 1 +#define HAVE__STRUPR 1 +//#define HAVE__STRLWR 1 // TODO, WinRT: consider using _strlwr_s instead +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +//#define HAVE_ITOA 1 // TODO, WinRT: consider using _itoa_s instead +//#define HAVE__LTOA 1 // TODO, WinRT: consider using _ltoa_s instead +//#define HAVE__ULTOA 1 // TODO, WinRT: consider using _ultoa_s instead +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +//#define HAVE_STRTOLL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE__STRICMP 1 +#define HAVE__STRNICMP 1 +#define HAVE_VSNPRINTF 1 +//#define HAVE_SSCANF 1 // TODO, WinRT: consider using sscanf_s instead +#define HAVE_M_PI 1 +#define HAVE_ATAN 1 +#define HAVE_ATAN2 1 +#define HAVE_CEIL 1 +#define HAVE__COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +//#define HAVE_SCALBN 1 +#define HAVE__SCALB 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE__FSEEKI64 1 + +/* Enable various audio drivers */ +#define SDL_AUDIO_DRIVER_XAUDIO2 1 +#define SDL_AUDIO_DRIVER_DISK 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 + +/* Enable various input drivers */ +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP +#define SDL_JOYSTICK_DISABLED 1 +#define SDL_HAPTIC_DISABLED 1 +#else +#define SDL_JOYSTICK_XINPUT 1 +#define SDL_HAPTIC_XINPUT 1 +#endif + +/* Enable various shared object loading systems */ +#define SDL_LOADSO_WINDOWS 1 + +/* Enable various threading systems */ +#if (NTDDI_VERSION >= NTDDI_WINBLUE) +#define SDL_THREAD_WINDOWS 1 +#else +/* WinRT on Windows 8.0 and Windows Phone 8.0 don't support CreateThread() */ +#define SDL_THREAD_STDCPP 1 +#endif + +/* Enable various timer systems */ +#define SDL_TIMER_WINDOWS 1 + +/* Enable various video drivers */ +#define SDL_VIDEO_DRIVER_WINRT 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 + +/* Enable OpenGL ES 2.0 (via a modified ANGLE library) */ +#define SDL_VIDEO_OPENGL_ES2 1 +#define SDL_VIDEO_OPENGL_EGL 1 + +/* Enable appropriate renderer(s) */ +#define SDL_VIDEO_RENDER_D3D11 1 + +#if SDL_VIDEO_OPENGL_ES2 +#define SDL_VIDEO_RENDER_OGL_ES2 1 +#endif + +/* Enable system power support */ +#define SDL_POWER_WINRT 1 + +/* Enable assembly routines (Win64 doesn't have inline asm) */ +#ifndef _WIN64 +#define SDL_ASSEMBLY_ROUTINES 1 +#endif + +#endif /* SDL_config_winrt_h_ */ diff --git a/external/SDL2/SDL_config_wiz.h b/external/SDL2/SDL_config_wiz.h index 2c72958..5bb845a 100644 --- a/external/SDL2/SDL_config_wiz.h +++ b/external/SDL2/SDL_config_wiz.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_config_h -#define _SDL_config_h +#ifndef SDL_config_wiz_h_ +#define SDL_config_wiz_h_ +#define SDL_config_h_ /* This is a set of defines to configure the SDL features */ @@ -51,7 +52,7 @@ #define HAVE_FREE 1 #define HAVE_ALLOCA 1 #define HAVE_GETENV 1 -#define HAVE_SETENV 1 +#define HAVE_SETENV 1 #define HAVE_PUTENV 1 #define HAVE_UNSETENV 1 #define HAVE_QSORT 1 @@ -75,8 +76,7 @@ #define HAVE_STRNCMP 1 #define HAVE_STRCASECMP 1 #define HAVE_STRNCASECMP 1 -#define HAVE_SSCANF 1 -#define HAVE_SNPRINTF 1 +#define HAVE_VSSCANF 1 #define HAVE_VSNPRINTF 1 #define HAVE_M_PI 1 #define HAVE_CEIL 1 @@ -90,12 +90,14 @@ #define HAVE_SIN 1 #define HAVE_SINF 1 #define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 #define HAVE_SIGACTION 1 #define HAVE_SETJMP 1 #define HAVE_NANOSLEEP 1 #define HAVE_POW 1 -#define SDL_CDROM_DISABLED 1 #define SDL_AUDIO_DRIVER_DUMMY 1 #define SDL_AUDIO_DRIVER_OSS 1 @@ -116,4 +118,4 @@ #define SDL_VIDEO_RENDER_OGL_ES 1 #define SDL_VIDEO_OPENGL_ES 1 -#endif /* _SDL_config_h */ +#endif /* SDL_config_wiz_h_ */ diff --git a/external/SDL2/SDL_copying.h b/external/SDL2/SDL_copying.h index 3a8fb75..8f60af6 100644 --- a/external/SDL2/SDL_copying.h +++ b/external/SDL2/SDL_copying.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2017 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/external/SDL2/SDL_cpuinfo.h b/external/SDL2/SDL_cpuinfo.h index a3b1012..1fc4099 100644 --- a/external/SDL2/SDL_cpuinfo.h +++ b/external/SDL2/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,54 +21,104 @@ /** * \file SDL_cpuinfo.h - * + * * CPU feature detection for SDL. */ -#ifndef _SDL_cpuinfo_h -#define _SDL_cpuinfo_h +#ifndef SDL_cpuinfo_h_ +#define SDL_cpuinfo_h_ #include "SDL_stdinc.h" /* Need to do this here because intrin.h has C++ code in it */ /* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */ -#if defined(_MSC_VER) && (_MSC_VER >= 1500) +#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64)) +#ifdef __clang__ +/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version, + so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */ + +#ifndef __PRFCHWINTRIN_H +#define __PRFCHWINTRIN_H + +static __inline__ void __attribute__((__always_inline__, __nodebug__)) +_m_prefetch(void *__P) +{ + __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */); +} + +#endif /* __PRFCHWINTRIN_H */ +#endif /* __clang__ */ #include #ifndef _WIN64 +#ifndef __MMX__ #define __MMX__ +#endif +#ifndef __3dNOW__ #define __3dNOW__ #endif +#endif +#ifndef __SSE__ #define __SSE__ +#endif +#ifndef __SSE2__ #define __SSE2__ +#endif +#ifndef __SSE3__ +#define __SSE3__ +#endif #elif defined(__MINGW64_VERSION_MAJOR) #include +#if !defined(SDL_DISABLE_ARM_NEON_H) && defined(__ARM_NEON) +# include +#endif #else -#ifdef __ALTIVEC__ -#if HAVE_ALTIVEC_H && !defined(__APPLE_ALTIVEC__) +/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */ +#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H) #include -#undef pixel #endif +#if !defined(SDL_DISABLE_ARM_NEON_H) +# if defined(__ARM_NEON) +# include +# elif defined(__WINDOWS__) || defined(__WINRT__) +/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */ +# if defined(_M_ARM) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# if defined (_M_ARM64) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# endif #endif -#ifdef __MMX__ -#include -#endif -#ifdef __3dNOW__ +#endif /* compiler version */ + +#if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H) #include #endif -#ifdef __SSE__ +#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H) +#include +#else +#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H) +#include +#endif +#if defined(__SSE__) && !defined(SDL_DISABLE_XMMINTRIN_H) #include #endif -#ifdef __SSE2__ +#if defined(__SSE2__) && !defined(SDL_DISABLE_EMMINTRIN_H) #include #endif +#if defined(__SSE3__) && !defined(SDL_DISABLE_PMMINTRIN_H) +#include #endif +#endif /* HAVE_IMMINTRIN_H */ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* This is a guess for the cacheline size used for padding. @@ -79,72 +129,431 @@ extern "C" { #define SDL_CACHELINE_SIZE 128 /** - * This function returns the number of CPU cores available. + * Get the number of CPU cores available. + * + * \returns the total number of logical CPU cores. On CPUs that include + * technologies such as hyperthreading, the number of logical cores + * may be more than the number of physical cores. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_GetCPUCount(void); /** - * This function returns the L1 cache line size of the CPU + * Determine the L1 cache line size of the CPU. * - * This is useful for determining multi-threaded structure padding - * or SIMD prefetch sizes. + * This is useful for determining multi-threaded structure padding or SIMD + * prefetch sizes. + * + * \returns the L1 cache line size of the CPU, in bytes. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_GetCPUCacheLineSize(void); /** - * This function returns true if the CPU has the RDTSC instruction. + * Determine whether the CPU has the RDTSC instruction. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has the RDTSC instruction or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(void); /** - * This function returns true if the CPU has AltiVec features. + * Determine whether the CPU has AltiVec features. + * + * This always returns false on CPUs that aren't using PowerPC instruction + * sets. + * + * \returns SDL_TRUE if the CPU has AltiVec features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void); /** - * This function returns true if the CPU has MMX features. + * Determine whether the CPU has MMX features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has MMX features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void); /** - * This function returns true if the CPU has 3DNow! features. + * Determine whether the CPU has 3DNow! features. + * + * This always returns false on CPUs that aren't using AMD instruction sets. + * + * \returns SDL_TRUE if the CPU has 3DNow! features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(void); /** - * This function returns true if the CPU has SSE features. + * Determine whether the CPU has SSE features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has SSE features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void); /** - * This function returns true if the CPU has SSE2 features. + * Determine whether the CPU has SSE2 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has SSE2 features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void); /** - * This function returns true if the CPU has SSE3 features. + * Determine whether the CPU has SSE3 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has SSE3 features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE3(void); /** - * This function returns true if the CPU has SSE4.1 features. + * Determine whether the CPU has SSE4.1 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has SSE4.1 features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void); /** - * This function returns true if the CPU has SSE4.2 features. + * Determine whether the CPU has SSE4.2 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has SSE4.2 features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void); +/** + * Determine whether the CPU has AVX features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has AVX features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX2 + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void); + +/** + * Determine whether the CPU has AVX2 features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has AVX2 features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_Has3DNow + * \sa SDL_HasAltiVec + * \sa SDL_HasAVX + * \sa SDL_HasMMX + * \sa SDL_HasRDTSC + * \sa SDL_HasSSE + * \sa SDL_HasSSE2 + * \sa SDL_HasSSE3 + * \sa SDL_HasSSE41 + * \sa SDL_HasSSE42 + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void); + +/** + * Determine whether the CPU has AVX-512F (foundation) features. + * + * This always returns false on CPUs that aren't using Intel instruction sets. + * + * \returns SDL_TRUE if the CPU has AVX-512F features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.9. + * + * \sa SDL_HasAVX + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void); + +/** + * Determine whether the CPU has ARM SIMD (ARMv6) features. + * + * This is different from ARM NEON, which is a different instruction set. + * + * This always returns false on CPUs that aren't using ARM instruction sets. + * + * \returns SDL_TRUE if the CPU has ARM SIMD features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_HasNEON + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void); + +/** + * Determine whether the CPU has NEON (ARM SIMD) features. + * + * This always returns false on CPUs that aren't using ARM instruction sets. + * + * \returns SDL_TRUE if the CPU has ARM NEON features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void); + +/** + * Get the amount of RAM configured in the system. + * + * \returns the amount of RAM configured in the system in MB. + * + * \since This function is available since SDL 2.0.1. + */ +extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void); + +/** + * Report the alignment this system needs for SIMD allocations. + * + * This will return the minimum number of bytes to which a pointer must be + * aligned to be compatible with SIMD instructions on the current machine. For + * example, if the machine supports SSE only, it will return 16, but if it + * supports AVX-512F, it'll return 64 (etc). This only reports values for + * instruction sets SDL knows about, so if your SDL build doesn't have + * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and + * not 64 for the AVX-512 instructions that exist but SDL doesn't know about. + * Plan accordingly. + * + * \returns the alignment in bytes needed for available, known SIMD + * instructions. + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void); + +/** + * Allocate memory in a SIMD-friendly way. + * + * This will allocate a block of memory that is suitable for use with SIMD + * instructions. Specifically, it will be properly aligned and padded for the + * system's supported vector instructions. + * + * The memory returned will be padded such that it is safe to read or write an + * incomplete vector at the end of the memory block. This can be useful so you + * don't have to drop back to a scalar fallback at the end of your SIMD + * processing loop to deal with the final elements without overflowing the + * allocated buffer. + * + * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() or + * delete[], etc. + * + * Note that SDL will only deal with SIMD instruction sets it is aware of; for + * example, SDL 2.0.8 knows that SSE wants 16-byte vectors (SDL_HasSSE()), and + * AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't know that AVX-512 wants + * 64. To be clear: if you can't decide to use an instruction set with an + * SDL_Has*() function, don't use that instruction set with memory allocated + * through here. + * + * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't + * out of memory, but you are not allowed to dereference it (because you only + * own zero bytes of that buffer). + * + * \param len The length, in bytes, of the block to allocate. The actual + * allocated block might be larger due to padding, etc. + * \returns a pointer to the newly-allocated block, NULL if out of memory. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_SIMDAlignment + * \sa SDL_SIMDRealloc + * \sa SDL_SIMDFree + */ +extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len); + +/** + * Reallocate memory obtained from SDL_SIMDAlloc + * + * It is not valid to use this function on a pointer from anything but + * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc, + * SDL_malloc, memalign, new[], etc. + * + * \param mem The pointer obtained from SDL_SIMDAlloc. This function also + * accepts NULL, at which point this function is the same as + * calling SDL_SIMDAlloc with a NULL pointer. + * \param len The length, in bytes, of the block to allocated. The actual + * allocated block might be larger due to padding, etc. Passing 0 + * will return a non-NULL pointer, assuming the system isn't out of + * memory. + * \returns a pointer to the newly-reallocated block, NULL if out of memory. + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_SIMDAlignment + * \sa SDL_SIMDAlloc + * \sa SDL_SIMDFree + */ +extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, const size_t len); + +/** + * Deallocate memory obtained from SDL_SIMDAlloc + * + * It is not valid to use this function on a pointer from anything but + * SDL_SIMDAlloc() or SDL_SIMDRealloc(). It can't be used on pointers from + * malloc, realloc, SDL_malloc, memalign, new[], etc. + * + * However, SDL_SIMDFree(NULL) is a legal no-op. + * + * The memory pointed to by `ptr` is no longer valid for access upon return, + * and may be returned to the system or reused by a future allocation. The + * pointer passed to this function is no longer safe to dereference once this + * function returns, and should be discarded. + * + * \param ptr The pointer, returned from SDL_SIMDAlloc or SDL_SIMDRealloc, to + * deallocate. NULL is a legal no-op. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_SIMDAlloc + * \sa SDL_SIMDRealloc + */ +extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_cpuinfo_h */ +#endif /* SDL_cpuinfo_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_egl.h b/external/SDL2/SDL_egl.h new file mode 100644 index 0000000..f90e27b --- /dev/null +++ b/external/SDL2/SDL_egl.h @@ -0,0 +1,2302 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_egl.h + * + * This is a simple file to encapsulate the EGL API headers. + */ +#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) + +#if defined(__vita__) || defined(__psp2__) +#include +#endif + +#include +#include + +#else /* _MSC_VER */ + +/* EGL headers for Visual Studio */ + +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ + + +#ifndef __eglplatform_h_ +#define __eglplatform_h_ + +/* +** Copyright 2007-2020 The Khronos Group Inc. +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* Platform-specific types and definitions for egl.h + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by filing an issue or pull request on the public Khronos EGL Registry, at + * https://www.github.com/KhronosGroup/EGL-Registry/ + */ + +/*#include */ + +/* Macros used in EGL function prototype declarations. + * + * EGL functions should be prototyped as: + * + * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); + * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); + * + * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h + */ + +#ifndef EGLAPI +#define EGLAPI KHRONOS_APICALL +#endif + +#ifndef EGLAPIENTRY +#define EGLAPIENTRY KHRONOS_APIENTRY +#endif +#define EGLAPIENTRYP EGLAPIENTRY* + +/* The types NativeDisplayType, NativeWindowType, and NativePixmapType + * are aliases of window-system-dependent types, such as X Display * or + * Windows Device Context. They must be defined in platform-specific + * code below. The EGL-prefixed versions of Native*Type are the same + * types, renamed in EGL 1.3 so all types in the API start with "EGL". + * + * Khronos STRONGLY RECOMMENDS that you use the default definitions + * provided below, since these changes affect both binary and source + * portability of applications using EGL running on different EGL + * implementations. + */ + +#if defined(EGL_NO_PLATFORM_SPECIFIC_TYPES) + +typedef void *EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + +#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include + +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; + +#elif defined(__EMSCRIPTEN__) + +typedef int EGLNativeDisplayType; +typedef int EGLNativePixmapType; +typedef int EGLNativeWindowType; + +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ + +typedef int EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + +#elif defined(WL_EGL_PLATFORM) + +typedef struct wl_display *EGLNativeDisplayType; +typedef struct wl_egl_pixmap *EGLNativePixmapType; +typedef struct wl_egl_window *EGLNativeWindowType; + +#elif defined(__GBM__) + +typedef struct gbm_device *EGLNativeDisplayType; +typedef struct gbm_bo *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + +#elif defined(__ANDROID__) || defined(ANDROID) + +struct ANativeWindow; +struct egl_native_pixmap_t; + +typedef void* EGLNativeDisplayType; +typedef struct egl_native_pixmap_t* EGLNativePixmapType; +typedef struct ANativeWindow* EGLNativeWindowType; + +#elif defined(USE_OZONE) + +typedef intptr_t EGLNativeDisplayType; +typedef intptr_t EGLNativePixmapType; +typedef intptr_t EGLNativeWindowType; + +#elif defined(USE_X11) + +/* X11 (tentative) */ +#include +#include + +typedef Display *EGLNativeDisplayType; +typedef Pixmap EGLNativePixmapType; +typedef Window EGLNativeWindowType; + +#elif defined(__unix__) + +typedef void *EGLNativeDisplayType; +typedef khronos_uintptr_t EGLNativePixmapType; +typedef khronos_uintptr_t EGLNativeWindowType; + +#elif defined(__APPLE__) + +typedef int EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + +#elif defined(__HAIKU__) + +#include + +typedef void *EGLNativeDisplayType; +typedef khronos_uintptr_t EGLNativePixmapType; +typedef khronos_uintptr_t EGLNativeWindowType; + +#elif defined(__Fuchsia__) + +typedef void *EGLNativeDisplayType; +typedef khronos_uintptr_t EGLNativePixmapType; +typedef khronos_uintptr_t EGLNativeWindowType; + +#else +#error "Platform not recognized" +#endif + +/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ +typedef EGLNativeDisplayType NativeDisplayType; +typedef EGLNativePixmapType NativePixmapType; +typedef EGLNativeWindowType NativeWindowType; + + +/* Define EGLint. This must be a signed integral type large enough to contain + * all legal attribute names and values passed into and out of EGL, whether + * their type is boolean, bitmask, enumerant (symbolic constant), integer, + * handle, or other. While in general a 32-bit integer will suffice, if + * handles are 64 bit types, then EGLint should be defined as a signed 64-bit + * integer type. + */ +typedef khronos_int32_t EGLint; + + +/* C++ / C typecast macros for special EGL handle values */ +#if defined(__cplusplus) +#define EGL_CAST(type, value) (static_cast(value)) +#else +#define EGL_CAST(type, value) ((type) (value)) +#endif + +#endif /* __eglplatform_h */ + + +#ifndef __egl_h_ +#define __egl_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: Apache-2.0 +** +** This header is generated from the Khronos EGL XML API Registry. +** The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.khronos.org/registry/egl +** +** Khronos $Git commit SHA1: b35e89ca9a $ on $Git commit date: 2021-09-01 09:34:00 +0530 $ +*/ + +/*#include */ + +#ifndef EGL_EGL_PROTOTYPES +#define EGL_EGL_PROTOTYPES 1 +#endif + +/* Generated on date 20210901 */ + +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_VERSION_1_0 +#define EGL_VERSION_1_0 1 +typedef unsigned int EGLBoolean; +typedef void *EGLDisplay; +/*#include */ +/*#include */ +typedef void *EGLConfig; +typedef void *EGLSurface; +typedef void *EGLContext; +typedef void (*__eglMustCastToProperFunctionPointerType)(void); +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300A +#define EGL_BAD_NATIVE_WINDOW 0x300B +#define EGL_BAD_PARAMETER 0x300C +#define EGL_BAD_SURFACE 0x300D +#define EGL_BLUE_SIZE 0x3022 +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_CORE_NATIVE_ENGINE 0x305B +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_DONT_CARE EGL_CAST(EGLint,-1) +#define EGL_DRAW 0x3059 +#define EGL_EXTENSIONS 0x3055 +#define EGL_FALSE 0 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_HEIGHT 0x3056 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_NONE 0x3038 +#define EGL_NON_CONFORMANT_CONFIG 0x3051 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_NO_CONTEXT EGL_CAST(EGLContext,0) +#define EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0) +#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0) +#define EGL_PBUFFER_BIT 0x0001 +#define EGL_PIXMAP_BIT 0x0002 +#define EGL_READ 0x305A +#define EGL_RED_SIZE 0x3024 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SLOW_CONFIG 0x3050 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_SUCCESS 0x3000 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_TRANSPARENT_RGB 0x3052 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRUE 1 +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_WIDTH 0x3057 +#define EGL_WINDOW_BIT 0x0004 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCHOOSECONFIGPROC) (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYBUFFERSPROC) (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +typedef EGLContext (EGLAPIENTRYP PFNEGLCREATECONTEXTPROC) (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPBUFFERSURFACEPROC) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEPROC) (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEWINDOWSURFACEPROC) (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYCONTEXTPROC) (EGLDisplay dpy, EGLContext ctx); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSURFACEPROC) (EGLDisplay dpy, EGLSurface surface); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCONFIGATTRIBPROC) (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCONFIGSPROC) (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETCURRENTDISPLAYPROC) (void); +typedef EGLSurface (EGLAPIENTRYP PFNEGLGETCURRENTSURFACEPROC) (EGLint readdraw); +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDISPLAYPROC) (EGLNativeDisplayType display_id); +typedef EGLint (EGLAPIENTRYP PFNEGLGETERRORPROC) (void); +typedef __eglMustCastToProperFunctionPointerType (EGLAPIENTRYP PFNEGLGETPROCADDRESSPROC) (const char *procname); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLINITIALIZEPROC) (EGLDisplay dpy, EGLint *major, EGLint *minor); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLMAKECURRENTPROC) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYCONTEXTPROC) (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYSTRINGPROC) (EGLDisplay dpy, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSPROC) (EGLDisplay dpy, EGLSurface surface); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLTERMINATEPROC) (EGLDisplay dpy); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITGLPROC) (void); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITNATIVEPROC) (EGLint engine); +#if EGL_EGL_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void); +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw); +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id); +EGLAPI EGLint EGLAPIENTRY eglGetError (void); +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname); +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine); +#endif +#endif /* EGL_VERSION_1_0 */ + +#ifndef EGL_VERSION_1_1 +#define EGL_VERSION_1_1 1 +#define EGL_BACK_BUFFER 0x3084 +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_CONTEXT_LOST 0x300E +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_NO_TEXTURE 0x305C +#define EGL_TEXTURE_2D 0x305F +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_RGB 0x305D +#define EGL_TEXTURE_RGBA 0x305E +#define EGL_TEXTURE_TARGET 0x3081 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDTEXIMAGEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASETEXIMAGEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSURFACEATTRIBPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPINTERVALPROC) (EGLDisplay dpy, EGLint interval); +#if EGL_EGL_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval); +#endif +#endif /* EGL_VERSION_1_1 */ + +#ifndef EGL_VERSION_1_2 +#define EGL_VERSION_1_2 1 +typedef unsigned int EGLenum; +typedef void *EGLClientBuffer; +#define EGL_ALPHA_FORMAT 0x3088 +#define EGL_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_ALPHA_FORMAT_PRE 0x308C +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_BUFFER_PRESERVED 0x3094 +#define EGL_BUFFER_DESTROYED 0x3095 +#define EGL_CLIENT_APIS 0x308D +#define EGL_COLORSPACE 0x3087 +#define EGL_COLORSPACE_sRGB 0x3089 +#define EGL_COLORSPACE_LINEAR 0x308A +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 +#define EGL_DISPLAY_SCALING 10000 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_LUMINANCE_BUFFER 0x308F +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENVG_BIT 0x0002 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENVG_API 0x30A1 +#define EGL_OPENVG_IMAGE 0x3096 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_RGB_BUFFER 0x308E +#define EGL_SINGLE_BUFFER 0x3085 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_UNKNOWN EGL_CAST(EGLint,-1) +#define EGL_VERTICAL_RESOLUTION 0x3091 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDAPIPROC) (EGLenum api); +typedef EGLenum (EGLAPIENTRYP PFNEGLQUERYAPIPROC) (void); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC) (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASETHREADPROC) (void); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITCLIENTPROC) (void); +#if EGL_EGL_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api); +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void); +#endif +#endif /* EGL_VERSION_1_2 */ + +#ifndef EGL_VERSION_1_3 +#define EGL_VERSION_1_3 1 +#define EGL_CONFORMANT 0x3042 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_VG_ALPHA_FORMAT_PRE 0x308C +#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_COLORSPACE_sRGB 0x3089 +#define EGL_VG_COLORSPACE_LINEAR 0x308A +#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 +#endif /* EGL_VERSION_1_3 */ + +#ifndef EGL_VERSION_1_4 +#define EGL_VERSION_1_4 1 +#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0) +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 +#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A +#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B +#define EGL_OPENGL_API 0x30A2 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +typedef EGLContext (EGLAPIENTRYP PFNEGLGETCURRENTCONTEXTPROC) (void); +#if EGL_EGL_PROTOTYPES +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); +#endif +#endif /* EGL_VERSION_1_4 */ + +#ifndef EGL_VERSION_1_5 +#define EGL_VERSION_1_5 1 +typedef void *EGLSync; +typedef intptr_t EGLAttrib; +typedef khronos_utime_nanoseconds_t EGLTime; +typedef void *EGLImage; +#define EGL_CONTEXT_MAJOR_VERSION 0x3098 +#define EGL_CONTEXT_MINOR_VERSION 0x30FB +#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD +#define EGL_NO_RESET_NOTIFICATION 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2 +#define EGL_OPENGL_ES3_BIT 0x00000040 +#define EGL_CL_EVENT_HANDLE 0x309C +#define EGL_SYNC_CL_EVENT 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 +#define EGL_SYNC_TYPE 0x30F7 +#define EGL_SYNC_STATUS 0x30F1 +#define EGL_SYNC_CONDITION 0x30F8 +#define EGL_SIGNALED 0x30F2 +#define EGL_UNSIGNALED 0x30F3 +#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 +#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull +#define EGL_TIMEOUT_EXPIRED 0x30F5 +#define EGL_CONDITION_SATISFIED 0x30F6 +#define EGL_NO_SYNC EGL_CAST(EGLSync,0) +#define EGL_SYNC_FENCE 0x30F9 +#define EGL_GL_COLORSPACE 0x309D +#define EGL_GL_COLORSPACE_SRGB 0x3089 +#define EGL_GL_COLORSPACE_LINEAR 0x308A +#define EGL_GL_RENDERBUFFER 0x30B9 +#define EGL_GL_TEXTURE_2D 0x30B1 +#define EGL_GL_TEXTURE_LEVEL 0x30BC +#define EGL_GL_TEXTURE_3D 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET 0x30BD +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +#define EGL_IMAGE_PRESERVED 0x30D2 +#define EGL_NO_IMAGE EGL_CAST(EGLImage,0) +typedef EGLSync (EGLAPIENTRYP PFNEGLCREATESYNCPROC) (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCPROC) (EGLDisplay dpy, EGLSync sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCPROC) (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBPROC) (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +typedef EGLImage (EGLAPIENTRYP PFNEGLCREATEIMAGEPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEPROC) (EGLDisplay dpy, EGLImage image); +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYPROC) (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITSYNCPROC) (EGLDisplay dpy, EGLSync sync, EGLint flags); +#if EGL_EGL_PROTOTYPES +EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image); +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags); +#endif +#endif /* EGL_VERSION_1_5 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __egl_h_ */ + + +#ifndef __eglext_h_ +#define __eglext_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: Apache-2.0 +** +** This header is generated from the Khronos EGL XML API Registry. +** The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.khronos.org/registry/egl +** +** Khronos $Git commit SHA1: b35e89ca9a $ on $Git commit date: 2021-09-01 09:34:00 +0530 $ +*/ + +/*#include */ + +#define EGL_EGLEXT_VERSION 20210901 + +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: _nomatch_^ + * Default extensions included: egl + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_KHR_cl_event +#define EGL_KHR_cl_event 1 +#define EGL_CL_EVENT_HANDLE_KHR 0x309C +#define EGL_SYNC_CL_EVENT_KHR 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF +#endif /* EGL_KHR_cl_event */ + +#ifndef EGL_KHR_cl_event2 +#define EGL_KHR_cl_event2 1 +typedef void *EGLSyncKHR; +typedef intptr_t EGLAttribKHR; +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#endif +#endif /* EGL_KHR_cl_event2 */ + +#ifndef EGL_KHR_client_get_all_proc_addresses +#define EGL_KHR_client_get_all_proc_addresses 1 +#endif /* EGL_KHR_client_get_all_proc_addresses */ + +#ifndef EGL_KHR_config_attribs +#define EGL_KHR_config_attribs 1 +#define EGL_CONFORMANT_KHR 0x3042 +#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 +#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 +#endif /* EGL_KHR_config_attribs */ + +#ifndef EGL_KHR_context_flush_control +#define EGL_KHR_context_flush_control 1 +#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0 +#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097 +#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 +#endif /* EGL_KHR_context_flush_control */ + +#ifndef EGL_KHR_create_context +#define EGL_KHR_create_context 1 +#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 +#endif /* EGL_KHR_create_context */ + +#ifndef EGL_KHR_create_context_no_error +#define EGL_KHR_create_context_no_error 1 +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3 +#endif /* EGL_KHR_create_context_no_error */ + +#ifndef EGL_KHR_debug +#define EGL_KHR_debug 1 +typedef void *EGLLabelKHR; +typedef void *EGLObjectKHR; +typedef void (EGLAPIENTRY *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message); +#define EGL_OBJECT_THREAD_KHR 0x33B0 +#define EGL_OBJECT_DISPLAY_KHR 0x33B1 +#define EGL_OBJECT_CONTEXT_KHR 0x33B2 +#define EGL_OBJECT_SURFACE_KHR 0x33B3 +#define EGL_OBJECT_IMAGE_KHR 0x33B4 +#define EGL_OBJECT_SYNC_KHR 0x33B5 +#define EGL_OBJECT_STREAM_KHR 0x33B6 +#define EGL_DEBUG_MSG_CRITICAL_KHR 0x33B9 +#define EGL_DEBUG_MSG_ERROR_KHR 0x33BA +#define EGL_DEBUG_MSG_WARN_KHR 0x33BB +#define EGL_DEBUG_MSG_INFO_KHR 0x33BC +#define EGL_DEBUG_CALLBACK_KHR 0x33B8 +typedef EGLint (EGLAPIENTRYP PFNEGLDEBUGMESSAGECONTROLKHRPROC) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEBUGKHRPROC) (EGLint attribute, EGLAttrib *value); +typedef EGLint (EGLAPIENTRYP PFNEGLLABELOBJECTKHRPROC) (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDebugKHR (EGLint attribute, EGLAttrib *value); +EGLAPI EGLint EGLAPIENTRY eglLabelObjectKHR (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label); +#endif +#endif /* EGL_KHR_debug */ + +#ifndef EGL_KHR_display_reference +#define EGL_KHR_display_reference 1 +#define EGL_TRACK_REFERENCES_KHR 0x3352 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBKHRPROC) (EGLDisplay dpy, EGLint name, EGLAttrib *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribKHR (EGLDisplay dpy, EGLint name, EGLAttrib *value); +#endif +#endif /* EGL_KHR_display_reference */ + +#ifndef EGL_KHR_fence_sync +#define EGL_KHR_fence_sync 1 +typedef khronos_utime_nanoseconds_t EGLTimeKHR; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 +#define EGL_SYNC_CONDITION_KHR 0x30F8 +#define EGL_SYNC_FENCE_KHR 0x30F9 +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_fence_sync */ + +#ifndef EGL_KHR_get_all_proc_addresses +#define EGL_KHR_get_all_proc_addresses 1 +#endif /* EGL_KHR_get_all_proc_addresses */ + +#ifndef EGL_KHR_gl_colorspace +#define EGL_KHR_gl_colorspace 1 +#define EGL_GL_COLORSPACE_KHR 0x309D +#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 +#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A +#endif /* EGL_KHR_gl_colorspace */ + +#ifndef EGL_KHR_gl_renderbuffer_image +#define EGL_KHR_gl_renderbuffer_image 1 +#define EGL_GL_RENDERBUFFER_KHR 0x30B9 +#endif /* EGL_KHR_gl_renderbuffer_image */ + +#ifndef EGL_KHR_gl_texture_2D_image +#define EGL_KHR_gl_texture_2D_image 1 +#define EGL_GL_TEXTURE_2D_KHR 0x30B1 +#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC +#endif /* EGL_KHR_gl_texture_2D_image */ + +#ifndef EGL_KHR_gl_texture_3D_image +#define EGL_KHR_gl_texture_3D_image 1 +#define EGL_GL_TEXTURE_3D_KHR 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD +#endif /* EGL_KHR_gl_texture_3D_image */ + +#ifndef EGL_KHR_gl_texture_cubemap_image +#define EGL_KHR_gl_texture_cubemap_image 1 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 +#endif /* EGL_KHR_gl_texture_cubemap_image */ + +#ifndef EGL_KHR_image +#define EGL_KHR_image 1 +typedef void *EGLImageKHR; +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define EGL_NO_IMAGE_KHR EGL_CAST(EGLImageKHR,0) +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); +#endif +#endif /* EGL_KHR_image */ + +#ifndef EGL_KHR_image_base +#define EGL_KHR_image_base 1 +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#endif /* EGL_KHR_image_base */ + +#ifndef EGL_KHR_image_pixmap +#define EGL_KHR_image_pixmap 1 +#endif /* EGL_KHR_image_pixmap */ + +#ifndef EGL_KHR_lock_surface +#define EGL_KHR_lock_surface 1 +#define EGL_READ_SURFACE_BIT_KHR 0x0001 +#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 +#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 +#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 +#define EGL_MATCH_FORMAT_KHR 0x3043 +#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 +#define EGL_FORMAT_RGB_565_KHR 0x30C1 +#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 +#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 +#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 +#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 +#define EGL_BITMAP_POINTER_KHR 0x30C6 +#define EGL_BITMAP_PITCH_KHR 0x30C7 +#define EGL_BITMAP_ORIGIN_KHR 0x30C8 +#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 +#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA +#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB +#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC +#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD +#define EGL_LOWER_LEFT_KHR 0x30CE +#define EGL_UPPER_LEFT_KHR 0x30CF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface); +#endif +#endif /* EGL_KHR_lock_surface */ + +#ifndef EGL_KHR_lock_surface2 +#define EGL_KHR_lock_surface2 1 +#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 +#endif /* EGL_KHR_lock_surface2 */ + +#ifndef EGL_KHR_lock_surface3 +#define EGL_KHR_lock_surface3 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#endif +#endif /* EGL_KHR_lock_surface3 */ + +#ifndef EGL_KHR_mutable_render_buffer +#define EGL_KHR_mutable_render_buffer 1 +#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000 +#endif /* EGL_KHR_mutable_render_buffer */ + +#ifndef EGL_KHR_no_config_context +#define EGL_KHR_no_config_context 1 +#define EGL_NO_CONFIG_KHR EGL_CAST(EGLConfig,0) +#endif /* EGL_KHR_no_config_context */ + +#ifndef EGL_KHR_partial_update +#define EGL_KHR_partial_update 1 +#define EGL_BUFFER_AGE_KHR 0x313D +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_KHR_partial_update */ + +#ifndef EGL_KHR_platform_android +#define EGL_KHR_platform_android 1 +#define EGL_PLATFORM_ANDROID_KHR 0x3141 +#endif /* EGL_KHR_platform_android */ + +#ifndef EGL_KHR_platform_gbm +#define EGL_KHR_platform_gbm 1 +#define EGL_PLATFORM_GBM_KHR 0x31D7 +#endif /* EGL_KHR_platform_gbm */ + +#ifndef EGL_KHR_platform_wayland +#define EGL_KHR_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_KHR 0x31D8 +#endif /* EGL_KHR_platform_wayland */ + +#ifndef EGL_KHR_platform_x11 +#define EGL_KHR_platform_x11 1 +#define EGL_PLATFORM_X11_KHR 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 +#endif /* EGL_KHR_platform_x11 */ + +#ifndef EGL_KHR_reusable_sync +#define EGL_KHR_reusable_sync 1 +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_STATUS_KHR 0x30F1 +#define EGL_SIGNALED_KHR 0x30F2 +#define EGL_UNSIGNALED_KHR 0x30F3 +#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 +#define EGL_CONDITION_SATISFIED_KHR 0x30F6 +#define EGL_SYNC_TYPE_KHR 0x30F7 +#define EGL_SYNC_REUSABLE_KHR 0x30FA +#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 +#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull +#define EGL_NO_SYNC_KHR EGL_CAST(EGLSyncKHR,0) +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_reusable_sync */ + +#ifndef EGL_KHR_stream +#define EGL_KHR_stream 1 +typedef void *EGLStreamKHR; +typedef khronos_uint64_t EGLuint64KHR; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_NO_STREAM_KHR EGL_CAST(EGLStreamKHR,0) +#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 +#define EGL_PRODUCER_FRAME_KHR 0x3212 +#define EGL_CONSUMER_FRAME_KHR 0x3213 +#define EGL_STREAM_STATE_KHR 0x3214 +#define EGL_STREAM_STATE_CREATED_KHR 0x3215 +#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 +#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 +#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 +#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 +#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A +#define EGL_BAD_STREAM_KHR 0x321B +#define EGL_BAD_STATE_KHR 0x321C +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_stream */ + +#ifndef EGL_KHR_stream_attrib +#define EGL_KHR_stream_attrib 1 +#ifdef KHRONOS_SUPPORT_INT64 +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBKHRPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribKHR (EGLDisplay dpy, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_stream_attrib */ + +#ifndef EGL_KHR_stream_consumer_gltexture +#define EGL_KHR_stream_consumer_gltexture 1 +#ifdef EGL_KHR_stream +#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_consumer_gltexture */ + +#ifndef EGL_KHR_stream_cross_process_fd +#define EGL_KHR_stream_cross_process_fd 1 +typedef int EGLNativeFileDescriptorKHR; +#ifdef EGL_KHR_stream +#define EGL_NO_FILE_DESCRIPTOR_KHR EGL_CAST(EGLNativeFileDescriptorKHR,-1) +typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_cross_process_fd */ + +#ifndef EGL_KHR_stream_fifo +#define EGL_KHR_stream_fifo 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC +#define EGL_STREAM_TIME_NOW_KHR 0x31FD +#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE +#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_fifo */ + +#ifndef EGL_KHR_stream_producer_aldatalocator +#define EGL_KHR_stream_producer_aldatalocator 1 +#ifdef EGL_KHR_stream +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_aldatalocator */ + +#ifndef EGL_KHR_stream_producer_eglsurface +#define EGL_KHR_stream_producer_eglsurface 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_BIT_KHR 0x0800 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_eglsurface */ + +#ifndef EGL_KHR_surfaceless_context +#define EGL_KHR_surfaceless_context 1 +#endif /* EGL_KHR_surfaceless_context */ + +#ifndef EGL_KHR_swap_buffers_with_damage +#define EGL_KHR_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_KHR_swap_buffers_with_damage */ + +#ifndef EGL_KHR_vg_parent_image +#define EGL_KHR_vg_parent_image 1 +#define EGL_VG_PARENT_IMAGE_KHR 0x30BA +#endif /* EGL_KHR_vg_parent_image */ + +#ifndef EGL_KHR_wait_sync +#define EGL_KHR_wait_sync 1 +typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#endif +#endif /* EGL_KHR_wait_sync */ + +#ifndef EGL_ANDROID_GLES_layers +#define EGL_ANDROID_GLES_layers 1 +#endif /* EGL_ANDROID_GLES_layers */ + +#ifndef EGL_ANDROID_blob_cache +#define EGL_ANDROID_blob_cache 1 +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#endif +#endif /* EGL_ANDROID_blob_cache */ + +#ifndef EGL_ANDROID_create_native_client_buffer +#define EGL_ANDROID_create_native_client_buffer 1 +#define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143 +#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001 +#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002 +#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004 +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC) (const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list); +#endif +#endif /* EGL_ANDROID_create_native_client_buffer */ + +#ifndef EGL_ANDROID_framebuffer_target +#define EGL_ANDROID_framebuffer_target 1 +#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 +#endif /* EGL_ANDROID_framebuffer_target */ + +#ifndef EGL_ANDROID_front_buffer_auto_refresh +#define EGL_ANDROID_front_buffer_auto_refresh 1 +#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C +#endif /* EGL_ANDROID_front_buffer_auto_refresh */ + +#ifndef EGL_ANDROID_get_frame_timestamps +#define EGL_ANDROID_get_frame_timestamps 1 +typedef khronos_stime_nanoseconds_t EGLnsecsANDROID; +#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID,-2) +#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID,-1) +#define EGL_TIMESTAMPS_ANDROID 0x3430 +#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431 +#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432 +#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433 +#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434 +#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435 +#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436 +#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437 +#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438 +#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439 +#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A +#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B +#define EGL_READS_DONE_TIME_ANDROID 0x343C +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglGetCompositorTimingSupportedANDROID (EGLDisplay dpy, EGLSurface surface, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglGetCompositorTimingANDROID (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values); +EGLAPI EGLBoolean EGLAPIENTRY eglGetNextFrameIdANDROID (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId); +EGLAPI EGLBoolean EGLAPIENTRY eglGetFrameTimestampSupportedANDROID (EGLDisplay dpy, EGLSurface surface, EGLint timestamp); +EGLAPI EGLBoolean EGLAPIENTRY eglGetFrameTimestampsANDROID (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values); +#endif +#endif /* EGL_ANDROID_get_frame_timestamps */ + +#ifndef EGL_ANDROID_get_native_client_buffer +#define EGL_ANDROID_get_native_client_buffer 1 +struct AHardwareBuffer; +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC) (const struct AHardwareBuffer *buffer); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLClientBuffer EGLAPIENTRY eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer); +#endif +#endif /* EGL_ANDROID_get_native_client_buffer */ + +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 +#endif /* EGL_ANDROID_image_native_buffer */ + +#ifndef EGL_ANDROID_native_fence_sync +#define EGL_ANDROID_native_fence_sync 1 +#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 +#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 +#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 +#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 +typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync); +#endif +#endif /* EGL_ANDROID_native_fence_sync */ + +#ifndef EGL_ANDROID_presentation_time +#define EGL_ANDROID_presentation_time 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglPresentationTimeANDROID (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time); +#endif +#endif /* EGL_ANDROID_presentation_time */ + +#ifndef EGL_ANDROID_recordable +#define EGL_ANDROID_recordable 1 +#define EGL_RECORDABLE_ANDROID 0x3142 +#endif /* EGL_ANDROID_recordable */ + +#ifndef EGL_ANGLE_d3d_share_handle_client_buffer +#define EGL_ANGLE_d3d_share_handle_client_buffer 1 +#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 +#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */ + +#ifndef EGL_ANGLE_device_d3d +#define EGL_ANGLE_device_d3d 1 +#define EGL_D3D9_DEVICE_ANGLE 0x33A0 +#define EGL_D3D11_DEVICE_ANGLE 0x33A1 +#endif /* EGL_ANGLE_device_d3d */ + +#ifndef EGL_ANGLE_query_surface_pointer +#define EGL_ANGLE_query_surface_pointer 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#endif +#endif /* EGL_ANGLE_query_surface_pointer */ + +#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle +#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 +#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */ + +#ifndef EGL_ANGLE_sync_control_rate +#define EGL_ANGLE_sync_control_rate 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETMSCRATEANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *numerator, EGLint *denominator); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglGetMscRateANGLE (EGLDisplay dpy, EGLSurface surface, EGLint *numerator, EGLint *denominator); +#endif +#endif /* EGL_ANGLE_sync_control_rate */ + +#ifndef EGL_ANGLE_window_fixed_size +#define EGL_ANGLE_window_fixed_size 1 +#define EGL_FIXED_SIZE_ANGLE 0x3201 +#endif /* EGL_ANGLE_window_fixed_size */ + +#ifndef EGL_ARM_image_format +#define EGL_ARM_image_format 1 +#define EGL_COLOR_COMPONENT_TYPE_UNSIGNED_INTEGER_ARM 0x3287 +#define EGL_COLOR_COMPONENT_TYPE_INTEGER_ARM 0x3288 +#endif /* EGL_ARM_image_format */ + +#ifndef EGL_ARM_implicit_external_sync +#define EGL_ARM_implicit_external_sync 1 +#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A +#endif /* EGL_ARM_implicit_external_sync */ + +#ifndef EGL_ARM_pixmap_multisample_discard +#define EGL_ARM_pixmap_multisample_discard 1 +#define EGL_DISCARD_SAMPLES_ARM 0x3286 +#endif /* EGL_ARM_pixmap_multisample_discard */ + +#ifndef EGL_EXT_bind_to_front +#define EGL_EXT_bind_to_front 1 +#define EGL_FRONT_BUFFER_EXT 0x3464 +#endif /* EGL_EXT_bind_to_front */ + +#ifndef EGL_EXT_buffer_age +#define EGL_EXT_buffer_age 1 +#define EGL_BUFFER_AGE_EXT 0x313D +#endif /* EGL_EXT_buffer_age */ + +#ifndef EGL_EXT_client_extensions +#define EGL_EXT_client_extensions 1 +#endif /* EGL_EXT_client_extensions */ + +#ifndef EGL_EXT_client_sync +#define EGL_EXT_client_sync 1 +#define EGL_SYNC_CLIENT_EXT 0x3364 +#define EGL_SYNC_CLIENT_SIGNAL_EXT 0x3365 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCLIENTSIGNALSYNCEXTPROC) (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglClientSignalSyncEXT (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_EXT_client_sync */ + +#ifndef EGL_EXT_compositor +#define EGL_EXT_compositor 1 +#define EGL_PRIMARY_COMPOSITOR_CONTEXT_EXT 0x3460 +#define EGL_EXTERNAL_REF_ID_EXT 0x3461 +#define EGL_COMPOSITOR_DROP_NEWEST_FRAME_EXT 0x3462 +#define EGL_COMPOSITOR_KEEP_NEWEST_FRAME_EXT 0x3463 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTLISTEXTPROC) (const EGLint *external_ref_ids, EGLint num_entries); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTATTRIBUTESEXTPROC) (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWLISTEXTPROC) (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWATTRIBUTESEXTPROC) (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORBINDTEXWINDOWEXTPROC) (EGLint external_win_id); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETSIZEEXTPROC) (EGLint external_win_id, EGLint width, EGLint height); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSWAPPOLICYEXTPROC) (EGLint external_win_id, EGLint policy); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextListEXT (const EGLint *external_ref_ids, EGLint num_entries); +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextAttributesEXT (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries); +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowListEXT (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries); +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowAttributesEXT (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries); +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorBindTexWindowEXT (EGLint external_win_id); +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetSizeEXT (EGLint external_win_id, EGLint width, EGLint height); +EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSwapPolicyEXT (EGLint external_win_id, EGLint policy); +#endif +#endif /* EGL_EXT_compositor */ + +#ifndef EGL_EXT_config_select_group +#define EGL_EXT_config_select_group 1 +#define EGL_CONFIG_SELECT_GROUP_EXT 0x34C0 +#endif /* EGL_EXT_config_select_group */ + +#ifndef EGL_EXT_create_context_robustness +#define EGL_EXT_create_context_robustness 1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 +#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF +#endif /* EGL_EXT_create_context_robustness */ + +#ifndef EGL_EXT_device_base +#define EGL_EXT_device_base 1 +typedef void *EGLDeviceEXT; +#define EGL_NO_DEVICE_EXT EGL_CAST(EGLDeviceEXT,0) +#define EGL_BAD_DEVICE_EXT 0x322B +#define EGL_DEVICE_EXT 0x322C +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#endif +#endif /* EGL_EXT_device_base */ + +#ifndef EGL_EXT_device_drm +#define EGL_EXT_device_drm 1 +#define EGL_DRM_DEVICE_FILE_EXT 0x3233 +#define EGL_DRM_MASTER_FD_EXT 0x333C +#endif /* EGL_EXT_device_drm */ + +#ifndef EGL_EXT_device_drm_render_node +#define EGL_EXT_device_drm_render_node 1 +#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377 +#endif /* EGL_EXT_device_drm_render_node */ + +#ifndef EGL_EXT_device_enumeration +#define EGL_EXT_device_enumeration 1 +#endif /* EGL_EXT_device_enumeration */ + +#ifndef EGL_EXT_device_openwf +#define EGL_EXT_device_openwf 1 +#define EGL_OPENWF_DEVICE_ID_EXT 0x3237 +#define EGL_OPENWF_DEVICE_EXT 0x333D +#endif /* EGL_EXT_device_openwf */ + +#ifndef EGL_EXT_device_persistent_id +#define EGL_EXT_device_persistent_id 1 +#define EGL_DEVICE_UUID_EXT 0x335C +#define EGL_DRIVER_UUID_EXT 0x335D +#define EGL_DRIVER_NAME_EXT 0x335E +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEBINARYEXTPROC) (EGLDeviceEXT device, EGLint name, EGLint max_size, void *value, EGLint *size); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceBinaryEXT (EGLDeviceEXT device, EGLint name, EGLint max_size, void *value, EGLint *size); +#endif +#endif /* EGL_EXT_device_persistent_id */ + +#ifndef EGL_EXT_device_query +#define EGL_EXT_device_query 1 +#endif /* EGL_EXT_device_query */ + +#ifndef EGL_EXT_device_query_name +#define EGL_EXT_device_query_name 1 +#define EGL_RENDERER_EXT 0x335F +#endif /* EGL_EXT_device_query_name */ + +#ifndef EGL_EXT_gl_colorspace_bt2020_linear +#define EGL_EXT_gl_colorspace_bt2020_linear 1 +#define EGL_GL_COLORSPACE_BT2020_LINEAR_EXT 0x333F +#endif /* EGL_EXT_gl_colorspace_bt2020_linear */ + +#ifndef EGL_EXT_gl_colorspace_bt2020_pq +#define EGL_EXT_gl_colorspace_bt2020_pq 1 +#define EGL_GL_COLORSPACE_BT2020_PQ_EXT 0x3340 +#endif /* EGL_EXT_gl_colorspace_bt2020_pq */ + +#ifndef EGL_EXT_gl_colorspace_display_p3 +#define EGL_EXT_gl_colorspace_display_p3 1 +#define EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363 +#endif /* EGL_EXT_gl_colorspace_display_p3 */ + +#ifndef EGL_EXT_gl_colorspace_display_p3_linear +#define EGL_EXT_gl_colorspace_display_p3_linear 1 +#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362 +#endif /* EGL_EXT_gl_colorspace_display_p3_linear */ + +#ifndef EGL_EXT_gl_colorspace_display_p3_passthrough +#define EGL_EXT_gl_colorspace_display_p3_passthrough 1 +#define EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490 +#endif /* EGL_EXT_gl_colorspace_display_p3_passthrough */ + +#ifndef EGL_EXT_gl_colorspace_scrgb +#define EGL_EXT_gl_colorspace_scrgb 1 +#define EGL_GL_COLORSPACE_SCRGB_EXT 0x3351 +#endif /* EGL_EXT_gl_colorspace_scrgb */ + +#ifndef EGL_EXT_gl_colorspace_scrgb_linear +#define EGL_EXT_gl_colorspace_scrgb_linear 1 +#define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350 +#endif /* EGL_EXT_gl_colorspace_scrgb_linear */ + +#ifndef EGL_EXT_image_dma_buf_import +#define EGL_EXT_image_dma_buf_import 1 +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B +#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C +#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D +#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E +#define EGL_ITU_REC601_EXT 0x327F +#define EGL_ITU_REC709_EXT 0x3280 +#define EGL_ITU_REC2020_EXT 0x3281 +#define EGL_YUV_FULL_RANGE_EXT 0x3282 +#define EGL_YUV_NARROW_RANGE_EXT 0x3283 +#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 +#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 +#endif /* EGL_EXT_image_dma_buf_import */ + +#ifndef EGL_EXT_image_dma_buf_import_modifiers +#define EGL_EXT_image_dma_buf_import_modifiers 1 +#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440 +#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441 +#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442 +#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443 +#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444 +#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445 +#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446 +#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447 +#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448 +#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449 +#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufFormatsEXT (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufModifiersEXT (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); +#endif +#endif /* EGL_EXT_image_dma_buf_import_modifiers */ + +#ifndef EGL_EXT_image_gl_colorspace +#define EGL_EXT_image_gl_colorspace 1 +#define EGL_GL_COLORSPACE_DEFAULT_EXT 0x314D +#endif /* EGL_EXT_image_gl_colorspace */ + +#ifndef EGL_EXT_image_implicit_sync_control +#define EGL_EXT_image_implicit_sync_control 1 +#define EGL_IMPORT_SYNC_TYPE_EXT 0x3470 +#define EGL_IMPORT_IMPLICIT_SYNC_EXT 0x3471 +#define EGL_IMPORT_EXPLICIT_SYNC_EXT 0x3472 +#endif /* EGL_EXT_image_implicit_sync_control */ + +#ifndef EGL_EXT_multiview_window +#define EGL_EXT_multiview_window 1 +#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134 +#endif /* EGL_EXT_multiview_window */ + +#ifndef EGL_EXT_output_base +#define EGL_EXT_output_base 1 +typedef void *EGLOutputLayerEXT; +typedef void *EGLOutputPortEXT; +#define EGL_NO_OUTPUT_LAYER_EXT EGL_CAST(EGLOutputLayerEXT,0) +#define EGL_NO_OUTPUT_PORT_EXT EGL_CAST(EGLOutputPortEXT,0) +#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D +#define EGL_BAD_OUTPUT_PORT_EXT 0x322E +#define EGL_SWAP_INTERVAL_EXT 0x322F +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers); +EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports); +EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name); +#endif +#endif /* EGL_EXT_output_base */ + +#ifndef EGL_EXT_output_drm +#define EGL_EXT_output_drm 1 +#define EGL_DRM_CRTC_EXT 0x3234 +#define EGL_DRM_PLANE_EXT 0x3235 +#define EGL_DRM_CONNECTOR_EXT 0x3236 +#endif /* EGL_EXT_output_drm */ + +#ifndef EGL_EXT_output_openwf +#define EGL_EXT_output_openwf 1 +#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238 +#define EGL_OPENWF_PORT_ID_EXT 0x3239 +#endif /* EGL_EXT_output_openwf */ + +#ifndef EGL_EXT_pixel_format_float +#define EGL_EXT_pixel_format_float 1 +#define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339 +#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A +#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B +#endif /* EGL_EXT_pixel_format_float */ + +#ifndef EGL_EXT_platform_base +#define EGL_EXT_platform_base 1 +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#endif +#endif /* EGL_EXT_platform_base */ + +#ifndef EGL_EXT_platform_device +#define EGL_EXT_platform_device 1 +#define EGL_PLATFORM_DEVICE_EXT 0x313F +#endif /* EGL_EXT_platform_device */ + +#ifndef EGL_EXT_platform_wayland +#define EGL_EXT_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_EXT 0x31D8 +#endif /* EGL_EXT_platform_wayland */ + +#ifndef EGL_EXT_platform_x11 +#define EGL_EXT_platform_x11 1 +#define EGL_PLATFORM_X11_EXT 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6 +#endif /* EGL_EXT_platform_x11 */ + +#ifndef EGL_EXT_platform_xcb +#define EGL_EXT_platform_xcb 1 +#define EGL_PLATFORM_XCB_EXT 0x31DC +#define EGL_PLATFORM_XCB_SCREEN_EXT 0x31DE +#endif /* EGL_EXT_platform_xcb */ + +#ifndef EGL_EXT_present_opaque +#define EGL_EXT_present_opaque 1 +#define EGL_PRESENT_OPAQUE_EXT 0x31DF +#endif /* EGL_EXT_present_opaque */ + +#ifndef EGL_EXT_protected_content +#define EGL_EXT_protected_content 1 +#define EGL_PROTECTED_CONTENT_EXT 0x32C0 +#endif /* EGL_EXT_protected_content */ + +#ifndef EGL_EXT_protected_surface +#define EGL_EXT_protected_surface 1 +#endif /* EGL_EXT_protected_surface */ + +#ifndef EGL_EXT_stream_consumer_egloutput +#define EGL_EXT_stream_consumer_egloutput 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer); +#endif +#endif /* EGL_EXT_stream_consumer_egloutput */ + +#ifndef EGL_EXT_surface_CTA861_3_metadata +#define EGL_EXT_surface_CTA861_3_metadata 1 +#define EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT 0x3360 +#define EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT 0x3361 +#endif /* EGL_EXT_surface_CTA861_3_metadata */ + +#ifndef EGL_EXT_surface_SMPTE2086_metadata +#define EGL_EXT_surface_SMPTE2086_metadata 1 +#define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT 0x3341 +#define EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT 0x3342 +#define EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT 0x3343 +#define EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT 0x3344 +#define EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT 0x3345 +#define EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT 0x3346 +#define EGL_SMPTE2086_WHITE_POINT_X_EXT 0x3347 +#define EGL_SMPTE2086_WHITE_POINT_Y_EXT 0x3348 +#define EGL_SMPTE2086_MAX_LUMINANCE_EXT 0x3349 +#define EGL_SMPTE2086_MIN_LUMINANCE_EXT 0x334A +#define EGL_METADATA_SCALING_EXT 50000 +#endif /* EGL_EXT_surface_SMPTE2086_metadata */ + +#ifndef EGL_EXT_swap_buffers_with_damage +#define EGL_EXT_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, const EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_EXT_swap_buffers_with_damage */ + +#ifndef EGL_EXT_sync_reuse +#define EGL_EXT_sync_reuse 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNSIGNALSYNCEXTPROC) (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglUnsignalSyncEXT (EGLDisplay dpy, EGLSync sync, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_EXT_sync_reuse */ + +#ifndef EGL_EXT_yuv_surface +#define EGL_EXT_yuv_surface 1 +#define EGL_YUV_ORDER_EXT 0x3301 +#define EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311 +#define EGL_YUV_SUBSAMPLE_EXT 0x3312 +#define EGL_YUV_DEPTH_RANGE_EXT 0x3317 +#define EGL_YUV_CSC_STANDARD_EXT 0x330A +#define EGL_YUV_PLANE_BPP_EXT 0x331A +#define EGL_YUV_BUFFER_EXT 0x3300 +#define EGL_YUV_ORDER_YUV_EXT 0x3302 +#define EGL_YUV_ORDER_YVU_EXT 0x3303 +#define EGL_YUV_ORDER_YUYV_EXT 0x3304 +#define EGL_YUV_ORDER_UYVY_EXT 0x3305 +#define EGL_YUV_ORDER_YVYU_EXT 0x3306 +#define EGL_YUV_ORDER_VYUY_EXT 0x3307 +#define EGL_YUV_ORDER_AYUV_EXT 0x3308 +#define EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313 +#define EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314 +#define EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315 +#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318 +#define EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319 +#define EGL_YUV_CSC_STANDARD_601_EXT 0x330B +#define EGL_YUV_CSC_STANDARD_709_EXT 0x330C +#define EGL_YUV_CSC_STANDARD_2020_EXT 0x330D +#define EGL_YUV_PLANE_BPP_0_EXT 0x331B +#define EGL_YUV_PLANE_BPP_8_EXT 0x331C +#define EGL_YUV_PLANE_BPP_10_EXT 0x331D +#endif /* EGL_EXT_yuv_surface */ + +#ifndef EGL_HI_clientpixmap +#define EGL_HI_clientpixmap 1 +struct EGLClientPixmapHI { + void *pData; + EGLint iWidth; + EGLint iHeight; + EGLint iStride; +}; +#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#endif +#endif /* EGL_HI_clientpixmap */ + +#ifndef EGL_HI_colorformats +#define EGL_HI_colorformats 1 +#define EGL_COLOR_FORMAT_HI 0x8F70 +#define EGL_COLOR_RGB_HI 0x8F71 +#define EGL_COLOR_RGBA_HI 0x8F72 +#define EGL_COLOR_ARGB_HI 0x8F73 +#endif /* EGL_HI_colorformats */ + +#ifndef EGL_IMG_context_priority +#define EGL_IMG_context_priority 1 +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#endif /* EGL_IMG_context_priority */ + +#ifndef EGL_IMG_image_plane_attribs +#define EGL_IMG_image_plane_attribs 1 +#define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105 +#define EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106 +#endif /* EGL_IMG_image_plane_attribs */ + +#ifndef EGL_MESA_drm_image +#define EGL_MESA_drm_image 1 +#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 +#define EGL_DRM_BUFFER_USE_MESA 0x31D1 +#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 +#define EGL_DRM_BUFFER_MESA 0x31D3 +#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 +#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 +#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 +#define EGL_DRM_BUFFER_USE_CURSOR_MESA 0x00000004 +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); +#endif +#endif /* EGL_MESA_drm_image */ + +#ifndef EGL_MESA_image_dma_buf_export +#define EGL_MESA_image_dma_buf_export 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers); +EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets); +#endif +#endif /* EGL_MESA_image_dma_buf_export */ + +#ifndef EGL_MESA_platform_gbm +#define EGL_MESA_platform_gbm 1 +#define EGL_PLATFORM_GBM_MESA 0x31D7 +#endif /* EGL_MESA_platform_gbm */ + +#ifndef EGL_MESA_platform_surfaceless +#define EGL_MESA_platform_surfaceless 1 +#define EGL_PLATFORM_SURFACELESS_MESA 0x31DD +#endif /* EGL_MESA_platform_surfaceless */ + +#ifndef EGL_MESA_query_driver +#define EGL_MESA_query_driver 1 +typedef char *(EGLAPIENTRYP PFNEGLGETDISPLAYDRIVERCONFIGPROC) (EGLDisplay dpy); +typedef const char *(EGLAPIENTRYP PFNEGLGETDISPLAYDRIVERNAMEPROC) (EGLDisplay dpy); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI char *EGLAPIENTRY eglGetDisplayDriverConfig (EGLDisplay dpy); +EGLAPI const char *EGLAPIENTRY eglGetDisplayDriverName (EGLDisplay dpy); +#endif +#endif /* EGL_MESA_query_driver */ + +#ifndef EGL_NOK_swap_region +#define EGL_NOK_swap_region 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#endif +#endif /* EGL_NOK_swap_region */ + +#ifndef EGL_NOK_swap_region2 +#define EGL_NOK_swap_region2 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#endif +#endif /* EGL_NOK_swap_region2 */ + +#ifndef EGL_NOK_texture_from_pixmap +#define EGL_NOK_texture_from_pixmap 1 +#define EGL_Y_INVERTED_NOK 0x307F +#endif /* EGL_NOK_texture_from_pixmap */ + +#ifndef EGL_NV_3dvision_surface +#define EGL_NV_3dvision_surface 1 +#define EGL_AUTO_STEREO_NV 0x3136 +#endif /* EGL_NV_3dvision_surface */ + +#ifndef EGL_NV_context_priority_realtime +#define EGL_NV_context_priority_realtime 1 +#define EGL_CONTEXT_PRIORITY_REALTIME_NV 0x3357 +#endif /* EGL_NV_context_priority_realtime */ + +#ifndef EGL_NV_coverage_sample +#define EGL_NV_coverage_sample 1 +#define EGL_COVERAGE_BUFFERS_NV 0x30E0 +#define EGL_COVERAGE_SAMPLES_NV 0x30E1 +#endif /* EGL_NV_coverage_sample */ + +#ifndef EGL_NV_coverage_sample_resolve +#define EGL_NV_coverage_sample_resolve 1 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 +#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 +#endif /* EGL_NV_coverage_sample_resolve */ + +#ifndef EGL_NV_cuda_event +#define EGL_NV_cuda_event 1 +#define EGL_CUDA_EVENT_HANDLE_NV 0x323B +#define EGL_SYNC_CUDA_EVENT_NV 0x323C +#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D +#endif /* EGL_NV_cuda_event */ + +#ifndef EGL_NV_depth_nonlinear +#define EGL_NV_depth_nonlinear 1 +#define EGL_DEPTH_ENCODING_NV 0x30E2 +#define EGL_DEPTH_ENCODING_NONE_NV 0 +#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 +#endif /* EGL_NV_depth_nonlinear */ + +#ifndef EGL_NV_device_cuda +#define EGL_NV_device_cuda 1 +#define EGL_CUDA_DEVICE_NV 0x323A +#endif /* EGL_NV_device_cuda */ + +#ifndef EGL_NV_native_query +#define EGL_NV_native_query 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#endif +#endif /* EGL_NV_native_query */ + +#ifndef EGL_NV_post_convert_rounding +#define EGL_NV_post_convert_rounding 1 +#endif /* EGL_NV_post_convert_rounding */ + +#ifndef EGL_NV_post_sub_buffer +#define EGL_NV_post_sub_buffer 1 +#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE +typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#endif +#endif /* EGL_NV_post_sub_buffer */ + +#ifndef EGL_NV_quadruple_buffer +#define EGL_NV_quadruple_buffer 1 +#define EGL_QUADRUPLE_BUFFER_NV 0x3231 +#endif /* EGL_NV_quadruple_buffer */ + +#ifndef EGL_NV_robustness_video_memory_purge +#define EGL_NV_robustness_video_memory_purge 1 +#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C +#endif /* EGL_NV_robustness_video_memory_purge */ + +#ifndef EGL_NV_stream_consumer_eglimage +#define EGL_NV_stream_consumer_eglimage 1 +#define EGL_STREAM_CONSUMER_IMAGE_NV 0x3373 +#define EGL_STREAM_IMAGE_ADD_NV 0x3374 +#define EGL_STREAM_IMAGE_REMOVE_NV 0x3375 +#define EGL_STREAM_IMAGE_AVAILABLE_NV 0x3376 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMIMAGECONSUMERCONNECTNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint num_modifiers, EGLuint64KHR *modifiers, EGLAttrib *attrib_list); +typedef EGLint (EGLAPIENTRYP PFNEGLQUERYSTREAMCONSUMEREVENTNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLTime timeout, EGLenum *event, EGLAttrib *aux); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMACQUIREIMAGENVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLImage *pImage, EGLSync sync); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMRELEASEIMAGENVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLImage image, EGLSync sync); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamImageConsumerConnectNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint num_modifiers, EGLuint64KHR *modifiers, EGLAttrib *attrib_list); +EGLAPI EGLint EGLAPIENTRY eglQueryStreamConsumerEventNV (EGLDisplay dpy, EGLStreamKHR stream, EGLTime timeout, EGLenum *event, EGLAttrib *aux); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamAcquireImageNV (EGLDisplay dpy, EGLStreamKHR stream, EGLImage *pImage, EGLSync sync); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamReleaseImageNV (EGLDisplay dpy, EGLStreamKHR stream, EGLImage image, EGLSync sync); +#endif +#endif /* EGL_NV_stream_consumer_eglimage */ + +#ifndef EGL_NV_stream_consumer_gltexture_yuv +#define EGL_NV_stream_consumer_gltexture_yuv 1 +#define EGL_YUV_PLANE0_TEXTURE_UNIT_NV 0x332C +#define EGL_YUV_PLANE1_TEXTURE_UNIT_NV 0x332D +#define EGL_YUV_PLANE2_TEXTURE_UNIT_NV 0x332E +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); +#endif +#endif /* EGL_NV_stream_consumer_gltexture_yuv */ + +#ifndef EGL_NV_stream_cross_display +#define EGL_NV_stream_cross_display 1 +#define EGL_STREAM_CROSS_DISPLAY_NV 0x334E +#endif /* EGL_NV_stream_cross_display */ + +#ifndef EGL_NV_stream_cross_object +#define EGL_NV_stream_cross_object 1 +#define EGL_STREAM_CROSS_OBJECT_NV 0x334D +#endif /* EGL_NV_stream_cross_object */ + +#ifndef EGL_NV_stream_cross_partition +#define EGL_NV_stream_cross_partition 1 +#define EGL_STREAM_CROSS_PARTITION_NV 0x323F +#endif /* EGL_NV_stream_cross_partition */ + +#ifndef EGL_NV_stream_cross_process +#define EGL_NV_stream_cross_process 1 +#define EGL_STREAM_CROSS_PROCESS_NV 0x3245 +#endif /* EGL_NV_stream_cross_process */ + +#ifndef EGL_NV_stream_cross_system +#define EGL_NV_stream_cross_system 1 +#define EGL_STREAM_CROSS_SYSTEM_NV 0x334F +#endif /* EGL_NV_stream_cross_system */ + +#ifndef EGL_NV_stream_dma +#define EGL_NV_stream_dma 1 +#define EGL_STREAM_DMA_NV 0x3371 +#define EGL_STREAM_DMA_SERVER_NV 0x3372 +#endif /* EGL_NV_stream_dma */ + +#ifndef EGL_NV_stream_fifo_next +#define EGL_NV_stream_fifo_next 1 +#define EGL_PENDING_FRAME_NV 0x3329 +#define EGL_STREAM_TIME_PENDING_NV 0x332A +#endif /* EGL_NV_stream_fifo_next */ + +#ifndef EGL_NV_stream_fifo_synchronous +#define EGL_NV_stream_fifo_synchronous 1 +#define EGL_STREAM_FIFO_SYNCHRONOUS_NV 0x3336 +#endif /* EGL_NV_stream_fifo_synchronous */ + +#ifndef EGL_NV_stream_flush +#define EGL_NV_stream_flush 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMFLUSHNVPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamFlushNV (EGLDisplay dpy, EGLStreamKHR stream); +#endif +#endif /* EGL_NV_stream_flush */ + +#ifndef EGL_NV_stream_frame_limits +#define EGL_NV_stream_frame_limits 1 +#define EGL_PRODUCER_MAX_FRAME_HINT_NV 0x3337 +#define EGL_CONSUMER_MAX_FRAME_HINT_NV 0x3338 +#endif /* EGL_NV_stream_frame_limits */ + +#ifndef EGL_NV_stream_metadata +#define EGL_NV_stream_metadata 1 +#define EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250 +#define EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251 +#define EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252 +#define EGL_PRODUCER_METADATA_NV 0x3253 +#define EGL_CONSUMER_METADATA_NV 0x3254 +#define EGL_PENDING_METADATA_NV 0x3328 +#define EGL_METADATA0_SIZE_NV 0x3255 +#define EGL_METADATA1_SIZE_NV 0x3256 +#define EGL_METADATA2_SIZE_NV 0x3257 +#define EGL_METADATA3_SIZE_NV 0x3258 +#define EGL_METADATA0_TYPE_NV 0x3259 +#define EGL_METADATA1_TYPE_NV 0x325A +#define EGL_METADATA2_TYPE_NV 0x325B +#define EGL_METADATA3_TYPE_NV 0x325C +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBNVPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribNV (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data); +#endif +#endif /* EGL_NV_stream_metadata */ + +#ifndef EGL_NV_stream_origin +#define EGL_NV_stream_origin 1 +#define EGL_STREAM_FRAME_ORIGIN_X_NV 0x3366 +#define EGL_STREAM_FRAME_ORIGIN_Y_NV 0x3367 +#define EGL_STREAM_FRAME_MAJOR_AXIS_NV 0x3368 +#define EGL_CONSUMER_AUTO_ORIENTATION_NV 0x3369 +#define EGL_PRODUCER_AUTO_ORIENTATION_NV 0x336A +#define EGL_LEFT_NV 0x336B +#define EGL_RIGHT_NV 0x336C +#define EGL_TOP_NV 0x336D +#define EGL_BOTTOM_NV 0x336E +#define EGL_X_AXIS_NV 0x336F +#define EGL_Y_AXIS_NV 0x3370 +#endif /* EGL_NV_stream_origin */ + +#ifndef EGL_NV_stream_remote +#define EGL_NV_stream_remote 1 +#define EGL_STREAM_STATE_INITIALIZING_NV 0x3240 +#define EGL_STREAM_TYPE_NV 0x3241 +#define EGL_STREAM_PROTOCOL_NV 0x3242 +#define EGL_STREAM_ENDPOINT_NV 0x3243 +#define EGL_STREAM_LOCAL_NV 0x3244 +#define EGL_STREAM_PRODUCER_NV 0x3247 +#define EGL_STREAM_CONSUMER_NV 0x3248 +#define EGL_STREAM_PROTOCOL_FD_NV 0x3246 +#endif /* EGL_NV_stream_remote */ + +#ifndef EGL_NV_stream_reset +#define EGL_NV_stream_reset 1 +#define EGL_SUPPORT_RESET_NV 0x3334 +#define EGL_SUPPORT_REUSE_NV 0x3335 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLRESETSTREAMNVPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglResetStreamNV (EGLDisplay dpy, EGLStreamKHR stream); +#endif +#endif /* EGL_NV_stream_reset */ + +#ifndef EGL_NV_stream_socket +#define EGL_NV_stream_socket 1 +#define EGL_STREAM_PROTOCOL_SOCKET_NV 0x324B +#define EGL_SOCKET_HANDLE_NV 0x324C +#define EGL_SOCKET_TYPE_NV 0x324D +#endif /* EGL_NV_stream_socket */ + +#ifndef EGL_NV_stream_socket_inet +#define EGL_NV_stream_socket_inet 1 +#define EGL_SOCKET_TYPE_INET_NV 0x324F +#endif /* EGL_NV_stream_socket_inet */ + +#ifndef EGL_NV_stream_socket_unix +#define EGL_NV_stream_socket_unix 1 +#define EGL_SOCKET_TYPE_UNIX_NV 0x324E +#endif /* EGL_NV_stream_socket_unix */ + +#ifndef EGL_NV_stream_sync +#define EGL_NV_stream_sync 1 +#define EGL_SYNC_NEW_FRAME_NV 0x321F +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); +#endif +#endif /* EGL_NV_stream_sync */ + +#ifndef EGL_NV_sync +#define EGL_NV_sync 1 +typedef void *EGLSyncNV; +typedef khronos_utime_nanoseconds_t EGLTimeNV; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 +#define EGL_SYNC_STATUS_NV 0x30E7 +#define EGL_SIGNALED_NV 0x30E8 +#define EGL_UNSIGNALED_NV 0x30E9 +#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 +#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull +#define EGL_ALREADY_SIGNALED_NV 0x30EA +#define EGL_TIMEOUT_EXPIRED_NV 0x30EB +#define EGL_CONDITION_SATISFIED_NV 0x30EC +#define EGL_SYNC_TYPE_NV 0x30ED +#define EGL_SYNC_CONDITION_NV 0x30EE +#define EGL_SYNC_FENCE_NV 0x30EF +#define EGL_NO_SYNC_NV EGL_CAST(EGLSyncNV,0) +typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync); +EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_sync */ + +#ifndef EGL_NV_system_time +#define EGL_NV_system_time 1 +typedef khronos_utime_nanoseconds_t EGLuint64NV; +#ifdef KHRONOS_SUPPORT_INT64 +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void); +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_system_time */ + +#ifndef EGL_NV_triple_buffer +#define EGL_NV_triple_buffer 1 +#define EGL_TRIPLE_BUFFER_NV 0x3230 +#endif /* EGL_NV_triple_buffer */ + +#ifndef EGL_TIZEN_image_native_buffer +#define EGL_TIZEN_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_TIZEN 0x32A0 +#endif /* EGL_TIZEN_image_native_buffer */ + +#ifndef EGL_TIZEN_image_native_surface +#define EGL_TIZEN_image_native_surface 1 +#define EGL_NATIVE_SURFACE_TIZEN 0x32A1 +#endif /* EGL_TIZEN_image_native_surface */ + +#ifndef EGL_WL_bind_wayland_display +#define EGL_WL_bind_wayland_display 1 +#define PFNEGLBINDWAYLANDDISPLAYWL PFNEGLBINDWAYLANDDISPLAYWLPROC +#define PFNEGLUNBINDWAYLANDDISPLAYWL PFNEGLUNBINDWAYLANDDISPLAYWLPROC +#define PFNEGLQUERYWAYLANDBUFFERWL PFNEGLQUERYWAYLANDBUFFERWLPROC +struct wl_display; +struct wl_resource; +#define EGL_WAYLAND_BUFFER_WL 0x31D5 +#define EGL_WAYLAND_PLANE_WL 0x31D6 +#define EGL_TEXTURE_Y_U_V_WL 0x31D7 +#define EGL_TEXTURE_Y_UV_WL 0x31D8 +#define EGL_TEXTURE_Y_XUXV_WL 0x31D9 +#define EGL_TEXTURE_EXTERNAL_WL 0x31DA +#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB +typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWLPROC) (EGLDisplay dpy, struct wl_display *display); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWLPROC) (EGLDisplay dpy, struct wl_display *display); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWLPROC) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL (EGLDisplay dpy, struct wl_display *display); +EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL (EGLDisplay dpy, struct wl_display *display); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); +#endif +#endif /* EGL_WL_bind_wayland_display */ + +#ifndef EGL_WL_create_wayland_buffer_from_image +#define EGL_WL_create_wayland_buffer_from_image 1 +#define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC +struct wl_buffer; +typedef struct wl_buffer *(EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC) (EGLDisplay dpy, EGLImageKHR image); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI struct wl_buffer *EGLAPIENTRY eglCreateWaylandBufferFromImageWL (EGLDisplay dpy, EGLImageKHR image); +#endif +#endif /* EGL_WL_create_wayland_buffer_from_image */ + +#ifdef __cplusplus +} +#endif + +#endif /* __eglext_h_ */ + +#endif /* _MSC_VER */ diff --git a/external/SDL2/SDL_endian.h b/external/SDL2/SDL_endian.h index a1a11df..53f6c2b 100644 --- a/external/SDL2/SDL_endian.h +++ b/external/SDL2/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,158 +21,105 @@ /** * \file SDL_endian.h - * + * * Functions for reading and writing endian-specific values */ -#ifndef _SDL_endian_h -#define _SDL_endian_h +#ifndef SDL_endian_h_ +#define SDL_endian_h_ #include "SDL_stdinc.h" +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version, + so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */ +#ifdef __clang__ +#ifndef __PRFCHWINTRIN_H +#define __PRFCHWINTRIN_H +static __inline__ void __attribute__((__always_inline__, __nodebug__)) +_m_prefetch(void *__P) +{ + __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */); +} +#endif /* __PRFCHWINTRIN_H */ +#endif /* __clang__ */ + +#include +#endif + /** * \name The two types of endianness */ -/*@{*/ -#define SDL_LIL_ENDIAN 1234 -#define SDL_BIG_ENDIAN 4321 -/*@}*/ +/* @{ */ +#define SDL_LIL_ENDIAN 1234 +#define SDL_BIG_ENDIAN 4321 +/* @} */ #ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */ #ifdef __linux__ #include #define SDL_BYTEORDER __BYTE_ORDER -#else /* __linux __ */ +#elif defined(__OpenBSD__) +#include +#define SDL_BYTEORDER BYTE_ORDER +#elif defined(__FreeBSD__) || defined(__NetBSD__) +#include +#define SDL_BYTEORDER BYTE_ORDER +#else #if defined(__hppa__) || \ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ - (defined(__MIPS__) && defined(__MISPEB__)) || \ + (defined(__MIPS__) && defined(__MIPSEB__)) || \ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ defined(__sparc__) -#define SDL_BYTEORDER SDL_BIG_ENDIAN +#define SDL_BYTEORDER SDL_BIG_ENDIAN #else -#define SDL_BYTEORDER SDL_LIL_ENDIAN +#define SDL_BYTEORDER SDL_LIL_ENDIAN #endif -#endif /* __linux __ */ +#endif /* __linux__ */ #endif /* !SDL_BYTEORDER */ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \file SDL_endian.h */ -#if defined(__GNUC__) && defined(__i386__) && \ - !(__GNUC__ == 2 && __GNUC_MINOR__ == 95 /* broken gcc version */) -SDL_FORCE_INLINE Uint16 -SDL_Swap16(Uint16 x) -{ - __asm__("xchgb %b0,%h0": "=q"(x):"0"(x)); - return x; -} -#elif defined(__GNUC__) && defined(__x86_64__) -SDL_FORCE_INLINE Uint16 -SDL_Swap16(Uint16 x) -{ - __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x)); - return x; -} -#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) -SDL_FORCE_INLINE Uint16 -SDL_Swap16(Uint16 x) -{ - int result; - __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x)); - return (Uint16)result; -} -#elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__)) && !defined(__mcoldfire__) -SDL_FORCE_INLINE Uint16 -SDL_Swap16(Uint16 x) -{ - __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc"); - return x; -} +/* various modern compilers may have builtin swap */ +#if defined(__GNUC__) || defined(__clang__) +# define HAS_BUILTIN_BSWAP16 (_SDL_HAS_BUILTIN(__builtin_bswap16)) || \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +# define HAS_BUILTIN_BSWAP32 (_SDL_HAS_BUILTIN(__builtin_bswap32)) || \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +# define HAS_BUILTIN_BSWAP64 (_SDL_HAS_BUILTIN(__builtin_bswap64)) || \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + + /* this one is broken */ +# define HAS_BROKEN_BSWAP (__GNUC__ == 2 && __GNUC_MINOR__ <= 95) #else +# define HAS_BUILTIN_BSWAP16 0 +# define HAS_BUILTIN_BSWAP32 0 +# define HAS_BUILTIN_BSWAP64 0 +# define HAS_BROKEN_BSWAP 0 +#endif + SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) { return SDL_static_cast(Uint16, ((x << 8) | (x >> 8))); } -#endif -#if defined(__GNUC__) && defined(__i386__) -SDL_FORCE_INLINE Uint32 -SDL_Swap32(Uint32 x) -{ - __asm__("bswap %0": "=r"(x):"0"(x)); - return x; -} -#elif defined(__GNUC__) && defined(__x86_64__) -SDL_FORCE_INLINE Uint32 -SDL_Swap32(Uint32 x) -{ - __asm__("bswapl %0": "=r"(x):"0"(x)); - return x; -} -#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) -SDL_FORCE_INLINE Uint32 -SDL_Swap32(Uint32 x) -{ - Uint32 result; - - __asm__("rlwimi %0,%2,24,16,23": "=&r"(result):"0"(x >> 24), "r"(x)); - __asm__("rlwimi %0,%2,8,8,15": "=&r"(result):"0"(result), "r"(x)); - __asm__("rlwimi %0,%2,24,0,7": "=&r"(result):"0"(result), "r"(x)); - return result; -} -#elif defined(__GNUC__) && (defined(__M68000__) || defined(__M68020__)) && !defined(__mcoldfire__) -SDL_FORCE_INLINE Uint32 -SDL_Swap32(Uint32 x) -{ - __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc"); - return x; -} -#else SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24))); } -#endif -#if defined(__GNUC__) && defined(__i386__) -SDL_FORCE_INLINE Uint64 -SDL_Swap64(Uint64 x) -{ - union - { - struct - { - Uint32 a, b; - } s; - Uint64 u; - } v; - v.u = x; - __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1": "=r"(v.s.a), "=r"(v.s.b):"0"(v.s.a), - "1"(v.s. - b)); - return v.u; -} -#elif defined(__GNUC__) && defined(__x86_64__) -SDL_FORCE_INLINE Uint64 -SDL_Swap64(Uint64 x) -{ - __asm__("bswapq %0": "=r"(x):"0"(x)); - return x; -} -#else SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) { @@ -187,14 +134,11 @@ SDL_Swap64(Uint64 x) x |= SDL_Swap32(hi); return (x); } -#endif - SDL_FORCE_INLINE float SDL_SwapFloat(float x) { - union - { + union { float f; Uint32 ui32; } swapper; @@ -203,41 +147,44 @@ SDL_SwapFloat(float x) return swapper.f; } +/* remove extra macros */ +#undef HAS_BROKEN_BSWAP +#undef HAS_BUILTIN_BSWAP16 +#undef HAS_BUILTIN_BSWAP32 +#undef HAS_BUILTIN_BSWAP64 /** * \name Swap to native * Byteswap item from the specified endianness to the native endianness. */ -/*@{*/ +/* @{ */ #if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define SDL_SwapLE16(X) (X) -#define SDL_SwapLE32(X) (X) -#define SDL_SwapLE64(X) (X) -#define SDL_SwapFloatLE(X) (X) -#define SDL_SwapBE16(X) SDL_Swap16(X) -#define SDL_SwapBE32(X) SDL_Swap32(X) -#define SDL_SwapBE64(X) SDL_Swap64(X) -#define SDL_SwapFloatBE(X) SDL_SwapFloat(X) +#define SDL_SwapLE16(X) (X) +#define SDL_SwapLE32(X) (X) +#define SDL_SwapLE64(X) (X) +#define SDL_SwapFloatLE(X) (X) +#define SDL_SwapBE16(X) SDL_Swap16(X) +#define SDL_SwapBE32(X) SDL_Swap32(X) +#define SDL_SwapBE64(X) SDL_Swap64(X) +#define SDL_SwapFloatBE(X) SDL_SwapFloat(X) #else -#define SDL_SwapLE16(X) SDL_Swap16(X) -#define SDL_SwapLE32(X) SDL_Swap32(X) -#define SDL_SwapLE64(X) SDL_Swap64(X) -#define SDL_SwapFloatLE(X) SDL_SwapFloat(X) -#define SDL_SwapBE16(X) (X) -#define SDL_SwapBE32(X) (X) -#define SDL_SwapBE64(X) (X) -#define SDL_SwapFloatBE(X) (X) +#define SDL_SwapLE16(X) SDL_Swap16(X) +#define SDL_SwapLE32(X) SDL_Swap32(X) +#define SDL_SwapLE64(X) SDL_Swap64(X) +#define SDL_SwapFloatLE(X) SDL_SwapFloat(X) +#define SDL_SwapBE16(X) (X) +#define SDL_SwapBE32(X) (X) +#define SDL_SwapBE64(X) (X) +#define SDL_SwapFloatBE(X) (X) #endif -/*@}*//*Swap to native*/ +/* @} *//* Swap to native */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_endian_h */ +#endif /* SDL_endian_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_error.h b/external/SDL2/SDL_error.h index 81c64da..5c961e4 100644 --- a/external/SDL2/SDL_error.h +++ b/external/SDL2/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,39 +21,124 @@ /** * \file SDL_error.h - * + * * Simple error message routines for SDL. */ -#ifndef _SDL_error_h -#define _SDL_error_h +#ifndef SDL_error_h_ +#define SDL_error_h_ #include "SDL_stdinc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* Public functions */ -/* SDL_SetError() unconditionally returns -1. */ -extern DECLSPEC int SDLCALL SDL_SetError(const char *fmt, ...); + + +/** + * Set the SDL error message for the current thread. + * + * Calling this function will replace any previous error message that was set. + * + * This function always returns -1, since SDL frequently uses -1 to signify an + * failing result, leading to this idiom: + * + * ```c + * if (error_code) { + * return SDL_SetError("This operation has failed: %d", error_code); + * } + * ``` + * + * \param fmt a printf()-style message format string + * \param ... additional parameters matching % tokens in the `fmt` string, if + * any + * \returns always -1. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ClearError + * \sa SDL_GetError + */ +extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); + +/** + * Retrieve a message about the last error that occurred on the current + * thread. + * + * It is possible for multiple errors to occur before calling SDL_GetError(). + * Only the last error is returned. + * + * The message is only applicable when an SDL function has signaled an error. + * You must check the return values of SDL function calls to determine when to + * appropriately call SDL_GetError(). You should *not* use the results of + * SDL_GetError() to decide if an error has occurred! Sometimes SDL will set + * an error string even when reporting success. + * + * SDL will *not* clear the error string for successful API calls. You *must* + * check return values for failure cases before you can assume the error + * string applies. + * + * Error strings are set per-thread, so an error set in a different thread + * will not interfere with the current thread's operation. + * + * The returned string is internally allocated and must not be freed by the + * application. + * + * \returns a message with information about the specific error that occurred, + * or an empty string if there hasn't been an error message set since + * the last call to SDL_ClearError(). The message is only applicable + * when an SDL function has signaled an error. You must check the + * return values of SDL function calls to determine when to + * appropriately call SDL_GetError(). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ClearError + * \sa SDL_SetError + */ extern DECLSPEC const char *SDLCALL SDL_GetError(void); + +/** + * Get the last error message that was set for the current thread. + * + * This allows the caller to copy the error string into a provided buffer, but + * otherwise operates exactly the same as SDL_GetError(). + * + * \param errstr A buffer to fill with the last error message that was set for + * the current thread + * \param maxlen The size of the buffer pointed to by the errstr parameter + * \returns the pointer passed in as the `errstr` parameter. + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_GetError + */ +extern DECLSPEC char * SDLCALL SDL_GetErrorMsg(char *errstr, int maxlen); + +/** + * Clear any previous error message for this thread. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetError + * \sa SDL_SetError + */ extern DECLSPEC void SDLCALL SDL_ClearError(void); /** * \name Internal error functions - * - * \internal + * + * \internal * Private error reporting function - used internally. */ -/*@{*/ -#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM) -#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED) -#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param)) +/* @{ */ +#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM) +#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED) +#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param)) typedef enum { SDL_ENOMEM, @@ -65,16 +150,14 @@ typedef enum } SDL_errorcode; /* SDL_Error() unconditionally returns -1. */ extern DECLSPEC int SDLCALL SDL_Error(SDL_errorcode code); -/*@}*//*Internal error functions*/ +/* @} *//* Internal error functions */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_error_h */ +#endif /* SDL_error_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_events.h b/external/SDL2/SDL_events.h index 205467e..3722a63 100644 --- a/external/SDL2/SDL_events.h +++ b/external/SDL2/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_events.h - * + * * Include file for SDL event handling. */ -#ifndef _SDL_events_h -#define _SDL_events_h +#ifndef SDL_events_h_ +#define SDL_events_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -42,17 +42,15 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* General keyboard/mouse state definitions */ -#define SDL_RELEASED 0 -#define SDL_PRESSED 1 +#define SDL_RELEASED 0 +#define SDL_PRESSED 1 /** - * \brief The types of events that can be delivered. + * The types of events that can be delivered. */ typedef enum { @@ -61,6 +59,37 @@ typedef enum /* Application events */ SDL_QUIT = 0x100, /**< User-requested quit */ + /* These application events have special meaning on iOS, see README-ios.md for details */ + SDL_APP_TERMINATING, /**< The application is being terminated by the OS + Called on iOS in applicationWillTerminate() + Called on Android in onDestroy() + */ + SDL_APP_LOWMEMORY, /**< The application is low on memory, free memory if possible. + Called on iOS in applicationDidReceiveMemoryWarning() + Called on Android in onLowMemory() + */ + SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background + Called on iOS in applicationWillResignActive() + Called on Android in onPause() + */ + SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time + Called on iOS in applicationDidEnterBackground() + Called on Android in onPause() + */ + SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground + Called on iOS in applicationWillEnterForeground() + Called on Android in onResume() + */ + SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive + Called on iOS in applicationDidBecomeActive() + Called on Android in onResume() + */ + + SDL_LOCALECHANGED, /**< The user's locale preferences have changed. */ + + /* Display events */ + SDL_DISPLAYEVENT = 0x150, /**< Display state change */ + /* Window events */ SDL_WINDOWEVENT = 0x200, /**< Window state change */ SDL_SYSWMEVENT, /**< System specific event */ @@ -70,6 +99,9 @@ typedef enum SDL_KEYUP, /**< Key released */ SDL_TEXTEDITING, /**< Keyboard text editing (composition) */ SDL_TEXTINPUT, /**< Keyboard text input */ + SDL_KEYMAPCHANGED, /**< Keymap changed due to a system event such as an + input language or keyboard layout change. + */ /* Mouse events */ SDL_MOUSEMOTION = 0x400, /**< Mouse moved */ @@ -86,13 +118,17 @@ typedef enum SDL_JOYDEVICEADDED, /**< A new joystick has been inserted into the system */ SDL_JOYDEVICEREMOVED, /**< An opened joystick has been removed */ - /* Game controller events */ - SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */ - SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */ - SDL_CONTROLLERBUTTONUP, /**< Game controller button released */ - SDL_CONTROLLERDEVICEADDED, /**< A new Game controller has been inserted into the system */ - SDL_CONTROLLERDEVICEREMOVED, /**< An opened Game controller has been removed */ - SDL_CONTROLLERDEVICEREMAPPED, /**< The controller mapping was updated */ + /* Game controller events */ + SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */ + SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */ + SDL_CONTROLLERBUTTONUP, /**< Game controller button released */ + SDL_CONTROLLERDEVICEADDED, /**< A new Game controller has been inserted into the system */ + SDL_CONTROLLERDEVICEREMOVED, /**< An opened Game controller has been removed */ + SDL_CONTROLLERDEVICEREMAPPED, /**< The controller mapping was updated */ + SDL_CONTROLLERTOUCHPADDOWN, /**< Game controller touchpad was touched */ + SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */ + SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */ + SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */ /* Touch events */ SDL_FINGERDOWN = 0x700, @@ -109,6 +145,23 @@ typedef enum /* Drag and drop events */ SDL_DROPFILE = 0x1000, /**< The system requests a file open */ + SDL_DROPTEXT, /**< text/plain drag-and-drop event */ + SDL_DROPBEGIN, /**< A new set of drops is beginning (NULL filename) */ + SDL_DROPCOMPLETE, /**< Current set of drops is now complete (NULL filename) */ + + /* Audio hotplug events */ + SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */ + SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */ + + /* Sensor events */ + SDL_SENSORUPDATE = 0x1200, /**< A sensor was updated */ + + /* Render events */ + SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */ + SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */ + + /* Internal events */ + SDL_POLLSENTINEL = 0x7F00, /**< Signals the end of an event poll cycle */ /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use, * and should be allocated with SDL_RegisterEvents() @@ -124,19 +177,34 @@ typedef enum /** * \brief Fields shared by every event */ -typedef struct SDL_GenericEvent +typedef struct SDL_CommonEvent { Uint32 type; - Uint32 timestamp; -} SDL_GenericEvent; - + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ +} SDL_CommonEvent; + +/** + * \brief Display state change event data (event.display.*) + */ +typedef struct SDL_DisplayEvent +{ + Uint32 type; /**< ::SDL_DISPLAYEVENT */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Uint32 display; /**< The associated display index */ + Uint8 event; /**< ::SDL_DisplayEventID */ + Uint8 padding1; + Uint8 padding2; + Uint8 padding3; + Sint32 data1; /**< event dependent data */ +} SDL_DisplayEvent; + /** * \brief Window state change event data (event.window.*) */ typedef struct SDL_WindowEvent { Uint32 type; /**< ::SDL_WINDOWEVENT */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The associated window */ Uint8 event; /**< ::SDL_WindowEventID */ Uint8 padding1; @@ -152,7 +220,7 @@ typedef struct SDL_WindowEvent typedef struct SDL_KeyboardEvent { Uint32 type; /**< ::SDL_KEYDOWN or ::SDL_KEYUP */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The window with keyboard focus, if any */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 repeat; /**< Non-zero if this is a key repeat */ @@ -168,7 +236,7 @@ typedef struct SDL_KeyboardEvent typedef struct SDL_TextEditingEvent { Uint32 type; /**< ::SDL_TEXTEDITING */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The window with keyboard focus, if any */ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */ Sint32 start; /**< The start cursor of selected editing text */ @@ -183,7 +251,7 @@ typedef struct SDL_TextEditingEvent typedef struct SDL_TextInputEvent { Uint32 type; /**< ::SDL_TEXTINPUT */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The window with keyboard focus, if any */ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */ } SDL_TextInputEvent; @@ -194,13 +262,10 @@ typedef struct SDL_TextInputEvent typedef struct SDL_MouseMotionEvent { Uint32 type; /**< ::SDL_MOUSEMOTION */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ - Uint8 state; /**< The current button state */ - Uint8 padding1; - Uint8 padding2; - Uint8 padding3; + Uint32 state; /**< The current button state */ Sint32 x; /**< X coordinate, relative to window */ Sint32 y; /**< Y coordinate, relative to window */ Sint32 xrel; /**< The relative motion in the X direction */ @@ -213,13 +278,13 @@ typedef struct SDL_MouseMotionEvent typedef struct SDL_MouseButtonEvent { Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint8 button; /**< The mouse button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ + Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */ Uint8 padding1; - Uint8 padding2; Sint32 x; /**< X coordinate, relative to window */ Sint32 y; /**< Y coordinate, relative to window */ } SDL_MouseButtonEvent; @@ -230,11 +295,14 @@ typedef struct SDL_MouseButtonEvent typedef struct SDL_MouseWheelEvent { Uint32 type; /**< ::SDL_MOUSEWHEEL */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ - Sint32 x; /**< The amount scrolled horizontally */ - Sint32 y; /**< The amount scrolled vertically */ + Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */ + Sint32 y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */ + Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */ + float preciseX; /**< The amount scrolled horizontally, positive to the right and negative to the left, with float precision (added in 2.0.18) */ + float preciseY; /**< The amount scrolled vertically, positive away from the user and negative toward the user, with float precision (added in 2.0.18) */ } SDL_MouseWheelEvent; /** @@ -243,7 +311,7 @@ typedef struct SDL_MouseWheelEvent typedef struct SDL_JoyAxisEvent { Uint32 type; /**< ::SDL_JOYAXISMOTION */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 axis; /**< The joystick axis index */ Uint8 padding1; @@ -259,7 +327,7 @@ typedef struct SDL_JoyAxisEvent typedef struct SDL_JoyBallEvent { Uint32 type; /**< ::SDL_JOYBALLMOTION */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 ball; /**< The joystick trackball index */ Uint8 padding1; @@ -275,14 +343,14 @@ typedef struct SDL_JoyBallEvent typedef struct SDL_JoyHatEvent { Uint32 type; /**< ::SDL_JOYHATMOTION */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 hat; /**< The joystick hat index */ Uint8 value; /**< The hat position value. * \sa ::SDL_HAT_LEFTUP ::SDL_HAT_UP ::SDL_HAT_RIGHTUP * \sa ::SDL_HAT_LEFT ::SDL_HAT_CENTERED ::SDL_HAT_RIGHT * \sa ::SDL_HAT_LEFTDOWN ::SDL_HAT_DOWN ::SDL_HAT_RIGHTDOWN - * + * * Note that zero means the POV is centered. */ Uint8 padding1; @@ -295,7 +363,7 @@ typedef struct SDL_JoyHatEvent typedef struct SDL_JoyButtonEvent { Uint32 type; /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 button; /**< The joystick button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ @@ -308,9 +376,9 @@ typedef struct SDL_JoyButtonEvent */ typedef struct SDL_JoyDeviceEvent { - Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */ - Uint32 timestamp; - Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */ + Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */ } SDL_JoyDeviceEvent; @@ -320,7 +388,7 @@ typedef struct SDL_JoyDeviceEvent typedef struct SDL_ControllerAxisEvent { Uint32 type; /**< ::SDL_CONTROLLERAXISMOTION */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */ Uint8 padding1; @@ -337,7 +405,7 @@ typedef struct SDL_ControllerAxisEvent typedef struct SDL_ControllerButtonEvent { Uint32 type; /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 button; /**< The controller button (SDL_GameControllerButton) */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ @@ -351,11 +419,52 @@ typedef struct SDL_ControllerButtonEvent */ typedef struct SDL_ControllerDeviceEvent { - Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ - Uint32 timestamp; - Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ + Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ } SDL_ControllerDeviceEvent; +/** + * \brief Game controller touchpad event structure (event.ctouchpad.*) + */ +typedef struct SDL_ControllerTouchpadEvent +{ + Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + SDL_JoystickID which; /**< The joystick instance id */ + Sint32 touchpad; /**< The index of the touchpad */ + Sint32 finger; /**< The index of the finger on the touchpad */ + float x; /**< Normalized in the range 0...1 with 0 being on the left */ + float y; /**< Normalized in the range 0...1 with 0 being at the top */ + float pressure; /**< Normalized in the range 0...1 */ +} SDL_ControllerTouchpadEvent; + +/** + * \brief Game controller sensor event structure (event.csensor.*) + */ +typedef struct SDL_ControllerSensorEvent +{ + Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + SDL_JoystickID which; /**< The joystick instance id */ + Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */ + float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */ +} SDL_ControllerSensorEvent; + +/** + * \brief Audio device event structure (event.adevice.*) + */ +typedef struct SDL_AudioDeviceEvent +{ + Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */ + Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */ + Uint8 padding1; + Uint8 padding2; + Uint8 padding3; +} SDL_AudioDeviceEvent; + /** * \brief Touch finger event structure (event.tfinger.*) @@ -363,14 +472,15 @@ typedef struct SDL_ControllerDeviceEvent typedef struct SDL_TouchFingerEvent { Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_TouchID touchId; /**< The touch device id */ SDL_FingerID fingerId; float x; /**< Normalized in the range 0...1 */ float y; /**< Normalized in the range 0...1 */ - float dx; /**< Normalized in the range 0...1 */ - float dy; /**< Normalized in the range 0...1 */ + float dx; /**< Normalized in the range -1...1 */ + float dy; /**< Normalized in the range -1...1 */ float pressure; /**< Normalized in the range 0...1 */ + Uint32 windowID; /**< The window underneath the finger, if any */ } SDL_TouchFingerEvent; @@ -380,22 +490,24 @@ typedef struct SDL_TouchFingerEvent typedef struct SDL_MultiGestureEvent { Uint32 type; /**< ::SDL_MULTIGESTURE */ - Uint32 timestamp; - SDL_TouchID touchId; /**< The touch device index */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + SDL_TouchID touchId; /**< The touch device id */ float dTheta; float dDist; float x; - float y; + float y; Uint16 numFingers; Uint16 padding; } SDL_MultiGestureEvent; -/* (event.dgesture.*) */ +/** + * \brief Dollar Gesture Event (event.dgesture.*) + */ typedef struct SDL_DollarGestureEvent { - Uint32 type; /**< ::SDL_DOLLARGESTURE */ - Uint32 timestamp; + Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_TouchID touchId; /**< The touch device id */ SDL_GestureID gestureId; Uint32 numFingers; @@ -407,34 +519,54 @@ typedef struct SDL_DollarGestureEvent /** * \brief An event used to request a file open by the system (event.drop.*) - * This event is disabled by default, you can enable it with SDL_EventState() - * \note If you enable this event, you must free the filename in the event. + * This event is enabled by default, you can disable it with SDL_EventState(). + * \note If this event is enabled, you must free the filename in the event. */ typedef struct SDL_DropEvent { - Uint32 type; /**< ::SDL_DROPFILE */ - Uint32 timestamp; - char *file; /**< The file name, which should be freed with SDL_free() */ + Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */ + Uint32 windowID; /**< The window that was dropped on, if any */ } SDL_DropEvent; +/** + * \brief Sensor event structure (event.sensor.*) + */ +typedef struct SDL_SensorEvent +{ + Uint32 type; /**< ::SDL_SENSORUPDATE */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ + Sint32 which; /**< The instance ID of the sensor */ + float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */ +} SDL_SensorEvent; + /** * \brief The "quit requested" event */ typedef struct SDL_QuitEvent { Uint32 type; /**< ::SDL_QUIT */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ } SDL_QuitEvent; +/** + * \brief OS Specific event + */ +typedef struct SDL_OSEvent +{ + Uint32 type; /**< ::SDL_QUIT */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ +} SDL_OSEvent; /** * \brief A user-defined event type (event.user.*) */ typedef struct SDL_UserEvent { - Uint32 type; /**< ::SDL_USEREVENT through ::SDL_NUMEVENTS-1 */ - Uint32 timestamp; + Uint32 type; /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 windowID; /**< The associated window if any */ Sint32 code; /**< User defined event code */ void *data1; /**< User defined data pointer */ @@ -454,7 +586,7 @@ typedef struct SDL_SysWMmsg SDL_SysWMmsg; typedef struct SDL_SysWMEvent { Uint32 type; /**< ::SDL_SYSWMEVENT */ - Uint32 timestamp; + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */ } SDL_SysWMEvent; @@ -463,54 +595,83 @@ typedef struct SDL_SysWMEvent */ typedef union SDL_Event { - Uint32 type; /**< Event type, shared with all events */ - SDL_GenericEvent generic; /**< Generic event data */ - SDL_WindowEvent window; /**< Window event data */ - SDL_KeyboardEvent key; /**< Keyboard event data */ - SDL_TextEditingEvent edit; /**< Text editing event data */ - SDL_TextInputEvent text; /**< Text input event data */ - SDL_MouseMotionEvent motion; /**< Mouse motion event data */ - SDL_MouseButtonEvent button; /**< Mouse button event data */ - SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */ - SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */ - SDL_JoyBallEvent jball; /**< Joystick ball event data */ - SDL_JoyHatEvent jhat; /**< Joystick hat event data */ - SDL_JoyButtonEvent jbutton; /**< Joystick button event data */ - SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */ - SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */ - SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */ - SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */ - SDL_QuitEvent quit; /**< Quit request event data */ - SDL_UserEvent user; /**< Custom event data */ - SDL_SysWMEvent syswm; /**< System dependent window event data */ - SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ - SDL_MultiGestureEvent mgesture; /**< Gesture event data */ - SDL_DollarGestureEvent dgesture; /**< Gesture event data */ - SDL_DropEvent drop; /**< Drag and drop event data */ + Uint32 type; /**< Event type, shared with all events */ + SDL_CommonEvent common; /**< Common event data */ + SDL_DisplayEvent display; /**< Display event data */ + SDL_WindowEvent window; /**< Window event data */ + SDL_KeyboardEvent key; /**< Keyboard event data */ + SDL_TextEditingEvent edit; /**< Text editing event data */ + SDL_TextInputEvent text; /**< Text input event data */ + SDL_MouseMotionEvent motion; /**< Mouse motion event data */ + SDL_MouseButtonEvent button; /**< Mouse button event data */ + SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */ + SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */ + SDL_JoyBallEvent jball; /**< Joystick ball event data */ + SDL_JoyHatEvent jhat; /**< Joystick hat event data */ + SDL_JoyButtonEvent jbutton; /**< Joystick button event data */ + SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */ + SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */ + SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */ + SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */ + SDL_ControllerTouchpadEvent ctouchpad; /**< Game Controller touchpad event data */ + SDL_ControllerSensorEvent csensor; /**< Game Controller sensor event data */ + SDL_AudioDeviceEvent adevice; /**< Audio device event data */ + SDL_SensorEvent sensor; /**< Sensor event data */ + SDL_QuitEvent quit; /**< Quit request event data */ + SDL_UserEvent user; /**< Custom event data */ + SDL_SysWMEvent syswm; /**< System dependent window event data */ + SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_MultiGestureEvent mgesture; /**< Gesture event data */ + SDL_DollarGestureEvent dgesture; /**< Gesture event data */ + SDL_DropEvent drop; /**< Drag and drop event data */ - /* This is necessary for ABI compatibility between Visual C++ and GCC - Visual C++ will respect the push pack pragma and use 52 bytes for - this structure, and GCC will use the alignment of the largest datatype - within the union, which is 8 bytes. + /* This is necessary for ABI compatibility between Visual C++ and GCC. + Visual C++ will respect the push pack pragma and use 52 bytes (size of + SDL_TextEditingEvent, the largest structure for 32-bit and 64-bit + architectures) for this union, and GCC will use the alignment of the + largest datatype within the union, which is 8 bytes on 64-bit + architectures. So... we'll add padding to force the size to be 56 bytes for both. + + On architectures where pointers are 16 bytes, this needs rounding up to + the next multiple of 16, 64, and on architectures where pointers are + even larger the size of SDL_UserEvent will dominate as being 3 pointers. */ - Uint8 padding[56]; + Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)]; } SDL_Event; +/* Make sure we haven't broken binary compatibility */ +SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding)); + /* Function prototypes */ /** - * Pumps the event loop, gathering events from the input devices. - * - * This function updates the event queue and internal input device state. - * - * This should only be run in the thread that sets the video mode. + * Pump the event loop, gathering events from the input devices. + * + * This function updates the event queue and internal input device state. + * + * **WARNING**: This should only be run in the thread that initialized the + * video subsystem, and for extra safety, you should consider only doing those + * things on the main thread in any case. + * + * SDL_PumpEvents() gathers all the pending input information from devices and + * places it in the event queue. Without calls to SDL_PumpEvents() no events + * would ever be placed on the queue. Often the need for calls to + * SDL_PumpEvents() is hidden from the user since SDL_PollEvent() and + * SDL_WaitEvent() implicitly call SDL_PumpEvents(). However, if you are not + * polling or waiting for events (e.g. you are filtering them), then you must + * call SDL_PumpEvents() to force an event queue update. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_WaitEvent */ extern DECLSPEC void SDLCALL SDL_PumpEvents(void); -/*@{*/ +/* @{ */ typedef enum { SDL_ADDEVENT, @@ -519,172 +680,456 @@ typedef enum } SDL_eventaction; /** - * Checks the event queue for messages and optionally returns them. - * - * If \c action is ::SDL_ADDEVENT, up to \c numevents events will be added to - * the back of the event queue. - * - * If \c action is ::SDL_PEEKEVENT, up to \c numevents events at the front - * of the event queue, within the specified minimum and maximum type, - * will be returned and will not be removed from the queue. - * - * If \c action is ::SDL_GETEVENT, up to \c numevents events at the front - * of the event queue, within the specified minimum and maximum type, - * will be returned and will be removed from the queue. - * - * \return The number of events actually stored, or -1 if there was an error. - * - * This function is thread-safe. + * Check the event queue for messages and optionally return them. + * + * `action` may be any of the following: + * + * - `SDL_ADDEVENT`: up to `numevents` events will be added to the back of the + * event queue. + * - `SDL_PEEKEVENT`: `numevents` events at the front of the event queue, + * within the specified minimum and maximum type, will be returned to the + * caller and will _not_ be removed from the queue. + * - `SDL_GETEVENT`: up to `numevents` events at the front of the event queue, + * within the specified minimum and maximum type, will be returned to the + * caller and will be removed from the queue. + * + * You may have to call SDL_PumpEvents() before calling this function. + * Otherwise, the events may not be ready to be filtered when you call + * SDL_PeepEvents(). + * + * This function is thread-safe. + * + * \param events destination buffer for the retrieved events + * \param numevents if action is SDL_ADDEVENT, the number of events to add + * back to the event queue; if action is SDL_PEEKEVENT or + * SDL_GETEVENT, the maximum number of events to retrieve + * \param action action to take; see [[#action|Remarks]] for details + * \param minType minimum value of the event type to be considered; + * SDL_FIRSTEVENT is a safe choice + * \param maxType maximum value of the event type to be considered; + * SDL_LASTEVENT is a safe choice + * \returns the number of events actually stored or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_PumpEvents + * \sa SDL_PushEvent */ extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action, Uint32 minType, Uint32 maxType); -/*@}*/ +/* @} */ /** - * Checks to see if certain event types are in the event queue. + * Check for the existence of a certain event type in the event queue. + * + * If you need to check for a range of event types, use SDL_HasEvents() + * instead. + * + * \param type the type of event to be queried; see SDL_EventType for details + * \returns SDL_TRUE if events matching `type` are present, or SDL_FALSE if + * events matching `type` are not present. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HasEvents */ extern DECLSPEC SDL_bool SDLCALL SDL_HasEvent(Uint32 type); + + +/** + * Check for the existence of certain event types in the event queue. + * + * If you need to check for a single event type, use SDL_HasEvent() instead. + * + * \param minType the low end of event type to be queried, inclusive; see + * SDL_EventType for details + * \param maxType the high end of event type to be queried, inclusive; see + * SDL_EventType for details + * \returns SDL_TRUE if events with type >= `minType` and <= `maxType` are + * present, or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HasEvents + */ extern DECLSPEC SDL_bool SDLCALL SDL_HasEvents(Uint32 minType, Uint32 maxType); /** - * This function clears events from the event queue + * Clear events of a specific type from the event queue. + * + * This will unconditionally remove any events from the queue that match + * `type`. If you need to remove a range of event types, use SDL_FlushEvents() + * instead. + * + * It's also normal to just ignore events you don't care about in your event + * loop without calling this function. + * + * This function only affects currently queued events. If you want to make + * sure that all pending OS events are flushed, you can call SDL_PumpEvents() + * on the main thread immediately before the flush call. + * + * \param type the type of event to be cleared; see SDL_EventType for details + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FlushEvents */ extern DECLSPEC void SDLCALL SDL_FlushEvent(Uint32 type); + +/** + * Clear events of a range of types from the event queue. + * + * This will unconditionally remove any events from the queue that are in the + * range of `minType` to `maxType`, inclusive. If you need to remove a single + * event type, use SDL_FlushEvent() instead. + * + * It's also normal to just ignore events you don't care about in your event + * loop without calling this function. + * + * This function only affects currently queued events. If you want to make + * sure that all pending OS events are flushed, you can call SDL_PumpEvents() + * on the main thread immediately before the flush call. + * + * \param minType the low end of event type to be cleared, inclusive; see + * SDL_EventType for details + * \param maxType the high end of event type to be cleared, inclusive; see + * SDL_EventType for details + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FlushEvent + */ extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType); /** - * \brief Polls for currently pending events. - * - * \return 1 if there are any pending events, or 0 if there are none available. - * - * \param event If not NULL, the next event is removed from the queue and - * stored in that area. + * Poll for currently pending events. + * + * If `event` is not NULL, the next event is removed from the queue and stored + * in the SDL_Event structure pointed to by `event`. The 1 returned refers to + * this event, immediately stored in the SDL Event structure -- not an event + * to follow. + * + * If `event` is NULL, it simply returns 1 if there is an event in the queue, + * but will not remove it from the queue. + * + * As this function may implicitly call SDL_PumpEvents(), you can only call + * this function in the thread that set the video mode. + * + * SDL_PollEvent() is the favored way of receiving system events since it can + * be done from the main loop and does not suspend the main loop while waiting + * on an event to be posted. + * + * The common practice is to fully process the event queue once every frame, + * usually as a first step before updating the game's state: + * + * ```c + * while (game_is_still_running) { + * SDL_Event event; + * while (SDL_PollEvent(&event)) { // poll until all events are handled! + * // decide what to do with this event. + * } + * + * // update game state, draw the current frame + * } + * ``` + * + * \param event the SDL_Event structure to be filled with the next event from + * the queue, or NULL + * \returns 1 if there is a pending event or 0 if there are none available. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetEventFilter + * \sa SDL_PeepEvents + * \sa SDL_PushEvent + * \sa SDL_SetEventFilter + * \sa SDL_WaitEvent + * \sa SDL_WaitEventTimeout */ extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event); /** - * \brief Waits indefinitely for the next available event. - * - * \return 1, or 0 if there was an error while waiting for events. - * - * \param event If not NULL, the next event is removed from the queue and - * stored in that area. + * Wait indefinitely for the next available event. + * + * If `event` is not NULL, the next event is removed from the queue and stored + * in the SDL_Event structure pointed to by `event`. + * + * As this function may implicitly call SDL_PumpEvents(), you can only call + * this function in the thread that initialized the video subsystem. + * + * \param event the SDL_Event structure to be filled in with the next event + * from the queue, or NULL + * \returns 1 on success or 0 if there was an error while waiting for events; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_PumpEvents + * \sa SDL_WaitEventTimeout */ extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event); /** - * \brief Waits until the specified timeout (in milliseconds) for the next - * available event. - * - * \return 1, or 0 if there was an error while waiting for events. - * - * \param event If not NULL, the next event is removed from the queue and - * stored in that area. + * Wait until the specified timeout (in milliseconds) for the next available + * event. + * + * If `event` is not NULL, the next event is removed from the queue and stored + * in the SDL_Event structure pointed to by `event`. + * + * As this function may implicitly call SDL_PumpEvents(), you can only call + * this function in the thread that initialized the video subsystem. + * + * \param event the SDL_Event structure to be filled in with the next event + * from the queue, or NULL + * \param timeout the maximum number of milliseconds to wait for the next + * available event + * \returns 1 on success or 0 if there was an error while waiting for events; + * call SDL_GetError() for more information. This also returns 0 if + * the timeout elapsed without an event arriving. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_PumpEvents + * \sa SDL_WaitEvent */ extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event * event, int timeout); /** - * \brief Add an event to the event queue. - * - * \return 1 on success, 0 if the event was filtered, or -1 if the event queue - * was full or there was some other error. + * Add an event to the event queue. + * + * The event queue can actually be used as a two way communication channel. + * Not only can events be read from the queue, but the user can also push + * their own events onto it. `event` is a pointer to the event structure you + * wish to push onto the queue. The event is copied into the queue, and the + * caller may dispose of the memory pointed to after SDL_PushEvent() returns. + * + * Note: Pushing device input events onto the queue doesn't modify the state + * of the device within SDL. + * + * This function is thread-safe, and can be called from other threads safely. + * + * Note: Events pushed onto the queue with SDL_PushEvent() get passed through + * the event filter but events added with SDL_PeepEvents() do not. + * + * For pushing application-specific events, please use SDL_RegisterEvents() to + * get an event type that does not conflict with other code that also wants + * its own custom event types. + * + * \param event the SDL_Event to be added to the queue + * \returns 1 on success, 0 if the event was filtered, or a negative error + * code on failure; call SDL_GetError() for more information. A + * common reason for error is the event queue being full. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PeepEvents + * \sa SDL_PollEvent + * \sa SDL_RegisterEvents */ extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event); +/** + * A function pointer used for callbacks that watch the event queue. + * + * \param userdata what was passed as `userdata` to SDL_SetEventFilter() + * or SDL_AddEventWatch, etc + * \param event the event that triggered the callback + * \returns 1 to permit event to be added to the queue, and 0 to disallow + * it. When used with SDL_AddEventWatch, the return value is ignored. + * + * \sa SDL_SetEventFilter + * \sa SDL_AddEventWatch + */ typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event); /** - * Sets up a filter to process all events before they change internal state and - * are posted to the internal event queue. - * - * The filter is protypted as: - * \code - * int SDL_EventFilter(void *userdata, SDL_Event * event); - * \endcode + * Set up a filter to process all events before they change internal state and + * are posted to the internal event queue. * - * If the filter returns 1, then the event will be added to the internal queue. - * If it returns 0, then the event will be dropped from the queue, but the - * internal state will still be updated. This allows selective filtering of - * dynamically arriving events. - * - * \warning Be very careful of what you do in the event filter function, as - * it may run in a different thread! - * - * There is one caveat when dealing with the ::SDL_QUITEVENT event type. The - * event filter is only called when the window manager desires to close the - * application window. If the event filter returns 1, then the window will - * be closed, otherwise the window will remain open if possible. + * If the filter function returns 1 when called, then the event will be added + * to the internal queue. If it returns 0, then the event will be dropped from + * the queue, but the internal state will still be updated. This allows + * selective filtering of dynamically arriving events. * - * If the quit event is generated by an interrupt signal, it will bypass the - * internal queue and be delivered to the application at the next event poll. + * **WARNING**: Be very careful of what you do in the event filter function, + * as it may run in a different thread! + * + * On platforms that support it, if the quit event is generated by an + * interrupt signal (e.g. pressing Ctrl-C), it will be delivered to the + * application at the next event poll. + * + * There is one caveat when dealing with the ::SDL_QuitEvent event type. The + * event filter is only called when the window manager desires to close the + * application window. If the event filter returns 1, then the window will be + * closed, otherwise the window will remain open if possible. + * + * Note: Disabled events never make it to the event filter function; see + * SDL_EventState(). + * + * Note: If you just want to inspect events without filtering, you should use + * SDL_AddEventWatch() instead. + * + * Note: Events pushed onto the queue with SDL_PushEvent() get passed through + * the event filter, but events pushed onto the queue with SDL_PeepEvents() do + * not. + * + * \param filter An SDL_EventFilter function to call when an event happens + * \param userdata a pointer that is passed to `filter` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AddEventWatch + * \sa SDL_EventState + * \sa SDL_GetEventFilter + * \sa SDL_PeepEvents + * \sa SDL_PushEvent */ extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter, void *userdata); /** - * Return the current event filter - can be used to "chain" filters. - * If there is no event filter set, this function returns SDL_FALSE. + * Query the current event filter. + * + * This function can be used to "chain" filters, by saving the existing filter + * before replacing it with a function that will call that saved filter. + * + * \param filter the current callback function will be stored here + * \param userdata the pointer that is passed to the current event filter will + * be stored here + * \returns SDL_TRUE on success or SDL_FALSE if there is no event filter set. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetEventFilter */ extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter * filter, void **userdata); /** - * Add a function which is called when an event is added to the queue. + * Add a callback to be triggered when an event is added to the event queue. + * + * `filter` will be called when an event happens, and its return value is + * ignored. + * + * **WARNING**: Be very careful of what you do in the event filter function, + * as it may run in a different thread! + * + * If the quit event is generated by a signal (e.g. SIGINT), it will bypass + * the internal queue and be delivered to the watch callback immediately, and + * arrive at the next event poll. + * + * Note: the callback is called for events posted by the user through + * SDL_PushEvent(), but not for disabled events, nor for events by a filter + * callback set with SDL_SetEventFilter(), nor for events posted by the user + * through SDL_PeepEvents(). + * + * \param filter an SDL_EventFilter function to call when an event happens. + * \param userdata a pointer that is passed to `filter` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DelEventWatch + * \sa SDL_SetEventFilter */ extern DECLSPEC void SDLCALL SDL_AddEventWatch(SDL_EventFilter filter, void *userdata); /** - * Remove an event watch function added with SDL_AddEventWatch() + * Remove an event watch callback added with SDL_AddEventWatch(). + * + * This function takes the same input as SDL_AddEventWatch() to identify and + * delete the corresponding callback. + * + * \param filter the function originally passed to SDL_AddEventWatch() + * \param userdata the pointer originally passed to SDL_AddEventWatch() + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AddEventWatch */ extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter, void *userdata); /** - * Run the filter function on the current event queue, removing any - * events for which the filter returns 0. + * Run a specific filter function on the current event queue, removing any + * events for which the filter returns 0. + * + * See SDL_SetEventFilter() for more information. Unlike SDL_SetEventFilter(), + * this function does not change the filter permanently, it only uses the + * supplied filter until this function returns. + * + * \param filter the SDL_EventFilter function to call when an event happens + * \param userdata a pointer that is passed to `filter` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetEventFilter + * \sa SDL_SetEventFilter */ extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter, void *userdata); -/*@{*/ -#define SDL_QUERY -1 -#define SDL_IGNORE 0 -#define SDL_DISABLE 0 -#define SDL_ENABLE 1 +/* @{ */ +#define SDL_QUERY -1 +#define SDL_IGNORE 0 +#define SDL_DISABLE 0 +#define SDL_ENABLE 1 /** - * This function allows you to set the state of processing certain events. - * - If \c state is set to ::SDL_IGNORE, that event will be automatically - * dropped from the event queue and will not event be filtered. - * - If \c state is set to ::SDL_ENABLE, that event will be processed - * normally. - * - If \c state is set to ::SDL_QUERY, SDL_EventState() will return the - * current processing state of the specified event. + * Set the state of processing events by type. + * + * `state` may be any of the following: + * + * - `SDL_QUERY`: returns the current processing state of the specified event + * - `SDL_IGNORE` (aka `SDL_DISABLE`): the event will automatically be dropped + * from the event queue and will not be filtered + * - `SDL_ENABLE`: the event will be processed normally + * + * \param type the type of event; see SDL_EventType for details + * \param state how to process the event + * \returns `SDL_DISABLE` or `SDL_ENABLE`, representing the processing state + * of the event before this function makes any changes to it. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetEventState */ extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint32 type, int state); -/*@}*/ +/* @} */ #define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY) /** - * This function allocates a set of user-defined events, and returns - * the beginning event number for that set of events. + * Allocate a set of user-defined events, and return the beginning event + * number for that set of events. * - * If there aren't enough user-defined events left, this function - * returns (Uint32)-1 + * Calling this function with `numevents` <= 0 is an error and will return + * (Uint32)-1. + * + * Note, (Uint32)-1 means the maximum unsigned 32-bit integer value (or + * 0xFFFFFFFF), but is clearer to write. + * + * \param numevents the number of events to be allocated + * \returns the beginning event number, or (Uint32)-1 if there are not enough + * user-defined events left. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PushEvent */ extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_events_h */ +#endif /* SDL_events_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_filesystem.h b/external/SDL2/SDL_filesystem.h new file mode 100644 index 0000000..16f02e2 --- /dev/null +++ b/external/SDL2/SDL_filesystem.h @@ -0,0 +1,145 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_filesystem.h + * + * \brief Include file for filesystem SDL API functions + */ + +#ifndef SDL_filesystem_h_ +#define SDL_filesystem_h_ + +#include "SDL_stdinc.h" + +#include "begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the directory where the application was run from. + * + * This is not necessarily a fast call, so you should call this once near + * startup and save the string if you need it. + * + * **Mac OS X and iOS Specific Functionality**: If the application is in a + * ".app" bundle, this function returns the Resource directory (e.g. + * MyApp.app/Contents/Resources/). This behaviour can be overridden by adding + * a property to the Info.plist file. Adding a string key with the name + * SDL_FILESYSTEM_BASE_DIR_TYPE with a supported value will change the + * behaviour. + * + * Supported values for the SDL_FILESYSTEM_BASE_DIR_TYPE property (Given an + * application in /Applications/SDLApp/MyApp.app): + * + * - `resource`: bundle resource directory (the default). For example: + * `/Applications/SDLApp/MyApp.app/Contents/Resources` + * - `bundle`: the Bundle directory. For example: + * `/Applications/SDLApp/MyApp.app/` + * - `parent`: the containing directory of the bundle. For example: + * `/Applications/SDLApp/` + * + * The returned path is guaranteed to end with a path separator ('\' on + * Windows, '/' on most other platforms). + * + * The pointer returned is owned by the caller. Please call SDL_free() on the + * pointer when done with it. + * + * \returns an absolute path in UTF-8 encoding to the application data + * directory. NULL will be returned on error or when the platform + * doesn't implement this functionality, call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.1. + * + * \sa SDL_GetPrefPath + */ +extern DECLSPEC char *SDLCALL SDL_GetBasePath(void); + +/** + * Get the user-and-app-specific path where files can be written. + * + * Get the "pref dir". This is meant to be where users can write personal + * files (preferences and save games, etc) that are specific to your + * application. This directory is unique per user, per application. + * + * This function will decide the appropriate location in the native + * filesystem, create the directory if necessary, and return a string of the + * absolute path to the directory in UTF-8 encoding. + * + * On Windows, the string might look like: + * + * `C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\` + * + * On Linux, the string might look like" + * + * `/home/bob/.local/share/My Program Name/` + * + * On Mac OS X, the string might look like: + * + * `/Users/bob/Library/Application Support/My Program Name/` + * + * You should assume the path returned by this function is the only safe place + * to write files (and that SDL_GetBasePath(), while it might be writable, or + * even the parent of the returned path, isn't where you should be writing + * things). + * + * Both the org and app strings may become part of a directory name, so please + * follow these rules: + * + * - Try to use the same org string (_including case-sensitivity_) for all + * your applications that use this function. + * - Always use a unique app string for each one, and make sure it never + * changes for an app once you've decided on it. + * - Unicode characters are legal, as long as it's UTF-8 encoded, but... + * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game + * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. + * + * The returned path is guaranteed to end with a path separator ('\' on + * Windows, '/' on most other platforms). + * + * The pointer returned is owned by the caller. Please call SDL_free() on the + * pointer when done with it. + * + * \param org the name of your organization + * \param app the name of your application + * \returns a UTF-8 string of the user directory in platform-dependent + * notation. NULL if there's a problem (creating directory failed, + * etc.). + * + * \since This function is available since SDL 2.0.1. + * + * \sa SDL_GetBasePath + */ +extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_filesystem_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_gamecontroller.h b/external/SDL2/SDL_gamecontroller.h index 318e51a..bdd9b89 100644 --- a/external/SDL2/SDL_gamecontroller.h +++ b/external/SDL2/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -25,40 +25,59 @@ * Include file for SDL game controller event handling */ -#ifndef _SDL_gamecontroller_h -#define _SDL_gamecontroller_h +#ifndef SDL_gamecontroller_h_ +#define SDL_gamecontroller_h_ #include "SDL_stdinc.h" #include "SDL_error.h" +#include "SDL_rwops.h" +#include "SDL_sensor.h" #include "SDL_joystick.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \file SDL_gamecontroller.h * * In order to use these functions, SDL_Init() must have been called - * with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system + * with the ::SDL_INIT_GAMECONTROLLER flag. This causes SDL to scan the system * for game controllers, and load appropriate drivers. + * + * If you would like to receive controller updates while the application + * is in the background, you should set the following hint before calling + * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS */ -/* The gamecontroller structure used to identify an SDL game controller */ +/** + * The gamecontroller structure used to identify an SDL game controller + */ struct _SDL_GameController; typedef struct _SDL_GameController SDL_GameController; +typedef enum +{ + SDL_CONTROLLER_TYPE_UNKNOWN = 0, + SDL_CONTROLLER_TYPE_XBOX360, + SDL_CONTROLLER_TYPE_XBOXONE, + SDL_CONTROLLER_TYPE_PS3, + SDL_CONTROLLER_TYPE_PS4, + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO, + SDL_CONTROLLER_TYPE_VIRTUAL, + SDL_CONTROLLER_TYPE_PS5, + SDL_CONTROLLER_TYPE_AMAZON_LUNA, + SDL_CONTROLLER_TYPE_GOOGLE_STADIA +} SDL_GameControllerType; typedef enum { - SDL_CONTROLLER_BINDTYPE_NONE = 0, - SDL_CONTROLLER_BINDTYPE_BUTTON, - SDL_CONTROLLER_BINDTYPE_AXIS, - SDL_CONTROLLER_BINDTYPE_HAT + SDL_CONTROLLER_BINDTYPE_NONE = 0, + SDL_CONTROLLER_BINDTYPE_BUTTON, + SDL_CONTROLLER_BINDTYPE_AXIS, + SDL_CONTROLLER_BINDTYPE_HAT } SDL_GameControllerBindType; /** @@ -66,233 +85,917 @@ typedef enum */ typedef struct SDL_GameControllerButtonBind { - SDL_GameControllerBindType bindType; - union - { - int button; - int axis; - struct { + SDL_GameControllerBindType bindType; + union + { + int button; + int axis; + struct { int hat; int hat_mask; } hat; - } value; + } value; } SDL_GameControllerButtonBind; /** * To count the number of game controllers in the system for the following: - * int nJoysticks = SDL_NumJoysticks(); - * int nGameControllers = 0; - * for ( int i = 0; i < nJoysticks; i++ ) { - * if ( SDL_IsGameController(i) ) { - * nGameControllers++; - * } - * } * - * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is: - * guid,name,mappings + * ```c + * int nJoysticks = SDL_NumJoysticks(); + * int nGameControllers = 0; + * for (int i = 0; i < nJoysticks; i++) { + * if (SDL_IsGameController(i)) { + * nGameControllers++; + * } + * } + * ``` + * + * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping() you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is: + * guid,name,mappings * * Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones. * Under Windows there is a reserved GUID of "xinput" that covers any XInput devices. - * The mapping format for joystick is: - * bX - a joystick button, index X - * hX.Y - hat X with value Y - * aX - axis X of the joystick + * The mapping format for joystick is: + * bX - a joystick button, index X + * hX.Y - hat X with value Y + * aX - axis X of the joystick * Buttons can be used as a controller axis and vice versa. * * This string shows an example of a valid mapping for a controller - * "341a3608000000000000504944564944,Aferglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", * + * ```c + * "03000000341a00003608000000000000,PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", + * ``` */ /** - * Add or update an existing mapping configuration + * Load a set of Game Controller mappings from a seekable SDL data stream. * - * \return 1 if mapping is added, 0 if updated, -1 on error + * You can call this function several times, if needed, to load different + * database files. + * + * If a new mapping is loaded for an already known controller GUID, the later + * version will overwrite the one currently loaded. + * + * Mappings not belonging to the current platform or with no platform field + * specified will be ignored (i.e. mappings for Linux will be ignored in + * Windows, etc). + * + * This function will load the text database entirely in memory before + * processing it, so take this into consideration if you are in a memory + * constrained environment. + * + * \param rw the data stream for the mappings to be added + * \param freerw non-zero to close the stream after being read + * \returns the number of mappings added or -1 on error; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_GameControllerAddMapping + * \sa SDL_GameControllerAddMappingsFromFile + * \sa SDL_GameControllerMappingForGUID */ -extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping( const char* mappingSring ); +extern DECLSPEC int SDLCALL SDL_GameControllerAddMappingsFromRW(SDL_RWops * rw, int freerw); /** - * Get a mapping string for a GUID + * Load a set of mappings from a file, filtered by the current SDL_GetPlatform() * - * \return the mapping string. Must be freed with SDL_free. Returns NULL if no mapping is available + * Convenience macro. */ -extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID( SDL_JoystickGUID guid ); +#define SDL_GameControllerAddMappingsFromFile(file) SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(file, "rb"), 1) /** - * Get a mapping string for an open GameController + * Add support for controllers that SDL is unaware of or to cause an existing + * controller to have a different binding. * - * \return the mapping string. Must be freed with SDL_free. Returns NULL if no mapping is available + * The mapping string has the format "GUID,name,mapping", where GUID is the + * string value from SDL_JoystickGetGUIDString(), name is the human readable + * string for the device and mappings are controller mappings to joystick + * ones. Under Windows there is a reserved GUID of "xinput" that covers all + * XInput devices. The mapping format for joystick is: {| |bX |a joystick + * button, index X |- |hX.Y |hat X with value Y |- |aX |axis X of the joystick + * |} Buttons can be used as a controller axes and vice versa. + * + * This string shows an example of a valid mapping for a controller: + * + * ```c + * "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7" + * ``` + * + * \param mappingString the mapping string + * \returns 1 if a new mapping is added, 0 if an existing mapping is updated, + * -1 on error; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerMapping + * \sa SDL_GameControllerMappingForGUID */ -extern DECLSPEC char * SDLCALL SDL_GameControllerMapping( SDL_GameController * gamecontroller ); +extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping(const char* mappingString); /** - * Is the joystick on this index supported by the game controller interface? + * Get the number of mappings installed. + * + * \returns the number of mappings. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerNumMappings(void); + +/** + * Get the mapping at a particular index. + * + * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if + * the index is out of range. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForIndex(int mapping_index); + +/** + * Get the game controller mapping string for a given GUID. + * + * The returned string must be freed with SDL_free(). + * + * \param guid a structure containing the GUID for which a mapping is desired + * \returns a mapping string or NULL on error; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetDeviceGUID + * \sa SDL_JoystickGetGUID + */ +extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid); + +/** + * Get the current mapping of a Game Controller. + * + * The returned string must be freed with SDL_free(). + * + * Details about mappings are discussed with SDL_GameControllerAddMapping(). + * + * \param gamecontroller the game controller you want to get the current + * mapping for + * \returns a string that has the controller's mapping or NULL if no mapping + * is available; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerAddMapping + * \sa SDL_GameControllerMappingForGUID + */ +extern DECLSPEC char * SDLCALL SDL_GameControllerMapping(SDL_GameController *gamecontroller); + +/** + * Check if the given joystick is supported by the game controller interface. + * + * `joystick_index` is the same as the `device_index` passed to + * SDL_JoystickOpen(). + * + * \param joystick_index the device_index of a device, up to + * SDL_NumJoysticks() + * \returns SDL_TRUE if the given joystick is supported by the game controller + * interface, SDL_FALSE if it isn't or it's an invalid index. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerNameForIndex + * \sa SDL_GameControllerOpen */ extern DECLSPEC SDL_bool SDLCALL SDL_IsGameController(int joystick_index); - /** - * Get the implementation dependent name of a game controller. - * This can be called before any controllers are opened. - * If no name can be found, this function returns NULL. + * Get the implementation dependent name for the game controller. + * + * This function can be called before any controllers are opened. + * + * `joystick_index` is the same as the `device_index` passed to + * SDL_JoystickOpen(). + * + * \param joystick_index the device_index of a device, from zero to + * SDL_NumJoysticks()-1 + * \returns the implementation-dependent name for the game controller, or NULL + * if there is no name or the index is invalid. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerName + * \sa SDL_GameControllerOpen + * \sa SDL_IsGameController */ extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index); /** - * Open a game controller for use. - * The index passed as an argument refers to the N'th game controller on the system. - * This index is the value which will identify this controller in future controller - * events. + * Get the type of a game controller. * - * \return A controller identifier, or NULL if an error occurred. + * This can be called before any controllers are opened. + * + * \param joystick_index the device_index of a device, from zero to + * SDL_NumJoysticks()-1 + * \returns the controller type. + * + * \since This function is available since SDL 2.0.12. + */ +extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerTypeForIndex(int joystick_index); + +/** + * Get the mapping of a game controller. + * + * This can be called before any controllers are opened. + * + * \param joystick_index the device_index of a device, from zero to + * SDL_NumJoysticks()-1 + * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if + * no mapping is available. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC char *SDLCALL SDL_GameControllerMappingForDeviceIndex(int joystick_index); + +/** + * Open a game controller for use. + * + * `joystick_index` is the same as the `device_index` passed to + * SDL_JoystickOpen(). + * + * The index passed as an argument refers to the N'th game controller on the + * system. This index is not the value which will identify this controller in + * future controller events. The joystick's instance id (SDL_JoystickID) will + * be used there instead. + * + * \param joystick_index the device_index of a device, up to + * SDL_NumJoysticks() + * \returns a gamecontroller identifier or NULL if an error occurred; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerClose + * \sa SDL_GameControllerNameForIndex + * \sa SDL_IsGameController */ extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_index); /** - * Return the name for this currently opened controller + * Get the SDL_GameController associated with an instance id. + * + * \param joyid the instance id to get the SDL_GameController for + * \returns an SDL_GameController on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.4. + */ +extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid); + +/** + * Get the SDL_GameController associated with a player index. + * + * Please note that the player index is _not_ the device index, nor is it the + * instance id! + * + * \param player_index the player index, which is not the device index or the + * instance id! + * \returns the SDL_GameController associated with a player index. + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_GameControllerGetPlayerIndex + * \sa SDL_GameControllerSetPlayerIndex + */ +extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index); + +/** + * Get the implementation-dependent name for an opened game controller. + * + * This is the same name as returned by SDL_GameControllerNameForIndex(), but + * it takes a controller identifier instead of the (unstable) device index. + * + * \param gamecontroller a game controller identifier previously returned by + * SDL_GameControllerOpen() + * \returns the implementation dependent name for the game controller, or NULL + * if there is no name or the identifier passed is invalid. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerNameForIndex + * \sa SDL_GameControllerOpen */ extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller); /** - * Returns SDL_TRUE if the controller has been opened and currently connected, - * or SDL_FALSE if it has not. + * Get the type of this currently opened controller + * + * This is the same name as returned by SDL_GameControllerTypeForIndex(), but + * it takes a controller identifier instead of the (unstable) device index. + * + * \param gamecontroller the game controller object to query. + * \returns the controller type. + * + * \since This function is available since SDL 2.0.12. + */ +extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_GameController *gamecontroller); + +/** + * Get the player index of an opened game controller. + * + * For XInput controllers this returns the XInput user index. + * + * \param gamecontroller the game controller object to query. + * \returns the player index for controller, or -1 if it's not available. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller); + +/** + * Set the player index of an opened game controller. + * + * \param gamecontroller the game controller object to adjust. + * \param player_index Player index to assign to this controller. + * + * \since This function is available since SDL 2.0.12. + */ +extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index); + +/** + * Get the USB vendor ID of an opened controller, if available. + * + * If the vendor ID isn't available this function returns 0. + * + * \param gamecontroller the game controller object to query. + * \return the USB vendor ID, or zero if unavailable. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetVendor(SDL_GameController *gamecontroller); + +/** + * Get the USB product ID of an opened controller, if available. + * + * If the product ID isn't available this function returns 0. + * + * \param gamecontroller the game controller object to query. + * \return the USB product ID, or zero if unavailable. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProduct(SDL_GameController *gamecontroller); + +/** + * Get the product version of an opened controller, if available. + * + * If the product version isn't available this function returns 0. + * + * \param gamecontroller the game controller object to query. + * \return the USB product version, or zero if unavailable. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller); + +/** + * Get the serial number of an opened controller, if available. + * + * Returns the serial number of the controller, or NULL if it is not + * available. + * + * \param gamecontroller the game controller object to query. + * \return the serial number, or NULL if unavailable. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller); + +/** + * Check if a controller has been opened and is currently connected. + * + * \param gamecontroller a game controller identifier previously returned by + * SDL_GameControllerOpen() + * \returns SDL_TRUE if the controller has been opened and is currently + * connected, or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerClose + * \sa SDL_GameControllerOpen */ extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerGetAttached(SDL_GameController *gamecontroller); /** - * Get the underlying joystick object used by a controller + * Get the Joystick ID from a Game Controller. + * + * This function will give you a SDL_Joystick object, which allows you to use + * the SDL_Joystick functions with a SDL_GameController object. This would be + * useful for getting a joystick's position at any given time, even if it + * hasn't moved (moving it would produce an event, which would have the axis' + * value). + * + * The pointer returned is owned by the SDL_GameController. You should not + * call SDL_JoystickClose() on it, for example, since doing so will likely + * cause SDL to crash. + * + * \param gamecontroller the game controller object that you want to get a + * joystick from + * \returns a SDL_Joystick object; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller); /** - * Enable/disable controller event polling. + * Query or change current state of Game Controller events. * - * If controller events are disabled, you must call SDL_GameControllerUpdate() - * yourself and check the state of the controller when you want controller - * information. + * If controller events are disabled, you must call SDL_GameControllerUpdate() + * yourself and check the state of the controller when you want controller + * information. * - * The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE. + * Any number can be passed to SDL_GameControllerEventState(), but only -1, 0, + * and 1 will have any effect. Other numbers will just be returned. + * + * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE` + * \returns the same value passed to the function, with exception to -1 + * (SDL_QUERY), which will return the current state. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickEventState */ extern DECLSPEC int SDLCALL SDL_GameControllerEventState(int state); /** - * Update the current state of the open game controllers. - * - * This is called automatically by the event loop if any game controller - * events are enabled. + * Manually pump game controller updates if not using the loop. + * + * This function is called automatically by the event loop if events are + * enabled. Under such circumstances, it will not be necessary to call this + * function. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void); /** - * The list of axii available from a controller + * The list of axes available from a controller + * + * Thumbstick axis values range from SDL_JOYSTICK_AXIS_MIN to SDL_JOYSTICK_AXIS_MAX, + * and are centered within ~8000 of zero, though advanced UI will allow users to set + * or autodetect the dead zone, which varies between controllers. + * + * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX. */ typedef enum { - SDL_CONTROLLER_AXIS_INVALID = -1, - SDL_CONTROLLER_AXIS_LEFTX, - SDL_CONTROLLER_AXIS_LEFTY, - SDL_CONTROLLER_AXIS_RIGHTX, - SDL_CONTROLLER_AXIS_RIGHTY, - SDL_CONTROLLER_AXIS_TRIGGERLEFT, - SDL_CONTROLLER_AXIS_TRIGGERRIGHT, - SDL_CONTROLLER_AXIS_MAX + SDL_CONTROLLER_AXIS_INVALID = -1, + SDL_CONTROLLER_AXIS_LEFTX, + SDL_CONTROLLER_AXIS_LEFTY, + SDL_CONTROLLER_AXIS_RIGHTX, + SDL_CONTROLLER_AXIS_RIGHTY, + SDL_CONTROLLER_AXIS_TRIGGERLEFT, + SDL_CONTROLLER_AXIS_TRIGGERRIGHT, + SDL_CONTROLLER_AXIS_MAX } SDL_GameControllerAxis; /** - * turn this string into a axis mapping + * Convert a string into SDL_GameControllerAxis enum. + * + * This function is called internally to translate SDL_GameController mapping + * strings for the underlying joystick device into the consistent + * SDL_GameController mapping. You do not normally need to call this function + * unless you are parsing SDL_GameController mappings in your own code. + * + * Note specially that "righttrigger" and "lefttrigger" map to + * `SDL_CONTROLLER_AXIS_TRIGGERRIGHT` and `SDL_CONTROLLER_AXIS_TRIGGERLEFT`, + * respectively. + * + * \param str string representing a SDL_GameController axis + * \returns the SDL_GameControllerAxis enum corresponding to the input string, + * or `SDL_CONTROLLER_AXIS_INVALID` if no match was found. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetStringForAxis */ -extern DECLSPEC SDL_GameControllerAxis SDLCALL SDL_GameControllerGetAxisFromString(const char *pchString); +extern DECLSPEC SDL_GameControllerAxis SDLCALL SDL_GameControllerGetAxisFromString(const char *str); /** - * turn this axis enum into a string mapping + * Convert from an SDL_GameControllerAxis enum to a string. + * + * The caller should not SDL_free() the returned string. + * + * \param axis an enum value for a given SDL_GameControllerAxis + * \returns a string for the given axis, or NULL if an invalid axis is + * specified. The string returned is of the format used by + * SDL_GameController mapping strings. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetAxisFromString */ extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis); /** - * Get the SDL joystick layer binding for this controller button mapping + * Get the SDL joystick layer binding for a controller axis mapping. + * + * \param gamecontroller a game controller + * \param axis an axis enum value (one of the SDL_GameControllerAxis values) + * \returns a SDL_GameControllerButtonBind describing the bind. On failure + * (like the given Controller axis doesn't exist on the device), its + * `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetBindForButton */ extern DECLSPEC SDL_GameControllerButtonBind SDLCALL SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis); /** - * Get the current state of an axis control on a game controller. + * Query whether a game controller has a given axis. * - * The state is a value ranging from -32768 to 32767. + * This merely reports whether the controller's mapping defined this axis, as + * that is all the information SDL has about the physical device. * - * The axis indices start at index 0. + * \param gamecontroller a game controller + * \param axis an axis enum value (an SDL_GameControllerAxis value) + * \returns SDL_TRUE if the controller has this axis, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL +SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis); + +/** + * Get the current state of an axis control on a game controller. + * + * The axis indices start at index 0. + * + * The state is a value ranging from -32768 to 32767. Triggers, however, range + * from 0 to 32767 (they never return a negative value). + * + * \param gamecontroller a game controller + * \param axis an axis index (one of the SDL_GameControllerAxis values) + * \returns axis state (including 0) on success or 0 (also) on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetButton */ extern DECLSPEC Sint16 SDLCALL -SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, - SDL_GameControllerAxis axis); +SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis); /** * The list of buttons available from a controller */ typedef enum { - SDL_CONTROLLER_BUTTON_INVALID = -1, - SDL_CONTROLLER_BUTTON_A, - SDL_CONTROLLER_BUTTON_B, - SDL_CONTROLLER_BUTTON_X, - SDL_CONTROLLER_BUTTON_Y, - SDL_CONTROLLER_BUTTON_BACK, - SDL_CONTROLLER_BUTTON_GUIDE, - SDL_CONTROLLER_BUTTON_START, - SDL_CONTROLLER_BUTTON_LEFTSTICK, - SDL_CONTROLLER_BUTTON_RIGHTSTICK, - SDL_CONTROLLER_BUTTON_LEFTSHOULDER, - SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, - SDL_CONTROLLER_BUTTON_DPAD_UP, - SDL_CONTROLLER_BUTTON_DPAD_DOWN, - SDL_CONTROLLER_BUTTON_DPAD_LEFT, - SDL_CONTROLLER_BUTTON_DPAD_RIGHT, - SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_BUTTON_INVALID = -1, + SDL_CONTROLLER_BUTTON_A, + SDL_CONTROLLER_BUTTON_B, + SDL_CONTROLLER_BUTTON_X, + SDL_CONTROLLER_BUTTON_Y, + SDL_CONTROLLER_BUTTON_BACK, + SDL_CONTROLLER_BUTTON_GUIDE, + SDL_CONTROLLER_BUTTON_START, + SDL_CONTROLLER_BUTTON_LEFTSTICK, + SDL_CONTROLLER_BUTTON_RIGHTSTICK, + SDL_CONTROLLER_BUTTON_LEFTSHOULDER, + SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, + SDL_CONTROLLER_BUTTON_DPAD_UP, + SDL_CONTROLLER_BUTTON_DPAD_DOWN, + SDL_CONTROLLER_BUTTON_DPAD_LEFT, + SDL_CONTROLLER_BUTTON_DPAD_RIGHT, + SDL_CONTROLLER_BUTTON_MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */ + SDL_CONTROLLER_BUTTON_PADDLE1, /* Xbox Elite paddle P1 */ + SDL_CONTROLLER_BUTTON_PADDLE2, /* Xbox Elite paddle P3 */ + SDL_CONTROLLER_BUTTON_PADDLE3, /* Xbox Elite paddle P2 */ + SDL_CONTROLLER_BUTTON_PADDLE4, /* Xbox Elite paddle P4 */ + SDL_CONTROLLER_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */ + SDL_CONTROLLER_BUTTON_MAX } SDL_GameControllerButton; /** - * turn this string into a button mapping + * Convert a string into an SDL_GameControllerButton enum. + * + * This function is called internally to translate SDL_GameController mapping + * strings for the underlying joystick device into the consistent + * SDL_GameController mapping. You do not normally need to call this function + * unless you are parsing SDL_GameController mappings in your own code. + * + * \param str string representing a SDL_GameController axis + * \returns the SDL_GameControllerButton enum corresponding to the input + * string, or `SDL_CONTROLLER_AXIS_INVALID` if no match was found. + * + * \since This function is available since SDL 2.0.0. */ -extern DECLSPEC SDL_GameControllerButton SDLCALL SDL_GameControllerGetButtonFromString(const char *pchString); +extern DECLSPEC SDL_GameControllerButton SDLCALL SDL_GameControllerGetButtonFromString(const char *str); /** - * turn this button enum into a string mapping + * Convert from an SDL_GameControllerButton enum to a string. + * + * The caller should not SDL_free() the returned string. + * + * \param button an enum value for a given SDL_GameControllerButton + * \returns a string for the given button, or NULL if an invalid axis is + * specified. The string returned is of the format used by + * SDL_GameController mapping strings. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetButtonFromString */ extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForButton(SDL_GameControllerButton button); /** - * Get the SDL joystick layer binding for this controller button mapping + * Get the SDL joystick layer binding for a controller button mapping. + * + * \param gamecontroller a game controller + * \param button an button enum value (an SDL_GameControllerButton value) + * \returns a SDL_GameControllerButtonBind describing the bind. On failure + * (like the given Controller button doesn't exist on the device), + * its `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetBindForAxis */ extern DECLSPEC SDL_GameControllerButtonBind SDLCALL SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button); +/** + * Query whether a game controller has a given button. + * + * This merely reports whether the controller's mapping defined this button, + * as that is all the information SDL has about the physical device. + * + * \param gamecontroller a game controller + * \param button a button enum value (an SDL_GameControllerButton value) + * \returns SDL_TRUE if the controller has this button, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasButton(SDL_GameController *gamecontroller, + SDL_GameControllerButton button); /** - * Get the current state of a button on a game controller. + * Get the current state of a button on a game controller. * - * The button indices start at index 0. + * \param gamecontroller a game controller + * \param button a button index (one of the SDL_GameControllerButton values) + * \returns 1 for pressed state or 0 for not pressed state or error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerGetAxis */ extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button); /** - * Close a controller previously opened with SDL_GameControllerOpen(). + * Get the number of touchpads on a game controller. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller); + +/** + * Get the number of supported simultaneous fingers on a touchpad on a game + * controller. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, int touchpad); + +/** + * Get the current state of a finger on a touchpad on a game controller. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure); + +/** + * Return whether a game controller has a particular sensor. + * + * \param gamecontroller The controller to query + * \param type The type of sensor to query + * \returns SDL_TRUE if the sensor exists, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type); + +/** + * Set whether data reporting for a game controller sensor is enabled. + * + * \param gamecontroller The controller to update + * \param type The type of sensor to enable/disable + * \param enabled Whether data reporting should be enabled + * \returns 0 or -1 if an error occurred. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled); + +/** + * Query whether sensor data reporting is enabled for a game controller. + * + * \param gamecontroller The controller to query + * \param type The type of sensor to query + * \returns SDL_TRUE if the sensor is enabled, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type); + +/** + * Get the data rate (number of events per second) of a game controller + * sensor. + * + * \param gamecontroller The controller to query + * \param type The type of sensor to query + * \return the data rate, or 0.0f if the data rate is not available. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC float SDLCALL SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_SensorType type); + +/** + * Get the current state of a game controller sensor. + * + * The number of values and interpretation of the data is sensor dependent. + * See SDL_sensor.h for the details for each type of sensor. + * + * \param gamecontroller The controller to query + * \param type The type of sensor to query + * \param data A pointer filled with the current sensor state + * \param num_values The number of values to write to data + * \return 0 or -1 if an error occurred. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values); + +/** + * Start a rumble effect on a game controller. + * + * Each call to this function cancels any previous rumble effect, and calling + * it with 0 intensity stops any rumbling. + * + * \param gamecontroller The controller to vibrate + * \param low_frequency_rumble The intensity of the low frequency (left) + * rumble motor, from 0 to 0xFFFF + * \param high_frequency_rumble The intensity of the high frequency (right) + * rumble motor, from 0 to 0xFFFF + * \param duration_ms The duration of the rumble effect, in milliseconds + * \returns 0, or -1 if rumble isn't supported on this controller + * + * \since This function is available since SDL 2.0.9. + * + * \sa SDL_GameControllerHasRumble + */ +extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); + +/** + * Start a rumble effect in the game controller's triggers. + * + * Each call to this function cancels any previous trigger rumble effect, and + * calling it with 0 intensity stops any rumbling. + * + * Note that this is rumbling of the _triggers_ and not the game controller as + * a whole. The first controller to offer this feature was the PlayStation 5's + * DualShock 5. + * + * \param gamecontroller The controller to vibrate + * \param left_rumble The intensity of the left trigger rumble motor, from 0 + * to 0xFFFF + * \param right_rumble The intensity of the right trigger rumble motor, from 0 + * to 0xFFFF + * \param duration_ms The duration of the rumble effect, in milliseconds + * \returns 0, or -1 if trigger rumble isn't supported on this controller + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_GameControllerHasRumbleTriggers + */ +extern DECLSPEC int SDLCALL SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); + +/** + * Query whether a game controller has an LED. + * + * \param gamecontroller The controller to query + * \returns SDL_TRUE, or SDL_FALSE if this controller does not have a + * modifiable LED + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasLED(SDL_GameController *gamecontroller); + +/** + * Query whether a game controller has rumble support. + * + * \param gamecontroller The controller to query + * \returns SDL_TRUE, or SDL_FALSE if this controller does not have rumble + * support + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_GameControllerRumble + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasRumble(SDL_GameController *gamecontroller); + +/** + * Query whether a game controller has rumble support on triggers. + * + * \param gamecontroller The controller to query + * \returns SDL_TRUE, or SDL_FALSE if this controller does not have trigger + * rumble support + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_GameControllerRumbleTriggers + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller); + +/** + * Update a game controller's LED color. + * + * \param gamecontroller The controller to update + * \param red The intensity of the red LED + * \param green The intensity of the green LED + * \param blue The intensity of the blue LED + * \returns 0, or -1 if this controller does not have a modifiable LED + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue); + +/** + * Send a controller specific effect packet + * + * \param gamecontroller The controller to affect + * \param data The data to send to the controller + * \param size The size of the data to send to the controller + * \returns 0, or -1 if this controller or driver doesn't support effect + * packets + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerSendEffect(SDL_GameController *gamecontroller, const void *data, int size); + +/** + * Close a game controller previously opened with SDL_GameControllerOpen(). + * + * \param gamecontroller a game controller identifier previously returned by + * SDL_GameControllerOpen() + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerOpen */ extern DECLSPEC void SDLCALL SDL_GameControllerClose(SDL_GameController *gamecontroller); +/** + * Return the sfSymbolsName for a given button on a game controller on Apple + * platforms. + * + * \param gamecontroller the controller to query + * \param button a button on the game controller + * \returns the sfSymbolsName or NULL if the name can't be found + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_GameControllerGetAppleSFSymbolsNameForAxis + */ +extern DECLSPEC const char* SDLCALL SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button); + +/** + * Return the sfSymbolsName for a given axis on a game controller on Apple + * platforms. + * + * \param gamecontroller the controller to query + * \param axis an axis on the game controller + * \returns the sfSymbolsName or NULL if the name can't be found + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_GameControllerGetAppleSFSymbolsNameForButton + */ +extern DECLSPEC const char* SDLCALL SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_gamecontroller_h */ +#endif /* SDL_gamecontroller_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_gesture.h b/external/SDL2/SDL_gesture.h index 458c367..e2caea2 100644 --- a/external/SDL2/SDL_gesture.h +++ b/external/SDL2/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_gesture.h - * + * * Include file for SDL gesture event handling. */ -#ifndef _SDL_gesture_h -#define _SDL_gesture_h +#ifndef SDL_gesture_h_ +#define SDL_gesture_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -38,9 +38,7 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif typedef Sint64 SDL_GestureID; @@ -48,44 +46,72 @@ typedef Sint64 SDL_GestureID; /* Function prototypes */ /** - * \brief Begin Recording a gesture on the specified touch, or all touches (-1) + * Begin recording a gesture on a specified touch device or all touch devices. * + * If the parameter `touchId` is -1 (i.e., all devices), this function will + * always return 1, regardless of whether there actually are any devices. * + * \param touchId the touch device id, or -1 for all touch devices + * \returns 1 on success or 0 if the specified device could not be found. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTouchDevice */ extern DECLSPEC int SDLCALL SDL_RecordGesture(SDL_TouchID touchId); /** - * \brief Save all currently loaded Dollar Gesture templates + * Save all currently loaded Dollar Gesture templates. * + * \param dst a SDL_RWops to save to + * \returns the number of saved templates on success or 0 on failure; call + * SDL_GetError() for more information. * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadDollarTemplates + * \sa SDL_SaveDollarTemplate */ -extern DECLSPEC int SDLCALL SDL_SaveAllDollarTemplates(SDL_RWops *src); +extern DECLSPEC int SDLCALL SDL_SaveAllDollarTemplates(SDL_RWops *dst); /** - * \brief Save a currently loaded Dollar Gesture template + * Save a currently loaded Dollar Gesture template. * + * \param gestureId a gesture id + * \param dst a SDL_RWops to save to + * \returns 1 on success or 0 on failure; call SDL_GetError() for more + * information. * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadDollarTemplates + * \sa SDL_SaveAllDollarTemplates */ -extern DECLSPEC int SDLCALL SDL_SaveDollarTemplate(SDL_GestureID gestureId,SDL_RWops *src); +extern DECLSPEC int SDLCALL SDL_SaveDollarTemplate(SDL_GestureID gestureId,SDL_RWops *dst); /** - * \brief Load Dollar Gesture templates from a file + * Load Dollar Gesture templates from a file. * + * \param touchId a touch id + * \param src a SDL_RWops to load from + * \returns the number of loaded templates on success or a negative error code + * (or 0) on failure; call SDL_GetError() for more information. * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SaveAllDollarTemplates + * \sa SDL_SaveDollarTemplate */ extern DECLSPEC int SDLCALL SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src); - /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_gesture_h */ +#endif /* SDL_gesture_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_haptic.h b/external/SDL2/SDL_haptic.h index c506c29..f240ae9 100644 --- a/external/SDL2/SDL_haptic.h +++ b/external/SDL2/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,13 +21,13 @@ /** * \file SDL_haptic.h - * - * \brief The SDL Haptic subsystem allows you to control haptic (force feedback) + * + * \brief The SDL haptic subsystem allows you to control haptic (force feedback) * devices. - * + * * The basic usage is as follows: - * - Initialize the Subsystem (::SDL_INIT_HAPTIC). - * - Open a Haptic Device. + * - Initialize the subsystem (::SDL_INIT_HAPTIC). + * - Open a haptic device. * - SDL_HapticOpen() to open from index. * - SDL_HapticOpenFromJoystick() to open from an existing joystick. * - Create an effect (::SDL_HapticEffect). @@ -76,7 +76,7 @@ * } * * // Create the effect - * memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default + * SDL_memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default * effect.type = SDL_HAPTIC_SINE; * effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates * effect.periodic.direction.dir[0] = 18000; // Force comes from south @@ -102,15 +102,10 @@ * return 0; // Success * } * \endcode - * - * You can also find out more information on my blog: - * http://bobbens.dyndns.org/journal/2010/sdl_haptic/ - * - * \author Edgar Simo Serra */ -#ifndef _SDL_haptic_h -#define _SDL_haptic_h +#ifndef SDL_haptic_h_ +#define SDL_haptic_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -119,16 +114,25 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { - /* *INDENT-ON* */ #endif /* __cplusplus */ +/* FIXME: For SDL 2.1, adjust all the magnitude variables to be Uint16 (0xFFFF). + * + * At the moment the magnitude variables are mixed between signed/unsigned, and + * it is also not made clear that ALL of those variables expect a max of 0x7FFF. + * + * Some platforms may have higher precision than that (Linux FF, Windows XInput) + * so we should fix the inconsistency in favor of higher possible precision, + * adjusting for platforms that use different scales. + * -flibit + */ + /** * \typedef SDL_Haptic - * + * * \brief The haptic structure used to identify an SDL haptic. - * + * * \sa SDL_HapticOpen * \sa SDL_HapticOpenFromJoystick * \sa SDL_HapticClose @@ -139,195 +143,210 @@ typedef struct _SDL_Haptic SDL_Haptic; /** * \name Haptic features - * + * * Different haptic features a device can have. */ -/*@{*/ +/* @{ */ /** * \name Haptic effects */ -/*@{*/ +/* @{ */ /** * \brief Constant effect supported. * * Constant haptic effect. - * + * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_CONSTANT (1<<0) +#define SDL_HAPTIC_CONSTANT (1u<<0) /** * \brief Sine wave effect supported. - * + * * Periodic haptic effect that simulates sine waves. - * + * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_SINE (1<<1) +#define SDL_HAPTIC_SINE (1u<<1) /** - * \brief Square wave effect supported. - * - * Periodic haptic effect that simulates square waves. - * - * \sa SDL_HapticPeriodic + * \brief Left/Right effect supported. + * + * Haptic effect for direct control over high/low frequency motors. + * + * \sa SDL_HapticLeftRight + * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry, + * we ran out of bits, and this is important for XInput devices. */ -#define SDL_HAPTIC_SQUARE (1<<2) +#define SDL_HAPTIC_LEFTRIGHT (1u<<2) + +/* !!! FIXME: put this back when we have more bits in 2.1 */ +/* #define SDL_HAPTIC_SQUARE (1<<2) */ /** * \brief Triangle wave effect supported. - * + * * Periodic haptic effect that simulates triangular waves. - * + * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_TRIANGLE (1<<3) +#define SDL_HAPTIC_TRIANGLE (1u<<3) /** * \brief Sawtoothup wave effect supported. - * + * * Periodic haptic effect that simulates saw tooth up waves. - * + * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_SAWTOOTHUP (1<<4) +#define SDL_HAPTIC_SAWTOOTHUP (1u<<4) /** * \brief Sawtoothdown wave effect supported. - * + * * Periodic haptic effect that simulates saw tooth down waves. - * + * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_SAWTOOTHDOWN (1<<5) +#define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5) /** * \brief Ramp effect supported. - * + * * Ramp haptic effect. - * + * * \sa SDL_HapticRamp */ -#define SDL_HAPTIC_RAMP (1<<6) +#define SDL_HAPTIC_RAMP (1u<<6) /** * \brief Spring effect supported - uses axes position. - * + * * Condition haptic effect that simulates a spring. Effect is based on the * axes position. * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_SPRING (1<<7) +#define SDL_HAPTIC_SPRING (1u<<7) /** * \brief Damper effect supported - uses axes velocity. - * + * * Condition haptic effect that simulates dampening. Effect is based on the * axes velocity. - * + * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_DAMPER (1<<8) +#define SDL_HAPTIC_DAMPER (1u<<8) /** * \brief Inertia effect supported - uses axes acceleration. - * + * * Condition haptic effect that simulates inertia. Effect is based on the axes * acceleration. * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_INERTIA (1<<9) +#define SDL_HAPTIC_INERTIA (1u<<9) /** * \brief Friction effect supported - uses axes movement. - * - * Condition haptic effect that simulates friction. Effect is based on the + * + * Condition haptic effect that simulates friction. Effect is based on the * axes movement. - * + * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_FRICTION (1<<10) +#define SDL_HAPTIC_FRICTION (1u<<10) /** * \brief Custom effect is supported. - * + * * User defined custom haptic effect. */ -#define SDL_HAPTIC_CUSTOM (1<<11) +#define SDL_HAPTIC_CUSTOM (1u<<11) -/*@}*//*Haptic effects*/ +/* @} *//* Haptic effects */ /* These last few are features the device has, not effects */ /** * \brief Device can set global gain. - * + * * Device supports setting the global gain. - * + * * \sa SDL_HapticSetGain */ -#define SDL_HAPTIC_GAIN (1<<12) +#define SDL_HAPTIC_GAIN (1u<<12) /** * \brief Device can set autocenter. - * + * * Device supports setting autocenter. - * + * * \sa SDL_HapticSetAutocenter */ -#define SDL_HAPTIC_AUTOCENTER (1<<13) +#define SDL_HAPTIC_AUTOCENTER (1u<<13) /** * \brief Device can be queried for effect status. - * - * Device can be queried for effect status. - * + * + * Device supports querying effect status. + * * \sa SDL_HapticGetEffectStatus */ -#define SDL_HAPTIC_STATUS (1<<14) +#define SDL_HAPTIC_STATUS (1u<<14) /** * \brief Device can be paused. - * + * + * Devices supports being paused. + * * \sa SDL_HapticPause * \sa SDL_HapticUnpause */ -#define SDL_HAPTIC_PAUSE (1<<15) +#define SDL_HAPTIC_PAUSE (1u<<15) /** * \name Direction encodings */ -/*@{*/ +/* @{ */ /** * \brief Uses polar coordinates for the direction. - * + * * \sa SDL_HapticDirection */ #define SDL_HAPTIC_POLAR 0 /** * \brief Uses cartesian coordinates for the direction. - * + * * \sa SDL_HapticDirection */ #define SDL_HAPTIC_CARTESIAN 1 /** * \brief Uses spherical coordinates for the direction. - * + * * \sa SDL_HapticDirection */ #define SDL_HAPTIC_SPHERICAL 2 -/*@}*//*Direction encodings*/ +/** + * \brief Use this value to play an effect on the steering wheel axis. This + * provides better compatibility across platforms and devices as SDL will guess + * the correct axis. + * \sa SDL_HapticDirection + */ +#define SDL_HAPTIC_STEERING_AXIS 3 -/*@}*//*Haptic features*/ +/* @} *//* Direction encodings */ + +/* @} *//* Haptic features */ /* * Misc defines. @@ -343,7 +362,10 @@ typedef struct _SDL_Haptic SDL_Haptic; /** * \brief Structure that represents a haptic direction. - * + * + * This is the direction where the force comes from, + * instead of the direction in which the force is exerted. + * * Directions can be specified by: * - ::SDL_HAPTIC_POLAR : Specified by polar coordinates. * - ::SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates. @@ -361,47 +383,47 @@ typedef struct _SDL_Haptic SDL_Haptic; | | |'-----'| |__|~')_____(' [ COMPUTER ] - - + + North (0,-1) ^ | | - (1,0) West <----[ HAPTIC ]----> East (-1,0) + (-1,0) West <----[ HAPTIC ]----> East (1,0) | | v South (0,1) - - + + [ USER ] \|||/ (o o) ---ooO-(_)-Ooo--- \endverbatim - * - * If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a + * + * If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a * degree starting north and turning clockwise. ::SDL_HAPTIC_POLAR only uses * the first \c dir parameter. The cardinal directions would be: * - North: 0 (0 degrees) * - East: 9000 (90 degrees) * - South: 18000 (180 degrees) * - West: 27000 (270 degrees) - * + * * If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions * (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses * the first three \c dir parameters. The cardinal directions would be: * - North: 0,-1, 0 - * - East: -1, 0, 0 + * - East: 1, 0, 0 * - South: 0, 1, 0 - * - West: 1, 0, 0 - * + * - West: -1, 0, 0 + * * The Z axis represents the height of the effect if supported, otherwise * it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you * can use any multiple you want, only the direction matters. - * + * * If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations. - * The first two \c dir parameters are used. The \c dir parameters are as + * The first two \c dir parameters are used. The \c dir parameters are as * follows (all values are in hundredths of degrees): * - Degrees from (1, 0) rotated towards (0, 1). * - Degrees towards (0, 0, 1) (device needs at least 3 axes). @@ -411,17 +433,17 @@ typedef struct _SDL_Haptic SDL_Haptic; * from the south means the user will have to pull the stick to counteract): * \code * SDL_HapticDirection direction; - * + * * // Cartesian directions * direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding. * direction.dir[0] = 0; // X position * direction.dir[1] = 1; // Y position * // Assuming the device has 2 axes, we don't need to specify third parameter. - * + * * // Polar directions * direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding. * direction.dir[0] = 18000; // Polar only uses first parameter - * + * * // Spherical coordinates * direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding * direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters. @@ -430,6 +452,7 @@ typedef struct _SDL_Haptic SDL_Haptic; * \sa SDL_HAPTIC_POLAR * \sa SDL_HAPTIC_CARTESIAN * \sa SDL_HAPTIC_SPHERICAL + * \sa SDL_HAPTIC_STEERING_AXIS * \sa SDL_HapticEffect * \sa SDL_HapticNumAxes */ @@ -442,12 +465,12 @@ typedef struct SDL_HapticDirection /** * \brief A structure containing a template for a Constant effect. - * - * The struct is exclusive to the ::SDL_HAPTIC_CONSTANT effect. - * + * + * This struct is exclusively for the ::SDL_HAPTIC_CONSTANT effect. + * * A constant effect applies a constant force in the specified direction * to the joystick. - * + * * \sa SDL_HAPTIC_CONSTANT * \sa SDL_HapticEffect */ @@ -477,25 +500,25 @@ typedef struct SDL_HapticConstant /** * \brief A structure containing a template for a Periodic effect. - * + * * The struct handles the following effects: * - ::SDL_HAPTIC_SINE - * - ::SDL_HAPTIC_SQUARE + * - ::SDL_HAPTIC_LEFTRIGHT * - ::SDL_HAPTIC_TRIANGLE * - ::SDL_HAPTIC_SAWTOOTHUP * - ::SDL_HAPTIC_SAWTOOTHDOWN - * + * * A periodic effect consists in a wave-shaped effect that repeats itself * over time. The type determines the shape of the wave and the parameters * determine the dimensions of the wave. - * - * Phase is given by hundredth of a cyle meaning that giving the phase a value - * of 9000 will displace it 25% of it's period. Here are sample values: + * + * Phase is given by hundredth of a degree meaning that giving the phase a value + * of 9000 will displace it 25% of its period. Here are sample values: * - 0: No phase displacement. - * - 9000: Displaced 25% of it's period. - * - 18000: Displaced 50% of it's period. - * - 27000: Displaced 75% of it's period. - * - 36000: Displaced 100% of it's period, same as 0, but 0 is preffered. + * - 9000: Displaced 25% of its period. + * - 18000: Displaced 50% of its period. + * - 27000: Displaced 75% of its period. + * - 36000: Displaced 100% of its period, same as 0, but 0 is preferred. * * Examples: * \verbatim @@ -503,30 +526,30 @@ typedef struct SDL_HapticConstant __ __ __ __ / \ / \ / \ / / \__/ \__/ \__/ - + SDL_HAPTIC_SQUARE __ __ __ __ __ | | | | | | | | | | | |__| |__| |__| |__| | - + SDL_HAPTIC_TRIANGLE /\ /\ /\ /\ /\ / \ / \ / \ / \ / / \/ \/ \/ \/ - + SDL_HAPTIC_SAWTOOTHUP /| /| /| /| /| /| /| / | / | / | / | / | / | / | / |/ |/ |/ |/ |/ |/ | - + SDL_HAPTIC_SAWTOOTHDOWN \ |\ |\ |\ |\ |\ |\ | \ | \ | \ | \ | \ | \ | \ | \| \| \| \| \| \| \| \endverbatim - * + * * \sa SDL_HAPTIC_SINE - * \sa SDL_HAPTIC_SQUARE + * \sa SDL_HAPTIC_LEFTRIGHT * \sa SDL_HAPTIC_TRIANGLE * \sa SDL_HAPTIC_SAWTOOTHUP * \sa SDL_HAPTIC_SAWTOOTHDOWN @@ -535,7 +558,7 @@ typedef struct SDL_HapticConstant typedef struct SDL_HapticPeriodic { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_SQUARE, + Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT, ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or ::SDL_HAPTIC_SAWTOOTHDOWN */ SDL_HapticDirection direction; /**< Direction of the effect. */ @@ -550,9 +573,9 @@ typedef struct SDL_HapticPeriodic /* Periodic */ Uint16 period; /**< Period of the wave. */ - Sint16 magnitude; /**< Peak value. */ + Sint16 magnitude; /**< Peak value; if negative, equivalent to 180 degrees extra phase shift. */ Sint16 offset; /**< Mean value of the wave. */ - Uint16 phase; /**< Horizontal shift given by hundredth of a cycle. */ + Uint16 phase; /**< Positive phase shift given by hundredth of a degree. */ /* Envelope */ Uint16 attack_length; /**< Duration of the attack. */ @@ -563,21 +586,21 @@ typedef struct SDL_HapticPeriodic /** * \brief A structure containing a template for a Condition effect. - * + * * The struct handles the following effects: * - ::SDL_HAPTIC_SPRING: Effect based on axes position. * - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity. * - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration. * - ::SDL_HAPTIC_FRICTION: Effect based on axes movement. - * + * * Direction is handled by condition internals instead of a direction member. * The condition effect specific members have three parameters. The first * refers to the X axis, the second refers to the Y axis and the third * refers to the Z axis. The right terms refer to the positive side of the - * axis and the left terms refer to the negative side of the axis. Please + * axis and the left terms refer to the negative side of the axis. Please * refer to the ::SDL_HapticDirection diagram for which side is positive and * which is negative. - * + * * \sa SDL_HapticDirection * \sa SDL_HAPTIC_SPRING * \sa SDL_HAPTIC_DAMPER @@ -601,24 +624,24 @@ typedef struct SDL_HapticCondition Uint16 interval; /**< How soon it can be triggered again after button. */ /* Condition */ - Uint16 right_sat[3]; /**< Level when joystick is to the positive side. */ - Uint16 left_sat[3]; /**< Level when joystick is to the negative side. */ + Uint16 right_sat[3]; /**< Level when joystick is to the positive side; max 0xFFFF. */ + Uint16 left_sat[3]; /**< Level when joystick is to the negative side; max 0xFFFF. */ Sint16 right_coeff[3]; /**< How fast to increase the force towards the positive side. */ Sint16 left_coeff[3]; /**< How fast to increase the force towards the negative side. */ - Uint16 deadband[3]; /**< Size of the dead zone. */ + Uint16 deadband[3]; /**< Size of the dead zone; max 0xFFFF: whole axis-range when 0-centered. */ Sint16 center[3]; /**< Position of the dead zone. */ } SDL_HapticCondition; /** * \brief A structure containing a template for a Ramp effect. - * + * * This struct is exclusively for the ::SDL_HAPTIC_RAMP effect. - * + * * The ramp effect starts at start strength and ends at end strength. * It augments in linear fashion. If you use attack and fade with a ramp - * they effects get added to the ramp effect making the effect become + * the effects get added to the ramp effect making the effect become * quadratic instead of linear. - * + * * \sa SDL_HAPTIC_RAMP * \sa SDL_HapticEffect */ @@ -647,16 +670,43 @@ typedef struct SDL_HapticRamp Uint16 fade_level; /**< Level at the end of the fade. */ } SDL_HapticRamp; +/** + * \brief A structure containing a template for a Left/Right effect. + * + * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect. + * + * The Left/Right effect is used to explicitly control the large and small + * motors, commonly found in modern game controllers. The small (right) motor + * is high frequency, and the large (left) motor is low frequency. + * + * \sa SDL_HAPTIC_LEFTRIGHT + * \sa SDL_HapticEffect + */ +typedef struct SDL_HapticLeftRight +{ + /* Header */ + Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */ + + /* Replay */ + Uint32 length; /**< Duration of the effect in milliseconds. */ + + /* Rumble */ + Uint16 large_magnitude; /**< Control of the large controller motor. */ + Uint16 small_magnitude; /**< Control of the small controller motor. */ +} SDL_HapticLeftRight; + /** * \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect. - * + * + * This struct is exclusively for the ::SDL_HAPTIC_CUSTOM effect. + * * A custom force feedback effect is much like a periodic effect, where the - * application can define it's exact shape. You will have to allocate the + * application can define its exact shape. You will have to allocate the * data yourself. Data should consist of channels * samples Uint16 samples. - * + * * If channels is one, the effect is rotated using the defined direction. * Otherwise it uses the samples in data for the different axes. - * + * * \sa SDL_HAPTIC_CUSTOM * \sa SDL_HapticEffect */ @@ -689,34 +739,34 @@ typedef struct SDL_HapticCustom /** * \brief The generic template for any haptic effect. - * + * * All values max at 32767 (0x7FFF). Signed values also can be negative. * Time values unless specified otherwise are in milliseconds. - * - * You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767 - * value. Neither delay, interval, attack_length nor fade_length support + * + * You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767 + * value. Neither delay, interval, attack_length nor fade_length support * ::SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends. - * + * * Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of * ::SDL_HAPTIC_INFINITY. - * + * * Button triggers may not be supported on all devices, it is advised to not * use them if possible. Buttons start at index 1 instead of index 0 like - * they joystick. - * + * the joystick. + * * If both attack_length and fade_level are 0, the envelope is not used, * otherwise both values are used. - * + * * Common parts: * \code * // Replay - All effects have this * Uint32 length; // Duration of effect (ms). * Uint16 delay; // Delay before starting effect. - * + * * // Trigger - All effects have this * Uint16 button; // Button that triggers effect. * Uint16 interval; // How soon before effect can be triggered again. - * + * * // Envelope - All effects except condition effects have this * Uint16 attack_length; // Duration of the attack (ms). * Uint16 attack_level; // Level at the start of the attack. @@ -734,18 +784,18 @@ typedef struct SDL_HapticCustom | / \ | / \ | / \ - | / \ + | / \ | attack_level --> | \ | | | <--- fade_level | +--------------------------------------------------> Time [--] [---] attack_length fade_length - + [------------------][-----------------------] delay length \endverbatim - * + * * Note either the attack_level or the fade_level may be above the actual * effect level. * @@ -753,6 +803,7 @@ typedef struct SDL_HapticCustom * \sa SDL_HapticPeriodic * \sa SDL_HapticCondition * \sa SDL_HapticRamp + * \sa SDL_HapticLeftRight * \sa SDL_HapticCustom */ typedef union SDL_HapticEffect @@ -763,438 +814,528 @@ typedef union SDL_HapticEffect SDL_HapticPeriodic periodic; /**< Periodic effect. */ SDL_HapticCondition condition; /**< Condition effect. */ SDL_HapticRamp ramp; /**< Ramp effect. */ + SDL_HapticLeftRight leftright; /**< Left/Right effect. */ SDL_HapticCustom custom; /**< Custom effect. */ } SDL_HapticEffect; /* Function prototypes */ + /** - * \brief Count the number of joysticks attached to the system. - * - * \return Number of haptic devices detected on the system. + * Count the number of haptic devices attached to the system. + * + * \returns the number of haptic devices detected on the system or a negative + * error code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticName */ extern DECLSPEC int SDLCALL SDL_NumHaptics(void); /** - * \brief Get the implementation dependent name of a Haptic device. - * - * This can be called before any joysticks are opened. - * If no name can be found, this function returns NULL. - * - * \param device_index Index of the device to get it's name. - * \return Name of the device or NULL on error. + * Get the implementation dependent name of a haptic device. * - * \sa SDL_NumHaptics + * This can be called before any joysticks are opened. If no name can be + * found, this function returns NULL. + * + * \param device_index index of the device to query. + * \returns the name of the device or NULL on failure; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_NumHaptics */ extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index); /** - * \brief Opens a Haptic device for usage. - * - * The index passed as an argument refers to the N'th Haptic device on this - * system. + * Open a haptic device for use. * - * When opening a haptic device, it's gain will be set to maximum and - * autocenter will be disabled. To modify these values use - * SDL_HapticSetGain() and SDL_HapticSetAutocenter(). + * The index passed as an argument refers to the N'th haptic device on this + * system. * - * \param device_index Index of the device to open. - * \return Device identifier or NULL on error. + * When opening a haptic device, its gain will be set to maximum and + * autocenter will be disabled. To modify these values use SDL_HapticSetGain() + * and SDL_HapticSetAutocenter(). * - * \sa SDL_HapticIndex - * \sa SDL_HapticOpenFromMouse - * \sa SDL_HapticOpenFromJoystick - * \sa SDL_HapticClose - * \sa SDL_HapticSetGain - * \sa SDL_HapticSetAutocenter - * \sa SDL_HapticPause - * \sa SDL_HapticStopAll + * \param device_index index of the device to open + * \returns the device identifier or NULL on failure; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticClose + * \sa SDL_HapticIndex + * \sa SDL_HapticOpenFromJoystick + * \sa SDL_HapticOpenFromMouse + * \sa SDL_HapticPause + * \sa SDL_HapticSetAutocenter + * \sa SDL_HapticSetGain + * \sa SDL_HapticStopAll */ extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpen(int device_index); /** - * \brief Checks if the haptic device at index has been opened. - * - * \param device_index Index to check to see if it has been opened. - * \return 1 if it has been opened or 0 if it hasn't. - * - * \sa SDL_HapticOpen - * \sa SDL_HapticIndex + * Check if the haptic device at the designated index has been opened. + * + * \param device_index the index of the device to query + * \returns 1 if it has been opened, 0 if it hasn't or on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticIndex + * \sa SDL_HapticOpen */ extern DECLSPEC int SDLCALL SDL_HapticOpened(int device_index); /** - * \brief Gets the index of a haptic device. - * - * \param haptic Haptic device to get the index of. - * \return The index of the haptic device or -1 on error. - * - * \sa SDL_HapticOpen - * \sa SDL_HapticOpened + * Get the index of a haptic device. + * + * \param haptic the SDL_Haptic device to query + * \returns the index of the specified haptic device or a negative error code + * on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticOpen + * \sa SDL_HapticOpened */ extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic); /** - * \brief Gets whether or not the current mouse has haptic capabilities. - * - * \return SDL_TRUE if the mouse is haptic, SDL_FALSE if it isn't. - * - * \sa SDL_HapticOpenFromMouse + * Query whether or not the current mouse has haptic capabilities. + * + * \returns SDL_TRUE if the mouse is haptic or SDL_FALSE if it isn't. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticOpenFromMouse */ extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void); /** - * \brief Tries to open a haptic device from the current mouse. - * - * \return The haptic device identifier or NULL on error. - * - * \sa SDL_MouseIsHaptic - * \sa SDL_HapticOpen + * Try to open a haptic device from the current mouse. + * + * \returns the haptic device identifier or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticOpen + * \sa SDL_MouseIsHaptic */ extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromMouse(void); /** - * \brief Checks to see if a joystick has haptic features. - * - * \param joystick Joystick to test for haptic capabilities. - * \return 1 if the joystick is haptic, 0 if it isn't - * or -1 if an error ocurred. - * - * \sa SDL_HapticOpenFromJoystick + * Query if a joystick has haptic features. + * + * \param joystick the SDL_Joystick to test for haptic capabilities + * \returns SDL_TRUE if the joystick is haptic, SDL_FALSE if it isn't, or a + * negative error code on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticOpenFromJoystick */ extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick); /** - * \brief Opens a Haptic device for usage from a Joystick device. - * - * You must still close the haptic device seperately. It will not be closed - * with the joystick. - * - * When opening from a joystick you should first close the haptic device before - * closing the joystick device. If not, on some implementations the haptic - * device will also get unallocated and you'll be unable to use force feedback - * on that device. - * - * \param joystick Joystick to create a haptic device from. - * \return A valid haptic device identifier on success or NULL on error. - * - * \sa SDL_HapticOpen - * \sa SDL_HapticClose + * Open a haptic device for use from a joystick device. + * + * You must still close the haptic device separately. It will not be closed + * with the joystick. + * + * When opened from a joystick you should first close the haptic device before + * closing the joystick device. If not, on some implementations the haptic + * device will also get unallocated and you'll be unable to use force feedback + * on that device. + * + * \param joystick the SDL_Joystick to create a haptic device from + * \returns a valid haptic device identifier on success or NULL on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticClose + * \sa SDL_HapticOpen + * \sa SDL_JoystickIsHaptic */ extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromJoystick(SDL_Joystick * joystick); /** - * \brief Closes a Haptic device previously opened with SDL_HapticOpen(). - * - * \param haptic Haptic device to close. + * Close a haptic device previously opened with SDL_HapticOpen(). + * + * \param haptic the SDL_Haptic device to close + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticOpen */ extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic); /** - * \brief Returns the number of effects a haptic device can store. - * - * On some platforms this isn't fully supported, and therefore is an - * aproximation. Always check to see if your created effect was actually - * created and do not rely solely on SDL_HapticNumEffects(). - * - * \param haptic The haptic device to query effect max. - * \return The number of effects the haptic device can store or - * -1 on error. - * - * \sa SDL_HapticNumEffectsPlaying - * \sa SDL_HapticQuery + * Get the number of effects a haptic device can store. + * + * On some platforms this isn't fully supported, and therefore is an + * approximation. Always check to see if your created effect was actually + * created and do not rely solely on SDL_HapticNumEffects(). + * + * \param haptic the SDL_Haptic device to query + * \returns the number of effects the haptic device can store or a negative + * error code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticNumEffectsPlaying + * \sa SDL_HapticQuery */ extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic); /** - * \brief Returns the number of effects a haptic device can play at the same - * time. - * - * This is not supported on all platforms, but will always return a value. - * Added here for the sake of completness. - * - * \param haptic The haptic device to query maximum playing effects. - * \return The number of effects the haptic device can play at the same time - * or -1 on error. + * Get the number of effects a haptic device can play at the same time. * - * \sa SDL_HapticNumEffects - * \sa SDL_HapticQuery + * This is not supported on all platforms, but will always return a value. + * + * \param haptic the SDL_Haptic device to query maximum playing effects + * \returns the number of effects the haptic device can play at the same time + * or a negative error code on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticNumEffects + * \sa SDL_HapticQuery */ extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic); /** - * \brief Gets the haptic devices supported features in bitwise matter. - * - * Example: - * \code - * if (SDL_HapticQueryEffects(haptic) & SDL_HAPTIC_CONSTANT) { - * printf("We have constant haptic effect!"); - * } - * \endcode - * - * \param haptic The haptic device to query. - * \return Haptic features in bitwise manner (OR'd). - * - * \sa SDL_HapticNumEffects - * \sa SDL_HapticEffectSupported + * Get the haptic device's supported features in bitwise manner. + * + * \param haptic the SDL_Haptic device to query + * \returns a list of supported haptic features in bitwise manner (OR'd), or 0 + * on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticEffectSupported + * \sa SDL_HapticNumEffects */ extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic); /** - * \brief Gets the number of haptic axes the device has. - * - * \sa SDL_HapticDirection + * Get the number of haptic axes the device has. + * + * The number of haptic axes might be useful if working with the + * SDL_HapticDirection effect. + * + * \param haptic the SDL_Haptic device to query + * \returns the number of axes on success or a negative error code on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_HapticNumAxes(SDL_Haptic * haptic); /** - * \brief Checks to see if effect is supported by haptic. - * - * \param haptic Haptic device to check on. - * \param effect Effect to check to see if it is supported. - * \return SDL_TRUE if effect is supported, SDL_FALSE if it isn't or -1 on error. - * - * \sa SDL_HapticQuery - * \sa SDL_HapticNewEffect + * Check to see if an effect is supported by a haptic device. + * + * \param haptic the SDL_Haptic device to query + * \param effect the desired effect to query + * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a + * negative error code on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticNewEffect + * \sa SDL_HapticQuery */ extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic, SDL_HapticEffect * effect); /** - * \brief Creates a new haptic effect on the device. - * - * \param haptic Haptic device to create the effect on. - * \param effect Properties of the effect to create. - * \return The id of the effect on success or -1 on error. - * - * \sa SDL_HapticUpdateEffect - * \sa SDL_HapticRunEffect - * \sa SDL_HapticDestroyEffect + * Create a new haptic effect on a specified device. + * + * \param haptic an SDL_Haptic device to create the effect on + * \param effect an SDL_HapticEffect structure containing the properties of + * the effect to create + * \returns the ID of the effect on success or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticDestroyEffect + * \sa SDL_HapticRunEffect + * \sa SDL_HapticUpdateEffect */ extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic, SDL_HapticEffect * effect); /** - * \brief Updates the properties of an effect. - * - * Can be used dynamically, although behaviour when dynamically changing - * direction may be strange. Specifically the effect may reupload itself - * and start playing from the start. You cannot change the type either when - * running SDL_HapticUpdateEffect(). - * - * \param haptic Haptic device that has the effect. - * \param effect Effect to update. - * \param data New effect properties to use. - * \return The id of the effect on success or -1 on error. - * - * \sa SDL_HapticNewEffect - * \sa SDL_HapticRunEffect - * \sa SDL_HapticDestroyEffect + * Update the properties of an effect. + * + * Can be used dynamically, although behavior when dynamically changing + * direction may be strange. Specifically the effect may re-upload itself and + * start playing from the start. You also cannot change the type either when + * running SDL_HapticUpdateEffect(). + * + * \param haptic the SDL_Haptic device that has the effect + * \param effect the identifier of the effect to update + * \param data an SDL_HapticEffect structure containing the new effect + * properties to use + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticDestroyEffect + * \sa SDL_HapticNewEffect + * \sa SDL_HapticRunEffect */ extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic, int effect, SDL_HapticEffect * data); /** - * \brief Runs the haptic effect on it's assosciated haptic device. - * - * If iterations are ::SDL_HAPTIC_INFINITY, it'll run the effect over and over - * repeating the envelope (attack and fade) every time. If you only want the - * effect to last forever, set ::SDL_HAPTIC_INFINITY in the effect's length - * parameter. - * - * \param haptic Haptic device to run the effect on. - * \param effect Identifier of the haptic effect to run. - * \param iterations Number of iterations to run the effect. Use - * ::SDL_HAPTIC_INFINITY for infinity. - * \return 0 on success or -1 on error. - * - * \sa SDL_HapticStopEffect - * \sa SDL_HapticDestroyEffect - * \sa SDL_HapticGetEffectStatus + * Run the haptic effect on its associated haptic device. + * + * To repeat the effect over and over indefinitely, set `iterations` to + * `SDL_HAPTIC_INFINITY`. (Repeats the envelope - attack and fade.) To make + * one instance of the effect last indefinitely (so the effect does not fade), + * set the effect's `length` in its structure/union to `SDL_HAPTIC_INFINITY` + * instead. + * + * \param haptic the SDL_Haptic device to run the effect on + * \param effect the ID of the haptic effect to run + * \param iterations the number of iterations to run the effect; use + * `SDL_HAPTIC_INFINITY` to repeat forever + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticDestroyEffect + * \sa SDL_HapticGetEffectStatus + * \sa SDL_HapticStopEffect */ extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic, int effect, Uint32 iterations); /** - * \brief Stops the haptic effect on it's assosciated haptic device. - * - * \param haptic Haptic device to stop the effect on. - * \param effect Identifier of the effect to stop. - * \return 0 on success or -1 on error. - * - * \sa SDL_HapticRunEffect - * \sa SDL_HapticDestroyEffect + * Stop the haptic effect on its associated haptic device. + * + * * + * + * \param haptic the SDL_Haptic device to stop the effect on + * \param effect the ID of the haptic effect to stop + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticDestroyEffect + * \sa SDL_HapticRunEffect */ extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic, int effect); /** - * \brief Destroys a haptic effect on the device. - * - * This will stop the effect if it's running. Effects are automatically - * destroyed when the device is closed. - * - * \param haptic Device to destroy the effect on. - * \param effect Identifier of the effect to destroy. - * - * \sa SDL_HapticNewEffect + * Destroy a haptic effect on the device. + * + * This will stop the effect if it's running. Effects are automatically + * destroyed when the device is closed. + * + * \param haptic the SDL_Haptic device to destroy the effect on + * \param effect the ID of the haptic effect to destroy + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticNewEffect */ extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic, int effect); /** - * \brief Gets the status of the current effect on the haptic device. - * - * Device must support the ::SDL_HAPTIC_STATUS feature. - * - * \param haptic Haptic device to query the effect status on. - * \param effect Identifier of the effect to query it's status. - * \return 0 if it isn't playing, ::SDL_HAPTIC_PLAYING if it is playing - * or -1 on error. - * - * \sa SDL_HapticRunEffect - * \sa SDL_HapticStopEffect + * Get the status of the current effect on the specified haptic device. + * + * Device must support the SDL_HAPTIC_STATUS feature. + * + * \param haptic the SDL_Haptic device to query for the effect status on + * \param effect the ID of the haptic effect to query its status + * \returns 0 if it isn't playing, 1 if it is playing, or a negative error + * code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticRunEffect + * \sa SDL_HapticStopEffect */ extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic, int effect); /** - * \brief Sets the global gain of the device. - * - * Device must support the ::SDL_HAPTIC_GAIN feature. - * - * The user may specify the maxmimum gain by setting the environment variable - * ::SDL_HAPTIC_GAIN_MAX which should be between 0 and 100. All calls to - * SDL_HapticSetGain() will scale linearly using ::SDL_HAPTIC_GAIN_MAX as the - * maximum. - * - * \param haptic Haptic device to set the gain on. - * \param gain Value to set the gain to, should be between 0 and 100. - * \return 0 on success or -1 on error. - * - * \sa SDL_HapticQuery + * Set the global gain of the specified haptic device. + * + * Device must support the SDL_HAPTIC_GAIN feature. + * + * The user may specify the maximum gain by setting the environment variable + * `SDL_HAPTIC_GAIN_MAX` which should be between 0 and 100. All calls to + * SDL_HapticSetGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the + * maximum. + * + * \param haptic the SDL_Haptic device to set the gain on + * \param gain value to set the gain to, should be between 0 and 100 (0 - 100) + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticQuery */ extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain); /** - * \brief Sets the global autocenter of the device. - * - * Autocenter should be between 0 and 100. Setting it to 0 will disable - * autocentering. + * Set the global autocenter of the device. * - * Device must support the ::SDL_HAPTIC_AUTOCENTER feature. + * Autocenter should be between 0 and 100. Setting it to 0 will disable + * autocentering. * - * \param haptic Haptic device to set autocentering on. - * \param autocenter Value to set autocenter to, 0 disables autocentering. - * \return 0 on success or -1 on error. - * - * \sa SDL_HapticQuery + * Device must support the SDL_HAPTIC_AUTOCENTER feature. + * + * \param haptic the SDL_Haptic device to set autocentering on + * \param autocenter value to set autocenter to (0-100) + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticQuery */ extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter); /** - * \brief Pauses a haptic device. - * - * Device must support the ::SDL_HAPTIC_PAUSE feature. Call - * SDL_HapticUnpause() to resume playback. - * - * Do not modify the effects nor add new ones while the device is paused. - * That can cause all sorts of weird errors. - * - * \param haptic Haptic device to pause. - * \return 0 on success or -1 on error. - * - * \sa SDL_HapticUnpause + * Pause a haptic device. + * + * Device must support the `SDL_HAPTIC_PAUSE` feature. Call + * SDL_HapticUnpause() to resume playback. + * + * Do not modify the effects nor add new ones while the device is paused. That + * can cause all sorts of weird errors. + * + * \param haptic the SDL_Haptic device to pause + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticUnpause */ extern DECLSPEC int SDLCALL SDL_HapticPause(SDL_Haptic * haptic); /** - * \brief Unpauses a haptic device. - * - * Call to unpause after SDL_HapticPause(). - * - * \param haptic Haptic device to pause. - * \return 0 on success or -1 on error. - * - * \sa SDL_HapticPause + * Unpause a haptic device. + * + * Call to unpause after SDL_HapticPause(). + * + * \param haptic the SDL_Haptic device to unpause + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticPause */ extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic); /** - * \brief Stops all the currently playing effects on a haptic device. - * - * \param haptic Haptic device to stop. - * \return 0 on success or -1 on error. + * Stop all the currently playing effects on a haptic device. + * + * \param haptic the SDL_Haptic device to stop + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_HapticStopAll(SDL_Haptic * haptic); /** - * \brief Checks to see if rumble is supported on a haptic device.. + * Check whether rumble is supported on a haptic device. * - * \param haptic Haptic device to check to see if it supports rumble. - * \return SDL_TRUE if effect is supported, SDL_FALSE if it isn't or -1 on error. + * \param haptic haptic device to check for rumble support + * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a + * negative error code on failure; call SDL_GetError() for more + * information. * - * \sa SDL_HapticRumbleInit - * \sa SDL_HapticRumblePlay - * \sa SDL_HapticRumbleStop + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticRumbleInit + * \sa SDL_HapticRumblePlay + * \sa SDL_HapticRumbleStop */ extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic); /** - * \brief Initializes the haptic device for simple rumble playback. + * Initialize a haptic device for simple rumble playback. * - * \param haptic Haptic device to initialize for simple rumble playback. - * \return 0 on success or -1 on error. + * \param haptic the haptic device to initialize for simple rumble playback + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * - * \sa SDL_HapticOpen - * \sa SDL_HapticRumbleSupported - * \sa SDL_HapticRumblePlay - * \sa SDL_HapticRumbleStop + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticOpen + * \sa SDL_HapticRumblePlay + * \sa SDL_HapticRumbleStop + * \sa SDL_HapticRumbleSupported */ extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic); /** - * \brief Runs simple rumble on a haptic device + * Run a simple rumble effect on a haptic device. * - * \param haptic Haptic device to play rumble effect on. - * \param strength Strength of the rumble to play as a 0-1 float value. - * \param length Length of the rumble to play in miliseconds. - * \return 0 on success or -1 on error. + * \param haptic the haptic device to play the rumble effect on + * \param strength strength of the rumble to play as a 0-1 float value + * \param length length of the rumble to play in milliseconds + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * - * \sa SDL_HapticRumbleSupported - * \sa SDL_HapticRumbleInit - * \sa SDL_HapticRumbleStop + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticRumbleInit + * \sa SDL_HapticRumbleStop + * \sa SDL_HapticRumbleSupported */ extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length ); /** - * \brief Stops the simple rumble on a haptic device. + * Stop the simple rumble on a haptic device. * - * \param haptic Haptic to stop the rumble on. - * \return 0 on success or -1 on error. + * \param haptic the haptic device to stop the rumble effect on + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * - * \sa SDL_HapticRumbleSupported - * \sa SDL_HapticRumbleInit - * \sa SDL_HapticRumblePlay + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HapticRumbleInit + * \sa SDL_HapticRumblePlay + * \sa SDL_HapticRumbleSupported */ extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic); - - /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_haptic_h */ +#endif /* SDL_haptic_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_hidapi.h b/external/SDL2/SDL_hidapi.h new file mode 100644 index 0000000..354af5c --- /dev/null +++ b/external/SDL2/SDL_hidapi.h @@ -0,0 +1,451 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_hidapi.h + * + * Header file for SDL HIDAPI functions. + * + * This is an adaptation of the original HIDAPI interface by Alan Ott, + * and includes source code licensed under the following BSD license: + * + Copyright (c) 2010, Alan Ott, Signal 11 Software + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Signal 11 Software nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + * + * If you would like a version of SDL without this code, you can build SDL + * with SDL_HIDAPI_DISABLED defined to 1. You might want to do this for example + * on iOS or tvOS to avoid a dependency on the CoreBluetooth framework. + */ + +#ifndef SDL_hidapi_h_ +#define SDL_hidapi_h_ + +#include "SDL_stdinc.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief A handle representing an open HID device + */ +struct SDL_hid_device_; +typedef struct SDL_hid_device_ SDL_hid_device; /**< opaque hidapi structure */ + +/** hidapi info structure */ +/** + * \brief Information about a connected HID device + */ +typedef struct SDL_hid_device_info +{ + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac only). */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac only).*/ + unsigned short usage; + /** The USB interface which this logical device + represents. + + * Valid on both Linux implementations in all cases. + * Valid on the Windows implementation only if the device + contains more than one interface. */ + int interface_number; + + /** Additional information about the USB interface. + Valid on libusb and Android implementations. */ + int interface_class; + int interface_subclass; + int interface_protocol; + + /** Pointer to the next device */ + struct SDL_hid_device_info *next; +} SDL_hid_device_info; + + +/** + * Initialize the HIDAPI library. + * + * This function initializes the HIDAPI library. Calling it is not strictly + * necessary, as it will be called automatically by SDL_hid_enumerate() and + * any of the SDL_hid_open_*() functions if it is needed. This function should + * be called at the beginning of execution however, if there is a chance of + * HIDAPI handles being opened by different threads simultaneously. + * + * Each call to this function should have a matching call to SDL_hid_exit() + * + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_hid_exit + */ +extern DECLSPEC int SDLCALL SDL_hid_init(void); + +/** + * Finalize the HIDAPI library. + * + * This function frees all of the static data associated with HIDAPI. It + * should be called at the end of execution to avoid memory leaks. + * + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_hid_init + */ +extern DECLSPEC int SDLCALL SDL_hid_exit(void); + +/** + * Check to see if devices may have been added or removed. + * + * Enumerating the HID devices is an expensive operation, so you can call this + * to see if there have been any system device changes since the last call to + * this function. A change in the counter returned doesn't necessarily mean + * that anything has changed, but you can call SDL_hid_enumerate() to get an + * updated device list. + * + * Calling this function for the first time may cause a thread or other system + * resource to be allocated to track device change notifications. + * + * \returns a change counter that is incremented with each potential device + * change, or 0 if device change detection isn't available. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_hid_enumerate + */ +extern DECLSPEC Uint32 SDLCALL SDL_hid_device_change_count(void); + +/** + * Enumerate the HID Devices. + * + * This function returns a linked list of all the HID devices attached to the + * system which match vendor_id and product_id. If `vendor_id` is set to 0 + * then any vendor matches. If `product_id` is set to 0 then any product + * matches. If `vendor_id` and `product_id` are both set to 0, then all HID + * devices will be returned. + * + * \param vendor_id The Vendor ID (VID) of the types of device to open. + * \param product_id The Product ID (PID) of the types of device to open. + * \returns a pointer to a linked list of type SDL_hid_device_info, containing + * information about the HID devices attached to the system, or NULL + * in the case of failure. Free this linked list by calling + * SDL_hid_free_enumeration(). + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_hid_device_change_count + */ +extern DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id); + +/** + * Free an enumeration Linked List + * + * This function frees a linked list created by SDL_hid_enumerate(). + * + * \param devs Pointer to a list of struct_device returned from + * SDL_hid_enumerate(). + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC void SDLCALL SDL_hid_free_enumeration(SDL_hid_device_info *devs); + +/** + * Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally + * a serial number. + * + * If `serial_number` is NULL, the first device with the specified VID and PID + * is opened. + * + * \param vendor_id The Vendor ID (VID) of the device to open. + * \param product_id The Product ID (PID) of the device to open. + * \param serial_number The Serial Number of the device to open (Optionally + * NULL). + * \returns a pointer to a SDL_hid_device object on success or NULL on + * failure. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + +/** + * Open a HID device by its path name. + * + * The path name be determined by calling SDL_hid_enumerate(), or a + * platform-specific path name can be used (eg: /dev/hidraw0 on Linux). + * + * \param path The path name of the device to open + * \returns a pointer to a SDL_hid_device object on success or NULL on + * failure. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */); + +/** + * Write an Output report to a HID device. + * + * The first byte of `data` must contain the Report ID. For devices which only + * support a single report, this must be set to 0x0. The remaining bytes + * contain the report data. Since the Report ID is mandatory, calls to + * SDL_hid_write() will always contain one more byte than the report contains. + * For example, if a hid report is 16 bytes long, 17 bytes must be passed to + * SDL_hid_write(), the Report ID (or 0x0, for devices with a single report), + * followed by the report data (16 bytes). In this example, the length passed + * in would be 17. + * + * SDL_hid_write() will send the data on the first OUT endpoint, if one + * exists. If it does not, it will send the data through the Control Endpoint + * (Endpoint 0). + * + * \param dev A device handle returned from SDL_hid_open(). + * \param data The data to send, including the report number as the first + * byte. + * \param length The length in bytes of the data to send. + * \returns the actual number of bytes written and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_write(SDL_hid_device *dev, const unsigned char *data, size_t length); + +/** + * Read an Input report from a HID device with timeout. + * + * Input reports are returned to the host through the INTERRUPT IN endpoint. + * The first byte will contain the Report number if the device uses numbered + * reports. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param data A buffer to put the read data into. + * \param length The number of bytes to read. For devices with multiple + * reports, make sure to read an extra byte for the report + * number. + * \param milliseconds timeout in milliseconds or -1 for blocking wait. + * \returns the actual number of bytes read and -1 on error. If no packet was + * available to be read within the timeout period, this function + * returns 0. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_read_timeout(SDL_hid_device *dev, unsigned char *data, size_t length, int milliseconds); + +/** + * Read an Input report from a HID device. + * + * Input reports are returned to the host through the INTERRUPT IN endpoint. + * The first byte will contain the Report number if the device uses numbered + * reports. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param data A buffer to put the read data into. + * \param length The number of bytes to read. For devices with multiple + * reports, make sure to read an extra byte for the report + * number. + * \returns the actual number of bytes read and -1 on error. If no packet was + * available to be read and the handle is in non-blocking mode, this + * function returns 0. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_read(SDL_hid_device *dev, unsigned char *data, size_t length); + +/** + * Set the device handle to be non-blocking. + * + * In non-blocking mode calls to SDL_hid_read() will return immediately with a + * value of 0 if there is no data to be read. In blocking mode, SDL_hid_read() + * will wait (block) until there is data to read before returning. + * + * Nonblocking can be turned on and off at any time. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param nonblock enable or not the nonblocking reads - 1 to enable + * nonblocking - 0 to disable nonblocking. + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_set_nonblocking(SDL_hid_device *dev, int nonblock); + +/** + * Send a Feature report to the device. + * + * Feature reports are sent over the Control endpoint as a Set_Report + * transfer. The first byte of `data` must contain the Report ID. For devices + * which only support a single report, this must be set to 0x0. The remaining + * bytes contain the report data. Since the Report ID is mandatory, calls to + * SDL_hid_send_feature_report() will always contain one more byte than the + * report contains. For example, if a hid report is 16 bytes long, 17 bytes + * must be passed to SDL_hid_send_feature_report(): the Report ID (or 0x0, for + * devices which do not use numbered reports), followed by the report data (16 + * bytes). In this example, the length passed in would be 17. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param data The data to send, including the report number as the first + * byte. + * \param length The length in bytes of the data to send, including the report + * number. + * \returns the actual number of bytes written and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_send_feature_report(SDL_hid_device *dev, const unsigned char *data, size_t length); + +/** + * Get a feature report from a HID device. + * + * Set the first byte of `data` to the Report ID of the report to be read. + * Make sure to allow space for this extra byte in `data`. Upon return, the + * first byte will still contain the Report ID, and the report data will start + * in data[1]. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param data A buffer to put the read data into, including the Report ID. + * Set the first byte of `data` to the Report ID of the report to + * be read, or set it to zero if your device does not use numbered + * reports. + * \param length The number of bytes to read, including an extra byte for the + * report ID. The buffer can be longer than the actual report. + * \returns the number of bytes read plus one for the report ID (which is + * still in the first byte), or -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_get_feature_report(SDL_hid_device *dev, unsigned char *data, size_t length); + +/** + * Close a HID device. + * + * \param dev A device handle returned from SDL_hid_open(). + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC void SDLCALL SDL_hid_close(SDL_hid_device *dev); + +/** + * Get The Manufacturer String from a HID device. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param string A wide string buffer to put the data into. + * \param maxlen The length of the buffer in multiples of wchar_t. + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_get_manufacturer_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); + +/** + * Get The Product String from a HID device. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param string A wide string buffer to put the data into. + * \param maxlen The length of the buffer in multiples of wchar_t. + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_get_product_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); + +/** + * Get The Serial Number String from a HID device. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param string A wide string buffer to put the data into. + * \param maxlen The length of the buffer in multiples of wchar_t. + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_get_serial_number_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); + +/** + * Get a string from a HID device, based on its string index. + * + * \param dev A device handle returned from SDL_hid_open(). + * \param string_index The index of the string to get. + * \param string A wide string buffer to put the data into. + * \param maxlen The length of the buffer in multiples of wchar_t. + * \returns 0 on success and -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_hid_get_indexed_string(SDL_hid_device *dev, int string_index, wchar_t *string, size_t maxlen); + +/** + * Start or stop a BLE scan on iOS and tvOS to pair Steam Controllers + * + * \param active SDL_TRUE to start the scan, SDL_FALSE to stop the scan + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC void SDLCALL SDL_hid_ble_scan(SDL_bool active); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_hidapi_h_ */ + +/* vi: set sts=4 ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_hints.h b/external/SDL2/SDL_hints.h index 315a331..1185f42 100644 --- a/external/SDL2/SDL_hints.h +++ b/external/SDL2/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_hints.h - * + * * Official documentation for SDL configuration variables * * This file contains functions to set and get configuration hints, @@ -36,23 +36,386 @@ * to how they would like the library to work. */ -#ifndef _SDL_hints_h -#define _SDL_hints_h +#ifndef SDL_hints_h_ +#define SDL_hints_h_ #include "SDL_stdinc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief A variable controlling how 3D acceleration is used to accelerate the SDL 1.2 screen surface. + * \brief A variable controlling whether the Android / iOS built-in + * accelerometer should be listed as a joystick device. * - * SDL can try to accelerate the SDL 1.2 screen surface by using streaming + * This variable can be set to the following values: + * "0" - The accelerometer is not listed as a joystick + * "1" - The accelerometer is available as a 3 axis joystick (the default). + */ +#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK" + +/** + * \brief Specify the behavior of Alt+Tab while the keyboard is grabbed. + * + * By default, SDL emulates Alt+Tab functionality while the keyboard is grabbed + * and your window is full-screen. This prevents the user from getting stuck in + * your application if you've enabled keyboard grab. + * + * The variable can be set to the following values: + * "0" - SDL will not handle Alt+Tab. Your application is responsible + for handling Alt+Tab while the keyboard is grabbed. + * "1" - SDL will minimize your window when Alt+Tab is pressed (default) +*/ +#define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED" + +/** + * \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it. + * This is a debugging aid for developers and not expected to be used by end users. The default is "1" + * + * This variable can be set to the following values: + * "0" - don't allow topmost + * "1" - allow topmost + */ +#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST" + +/** + * \brief Android APK expansion main file version. Should be a string number like "1", "2" etc. + * + * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION. + * + * If both hints were set then SDL_RWFromFile() will look into expansion files + * after a given relative path was not found in the internal storage and assets. + * + * By default this hint is not set and the APK expansion files are not searched. + */ +#define SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION" + +/** + * \brief Android APK expansion patch file version. Should be a string number like "1", "2" etc. + * + * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION. + * + * If both hints were set then SDL_RWFromFile() will look into expansion files + * after a given relative path was not found in the internal storage and assets. + * + * By default this hint is not set and the APK expansion files are not searched. + */ +#define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION" + +/** + * \brief A variable to control whether the event loop will block itself when the app is paused. + * + * The variable can be set to the following values: + * "0" - Non blocking. + * "1" - Blocking. (default) + * + * The value should be set before SDL is initialized. + */ +#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" + +/** + * \brief A variable to control whether SDL will pause audio in background + * (Requires SDL_ANDROID_BLOCK_ON_PAUSE as "Non blocking") + * + * The variable can be set to the following values: + * "0" - Non paused. + * "1" - Paused. (default) + * + * The value should be set before SDL is initialized. + */ +#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO" + +/** + * \brief A variable to control whether we trap the Android back button to handle it manually. + * This is necessary for the right mouse button to work on some Android devices, or + * to be able to trap the back button for use in your code reliably. If set to true, + * the back button will show up as an SDL_KEYDOWN / SDL_KEYUP pair with a keycode of + * SDL_SCANCODE_AC_BACK. + * + * The variable can be set to the following values: + * "0" - Back button will be handled as usual for system. (default) + * "1" - Back button will be trapped, allowing you to handle the key press + * manually. (This will also let right mouse click work on systems + * where the right mouse button functions as back.) + * + * The value of this hint is used at runtime, so it can be changed at any time. + */ +#define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" + +/** + * \brief Specify an application name. + * + * This hint lets you specify the application name sent to the OS when + * required. For example, this will often appear in volume control applets for + * audio streams, and in lists of applications which are inhibiting the + * screensaver. You should use a string that describes your program ("My Game + * 2: The Revenge") + * + * Setting this to "" or leaving it unset will have SDL use a reasonable + * default: probably the application's name or "SDL Application" if SDL + * doesn't have any better information. + * + * Note that, for audio streams, this can be overridden with + * SDL_HINT_AUDIO_DEVICE_APP_NAME. + * + * On targets where this is not supported, this hint does nothing. + */ +#define SDL_HINT_APP_NAME "SDL_APP_NAME" + +/** + * \brief A variable controlling whether controllers used with the Apple TV + * generate UI events. + * + * When UI events are generated by controller input, the app will be + * backgrounded when the Apple TV remote's menu button is pressed, and when the + * pause or B buttons on gamepads are pressed. + * + * More information about properly making use of controllers for the Apple TV + * can be found here: + * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/ + * + * This variable can be set to the following values: + * "0" - Controller input does not generate UI events (the default). + * "1" - Controller input generates UI events. + */ +#define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS" + +/** + * \brief A variable controlling whether the Apple TV remote's joystick axes + * will automatically match the rotation of the remote. + * + * This variable can be set to the following values: + * "0" - Remote orientation does not affect joystick axes (the default). + * "1" - Joystick axes are based on the orientation of the remote. + */ +#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION" + +/** + * \brief A variable controlling the audio category on iOS and Mac OS X + * + * This variable can be set to the following values: + * + * "ambient" - Use the AVAudioSessionCategoryAmbient audio category, will be muted by the phone mute switch (default) + * "playback" - Use the AVAudioSessionCategoryPlayback category + * + * For more information, see Apple's documentation: + * https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html + */ +#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" + +/** + * \brief Specify an application name for an audio device. + * + * Some audio backends (such as PulseAudio) allow you to describe your audio + * stream. Among other things, this description might show up in a system + * control panel that lets the user adjust the volume on specific audio + * streams instead of using one giant master volume slider. + * + * This hints lets you transmit that information to the OS. The contents of + * this hint are used while opening an audio device. You should use a string + * that describes your program ("My Game 2: The Revenge") + * + * Setting this to "" or leaving it unset will have SDL use a reasonable + * default: this will be the name set with SDL_HINT_APP_NAME, if that hint is + * set. Otherwise, it'll probably the application's name or "SDL Application" + * if SDL doesn't have any better information. + * + * On targets where this is not supported, this hint does nothing. + */ +#define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME" + +/** + * \brief Specify an application name for an audio device. + * + * Some audio backends (such as PulseAudio) allow you to describe your audio + * stream. Among other things, this description might show up in a system + * control panel that lets the user adjust the volume on specific audio + * streams instead of using one giant master volume slider. + * + * This hints lets you transmit that information to the OS. The contents of + * this hint are used while opening an audio device. You should use a string + * that describes your what your program is playing ("audio stream" is + * probably sufficient in many cases, but this could be useful for something + * like "team chat" if you have a headset playing VoIP audio separately). + * + * Setting this to "" or leaving it unset will have SDL use a reasonable + * default: "audio stream" or something similar. + * + * On targets where this is not supported, this hint does nothing. + */ +#define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME" + +/** + * \brief Specify an application role for an audio device. + * + * Some audio backends (such as Pipewire) allow you to describe the role of + * your audio stream. Among other things, this description might show up in + * a system control panel or software for displaying and manipulating media + * playback/capture graphs. + * + * This hints lets you transmit that information to the OS. The contents of + * this hint are used while opening an audio device. You should use a string + * that describes your what your program is playing (Game, Music, Movie, + * etc...). + * + * Setting this to "" or leaving it unset will have SDL use a reasonable + * default: "Game" or something similar. + * + * On targets where this is not supported, this hint does nothing. + */ +#define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE" + +/** + * \brief A variable controlling speed/quality tradeoff of audio resampling. + * + * If available, SDL can use libsamplerate ( http://www.mega-nerd.com/SRC/ ) + * to handle audio resampling. There are different resampling modes available + * that produce different levels of quality, using more CPU. + * + * If this hint isn't specified to a valid setting, or libsamplerate isn't + * available, SDL will use the default, internal resampling algorithm. + * + * Note that this is currently only applicable to resampling audio that is + * being written to a device for playback or audio being read from a device + * for capture. SDL_AudioCVT always uses the default resampler (although this + * might change for SDL 2.1). + * + * This hint is currently only checked at audio subsystem initialization. + * + * This variable can be set to the following values: + * + * "0" or "default" - Use SDL's internal resampling (Default when not set - low quality, fast) + * "1" or "fast" - Use fast, slightly higher quality resampling, if available + * "2" or "medium" - Use medium quality resampling, if available + * "3" or "best" - Use high quality resampling, if available + */ +#define SDL_HINT_AUDIO_RESAMPLING_MODE "SDL_AUDIO_RESAMPLING_MODE" + +/** + * \brief A variable controlling whether SDL updates joystick state when getting input events + * + * This variable can be set to the following values: + * + * "0" - You'll call SDL_JoystickUpdate() manually + * "1" - SDL will automatically call SDL_JoystickUpdate() (default) + * + * This hint can be toggled on and off at runtime. + */ +#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS" + +/** + * \brief A variable controlling whether SDL updates sensor state when getting input events + * + * This variable can be set to the following values: + * + * "0" - You'll call SDL_SensorUpdate() manually + * "1" - SDL will automatically call SDL_SensorUpdate() (default) + * + * This hint can be toggled on and off at runtime. + */ +#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS" + +/** + * \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs. + * + * The bitmap header version 4 is required for proper alpha channel support and + * SDL will use it when required. Should this not be desired, this hint can + * force the use of the 40 byte header version which is supported everywhere. + * + * The variable can be set to the following values: + * "0" - Surfaces with a colorkey or an alpha channel are saved to a + * 32-bit BMP file with an alpha mask. SDL will use the bitmap + * header version 4 and set the alpha mask accordingly. + * "1" - Surfaces with a colorkey or an alpha channel are saved to a + * 32-bit BMP file without an alpha mask. The alpha channel data + * will be in the file, but applications are going to ignore it. + * + * The default value is "0". + */ +#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT" + +/** + * \brief Override for SDL_GetDisplayUsableBounds() + * + * If set, this hint will override the expected results for + * SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want + * to do this, but this allows an embedded system to request that some of the + * screen be reserved for other uses when paired with a well-behaved + * application. + * + * The contents of this hint must be 4 comma-separated integers, the first + * is the bounds x, then y, width and height, in that order. + */ +#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS" + +/** + * \brief Disable giving back control to the browser automatically + * when running with asyncify + * + * With -s ASYNCIFY, SDL2 calls emscripten_sleep during operations + * such as refreshing the screen or polling events. + * + * This hint only applies to the emscripten platform + * + * The variable can be set to the following values: + * "0" - Disable emscripten_sleep calls (if you give back browser control manually or use asyncify for other purposes) + * "1" - Enable emscripten_sleep calls (the default) + */ +#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY" + +/** + * \brief override the binding element for keyboard inputs for Emscripten builds + * + * This hint only applies to the emscripten platform + * + * The variable can be one of + * "#window" - The javascript window object (this is the default) + * "#document" - The javascript document object + * "#screen" - the javascript window.screen object + * "#canvas" - the WebGL canvas element + * any other string without a leading # sign applies to the element on the page with that ID. + */ +#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" + +/** + * \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs + * + * The variable can be set to the following values: + * "0" - Do not scan for Steam Controllers + * "1" - Scan for Steam Controllers (the default) + * + * The default value is "1". This hint must be set before initializing the joystick subsystem. + */ +#define SDL_HINT_ENABLE_STEAM_CONTROLLERS "SDL_ENABLE_STEAM_CONTROLLERS" + +/** + * \brief A variable controlling whether SDL logs all events pushed onto its internal queue. + * + * This variable can be set to the following values: + * + * "0" - Don't log any events (default) + * "1" - Log all events except mouse and finger motion, which are pretty spammy. + * "2" - Log all events. + * + * This is generally meant to be used to debug SDL itself, but can be useful + * for application developers that need better visibility into what is going + * on in the event queue. Logged events are sent through SDL_Log(), which + * means by default they appear on stdout on most platforms or maybe + * OutputDebugString() on Windows, and can be funneled by the app with + * SDL_LogSetOutputFunction(), etc. + * + * This hint can be toggled on and off at runtime, if you only need to log + * events for a small subset of program execution. + */ +#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" + +/** + * \brief A variable controlling how 3D acceleration is used to accelerate the SDL screen surface. + * + * SDL can try to accelerate the SDL screen surface by using streaming * textures with a 3D rendering engine. This variable controls whether and * how this is done. * @@ -66,6 +429,673 @@ extern "C" { */ #define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION" +/** + * \brief A variable that lets you manually hint extra gamecontroller db entries. + * + * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h + * + * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) + * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping() + */ +#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" + +/** + * \brief A variable that lets you provide a file with extra gamecontroller db entries. + * + * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h + * + * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) + * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping() + */ +#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE" + +/** + * \brief A variable that overrides the automatic controller type detection + * + * The variable should be comma separated entries, in the form: VID/PID=type + * + * The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd + * + * The type should be one of: + * Xbox360 + * XboxOne + * PS3 + * PS4 + * PS5 + * SwitchPro + * + * This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) + */ +#define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE" + +/** + * \brief A variable containing a list of devices to skip when scanning for game controllers. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES "SDL_GAMECONTROLLER_IGNORE_DEVICES" + +/** + * \brief If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable. + * + * The format of the string is a comma separated list of USB VID/PID pairs + * in hexadecimal form, e.g. + * + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of @file, in which case the named + * file will be loaded and interpreted as the value of the variable. + */ +#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT" + +/** + * \brief If set, game controller face buttons report their values according to their labels instead of their positional layout. + * + * For example, on Nintendo Switch controllers, normally you'd get: + * + * (Y) + * (X) (B) + * (A) + * + * but if this hint is set, you'll get: + * + * (X) + * (Y) (A) + * (B) + * + * The variable can be set to the following values: + * "0" - Report the face buttons by position, as though they were on an Xbox controller. + * "1" - Report the face buttons by label instead of position + * + * The default value is "1". This hint may be set at any time. + */ +#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS" + +/** + * \brief A variable controlling whether grabbing input grabs the keyboard + * + * This variable can be set to the following values: + * "0" - Grab will affect only the mouse + * "1" - Grab will affect mouse and keyboard + * + * By default SDL will not grab the keyboard so system shortcuts still work. + */ +#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD" + +/** + * \brief A variable controlling whether the idle timer is disabled on iOS. + * + * When an iOS app does not receive touches for some time, the screen is + * dimmed automatically. For games where the accelerometer is the only input + * this is problematic. This functionality can be disabled by setting this + * hint. + * + * As of SDL 2.0.4, SDL_EnableScreenSaver() and SDL_DisableScreenSaver() + * accomplish the same thing on iOS. They should be preferred over this hint. + * + * This variable can be set to the following values: + * "0" - Enable idle timer + * "1" - Disable idle timer + */ +#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED" + +/** + * \brief A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_TEXTEDITING events. + * + * The variable can be set to the following values: + * "0" - SDL_TEXTEDITING events are sent, and it is the application's + * responsibility to render the text from these events and + * differentiate it somehow from committed text. (default) + * "1" - If supported by the IME then SDL_TEXTEDITING events are not sent, + * and text that is being composed will be rendered in its own UI. + */ +#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" + +/** + * \brief A variable to control whether certain IMEs should show native UI components (such as the Candidate List) instead of suppressing them. + * + * The variable can be set to the following values: + * "0" - Native UI components are not display. (default) + * "1" - Native UI components are displayed. + */ +#define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI" + +/** + * \brief A variable controlling whether the home indicator bar on iPhone X + * should be hidden. + * + * This variable can be set to the following values: + * "0" - The indicator bar is not hidden (default for windowed applications) + * "1" - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications) + * "2" - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action (default for fullscreen applications) + */ +#define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR" + +/** + * \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background. + * + * The variable can be set to the following values: + * "0" - Disable joystick & gamecontroller input events when the + * application is in the background. + * "1" - Enable joystick & gamecontroller input events when the + * application is in the background. + * + * The default value is "0". This hint may be set at any time. + */ +#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" + +/** + * \brief A variable controlling whether the HIDAPI joystick drivers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI drivers are not used + * "1" - HIDAPI drivers are used (the default) + * + * This variable is the default for all drivers, but can be overridden by the hints for specific drivers below. + */ +#define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI" + +/** + * \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE" + + /** + * \brief A variable controlling whether Switch Joy-Cons should be treated the same as Switch Pro Controllers when using the HIDAPI driver. + * + * This variable can be set to the following values: + * "0" - basic Joy-Con support with no analog input (the default) + * "1" - Joy-Cons treated as half full Pro Controllers with analog inputs and sensors + * + * This does not combine Joy-Cons into a single controller. That's up to the user. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS" + + /** + * \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_LUNA "SDL_JOYSTICK_HIDAPI_LUNA" + +/** + * \brief A variable controlling whether the HIDAPI driver for PS4 controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4" + +/** + * \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver. + * + * This variable can be set to the following values: + * "0" - extended reports are not enabled (the default) + * "1" - extended reports + * + * Extended input reports allow rumble on Bluetooth PS4 controllers, but + * break DirectInput handling for applications that don't use SDL. + * + * Once extended reports are enabled, they can not be disabled without + * power cycling the controller. + * + * For compatibility with applications written for versions of SDL prior + * to the introduction of PS5 controller support, this value will also + * control the state of extended reports on PS5 controllers when the + * SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE hint is not explicitly set. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE" + +/** + * \brief A variable controlling whether the HIDAPI driver for PS5 controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5" + +/** + * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller. + * + * This variable can be set to the following values: + * "0" - player LEDs are not enabled + * "1" - player LEDs are enabled (the default) + */ +#define SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED" + +/** + * \brief A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver. + * + * This variable can be set to the following values: + * "0" - extended reports are not enabled (the default) + * "1" - extended reports + * + * Extended input reports allow rumble on Bluetooth PS5 controllers, but + * break DirectInput handling for applications that don't use SDL. + * + * Once extended reports are enabled, they can not be disabled without + * power cycling the controller. + * + * For compatibility with applications written for versions of SDL prior + * to the introduction of PS5 controller support, this value defaults to + * the value of SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE" + +/** + * \brief A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA" + +/** + * \brief A variable controlling whether the HIDAPI driver for Steam Controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used for Steam Controllers, which requires Bluetooth access + * and may prompt the user for permission on iOS and Android. + * + * The default is "0" + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" + +/** + * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH" + +/** + * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch controller is opened + * + * This variable can be set to the following values: + * "0" - home button LED is turned off + * "1" - home button LED is turned on + * + * By default the Home button LED state is not changed. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED" + +/** + * \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used. + * + * This variable can be set to the following values: + * "0" - HIDAPI driver is not used + * "1" - HIDAPI driver is used + * + * The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX" + + /** + * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. + * + * This variable can be set to the following values: + * "0" - RAWINPUT drivers are not used + * "1" - RAWINPUT drivers are used (the default) + * + */ +#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT" + + /** + * \brief A variable controlling whether the RAWINPUT driver should pull correlated data from XInput. + * + * This variable can be set to the following values: + * "0" - RAWINPUT driver will only use data from raw input APIs + * "1" - RAWINPUT driver will also pull data from XInput, providing + * better trigger axes, guide button presses, and rumble support + * for Xbox controllers + * + * The default is "1". This hint applies to any joysticks opened after setting the hint. + */ +#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT" + + /** + * \brief A variable controlling whether a separate thread should be used + * for handling joystick detection and raw input messages on Windows + * + * This variable can be set to the following values: + * "0" - A separate thread is not used (the default) + * "1" - A separate thread is used for handling raw input messages + * + */ +#define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" + +/** + * \brief Determines whether SDL enforces that DRM master is required in order + * to initialize the KMSDRM video backend. + * + * The DRM subsystem has a concept of a "DRM master" which is a DRM client that + * has the ability to set planes, set cursor, etc. When SDL is DRM master, it + * can draw to the screen using the SDL rendering APIs. Without DRM master, SDL + * is still able to process input and query attributes of attached displays, + * but it cannot change display state or draw to the screen directly. + * + * In some cases, it can be useful to have the KMSDRM backend even if it cannot + * be used for rendering. An app may want to use SDL for input processing while + * using another rendering API (such as an MMAL overlay on Raspberry Pi) or + * using its own code to render to DRM overlays that SDL doesn't support. + * + * This hint must be set before initializing the video subsystem. + * + * This variable can be set to the following values: + * "0" - SDL will allow usage of the KMSDRM backend without DRM master + * "1" - SDL Will require DRM master to use the KMSDRM backend (default) + */ +#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER" + + /** + * \brief A comma separated list of devices to open as joysticks + * + * This variable is currently only used by the Linux joystick driver. + */ +#define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE" + + /** + * \brief A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux + * + * This variable can be set to the following values: + * "0" - Use /dev/input/event* + * "1" - Use /dev/input/js* + * + * By default the /dev/input/event* interfaces are used + */ +#define SDL_HINT_LINUX_JOYSTICK_CLASSIC "SDL_LINUX_JOYSTICK_CLASSIC" + + /** + * \brief A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. + * + * This variable can be set to the following values: + * "0" - Return unfiltered joystick axis values (the default) + * "1" - Return axis values with deadzones taken into account + */ +#define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES" + +/** +* \brief When set don't force the SDL app to become a foreground process +* +* This hint only applies to Mac OS X. +* +*/ +#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP" + +/** + * \brief A variable that determines whether ctrl+click should generate a right-click event on Mac + * + * If present, holding ctrl while left clicking will generate a right click + * event when on Mac. + */ +#define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK" + +/** + * \brief A variable setting the double click radius, in pixels. + */ +#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS" + +/** + * \brief A variable setting the double click time, in milliseconds. + */ +#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME" + +/** + * \brief Allow mouse click events when clicking to focus an SDL window + * + * This variable can be set to the following values: + * "0" - Ignore mouse clicks that activate a window + * "1" - Generate events for mouse clicks that activate a window + * + * By default SDL will ignore mouse clicks that activate a window + */ +#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH" + +/** + * \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode + */ +#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE" + +/** + * \brief A variable controlling whether relative mouse mode is implemented using mouse warping + * + * This variable can be set to the following values: + * "0" - Relative mouse mode uses raw input + * "1" - Relative mouse mode uses mouse warping + * + * By default SDL will use raw input for relative mouse mode + */ +#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP" + +/** + * \brief A variable controlling whether relative mouse motion is affected by renderer scaling + * + * This variable can be set to the following values: + * "0" - Relative motion is unaffected by DPI or renderer's logical size + * "1" - Relative motion is scaled according to DPI scaling and logical size + * + * By default relative mouse deltas are affected by DPI and renderer scaling + */ +#define SDL_HINT_MOUSE_RELATIVE_SCALING "SDL_MOUSE_RELATIVE_SCALING" + +/** + * \brief A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode + */ +#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" + +/** + * \brief A variable controlling whether mouse events should generate synthetic touch events + * + * This variable can be set to the following values: + * "0" - Mouse events will not generate touch events (default for desktop platforms) + * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS) + */ +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + +/** + * \brief Tell SDL not to catch the SIGINT or SIGTERM signals. + * + * This hint only applies to Unix-like platforms, and should set before + * any calls to SDL_Init() + * + * The variable can be set to the following values: + * "0" - SDL will install a SIGINT and SIGTERM handler, and when it + * catches a signal, convert it into an SDL_QUIT event. + * "1" - SDL will not install a signal handler at all. + */ +#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" + +/** + * \brief A variable controlling what driver to use for OpenGL ES contexts. + * + * On some platforms, currently Windows and X11, OpenGL drivers may support + * creating contexts with an OpenGL ES profile. By default SDL uses these + * profiles, when available, otherwise it attempts to load an OpenGL ES + * library, e.g. that provided by the ANGLE project. This variable controls + * whether SDL follows this default behaviour or will always load an + * OpenGL ES library. + * + * Circumstances where this is useful include + * - Testing an app with a particular OpenGL ES implementation, e.g ANGLE, + * or emulator, e.g. those from ARM, Imagination or Qualcomm. + * - Resolving OpenGL ES function addresses at link time by linking with + * the OpenGL ES library instead of querying them at run time with + * SDL_GL_GetProcAddress(). + * + * Caution: for an application to work with the default behaviour across + * different OpenGL drivers it must query the OpenGL ES function + * addresses at run time using SDL_GL_GetProcAddress(). + * + * This variable is ignored on most platforms because OpenGL ES is native + * or not supported. + * + * This variable can be set to the following values: + * "0" - Use ES profile of OpenGL, if available. (Default when not set.) + * "1" - Load OpenGL ES library using the default library names. + * + */ +#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" + +/** + * \brief A variable controlling which orientations are allowed on iOS/Android. + * + * In some circumstances it is necessary to be able to explicitly control + * which UI orientations are allowed. + * + * This variable is a space delimited list of the following values: + * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown" + */ +#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS" + +/** + * \brief A variable controlling the use of a sentinel event when polling the event queue + * + * This variable can be set to the following values: + * "0" - Disable poll sentinels + * "1" - Enable poll sentinels + * + * When polling for events, SDL_PumpEvents is used to gather new events from devices. + * If a device keeps producing new events between calls to SDL_PumpEvents, a poll loop will + * become stuck until the new events stop. + * This is most noticable when moving a high frequency mouse. + * + * By default, poll sentinels are enabled. + */ +#define SDL_HINT_POLL_SENTINEL "SDL_POLL_SENTINEL" + +/** + * \brief Override for SDL_GetPreferredLocales() + * + * If set, this will be favored over anything the OS might report for the + * user's preferred locales. Changing this hint at runtime will not generate + * a SDL_LOCALECHANGED event (but if you can change the hint, you can push + * your own event, if you want). + * + * The format of this hint is a comma-separated list of language and locale, + * combined with an underscore, as is a common format: "en_GB". Locale is + * optional: "en". So you might have a list like this: "en_GB,jp,es_PT" + */ +#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES" + +/** + * \brief A variable describing the content orientation on QtWayland-based platforms. + * + * On QtWayland platforms, windows are rotated client-side to allow for custom + * transitions. In order to correctly position overlays (e.g. volume bar) and + * gestures (e.g. events view, close/minimize gestures), the system needs to + * know in which orientation the application is currently drawing its contents. + * + * This does not cause the window to be rotated or resized, the application + * needs to take care of drawing the content in the right orientation (the + * framebuffer is always in portrait mode). + * + * This variable can be one of the following values: + * "primary" (default), "portrait", "landscape", "inverted-portrait", "inverted-landscape" + */ +#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION" + +/** + * \brief Flags to set on QtWayland windows to integrate with the native window manager. + * + * On QtWayland platforms, this hint controls the flags to set on the windows. + * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures. + * + * This variable is a space-separated list of the following values (empty = no flags): + * "OverridesSystemGestures", "StaysOnTop", "BypassWindowManager" + */ +#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS" + +/** + * \brief A variable controlling whether the 2D render API is compatible or efficient. + * + * This variable can be set to the following values: + * + * "0" - Don't use batching to make rendering more efficient. + * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls. + * + * Up to SDL 2.0.9, the render API would draw immediately when requested. Now + * it batches up draw requests and sends them all to the GPU only when forced + * to (during SDL_RenderPresent, when changing render targets, by updating a + * texture that the batch needs, etc). This is significantly more efficient, + * but it can cause problems for apps that expect to render on top of the + * render API's output. As such, SDL will disable batching if a specific + * render backend is requested (since this might indicate that the app is + * planning to use the underlying graphics API directly). This hint can + * be used to explicitly request batching in this instance. It is a contract + * that you will either never use the underlying graphics API directly, or + * if you do, you will call SDL_RenderFlush() before you do so any current + * batch goes to the GPU before your work begins. Not following this contract + * will result in undefined behavior. + */ +#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" + +/** + * \brief A variable controlling how the 2D render API renders lines + * + * This variable can be set to the following values: + * "0" - Use the default line drawing method (Bresenham's line algorithm as of SDL 2.0.20) + * "1" - Use the driver point API using Bresenham's line algorithm (correct, draws many points) + * "2" - Use the driver line API (occasionally misses line endpoints based on hardware driver quirks, was the default before 2.0.20) + * "3" - Use the driver geometry API (correct, draws thicker diagonal lines) + * + * This variable should be set when the renderer is created. + */ +#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" + +/** + * \brief A variable controlling whether to enable Direct3D 11+'s Debug Layer. + * + * This variable does not have any effect on the Direct3D 9 based renderer. + * + * This variable can be set to the following values: + * "0" - Disable Debug Layer use + * "1" - Enable Debug Layer use + * + * By default, SDL does not use Direct3D Debug Layer. + */ +#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" + +/** + * \brief A variable controlling whether the Direct3D device is initialized for thread-safe operations. + * + * This variable can be set to the following values: + * "0" - Thread-safety is not enabled (faster) + * "1" - Thread-safety is enabled + * + * By default the Direct3D device is created with thread-safety disabled. + */ +#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE" + /** * \brief A variable specifying which render driver to use. * @@ -78,6 +1108,7 @@ extern "C" { * "opengl" * "opengles2" * "opengles" + * "metal" * "software" * * The default varies by platform, but it's the first one in the list that @@ -85,6 +1116,17 @@ extern "C" { */ #define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER" +/** + * \brief A variable controlling the scaling policy for SDL_RenderSetLogicalSize. + * + * This variable can be set to the following values: + * "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen + * "1" or "overscan" - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen + * + * By default letterbox is used + */ +#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE "SDL_RENDER_LOGICAL_SIZE_MODE" + /** * \brief A variable controlling whether the OpenGL render driver uses shaders if they are available. * @@ -102,14 +1144,14 @@ extern "C" { * This variable can be set to the following values: * "0" or "nearest" - Nearest pixel sampling * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D) - * "2" or "best" - Anisotropic filtering (supported by Direct3D) + * "2" or "best" - Currently this is the same as "linear" * * By default nearest pixel sampling is used */ #define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY" /** - * \brief A variable controlling whether updates to the SDL 1.2 screen surface should be synchronized with the vertical refresh, to avoid tearing. + * \brief A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing. * * This variable can be set to the following values: * "0" - Disable vsync @@ -119,16 +1161,309 @@ extern "C" { */ #define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC" + /** + * \brief A variable to control whether the return key on the soft keyboard + * should hide the soft keyboard on Android and iOS. + * + * The variable can be set to the following values: + * "0" - The return key will be handled as a key event. This is the behaviour of SDL <= 2.0.3. (default) + * "1" - The return key will hide the keyboard. + * + * The value of this hint is used at runtime, so it can be changed at any time. + */ +#define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME" + /** - * \brief A variable controlling whether the X11 VidMode extension should be used. + * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI + * + * Also known as Z-order. The variable can take a negative or positive value. + * The default is 10000. + */ +#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER" + +/** + * \brief Specify an "activity name" for screensaver inhibition. + * + * Some platforms, notably Linux desktops, list the applications which are + * inhibiting the screensaver or other power-saving features. + * + * This hint lets you specify the "activity name" sent to the OS when + * SDL_DisableScreenSaver() is used (or the screensaver is automatically + * disabled). The contents of this hint are used when the screensaver is + * disabled. You should use a string that describes what your program is doing + * (and, therefore, why the screensaver is disabled). For example, "Playing a + * game" or "Watching a video". + * + * Setting this to "" or leaving it unset will have SDL use a reasonable + * default: "Playing a game" or something similar. + * + * On targets where this is not supported, this hint does nothing. + */ +#define SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME" + +/** + * \brief Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime. + * + * On some platforms, like Linux, a realtime priority thread may be subject to restrictions + * that require special handling by the application. This hint exists to let SDL know that + * the app is prepared to handle said restrictions. + * + * On Linux, SDL will apply the following configuration to any thread that becomes realtime: + * * The SCHED_RESET_ON_FORK bit will be set on the scheduling policy, + * * An RLIMIT_RTTIME budget will be configured to the rtkit specified limit. + * * Exceeding this limit will result in the kernel sending SIGKILL to the app, + * * Refer to the man pages for more information. + * + * This variable can be set to the following values: + * "0" - default platform specific behaviour + * "1" - Force SDL_THREAD_PRIORITY_TIME_CRITICAL to a realtime scheduling policy + */ +#define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL" + +/** +* \brief A string specifying additional information to use with SDL_SetThreadPriority. +* +* By default SDL_SetThreadPriority will make appropriate system changes in order to +* apply a thread priority. For example on systems using pthreads the scheduler policy +* is changed automatically to a policy that works well with a given priority. +* Code which has specific requirements can override SDL's default behavior with this hint. +* +* pthread hint values are "current", "other", "fifo" and "rr". +* Currently no other platform hint values are defined but may be in the future. +* +* \note On Linux, the kernel may send SIGKILL to realtime tasks which exceed the distro +* configured execution budget for rtkit. This budget can be queried through RLIMIT_RTTIME +* after calling SDL_SetThreadPriority(). +*/ +#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY" + +/** +* \brief A string specifying SDL's threads stack size in bytes or "0" for the backend's default size +* +* Use this hint in case you need to set SDL's threads stack size to other than the default. +* This is specially useful if you build SDL against a non glibc libc library (such as musl) which +* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses). +* Support for this hint is currently available only in the pthread, Windows, and PSP backend. +* +* Instead of this hint, in 2.0.9 and later, you can use +* SDL_CreateThreadWithStackSize(). This hint only works with the classic +* SDL_CreateThread(). +*/ +#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE" + +/** + * \brief A variable that controls the timer resolution, in milliseconds. + * + * The higher resolution the timer, the more frequently the CPU services + * timer interrupts, and the more precise delays are, but this takes up + * power and CPU time. This hint is only used on Windows. + * + * See this blog post for more information: + * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/ + * + * If this variable is set to "0", the system timer resolution is not set. + * + * The default value is "1". This hint may be set at any time. + */ +#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION" + +/** + * \brief A variable controlling whether touch events should generate synthetic mouse events * * This variable can be set to the following values: - * "0" - Disable XVidMode - * "1" - Enable XVidMode + * "0" - Touch events will not generate mouse events + * "1" - Touch events will generate mouse events * - * By default SDL will use XVidMode if it is available. + * By default SDL will generate mouse events for touch events */ -#define SDL_HINT_VIDEO_X11_XVIDMODE "SDL_VIDEO_X11_XVIDMODE" +#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" + +/** + * \brief A variable controlling whether the Android / tvOS remotes + * should be listed as joystick devices, instead of sending keyboard events. + * + * This variable can be set to the following values: + * "0" - Remotes send enter/escape/arrow key events + * "1" - Remotes are available as 2 axis, 2 button joysticks (the default). + */ +#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK" + +/** + * \brief A variable controlling whether the screensaver is enabled. + * + * This variable can be set to the following values: + * "0" - Disable screensaver + * "1" - Enable screensaver + * + * By default SDL will disable the screensaver. + */ +#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" + +/** + * \brief Tell the video driver that we only want a double buffer. + * + * By default, most lowlevel 2D APIs will use a triple buffer scheme that + * wastes no CPU time on waiting for vsync after issuing a flip, but + * introduces a frame of latency. On the other hand, using a double buffer + * scheme instead is recommended for cases where low latency is an important + * factor because we save a whole frame of latency. + * We do so by waiting for vsync immediately after issuing a flip, usually just + * after eglSwapBuffers call in the backend's *_SwapWindow function. + * + * Since it's driver-specific, it's only supported where possible and + * implemented. Currently supported the following drivers: + * + * - KMSDRM (kmsdrm) + * - Raspberry Pi (raspberrypi) + */ +#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER" + +/** + * \brief A variable controlling whether the EGL window is allowed to be + * composited as transparent, rather than opaque. + * + * Most window systems will always render windows opaque, even if the surface + * format has an alpha channel. This is not always true, however, so by default + * SDL will try to enforce opaque composition. To override this behavior, you + * can set this hint to "1". + */ +#define SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY "SDL_VIDEO_EGL_ALLOW_TRANSPARENCY" + +/** + * \brief A variable controlling whether the graphics context is externally managed. + * + * This variable can be set to the following values: + * "0" - SDL will manage graphics contexts that are attached to windows. + * "1" - Disable graphics context management on windows. + * + * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the + * context will be automatically saved and restored when pausing the application. Additionally, some + * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this + * behavior, which is desireable when the application manages the graphics context, such as + * an externally managed OpenGL context or attaching a Vulkan surface to the window. + */ +#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT" + +/** + * \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS) + */ +#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED" + +/** + * \brief A variable that dictates policy for fullscreen Spaces on Mac OS X. + * + * This hint only applies to Mac OS X. + * + * The variable can be set to the following values: + * "0" - Disable Spaces support (FULLSCREEN_DESKTOP won't use them and + * SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen" + * button on their titlebars). + * "1" - Enable Spaces support (FULLSCREEN_DESKTOP will use them and + * SDL_WINDOW_RESIZABLE windows will offer the "fullscreen" + * button on their titlebars). + * + * The default value is "1". Spaces are disabled regardless of this hint if + * the OS isn't at least Mac OS X Lion (10.7). This hint must be set before + * any windows are created. + */ +#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" + +/** + * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false. + * \warning Before SDL 2.0.14, this defaulted to true! In 2.0.14, we're + * seeing if "true" causes more problems than it solves in modern times. + * + */ +#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" + +/** + * \brief A variable controlling whether the libdecor Wayland backend is allowed to be used. + * + * This variable can be set to the following values: + * "0" - libdecor use is disabled. + * "1" - libdecor use is enabled (default). + * + * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable. + */ +#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR" + +/** +* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p"). +* +* If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has +* SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly +* created SDL_Window: +* +* 1. Its pixel format will be set to the same pixel format as this SDL_Window. This is +* needed for example when sharing an OpenGL context across multiple windows. +* +* 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for +* OpenGL rendering. +* +* This variable can be set to the following values: +* The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should +* share a pixel format with. +*/ +#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT" + +/** +* \brief A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries +* +* SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It +* can use two different sets of binaries, those compiled by the user from source +* or those provided by the Chrome browser. In the later case, these binaries require +* that SDL loads a DLL providing the shader compiler. +* +* This variable can be set to the following values: +* "d3dcompiler_46.dll" - default, best for Vista or later. +* "d3dcompiler_43.dll" - for XP support. +* "none" - do not load any library, useful if you compiled ANGLE from source and included the compiler in your binaries. +* +*/ +#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" + +/** + * \brief A variable controlling whether X11 should use GLX or EGL by default + * + * This variable can be set to the following values: + * "0" - Use GLX + * "1" - Use EGL + * + * By default SDL will use GLX when both are present. + */ +#define SDL_HINT_VIDEO_X11_FORCE_EGL "SDL_VIDEO_X11_FORCE_EGL" + +/** + * \brief A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used. + * + * This variable can be set to the following values: + * "0" - Disable _NET_WM_BYPASS_COMPOSITOR + * "1" - Enable _NET_WM_BYPASS_COMPOSITOR + * + * By default SDL will use _NET_WM_BYPASS_COMPOSITOR + * + */ +#define SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR" + +/** + * \brief A variable controlling whether the X11 _NET_WM_PING protocol should be supported. + * + * This variable can be set to the following values: + * "0" - Disable _NET_WM_PING + * "1" - Enable _NET_WM_PING + * + * By default SDL will use _NET_WM_PING, but for applications that know they + * will not always be able to respond to ping requests in a timely manner they can + * turn it off to avoid the window manager thinking the app is hung. + * The hint is checked in CreateWindow. + */ +#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING" + +/** + * \brief A variable forcing the visual ID chosen for new X11 windows + * + */ +#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID" /** * \brief A variable controlling whether the X11 Xinerama extension should be used. @@ -153,80 +1488,341 @@ extern "C" { #define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR" /** - * \brief A variable controlling whether grabbing input grabs the keyboard + * \brief A variable controlling whether the X11 VidMode extension should be used. * * This variable can be set to the following values: - * "0" - Grab will affect only the mouse - * "1" - Grab will affect mouse and keyboard + * "0" - Disable XVidMode + * "1" - Enable XVidMode * - * By default SDL will not grab the keyboard so system shortcuts still work. + * By default SDL will use XVidMode if it is available. */ -#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD" +#define SDL_HINT_VIDEO_X11_XVIDMODE "SDL_VIDEO_X11_XVIDMODE" /** - * \brief Minimize your SDL_Window if it loses key focus when in Fullscreen mode. Defaults to true. + * \brief Controls how the fact chunk affects the loading of a WAVE file. * - */ -#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" - - -/** - * \brief A variable controlling whether the idle timer is disabled on iOS. + * The fact chunk stores information about the number of samples of a WAVE + * file. The Standards Update from Microsoft notes that this value can be used + * to 'determine the length of the data in seconds'. This is especially useful + * for compressed formats (for which this is a mandatory chunk) if they produce + * multiple sample frames per block and truncating the block is not allowed. + * The fact chunk can exactly specify how many sample frames there should be + * in this case. * - * When an iOS app does not receive touches for some time, the screen is - * dimmed automatically. For games where the accelerometer is the only input - * this is problematic. This functionality can be disabled by setting this - * hint. + * Unfortunately, most application seem to ignore the fact chunk and so SDL + * ignores it by default as well. * * This variable can be set to the following values: - * "0" - Enable idle timer - * "1" - Disable idle timer - */ -#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED" - -/** - * \brief A variable controlling which orientations are allowed on iOS. * - * In some circumstances it is necessary to be able to explicitly control - * which UI orientations are allowed. - * - * This variable is a space delimited list of the following values: - * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown" + * "truncate" - Use the number of samples to truncate the wave data if + * the fact chunk is present and valid + * "strict" - Like "truncate", but raise an error if the fact chunk + * is invalid, not present for non-PCM formats, or if the + * data chunk doesn't have that many samples + * "ignorezero" - Like "truncate", but ignore fact chunk if the number of + * samples is zero + * "ignore" - Ignore fact chunk entirely (default) */ -#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS" +#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" +/** + * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file. + * + * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE + * file) is not always reliable. In case the size is wrong, it's possible to + * just ignore it and step through the chunks until a fixed limit is reached. + * + * Note that files that have trailing data unrelated to the WAVE file or + * corrupt files may slow down the loading process without a reliable boundary. + * By default, SDL stops after 10000 chunks to prevent wasting time. Use the + * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value. + * + * This variable can be set to the following values: + * + * "force" - Always use the RIFF chunk size as a boundary for the chunk search + * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default) + * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB + * "maximum" - Search for chunks until the end of file (not recommended) + */ +#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" + +/** + * \brief Controls how a truncated WAVE file is handled. + * + * A WAVE file is considered truncated if any of the chunks are incomplete or + * the data chunk size is not a multiple of the block size. By default, SDL + * decodes until the first incomplete block, as most applications seem to do. + * + * This variable can be set to the following values: + * + * "verystrict" - Raise an error if the file is truncated + * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored + * "dropframe" - Decode until the first incomplete sample frame + * "dropblock" - Decode until the first incomplete block (default) + */ +#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" + +/** + * \brief Tell SDL not to name threads on Windows with the 0x406D1388 Exception. + * The 0x406D1388 Exception is a trick used to inform Visual Studio of a + * thread's name, but it tends to cause problems with other debuggers, + * and the .NET runtime. Note that SDL 2.0.6 and later will still use + * the (safer) SetThreadDescription API, introduced in the Windows 10 + * Creators Update, if available. + * + * The variable can be set to the following values: + * "0" - SDL will raise the 0x406D1388 Exception to name threads. + * This is the default behavior of SDL <= 2.0.4. + * "1" - SDL will not raise this exception, and threads will be unnamed. (default) + * This is necessary with .NET languages or debuggers that aren't Visual Studio. + */ +#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING" + +/** + * \brief A variable controlling whether the windows message loop is processed by SDL + * + * This variable can be set to the following values: + * "0" - The window message loop is not run + * "1" - The window message loop is processed in SDL_PumpEvents() + * + * By default SDL will process the windows message loop + */ +#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP" + +/** + * \brief Force SDL to use Critical Sections for mutexes on Windows. + * On Windows 7 and newer, Slim Reader/Writer Locks are available. + * They offer better performance, allocate no kernel ressources and + * use less memory. SDL will fall back to Critical Sections on older + * OS versions or if forced to by this hint. + * + * This variable can be set to the following values: + * "0" - Use SRW Locks when available. If not, fall back to Critical Sections. (default) + * "1" - Force the use of Critical Sections in all cases. + * + */ +#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS" + +/** + * \brief Force SDL to use Kernel Semaphores on Windows. + * Kernel Semaphores are inter-process and require a context + * switch on every interaction. On Windows 8 and newer, the + * WaitOnAddress API is available. Using that and atomics to + * implement semaphores increases performance. + * SDL will fall back to Kernel Objects on older OS versions + * or if forced to by this hint. + * + * This variable can be set to the following values: + * "0" - Use Atomics and WaitOnAddress API when available. If not, fall back to Kernel Objects. (default) + * "1" - Force the use of Kernel Objects in all cases. + * + */ +#define SDL_HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL" + +/** + * \brief A variable to specify custom icon resource id from RC file on Windows platform + */ +#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON" +#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL" + +/** + * \brief Tell SDL not to generate window-close events for Alt+F4 on Windows. + * + * The variable can be set to the following values: + * "0" - SDL will generate a window-close event when it sees Alt+F4. + * "1" - SDL will only do normal key handling for Alt+F4. + */ +#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4" + +/** + * \brief Use the D3D9Ex API introduced in Windows Vista, instead of normal D3D9. + * Direct3D 9Ex contains changes to state management that can eliminate device + * loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may require + * some changes to your application to cope with the new behavior, so this + * is disabled by default. + * + * This hint must be set before initializing the video subsystem. + * + * For more information on Direct3D 9Ex, see: + * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/graphics-apis-in-windows-vista#direct3d-9ex + * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/direct3d-9ex-improvements + * + * This variable can be set to the following values: + * "0" - Use the original Direct3D 9 API (default) + * "1" - Use the Direct3D 9Ex API on Vista and later (and fall back if D3D9Ex is unavailable) + * + */ +#define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX" + +/** + * \brief A variable controlling whether the window frame and title bar are interactive when the cursor is hidden + * + * This variable can be set to the following values: + * "0" - The window frame is not interactive when the cursor is hidden (no move, resize, etc) + * "1" - The window frame is interactive when the cursor is hidden + * + * By default SDL will allow interaction with the window frame when the cursor is hidden + */ +#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN" + +/** +* \brief A variable controlling whether the window is activated when the SDL_ShowWindow function is called +* +* This variable can be set to the following values: +* "0" - The window is activated when the SDL_ShowWindow function is called +* "1" - The window is not activated when the SDL_ShowWindow function is called +* +* By default SDL will activate the window when the SDL_ShowWindow function is called +*/ +#define SDL_HINT_WINDOW_NO_ACTIVATION_WHEN_SHOWN "SDL_WINDOW_NO_ACTIVATION_WHEN_SHOWN" + +/** \brief Allows back-button-press events on Windows Phone to be marked as handled + * + * Windows Phone devices typically feature a Back button. When pressed, + * the OS will emit back-button-press events, which apps are expected to + * handle in an appropriate manner. If apps do not explicitly mark these + * events as 'Handled', then the OS will invoke its default behavior for + * unhandled back-button-press events, which on Windows Phone 8 and 8.1 is to + * terminate the app (and attempt to switch to the previous app, or to the + * device's home screen). + * + * Setting the SDL_HINT_WINRT_HANDLE_BACK_BUTTON hint to "1" will cause SDL + * to mark back-button-press events as Handled, if and when one is sent to + * the app. + * + * Internally, Windows Phone sends back button events as parameters to + * special back-button-press callback functions. Apps that need to respond + * to back-button-press events are expected to register one or more + * callback functions for such, shortly after being launched (during the + * app's initialization phase). After the back button is pressed, the OS + * will invoke these callbacks. If the app's callback(s) do not explicitly + * mark the event as handled by the time they return, or if the app never + * registers one of these callback, the OS will consider the event + * un-handled, and it will apply its default back button behavior (terminate + * the app). + * + * SDL registers its own back-button-press callback with the Windows Phone + * OS. This callback will emit a pair of SDL key-press events (SDL_KEYDOWN + * and SDL_KEYUP), each with a scancode of SDL_SCANCODE_AC_BACK, after which + * it will check the contents of the hint, SDL_HINT_WINRT_HANDLE_BACK_BUTTON. + * If the hint's value is set to "1", the back button event's Handled + * property will get set to 'true'. If the hint's value is set to something + * else, or if it is unset, SDL will leave the event's Handled property + * alone. (By default, the OS sets this property to 'false', to note.) + * + * SDL apps can either set SDL_HINT_WINRT_HANDLE_BACK_BUTTON well before a + * back button is pressed, or can set it in direct-response to a back button + * being pressed. + * + * In order to get notified when a back button is pressed, SDL apps should + * register a callback function with SDL_AddEventWatch(), and have it listen + * for SDL_KEYDOWN events that have a scancode of SDL_SCANCODE_AC_BACK. + * (Alternatively, SDL_KEYUP events can be listened-for. Listening for + * either event type is suitable.) Any value of SDL_HINT_WINRT_HANDLE_BACK_BUTTON + * set by such a callback, will be applied to the OS' current + * back-button-press event. + * + * More details on back button behavior in Windows Phone apps can be found + * at the following page, on Microsoft's developer site: + * http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj247550(v=vs.105).aspx + */ +#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON" + +/** \brief Label text for a WinRT app's privacy policy link + * + * Network-enabled WinRT apps must include a privacy policy. On Windows 8, 8.1, and RT, + * Microsoft mandates that this policy be available via the Windows Settings charm. + * SDL provides code to add a link there, with its label text being set via the + * optional hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL. + * + * Please note that a privacy policy's contents are not set via this hint. A separate + * hint, SDL_HINT_WINRT_PRIVACY_POLICY_URL, is used to link to the actual text of the + * policy. + * + * The contents of this hint should be encoded as a UTF8 string. + * + * The default value is "Privacy Policy". This hint should only be set during app + * initialization, preferably before any calls to SDL_Init(). + * + * For additional information on linking to a privacy policy, see the documentation for + * SDL_HINT_WINRT_PRIVACY_POLICY_URL. + */ +#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL" + +/** + * \brief A URL to a WinRT app's privacy policy + * + * All network-enabled WinRT apps must make a privacy policy available to its + * users. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be + * be available in the Windows Settings charm, as accessed from within the app. + * SDL provides code to add a URL-based link there, which can point to the app's + * privacy policy. + * + * To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL + * before calling any SDL_Init() functions. The contents of the hint should + * be a valid URL. For example, "http://www.example.com". + * + * The default value is "", which will prevent SDL from adding a privacy policy + * link to the Settings charm. This hint should only be set during app init. + * + * The label text of an app's "Privacy Policy" link may be customized via another + * hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL. + * + * Please note that on Windows Phone, Microsoft does not provide standard UI + * for displaying a privacy policy link, and as such, SDL_HINT_WINRT_PRIVACY_POLICY_URL + * will not get used on that platform. Network-enabled phone apps should display + * their privacy policy through some other, in-app means. + */ +#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL" + +/** + * \brief Mark X11 windows as override-redirect. + * + * If set, this _might_ increase framerate at the expense of the desktop + * not working as expected. Override-redirect windows aren't noticed by the + * window manager at all. + * + * You should probably only use this for fullscreen windows, and you probably + * shouldn't even use it for that. But it's here if you want to try! + */ +#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" /** * \brief A variable that lets you disable the detection and use of Xinput gamepad devices * * The variable can be set to the following values: - * "0" - Disable XInput timer (only uses direct input) - * "1" - Enable XInput timer (the default) + * "0" - Disable XInput detection (only uses direct input) + * "1" - Enable XInput detection (the default) */ #define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" +/** + * \brief A variable that causes SDL to use the old axis and button mapping for XInput devices. + * + * This hint is for backwards compatibility only and will be removed in SDL 2.1 + * + * The default value is "0". This hint must be set before SDL_Init() + */ +#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING" /** - * \brief A variable that lets you manually hint extra gamecontroller db entries - * - * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h + * \brief A variable that causes SDL to not ignore audio "monitors" * - * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) - * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping() - */ -#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" - - -/** - * \brief If set to 0 then never set the top most bit on a SDL Window, even if the video mode expects it. - * This is a debugging aid for developers and not expected to be used by end users. The default is "1" + * This is currently only used for PulseAudio and ignored elsewhere. * - * This variable can be set to the following values: - * "0" - don't allow topmost - * "1" - allow topmost + * By default, SDL ignores audio devices that aren't associated with physical + * hardware. Changing this hint to "1" will expose anything SDL sees that + * appears to be an audio source or sink. This will add "devices" to the list + * that the user probably doesn't want or need, but it can be useful in + * scenarios where you want to hook up SDL to some sort of virtual device, + * etc. + * + * The default value is "0". This hint must be set before SDL_Init(). + * + * This hint is available since SDL 2.0.16. Before then, virtual devices are + * always ignored. */ -#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST" - +#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS" /** @@ -241,50 +1837,131 @@ typedef enum /** - * \brief Set a hint with a specific priority + * Set a hint with a specific priority. * - * The priority controls the behavior when setting a hint that already - * has a value. Hints will replace existing hints of their priority and - * lower. Environment variables are considered to have override priority. - * - * \return SDL_TRUE if the hint was set, SDL_FALSE otherwise + * The priority controls the behavior when setting a hint that already has a + * value. Hints will replace existing hints of their priority and lower. + * Environment variables are considered to have override priority. + * + * \param name the hint to set + * \param value the value of the hint variable + * \param priority the SDL_HintPriority level for the hint + * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetHint + * \sa SDL_SetHint */ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority); /** - * \brief Set a hint with normal priority - * - * \return SDL_TRUE if the hint was set, SDL_FALSE otherwise + * Set a hint with normal priority. + * + * Hints will not be set if there is an existing override hint or environment + * variable that takes precedence. You can use SDL_SetHintWithPriority() to + * set the hint with override priority instead. + * + * \param name the hint to set + * \param value the value of the hint variable + * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetHint + * \sa SDL_SetHintWithPriority */ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, const char *value); - /** - * \brief Get a hint - * - * \return The string value of a hint variable. + * Get the value of a hint. + * + * \param name the hint to query + * \returns the string value of a hint or NULL if the hint isn't set. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetHint + * \sa SDL_SetHintWithPriority */ extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name); /** - * \brief Clear all hints + * Get the boolean value of a hint variable. * - * This function is called during SDL_Quit() to free stored hints. + * \param name the name of the hint to get the boolean value from + * \param default_value the value to return if the hint does not exist + * \returns the boolean value of a hint or the provided default value if the + * hint does not exist. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_GetHint + * \sa SDL_SetHint + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value); + +/** + * Type definition of the hint callback function. + * + * \param userdata what was passed as `userdata` to SDL_AddHintCallback() + * \param name what was passed as `name` to SDL_AddHintCallback() + * \param oldValue the previous hint value + * \param newValue the new value hint is to be set to + */ +typedef void (SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue); + +/** + * Add a function to watch a particular hint. + * + * \param name the hint to watch + * \param callback An SDL_HintCallback function that will be called when the + * hint value changes + * \param userdata a pointer to pass to the callback function + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DelHintCallback + */ +extern DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name, + SDL_HintCallback callback, + void *userdata); + +/** + * Remove a function watching a particular hint. + * + * \param name the hint being watched + * \param callback An SDL_HintCallback function that will be called when the + * hint value changes + * \param userdata a pointer being passed to the callback function + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AddHintCallback + */ +extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name, + SDL_HintCallback callback, + void *userdata); + +/** + * Clear all hints. + * + * This function is automatically called during SDL_Quit(). + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_ClearHints(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_hints_h */ +#endif /* SDL_hints_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_joystick.h b/external/SDL2/SDL_joystick.h index c948c05..e80c005 100644 --- a/external/SDL2/SDL_joystick.h +++ b/external/SDL2/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,23 +21,25 @@ /** * \file SDL_joystick.h - * + * * Include file for SDL joystick event handling * - * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks, with the exact joystick + * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks(), with the exact joystick * behind a device_index changing as joysticks are plugged and unplugged. * * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted * then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in. * - * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of + * The term "player_index" is the number assigned to a player on a specific + * controller. For XInput controllers this returns the XInput user index. + * Many joysticks will not be able to supply this information. + * + * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of * the device (a X360 wired controller for example). This identifier is platform dependent. - * - * */ -#ifndef _SDL_joystick_h -#define _SDL_joystick_h +#ifndef SDL_joystick_h_ +#define SDL_joystick_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -45,9 +47,7 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** @@ -56,198 +56,891 @@ extern "C" { * In order to use these functions, SDL_Init() must have been called * with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system * for joysticks, and load appropriate drivers. + * + * If you would like to receive joystick updates while the application + * is in the background, you should set the following hint before calling + * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS */ -/* The joystick structure used to identify an SDL joystick */ +/** + * The joystick structure used to identify an SDL joystick + */ struct _SDL_Joystick; typedef struct _SDL_Joystick SDL_Joystick; /* A structure that encodes the stable unique id for a joystick device */ typedef struct { - Uint8 data[16]; + Uint8 data[16]; } SDL_JoystickGUID; +/** + * This is a unique ID for a joystick for the time it is connected to the system, + * and is never reused for the lifetime of the application. If the joystick is + * disconnected and reconnected, it will get a new ID. + * + * The ID value starts at 0 and increments from there. The value -1 is an invalid ID. + */ typedef Sint32 SDL_JoystickID; +typedef enum +{ + SDL_JOYSTICK_TYPE_UNKNOWN, + SDL_JOYSTICK_TYPE_GAMECONTROLLER, + SDL_JOYSTICK_TYPE_WHEEL, + SDL_JOYSTICK_TYPE_ARCADE_STICK, + SDL_JOYSTICK_TYPE_FLIGHT_STICK, + SDL_JOYSTICK_TYPE_DANCE_PAD, + SDL_JOYSTICK_TYPE_GUITAR, + SDL_JOYSTICK_TYPE_DRUM_KIT, + SDL_JOYSTICK_TYPE_ARCADE_PAD, + SDL_JOYSTICK_TYPE_THROTTLE +} SDL_JoystickType; + +typedef enum +{ + SDL_JOYSTICK_POWER_UNKNOWN = -1, + SDL_JOYSTICK_POWER_EMPTY, /* <= 5% */ + SDL_JOYSTICK_POWER_LOW, /* <= 20% */ + SDL_JOYSTICK_POWER_MEDIUM, /* <= 70% */ + SDL_JOYSTICK_POWER_FULL, /* <= 100% */ + SDL_JOYSTICK_POWER_WIRED, + SDL_JOYSTICK_POWER_MAX +} SDL_JoystickPowerLevel; + +/* Set max recognized G-force from accelerometer + See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed + */ +#define SDL_IPHONE_MAX_GFORCE 5.0 + /* Function prototypes */ + /** - * Count the number of joysticks attached to the system right now + * Locking for multi-threaded access to the joystick API + * + * If you are using the joystick API or handling events from multiple threads + * you should use these locking functions to protect access to the joysticks. + * + * In particular, you are guaranteed that the joystick list won't change, so + * the API functions that take a joystick index will be valid, and joystick + * and game controller events will not be delivered. + * + * \since This function is available since SDL 2.0.7. + */ +extern DECLSPEC void SDLCALL SDL_LockJoysticks(void); + + +/** + * Unlocking for multi-threaded access to the joystick API + * + * If you are using the joystick API or handling events from multiple threads + * you should use these locking functions to protect access to the joysticks. + * + * In particular, you are guaranteed that the joystick list won't change, so + * the API functions that take a joystick index will be valid, and joystick + * and game controller events will not be delivered. + * + * \since This function is available since SDL 2.0.7. + */ +extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void); + +/** + * Count the number of joysticks attached to the system. + * + * \returns the number of attached joysticks on success or a negative error + * code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickName + * \sa SDL_JoystickOpen */ extern DECLSPEC int SDLCALL SDL_NumJoysticks(void); /** - * Get the implementation dependent name of a joystick. - * This can be called before any joysticks are opened. - * If no name can be found, this function returns NULL. + * Get the implementation dependent name of a joystick. + * + * This can be called before any joysticks are opened. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system) + * \returns the name of the selected joystick. If no name can be found, this + * function returns NULL; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickName + * \sa SDL_JoystickOpen */ extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index); /** - * Open a joystick for use. - * The index passed as an argument refers tothe N'th joystick on the system. - * This index is the value which will identify this joystick in future joystick - * events. - * - * \return A joystick identifier, or NULL if an error occurred. + * Get the player index of a joystick, or -1 if it's not available This can be + * called before any joysticks are opened. + * + * \since This function is available since SDL 2.0.9. */ -extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index); +extern DECLSPEC int SDLCALL SDL_JoystickGetDevicePlayerIndex(int device_index); /** - * Return the name for this currently opened joystick. - * If no name can be found, this function returns NULL. - */ -extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick * joystick); - -/** - * Return the GUID for the joystick at this index + * Get the implementation-dependent GUID for the joystick at a given device + * index. + * + * This function can be called before any joysticks are opened. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system + * \returns the GUID of the selected joystick. If called on an invalid index, + * this function returns a zero GUID + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetGUID + * \sa SDL_JoystickGetGUIDString */ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetDeviceGUID(int device_index); /** - * Return the GUID for this opened joystick + * Get the USB vendor ID of a joystick, if available. + * + * This can be called before any joysticks are opened. If the vendor ID isn't + * available this function returns 0. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system + * \returns the USB vendor ID of the selected joystick. If called on an + * invalid index, this function returns zero + * + * \since This function is available since SDL 2.0.6. */ -extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick * joystick); +extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceVendor(int device_index); /** - * Return a string representation for this guid. pszGUID must point to at least 33 bytes - * (32 for the string plus a NULL terminator). + * Get the USB product ID of a joystick, if available. + * + * This can be called before any joysticks are opened. If the product ID isn't + * available this function returns 0. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system + * \returns the USB product ID of the selected joystick. If called on an + * invalid index, this function returns zero + * + * \since This function is available since SDL 2.0.6. */ -extern DECLSPEC void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID); +extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProduct(int device_index); /** - * convert a string into a joystick formatted guid + * Get the product version of a joystick, if available. + * + * This can be called before any joysticks are opened. If the product version + * isn't available this function returns 0. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system + * \returns the product version of the selected joystick. If called on an + * invalid index, this function returns zero + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProductVersion(int device_index); + +/** + * Get the type of a joystick, if available. + * + * This can be called before any joysticks are opened. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system + * \returns the SDL_JoystickType of the selected joystick. If called on an + * invalid index, this function returns `SDL_JOYSTICK_TYPE_UNKNOWN` + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetDeviceType(int device_index); + +/** + * Get the instance ID of a joystick. + * + * This can be called before any joysticks are opened. If the index is out of + * range, this function will return -1. + * + * \param device_index the index of the joystick to query (the N'th joystick + * on the system + * \returns the instance id of the selected joystick. If called on an invalid + * index, this function returns zero + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickGetDeviceInstanceID(int device_index); + +/** + * Open a joystick for use. + * + * The `device_index` argument refers to the N'th joystick presently + * recognized by SDL on the system. It is **NOT** the same as the instance ID + * used to identify the joystick in future events. See + * SDL_JoystickInstanceID() for more details about instance IDs. + * + * The joystick subsystem must be initialized before a joystick can be opened + * for use. + * + * \param device_index the index of the joystick to query + * \returns a joystick identifier or NULL if an error occurred; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickClose + * \sa SDL_JoystickInstanceID + */ +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index); + +/** + * Get the SDL_Joystick associated with an instance id. + * + * \param instance_id the instance id to get the SDL_Joystick for + * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.4. + */ +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id); + +/** + * Get the SDL_Joystick associated with a player index. + * + * \param player_index the player index to get the SDL_Joystick for + * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.12. + */ +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index); + +/** + * Attach a new virtual joystick. + * + * \returns the joystick's device index, or -1 if an error occurred. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, + int naxes, + int nbuttons, + int nhats); + +/** + * Detach a virtual joystick. + * + * \param device_index a value previously returned from + * SDL_JoystickAttachVirtual() + * \returns 0 on success, or -1 if an error occurred. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index); + +/** + * Query whether or not the joystick at a given device index is virtual. + * + * \param device_index a joystick device index. + * \returns SDL_TRUE if the joystick is virtual, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index); + +/** + * Set values on an opened, virtual-joystick's axis. + * + * Please note that values set here will not be applied until the next call to + * SDL_JoystickUpdate, which can either be called directly, or can be called + * indirectly through various other SDL APIs, including, but not limited to + * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout, + * SDL_WaitEvent. + * + * \param joystick the virtual joystick on which to set state. + * \param axis the specific axis on the virtual joystick to set. + * \param value the new value for the specified axis. + * \returns 0 on success, -1 on error. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value); + +/** + * Set values on an opened, virtual-joystick's button. + * + * Please note that values set here will not be applied until the next call to + * SDL_JoystickUpdate, which can either be called directly, or can be called + * indirectly through various other SDL APIs, including, but not limited to + * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout, + * SDL_WaitEvent. + * + * \param joystick the virtual joystick on which to set state. + * \param button the specific button on the virtual joystick to set. + * \param value the new value for the specified button. + * \returns 0 on success, -1 on error. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value); + +/** + * Set values on an opened, virtual-joystick's hat. + * + * Please note that values set here will not be applied until the next call to + * SDL_JoystickUpdate, which can either be called directly, or can be called + * indirectly through various other SDL APIs, including, but not limited to + * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout, + * SDL_WaitEvent. + * + * \param joystick the virtual joystick on which to set state. + * \param hat the specific hat on the virtual joystick to set. + * \param value the new value for the specified hat. + * \returns 0 on success, -1 on error. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value); + +/** + * Get the implementation dependent name of a joystick. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the name of the selected joystick. If no name can be found, this + * function returns NULL; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickNameForIndex + * \sa SDL_JoystickOpen + */ +extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick *joystick); + +/** + * Get the player index of an opened joystick. + * + * For XInput controllers this returns the XInput user index. Many joysticks + * will not be able to supply this information. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the player index, or -1 if it's not available. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick); + +/** + * Set the player index of an opened joystick. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \param player_index the player index to set. + * + * \since This function is available since SDL 2.0.12. + */ +extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index); + +/** + * Get the implementation-dependent GUID for the joystick. + * + * This function requires an open joystick. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the GUID of the given joystick. If called on an invalid index, + * this function returns a zero GUID; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetDeviceGUID + * \sa SDL_JoystickGetGUIDString + */ +extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick *joystick); + +/** + * Get the USB vendor ID of an opened joystick, if available. + * + * If the vendor ID isn't available this function returns 0. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the USB vendor ID of the selected joystick, or 0 if unavailable. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetVendor(SDL_Joystick *joystick); + +/** + * Get the USB product ID of an opened joystick, if available. + * + * If the product ID isn't available this function returns 0. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the USB product ID of the selected joystick, or 0 if unavailable. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProduct(SDL_Joystick *joystick); + +/** + * Get the product version of an opened joystick, if available. + * + * If the product version isn't available this function returns 0. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the product version of the selected joystick, or 0 if unavailable. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProductVersion(SDL_Joystick *joystick); + +/** + * Get the serial number of an opened joystick, if available. + * + * Returns the serial number of the joystick, or NULL if it is not available. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the serial number of the selected joystick, or NULL if + * unavailable. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC const char * SDLCALL SDL_JoystickGetSerial(SDL_Joystick *joystick); + +/** + * Get the type of an opened joystick. + * + * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen() + * \returns the SDL_JoystickType of the selected joystick. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetType(SDL_Joystick *joystick); + +/** + * Get an ASCII string representation for a given SDL_JoystickGUID. + * + * You should supply at least 33 bytes for pszGUID. + * + * \param guid the SDL_JoystickGUID you wish to convert to string + * \param pszGUID buffer in which to write the ASCII string + * \param cbGUID the size of pszGUID + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetDeviceGUID + * \sa SDL_JoystickGetGUID + * \sa SDL_JoystickGetGUIDFromString + */ +extern DECLSPEC void SDLCALL SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID); + +/** + * Convert a GUID string into a SDL_JoystickGUID structure. + * + * Performs no error checking. If this function is given a string containing + * an invalid GUID, the function will silently succeed, but the GUID generated + * will not be useful. + * + * \param pchGUID string containing an ASCII representation of a GUID + * \returns a SDL_JoystickGUID structure. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetGUIDString */ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUIDFromString(const char *pchGUID); /** - * Returns SDL_TRUE if the joystick has been opened and currently connected, or SDL_FALSE if it has not. + * Get the status of a specified joystick. + * + * \param joystick the joystick to query + * \returns SDL_TRUE if the joystick has been opened, SDL_FALSE if it has not; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickClose + * \sa SDL_JoystickOpen */ -extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAttached(SDL_Joystick * joystick); +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAttached(SDL_Joystick *joystick); /** - * Get the instance ID of an opened joystick or -1 if the joystick is invalid. + * Get the instance ID of an opened joystick. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \returns the instance ID of the specified joystick on success or a negative + * error code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickOpen */ -extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickInstanceID(SDL_Joystick * joystick); +extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickInstanceID(SDL_Joystick *joystick); /** - * Get the number of general axis controls on a joystick. + * Get the number of general axis controls on a joystick. + * + * Often, the directional pad on a game controller will either look like 4 + * separate buttons or a POV hat, and not axes, but all of this is up to the + * device and platform. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \returns the number of axis controls/number of axes on success or a + * negative error code on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetAxis + * \sa SDL_JoystickOpen */ -extern DECLSPEC int SDLCALL SDL_JoystickNumAxes(SDL_Joystick * joystick); +extern DECLSPEC int SDLCALL SDL_JoystickNumAxes(SDL_Joystick *joystick); /** - * Get the number of trackballs on a joystick. - * - * Joystick trackballs have only relative motion events associated - * with them and their state cannot be polled. + * Get the number of trackballs on a joystick. + * + * Joystick trackballs have only relative motion events associated with them + * and their state cannot be polled. + * + * Most joysticks do not have trackballs. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \returns the number of trackballs on success or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetBall */ -extern DECLSPEC int SDLCALL SDL_JoystickNumBalls(SDL_Joystick * joystick); +extern DECLSPEC int SDLCALL SDL_JoystickNumBalls(SDL_Joystick *joystick); /** - * Get the number of POV hats on a joystick. + * Get the number of POV hats on a joystick. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \returns the number of POV hats on success or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetHat + * \sa SDL_JoystickOpen */ -extern DECLSPEC int SDLCALL SDL_JoystickNumHats(SDL_Joystick * joystick); +extern DECLSPEC int SDLCALL SDL_JoystickNumHats(SDL_Joystick *joystick); /** - * Get the number of buttons on a joystick. + * Get the number of buttons on a joystick. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \returns the number of buttons on success or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickGetButton + * \sa SDL_JoystickOpen */ -extern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick * joystick); +extern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick *joystick); /** - * Update the current state of the open joysticks. - * - * This is called automatically by the event loop if any joystick - * events are enabled. + * Update the current state of the open joysticks. + * + * This is called automatically by the event loop if any joystick events are + * enabled. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickEventState */ extern DECLSPEC void SDLCALL SDL_JoystickUpdate(void); /** - * Enable/disable joystick event polling. - * - * If joystick events are disabled, you must call SDL_JoystickUpdate() - * yourself and check the state of the joystick when you want joystick - * information. - * - * The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE. + * Enable/disable joystick event polling. + * + * If joystick events are disabled, you must call SDL_JoystickUpdate() + * yourself and manually check the state of the joystick when you want + * joystick information. + * + * It is recommended that you leave joystick event handling enabled. + * + * **WARNING**: Calling this function may delete all events currently in SDL's + * event queue. + * + * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE` + * \returns 1 if enabled, 0 if disabled, or a negative error code on failure; + * call SDL_GetError() for more information. + * + * If `state` is `SDL_QUERY` then the current state is returned, + * otherwise the new processing state is returned. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GameControllerEventState */ extern DECLSPEC int SDLCALL SDL_JoystickEventState(int state); +#define SDL_JOYSTICK_AXIS_MAX 32767 +#define SDL_JOYSTICK_AXIS_MIN -32768 + /** - * Get the current state of an axis control on a joystick. - * - * The state is a value ranging from -32768 to 32767. - * - * The axis indices start at index 0. + * Get the current state of an axis control on a joystick. + * + * SDL makes no promises about what part of the joystick any given axis refers + * to. Your game should have some sort of configuration UI to let users + * specify what each axis should be bound to. Alternately, SDL's higher-level + * Game Controller API makes a great effort to apply order to this lower-level + * interface, so you know that a specific axis is the "left thumb stick," etc. + * + * The value returned by SDL_JoystickGetAxis() is a signed integer (-32768 to + * 32767) representing the current position of the axis. It may be necessary + * to impose certain tolerances on these values to account for jitter. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \param axis the axis to query; the axis indices start at index 0 + * \returns a 16-bit signed integer representing the current position of the + * axis or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickNumAxes */ -extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick * joystick, +extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis); +/** + * Get the initial state of an axis control on a joystick. + * + * The state is a value ranging from -32768 to 32767. + * + * The axis indices start at index 0. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \param axis the axis to query; the axis indices start at index 0 + * \param state Upon return, the initial value is supplied here. + * \return SDL_TRUE if this axis has any initial value, or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, + int axis, Sint16 *state); + /** * \name Hat positions */ -/*@{*/ -#define SDL_HAT_CENTERED 0x00 -#define SDL_HAT_UP 0x01 -#define SDL_HAT_RIGHT 0x02 -#define SDL_HAT_DOWN 0x04 -#define SDL_HAT_LEFT 0x08 -#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) -#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) -#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) -#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) -/*@}*/ +/* @{ */ +#define SDL_HAT_CENTERED 0x00 +#define SDL_HAT_UP 0x01 +#define SDL_HAT_RIGHT 0x02 +#define SDL_HAT_DOWN 0x04 +#define SDL_HAT_LEFT 0x08 +#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) +#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) +#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) +#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) +/* @} */ /** - * Get the current state of a POV hat on a joystick. + * Get the current state of a POV hat on a joystick. * - * The hat indices start at index 0. - * - * \return The return value is one of the following positions: - * - ::SDL_HAT_CENTERED - * - ::SDL_HAT_UP - * - ::SDL_HAT_RIGHT - * - ::SDL_HAT_DOWN - * - ::SDL_HAT_LEFT - * - ::SDL_HAT_RIGHTUP - * - ::SDL_HAT_RIGHTDOWN - * - ::SDL_HAT_LEFTUP - * - ::SDL_HAT_LEFTDOWN + * The returned value will be one of the following positions: + * + * - `SDL_HAT_CENTERED` + * - `SDL_HAT_UP` + * - `SDL_HAT_RIGHT` + * - `SDL_HAT_DOWN` + * - `SDL_HAT_LEFT` + * - `SDL_HAT_RIGHTUP` + * - `SDL_HAT_RIGHTDOWN` + * - `SDL_HAT_LEFTUP` + * - `SDL_HAT_LEFTDOWN` + * + * \param joystick an SDL_Joystick structure containing joystick information + * \param hat the hat index to get the state from; indices start at index 0 + * \returns the current hat position. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickNumHats */ -extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetHat(SDL_Joystick * joystick, +extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetHat(SDL_Joystick *joystick, int hat); /** - * Get the ball axis change since the last poll. - * - * \return 0, or -1 if you passed it invalid parameters. - * - * The ball indices start at index 0. + * Get the ball axis change since the last poll. + * + * Trackballs can only return relative motion since the last call to + * SDL_JoystickGetBall(), these motion deltas are placed into `dx` and `dy`. + * + * Most joysticks do not have trackballs. + * + * \param joystick the SDL_Joystick to query + * \param ball the ball index to query; ball indices start at index 0 + * \param dx stores the difference in the x axis position since the last poll + * \param dy stores the difference in the y axis position since the last poll + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickNumBalls */ -extern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick * joystick, +extern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy); /** - * Get the current state of a button on a joystick. - * - * The button indices start at index 0. + * Get the current state of a button on a joystick. + * + * \param joystick an SDL_Joystick structure containing joystick information + * \param button the button index to get the state from; indices start at + * index 0 + * \returns 1 if the specified button is pressed, 0 otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickNumButtons */ -extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick * joystick, +extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick *joystick, int button); /** - * Close a joystick previously opened with SDL_JoystickOpen(). + * Start a rumble effect. + * + * Each call to this function cancels any previous rumble effect, and calling + * it with 0 intensity stops any rumbling. + * + * \param joystick The joystick to vibrate + * \param low_frequency_rumble The intensity of the low frequency (left) + * rumble motor, from 0 to 0xFFFF + * \param high_frequency_rumble The intensity of the high frequency (right) + * rumble motor, from 0 to 0xFFFF + * \param duration_ms The duration of the rumble effect, in milliseconds + * \returns 0, or -1 if rumble isn't supported on this joystick + * + * \since This function is available since SDL 2.0.9. + * + * \sa SDL_JoystickHasRumble */ -extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick * joystick); +extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); +/** + * Start a rumble effect in the joystick's triggers + * + * Each call to this function cancels any previous trigger rumble effect, and + * calling it with 0 intensity stops any rumbling. + * + * Note that this function is for _trigger_ rumble; the first joystick to + * support this was the PlayStation 5's DualShock 5 controller. If you want + * the (more common) whole-controller rumble, use SDL_JoystickRumble() + * instead. + * + * \param joystick The joystick to vibrate + * \param left_rumble The intensity of the left trigger rumble motor, from 0 + * to 0xFFFF + * \param right_rumble The intensity of the right trigger rumble motor, from 0 + * to 0xFFFF + * \param duration_ms The duration of the rumble effect, in milliseconds + * \returns 0, or -1 if trigger rumble isn't supported on this joystick + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_JoystickHasRumbleTriggers + */ +extern DECLSPEC int SDLCALL SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); + +/** + * Query whether a joystick has an LED. + * + * An example of a joystick LED is the light on the back of a PlayStation 4's + * DualShock 4 controller. + * + * \param joystick The joystick to query + * \return SDL_TRUE if the joystick has a modifiable LED, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasLED(SDL_Joystick *joystick); + +/** + * Query whether a joystick has rumble support. + * + * \param joystick The joystick to query + * \return SDL_TRUE if the joystick has rumble, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_JoystickRumble + */ +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumble(SDL_Joystick *joystick); + +/** + * Query whether a joystick has rumble support on triggers. + * + * \param joystick The joystick to query + * \return SDL_TRUE if the joystick has trigger rumble, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_JoystickRumbleTriggers + */ +extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick); + +/** + * Update a joystick's LED color. + * + * An example of a joystick LED is the light on the back of a PlayStation 4's + * DualShock 4 controller. + * + * \param joystick The joystick to update + * \param red The intensity of the red LED + * \param green The intensity of the green LED + * \param blue The intensity of the blue LED + * \returns 0 on success, -1 if this joystick does not have a modifiable LED + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); + +/** + * Send a joystick specific effect packet + * + * \param joystick The joystick to affect + * \param data The data to send to the joystick + * \param size The size of the data to send to the joystick + * \returns 0, or -1 if this joystick or driver doesn't support effect packets + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC int SDLCALL SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size); + +/** + * Close a joystick previously opened with SDL_JoystickOpen(). + * + * \param joystick The joystick device to close + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_JoystickOpen + */ +extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick *joystick); + +/** + * Get the battery level of a joystick as SDL_JoystickPowerLevel. + * + * \param joystick the SDL_Joystick to query + * \returns the current battery level as SDL_JoystickPowerLevel on success or + * `SDL_JOYSTICK_POWER_UNKNOWN` if it is unknown + * + * \since This function is available since SDL 2.0.4. + */ +extern DECLSPEC SDL_JoystickPowerLevel SDLCALL SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_joystick_h */ +#endif /* SDL_joystick_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_keyboard.h b/external/SDL2/SDL_keyboard.h index e6aa484..a53dde6 100644 --- a/external/SDL2/SDL_keyboard.h +++ b/external/SDL2/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_keyboard.h - * + * * Include file for SDL keyboard event handling */ -#ifndef _SDL_keyboard_h -#define _SDL_keyboard_h +#ifndef SDL_keyboard_h_ +#define SDL_keyboard_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -36,184 +36,281 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \brief The SDL keysym structure, used in key events. + * + * \note If you are looking for translated character input, see the ::SDL_TEXTINPUT event. */ typedef struct SDL_Keysym { SDL_Scancode scancode; /**< SDL physical key code - see ::SDL_Scancode for details */ SDL_Keycode sym; /**< SDL virtual key code - see ::SDL_Keycode for details */ Uint16 mod; /**< current key modifiers */ - Uint32 unicode; /**< \deprecated use SDL_TextInputEvent instead */ + Uint32 unused; } SDL_Keysym; /* Function prototypes */ /** - * \brief Get the window which currently has keyboard focus. + * Query the window which currently has keyboard focus. + * + * \returns the window with keyboard focus. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void); /** - * \brief Get a snapshot of the current state of the keyboard. - * - * \param numkeys if non-NULL, receives the length of the returned array. - * - * \return An array of key states. Indexes into this array are obtained by using ::SDL_Scancode values. - * - * \b Example: - * \code - * Uint8 *state = SDL_GetKeyboardState(NULL); - * if ( state[SDL_SCANCODE_RETURN] ) { - * printf(" is pressed.\n"); - * } - * \endcode + * Get a snapshot of the current state of the keyboard. + * + * The pointer returned is a pointer to an internal SDL array. It will be + * valid for the whole lifetime of the application and should not be freed by + * the caller. + * + * A array element with a value of 1 means that the key is pressed and a value + * of 0 means that it is not. Indexes into this array are obtained by using + * SDL_Scancode values. + * + * Use SDL_PumpEvents() to update the state array. + * + * This function gives you the current state after all events have been + * processed, so if a key or button has been pressed and released before you + * process events, then the pressed state will never show up in the + * SDL_GetKeyboardState() calls. + * + * Note: This function doesn't take into account whether shift has been + * pressed or not. + * + * \param numkeys if non-NULL, receives the length of the returned array + * \returns a pointer to an array of key states. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PumpEvents */ -extern DECLSPEC Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys); +extern DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys); /** - * \brief Get the current key modifier state for the keyboard. + * Get the current key modifier state for the keyboard. + * + * \returns an OR'd combination of the modifier keys for the keyboard. See + * SDL_Keymod for details. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetKeyboardState + * \sa SDL_SetModState */ extern DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void); /** - * \brief Set the current key modifier state for the keyboard. - * - * \note This does not change the keyboard state, only the key modifier flags. + * Set the current key modifier state for the keyboard. + * + * The inverse of SDL_GetModState(), SDL_SetModState() allows you to impose + * modifier key states on your application. Simply pass your desired modifier + * states into `modstate`. This value may be a bitwise, OR'd combination of + * SDL_Keymod values. + * + * This does not change the keyboard state, only the key modifier flags that + * SDL reports. + * + * \param modstate the desired SDL_Keymod for the keyboard + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetModState */ extern DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate); /** - * \brief Get the key code corresponding to the given scancode according - * to the current keyboard layout. - * - * See ::SDL_Keycode for details. - * - * \sa SDL_GetKeyName() + * Get the key code corresponding to the given scancode according to the + * current keyboard layout. + * + * See SDL_Keycode for details. + * + * \param scancode the desired SDL_Scancode to query + * \returns the SDL_Keycode that corresponds to the given SDL_Scancode. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetKeyName + * \sa SDL_GetScancodeFromKey */ extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode); /** - * \brief Get the scancode corresponding to the given key code according to the - * current keyboard layout. - * - * See ::SDL_Scancode for details. - * - * \sa SDL_GetScancodeName() + * Get the scancode corresponding to the given key code according to the + * current keyboard layout. + * + * See SDL_Scancode for details. + * + * \param key the desired SDL_Keycode to query + * \returns the SDL_Scancode that corresponds to the given SDL_Keycode. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetKeyFromScancode + * \sa SDL_GetScancodeName */ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key); /** - * \brief Get a human-readable name for a scancode. - * - * \return A pointer to the name for the scancode. - * If the scancode doesn't have a name, this function returns - * an empty string (""). + * Get a human-readable name for a scancode. * - * \sa SDL_Scancode + * See SDL_Scancode for details. + * + * **Warning**: The returned name is by design not stable across platforms, + * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left + * Windows" under Microsoft Windows, and some scancodes like + * `SDL_SCANCODE_NONUSBACKSLASH` don't have any name at all. There are even + * scancodes that share names, e.g. `SDL_SCANCODE_RETURN` and + * `SDL_SCANCODE_RETURN2` (both called "Return"). This function is therefore + * unsuitable for creating a stable cross-platform two-way mapping between + * strings and scancodes. + * + * \param scancode the desired SDL_Scancode to query + * \returns a pointer to the name for the scancode. If the scancode doesn't + * have a name this function returns an empty string (""). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetScancodeFromKey + * \sa SDL_GetScancodeFromName */ extern DECLSPEC const char *SDLCALL SDL_GetScancodeName(SDL_Scancode scancode); /** - * \brief Get a scancode from a human-readable name - * - * \return scancode, or SDL_SCANCODE_UNKNOWN if the name wasn't recognized + * Get a scancode from a human-readable name. * - * \sa SDL_Scancode + * \param name the human-readable scancode name + * \returns the SDL_Scancode, or `SDL_SCANCODE_UNKNOWN` if the name wasn't + * recognized; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetKeyFromName + * \sa SDL_GetScancodeFromKey + * \sa SDL_GetScancodeName */ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name); /** - * \brief Get a human-readable name for a key. - * - * \return A pointer to a UTF-8 string that stays valid at least until the next - * call to this function. If you need it around any longer, you must - * copy it. If the key doesn't have a name, this function returns an - * empty string (""). - * - * \sa SDL_Key + * Get a human-readable name for a key. + * + * See SDL_Scancode and SDL_Keycode for details. + * + * \param key the desired SDL_Keycode to query + * \returns a pointer to a UTF-8 string that stays valid at least until the + * next call to this function. If you need it around any longer, you + * must copy it. If the key doesn't have a name, this function + * returns an empty string (""). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetKeyFromName + * \sa SDL_GetKeyFromScancode + * \sa SDL_GetScancodeFromKey */ extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key); /** - * \brief Get a key code from a human-readable name - * - * \return key code, or SDLK_UNKNOWN if the name wasn't recognized + * Get a key code from a human-readable name. * - * \sa SDL_Keycode + * \param name the human-readable key name + * \returns key code, or `SDLK_UNKNOWN` if the name wasn't recognized; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetKeyFromScancode + * \sa SDL_GetKeyName + * \sa SDL_GetScancodeFromName */ extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name); /** - * \brief Start accepting Unicode text input events. - * This function will show the on-screen keyboard if supported. - * - * \sa SDL_StopTextInput() - * \sa SDL_SetTextInputRect() - * \sa SDL_HasScreenKeyboardSupport() + * Start accepting Unicode text input events. + * + * This function will start accepting Unicode text input events in the focused + * SDL window, and start emitting SDL_TextInputEvent (SDL_TEXTINPUT) and + * SDL_TextEditingEvent (SDL_TEXTEDITING) events. Please use this function in + * pair with SDL_StopTextInput(). + * + * On some platforms using this function activates the screen keyboard. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetTextInputRect + * \sa SDL_StopTextInput */ extern DECLSPEC void SDLCALL SDL_StartTextInput(void); /** - * \brief Return whether or not Unicode text input events are enabled. + * Check whether or not Unicode text input events are enabled. * - * \sa SDL_StartTextInput() - * \sa SDL_StopTextInput() + * \returns SDL_TRUE if text input events are enabled else SDL_FALSE. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_StartTextInput */ extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputActive(void); /** - * \brief Stop receiving any text input events. - * This function will hide the on-screen keyboard if supported. - * - * \sa SDL_StartTextInput() - * \sa SDL_HasScreenKeyboardSupport() + * Stop receiving any text input events. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_StartTextInput */ extern DECLSPEC void SDLCALL SDL_StopTextInput(void); /** - * \brief Set the rectangle used to type Unicode text inputs. - * This is used as a hint for IME and on-screen keyboard placement. - * - * \sa SDL_StartTextInput() + * Set the rectangle used to type Unicode text inputs. + * + * \param rect the SDL_Rect structure representing the rectangle to receive + * text (ignored if NULL) + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_StartTextInput */ extern DECLSPEC void SDLCALL SDL_SetTextInputRect(SDL_Rect *rect); /** - * \brief Returns whether the platform has some screen keyboard support. - * - * \return SDL_TRUE if some keyboard support is available else SDL_FALSE. - * - * \note Not all screen keyboard functions are supported on all platforms. - * - * \sa SDL_IsScreenKeyboardShown() + * Check whether the platform has screen keyboard support. + * + * \returns SDL_TRUE if the platform has some screen keyboard support or + * SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_StartTextInput + * \sa SDL_IsScreenKeyboardShown */ extern DECLSPEC SDL_bool SDLCALL SDL_HasScreenKeyboardSupport(void); /** - * \brief Returns whether the screen keyboard is shown for given window. - * - * \param window The window for which screen keyboard should be queried. - * - * \return SDL_TRUE if screen keyboard is shown else SDL_FALSE. - * - * \sa SDL_HasScreenKeyboardSupport() + * Check whether the screen keyboard is shown for given window. + * + * \param window the window for which screen keyboard should be queried + * \returns SDL_TRUE if screen keyboard is shown or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HasScreenKeyboardSupport */ extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenKeyboardShown(SDL_Window *window); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_keyboard_h */ +#endif /* SDL_keyboard_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_keycode.h b/external/SDL2/SDL_keycode.h index 70742b1..3560254 100644 --- a/external/SDL2/SDL_keycode.h +++ b/external/SDL2/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,35 +21,38 @@ /** * \file SDL_keycode.h - * + * * Defines constants which identify keyboard keys and modifiers. */ -#ifndef _SDL_keycode_h -#define _SDL_keycode_h +#ifndef SDL_keycode_h_ +#define SDL_keycode_h_ #include "SDL_stdinc.h" #include "SDL_scancode.h" /** * \brief The SDL virtual key representation. - * + * * Values of this type are used to represent keyboard keys using the current * layout of the keyboard. These values include Unicode values representing * the unmodified character that would be generated by pressing the key, or * an SDLK_* constant for those keys that do not generate characters. + * + * A special exception is the number keys at the top of the keyboard which + * always map to SDLK_0...SDLK_9, regardless of layout. */ typedef Sint32 SDL_Keycode; #define SDLK_SCANCODE_MASK (1<<30) -#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK) +#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK) -enum +typedef enum { SDLK_UNKNOWN = 0, SDLK_RETURN = '\r', - SDLK_ESCAPE = '\033', + SDLK_ESCAPE = '\x1B', SDLK_BACKSPACE = '\b', SDLK_TAB = '\t', SDLK_SPACE = ' ', @@ -85,9 +88,11 @@ enum SDLK_GREATER = '>', SDLK_QUESTION = '?', SDLK_AT = '@', - /* + + /* Skip uppercase letters */ + SDLK_LEFTBRACKET = '[', SDLK_BACKSLASH = '\\', SDLK_RIGHTBRACKET = ']', @@ -142,7 +147,7 @@ enum SDLK_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT), SDLK_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME), SDLK_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP), - SDLK_DELETE = '\177', + SDLK_DELETE = '\x7F', SDLK_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END), SDLK_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN), SDLK_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT), @@ -308,8 +313,13 @@ enum SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN), SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP), SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT), - SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP) -}; + SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP), + SDLK_APP1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP1), + SDLK_APP2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP2), + + SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND), + SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD) +} SDL_KeyCode; /** * \brief Enumeration of valid key mods (possibly OR'd together). @@ -328,14 +338,16 @@ typedef enum KMOD_NUM = 0x1000, KMOD_CAPS = 0x2000, KMOD_MODE = 0x4000, - KMOD_RESERVED = 0x8000 + KMOD_SCROLL = 0x8000, + + KMOD_CTRL = KMOD_LCTRL | KMOD_RCTRL, + KMOD_SHIFT = KMOD_LSHIFT | KMOD_RSHIFT, + KMOD_ALT = KMOD_LALT | KMOD_RALT, + KMOD_GUI = KMOD_LGUI | KMOD_RGUI, + + KMOD_RESERVED = KMOD_SCROLL /* This is for source-level compatibility with SDL 2.0.0. */ } SDL_Keymod; -#define KMOD_CTRL (KMOD_LCTRL|KMOD_RCTRL) -#define KMOD_SHIFT (KMOD_LSHIFT|KMOD_RSHIFT) -#define KMOD_ALT (KMOD_LALT|KMOD_RALT) -#define KMOD_GUI (KMOD_LGUI|KMOD_RGUI) - -#endif /* _SDL_keycode_h */ +#endif /* SDL_keycode_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_loadso.h b/external/SDL2/SDL_loadso.h index edd32d5..61857c8 100644 --- a/external/SDL2/SDL_loadso.h +++ b/external/SDL2/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,7 +24,7 @@ * * System dependent library loading routines * - * Some things to keep in mind: + * Some things to keep in mind: * \li These functions only work on C function names. Other languages may * have name mangling and intrinsic language support that varies from * compiler to compiler. @@ -38,8 +38,8 @@ * the results you expect. :) */ -#ifndef _SDL_loadso_h -#define _SDL_loadso_h +#ifndef SDL_loadso_h_ +#define SDL_loadso_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -47,39 +47,69 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * This function dynamically loads a shared object and returns a pointer - * to the object handle (or NULL if there was an error). - * The 'sofile' parameter is a system dependent name of the object file. + * Dynamically load a shared object. + * + * \param sofile a system-dependent name of the object file + * \returns an opaque pointer to the object handle or NULL if there was an + * error; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadFunction + * \sa SDL_UnloadObject */ extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile); /** - * Given an object handle, this function looks up the address of the - * named function in the shared object and returns it. This address - * is no longer valid after calling SDL_UnloadObject(). + * Look up the address of the named function in a shared object. + * + * This function pointer is no longer valid after calling SDL_UnloadObject(). + * + * This function can only look up C function names. Other languages may have + * name mangling and intrinsic language support that varies from compiler to + * compiler. + * + * Make sure you declare your function pointers with the same calling + * convention as the actual library function. Your code will crash + * mysteriously if you do not do this. + * + * If the requested function doesn't exist, NULL is returned. + * + * \param handle a valid shared object handle returned by SDL_LoadObject() + * \param name the name of the function to look up + * \returns a pointer to the function or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadObject + * \sa SDL_UnloadObject */ extern DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name); /** - * Unload a shared object from memory. + * Unload a shared object from memory. + * + * \param handle a valid shared object handle returned by SDL_LoadObject() + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadFunction + * \sa SDL_LoadObject */ extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_loadso_h */ +#endif /* SDL_loadso_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_locale.h b/external/SDL2/SDL_locale.h new file mode 100644 index 0000000..7515779 --- /dev/null +++ b/external/SDL2/SDL_locale.h @@ -0,0 +1,103 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_locale.h + * + * Include file for SDL locale services + */ + +#ifndef _SDL_locale_h +#define _SDL_locale_h + +#include "SDL_stdinc.h" +#include "SDL_error.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + + +typedef struct SDL_Locale +{ + const char *language; /**< A language name, like "en" for English. */ + const char *country; /**< A country, like "US" for America. Can be NULL. */ +} SDL_Locale; + +/** + * Report the user's preferred locale. + * + * This returns an array of SDL_Locale structs, the final item zeroed out. + * When the caller is done with this array, it should call SDL_free() on the + * returned value; all the memory involved is allocated in a single block, so + * a single SDL_free() will suffice. + * + * Returned language strings are in the format xx, where 'xx' is an ISO-639 + * language specifier (such as "en" for English, "de" for German, etc). + * Country strings are in the format YY, where "YY" is an ISO-3166 country + * code (such as "US" for the United States, "CA" for Canada, etc). Country + * might be NULL if there's no specific guidance on them (so you might get { + * "en", "US" } for American English, but { "en", NULL } means "English + * language, generically"). Language strings are never NULL, except to + * terminate the array. + * + * Please note that not all of these strings are 2 characters; some are three + * or more. + * + * The returned list of locales are in the order of the user's preference. For + * example, a German citizen that is fluent in US English and knows enough + * Japanese to navigate around Tokyo might have a list like: { "de", "en_US", + * "jp", NULL }. Someone from England might prefer British English (where + * "color" is spelled "colour", etc), but will settle for anything like it: { + * "en_GB", "en", NULL }. + * + * This function returns NULL on error, including when the platform does not + * supply this information at all. + * + * This might be a "slow" call that has to query the operating system. It's + * best to ask for this once and save the results. However, this list can + * change, usually because the user has changed a system preference outside of + * your program; SDL will send an SDL_LOCALECHANGED event in this case, if + * possible, and you can call this function again to get an updated copy of + * preferred locales. + * + * \return array of locales, terminated with a locale with a NULL language + * field. Will return NULL on error. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_Locale * SDLCALL SDL_GetPreferredLocales(void); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#include "close_code.h" + +#endif /* _SDL_locale_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_log.h b/external/SDL2/SDL_log.h index ba56e40..dbbcb1e 100644 --- a/external/SDL2/SDL_log.h +++ b/external/SDL2/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_log.h - * + * * Simple log messages with categories and priorities. * * By default logs are quiet, but if you're debugging SDL you might want: @@ -34,17 +34,15 @@ * Others: standard error output (stderr) */ -#ifndef _SDL_log_h -#define _SDL_log_h +#ifndef SDL_log_h_ +#define SDL_log_h_ #include "SDL_stdinc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif @@ -60,10 +58,10 @@ extern "C" { * * By default the application category is enabled at the INFO level, * the assert category is enabled at the WARN level, test is enabled - * at the VERBOSE level and all other categories are enabled at the + * at the VERBOSE level and all other categories are enabled at the * CRITICAL level. */ -enum +typedef enum { SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_CATEGORY_ERROR, @@ -96,7 +94,7 @@ enum }; */ SDL_LOG_CATEGORY_CUSTOM -}; +} SDL_LogCategory; /** * \brief The predefined log priorities @@ -114,102 +112,293 @@ typedef enum /** - * \brief Set the priority of all log categories + * Set the priority of all log categories. + * + * \param priority the SDL_LogPriority to assign + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogSetPriority */ extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority); /** - * \brief Set the priority of a particular log category + * Set the priority of a particular log category. + * + * \param category the category to assign a priority to + * \param priority the SDL_LogPriority to assign + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogGetPriority + * \sa SDL_LogSetAllPriority */ extern DECLSPEC void SDLCALL SDL_LogSetPriority(int category, SDL_LogPriority priority); /** - * \brief Get the priority of a particular log category + * Get the priority of a particular log category. + * + * \param category the category to query + * \returns the SDL_LogPriority for the requested category + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogSetPriority */ extern DECLSPEC SDL_LogPriority SDLCALL SDL_LogGetPriority(int category); /** - * \brief Reset all priorities to default. + * Reset all priorities to default. * - * \note This is called in SDL_Quit(). + * This is called by SDL_Quit(). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogSetAllPriority + * \sa SDL_LogSetPriority */ extern DECLSPEC void SDLCALL SDL_LogResetPriorities(void); /** - * \brief Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO + * Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO. + * + * = * \param fmt a printf() style message format string + * + * \param ... additional parameters matching % tokens in the `fmt` string, if + * any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_Log(const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); /** - * \brief Log a message with SDL_LOG_PRIORITY_VERBOSE + * Log a message with SDL_LOG_PRIORITY_VERBOSE. + * + * \param category the category of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Log a message with SDL_LOG_PRIORITY_DEBUG + * Log a message with SDL_LOG_PRIORITY_DEBUG. + * + * \param category the category of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogDebug(int category, const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Log a message with SDL_LOG_PRIORITY_INFO + * Log a message with SDL_LOG_PRIORITY_INFO. + * + * \param category the category of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogInfo(int category, const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Log a message with SDL_LOG_PRIORITY_WARN + * Log a message with SDL_LOG_PRIORITY_WARN. + * + * \param category the category of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose */ -extern DECLSPEC void SDLCALL SDL_LogWarn(int category, const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Log a message with SDL_LOG_PRIORITY_ERROR + * Log a message with SDL_LOG_PRIORITY_ERROR. + * + * \param category the category of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogError(int category, const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Log a message with SDL_LOG_PRIORITY_CRITICAL + * Log a message with SDL_LOG_PRIORITY_CRITICAL. + * + * \param category the category of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogCritical(int category, const char *fmt, ...); +extern DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Log a message with the specified category and priority. + * Log a message with the specified category and priority. + * + * \param category the category of the message + * \param priority the priority of the message + * \param fmt a printf() style message format string + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessageV + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ extern DECLSPEC void SDLCALL SDL_LogMessage(int category, SDL_LogPriority priority, - const char *fmt, ...); + SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(3); /** - * \brief Log a message with the specified category and priority. + * Log a message with the specified category and priority. + * + * \param category the category of the message + * \param priority the priority of the message + * \param fmt a printf() style message format string + * \param ap a variable argument list + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Log + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogVerbose + * \sa SDL_LogWarn */ extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap); /** - * \brief The prototype for the log output function + * The prototype for the log output callback function. + * + * This function is called by SDL when there is new text to be logged. + * + * \param userdata what was passed as `userdata` to SDL_LogSetOutputFunction() + * \param category the category of the message + * \param priority the priority of the message + * \param message the message being output */ -typedef void (*SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message); +typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message); /** - * \brief Get the current log output function. + * Get the current log output function. + * + * \param callback an SDL_LogOutputFunction filled in with the current log + * callback + * \param userdata a pointer filled in with the pointer that is passed to + * `callback` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogSetOutputFunction */ extern DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata); /** - * \brief This function allows you to replace the default log output - * function with one of your own. + * Replace the default log output function with one of your own. + * + * \param callback an SDL_LogOutputFunction to call instead of the default + * \param userdata a pointer that is passed to `callback` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LogGetOutputFunction */ extern DECLSPEC void SDLCALL SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_log_h */ +#endif /* SDL_log_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_main.h b/external/SDL2/SDL_main.h index 8a7859f..b3fec15 100644 --- a/external/SDL2/SDL_main.h +++ b/external/SDL2/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,28 +19,85 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_main_h -#define _SDL_main_h +#ifndef SDL_main_h_ +#define SDL_main_h_ #include "SDL_stdinc.h" /** * \file SDL_main.h - * + * * Redefine main() on some platforms so that it is called by SDL. */ -#if defined(__WIN32__) || defined(__IPHONEOS__) || defined(__ANDROID__) #ifndef SDL_MAIN_HANDLED -#define SDL_MAIN_NEEDED -#endif -#endif +#if defined(__WIN32__) +/* On Windows SDL provides WinMain(), which parses the command line and passes + the arguments to your main function. -#ifdef __cplusplus -#define C_LINKAGE "C" -#else -#define C_LINKAGE -#endif /* __cplusplus */ + If you provide your own WinMain(), you may define SDL_MAIN_HANDLED + */ +#define SDL_MAIN_AVAILABLE + +#elif defined(__WINRT__) +/* On WinRT, SDL provides a main function that initializes CoreApplication, + creating an instance of IFrameworkView in the process. + + Please note that #include'ing SDL_main.h is not enough to get a main() + function working. In non-XAML apps, the file, + src/main/winrt/SDL_WinRT_main_NonXAML.cpp, or a copy of it, must be compiled + into the app itself. In XAML apps, the function, SDL_WinRTRunApp must be + called, with a pointer to the Direct3D-hosted XAML control passed in. +*/ +#define SDL_MAIN_NEEDED + +#elif defined(__IPHONEOS__) +/* On iOS SDL provides a main function that creates an application delegate + and starts the iOS application run loop. + + If you link with SDL dynamically on iOS, the main function can't be in a + shared library, so you need to link with libSDLmain.a, which includes a + stub main function that calls into the shared library to start execution. + + See src/video/uikit/SDL_uikitappdelegate.m for more details. + */ +#define SDL_MAIN_NEEDED + +#elif defined(__ANDROID__) +/* On Android SDL provides a Java class in SDLActivity.java that is the + main activity entry point. + + See docs/README-android.md for more details on extending that class. + */ +#define SDL_MAIN_NEEDED + +/* We need to export SDL_main so it can be launched from Java */ +#define SDLMAIN_DECLSPEC DECLSPEC + +#elif defined(__NACL__) +/* On NACL we use ppapi_simple to set up the application helper code, + then wait for the first PSE_INSTANCE_DIDCHANGEVIEW event before + starting the user main function. + All user code is run in a separate thread by ppapi_simple, thus + allowing for blocking io to take place via nacl_io +*/ +#define SDL_MAIN_NEEDED + +#elif defined(__PSP__) +/* On PSP SDL provides a main function that sets the module info, + activates the GPU and starts the thread required to be able to exit + the software. + + If you provide this yourself, you may define SDL_MAIN_HANDLED + */ +#define SDL_MAIN_AVAILABLE + +#endif +#endif /* SDL_MAIN_HANDLED */ + +#ifndef SDLMAIN_DECLSPEC +#define SDLMAIN_DECLSPEC +#endif /** * \file SDL_main.h @@ -57,42 +114,122 @@ * \endcode */ -#ifdef SDL_MAIN_NEEDED -#define main SDL_main +#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) +#define main SDL_main +#endif + +#include "begin_code.h" +#ifdef __cplusplus +extern "C" { #endif /** * The prototype for the application's main() function */ -extern C_LINKAGE int SDL_main(int argc, char *argv[]); +typedef int (*SDL_main_func)(int argc, char *argv[]); +extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); -#include "begin_code.h" -#ifdef __cplusplus -/* *INDENT-OFF* */ -extern "C" { -/* *INDENT-ON* */ -#endif +/** + * Circumvent failure of SDL_Init() when not using SDL_main() as an entry + * point. + * + * This function is defined in SDL_main.h, along with the preprocessor rule to + * redefine main() as SDL_main(). Thus to ensure that your main() function + * will not be changed it is necessary to define SDL_MAIN_HANDLED before + * including SDL.h. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_Init + */ +extern DECLSPEC void SDLCALL SDL_SetMainReady(void); #ifdef __WIN32__ /** - * This can be called to set the application class at startup + * Register a win32 window class for SDL's use. + * + * This can be called to set the application window class at startup. It is + * safe to call this multiple times, as long as every call is eventually + * paired with a call to SDL_UnregisterApp, but a second registration attempt + * while a previous registration is still active will be ignored, other than + * to increment a counter. + * + * Most applications do not need to, and should not, call this directly; SDL + * will call it when initializing the video subsystem. + * + * \param name the window class name, in UTF-8 encoding. If NULL, SDL + * currently uses "SDL_app" but this isn't guaranteed. + * \param style the value to use in WNDCLASSEX::style. If `name` is NULL, SDL + * currently uses `(CS_BYTEALIGNCLIENT | CS_OWNDC)` regardless of + * what is specified here. + * \param hInst the HINSTANCE to use in WNDCLASSEX::hInstance. If zero, SDL + * will use `GetModuleHandle(NULL)` instead. + * \returns 0 on success, -1 on error. SDL_GetError() may have details. + * + * \since This function is available since SDL 2.0.2. + */ +extern DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); + +/** + * Deregister the win32 window class from an SDL_RegisterApp call. + * + * This can be called to undo the effects of SDL_RegisterApp. + * + * Most applications do not need to, and should not, call this directly; SDL + * will call it when deinitializing the video subsystem. + * + * It is safe to call this multiple times, as long as every call is eventually + * paired with a prior call to SDL_RegisterApp. The window class will only be + * deregistered when the registration counter in SDL_RegisterApp decrements to + * zero through calls to this function. + * + * \since This function is available since SDL 2.0.2. */ -extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, - void *hInst); extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); #endif /* __WIN32__ */ +#ifdef __WINRT__ + +/** + * Initialize and launch an SDL/WinRT application. + * + * \param mainFunction the SDL app's C-style main(), an SDL_main_func + * \param reserved reserved for future use; should be NULL + * \returns 0 on success or -1 on failure; call SDL_GetError() to retrieve + * more information on the failure. + * + * \since This function is available since SDL 2.0.3. + */ +extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved); + +#endif /* __WINRT__ */ + +#if defined(__IPHONEOS__) + +/** + * Initializes and launches an SDL application. + * + * \param argc The argc parameter from the application's main() function + * \param argv The argv parameter from the application's main() function + * \param mainFunction The SDL app's C-style main(), an SDL_main_func + * \return the return value from mainFunction + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction); + +#endif /* __IPHONEOS__ */ + + #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_main_h */ +#endif /* SDL_main_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_messagebox.h b/external/SDL2/SDL_messagebox.h index dd788cf..d763534 100644 --- a/external/SDL2/SDL_messagebox.h +++ b/external/SDL2/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_messagebox_h -#define _SDL_messagebox_h +#ifndef SDL_messagebox_h_ +#define SDL_messagebox_h_ #include "SDL_stdinc.h" #include "SDL_video.h" /* For SDL_Window */ @@ -28,23 +28,23 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief SDL_MessageBox flags. If supported will display warning icon, etc. + * SDL_MessageBox flags. If supported will display warning icon, etc. */ typedef enum { - SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */ - SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */ - SDL_MESSAGEBOX_INFORMATION = 0x00000040 /**< informational dialog */ + SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */ + SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */ + SDL_MESSAGEBOX_INFORMATION = 0x00000040, /**< informational dialog */ + SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT = 0x00000080, /**< buttons placed left to right */ + SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT = 0x00000100 /**< buttons placed right to left */ } SDL_MessageBoxFlags; /** - * \brief Flags for SDL_MessageBoxButtonData. + * Flags for SDL_MessageBoxButtonData. */ typedef enum { @@ -53,17 +53,17 @@ typedef enum } SDL_MessageBoxButtonFlags; /** - * \brief Individual button data. + * Individual button data. */ typedef struct { Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */ - int buttonid; /**< User defined button id (value returned via SDL_MessageBox) */ + int buttonid; /**< User defined button id (value returned via SDL_ShowMessageBox) */ const char * text; /**< The UTF-8 button text */ } SDL_MessageBoxButtonData; /** - * \brief RGB value used in a message box color scheme + * RGB value used in a message box color scheme */ typedef struct { @@ -81,7 +81,7 @@ typedef enum } SDL_MessageBoxColorType; /** - * \brief A set of colors to use for message box dialogs + * A set of colors to use for message box dialogs */ typedef struct { @@ -89,7 +89,7 @@ typedef struct } SDL_MessageBoxColorScheme; /** - * \brief MessageBox structure containing title, text, window, etc. + * MessageBox structure containing title, text, window, etc. */ typedef struct { @@ -105,43 +105,89 @@ typedef struct } SDL_MessageBoxData; /** - * \brief Create a modal message box. + * Create a modal message box. * - * \param messagebox The SDL_MessageBox structure with title, text, etc. + * If your needs aren't complex, it might be easier to use + * SDL_ShowSimpleMessageBox. * - * \return -1 on error, otherwise 0 and buttonid contains user id of button - * hit or -1 if dialog was closed. + * This function should be called on the thread that created the parent + * window, or on the main thread if the messagebox has no parent. It will + * block execution of that thread until the user clicks a button or closes the + * messagebox. * - * \note This function should be called on the thread that created the parent - * window, or on the main thread if the messagebox has no parent. It will - * block execution of that thread until the user clicks a button or - * closes the messagebox. + * This function may be called at any time, even before SDL_Init(). This makes + * it useful for reporting errors like a failure to create a renderer or + * OpenGL context. + * + * On X11, SDL rolls its own dialog box with X11 primitives instead of a + * formal toolkit like GTK+ or Qt. + * + * Note that if SDL_Init() would fail because there isn't any available video + * target, this function is likely to fail for the same reasons. If this is a + * concern, check the return value from this function and fall back to writing + * to stderr if you can. + * + * \param messageboxdata the SDL_MessageBoxData structure with title, text and + * other options + * \param buttonid the pointer to which user id of hit button should be copied + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ShowSimpleMessageBox */ extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); /** - * \brief Create a simple modal message box + * Display a simple modal message box. * - * \param flags ::SDL_MessageBoxFlags - * \param title UTF-8 title text - * \param message UTF-8 message text - * \param window The parent window, or NULL for no parent + * If your needs aren't complex, this function is preferred over + * SDL_ShowMessageBox. * - * \return 0 on success, -1 on error + * `flags` may be any of the following: * - * \sa SDL_ShowMessageBox + * - `SDL_MESSAGEBOX_ERROR`: error dialog + * - `SDL_MESSAGEBOX_WARNING`: warning dialog + * - `SDL_MESSAGEBOX_INFORMATION`: informational dialog + * + * This function should be called on the thread that created the parent + * window, or on the main thread if the messagebox has no parent. It will + * block execution of that thread until the user clicks a button or closes the + * messagebox. + * + * This function may be called at any time, even before SDL_Init(). This makes + * it useful for reporting errors like a failure to create a renderer or + * OpenGL context. + * + * On X11, SDL rolls its own dialog box with X11 primitives instead of a + * formal toolkit like GTK+ or Qt. + * + * Note that if SDL_Init() would fail because there isn't any available video + * target, this function is likely to fail for the same reasons. If this is a + * concern, check the return value from this function and fall back to writing + * to stderr if you can. + * + * \param flags an SDL_MessageBoxFlags value + * \param title UTF-8 title text + * \param message UTF-8 message text + * \param window the parent window, or NULL for no parent + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ShowMessageBox */ extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_messagebox_h */ +#endif /* SDL_messagebox_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_metal.h b/external/SDL2/SDL_metal.h new file mode 100644 index 0000000..9ecaa81 --- /dev/null +++ b/external/SDL2/SDL_metal.h @@ -0,0 +1,112 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_metal.h + * + * Header file for functions to creating Metal layers and views on SDL windows. + */ + +#ifndef SDL_metal_h_ +#define SDL_metal_h_ + +#include "SDL_video.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS). + * + * \note This can be cast directly to an NSView or UIView. + */ +typedef void *SDL_MetalView; + +/** + * \name Metal support functions + */ +/* @{ */ + +/** + * Create a CAMetalLayer-backed NSView/UIView and attach it to the specified + * window. + * + * On macOS, this does *not* associate a MTLDevice with the CAMetalLayer on + * its own. It is up to user code to do that. + * + * The returned handle can be casted directly to a NSView or UIView. To access + * the backing CAMetalLayer, call SDL_Metal_GetLayer(). + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_Metal_DestroyView + * \sa SDL_Metal_GetLayer + */ +extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window); + +/** + * Destroy an existing SDL_MetalView object. + * + * This should be called before SDL_DestroyWindow, if SDL_Metal_CreateView was + * called after SDL_CreateWindow. + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_Metal_CreateView + */ +extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view); + +/** + * Get a pointer to the backing CAMetalLayer for the given view. + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_MetalCreateView + */ +extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view); + +/** + * Get the size of a window's underlying drawable in pixels (for use with + * setting viewport, scissor & etc). + * + * \param window SDL_Window from which the drawable size should be queried + * \param w Pointer to variable for storing the width in pixels, may be NULL + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_GetWindowSize + * \sa SDL_CreateWindow + */ +extern DECLSPEC void SDLCALL SDL_Metal_GetDrawableSize(SDL_Window* window, int *w, + int *h); + +/* @} *//* Metal support functions */ + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_metal_h_ */ diff --git a/external/SDL2/SDL_misc.h b/external/SDL2/SDL_misc.h new file mode 100644 index 0000000..261b6b8 --- /dev/null +++ b/external/SDL2/SDL_misc.h @@ -0,0 +1,79 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_misc.h + * + * \brief Include file for SDL API functions that don't fit elsewhere. + */ + +#ifndef SDL_misc_h_ +#define SDL_misc_h_ + +#include "SDL_stdinc.h" + +#include "begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Open a URL/URI in the browser or other appropriate external application. + * + * Open a URL in a separate, system-provided application. How this works will + * vary wildly depending on the platform. This will likely launch what makes + * sense to handle a specific URL's protocol (a web browser for `http://`, + * etc), but it might also be able to launch file managers for directories and + * other things. + * + * What happens when you open a URL varies wildly as well: your game window + * may lose focus (and may or may not lose focus if your game was fullscreen + * or grabbing input at the time). On mobile devices, your app will likely + * move to the background or your process might be paused. Any given platform + * may or may not handle a given URL. + * + * If this is unimplemented (or simply unavailable) for a platform, this will + * fail with an error. A successful result does not mean the URL loaded, just + * that we launched _something_ to handle it (or at least believe we did). + * + * All this to say: this function can be useful, but you should definitely + * test it on every platform you target. + * + * \param url A valid URL/URI to open. Use `file:///full/path/to/file` for + * local files, if supported. + * \returns 0 on success, or -1 on error; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC int SDLCALL SDL_OpenURL(const char *url); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_misc_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_mouse.h b/external/SDL2/SDL_mouse.h index f6d6300..1d4a2db 100644 --- a/external/SDL2/SDL_mouse.h +++ b/external/SDL2/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_mouse.h - * + * * Include file for SDL mouse event handling. */ -#ifndef _SDL_mouse_h -#define _SDL_mouse_h +#ifndef SDL_mouse_h_ +#define SDL_mouse_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -35,113 +35,277 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif -typedef struct SDL_Cursor SDL_Cursor; /* Implementation dependent */ +typedef struct SDL_Cursor SDL_Cursor; /**< Implementation dependent */ /** - * \brief Cursor types for SDL_CreateSystemCursor. + * \brief Cursor types for SDL_CreateSystemCursor(). */ typedef enum { - SDL_SYSTEM_CURSOR_ARROW, // Arrow - SDL_SYSTEM_CURSOR_IBEAM, // I-beam - SDL_SYSTEM_CURSOR_WAIT, // Wait - SDL_SYSTEM_CURSOR_CROSSHAIR, // Crosshair - SDL_SYSTEM_CURSOR_WAITARROW, // Small wait cursor (or Wait if not available) - SDL_SYSTEM_CURSOR_SIZENWSE, // Double arrow pointing northwest and southeast - SDL_SYSTEM_CURSOR_SIZENESW, // Double arrow pointing northeast and southwest - SDL_SYSTEM_CURSOR_SIZEWE, // Double arrow pointing west and east - SDL_SYSTEM_CURSOR_SIZENS, // Double arrow pointing north and south - SDL_SYSTEM_CURSOR_SIZEALL, // Four pointed arrow pointing north, south, east, and west - SDL_SYSTEM_CURSOR_NO, // Slashed circle or crossbones - SDL_SYSTEM_CURSOR_HAND, // Hand + SDL_SYSTEM_CURSOR_ARROW, /**< Arrow */ + SDL_SYSTEM_CURSOR_IBEAM, /**< I-beam */ + SDL_SYSTEM_CURSOR_WAIT, /**< Wait */ + SDL_SYSTEM_CURSOR_CROSSHAIR, /**< Crosshair */ + SDL_SYSTEM_CURSOR_WAITARROW, /**< Small wait cursor (or Wait if not available) */ + SDL_SYSTEM_CURSOR_SIZENWSE, /**< Double arrow pointing northwest and southeast */ + SDL_SYSTEM_CURSOR_SIZENESW, /**< Double arrow pointing northeast and southwest */ + SDL_SYSTEM_CURSOR_SIZEWE, /**< Double arrow pointing west and east */ + SDL_SYSTEM_CURSOR_SIZENS, /**< Double arrow pointing north and south */ + SDL_SYSTEM_CURSOR_SIZEALL, /**< Four pointed arrow pointing north, south, east, and west */ + SDL_SYSTEM_CURSOR_NO, /**< Slashed circle or crossbones */ + SDL_SYSTEM_CURSOR_HAND, /**< Hand */ SDL_NUM_SYSTEM_CURSORS } SDL_SystemCursor; +/** + * \brief Scroll direction types for the Scroll event + */ +typedef enum +{ + SDL_MOUSEWHEEL_NORMAL, /**< The scroll direction is normal */ + SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */ +} SDL_MouseWheelDirection; + /* Function prototypes */ /** - * \brief Get the window which currently has mouse focus. + * Get the window which currently has mouse focus. + * + * \returns the window with mouse focus. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void); /** - * \brief Retrieve the current state of the mouse. - * - * The current button state is returned as a button bitmask, which can - * be tested using the SDL_BUTTON(X) macros, and x and y are set to the - * mouse cursor position relative to the focus window for the currently - * selected mouse. You can pass NULL for either x or y. + * Retrieve the current state of the mouse. + * + * The current button state is returned as a button bitmask, which can be + * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the + * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the + * mouse cursor position relative to the focus window. You can pass NULL for + * either `x` or `y`. + * + * \param x the x coordinate of the mouse cursor position relative to the + * focus window + * \param y the y coordinate of the mouse cursor position relative to the + * focus window + * \returns a 32-bit button bitmask of the current button state. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetGlobalMouseState + * \sa SDL_GetRelativeMouseState + * \sa SDL_PumpEvents */ extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(int *x, int *y); /** - * \brief Retrieve the relative state of the mouse. + * Get the current state of the mouse in relation to the desktop. * - * The current button state is returned as a button bitmask, which can - * be tested using the SDL_BUTTON(X) macros, and x and y are set to the - * mouse deltas since the last call to SDL_GetRelativeMouseState(). + * This works similarly to SDL_GetMouseState(), but the coordinates will be + * reported relative to the top-left of the desktop. This can be useful if you + * need to track the mouse outside of a specific window and SDL_CaptureMouse() + * doesn't fit your needs. For example, it could be useful if you need to + * track the mouse while dragging a window, where coordinates relative to a + * window might not be in sync at all times. + * + * Note: SDL_GetMouseState() returns the mouse position as SDL understands it + * from the last pump of the event queue. This function, however, queries the + * OS for the current mouse position, and as such, might be a slightly less + * efficient function. Unless you know what you're doing and have a good + * reason to use this function, you probably want SDL_GetMouseState() instead. + * + * \param x filled in with the current X coord relative to the desktop; can be + * NULL + * \param y filled in with the current Y coord relative to the desktop; can be + * NULL + * \returns the current button state as a bitmask which can be tested using + * the SDL_BUTTON(X) macros. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_CaptureMouse + */ +extern DECLSPEC Uint32 SDLCALL SDL_GetGlobalMouseState(int *x, int *y); + +/** + * Retrieve the relative state of the mouse. + * + * The current button state is returned as a button bitmask, which can be + * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the + * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the + * mouse deltas since the last call to SDL_GetRelativeMouseState() or since + * event initialization. You can pass NULL for either `x` or `y`. + * + * \param x a pointer filled with the last recorded x coordinate of the mouse + * \param y a pointer filled with the last recorded y coordinate of the mouse + * \returns a 32-bit button bitmask of the relative button state. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetMouseState */ extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(int *x, int *y); /** - * \brief Moves the mouse to the given position within the window. - * - * \param window The window to move the mouse into, or NULL for the current mouse focus - * \param x The x coordinate within the window - * \param y The y coordinate within the window - * - * \note This function generates a mouse motion event + * Move the mouse cursor to the given position within the window. + * + * This function generates a mouse motion event. + * + * Note that this function will appear to succeed, but not actually move the + * mouse when used over Microsoft Remote Desktop. + * + * \param window the window to move the mouse into, or NULL for the current + * mouse focus + * \param x the x coordinate within the window + * \param y the y coordinate within the window + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WarpMouseGlobal */ extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window, int x, int y); /** - * \brief Set relative mouse mode. - * - * \param enabled Whether or not to enable relative mode + * Move the mouse to the given position in global screen space. * - * \return 0 on success, or -1 if relative mode is not supported. - * - * While the mouse is in relative mode, the cursor is hidden, and the - * driver will try to report continuous motion in the current window. - * Only relative motion events will be delivered, the mouse position - * will not change. - * - * \note This function will flush any pending mouse motion. - * - * \sa SDL_GetRelativeMouseMode() + * This function generates a mouse motion event. + * + * A failure of this function usually means that it is unsupported by a + * platform. + * + * Note that this function will appear to succeed, but not actually move the + * mouse when used over Microsoft Remote Desktop. + * + * \param x the x coordinate + * \param y the y coordinate + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_WarpMouseInWindow + */ +extern DECLSPEC int SDLCALL SDL_WarpMouseGlobal(int x, int y); + +/** + * Set relative mouse mode. + * + * While the mouse is in relative mode, the cursor is hidden, and the driver + * will try to report continuous motion in the current window. Only relative + * motion events will be delivered, the mouse position will not change. + * + * Note that this function will not be able to provide continuous relative + * motion when used over Microsoft Remote Desktop, instead motion is limited + * to the bounds of the screen. + * + * This function will flush any pending mouse motion. + * + * \param enabled SDL_TRUE to enable relative mode, SDL_FALSE to disable. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * If relative mode is not supported, this returns -1. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRelativeMouseMode */ extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled); /** - * \brief Query whether relative mouse mode is enabled. - * - * \sa SDL_SetRelativeMouseMode() + * Capture the mouse and to track input outside an SDL window. + * + * Capturing enables your app to obtain mouse events globally, instead of just + * within your window. Not all video targets support this function. When + * capturing is enabled, the current window will get all mouse events, but + * unlike relative mode, no change is made to the cursor and it is not + * restrained to your window. + * + * This function may also deny mouse input to other windows--both those in + * your application and others on the system--so you should use this function + * sparingly, and in small bursts. For example, you might want to track the + * mouse while the user is dragging something, until the user releases a mouse + * button. It is not recommended that you capture the mouse for long periods + * of time, such as the entire time your app is running. For that, you should + * probably use SDL_SetRelativeMouseMode() or SDL_SetWindowGrab(), depending + * on your goals. + * + * While captured, mouse events still report coordinates relative to the + * current (foreground) window, but those coordinates may be outside the + * bounds of the window (including negative values). Capturing is only allowed + * for the foreground window. If the window loses focus while capturing, the + * capture will be disabled automatically. + * + * While capturing is enabled, the current window will have the + * `SDL_WINDOW_MOUSE_CAPTURE` flag set. + * + * \param enabled SDL_TRUE to enable capturing, SDL_FALSE to disable. + * \returns 0 on success or -1 if not supported; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_GetGlobalMouseState + */ +extern DECLSPEC int SDLCALL SDL_CaptureMouse(SDL_bool enabled); + +/** + * Query whether relative mouse mode is enabled. + * + * \returns SDL_TRUE if relative mode is enabled or SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetRelativeMouseMode */ extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void); /** - * \brief Create a cursor, using the specified bitmap data and - * mask (in MSB format). - * - * The cursor width must be a multiple of 8 bits. - * - * The cursor is created in black and white according to the following: - * - * - * - * - * - * - *
data mask resulting pixel on screen
0 1 White
1 1 Black
0 0 Transparent
1 0 Inverted color if possible, black - * if not.
- * - * \sa SDL_FreeCursor() + * Create a cursor using the specified bitmap data and mask (in MSB format). + * + * `mask` has to be in MSB (Most Significant Bit) format. + * + * The cursor width (`w`) must be a multiple of 8 bits. + * + * The cursor is created in black and white according to the following: + * + * - data=0, mask=1: white + * - data=1, mask=1: black + * - data=0, mask=0: transparent + * - data=1, mask=0: inverted color if possible, black if not. + * + * Cursors created with this function must be freed with SDL_FreeCursor(). + * + * If you want to have a color cursor, or create your cursor from an + * SDL_Surface, you should use SDL_CreateColorCursor(). Alternately, you can + * hide the cursor and draw your own as part of your game's rendering, but it + * will be bound to the framerate. + * + * Also, since SDL 2.0.0, SDL_CreateSystemCursor() is available, which + * provides twelve readily available system cursors to pick from. + * + * \param data the color value for each pixel of the cursor + * \param mask the mask value for each pixel of the cursor + * \param w the width of the cursor + * \param h the height of the cursor + * \param hot_x the X-axis location of the upper left corner of the cursor + * relative to the actual mouse position + * \param hot_y the Y-axis location of the upper left corner of the cursor + * relative to the actual mouse position + * \returns a new cursor with the specified parameters on success or NULL on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreeCursor + * \sa SDL_SetCursor + * \sa SDL_ShowCursor */ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data, const Uint8 * mask, @@ -149,75 +313,142 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data, int hot_y); /** - * \brief Create a color cursor. - * - * \sa SDL_FreeCursor() + * Create a color cursor. + * + * \param surface an SDL_Surface structure representing the cursor image + * \param hot_x the x position of the cursor hot spot + * \param hot_y the y position of the cursor hot spot + * \returns the new cursor on success or NULL on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateCursor + * \sa SDL_FreeCursor */ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y); /** - * \brief Create a system cursor. + * Create a system cursor. * - * \sa SDL_FreeCursor() + * \param id an SDL_SystemCursor enum value + * \returns a cursor on success or NULL on failure; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreeCursor */ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id); /** - * \brief Set the active cursor. + * Set the active cursor. + * + * This function sets the currently active cursor to the specified one. If the + * cursor is currently visible, the change will be immediately represented on + * the display. SDL_SetCursor(NULL) can be used to force cursor redraw, if + * this is desired for any reason. + * + * \param cursor a cursor to make active + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateCursor + * \sa SDL_GetCursor + * \sa SDL_ShowCursor */ extern DECLSPEC void SDLCALL SDL_SetCursor(SDL_Cursor * cursor); /** - * \brief Return the active cursor. + * Get the active cursor. + * + * This function returns a pointer to the current cursor which is owned by the + * library. It is not necessary to free the cursor with SDL_FreeCursor(). + * + * \returns the active cursor or NULL if there is no mouse. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetCursor */ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void); /** - * \brief Frees a cursor created with SDL_CreateCursor(). - * - * \sa SDL_CreateCursor() + * Get the default cursor. + * + * \returns the default cursor on success or NULL on failure. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSystemCursor + */ +extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void); + +/** + * Free a previously-created cursor. + * + * Use this function to free cursor resources created with SDL_CreateCursor(), + * SDL_CreateColorCursor() or SDL_CreateSystemCursor(). + * + * \param cursor the cursor to free + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateColorCursor + * \sa SDL_CreateCursor + * \sa SDL_CreateSystemCursor */ extern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor * cursor); /** - * \brief Toggle whether or not the cursor is shown. - * - * \param toggle 1 to show the cursor, 0 to hide it, -1 to query the current - * state. - * - * \return 1 if the cursor is shown, or 0 if the cursor is hidden. + * Toggle whether or not the cursor is shown. + * + * The cursor starts off displayed but can be turned off. Passing `SDL_ENABLE` + * displays the cursor and passing `SDL_DISABLE` hides it. + * + * The current state of the mouse cursor can be queried by passing + * `SDL_QUERY`; either `SDL_DISABLE` or `SDL_ENABLE` will be returned. + * + * \param toggle `SDL_ENABLE` to show the cursor, `SDL_DISABLE` to hide it, + * `SDL_QUERY` to query the current state without changing it. + * \returns `SDL_ENABLE` if the cursor is shown, or `SDL_DISABLE` if the + * cursor is hidden, or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateCursor + * \sa SDL_SetCursor */ extern DECLSPEC int SDLCALL SDL_ShowCursor(int toggle); /** - * Used as a mask when testing buttons in buttonstate. - * - Button 1: Left mouse button - * - Button 2: Middle mouse button - * - Button 3: Right mouse button + * Used as a mask when testing buttons in buttonstate. + * + * - Button 1: Left mouse button + * - Button 2: Middle mouse button + * - Button 3: Right mouse button */ -#define SDL_BUTTON(X) (1 << ((X)-1)) -#define SDL_BUTTON_LEFT 1 -#define SDL_BUTTON_MIDDLE 2 -#define SDL_BUTTON_RIGHT 3 -#define SDL_BUTTON_X1 4 -#define SDL_BUTTON_X2 5 -#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT) -#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE) -#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT) -#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1) -#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2) - +#define SDL_BUTTON(X) (1 << ((X)-1)) +#define SDL_BUTTON_LEFT 1 +#define SDL_BUTTON_MIDDLE 2 +#define SDL_BUTTON_RIGHT 3 +#define SDL_BUTTON_X1 4 +#define SDL_BUTTON_X2 5 +#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT) +#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE) +#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT) +#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1) +#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2) /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_mouse_h */ +#endif /* SDL_mouse_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_mutex.h b/external/SDL2/SDL_mutex.h index 30519b8..173468f 100644 --- a/external/SDL2/SDL_mutex.h +++ b/external/SDL2/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,12 +19,12 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_mutex_h -#define _SDL_mutex_h +#ifndef SDL_mutex_h_ +#define SDL_mutex_h_ /** * \file SDL_mutex.h - * + * * Functions to provide thread synchronization primitives. */ @@ -34,222 +34,438 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * Synchronization functions which can time out return this value * if they time out. */ -#define SDL_MUTEX_TIMEDOUT 1 +#define SDL_MUTEX_TIMEDOUT 1 /** * This is the timeout value which corresponds to never time out. */ -#define SDL_MUTEX_MAXWAIT (~(Uint32)0) +#define SDL_MUTEX_MAXWAIT (~(Uint32)0) /** * \name Mutex functions */ -/*@{*/ +/* @{ */ -/* The SDL mutex structure, defined in SDL_mutex.c */ +/* The SDL mutex structure, defined in SDL_sysmutex.c */ struct SDL_mutex; typedef struct SDL_mutex SDL_mutex; /** - * Create a mutex, initialized unlocked. + * Create a new mutex. + * + * All newly-created mutexes begin in the _unlocked_ state. + * + * Calls to SDL_LockMutex() will not return while the mutex is locked by + * another thread. See SDL_TryLockMutex() to attempt to lock without blocking. + * + * SDL mutexes are reentrant. + * + * \returns the initialized and unlocked mutex or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DestroyMutex + * \sa SDL_LockMutex + * \sa SDL_TryLockMutex + * \sa SDL_UnlockMutex */ extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void); /** - * Lock the mutex. - * - * \return 0, or -1 on error. + * Lock the mutex. + * + * This will block until the mutex is available, which is to say it is in the + * unlocked state and the OS has chosen the caller as the next thread to lock + * it. Of all threads waiting to lock the mutex, only one may do so at a time. + * + * It is legal for the owning thread to lock an already-locked mutex. It must + * unlock it the same number of times before it is actually made available for + * other threads in the system (this is known as a "recursive mutex"). + * + * \param mutex the mutex to lock + * \return 0, or -1 on error. + * + * \since This function is available since SDL 2.0.0. */ -#define SDL_mutexP(m) SDL_LockMutex(m) extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex); +#define SDL_mutexP(m) SDL_LockMutex(m) /** - * Try to lock the mutex - * - * \return 0, SDL_MUTEX_TIMEDOUT, or -1 on error + * Try to lock a mutex without blocking. + * + * This works just like SDL_LockMutex(), but if the mutex is not available, + * this function returns `SDL_MUTEX_TIMEOUT` immediately. + * + * This technique is useful if you need exclusive access to a resource but + * don't want to wait for it, and will return to it to try again later. + * + * \param mutex the mutex to try to lock + * \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateMutex + * \sa SDL_DestroyMutex + * \sa SDL_LockMutex + * \sa SDL_UnlockMutex */ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex); /** - * Unlock the mutex. - * - * \return 0, or -1 on error. - * - * \warning It is an error to unlock a mutex that has not been locked by - * the current thread, and doing so results in undefined behavior. + * Unlock the mutex. + * + * It is legal for the owning thread to lock an already-locked mutex. It must + * unlock it the same number of times before it is actually made available for + * other threads in the system (this is known as a "recursive mutex"). + * + * It is an error to unlock a mutex that has not been locked by the current + * thread, and doing so results in undefined behavior. + * + * It is also an error to unlock a mutex that isn't locked at all. + * + * \param mutex the mutex to unlock. + * \returns 0, or -1 on error. + * + * \since This function is available since SDL 2.0.0. */ -#define SDL_mutexV(m) SDL_UnlockMutex(m) extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex); +#define SDL_mutexV(m) SDL_UnlockMutex(m) -/** - * Destroy a mutex. +/** + * Destroy a mutex created with SDL_CreateMutex(). + * + * This function must be called on any mutex that is no longer needed. Failure + * to destroy a mutex will result in a system memory or resource leak. While + * it is safe to destroy a mutex that is _unlocked_, it is not safe to attempt + * to destroy a locked mutex, and may result in undefined behavior depending + * on the platform. + * + * \param mutex the mutex to destroy + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateMutex + * \sa SDL_LockMutex + * \sa SDL_TryLockMutex + * \sa SDL_UnlockMutex */ extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex); -/*@}*//*Mutex functions*/ +/* @} *//* Mutex functions */ /** * \name Semaphore functions */ -/*@{*/ +/* @{ */ -/* The SDL semaphore structure, defined in SDL_sem.c */ +/* The SDL semaphore structure, defined in SDL_syssem.c */ struct SDL_semaphore; typedef struct SDL_semaphore SDL_sem; /** - * Create a semaphore, initialized with value, returns NULL on failure. + * Create a semaphore. + * + * This function creates a new semaphore and initializes it with the value + * `initial_value`. Each wait operation on the semaphore will atomically + * decrement the semaphore value and potentially block if the semaphore value + * is 0. Each post operation will atomically increment the semaphore value and + * wake waiting threads and allow them to retry the wait operation. + * + * \param initial_value the starting value of the semaphore + * \returns a new semaphore or NULL on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DestroySemaphore + * \sa SDL_SemPost + * \sa SDL_SemTryWait + * \sa SDL_SemValue + * \sa SDL_SemWait + * \sa SDL_SemWaitTimeout */ extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value); /** - * Destroy a semaphore. + * Destroy a semaphore. + * + * It is not safe to destroy a semaphore if there are threads currently + * waiting on it. + * + * \param sem the semaphore to destroy + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSemaphore + * \sa SDL_SemPost + * \sa SDL_SemTryWait + * \sa SDL_SemValue + * \sa SDL_SemWait + * \sa SDL_SemWaitTimeout */ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem); /** - * This function suspends the calling thread until the semaphore pointed - * to by \c sem has a positive count. It then atomically decreases the - * semaphore count. + * Wait until a semaphore has a positive value and then decrements it. + * + * This function suspends the calling thread until either the semaphore + * pointed to by `sem` has a positive value or the call is interrupted by a + * signal or error. If the call is successful it will atomically decrement the + * semaphore value. + * + * This function is the equivalent of calling SDL_SemWaitTimeout() with a time + * length of `SDL_MUTEX_MAXWAIT`. + * + * \param sem the semaphore wait on + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSemaphore + * \sa SDL_DestroySemaphore + * \sa SDL_SemPost + * \sa SDL_SemTryWait + * \sa SDL_SemValue + * \sa SDL_SemWait + * \sa SDL_SemWaitTimeout */ extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem); /** - * Non-blocking variant of SDL_SemWait(). - * - * \return 0 if the wait succeeds, ::SDL_MUTEX_TIMEDOUT if the wait would - * block, and -1 on error. + * See if a semaphore has a positive value and decrement it if it does. + * + * This function checks to see if the semaphore pointed to by `sem` has a + * positive value and atomically decrements the semaphore value if it does. If + * the semaphore doesn't have a positive value, the function immediately + * returns SDL_MUTEX_TIMEDOUT. + * + * \param sem the semaphore to wait on + * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait would + * block, or a negative error code on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSemaphore + * \sa SDL_DestroySemaphore + * \sa SDL_SemPost + * \sa SDL_SemValue + * \sa SDL_SemWait + * \sa SDL_SemWaitTimeout */ extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem); /** - * Variant of SDL_SemWait() with a timeout in milliseconds. - * - * \return 0 if the wait succeeds, ::SDL_MUTEX_TIMEDOUT if the wait does not - * succeed in the allotted time, and -1 on error. - * - * \warning On some platforms this function is implemented by looping with a - * delay of 1 ms, and so should be avoided if possible. + * Wait until a semaphore has a positive value and then decrements it. + * + * This function suspends the calling thread until either the semaphore + * pointed to by `sem` has a positive value, the call is interrupted by a + * signal or error, or the specified time has elapsed. If the call is + * successful it will atomically decrement the semaphore value. + * + * \param sem the semaphore to wait on + * \param ms the length of the timeout, in milliseconds + * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not + * succeed in the allotted time, or a negative error code on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSemaphore + * \sa SDL_DestroySemaphore + * \sa SDL_SemPost + * \sa SDL_SemTryWait + * \sa SDL_SemValue + * \sa SDL_SemWait */ extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem * sem, Uint32 ms); /** - * Atomically increases the semaphore's count (not blocking). - * - * \return 0, or -1 on error. + * Atomically increment a semaphore's value and wake waiting threads. + * + * \param sem the semaphore to increment + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSemaphore + * \sa SDL_DestroySemaphore + * \sa SDL_SemTryWait + * \sa SDL_SemValue + * \sa SDL_SemWait + * \sa SDL_SemWaitTimeout */ extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem); /** - * Returns the current count of the semaphore. + * Get the current value of a semaphore. + * + * \param sem the semaphore to query + * \returns the current value of the semaphore. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSemaphore */ extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem); -/*@}*//*Semaphore functions*/ +/* @} *//* Semaphore functions */ /** * \name Condition variable functions */ -/*@{*/ +/* @{ */ -/* The SDL condition variable structure, defined in SDL_cond.c */ +/* The SDL condition variable structure, defined in SDL_syscond.c */ struct SDL_cond; typedef struct SDL_cond SDL_cond; /** - * Create a condition variable. + * Create a condition variable. * - * Typical use of condition variables: + * \returns a new condition variable or NULL on failure; call SDL_GetError() + * for more information. * - * Thread A: - * SDL_LockMutex(lock); - * while ( ! condition ) { - * SDL_CondWait(cond, lock); - * } - * SDL_UnlockMutex(lock); + * \since This function is available since SDL 2.0.0. * - * Thread B: - * SDL_LockMutex(lock); - * ... - * condition = true; - * ... - * SDL_CondSignal(cond); - * SDL_UnlockMutex(lock); - * - * There is some discussion whether to signal the condition variable - * with the mutex locked or not. There is some potential performance - * benefit to unlocking first on some platforms, but there are some - * potential race conditions depending on how your code is structured. - * - * In general it's safer to signal the condition variable while the - * mutex is locked. + * \sa SDL_CondBroadcast + * \sa SDL_CondSignal + * \sa SDL_CondWait + * \sa SDL_CondWaitTimeout + * \sa SDL_DestroyCond */ extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void); /** - * Destroy a condition variable. + * Destroy a condition variable. + * + * \param cond the condition variable to destroy + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CondBroadcast + * \sa SDL_CondSignal + * \sa SDL_CondWait + * \sa SDL_CondWaitTimeout + * \sa SDL_CreateCond */ extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond); /** - * Restart one of the threads that are waiting on the condition variable. - * - * \return 0 or -1 on error. + * Restart one of the threads that are waiting on the condition variable. + * + * \param cond the condition variable to signal + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CondBroadcast + * \sa SDL_CondWait + * \sa SDL_CondWaitTimeout + * \sa SDL_CreateCond + * \sa SDL_DestroyCond */ extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond); /** - * Restart all threads that are waiting on the condition variable. + * Restart all threads that are waiting on the condition variable. * - * \return 0 or -1 on error. + * \param cond the condition variable to signal + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CondSignal + * \sa SDL_CondWait + * \sa SDL_CondWaitTimeout + * \sa SDL_CreateCond + * \sa SDL_DestroyCond */ extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond); /** - * Wait on the condition variable, unlocking the provided mutex. - * - * \warning The mutex must be locked before entering this function! - * - * The mutex is re-locked once the condition variable is signaled. - * - * \return 0 when it is signaled, or -1 on error. + * Wait until a condition variable is signaled. + * + * This function unlocks the specified `mutex` and waits for another thread to + * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable + * `cond`. Once the condition variable is signaled, the mutex is re-locked and + * the function returns. + * + * The mutex must be locked before calling this function. + * + * This function is the equivalent of calling SDL_CondWaitTimeout() with a + * time length of `SDL_MUTEX_MAXWAIT`. + * + * \param cond the condition variable to wait on + * \param mutex the mutex used to coordinate thread access + * \returns 0 when it is signaled or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CondBroadcast + * \sa SDL_CondSignal + * \sa SDL_CondWaitTimeout + * \sa SDL_CreateCond + * \sa SDL_DestroyCond */ extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex); /** - * Waits for at most \c ms milliseconds, and returns 0 if the condition - * variable is signaled, ::SDL_MUTEX_TIMEDOUT if the condition is not - * signaled in the allotted time, and -1 on error. + * Wait until a condition variable is signaled or a certain time has passed. * - * \warning On some platforms this function is implemented by looping with a - * delay of 1 ms, and so should be avoided if possible. + * This function unlocks the specified `mutex` and waits for another thread to + * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable + * `cond`, or for the specified time to elapse. Once the condition variable is + * signaled or the time elapsed, the mutex is re-locked and the function + * returns. + * + * The mutex must be locked before calling this function. + * + * \param cond the condition variable to wait on + * \param mutex the mutex used to coordinate thread access + * \param ms the maximum time to wait, in milliseconds, or `SDL_MUTEX_MAXWAIT` + * to wait indefinitely + * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if + * the condition is not signaled in the allotted time, or a negative + * error code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CondBroadcast + * \sa SDL_CondSignal + * \sa SDL_CondWait + * \sa SDL_CreateCond + * \sa SDL_DestroyCond */ extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms); -/*@}*//*Condition variable functions*/ +/* @} *//* Condition variable functions */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_mutex_h */ +#endif /* SDL_mutex_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_name.h b/external/SDL2/SDL_name.h index 511619a..6ff35b4 100644 --- a/external/SDL2/SDL_name.h +++ b/external/SDL2/SDL_name.h @@ -1,11 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga -#ifndef _SDLname_h_ -#define _SDLname_h_ + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDLname_h_ +#define SDLname_h_ #if defined(__STDC__) || defined(__cplusplus) #define NeedFunctionPrototypes 1 #endif -#define SDL_NAME(X) SDL_##X +#define SDL_NAME(X) SDL_##X -#endif /* _SDLname_h_ */ +#endif /* SDLname_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_opengl.h b/external/SDL2/SDL_opengl.h index 079ed74..9aed503 100644 --- a/external/SDL2/SDL_opengl.h +++ b/external/SDL2/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,5304 +21,1954 @@ /** * \file SDL_opengl.h - * + * * This is a simple file to encapsulate the OpenGL API headers. */ -#ifndef _SDL_opengl_h -#define _SDL_opengl_h - -#include "SDL_config.h" - -#ifndef __IPHONEOS__ - -#ifdef __WIN32__ -#define WIN32_LEAN_AND_MEAN -#ifndef NOMINMAX -#define NOMINMAX /* Don't defined min() and max() */ -#endif -#include -#endif - -#ifdef __HAIKU__ /* !!! FIXME: temp compiler warning fix... */ -#define NO_SDL_GLEXT 1 -#endif - -#ifdef __glext_h_ -/* Someone has already included glext.h */ -#define NO_SDL_GLEXT -#endif -#ifndef NO_SDL_GLEXT -#define __glext_h_ /* Don't let gl.h include glext.h */ -#endif -#if defined(__MACOSX__) -#include /* Header File For The OpenGL Library */ -#define __X_GL_H -#else -#include /* Header File For The OpenGL Library */ -#endif -#ifndef NO_SDL_GLEXT -#undef __glext_h_ -#endif - -/** - * \file SDL_opengl.h - * - * This file is included because glext.h is not available on some systems. - * If you don't want this version included, simply define ::NO_SDL_GLEXT. - * - * The latest version is available from: - * http://www.opengl.org/registry/ - */ - /** * \def NO_SDL_GLEXT - * - * Define this if you have your own version of glext.h and want to disable the + * + * Define this if you have your own version of glext.h and want to disable the * version included in SDL_opengl.h. */ -#if !defined(NO_SDL_GLEXT) && !defined(GL_GLEXT_LEGACY) -/* *INDENT-OFF* */ -#ifndef __glext_h_ -#define __glext_h_ +#ifndef SDL_opengl_h_ +#define SDL_opengl_h_ + +#include "SDL_config.h" + +#ifndef __IPHONEOS__ /* No OpenGL on iOS. */ + +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __gl_h_ +#define __gl_h_ + +#if defined(USE_MGL_NAMESPACE) +#include "gl_mangle.h" +#endif + + +/********************************************************************** + * Begin system-specific stuff. + */ + +#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__) +#define __WIN32__ +#endif + +#if defined(__WIN32__) && !defined(__CYGWIN__) +# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */ +# define GLAPI __declspec(dllexport) +# elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */ +# define GLAPI __declspec(dllimport) +# else /* for use with static link lib build of Win32 edition only */ +# define GLAPI extern +# endif /* _STATIC_MESA support */ +# if defined(__MINGW32__) && defined(GL_NO_STDCALL) || defined(UNDER_CE) /* The generated DLLs by MingW with STDCALL are not compatible with the ones done by Microsoft's compilers */ +# define GLAPIENTRY +# else +# define GLAPIENTRY __stdcall +# endif +#elif defined(__CYGWIN__) && defined(USE_OPENGL32) /* use native windows opengl32 */ +# define GLAPI extern +# define GLAPIENTRY __stdcall +#elif defined(__OS2__) || defined(__EMX__) /* native os/2 opengl */ +# define GLAPI extern +# define GLAPIENTRY _System +# define APIENTRY _System +# if defined(__GNUC__) && !defined(_System) +# define _System +# endif +#elif (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +# define GLAPI __attribute__((visibility("default"))) +# define GLAPIENTRY +#endif /* WIN32 && !CYGWIN */ + +/* + * WINDOWS: Include windows.h here to define APIENTRY. + * It is also useful when applications include this file by + * including only glut.h, since glut.h depends on windows.h. + * Applications needing to include windows.h with parms other + * than "WIN32_LEAN_AND_MEAN" may include windows.h before + * glut.h or gl.h. + */ +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#ifndef NOMINMAX /* don't define min() and max(). */ +#define NOMINMAX +#endif +#include +#endif + +#ifndef GLAPI +#define GLAPI extern +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY +#endif + +#ifndef APIENTRY +#define APIENTRY GLAPIENTRY +#endif + +/* "P" suffix to be used for a pointer to a function */ +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifndef GLAPIENTRYP +#define GLAPIENTRYP GLAPIENTRY * +#endif + +#if defined(PRAGMA_EXPORT_SUPPORTED) +#pragma export on +#endif + +/* + * End system-specific stuff. + **********************************************************************/ + + #ifdef __cplusplus extern "C" { #endif + + +#define GL_VERSION_1_1 1 +#define GL_VERSION_1_2 1 +#define GL_VERSION_1_3 1 +#define GL_ARB_imaging 1 + + /* -** Copyright (c) 2007-2010 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ - -/* Header file version number, required by OpenGL ABI for Linux */ -/* glext.h last updated $Date: 2010-08-03 01:30:25 -0700 (Tue, 03 Aug 2010) $ */ -/* Current version at http://www.opengl.org/registry/ */ -#define GL_GLEXT_VERSION 64 -/* Function declaration macros - to move into glplatform.h */ - -#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 -#include -#endif - -#ifndef APIENTRY -#define APIENTRY -#endif -#ifndef APIENTRYP -#define APIENTRYP APIENTRY * -#endif -#ifndef GLAPI -#define GLAPI extern -#endif - -/*************************************************************/ - -#ifndef GL_VERSION_1_2 -#define GL_UNSIGNED_BYTE_3_3_2 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2 0x8036 -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_PACK_SKIP_IMAGES 0x806B -#define GL_PACK_IMAGE_HEIGHT 0x806C -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_PROXY_TEXTURE_3D 0x8070 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 -#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 -#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 -#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#endif - -#ifndef GL_VERSION_1_2_DEPRECATED -#define GL_RESCALE_NORMAL 0x803A -#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 -#define GL_SINGLE_COLOR 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR 0x81FA -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#endif - -#ifndef GL_ARB_imaging -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 -#define GL_FUNC_ADD 0x8006 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_BLEND_EQUATION 0x8009 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#endif - -#ifndef GL_ARB_imaging_DEPRECATED -#define GL_CONVOLUTION_1D 0x8010 -#define GL_CONVOLUTION_2D 0x8011 -#define GL_SEPARABLE_2D 0x8012 -#define GL_CONVOLUTION_BORDER_MODE 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS 0x8015 -#define GL_REDUCE 0x8016 -#define GL_CONVOLUTION_FORMAT 0x8017 -#define GL_CONVOLUTION_WIDTH 0x8018 -#define GL_CONVOLUTION_HEIGHT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 -#define GL_HISTOGRAM 0x8024 -#define GL_PROXY_HISTOGRAM 0x8025 -#define GL_HISTOGRAM_WIDTH 0x8026 -#define GL_HISTOGRAM_FORMAT 0x8027 -#define GL_HISTOGRAM_RED_SIZE 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C -#define GL_HISTOGRAM_SINK 0x802D -#define GL_MINMAX 0x802E -#define GL_MINMAX_FORMAT 0x802F -#define GL_MINMAX_SINK 0x8030 -#define GL_TABLE_TOO_LARGE 0x8031 -#define GL_COLOR_MATRIX 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA -#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB -#define GL_COLOR_TABLE 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 -#define GL_PROXY_COLOR_TABLE 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 -#define GL_COLOR_TABLE_SCALE 0x80D6 -#define GL_COLOR_TABLE_BIAS 0x80D7 -#define GL_COLOR_TABLE_FORMAT 0x80D8 -#define GL_COLOR_TABLE_WIDTH 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF -#define GL_CONSTANT_BORDER 0x8151 -#define GL_REPLICATE_BORDER 0x8153 -#define GL_CONVOLUTION_BORDER_COLOR 0x8154 -#endif - -#ifndef GL_VERSION_1_3 -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_MULTISAMPLE 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE 0x809F -#define GL_SAMPLE_COVERAGE 0x80A0 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C -#define GL_COMPRESSED_RGB 0x84ED -#define GL_COMPRESSED_RGBA 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT 0x84EF -#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 -#define GL_TEXTURE_COMPRESSED 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_CLAMP_TO_BORDER 0x812D -#endif - -#ifndef GL_VERSION_1_3_DEPRECATED -#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 -#define GL_MAX_TEXTURE_UNITS 0x84E2 -#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 -#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 -#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 -#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 -#define GL_MULTISAMPLE_BIT 0x20000000 -#define GL_NORMAL_MAP 0x8511 -#define GL_REFLECTION_MAP 0x8512 -#define GL_COMPRESSED_ALPHA 0x84E9 -#define GL_COMPRESSED_LUMINANCE 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB -#define GL_COMPRESSED_INTENSITY 0x84EC -#define GL_COMBINE 0x8570 -#define GL_COMBINE_RGB 0x8571 -#define GL_COMBINE_ALPHA 0x8572 -#define GL_SOURCE0_RGB 0x8580 -#define GL_SOURCE1_RGB 0x8581 -#define GL_SOURCE2_RGB 0x8582 -#define GL_SOURCE0_ALPHA 0x8588 -#define GL_SOURCE1_ALPHA 0x8589 -#define GL_SOURCE2_ALPHA 0x858A -#define GL_OPERAND0_RGB 0x8590 -#define GL_OPERAND1_RGB 0x8591 -#define GL_OPERAND2_RGB 0x8592 -#define GL_OPERAND0_ALPHA 0x8598 -#define GL_OPERAND1_ALPHA 0x8599 -#define GL_OPERAND2_ALPHA 0x859A -#define GL_RGB_SCALE 0x8573 -#define GL_ADD_SIGNED 0x8574 -#define GL_INTERPOLATE 0x8575 -#define GL_SUBTRACT 0x84E7 -#define GL_CONSTANT 0x8576 -#define GL_PRIMARY_COLOR 0x8577 -#define GL_PREVIOUS 0x8578 -#define GL_DOT3_RGB 0x86AE -#define GL_DOT3_RGBA 0x86AF -#endif - -#ifndef GL_VERSION_1_4 -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_DEPTH_COMPONENT32 0x81A7 -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD -#define GL_TEXTURE_LOD_BIAS 0x8501 -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_TEXTURE_DEPTH_SIZE 0x884A -#define GL_TEXTURE_COMPARE_MODE 0x884C -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#endif - -#ifndef GL_VERSION_1_4_DEPRECATED -#define GL_POINT_SIZE_MIN 0x8126 -#define GL_POINT_SIZE_MAX 0x8127 -#define GL_POINT_DISTANCE_ATTENUATION 0x8129 -#define GL_GENERATE_MIPMAP 0x8191 -#define GL_GENERATE_MIPMAP_HINT 0x8192 -#define GL_FOG_COORDINATE_SOURCE 0x8450 -#define GL_FOG_COORDINATE 0x8451 -#define GL_FRAGMENT_DEPTH 0x8452 -#define GL_CURRENT_FOG_COORDINATE 0x8453 -#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 -#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 -#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 -#define GL_FOG_COORDINATE_ARRAY 0x8457 -#define GL_COLOR_SUM 0x8458 -#define GL_CURRENT_SECONDARY_COLOR 0x8459 -#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A -#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B -#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C -#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D -#define GL_SECONDARY_COLOR_ARRAY 0x845E -#define GL_TEXTURE_FILTER_CONTROL 0x8500 -#define GL_DEPTH_TEXTURE_MODE 0x884B -#define GL_COMPARE_R_TO_TEXTURE 0x884E -#endif - -#ifndef GL_VERSION_1_5 -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 -#define GL_QUERY_COUNTER_BITS 0x8864 -#define GL_CURRENT_QUERY 0x8865 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F -#define GL_READ_ONLY 0x88B8 -#define GL_WRITE_ONLY 0x88B9 -#define GL_READ_WRITE 0x88BA -#define GL_BUFFER_ACCESS 0x88BB -#define GL_BUFFER_MAPPED 0x88BC -#define GL_BUFFER_MAP_POINTER 0x88BD -#define GL_STREAM_DRAW 0x88E0 -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_DRAW 0x88E4 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_SAMPLES_PASSED 0x8914 -#endif - -#ifndef GL_VERSION_1_5_DEPRECATED -#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 -#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A -#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B -#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C -#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D -#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E -#define GL_FOG_COORD_SRC 0x8450 -#define GL_FOG_COORD 0x8451 -#define GL_CURRENT_FOG_COORD 0x8453 -#define GL_FOG_COORD_ARRAY_TYPE 0x8454 -#define GL_FOG_COORD_ARRAY_STRIDE 0x8455 -#define GL_FOG_COORD_ARRAY_POINTER 0x8456 -#define GL_FOG_COORD_ARRAY 0x8457 -#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D -#define GL_SRC0_RGB 0x8580 -#define GL_SRC1_RGB 0x8581 -#define GL_SRC2_RGB 0x8582 -#define GL_SRC0_ALPHA 0x8588 -#define GL_SRC1_ALPHA 0x8589 -#define GL_SRC2_ALPHA 0x858A -#endif - -#ifndef GL_VERSION_2_0 -#define GL_BLEND_EQUATION_RGB 0x8009 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 -#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_DRAW_BUFFER0 0x8825 -#define GL_DRAW_BUFFER1 0x8826 -#define GL_DRAW_BUFFER2 0x8827 -#define GL_DRAW_BUFFER3 0x8828 -#define GL_DRAW_BUFFER4 0x8829 -#define GL_DRAW_BUFFER5 0x882A -#define GL_DRAW_BUFFER6 0x882B -#define GL_DRAW_BUFFER7 0x882C -#define GL_DRAW_BUFFER8 0x882D -#define GL_DRAW_BUFFER9 0x882E -#define GL_DRAW_BUFFER10 0x882F -#define GL_DRAW_BUFFER11 0x8830 -#define GL_DRAW_BUFFER12 0x8831 -#define GL_DRAW_BUFFER13 0x8832 -#define GL_DRAW_BUFFER14 0x8833 -#define GL_DRAW_BUFFER15 0x8834 -#define GL_BLEND_EQUATION_ALPHA 0x883D -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A -#define GL_MAX_VARYING_FLOATS 0x8B4B -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_SHADER_TYPE 0x8B4F -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_1D 0x8B5D -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_SAMPLER_1D_SHADOW 0x8B61 -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_DELETE_STATUS 0x8B80 -#define GL_COMPILE_STATUS 0x8B81 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D -#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 -#define GL_LOWER_LEFT 0x8CA1 -#define GL_UPPER_LEFT 0x8CA2 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 -#endif - -#ifndef GL_VERSION_2_0_DEPRECATED -#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 -#define GL_POINT_SPRITE 0x8861 -#define GL_COORD_REPLACE 0x8862 -#define GL_MAX_TEXTURE_COORDS 0x8871 -#endif - -#ifndef GL_VERSION_2_1 -#define GL_PIXEL_PACK_BUFFER 0x88EB -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF -#define GL_FLOAT_MAT2x3 0x8B65 -#define GL_FLOAT_MAT2x4 0x8B66 -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT3x4 0x8B68 -#define GL_FLOAT_MAT4x2 0x8B69 -#define GL_FLOAT_MAT4x3 0x8B6A -#define GL_SRGB 0x8C40 -#define GL_SRGB8 0x8C41 -#define GL_SRGB_ALPHA 0x8C42 -#define GL_SRGB8_ALPHA8 0x8C43 -#define GL_COMPRESSED_SRGB 0x8C48 -#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 -#endif - -#ifndef GL_VERSION_2_1_DEPRECATED -#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F -#define GL_SLUMINANCE_ALPHA 0x8C44 -#define GL_SLUMINANCE8_ALPHA8 0x8C45 -#define GL_SLUMINANCE 0x8C46 -#define GL_SLUMINANCE8 0x8C47 -#define GL_COMPRESSED_SLUMINANCE 0x8C4A -#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B -#endif - -#ifndef GL_VERSION_3_0 -#define GL_COMPARE_REF_TO_TEXTURE 0x884E -#define GL_CLIP_DISTANCE0 0x3000 -#define GL_CLIP_DISTANCE1 0x3001 -#define GL_CLIP_DISTANCE2 0x3002 -#define GL_CLIP_DISTANCE3 0x3003 -#define GL_CLIP_DISTANCE4 0x3004 -#define GL_CLIP_DISTANCE5 0x3005 -#define GL_CLIP_DISTANCE6 0x3006 -#define GL_CLIP_DISTANCE7 0x3007 -#define GL_MAX_CLIP_DISTANCES 0x0D32 -#define GL_MAJOR_VERSION 0x821B -#define GL_MINOR_VERSION 0x821C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_CONTEXT_FLAGS 0x821E -#define GL_DEPTH_BUFFER 0x8223 -#define GL_STENCIL_BUFFER 0x8224 -#define GL_COMPRESSED_RED 0x8225 -#define GL_COMPRESSED_RG 0x8226 -#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 -#define GL_RGBA32F 0x8814 -#define GL_RGB32F 0x8815 -#define GL_RGBA16F 0x881A -#define GL_RGB16F 0x881B -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD -#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF -#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 -#define GL_CLAMP_READ_COLOR 0x891C -#define GL_FIXED_ONLY 0x891D -#define GL_MAX_VARYING_COMPONENTS 0x8B4B -#define GL_TEXTURE_1D_ARRAY 0x8C18 -#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 -#define GL_TEXTURE_2D_ARRAY 0x8C1A -#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B -#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C -#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D -#define GL_R11F_G11F_B10F 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B -#define GL_RGB9_E5 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E -#define GL_TEXTURE_SHARED_SIZE 0x8C3F -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 -#define GL_PRIMITIVES_GENERATED 0x8C87 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 -#define GL_RASTERIZER_DISCARD 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B -#define GL_INTERLEAVED_ATTRIBS 0x8C8C -#define GL_SEPARATE_ATTRIBS 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F -#define GL_RGBA32UI 0x8D70 -#define GL_RGB32UI 0x8D71 -#define GL_RGBA16UI 0x8D76 -#define GL_RGB16UI 0x8D77 -#define GL_RGBA8UI 0x8D7C -#define GL_RGB8UI 0x8D7D -#define GL_RGBA32I 0x8D82 -#define GL_RGB32I 0x8D83 -#define GL_RGBA16I 0x8D88 -#define GL_RGB16I 0x8D89 -#define GL_RGBA8I 0x8D8E -#define GL_RGB8I 0x8D8F -#define GL_RED_INTEGER 0x8D94 -#define GL_GREEN_INTEGER 0x8D95 -#define GL_BLUE_INTEGER 0x8D96 -#define GL_RGB_INTEGER 0x8D98 -#define GL_RGBA_INTEGER 0x8D99 -#define GL_BGR_INTEGER 0x8D9A -#define GL_BGRA_INTEGER 0x8D9B -#define GL_SAMPLER_1D_ARRAY 0x8DC0 -#define GL_SAMPLER_2D_ARRAY 0x8DC1 -#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 -#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 -#define GL_UNSIGNED_INT_VEC2 0x8DC6 -#define GL_UNSIGNED_INT_VEC3 0x8DC7 -#define GL_UNSIGNED_INT_VEC4 0x8DC8 -#define GL_INT_SAMPLER_1D 0x8DC9 -#define GL_INT_SAMPLER_2D 0x8DCA -#define GL_INT_SAMPLER_3D 0x8DCB -#define GL_INT_SAMPLER_CUBE 0x8DCC -#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE -#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF -#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 -#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 -#define GL_QUERY_WAIT 0x8E13 -#define GL_QUERY_NO_WAIT 0x8E14 -#define GL_QUERY_BY_REGION_WAIT 0x8E15 -#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 -#define GL_BUFFER_ACCESS_FLAGS 0x911F -#define GL_BUFFER_MAP_LENGTH 0x9120 -#define GL_BUFFER_MAP_OFFSET 0x9121 -/* Reuse tokens from ARB_depth_buffer_float */ -/* reuse GL_DEPTH_COMPONENT32F */ -/* reuse GL_DEPTH32F_STENCIL8 */ -/* reuse GL_FLOAT_32_UNSIGNED_INT_24_8_REV */ -/* Reuse tokens from ARB_framebuffer_object */ -/* reuse GL_INVALID_FRAMEBUFFER_OPERATION */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */ -/* reuse GL_FRAMEBUFFER_DEFAULT */ -/* reuse GL_FRAMEBUFFER_UNDEFINED */ -/* reuse GL_DEPTH_STENCIL_ATTACHMENT */ -/* reuse GL_INDEX */ -/* reuse GL_MAX_RENDERBUFFER_SIZE */ -/* reuse GL_DEPTH_STENCIL */ -/* reuse GL_UNSIGNED_INT_24_8 */ -/* reuse GL_DEPTH24_STENCIL8 */ -/* reuse GL_TEXTURE_STENCIL_SIZE */ -/* reuse GL_TEXTURE_RED_TYPE */ -/* reuse GL_TEXTURE_GREEN_TYPE */ -/* reuse GL_TEXTURE_BLUE_TYPE */ -/* reuse GL_TEXTURE_ALPHA_TYPE */ -/* reuse GL_TEXTURE_DEPTH_TYPE */ -/* reuse GL_UNSIGNED_NORMALIZED */ -/* reuse GL_FRAMEBUFFER_BINDING */ -/* reuse GL_DRAW_FRAMEBUFFER_BINDING */ -/* reuse GL_RENDERBUFFER_BINDING */ -/* reuse GL_READ_FRAMEBUFFER */ -/* reuse GL_DRAW_FRAMEBUFFER */ -/* reuse GL_READ_FRAMEBUFFER_BINDING */ -/* reuse GL_RENDERBUFFER_SAMPLES */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */ -/* reuse GL_FRAMEBUFFER_COMPLETE */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER */ -/* reuse GL_FRAMEBUFFER_UNSUPPORTED */ -/* reuse GL_MAX_COLOR_ATTACHMENTS */ -/* reuse GL_COLOR_ATTACHMENT0 */ -/* reuse GL_COLOR_ATTACHMENT1 */ -/* reuse GL_COLOR_ATTACHMENT2 */ -/* reuse GL_COLOR_ATTACHMENT3 */ -/* reuse GL_COLOR_ATTACHMENT4 */ -/* reuse GL_COLOR_ATTACHMENT5 */ -/* reuse GL_COLOR_ATTACHMENT6 */ -/* reuse GL_COLOR_ATTACHMENT7 */ -/* reuse GL_COLOR_ATTACHMENT8 */ -/* reuse GL_COLOR_ATTACHMENT9 */ -/* reuse GL_COLOR_ATTACHMENT10 */ -/* reuse GL_COLOR_ATTACHMENT11 */ -/* reuse GL_COLOR_ATTACHMENT12 */ -/* reuse GL_COLOR_ATTACHMENT13 */ -/* reuse GL_COLOR_ATTACHMENT14 */ -/* reuse GL_COLOR_ATTACHMENT15 */ -/* reuse GL_DEPTH_ATTACHMENT */ -/* reuse GL_STENCIL_ATTACHMENT */ -/* reuse GL_FRAMEBUFFER */ -/* reuse GL_RENDERBUFFER */ -/* reuse GL_RENDERBUFFER_WIDTH */ -/* reuse GL_RENDERBUFFER_HEIGHT */ -/* reuse GL_RENDERBUFFER_INTERNAL_FORMAT */ -/* reuse GL_STENCIL_INDEX1 */ -/* reuse GL_STENCIL_INDEX4 */ -/* reuse GL_STENCIL_INDEX8 */ -/* reuse GL_STENCIL_INDEX16 */ -/* reuse GL_RENDERBUFFER_RED_SIZE */ -/* reuse GL_RENDERBUFFER_GREEN_SIZE */ -/* reuse GL_RENDERBUFFER_BLUE_SIZE */ -/* reuse GL_RENDERBUFFER_ALPHA_SIZE */ -/* reuse GL_RENDERBUFFER_DEPTH_SIZE */ -/* reuse GL_RENDERBUFFER_STENCIL_SIZE */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */ -/* reuse GL_MAX_SAMPLES */ -/* Reuse tokens from ARB_framebuffer_sRGB */ -/* reuse GL_FRAMEBUFFER_SRGB */ -/* Reuse tokens from ARB_half_float_vertex */ -/* reuse GL_HALF_FLOAT */ -/* Reuse tokens from ARB_map_buffer_range */ -/* reuse GL_MAP_READ_BIT */ -/* reuse GL_MAP_WRITE_BIT */ -/* reuse GL_MAP_INVALIDATE_RANGE_BIT */ -/* reuse GL_MAP_INVALIDATE_BUFFER_BIT */ -/* reuse GL_MAP_FLUSH_EXPLICIT_BIT */ -/* reuse GL_MAP_UNSYNCHRONIZED_BIT */ -/* Reuse tokens from ARB_texture_compression_rgtc */ -/* reuse GL_COMPRESSED_RED_RGTC1 */ -/* reuse GL_COMPRESSED_SIGNED_RED_RGTC1 */ -/* reuse GL_COMPRESSED_RG_RGTC2 */ -/* reuse GL_COMPRESSED_SIGNED_RG_RGTC2 */ -/* Reuse tokens from ARB_texture_rg */ -/* reuse GL_RG */ -/* reuse GL_RG_INTEGER */ -/* reuse GL_R8 */ -/* reuse GL_R16 */ -/* reuse GL_RG8 */ -/* reuse GL_RG16 */ -/* reuse GL_R16F */ -/* reuse GL_R32F */ -/* reuse GL_RG16F */ -/* reuse GL_RG32F */ -/* reuse GL_R8I */ -/* reuse GL_R8UI */ -/* reuse GL_R16I */ -/* reuse GL_R16UI */ -/* reuse GL_R32I */ -/* reuse GL_R32UI */ -/* reuse GL_RG8I */ -/* reuse GL_RG8UI */ -/* reuse GL_RG16I */ -/* reuse GL_RG16UI */ -/* reuse GL_RG32I */ -/* reuse GL_RG32UI */ -/* Reuse tokens from ARB_vertex_array_object */ -/* reuse GL_VERTEX_ARRAY_BINDING */ -#endif - -#ifndef GL_VERSION_3_0_DEPRECATED -#define GL_CLAMP_VERTEX_COLOR 0x891A -#define GL_CLAMP_FRAGMENT_COLOR 0x891B -#define GL_ALPHA_INTEGER 0x8D97 -/* Reuse tokens from ARB_framebuffer_object */ -/* reuse GL_TEXTURE_LUMINANCE_TYPE */ -/* reuse GL_TEXTURE_INTENSITY_TYPE */ -#endif - -#ifndef GL_VERSION_3_1 -#define GL_SAMPLER_2D_RECT 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 -#define GL_SAMPLER_BUFFER 0x8DC2 -#define GL_INT_SAMPLER_2D_RECT 0x8DCD -#define GL_INT_SAMPLER_BUFFER 0x8DD0 -#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 -#define GL_TEXTURE_BUFFER 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D -#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E -#define GL_TEXTURE_RECTANGLE 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 -#define GL_RED_SNORM 0x8F90 -#define GL_RG_SNORM 0x8F91 -#define GL_RGB_SNORM 0x8F92 -#define GL_RGBA_SNORM 0x8F93 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGB8_SNORM 0x8F96 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_R16_SNORM 0x8F98 -#define GL_RG16_SNORM 0x8F99 -#define GL_RGB16_SNORM 0x8F9A -#define GL_RGBA16_SNORM 0x8F9B -#define GL_SIGNED_NORMALIZED 0x8F9C -#define GL_PRIMITIVE_RESTART 0x8F9D -#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E -/* Reuse tokens from ARB_copy_buffer */ -/* reuse GL_COPY_READ_BUFFER */ -/* reuse GL_COPY_WRITE_BUFFER */ -/* Reuse tokens from ARB_draw_instanced (none) */ -/* Reuse tokens from ARB_uniform_buffer_object */ -/* reuse GL_UNIFORM_BUFFER */ -/* reuse GL_UNIFORM_BUFFER_BINDING */ -/* reuse GL_UNIFORM_BUFFER_START */ -/* reuse GL_UNIFORM_BUFFER_SIZE */ -/* reuse GL_MAX_VERTEX_UNIFORM_BLOCKS */ -/* reuse GL_MAX_FRAGMENT_UNIFORM_BLOCKS */ -/* reuse GL_MAX_COMBINED_UNIFORM_BLOCKS */ -/* reuse GL_MAX_UNIFORM_BUFFER_BINDINGS */ -/* reuse GL_MAX_UNIFORM_BLOCK_SIZE */ -/* reuse GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS */ -/* reuse GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS */ -/* reuse GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT */ -/* reuse GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */ -/* reuse GL_ACTIVE_UNIFORM_BLOCKS */ -/* reuse GL_UNIFORM_TYPE */ -/* reuse GL_UNIFORM_SIZE */ -/* reuse GL_UNIFORM_NAME_LENGTH */ -/* reuse GL_UNIFORM_BLOCK_INDEX */ -/* reuse GL_UNIFORM_OFFSET */ -/* reuse GL_UNIFORM_ARRAY_STRIDE */ -/* reuse GL_UNIFORM_MATRIX_STRIDE */ -/* reuse GL_UNIFORM_IS_ROW_MAJOR */ -/* reuse GL_UNIFORM_BLOCK_BINDING */ -/* reuse GL_UNIFORM_BLOCK_DATA_SIZE */ -/* reuse GL_UNIFORM_BLOCK_NAME_LENGTH */ -/* reuse GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS */ -/* reuse GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES */ -/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER */ -/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER */ -/* reuse GL_INVALID_INDEX */ -#endif - -#ifndef GL_VERSION_3_2 -#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 -#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 -#define GL_LINES_ADJACENCY 0x000A -#define GL_LINE_STRIP_ADJACENCY 0x000B -#define GL_TRIANGLES_ADJACENCY 0x000C -#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D -#define GL_PROGRAM_POINT_SIZE 0x8642 -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 -#define GL_GEOMETRY_SHADER 0x8DD9 -#define GL_GEOMETRY_VERTICES_OUT 0x8916 -#define GL_GEOMETRY_INPUT_TYPE 0x8917 -#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 -#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 -#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 -#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 -#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 -#define GL_CONTEXT_PROFILE_MASK 0x9126 -/* reuse GL_MAX_VARYING_COMPONENTS */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */ -/* Reuse tokens from ARB_depth_clamp */ -/* reuse GL_DEPTH_CLAMP */ -/* Reuse tokens from ARB_draw_elements_base_vertex (none) */ -/* Reuse tokens from ARB_fragment_coord_conventions (none) */ -/* Reuse tokens from ARB_provoking_vertex */ -/* reuse GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION */ -/* reuse GL_FIRST_VERTEX_CONVENTION */ -/* reuse GL_LAST_VERTEX_CONVENTION */ -/* reuse GL_PROVOKING_VERTEX */ -/* Reuse tokens from ARB_seamless_cube_map */ -/* reuse GL_TEXTURE_CUBE_MAP_SEAMLESS */ -/* Reuse tokens from ARB_sync */ -/* reuse GL_MAX_SERVER_WAIT_TIMEOUT */ -/* reuse GL_OBJECT_TYPE */ -/* reuse GL_SYNC_CONDITION */ -/* reuse GL_SYNC_STATUS */ -/* reuse GL_SYNC_FLAGS */ -/* reuse GL_SYNC_FENCE */ -/* reuse GL_SYNC_GPU_COMMANDS_COMPLETE */ -/* reuse GL_UNSIGNALED */ -/* reuse GL_SIGNALED */ -/* reuse GL_ALREADY_SIGNALED */ -/* reuse GL_TIMEOUT_EXPIRED */ -/* reuse GL_CONDITION_SATISFIED */ -/* reuse GL_WAIT_FAILED */ -/* reuse GL_TIMEOUT_IGNORED */ -/* reuse GL_SYNC_FLUSH_COMMANDS_BIT */ -/* reuse GL_TIMEOUT_IGNORED */ -/* Reuse tokens from ARB_texture_multisample */ -/* reuse GL_SAMPLE_POSITION */ -/* reuse GL_SAMPLE_MASK */ -/* reuse GL_SAMPLE_MASK_VALUE */ -/* reuse GL_MAX_SAMPLE_MASK_WORDS */ -/* reuse GL_TEXTURE_2D_MULTISAMPLE */ -/* reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE */ -/* reuse GL_TEXTURE_2D_MULTISAMPLE_ARRAY */ -/* reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY */ -/* reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE */ -/* reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY */ -/* reuse GL_TEXTURE_SAMPLES */ -/* reuse GL_TEXTURE_FIXED_SAMPLE_LOCATIONS */ -/* reuse GL_SAMPLER_2D_MULTISAMPLE */ -/* reuse GL_INT_SAMPLER_2D_MULTISAMPLE */ -/* reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE */ -/* reuse GL_SAMPLER_2D_MULTISAMPLE_ARRAY */ -/* reuse GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY */ -/* reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY */ -/* reuse GL_MAX_COLOR_TEXTURE_SAMPLES */ -/* reuse GL_MAX_DEPTH_TEXTURE_SAMPLES */ -/* reuse GL_MAX_INTEGER_SAMPLES */ -/* Don't need to reuse tokens from ARB_vertex_array_bgra since they're already in 1.2 core */ -#endif - -#ifndef GL_VERSION_3_3 -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE -/* Reuse tokens from ARB_blend_func_extended */ -/* reuse GL_SRC1_COLOR */ -/* reuse GL_ONE_MINUS_SRC1_COLOR */ -/* reuse GL_ONE_MINUS_SRC1_ALPHA */ -/* reuse GL_MAX_DUAL_SOURCE_DRAW_BUFFERS */ -/* Reuse tokens from ARB_explicit_attrib_location (none) */ -/* Reuse tokens from ARB_occlusion_query2 */ -/* reuse GL_ANY_SAMPLES_PASSED */ -/* Reuse tokens from ARB_sampler_objects */ -/* reuse GL_SAMPLER_BINDING */ -/* Reuse tokens from ARB_shader_bit_encoding (none) */ -/* Reuse tokens from ARB_texture_rgb10_a2ui */ -/* reuse GL_RGB10_A2UI */ -/* Reuse tokens from ARB_texture_swizzle */ -/* reuse GL_TEXTURE_SWIZZLE_R */ -/* reuse GL_TEXTURE_SWIZZLE_G */ -/* reuse GL_TEXTURE_SWIZZLE_B */ -/* reuse GL_TEXTURE_SWIZZLE_A */ -/* reuse GL_TEXTURE_SWIZZLE_RGBA */ -/* Reuse tokens from ARB_timer_query */ -/* reuse GL_TIME_ELAPSED */ -/* reuse GL_TIMESTAMP */ -/* Reuse tokens from ARB_vertex_type_2_10_10_10_rev */ -/* reuse GL_INT_2_10_10_10_REV */ -#endif - -#ifndef GL_VERSION_4_0 -#define GL_SAMPLE_SHADING 0x8C36 -#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 -#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E -#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F -#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B -#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F -/* Reuse tokens from ARB_texture_query_lod (none) */ -/* Reuse tokens from ARB_draw_buffers_blend (none) */ -/* Reuse tokens from ARB_draw_indirect */ -/* reuse GL_DRAW_INDIRECT_BUFFER */ -/* reuse GL_DRAW_INDIRECT_BUFFER_BINDING */ -/* Reuse tokens from ARB_gpu_shader5 */ -/* reuse GL_GEOMETRY_SHADER_INVOCATIONS */ -/* reuse GL_MAX_GEOMETRY_SHADER_INVOCATIONS */ -/* reuse GL_MIN_FRAGMENT_INTERPOLATION_OFFSET */ -/* reuse GL_MAX_FRAGMENT_INTERPOLATION_OFFSET */ -/* reuse GL_FRAGMENT_INTERPOLATION_OFFSET_BITS */ -/* reuse GL_MAX_VERTEX_STREAMS */ -/* Reuse tokens from ARB_gpu_shader_fp64 */ -/* reuse GL_DOUBLE_VEC2 */ -/* reuse GL_DOUBLE_VEC3 */ -/* reuse GL_DOUBLE_VEC4 */ -/* reuse GL_DOUBLE_MAT2 */ -/* reuse GL_DOUBLE_MAT3 */ -/* reuse GL_DOUBLE_MAT4 */ -/* reuse GL_DOUBLE_MAT2x3 */ -/* reuse GL_DOUBLE_MAT2x4 */ -/* reuse GL_DOUBLE_MAT3x2 */ -/* reuse GL_DOUBLE_MAT3x4 */ -/* reuse GL_DOUBLE_MAT4x2 */ -/* reuse GL_DOUBLE_MAT4x3 */ -/* Reuse tokens from ARB_shader_subroutine */ -/* reuse GL_ACTIVE_SUBROUTINES */ -/* reuse GL_ACTIVE_SUBROUTINE_UNIFORMS */ -/* reuse GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS */ -/* reuse GL_ACTIVE_SUBROUTINE_MAX_LENGTH */ -/* reuse GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH */ -/* reuse GL_MAX_SUBROUTINES */ -/* reuse GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS */ -/* reuse GL_NUM_COMPATIBLE_SUBROUTINES */ -/* reuse GL_COMPATIBLE_SUBROUTINES */ -/* Reuse tokens from ARB_tessellation_shader */ -/* reuse GL_PATCHES */ -/* reuse GL_PATCH_VERTICES */ -/* reuse GL_PATCH_DEFAULT_INNER_LEVEL */ -/* reuse GL_PATCH_DEFAULT_OUTER_LEVEL */ -/* reuse GL_TESS_CONTROL_OUTPUT_VERTICES */ -/* reuse GL_TESS_GEN_MODE */ -/* reuse GL_TESS_GEN_SPACING */ -/* reuse GL_TESS_GEN_VERTEX_ORDER */ -/* reuse GL_TESS_GEN_POINT_MODE */ -/* reuse GL_ISOLINES */ -/* reuse GL_FRACTIONAL_ODD */ -/* reuse GL_FRACTIONAL_EVEN */ -/* reuse GL_MAX_PATCH_VERTICES */ -/* reuse GL_MAX_TESS_GEN_LEVEL */ -/* reuse GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS */ -/* reuse GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS */ -/* reuse GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS */ -/* reuse GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS */ -/* reuse GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS */ -/* reuse GL_MAX_TESS_PATCH_COMPONENTS */ -/* reuse GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS */ -/* reuse GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS */ -/* reuse GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS */ -/* reuse GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS */ -/* reuse GL_MAX_TESS_CONTROL_INPUT_COMPONENTS */ -/* reuse GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS */ -/* reuse GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS */ -/* reuse GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS */ -/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER */ -/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER */ -/* reuse GL_TESS_EVALUATION_SHADER */ -/* reuse GL_TESS_CONTROL_SHADER */ -/* Reuse tokens from ARB_texture_buffer_object_rgb32 (none) */ -/* Reuse tokens from ARB_transform_feedback2 */ -/* reuse GL_TRANSFORM_FEEDBACK */ -/* reuse GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED */ -/* reuse GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE */ -/* reuse GL_TRANSFORM_FEEDBACK_BINDING */ -/* Reuse tokens from ARB_transform_feedback3 */ -/* reuse GL_MAX_TRANSFORM_FEEDBACK_BUFFERS */ -/* reuse GL_MAX_VERTEX_STREAMS */ -#endif - -#ifndef GL_VERSION_4_1 -/* Reuse tokens from ARB_ES2_compatibility */ -/* reuse GL_FIXED */ -/* reuse GL_IMPLEMENTATION_COLOR_READ_TYPE */ -/* reuse GL_IMPLEMENTATION_COLOR_READ_FORMAT */ -/* reuse GL_LOW_FLOAT */ -/* reuse GL_MEDIUM_FLOAT */ -/* reuse GL_HIGH_FLOAT */ -/* reuse GL_LOW_INT */ -/* reuse GL_MEDIUM_INT */ -/* reuse GL_HIGH_INT */ -/* reuse GL_SHADER_COMPILER */ -/* reuse GL_NUM_SHADER_BINARY_FORMATS */ -/* reuse GL_MAX_VERTEX_UNIFORM_VECTORS */ -/* reuse GL_MAX_VARYING_VECTORS */ -/* reuse GL_MAX_FRAGMENT_UNIFORM_VECTORS */ -/* Reuse tokens from ARB_get_program_binary */ -/* reuse GL_PROGRAM_BINARY_RETRIEVABLE_HINT */ -/* reuse GL_PROGRAM_BINARY_LENGTH */ -/* reuse GL_NUM_PROGRAM_BINARY_FORMATS */ -/* reuse GL_PROGRAM_BINARY_FORMATS */ -/* Reuse tokens from ARB_separate_shader_objects */ -/* reuse GL_VERTEX_SHADER_BIT */ -/* reuse GL_FRAGMENT_SHADER_BIT */ -/* reuse GL_GEOMETRY_SHADER_BIT */ -/* reuse GL_TESS_CONTROL_SHADER_BIT */ -/* reuse GL_TESS_EVALUATION_SHADER_BIT */ -/* reuse GL_ALL_SHADER_BITS */ -/* reuse GL_PROGRAM_SEPARABLE */ -/* reuse GL_ACTIVE_PROGRAM */ -/* reuse GL_PROGRAM_PIPELINE_BINDING */ -/* Reuse tokens from ARB_shader_precision (none) */ -/* Reuse tokens from ARB_vertex_attrib_64bit - all are in GL 3.0 and 4.0 already */ -/* Reuse tokens from ARB_viewport_array - some are in GL 1.1 and ARB_provoking_vertex already */ -/* reuse GL_MAX_VIEWPORTS */ -/* reuse GL_VIEWPORT_SUBPIXEL_BITS */ -/* reuse GL_VIEWPORT_BOUNDS_RANGE */ -/* reuse GL_LAYER_PROVOKING_VERTEX */ -/* reuse GL_VIEWPORT_INDEX_PROVOKING_VERTEX */ -/* reuse GL_UNDEFINED_VERTEX */ -#endif - -#ifndef GL_ARB_multitexture -#define GL_TEXTURE0_ARB 0x84C0 -#define GL_TEXTURE1_ARB 0x84C1 -#define GL_TEXTURE2_ARB 0x84C2 -#define GL_TEXTURE3_ARB 0x84C3 -#define GL_TEXTURE4_ARB 0x84C4 -#define GL_TEXTURE5_ARB 0x84C5 -#define GL_TEXTURE6_ARB 0x84C6 -#define GL_TEXTURE7_ARB 0x84C7 -#define GL_TEXTURE8_ARB 0x84C8 -#define GL_TEXTURE9_ARB 0x84C9 -#define GL_TEXTURE10_ARB 0x84CA -#define GL_TEXTURE11_ARB 0x84CB -#define GL_TEXTURE12_ARB 0x84CC -#define GL_TEXTURE13_ARB 0x84CD -#define GL_TEXTURE14_ARB 0x84CE -#define GL_TEXTURE15_ARB 0x84CF -#define GL_TEXTURE16_ARB 0x84D0 -#define GL_TEXTURE17_ARB 0x84D1 -#define GL_TEXTURE18_ARB 0x84D2 -#define GL_TEXTURE19_ARB 0x84D3 -#define GL_TEXTURE20_ARB 0x84D4 -#define GL_TEXTURE21_ARB 0x84D5 -#define GL_TEXTURE22_ARB 0x84D6 -#define GL_TEXTURE23_ARB 0x84D7 -#define GL_TEXTURE24_ARB 0x84D8 -#define GL_TEXTURE25_ARB 0x84D9 -#define GL_TEXTURE26_ARB 0x84DA -#define GL_TEXTURE27_ARB 0x84DB -#define GL_TEXTURE28_ARB 0x84DC -#define GL_TEXTURE29_ARB 0x84DD -#define GL_TEXTURE30_ARB 0x84DE -#define GL_TEXTURE31_ARB 0x84DF -#define GL_ACTIVE_TEXTURE_ARB 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 -#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 -#endif - -#ifndef GL_ARB_transpose_matrix -#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 -#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 -#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 -#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 -#endif - -#ifndef GL_ARB_multisample -#define GL_MULTISAMPLE_ARB 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F -#define GL_SAMPLE_COVERAGE_ARB 0x80A0 -#define GL_SAMPLE_BUFFERS_ARB 0x80A8 -#define GL_SAMPLES_ARB 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB -#define GL_MULTISAMPLE_BIT_ARB 0x20000000 -#endif - -#ifndef GL_ARB_texture_env_add -#endif - -#ifndef GL_ARB_texture_cube_map -#define GL_NORMAL_MAP_ARB 0x8511 -#define GL_REFLECTION_MAP_ARB 0x8512 -#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C -#endif - -#ifndef GL_ARB_texture_compression -#define GL_COMPRESSED_ALPHA_ARB 0x84E9 -#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB -#define GL_COMPRESSED_INTENSITY_ARB 0x84EC -#define GL_COMPRESSED_RGB_ARB 0x84ED -#define GL_COMPRESSED_RGBA_ARB 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF -#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 -#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 -#endif - -#ifndef GL_ARB_texture_border_clamp -#define GL_CLAMP_TO_BORDER_ARB 0x812D -#endif - -#ifndef GL_ARB_point_parameters -#define GL_POINT_SIZE_MIN_ARB 0x8126 -#define GL_POINT_SIZE_MAX_ARB 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 -#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 -#endif - -#ifndef GL_ARB_vertex_blend -#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 -#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 -#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 -#define GL_VERTEX_BLEND_ARB 0x86A7 -#define GL_CURRENT_WEIGHT_ARB 0x86A8 -#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 -#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA -#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB -#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC -#define GL_WEIGHT_ARRAY_ARB 0x86AD -#define GL_MODELVIEW0_ARB 0x1700 -#define GL_MODELVIEW1_ARB 0x850A -#define GL_MODELVIEW2_ARB 0x8722 -#define GL_MODELVIEW3_ARB 0x8723 -#define GL_MODELVIEW4_ARB 0x8724 -#define GL_MODELVIEW5_ARB 0x8725 -#define GL_MODELVIEW6_ARB 0x8726 -#define GL_MODELVIEW7_ARB 0x8727 -#define GL_MODELVIEW8_ARB 0x8728 -#define GL_MODELVIEW9_ARB 0x8729 -#define GL_MODELVIEW10_ARB 0x872A -#define GL_MODELVIEW11_ARB 0x872B -#define GL_MODELVIEW12_ARB 0x872C -#define GL_MODELVIEW13_ARB 0x872D -#define GL_MODELVIEW14_ARB 0x872E -#define GL_MODELVIEW15_ARB 0x872F -#define GL_MODELVIEW16_ARB 0x8730 -#define GL_MODELVIEW17_ARB 0x8731 -#define GL_MODELVIEW18_ARB 0x8732 -#define GL_MODELVIEW19_ARB 0x8733 -#define GL_MODELVIEW20_ARB 0x8734 -#define GL_MODELVIEW21_ARB 0x8735 -#define GL_MODELVIEW22_ARB 0x8736 -#define GL_MODELVIEW23_ARB 0x8737 -#define GL_MODELVIEW24_ARB 0x8738 -#define GL_MODELVIEW25_ARB 0x8739 -#define GL_MODELVIEW26_ARB 0x873A -#define GL_MODELVIEW27_ARB 0x873B -#define GL_MODELVIEW28_ARB 0x873C -#define GL_MODELVIEW29_ARB 0x873D -#define GL_MODELVIEW30_ARB 0x873E -#define GL_MODELVIEW31_ARB 0x873F -#endif - -#ifndef GL_ARB_matrix_palette -#define GL_MATRIX_PALETTE_ARB 0x8840 -#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 -#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 -#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 -#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 -#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 -#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 -#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 -#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 -#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 -#endif - -#ifndef GL_ARB_texture_env_combine -#define GL_COMBINE_ARB 0x8570 -#define GL_COMBINE_RGB_ARB 0x8571 -#define GL_COMBINE_ALPHA_ARB 0x8572 -#define GL_SOURCE0_RGB_ARB 0x8580 -#define GL_SOURCE1_RGB_ARB 0x8581 -#define GL_SOURCE2_RGB_ARB 0x8582 -#define GL_SOURCE0_ALPHA_ARB 0x8588 -#define GL_SOURCE1_ALPHA_ARB 0x8589 -#define GL_SOURCE2_ALPHA_ARB 0x858A -#define GL_OPERAND0_RGB_ARB 0x8590 -#define GL_OPERAND1_RGB_ARB 0x8591 -#define GL_OPERAND2_RGB_ARB 0x8592 -#define GL_OPERAND0_ALPHA_ARB 0x8598 -#define GL_OPERAND1_ALPHA_ARB 0x8599 -#define GL_OPERAND2_ALPHA_ARB 0x859A -#define GL_RGB_SCALE_ARB 0x8573 -#define GL_ADD_SIGNED_ARB 0x8574 -#define GL_INTERPOLATE_ARB 0x8575 -#define GL_SUBTRACT_ARB 0x84E7 -#define GL_CONSTANT_ARB 0x8576 -#define GL_PRIMARY_COLOR_ARB 0x8577 -#define GL_PREVIOUS_ARB 0x8578 -#endif - -#ifndef GL_ARB_texture_env_crossbar -#endif - -#ifndef GL_ARB_texture_env_dot3 -#define GL_DOT3_RGB_ARB 0x86AE -#define GL_DOT3_RGBA_ARB 0x86AF -#endif - -#ifndef GL_ARB_texture_mirrored_repeat -#define GL_MIRRORED_REPEAT_ARB 0x8370 -#endif - -#ifndef GL_ARB_depth_texture -#define GL_DEPTH_COMPONENT16_ARB 0x81A5 -#define GL_DEPTH_COMPONENT24_ARB 0x81A6 -#define GL_DEPTH_COMPONENT32_ARB 0x81A7 -#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A -#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B -#endif - -#ifndef GL_ARB_shadow -#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C -#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D -#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E -#endif - -#ifndef GL_ARB_shadow_ambient -#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF -#endif - -#ifndef GL_ARB_window_pos -#endif - -#ifndef GL_ARB_vertex_program -#define GL_COLOR_SUM_ARB 0x8458 -#define GL_VERTEX_PROGRAM_ARB 0x8620 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 -#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 -#define GL_PROGRAM_LENGTH_ARB 0x8627 -#define GL_PROGRAM_STRING_ARB 0x8628 -#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E -#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F -#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 -#define GL_CURRENT_MATRIX_ARB 0x8641 -#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 -#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B -#define GL_PROGRAM_BINDING_ARB 0x8677 -#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A -#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 -#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 -#define GL_PROGRAM_FORMAT_ARB 0x8876 -#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 -#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 -#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 -#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 -#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 -#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 -#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 -#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 -#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 -#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 -#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA -#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB -#define GL_PROGRAM_ATTRIBS_ARB 0x88AC -#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD -#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE -#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF -#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 -#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 -#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 -#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 -#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 -#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 -#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 -#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 -#define GL_MATRIX0_ARB 0x88C0 -#define GL_MATRIX1_ARB 0x88C1 -#define GL_MATRIX2_ARB 0x88C2 -#define GL_MATRIX3_ARB 0x88C3 -#define GL_MATRIX4_ARB 0x88C4 -#define GL_MATRIX5_ARB 0x88C5 -#define GL_MATRIX6_ARB 0x88C6 -#define GL_MATRIX7_ARB 0x88C7 -#define GL_MATRIX8_ARB 0x88C8 -#define GL_MATRIX9_ARB 0x88C9 -#define GL_MATRIX10_ARB 0x88CA -#define GL_MATRIX11_ARB 0x88CB -#define GL_MATRIX12_ARB 0x88CC -#define GL_MATRIX13_ARB 0x88CD -#define GL_MATRIX14_ARB 0x88CE -#define GL_MATRIX15_ARB 0x88CF -#define GL_MATRIX16_ARB 0x88D0 -#define GL_MATRIX17_ARB 0x88D1 -#define GL_MATRIX18_ARB 0x88D2 -#define GL_MATRIX19_ARB 0x88D3 -#define GL_MATRIX20_ARB 0x88D4 -#define GL_MATRIX21_ARB 0x88D5 -#define GL_MATRIX22_ARB 0x88D6 -#define GL_MATRIX23_ARB 0x88D7 -#define GL_MATRIX24_ARB 0x88D8 -#define GL_MATRIX25_ARB 0x88D9 -#define GL_MATRIX26_ARB 0x88DA -#define GL_MATRIX27_ARB 0x88DB -#define GL_MATRIX28_ARB 0x88DC -#define GL_MATRIX29_ARB 0x88DD -#define GL_MATRIX30_ARB 0x88DE -#define GL_MATRIX31_ARB 0x88DF -#endif - -#ifndef GL_ARB_fragment_program -#define GL_FRAGMENT_PROGRAM_ARB 0x8804 -#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 -#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 -#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 -#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 -#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 -#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A -#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B -#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C -#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D -#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E -#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F -#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 -#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 -#endif - -#ifndef GL_ARB_vertex_buffer_object -#define GL_BUFFER_SIZE_ARB 0x8764 -#define GL_BUFFER_USAGE_ARB 0x8765 -#define GL_ARRAY_BUFFER_ARB 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 -#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 -#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 -#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A -#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B -#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C -#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D -#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F -#define GL_READ_ONLY_ARB 0x88B8 -#define GL_WRITE_ONLY_ARB 0x88B9 -#define GL_READ_WRITE_ARB 0x88BA -#define GL_BUFFER_ACCESS_ARB 0x88BB -#define GL_BUFFER_MAPPED_ARB 0x88BC -#define GL_BUFFER_MAP_POINTER_ARB 0x88BD -#define GL_STREAM_DRAW_ARB 0x88E0 -#define GL_STREAM_READ_ARB 0x88E1 -#define GL_STREAM_COPY_ARB 0x88E2 -#define GL_STATIC_DRAW_ARB 0x88E4 -#define GL_STATIC_READ_ARB 0x88E5 -#define GL_STATIC_COPY_ARB 0x88E6 -#define GL_DYNAMIC_DRAW_ARB 0x88E8 -#define GL_DYNAMIC_READ_ARB 0x88E9 -#define GL_DYNAMIC_COPY_ARB 0x88EA -#endif - -#ifndef GL_ARB_occlusion_query -#define GL_QUERY_COUNTER_BITS_ARB 0x8864 -#define GL_CURRENT_QUERY_ARB 0x8865 -#define GL_QUERY_RESULT_ARB 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 -#define GL_SAMPLES_PASSED_ARB 0x8914 -#endif - -#ifndef GL_ARB_shader_objects -#define GL_PROGRAM_OBJECT_ARB 0x8B40 -#define GL_SHADER_OBJECT_ARB 0x8B48 -#define GL_OBJECT_TYPE_ARB 0x8B4E -#define GL_OBJECT_SUBTYPE_ARB 0x8B4F -#define GL_FLOAT_VEC2_ARB 0x8B50 -#define GL_FLOAT_VEC3_ARB 0x8B51 -#define GL_FLOAT_VEC4_ARB 0x8B52 -#define GL_INT_VEC2_ARB 0x8B53 -#define GL_INT_VEC3_ARB 0x8B54 -#define GL_INT_VEC4_ARB 0x8B55 -#define GL_BOOL_ARB 0x8B56 -#define GL_BOOL_VEC2_ARB 0x8B57 -#define GL_BOOL_VEC3_ARB 0x8B58 -#define GL_BOOL_VEC4_ARB 0x8B59 -#define GL_FLOAT_MAT2_ARB 0x8B5A -#define GL_FLOAT_MAT3_ARB 0x8B5B -#define GL_FLOAT_MAT4_ARB 0x8B5C -#define GL_SAMPLER_1D_ARB 0x8B5D -#define GL_SAMPLER_2D_ARB 0x8B5E -#define GL_SAMPLER_3D_ARB 0x8B5F -#define GL_SAMPLER_CUBE_ARB 0x8B60 -#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 -#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 -#define GL_SAMPLER_2D_RECT_ARB 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 -#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 -#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 -#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 -#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 -#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 -#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 -#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 -#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 -#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 -#endif - -#ifndef GL_ARB_vertex_shader -#define GL_VERTEX_SHADER_ARB 0x8B31 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A -#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D -#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 -#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A -#endif - -#ifndef GL_ARB_fragment_shader -#define GL_FRAGMENT_SHADER_ARB 0x8B30 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B -#endif - -#ifndef GL_ARB_shading_language_100 -#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C -#endif - -#ifndef GL_ARB_texture_non_power_of_two -#endif - -#ifndef GL_ARB_point_sprite -#define GL_POINT_SPRITE_ARB 0x8861 -#define GL_COORD_REPLACE_ARB 0x8862 -#endif - -#ifndef GL_ARB_fragment_program_shadow -#endif - -#ifndef GL_ARB_draw_buffers -#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 -#define GL_DRAW_BUFFER0_ARB 0x8825 -#define GL_DRAW_BUFFER1_ARB 0x8826 -#define GL_DRAW_BUFFER2_ARB 0x8827 -#define GL_DRAW_BUFFER3_ARB 0x8828 -#define GL_DRAW_BUFFER4_ARB 0x8829 -#define GL_DRAW_BUFFER5_ARB 0x882A -#define GL_DRAW_BUFFER6_ARB 0x882B -#define GL_DRAW_BUFFER7_ARB 0x882C -#define GL_DRAW_BUFFER8_ARB 0x882D -#define GL_DRAW_BUFFER9_ARB 0x882E -#define GL_DRAW_BUFFER10_ARB 0x882F -#define GL_DRAW_BUFFER11_ARB 0x8830 -#define GL_DRAW_BUFFER12_ARB 0x8831 -#define GL_DRAW_BUFFER13_ARB 0x8832 -#define GL_DRAW_BUFFER14_ARB 0x8833 -#define GL_DRAW_BUFFER15_ARB 0x8834 -#endif - -#ifndef GL_ARB_texture_rectangle -#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 -#endif - -#ifndef GL_ARB_color_buffer_float -#define GL_RGBA_FLOAT_MODE_ARB 0x8820 -#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A -#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B -#define GL_CLAMP_READ_COLOR_ARB 0x891C -#define GL_FIXED_ONLY_ARB 0x891D -#endif - -#ifndef GL_ARB_half_float_pixel -#define GL_HALF_FLOAT_ARB 0x140B -#endif - -#ifndef GL_ARB_texture_float -#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 -#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 -#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 -#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 -#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 -#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 -#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 -#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 -#define GL_RGBA32F_ARB 0x8814 -#define GL_RGB32F_ARB 0x8815 -#define GL_ALPHA32F_ARB 0x8816 -#define GL_INTENSITY32F_ARB 0x8817 -#define GL_LUMINANCE32F_ARB 0x8818 -#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 -#define GL_RGBA16F_ARB 0x881A -#define GL_RGB16F_ARB 0x881B -#define GL_ALPHA16F_ARB 0x881C -#define GL_INTENSITY16F_ARB 0x881D -#define GL_LUMINANCE16F_ARB 0x881E -#define GL_LUMINANCE_ALPHA16F_ARB 0x881F -#endif - -#ifndef GL_ARB_pixel_buffer_object -#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB -#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF -#endif - -#ifndef GL_ARB_depth_buffer_float -#define GL_DEPTH_COMPONENT32F 0x8CAC -#define GL_DEPTH32F_STENCIL8 0x8CAD -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD -#endif - -#ifndef GL_ARB_draw_instanced -#endif - -#ifndef GL_ARB_framebuffer_object -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 -#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 -#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 -#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 -#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 -#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 -#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 -#define GL_FRAMEBUFFER_DEFAULT 0x8218 -#define GL_FRAMEBUFFER_UNDEFINED 0x8219 -#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 -#define GL_DEPTH_STENCIL 0x84F9 -#define GL_UNSIGNED_INT_24_8 0x84FA -#define GL_DEPTH24_STENCIL8 0x88F0 -#define GL_TEXTURE_STENCIL_SIZE 0x88F1 -#define GL_TEXTURE_RED_TYPE 0x8C10 -#define GL_TEXTURE_GREEN_TYPE 0x8C11 -#define GL_TEXTURE_BLUE_TYPE 0x8C12 -#define GL_TEXTURE_ALPHA_TYPE 0x8C13 -#define GL_TEXTURE_DEPTH_TYPE 0x8C16 -#define GL_UNSIGNED_NORMALIZED 0x8C17 -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA -#define GL_RENDERBUFFER_SAMPLES 0x8CAB -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_COLOR_ATTACHMENT1 0x8CE1 -#define GL_COLOR_ATTACHMENT2 0x8CE2 -#define GL_COLOR_ATTACHMENT3 0x8CE3 -#define GL_COLOR_ATTACHMENT4 0x8CE4 -#define GL_COLOR_ATTACHMENT5 0x8CE5 -#define GL_COLOR_ATTACHMENT6 0x8CE6 -#define GL_COLOR_ATTACHMENT7 0x8CE7 -#define GL_COLOR_ATTACHMENT8 0x8CE8 -#define GL_COLOR_ATTACHMENT9 0x8CE9 -#define GL_COLOR_ATTACHMENT10 0x8CEA -#define GL_COLOR_ATTACHMENT11 0x8CEB -#define GL_COLOR_ATTACHMENT12 0x8CEC -#define GL_COLOR_ATTACHMENT13 0x8CED -#define GL_COLOR_ATTACHMENT14 0x8CEE -#define GL_COLOR_ATTACHMENT15 0x8CEF -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_STENCIL_INDEX1 0x8D46 -#define GL_STENCIL_INDEX4 0x8D47 -#define GL_STENCIL_INDEX8 0x8D48 -#define GL_STENCIL_INDEX16 0x8D49 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#define GL_MAX_SAMPLES 0x8D57 -#endif - -#ifndef GL_ARB_framebuffer_object_DEPRECATED -#define GL_INDEX 0x8222 -#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 -#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 -#endif - -#ifndef GL_ARB_framebuffer_sRGB -#define GL_FRAMEBUFFER_SRGB 0x8DB9 -#endif - -#ifndef GL_ARB_geometry_shader4 -#define GL_LINES_ADJACENCY_ARB 0x000A -#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B -#define GL_TRIANGLES_ADJACENCY_ARB 0x000C -#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D -#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 -#define GL_GEOMETRY_SHADER_ARB 0x8DD9 -#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA -#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB -#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC -#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD -#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 -/* reuse GL_MAX_VARYING_COMPONENTS */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */ -#endif - -#ifndef GL_ARB_half_float_vertex -#define GL_HALF_FLOAT 0x140B -#endif - -#ifndef GL_ARB_instanced_arrays -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE -#endif - -#ifndef GL_ARB_map_buffer_range -#define GL_MAP_READ_BIT 0x0001 -#define GL_MAP_WRITE_BIT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 -#endif - -#ifndef GL_ARB_texture_buffer_object -#define GL_TEXTURE_BUFFER_ARB 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D -#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E -#endif - -#ifndef GL_ARB_texture_compression_rgtc -#define GL_COMPRESSED_RED_RGTC1 0x8DBB -#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#define GL_COMPRESSED_RG_RGTC2 0x8DBD -#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#endif - -#ifndef GL_ARB_texture_rg -#define GL_RG 0x8227 -#define GL_RG_INTEGER 0x8228 -#define GL_R8 0x8229 -#define GL_R16 0x822A -#define GL_RG8 0x822B -#define GL_RG16 0x822C -#define GL_R16F 0x822D -#define GL_R32F 0x822E -#define GL_RG16F 0x822F -#define GL_RG32F 0x8230 -#define GL_R8I 0x8231 -#define GL_R8UI 0x8232 -#define GL_R16I 0x8233 -#define GL_R16UI 0x8234 -#define GL_R32I 0x8235 -#define GL_R32UI 0x8236 -#define GL_RG8I 0x8237 -#define GL_RG8UI 0x8238 -#define GL_RG16I 0x8239 -#define GL_RG16UI 0x823A -#define GL_RG32I 0x823B -#define GL_RG32UI 0x823C -#endif - -#ifndef GL_ARB_vertex_array_object -#define GL_VERTEX_ARRAY_BINDING 0x85B5 -#endif - -#ifndef GL_ARB_uniform_buffer_object -#define GL_UNIFORM_BUFFER 0x8A11 -#define GL_UNIFORM_BUFFER_BINDING 0x8A28 -#define GL_UNIFORM_BUFFER_START 0x8A29 -#define GL_UNIFORM_BUFFER_SIZE 0x8A2A -#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B -#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C -#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D -#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E -#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F -#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 -#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 -#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 -#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 -#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 -#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 -#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 -#define GL_UNIFORM_TYPE 0x8A37 -#define GL_UNIFORM_SIZE 0x8A38 -#define GL_UNIFORM_NAME_LENGTH 0x8A39 -#define GL_UNIFORM_BLOCK_INDEX 0x8A3A -#define GL_UNIFORM_OFFSET 0x8A3B -#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C -#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D -#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E -#define GL_UNIFORM_BLOCK_BINDING 0x8A3F -#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 -#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 -#define GL_INVALID_INDEX 0xFFFFFFFFu -#endif - -#ifndef GL_ARB_compatibility -/* ARB_compatibility just defines tokens from core 3.0 */ -#endif - -#ifndef GL_ARB_copy_buffer -#define GL_COPY_READ_BUFFER 0x8F36 -#define GL_COPY_WRITE_BUFFER 0x8F37 -#endif - -#ifndef GL_ARB_shader_texture_lod -#endif - -#ifndef GL_ARB_depth_clamp -#define GL_DEPTH_CLAMP 0x864F -#endif - -#ifndef GL_ARB_draw_elements_base_vertex -#endif - -#ifndef GL_ARB_fragment_coord_conventions -#endif - -#ifndef GL_ARB_provoking_vertex -#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C -#define GL_FIRST_VERTEX_CONVENTION 0x8E4D -#define GL_LAST_VERTEX_CONVENTION 0x8E4E -#define GL_PROVOKING_VERTEX 0x8E4F -#endif - -#ifndef GL_ARB_seamless_cube_map -#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F -#endif - -#ifndef GL_ARB_sync -#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 -#define GL_OBJECT_TYPE 0x9112 -#define GL_SYNC_CONDITION 0x9113 -#define GL_SYNC_STATUS 0x9114 -#define GL_SYNC_FLAGS 0x9115 -#define GL_SYNC_FENCE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 -#define GL_UNSIGNALED 0x9118 -#define GL_SIGNALED 0x9119 -#define GL_ALREADY_SIGNALED 0x911A -#define GL_TIMEOUT_EXPIRED 0x911B -#define GL_CONDITION_SATISFIED 0x911C -#define GL_WAIT_FAILED 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 -#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull -#endif - -#ifndef GL_ARB_texture_multisample -#define GL_SAMPLE_POSITION 0x8E50 -#define GL_SAMPLE_MASK 0x8E51 -#define GL_SAMPLE_MASK_VALUE 0x8E52 -#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 -#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 -#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 -#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 -#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 -#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 -#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 -#define GL_TEXTURE_SAMPLES 0x9106 -#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 -#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 -#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A -#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B -#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D -#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E -#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F -#define GL_MAX_INTEGER_SAMPLES 0x9110 -#endif - -#ifndef GL_ARB_vertex_array_bgra -/* reuse GL_BGRA */ -#endif - -#ifndef GL_ARB_draw_buffers_blend -#endif - -#ifndef GL_ARB_sample_shading -#define GL_SAMPLE_SHADING_ARB 0x8C36 -#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 -#endif - -#ifndef GL_ARB_texture_cube_map_array -#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B -#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F -#endif - -#ifndef GL_ARB_texture_gather -#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E -#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F -#endif - -#ifndef GL_ARB_texture_query_lod -#endif - -#ifndef GL_ARB_shading_language_include -#define GL_SHADER_INCLUDE_ARB 0x8DAE -#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 -#define GL_NAMED_STRING_TYPE_ARB 0x8DEA -#endif - -#ifndef GL_ARB_texture_compression_bptc -#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C -#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D -#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E -#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F -#endif - -#ifndef GL_ARB_blend_func_extended -#define GL_SRC1_COLOR 0x88F9 -/* reuse GL_SRC1_ALPHA */ -#define GL_ONE_MINUS_SRC1_COLOR 0x88FA -#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB -#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC -#endif - -#ifndef GL_ARB_explicit_attrib_location -#endif - -#ifndef GL_ARB_occlusion_query2 -#define GL_ANY_SAMPLES_PASSED 0x8C2F -#endif - -#ifndef GL_ARB_sampler_objects -#define GL_SAMPLER_BINDING 0x8919 -#endif - -#ifndef GL_ARB_shader_bit_encoding -#endif - -#ifndef GL_ARB_texture_rgb10_a2ui -#define GL_RGB10_A2UI 0x906F -#endif - -#ifndef GL_ARB_texture_swizzle -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 -#endif - -#ifndef GL_ARB_timer_query -#define GL_TIME_ELAPSED 0x88BF -#define GL_TIMESTAMP 0x8E28 -#endif - -#ifndef GL_ARB_vertex_type_2_10_10_10_rev -/* reuse GL_UNSIGNED_INT_2_10_10_10_REV */ -#define GL_INT_2_10_10_10_REV 0x8D9F -#endif - -#ifndef GL_ARB_draw_indirect -#define GL_DRAW_INDIRECT_BUFFER 0x8F3F -#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 -#endif - -#ifndef GL_ARB_gpu_shader5 -#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F -#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C -#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D -/* reuse GL_MAX_VERTEX_STREAMS */ -#endif - -#ifndef GL_ARB_gpu_shader_fp64 -/* reuse GL_DOUBLE */ -#define GL_DOUBLE_VEC2 0x8FFC -#define GL_DOUBLE_VEC3 0x8FFD -#define GL_DOUBLE_VEC4 0x8FFE -#define GL_DOUBLE_MAT2 0x8F46 -#define GL_DOUBLE_MAT3 0x8F47 -#define GL_DOUBLE_MAT4 0x8F48 -#define GL_DOUBLE_MAT2x3 0x8F49 -#define GL_DOUBLE_MAT2x4 0x8F4A -#define GL_DOUBLE_MAT3x2 0x8F4B -#define GL_DOUBLE_MAT3x4 0x8F4C -#define GL_DOUBLE_MAT4x2 0x8F4D -#define GL_DOUBLE_MAT4x3 0x8F4E -#endif - -#ifndef GL_ARB_shader_subroutine -#define GL_ACTIVE_SUBROUTINES 0x8DE5 -#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 -#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 -#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 -#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 -#define GL_MAX_SUBROUTINES 0x8DE7 -#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 -#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A -#define GL_COMPATIBLE_SUBROUTINES 0x8E4B -/* reuse GL_UNIFORM_SIZE */ -/* reuse GL_UNIFORM_NAME_LENGTH */ -#endif - -#ifndef GL_ARB_tessellation_shader -#define GL_PATCHES 0x000E -#define GL_PATCH_VERTICES 0x8E72 -#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 -#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 -#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 -#define GL_TESS_GEN_MODE 0x8E76 -#define GL_TESS_GEN_SPACING 0x8E77 -#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 -#define GL_TESS_GEN_POINT_MODE 0x8E79 -/* reuse GL_TRIANGLES */ -/* reuse GL_QUADS */ -#define GL_ISOLINES 0x8E7A -/* reuse GL_EQUAL */ -#define GL_FRACTIONAL_ODD 0x8E7B -#define GL_FRACTIONAL_EVEN 0x8E7C -/* reuse GL_CCW */ -/* reuse GL_CW */ -#define GL_MAX_PATCH_VERTICES 0x8E7D -#define GL_MAX_TESS_GEN_LEVEL 0x8E7E -#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F -#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 -#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 -#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 -#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 -#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 -#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 -#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 -#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 -#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A -#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C -#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D -#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E -#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F -#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 -#define GL_TESS_EVALUATION_SHADER 0x8E87 -#define GL_TESS_CONTROL_SHADER 0x8E88 -#endif - -#ifndef GL_ARB_texture_buffer_object_rgb32 -/* reuse GL_RGB32F */ -/* reuse GL_RGB32UI */ -/* reuse GL_RGB32I */ -#endif - -#ifndef GL_ARB_transform_feedback2 -#define GL_TRANSFORM_FEEDBACK 0x8E22 -#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 -#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 -#endif - -#ifndef GL_ARB_transform_feedback3 -#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 -#define GL_MAX_VERTEX_STREAMS 0x8E71 -#endif - -#ifndef GL_ARB_ES2_compatibility -#define GL_FIXED 0x140C -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 -#define GL_SHADER_COMPILER 0x8DFA -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD -#endif - -#ifndef GL_ARB_get_program_binary -#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 -#define GL_PROGRAM_BINARY_LENGTH 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE -#define GL_PROGRAM_BINARY_FORMATS 0x87FF -#endif - -#ifndef GL_ARB_separate_shader_objects -#define GL_VERTEX_SHADER_BIT 0x00000001 -#define GL_FRAGMENT_SHADER_BIT 0x00000002 -#define GL_GEOMETRY_SHADER_BIT 0x00000004 -#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 -#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 -#define GL_ALL_SHADER_BITS 0xFFFFFFFF -#define GL_PROGRAM_SEPARABLE 0x8258 -#define GL_ACTIVE_PROGRAM 0x8259 -#define GL_PROGRAM_PIPELINE_BINDING 0x825A -#endif - -#ifndef GL_ARB_shader_precision -#endif - -#ifndef GL_ARB_vertex_attrib_64bit -/* reuse GL_RGB32I */ -/* reuse GL_DOUBLE_VEC2 */ -/* reuse GL_DOUBLE_VEC3 */ -/* reuse GL_DOUBLE_VEC4 */ -/* reuse GL_DOUBLE_MAT2 */ -/* reuse GL_DOUBLE_MAT3 */ -/* reuse GL_DOUBLE_MAT4 */ -/* reuse GL_DOUBLE_MAT2x3 */ -/* reuse GL_DOUBLE_MAT2x4 */ -/* reuse GL_DOUBLE_MAT3x2 */ -/* reuse GL_DOUBLE_MAT3x4 */ -/* reuse GL_DOUBLE_MAT4x2 */ -/* reuse GL_DOUBLE_MAT4x3 */ -#endif - -#ifndef GL_ARB_viewport_array -/* reuse GL_SCISSOR_BOX */ -/* reuse GL_VIEWPORT */ -/* reuse GL_DEPTH_RANGE */ -/* reuse GL_SCISSOR_TEST */ -#define GL_MAX_VIEWPORTS 0x825B -#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C -#define GL_VIEWPORT_BOUNDS_RANGE 0x825D -#define GL_LAYER_PROVOKING_VERTEX 0x825E -#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F -#define GL_UNDEFINED_VERTEX 0x8260 -/* reuse GL_FIRST_VERTEX_CONVENTION */ -/* reuse GL_LAST_VERTEX_CONVENTION */ -/* reuse GL_PROVOKING_VERTEX */ -#endif - -#ifndef GL_ARB_cl_event -#define GL_SYNC_CL_EVENT_ARB 0x8240 -#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 -#endif - -#ifndef GL_ARB_debug_output -#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 -#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 -#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 -#define GL_DEBUG_SOURCE_API_ARB 0x8246 -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 -#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 -#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 -#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A -#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B -#define GL_DEBUG_TYPE_ERROR_ARB 0x824C -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E -#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F -#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 -#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 -#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 -#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 -#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 -#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 -#endif - -#ifndef GL_ARB_robustness -/* reuse GL_NO_ERROR */ -#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 -#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 -#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 -#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 -#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 -#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 -#endif - -#ifndef GL_ARB_shader_stencil_export -#endif - -#ifndef GL_EXT_abgr -#define GL_ABGR_EXT 0x8000 -#endif - -#ifndef GL_EXT_blend_color -#define GL_CONSTANT_COLOR_EXT 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 -#define GL_CONSTANT_ALPHA_EXT 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 -#define GL_BLEND_COLOR_EXT 0x8005 -#endif - -#ifndef GL_EXT_polygon_offset -#define GL_POLYGON_OFFSET_EXT 0x8037 -#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 -#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 -#endif - -#ifndef GL_EXT_texture -#define GL_ALPHA4_EXT 0x803B -#define GL_ALPHA8_EXT 0x803C -#define GL_ALPHA12_EXT 0x803D -#define GL_ALPHA16_EXT 0x803E -#define GL_LUMINANCE4_EXT 0x803F -#define GL_LUMINANCE8_EXT 0x8040 -#define GL_LUMINANCE12_EXT 0x8041 -#define GL_LUMINANCE16_EXT 0x8042 -#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 -#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 -#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 -#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 -#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 -#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 -#define GL_INTENSITY_EXT 0x8049 -#define GL_INTENSITY4_EXT 0x804A -#define GL_INTENSITY8_EXT 0x804B -#define GL_INTENSITY12_EXT 0x804C -#define GL_INTENSITY16_EXT 0x804D -#define GL_RGB2_EXT 0x804E -#define GL_RGB4_EXT 0x804F -#define GL_RGB5_EXT 0x8050 -#define GL_RGB8_EXT 0x8051 -#define GL_RGB10_EXT 0x8052 -#define GL_RGB12_EXT 0x8053 -#define GL_RGB16_EXT 0x8054 -#define GL_RGBA2_EXT 0x8055 -#define GL_RGBA4_EXT 0x8056 -#define GL_RGB5_A1_EXT 0x8057 -#define GL_RGBA8_EXT 0x8058 -#define GL_RGB10_A2_EXT 0x8059 -#define GL_RGBA12_EXT 0x805A -#define GL_RGBA16_EXT 0x805B -#define GL_TEXTURE_RED_SIZE_EXT 0x805C -#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D -#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E -#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F -#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 -#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 -#define GL_REPLACE_EXT 0x8062 -#define GL_PROXY_TEXTURE_1D_EXT 0x8063 -#define GL_PROXY_TEXTURE_2D_EXT 0x8064 -#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 -#endif - -#ifndef GL_EXT_texture3D -#define GL_PACK_SKIP_IMAGES_EXT 0x806B -#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C -#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D -#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E -#define GL_TEXTURE_3D_EXT 0x806F -#define GL_PROXY_TEXTURE_3D_EXT 0x8070 -#define GL_TEXTURE_DEPTH_EXT 0x8071 -#define GL_TEXTURE_WRAP_R_EXT 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 -#endif - -#ifndef GL_SGIS_texture_filter4 -#define GL_FILTER4_SGIS 0x8146 -#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 -#endif - -#ifndef GL_EXT_subtexture -#endif - -#ifndef GL_EXT_copy_texture -#endif - -#ifndef GL_EXT_histogram -#define GL_HISTOGRAM_EXT 0x8024 -#define GL_PROXY_HISTOGRAM_EXT 0x8025 -#define GL_HISTOGRAM_WIDTH_EXT 0x8026 -#define GL_HISTOGRAM_FORMAT_EXT 0x8027 -#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 -#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 -#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A -#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B -#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C -#define GL_HISTOGRAM_SINK_EXT 0x802D -#define GL_MINMAX_EXT 0x802E -#define GL_MINMAX_FORMAT_EXT 0x802F -#define GL_MINMAX_SINK_EXT 0x8030 -#define GL_TABLE_TOO_LARGE_EXT 0x8031 -#endif - -#ifndef GL_EXT_convolution -#define GL_CONVOLUTION_1D_EXT 0x8010 -#define GL_CONVOLUTION_2D_EXT 0x8011 -#define GL_SEPARABLE_2D_EXT 0x8012 -#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 -#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 -#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 -#define GL_REDUCE_EXT 0x8016 -#define GL_CONVOLUTION_FORMAT_EXT 0x8017 -#define GL_CONVOLUTION_WIDTH_EXT 0x8018 -#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 -#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A -#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B -#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C -#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D -#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E -#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F -#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 -#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 -#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 -#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 -#endif - -#ifndef GL_SGI_color_matrix -#define GL_COLOR_MATRIX_SGI 0x80B1 -#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 -#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 -#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 -#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 -#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 -#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 -#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 -#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 -#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA -#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB -#endif - -#ifndef GL_SGI_color_table -#define GL_COLOR_TABLE_SGI 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 -#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 -#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 -#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 -#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 -#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 -#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA -#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB -#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC -#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD -#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE -#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF -#endif - -#ifndef GL_SGIS_pixel_texture -#define GL_PIXEL_TEXTURE_SGIS 0x8353 -#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 -#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 -#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 -#endif - -#ifndef GL_SGIX_pixel_texture -#define GL_PIXEL_TEX_GEN_SGIX 0x8139 -#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B -#endif - -#ifndef GL_SGIS_texture4D -#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 -#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 -#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 -#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 -#define GL_TEXTURE_4D_SGIS 0x8134 -#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 -#define GL_TEXTURE_4DSIZE_SGIS 0x8136 -#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 -#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 -#define GL_TEXTURE_4D_BINDING_SGIS 0x814F -#endif - -#ifndef GL_SGI_texture_color_table -#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC -#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD -#endif - -#ifndef GL_EXT_cmyka -#define GL_CMYK_EXT 0x800C -#define GL_CMYKA_EXT 0x800D -#define GL_PACK_CMYK_HINT_EXT 0x800E -#define GL_UNPACK_CMYK_HINT_EXT 0x800F -#endif - -#ifndef GL_EXT_texture_object -#define GL_TEXTURE_PRIORITY_EXT 0x8066 -#define GL_TEXTURE_RESIDENT_EXT 0x8067 -#define GL_TEXTURE_1D_BINDING_EXT 0x8068 -#define GL_TEXTURE_2D_BINDING_EXT 0x8069 -#define GL_TEXTURE_3D_BINDING_EXT 0x806A -#endif - -#ifndef GL_SGIS_detail_texture -#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 -#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 -#define GL_LINEAR_DETAIL_SGIS 0x8097 -#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 -#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 -#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A -#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B -#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C -#endif - -#ifndef GL_SGIS_sharpen_texture -#define GL_LINEAR_SHARPEN_SGIS 0x80AD -#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE -#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF -#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 -#endif - -#ifndef GL_EXT_packed_pixels -#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 -#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 -#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 -#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 -#endif - -#ifndef GL_SGIS_texture_lod -#define GL_TEXTURE_MIN_LOD_SGIS 0x813A -#define GL_TEXTURE_MAX_LOD_SGIS 0x813B -#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C -#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D -#endif - -#ifndef GL_SGIS_multisample -#define GL_MULTISAMPLE_SGIS 0x809D -#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F -#define GL_SAMPLE_MASK_SGIS 0x80A0 -#define GL_1PASS_SGIS 0x80A1 -#define GL_2PASS_0_SGIS 0x80A2 -#define GL_2PASS_1_SGIS 0x80A3 -#define GL_4PASS_0_SGIS 0x80A4 -#define GL_4PASS_1_SGIS 0x80A5 -#define GL_4PASS_2_SGIS 0x80A6 -#define GL_4PASS_3_SGIS 0x80A7 -#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 -#define GL_SAMPLES_SGIS 0x80A9 -#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA -#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB -#define GL_SAMPLE_PATTERN_SGIS 0x80AC -#endif - -#ifndef GL_EXT_rescale_normal -#define GL_RESCALE_NORMAL_EXT 0x803A -#endif - -#ifndef GL_EXT_vertex_array -#define GL_VERTEX_ARRAY_EXT 0x8074 -#define GL_NORMAL_ARRAY_EXT 0x8075 -#define GL_COLOR_ARRAY_EXT 0x8076 -#define GL_INDEX_ARRAY_EXT 0x8077 -#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 -#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 -#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A -#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B -#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C -#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D -#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E -#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F -#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 -#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 -#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 -#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 -#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 -#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 -#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 -#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 -#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 -#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 -#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A -#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B -#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C -#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D -#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E -#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F -#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 -#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 -#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 -#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 -#endif - -#ifndef GL_EXT_misc_attribute -#endif - -#ifndef GL_SGIS_generate_mipmap -#define GL_GENERATE_MIPMAP_SGIS 0x8191 -#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 -#endif - -#ifndef GL_SGIX_clipmap -#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 -#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 -#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 -#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 -#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 -#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 -#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 -#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 -#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 -#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D -#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E -#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F -#endif - -#ifndef GL_SGIX_shadow -#define GL_TEXTURE_COMPARE_SGIX 0x819A -#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B -#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C -#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D -#endif - -#ifndef GL_SGIS_texture_edge_clamp -#define GL_CLAMP_TO_EDGE_SGIS 0x812F -#endif - -#ifndef GL_SGIS_texture_border_clamp -#define GL_CLAMP_TO_BORDER_SGIS 0x812D -#endif - -#ifndef GL_EXT_blend_minmax -#define GL_FUNC_ADD_EXT 0x8006 -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#define GL_BLEND_EQUATION_EXT 0x8009 -#endif - -#ifndef GL_EXT_blend_subtract -#define GL_FUNC_SUBTRACT_EXT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B -#endif - -#ifndef GL_EXT_blend_logic_op -#endif - -#ifndef GL_SGIX_interlace -#define GL_INTERLACE_SGIX 0x8094 -#endif - -#ifndef GL_SGIX_pixel_tiles -#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E -#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F -#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 -#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 -#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 -#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 -#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 -#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 -#endif - -#ifndef GL_SGIS_texture_select -#define GL_DUAL_ALPHA4_SGIS 0x8110 -#define GL_DUAL_ALPHA8_SGIS 0x8111 -#define GL_DUAL_ALPHA12_SGIS 0x8112 -#define GL_DUAL_ALPHA16_SGIS 0x8113 -#define GL_DUAL_LUMINANCE4_SGIS 0x8114 -#define GL_DUAL_LUMINANCE8_SGIS 0x8115 -#define GL_DUAL_LUMINANCE12_SGIS 0x8116 -#define GL_DUAL_LUMINANCE16_SGIS 0x8117 -#define GL_DUAL_INTENSITY4_SGIS 0x8118 -#define GL_DUAL_INTENSITY8_SGIS 0x8119 -#define GL_DUAL_INTENSITY12_SGIS 0x811A -#define GL_DUAL_INTENSITY16_SGIS 0x811B -#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C -#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D -#define GL_QUAD_ALPHA4_SGIS 0x811E -#define GL_QUAD_ALPHA8_SGIS 0x811F -#define GL_QUAD_LUMINANCE4_SGIS 0x8120 -#define GL_QUAD_LUMINANCE8_SGIS 0x8121 -#define GL_QUAD_INTENSITY4_SGIS 0x8122 -#define GL_QUAD_INTENSITY8_SGIS 0x8123 -#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 -#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 -#endif - -#ifndef GL_SGIX_sprite -#define GL_SPRITE_SGIX 0x8148 -#define GL_SPRITE_MODE_SGIX 0x8149 -#define GL_SPRITE_AXIS_SGIX 0x814A -#define GL_SPRITE_TRANSLATION_SGIX 0x814B -#define GL_SPRITE_AXIAL_SGIX 0x814C -#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D -#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E -#endif - -#ifndef GL_SGIX_texture_multi_buffer -#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E -#endif - -#ifndef GL_EXT_point_parameters -#define GL_POINT_SIZE_MIN_EXT 0x8126 -#define GL_POINT_SIZE_MAX_EXT 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 -#define GL_DISTANCE_ATTENUATION_EXT 0x8129 -#endif - -#ifndef GL_SGIS_point_parameters -#define GL_POINT_SIZE_MIN_SGIS 0x8126 -#define GL_POINT_SIZE_MAX_SGIS 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 -#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 -#endif - -#ifndef GL_SGIX_instruments -#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 -#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 -#endif - -#ifndef GL_SGIX_texture_scale_bias -#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 -#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A -#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B -#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C -#endif - -#ifndef GL_SGIX_framezoom -#define GL_FRAMEZOOM_SGIX 0x818B -#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C -#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D -#endif - -#ifndef GL_SGIX_tag_sample_buffer -#endif - -#ifndef GL_FfdMaskSGIX -#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 -#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 -#endif - -#ifndef GL_SGIX_polynomial_ffd -#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 -#define GL_TEXTURE_DEFORMATION_SGIX 0x8195 -#define GL_DEFORMATIONS_MASK_SGIX 0x8196 -#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 -#endif - -#ifndef GL_SGIX_reference_plane -#define GL_REFERENCE_PLANE_SGIX 0x817D -#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E -#endif - -#ifndef GL_SGIX_flush_raster -#endif - -#ifndef GL_SGIX_depth_texture -#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 -#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 -#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 -#endif - -#ifndef GL_SGIS_fog_function -#define GL_FOG_FUNC_SGIS 0x812A -#define GL_FOG_FUNC_POINTS_SGIS 0x812B -#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C -#endif - -#ifndef GL_SGIX_fog_offset -#define GL_FOG_OFFSET_SGIX 0x8198 -#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 -#endif - -#ifndef GL_HP_image_transform -#define GL_IMAGE_SCALE_X_HP 0x8155 -#define GL_IMAGE_SCALE_Y_HP 0x8156 -#define GL_IMAGE_TRANSLATE_X_HP 0x8157 -#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 -#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 -#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A -#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B -#define GL_IMAGE_MAG_FILTER_HP 0x815C -#define GL_IMAGE_MIN_FILTER_HP 0x815D -#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E -#define GL_CUBIC_HP 0x815F -#define GL_AVERAGE_HP 0x8160 -#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 -#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 -#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 -#endif - -#ifndef GL_HP_convolution_border_modes -#define GL_IGNORE_BORDER_HP 0x8150 -#define GL_CONSTANT_BORDER_HP 0x8151 -#define GL_REPLICATE_BORDER_HP 0x8153 -#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 -#endif - -#ifndef GL_INGR_palette_buffer -#endif - -#ifndef GL_SGIX_texture_add_env -#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE -#endif - -#ifndef GL_EXT_color_subtable -#endif - -#ifndef GL_PGI_vertex_hints -#define GL_VERTEX_DATA_HINT_PGI 0x1A22A -#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B -#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C -#define GL_MAX_VERTEX_HINT_PGI 0x1A22D -#define GL_COLOR3_BIT_PGI 0x00010000 -#define GL_COLOR4_BIT_PGI 0x00020000 -#define GL_EDGEFLAG_BIT_PGI 0x00040000 -#define GL_INDEX_BIT_PGI 0x00080000 -#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 -#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 -#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 -#define GL_MAT_EMISSION_BIT_PGI 0x00800000 -#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 -#define GL_MAT_SHININESS_BIT_PGI 0x02000000 -#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 -#define GL_NORMAL_BIT_PGI 0x08000000 -#define GL_TEXCOORD1_BIT_PGI 0x10000000 -#define GL_TEXCOORD2_BIT_PGI 0x20000000 -#define GL_TEXCOORD3_BIT_PGI 0x40000000 -#define GL_TEXCOORD4_BIT_PGI 0x80000000 -#define GL_VERTEX23_BIT_PGI 0x00000004 -#define GL_VERTEX4_BIT_PGI 0x00000008 -#endif - -#ifndef GL_PGI_misc_hints -#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 -#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD -#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE -#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 -#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 -#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 -#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C -#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D -#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E -#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F -#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 -#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 -#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 -#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 -#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 -#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 -#define GL_CLIP_NEAR_HINT_PGI 0x1A220 -#define GL_CLIP_FAR_HINT_PGI 0x1A221 -#define GL_WIDE_LINE_HINT_PGI 0x1A222 -#define GL_BACK_NORMALS_HINT_PGI 0x1A223 -#endif - -#ifndef GL_EXT_paletted_texture -#define GL_COLOR_INDEX1_EXT 0x80E2 -#define GL_COLOR_INDEX2_EXT 0x80E3 -#define GL_COLOR_INDEX4_EXT 0x80E4 -#define GL_COLOR_INDEX8_EXT 0x80E5 -#define GL_COLOR_INDEX12_EXT 0x80E6 -#define GL_COLOR_INDEX16_EXT 0x80E7 -#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED -#endif - -#ifndef GL_EXT_clip_volume_hint -#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 -#endif - -#ifndef GL_SGIX_list_priority -#define GL_LIST_PRIORITY_SGIX 0x8182 -#endif - -#ifndef GL_SGIX_ir_instrument1 -#define GL_IR_INSTRUMENT1_SGIX 0x817F -#endif - -#ifndef GL_SGIX_calligraphic_fragment -#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 -#endif - -#ifndef GL_SGIX_texture_lod_bias -#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E -#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F -#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 -#endif - -#ifndef GL_SGIX_shadow_ambient -#define GL_SHADOW_AMBIENT_SGIX 0x80BF -#endif - -#ifndef GL_EXT_index_texture -#endif - -#ifndef GL_EXT_index_material -#define GL_INDEX_MATERIAL_EXT 0x81B8 -#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 -#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA -#endif - -#ifndef GL_EXT_index_func -#define GL_INDEX_TEST_EXT 0x81B5 -#define GL_INDEX_TEST_FUNC_EXT 0x81B6 -#define GL_INDEX_TEST_REF_EXT 0x81B7 -#endif - -#ifndef GL_EXT_index_array_formats -#define GL_IUI_V2F_EXT 0x81AD -#define GL_IUI_V3F_EXT 0x81AE -#define GL_IUI_N3F_V2F_EXT 0x81AF -#define GL_IUI_N3F_V3F_EXT 0x81B0 -#define GL_T2F_IUI_V2F_EXT 0x81B1 -#define GL_T2F_IUI_V3F_EXT 0x81B2 -#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 -#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 -#endif - -#ifndef GL_EXT_compiled_vertex_array -#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 -#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 -#endif - -#ifndef GL_EXT_cull_vertex -#define GL_CULL_VERTEX_EXT 0x81AA -#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB -#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC -#endif - -#ifndef GL_SGIX_ycrcb -#define GL_YCRCB_422_SGIX 0x81BB -#define GL_YCRCB_444_SGIX 0x81BC -#endif - -#ifndef GL_SGIX_fragment_lighting -#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 -#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 -#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 -#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 -#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 -#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 -#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 -#define GL_LIGHT_ENV_MODE_SGIX 0x8407 -#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 -#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 -#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A -#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B -#define GL_FRAGMENT_LIGHT0_SGIX 0x840C -#define GL_FRAGMENT_LIGHT1_SGIX 0x840D -#define GL_FRAGMENT_LIGHT2_SGIX 0x840E -#define GL_FRAGMENT_LIGHT3_SGIX 0x840F -#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 -#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 -#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 -#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 -#endif - -#ifndef GL_IBM_rasterpos_clip -#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 -#endif - -#ifndef GL_HP_texture_lighting -#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 -#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 -#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 -#endif - -#ifndef GL_EXT_draw_range_elements -#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 -#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 -#endif - -#ifndef GL_WIN_phong_shading -#define GL_PHONG_WIN 0x80EA -#define GL_PHONG_HINT_WIN 0x80EB -#endif - -#ifndef GL_WIN_specular_fog -#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC -#endif - -#ifndef GL_EXT_light_texture -#define GL_FRAGMENT_MATERIAL_EXT 0x8349 -#define GL_FRAGMENT_NORMAL_EXT 0x834A -#define GL_FRAGMENT_COLOR_EXT 0x834C -#define GL_ATTENUATION_EXT 0x834D -#define GL_SHADOW_ATTENUATION_EXT 0x834E -#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F -#define GL_TEXTURE_LIGHT_EXT 0x8350 -#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 -#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 -/* reuse GL_FRAGMENT_DEPTH_EXT */ -#endif - -#ifndef GL_SGIX_blend_alpha_minmax -#define GL_ALPHA_MIN_SGIX 0x8320 -#define GL_ALPHA_MAX_SGIX 0x8321 -#endif - -#ifndef GL_SGIX_impact_pixel_texture -#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184 -#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185 -#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186 -#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187 -#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188 -#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189 -#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A -#endif - -#ifndef GL_EXT_bgra -#define GL_BGR_EXT 0x80E0 -#define GL_BGRA_EXT 0x80E1 -#endif - -#ifndef GL_SGIX_async -#define GL_ASYNC_MARKER_SGIX 0x8329 -#endif - -#ifndef GL_SGIX_async_pixel -#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C -#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D -#define GL_ASYNC_READ_PIXELS_SGIX 0x835E -#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F -#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 -#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 -#endif - -#ifndef GL_SGIX_async_histogram -#define GL_ASYNC_HISTOGRAM_SGIX 0x832C -#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D -#endif - -#ifndef GL_INTEL_texture_scissor -#endif - -#ifndef GL_INTEL_parallel_arrays -#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 -#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 -#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 -#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 -#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 -#endif - -#ifndef GL_HP_occlusion_test -#define GL_OCCLUSION_TEST_HP 0x8165 -#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 -#endif - -#ifndef GL_EXT_pixel_transform -#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 -#define GL_PIXEL_MAG_FILTER_EXT 0x8331 -#define GL_PIXEL_MIN_FILTER_EXT 0x8332 -#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 -#define GL_CUBIC_EXT 0x8334 -#define GL_AVERAGE_EXT 0x8335 -#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 -#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 -#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 -#endif - -#ifndef GL_EXT_pixel_transform_color_table -#endif - -#ifndef GL_EXT_shared_texture_palette -#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB -#endif - -#ifndef GL_EXT_separate_specular_color -#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 -#define GL_SINGLE_COLOR_EXT 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA -#endif - -#ifndef GL_EXT_secondary_color -#define GL_COLOR_SUM_EXT 0x8458 -#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 -#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A -#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B -#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C -#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D -#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E -#endif - -#ifndef GL_EXT_texture_perturb_normal -#define GL_PERTURB_EXT 0x85AE -#define GL_TEXTURE_NORMAL_EXT 0x85AF -#endif - -#ifndef GL_EXT_multi_draw_arrays -#endif - -#ifndef GL_EXT_fog_coord -#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 -#define GL_FOG_COORDINATE_EXT 0x8451 -#define GL_FRAGMENT_DEPTH_EXT 0x8452 -#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 -#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 -#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 -#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 -#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 -#endif - -#ifndef GL_REND_screen_coordinates -#define GL_SCREEN_COORDINATES_REND 0x8490 -#define GL_INVERTED_SCREEN_W_REND 0x8491 -#endif - -#ifndef GL_EXT_coordinate_frame -#define GL_TANGENT_ARRAY_EXT 0x8439 -#define GL_BINORMAL_ARRAY_EXT 0x843A -#define GL_CURRENT_TANGENT_EXT 0x843B -#define GL_CURRENT_BINORMAL_EXT 0x843C -#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E -#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F -#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 -#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 -#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 -#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 -#define GL_MAP1_TANGENT_EXT 0x8444 -#define GL_MAP2_TANGENT_EXT 0x8445 -#define GL_MAP1_BINORMAL_EXT 0x8446 -#define GL_MAP2_BINORMAL_EXT 0x8447 -#endif - -#ifndef GL_EXT_texture_env_combine -#define GL_COMBINE_EXT 0x8570 -#define GL_COMBINE_RGB_EXT 0x8571 -#define GL_COMBINE_ALPHA_EXT 0x8572 -#define GL_RGB_SCALE_EXT 0x8573 -#define GL_ADD_SIGNED_EXT 0x8574 -#define GL_INTERPOLATE_EXT 0x8575 -#define GL_CONSTANT_EXT 0x8576 -#define GL_PRIMARY_COLOR_EXT 0x8577 -#define GL_PREVIOUS_EXT 0x8578 -#define GL_SOURCE0_RGB_EXT 0x8580 -#define GL_SOURCE1_RGB_EXT 0x8581 -#define GL_SOURCE2_RGB_EXT 0x8582 -#define GL_SOURCE0_ALPHA_EXT 0x8588 -#define GL_SOURCE1_ALPHA_EXT 0x8589 -#define GL_SOURCE2_ALPHA_EXT 0x858A -#define GL_OPERAND0_RGB_EXT 0x8590 -#define GL_OPERAND1_RGB_EXT 0x8591 -#define GL_OPERAND2_RGB_EXT 0x8592 -#define GL_OPERAND0_ALPHA_EXT 0x8598 -#define GL_OPERAND1_ALPHA_EXT 0x8599 -#define GL_OPERAND2_ALPHA_EXT 0x859A -#endif - -#ifndef GL_APPLE_specular_vector -#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 -#endif - -#ifndef GL_APPLE_transform_hint -#define GL_TRANSFORM_HINT_APPLE 0x85B1 -#endif - -#ifndef GL_SGIX_fog_scale -#define GL_FOG_SCALE_SGIX 0x81FC -#define GL_FOG_SCALE_VALUE_SGIX 0x81FD -#endif - -#ifndef GL_SUNX_constant_data -#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 -#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 -#endif - -#ifndef GL_SUN_global_alpha -#define GL_GLOBAL_ALPHA_SUN 0x81D9 -#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA -#endif - -#ifndef GL_SUN_triangle_list -#define GL_RESTART_SUN 0x0001 -#define GL_REPLACE_MIDDLE_SUN 0x0002 -#define GL_REPLACE_OLDEST_SUN 0x0003 -#define GL_TRIANGLE_LIST_SUN 0x81D7 -#define GL_REPLACEMENT_CODE_SUN 0x81D8 -#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 -#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 -#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 -#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 -#define GL_R1UI_V3F_SUN 0x85C4 -#define GL_R1UI_C4UB_V3F_SUN 0x85C5 -#define GL_R1UI_C3F_V3F_SUN 0x85C6 -#define GL_R1UI_N3F_V3F_SUN 0x85C7 -#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 -#define GL_R1UI_T2F_V3F_SUN 0x85C9 -#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA -#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB -#endif - -#ifndef GL_SUN_vertex -#endif - -#ifndef GL_EXT_blend_func_separate -#define GL_BLEND_DST_RGB_EXT 0x80C8 -#define GL_BLEND_SRC_RGB_EXT 0x80C9 -#define GL_BLEND_DST_ALPHA_EXT 0x80CA -#define GL_BLEND_SRC_ALPHA_EXT 0x80CB -#endif - -#ifndef GL_INGR_color_clamp -#define GL_RED_MIN_CLAMP_INGR 0x8560 -#define GL_GREEN_MIN_CLAMP_INGR 0x8561 -#define GL_BLUE_MIN_CLAMP_INGR 0x8562 -#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 -#define GL_RED_MAX_CLAMP_INGR 0x8564 -#define GL_GREEN_MAX_CLAMP_INGR 0x8565 -#define GL_BLUE_MAX_CLAMP_INGR 0x8566 -#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 -#endif - -#ifndef GL_INGR_interlace_read -#define GL_INTERLACE_READ_INGR 0x8568 -#endif - -#ifndef GL_EXT_stencil_wrap -#define GL_INCR_WRAP_EXT 0x8507 -#define GL_DECR_WRAP_EXT 0x8508 -#endif - -#ifndef GL_EXT_422_pixels -#define GL_422_EXT 0x80CC -#define GL_422_REV_EXT 0x80CD -#define GL_422_AVERAGE_EXT 0x80CE -#define GL_422_REV_AVERAGE_EXT 0x80CF -#endif - -#ifndef GL_NV_texgen_reflection -#define GL_NORMAL_MAP_NV 0x8511 -#define GL_REFLECTION_MAP_NV 0x8512 -#endif - -#ifndef GL_EXT_texture_cube_map -#define GL_NORMAL_MAP_EXT 0x8511 -#define GL_REFLECTION_MAP_EXT 0x8512 -#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C -#endif - -#ifndef GL_SUN_convolution_border_modes -#define GL_WRAP_BORDER_SUN 0x81D4 -#endif - -#ifndef GL_EXT_texture_env_add -#endif - -#ifndef GL_EXT_texture_lod_bias -#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD -#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 -#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 -#endif - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -#endif - -#ifndef GL_EXT_vertex_weighting -#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH -#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 -#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX -#define GL_MODELVIEW1_MATRIX_EXT 0x8506 -#define GL_VERTEX_WEIGHTING_EXT 0x8509 -#define GL_MODELVIEW0_EXT GL_MODELVIEW -#define GL_MODELVIEW1_EXT 0x850A -#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B -#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C -#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D -#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E -#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F -#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 -#endif - -#ifndef GL_NV_light_max_exponent -#define GL_MAX_SHININESS_NV 0x8504 -#define GL_MAX_SPOT_EXPONENT_NV 0x8505 -#endif - -#ifndef GL_NV_vertex_array_range -#define GL_VERTEX_ARRAY_RANGE_NV 0x851D -#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E -#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F -#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 -#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 -#endif - -#ifndef GL_NV_register_combiners -#define GL_REGISTER_COMBINERS_NV 0x8522 -#define GL_VARIABLE_A_NV 0x8523 -#define GL_VARIABLE_B_NV 0x8524 -#define GL_VARIABLE_C_NV 0x8525 -#define GL_VARIABLE_D_NV 0x8526 -#define GL_VARIABLE_E_NV 0x8527 -#define GL_VARIABLE_F_NV 0x8528 -#define GL_VARIABLE_G_NV 0x8529 -#define GL_CONSTANT_COLOR0_NV 0x852A -#define GL_CONSTANT_COLOR1_NV 0x852B -#define GL_PRIMARY_COLOR_NV 0x852C -#define GL_SECONDARY_COLOR_NV 0x852D -#define GL_SPARE0_NV 0x852E -#define GL_SPARE1_NV 0x852F -#define GL_DISCARD_NV 0x8530 -#define GL_E_TIMES_F_NV 0x8531 -#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 -#define GL_UNSIGNED_IDENTITY_NV 0x8536 -#define GL_UNSIGNED_INVERT_NV 0x8537 -#define GL_EXPAND_NORMAL_NV 0x8538 -#define GL_EXPAND_NEGATE_NV 0x8539 -#define GL_HALF_BIAS_NORMAL_NV 0x853A -#define GL_HALF_BIAS_NEGATE_NV 0x853B -#define GL_SIGNED_IDENTITY_NV 0x853C -#define GL_SIGNED_NEGATE_NV 0x853D -#define GL_SCALE_BY_TWO_NV 0x853E -#define GL_SCALE_BY_FOUR_NV 0x853F -#define GL_SCALE_BY_ONE_HALF_NV 0x8540 -#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 -#define GL_COMBINER_INPUT_NV 0x8542 -#define GL_COMBINER_MAPPING_NV 0x8543 -#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 -#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 -#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 -#define GL_COMBINER_MUX_SUM_NV 0x8547 -#define GL_COMBINER_SCALE_NV 0x8548 -#define GL_COMBINER_BIAS_NV 0x8549 -#define GL_COMBINER_AB_OUTPUT_NV 0x854A -#define GL_COMBINER_CD_OUTPUT_NV 0x854B -#define GL_COMBINER_SUM_OUTPUT_NV 0x854C -#define GL_MAX_GENERAL_COMBINERS_NV 0x854D -#define GL_NUM_GENERAL_COMBINERS_NV 0x854E -#define GL_COLOR_SUM_CLAMP_NV 0x854F -#define GL_COMBINER0_NV 0x8550 -#define GL_COMBINER1_NV 0x8551 -#define GL_COMBINER2_NV 0x8552 -#define GL_COMBINER3_NV 0x8553 -#define GL_COMBINER4_NV 0x8554 -#define GL_COMBINER5_NV 0x8555 -#define GL_COMBINER6_NV 0x8556 -#define GL_COMBINER7_NV 0x8557 -/* reuse GL_TEXTURE0_ARB */ -/* reuse GL_TEXTURE1_ARB */ -/* reuse GL_ZERO */ -/* reuse GL_NONE */ -/* reuse GL_FOG */ -#endif - -#ifndef GL_NV_fog_distance -#define GL_FOG_DISTANCE_MODE_NV 0x855A -#define GL_EYE_RADIAL_NV 0x855B -#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C -/* reuse GL_EYE_PLANE */ -#endif - -#ifndef GL_NV_texgen_emboss -#define GL_EMBOSS_LIGHT_NV 0x855D -#define GL_EMBOSS_CONSTANT_NV 0x855E -#define GL_EMBOSS_MAP_NV 0x855F -#endif - -#ifndef GL_NV_blend_square -#endif - -#ifndef GL_NV_texture_env_combine4 -#define GL_COMBINE4_NV 0x8503 -#define GL_SOURCE3_RGB_NV 0x8583 -#define GL_SOURCE3_ALPHA_NV 0x858B -#define GL_OPERAND3_RGB_NV 0x8593 -#define GL_OPERAND3_ALPHA_NV 0x859B -#endif - -#ifndef GL_MESA_resize_buffers -#endif - -#ifndef GL_MESA_window_pos -#endif - -#ifndef GL_EXT_texture_compression_s3tc -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#endif - -#ifndef GL_IBM_cull_vertex -#define GL_CULL_VERTEX_IBM 103050 -#endif - -#ifndef GL_IBM_multimode_draw_arrays -#endif - -#ifndef GL_IBM_vertex_array_lists -#define GL_VERTEX_ARRAY_LIST_IBM 103070 -#define GL_NORMAL_ARRAY_LIST_IBM 103071 -#define GL_COLOR_ARRAY_LIST_IBM 103072 -#define GL_INDEX_ARRAY_LIST_IBM 103073 -#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 -#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 -#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 -#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 -#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 -#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 -#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 -#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 -#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 -#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 -#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 -#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 -#endif - -#ifndef GL_SGIX_subsample -#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 -#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 -#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 -#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 -#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 -#endif - -#ifndef GL_SGIX_ycrcb_subsample -#endif - -#ifndef GL_SGIX_ycrcba -#define GL_YCRCB_SGIX 0x8318 -#define GL_YCRCBA_SGIX 0x8319 -#endif - -#ifndef GL_SGI_depth_pass_instrument -#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 -#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 -#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 -#endif - -#ifndef GL_3DFX_texture_compression_FXT1 -#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 -#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 -#endif - -#ifndef GL_3DFX_multisample -#define GL_MULTISAMPLE_3DFX 0x86B2 -#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 -#define GL_SAMPLES_3DFX 0x86B4 -#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 -#endif - -#ifndef GL_3DFX_tbuffer -#endif - -#ifndef GL_EXT_multisample -#define GL_MULTISAMPLE_EXT 0x809D -#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F -#define GL_SAMPLE_MASK_EXT 0x80A0 -#define GL_1PASS_EXT 0x80A1 -#define GL_2PASS_0_EXT 0x80A2 -#define GL_2PASS_1_EXT 0x80A3 -#define GL_4PASS_0_EXT 0x80A4 -#define GL_4PASS_1_EXT 0x80A5 -#define GL_4PASS_2_EXT 0x80A6 -#define GL_4PASS_3_EXT 0x80A7 -#define GL_SAMPLE_BUFFERS_EXT 0x80A8 -#define GL_SAMPLES_EXT 0x80A9 -#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA -#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB -#define GL_SAMPLE_PATTERN_EXT 0x80AC -#define GL_MULTISAMPLE_BIT_EXT 0x20000000 -#endif - -#ifndef GL_SGIX_vertex_preclip -#define GL_VERTEX_PRECLIP_SGIX 0x83EE -#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF -#endif - -#ifndef GL_SGIX_convolution_accuracy -#define GL_CONVOLUTION_HINT_SGIX 0x8316 -#endif - -#ifndef GL_SGIX_resample -#define GL_PACK_RESAMPLE_SGIX 0x842C -#define GL_UNPACK_RESAMPLE_SGIX 0x842D -#define GL_RESAMPLE_REPLICATE_SGIX 0x842E -#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F -#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 -#endif - -#ifndef GL_SGIS_point_line_texgen -#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 -#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 -#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 -#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 -#define GL_EYE_POINT_SGIS 0x81F4 -#define GL_OBJECT_POINT_SGIS 0x81F5 -#define GL_EYE_LINE_SGIS 0x81F6 -#define GL_OBJECT_LINE_SGIS 0x81F7 -#endif - -#ifndef GL_SGIS_texture_color_mask -#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF -#endif - -#ifndef GL_EXT_texture_env_dot3 -#define GL_DOT3_RGB_EXT 0x8740 -#define GL_DOT3_RGBA_EXT 0x8741 -#endif - -#ifndef GL_ATI_texture_mirror_once -#define GL_MIRROR_CLAMP_ATI 0x8742 -#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 -#endif - -#ifndef GL_NV_fence -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 -#endif - -#ifndef GL_IBM_texture_mirrored_repeat -#define GL_MIRRORED_REPEAT_IBM 0x8370 -#endif - -#ifndef GL_NV_evaluators -#define GL_EVAL_2D_NV 0x86C0 -#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 -#define GL_MAP_TESSELLATION_NV 0x86C2 -#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 -#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 -#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 -#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 -#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 -#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 -#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 -#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA -#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB -#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC -#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD -#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE -#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF -#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 -#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 -#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 -#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 -#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 -#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 -#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 -#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 -#endif - -#ifndef GL_NV_packed_depth_stencil -#define GL_DEPTH_STENCIL_NV 0x84F9 -#define GL_UNSIGNED_INT_24_8_NV 0x84FA -#endif - -#ifndef GL_NV_register_combiners2 -#define GL_PER_STAGE_CONSTANTS_NV 0x8535 -#endif - -#ifndef GL_NV_texture_compression_vtc -#endif - -#ifndef GL_NV_texture_rectangle -#define GL_TEXTURE_RECTANGLE_NV 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 -#endif - -#ifndef GL_NV_texture_shader -#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C -#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D -#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E -#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 -#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA -#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB -#define GL_DSDT_MAG_INTENSITY_NV 0x86DC -#define GL_SHADER_CONSISTENT_NV 0x86DD -#define GL_TEXTURE_SHADER_NV 0x86DE -#define GL_SHADER_OPERATION_NV 0x86DF -#define GL_CULL_MODES_NV 0x86E0 -#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 -#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 -#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 -#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV -#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV -#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV -#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 -#define GL_CONST_EYE_NV 0x86E5 -#define GL_PASS_THROUGH_NV 0x86E6 -#define GL_CULL_FRAGMENT_NV 0x86E7 -#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 -#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 -#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA -#define GL_DOT_PRODUCT_NV 0x86EC -#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED -#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE -#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 -#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 -#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 -#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 -#define GL_HILO_NV 0x86F4 -#define GL_DSDT_NV 0x86F5 -#define GL_DSDT_MAG_NV 0x86F6 -#define GL_DSDT_MAG_VIB_NV 0x86F7 -#define GL_HILO16_NV 0x86F8 -#define GL_SIGNED_HILO_NV 0x86F9 -#define GL_SIGNED_HILO16_NV 0x86FA -#define GL_SIGNED_RGBA_NV 0x86FB -#define GL_SIGNED_RGBA8_NV 0x86FC -#define GL_SIGNED_RGB_NV 0x86FE -#define GL_SIGNED_RGB8_NV 0x86FF -#define GL_SIGNED_LUMINANCE_NV 0x8701 -#define GL_SIGNED_LUMINANCE8_NV 0x8702 -#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 -#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 -#define GL_SIGNED_ALPHA_NV 0x8705 -#define GL_SIGNED_ALPHA8_NV 0x8706 -#define GL_SIGNED_INTENSITY_NV 0x8707 -#define GL_SIGNED_INTENSITY8_NV 0x8708 -#define GL_DSDT8_NV 0x8709 -#define GL_DSDT8_MAG8_NV 0x870A -#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B -#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C -#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D -#define GL_HI_SCALE_NV 0x870E -#define GL_LO_SCALE_NV 0x870F -#define GL_DS_SCALE_NV 0x8710 -#define GL_DT_SCALE_NV 0x8711 -#define GL_MAGNITUDE_SCALE_NV 0x8712 -#define GL_VIBRANCE_SCALE_NV 0x8713 -#define GL_HI_BIAS_NV 0x8714 -#define GL_LO_BIAS_NV 0x8715 -#define GL_DS_BIAS_NV 0x8716 -#define GL_DT_BIAS_NV 0x8717 -#define GL_MAGNITUDE_BIAS_NV 0x8718 -#define GL_VIBRANCE_BIAS_NV 0x8719 -#define GL_TEXTURE_BORDER_VALUES_NV 0x871A -#define GL_TEXTURE_HI_SIZE_NV 0x871B -#define GL_TEXTURE_LO_SIZE_NV 0x871C -#define GL_TEXTURE_DS_SIZE_NV 0x871D -#define GL_TEXTURE_DT_SIZE_NV 0x871E -#define GL_TEXTURE_MAG_SIZE_NV 0x871F -#endif - -#ifndef GL_NV_texture_shader2 -#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF -#endif - -#ifndef GL_NV_vertex_array_range2 -#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 -#endif - -#ifndef GL_NV_vertex_program -#define GL_VERTEX_PROGRAM_NV 0x8620 -#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 -#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 -#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 -#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 -#define GL_CURRENT_ATTRIB_NV 0x8626 -#define GL_PROGRAM_LENGTH_NV 0x8627 -#define GL_PROGRAM_STRING_NV 0x8628 -#define GL_MODELVIEW_PROJECTION_NV 0x8629 -#define GL_IDENTITY_NV 0x862A -#define GL_INVERSE_NV 0x862B -#define GL_TRANSPOSE_NV 0x862C -#define GL_INVERSE_TRANSPOSE_NV 0x862D -#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E -#define GL_MAX_TRACK_MATRICES_NV 0x862F -#define GL_MATRIX0_NV 0x8630 -#define GL_MATRIX1_NV 0x8631 -#define GL_MATRIX2_NV 0x8632 -#define GL_MATRIX3_NV 0x8633 -#define GL_MATRIX4_NV 0x8634 -#define GL_MATRIX5_NV 0x8635 -#define GL_MATRIX6_NV 0x8636 -#define GL_MATRIX7_NV 0x8637 -#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 -#define GL_CURRENT_MATRIX_NV 0x8641 -#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 -#define GL_PROGRAM_PARAMETER_NV 0x8644 -#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 -#define GL_PROGRAM_TARGET_NV 0x8646 -#define GL_PROGRAM_RESIDENT_NV 0x8647 -#define GL_TRACK_MATRIX_NV 0x8648 -#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 -#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A -#define GL_PROGRAM_ERROR_POSITION_NV 0x864B -#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 -#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 -#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 -#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 -#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 -#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 -#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 -#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 -#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 -#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 -#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A -#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B -#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C -#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D -#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E -#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F -#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 -#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 -#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 -#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 -#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 -#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 -#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 -#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 -#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 -#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 -#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A -#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B -#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C -#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D -#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E -#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F -#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 -#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 -#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 -#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 -#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 -#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 -#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 -#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 -#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 -#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 -#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A -#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B -#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C -#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D -#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E -#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F -#endif - -#ifndef GL_SGIX_texture_coordinate_clamp -#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 -#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A -#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B -#endif - -#ifndef GL_SGIX_scalebias_hint -#define GL_SCALEBIAS_HINT_SGIX 0x8322 -#endif - -#ifndef GL_OML_interlace -#define GL_INTERLACE_OML 0x8980 -#define GL_INTERLACE_READ_OML 0x8981 -#endif - -#ifndef GL_OML_subsample -#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 -#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 -#endif - -#ifndef GL_OML_resample -#define GL_PACK_RESAMPLE_OML 0x8984 -#define GL_UNPACK_RESAMPLE_OML 0x8985 -#define GL_RESAMPLE_REPLICATE_OML 0x8986 -#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 -#define GL_RESAMPLE_AVERAGE_OML 0x8988 -#define GL_RESAMPLE_DECIMATE_OML 0x8989 -#endif - -#ifndef GL_NV_copy_depth_to_color -#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E -#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F -#endif - -#ifndef GL_ATI_envmap_bumpmap -#define GL_BUMP_ROT_MATRIX_ATI 0x8775 -#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 -#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 -#define GL_BUMP_TEX_UNITS_ATI 0x8778 -#define GL_DUDV_ATI 0x8779 -#define GL_DU8DV8_ATI 0x877A -#define GL_BUMP_ENVMAP_ATI 0x877B -#define GL_BUMP_TARGET_ATI 0x877C -#endif - -#ifndef GL_ATI_fragment_shader -#define GL_FRAGMENT_SHADER_ATI 0x8920 -#define GL_REG_0_ATI 0x8921 -#define GL_REG_1_ATI 0x8922 -#define GL_REG_2_ATI 0x8923 -#define GL_REG_3_ATI 0x8924 -#define GL_REG_4_ATI 0x8925 -#define GL_REG_5_ATI 0x8926 -#define GL_REG_6_ATI 0x8927 -#define GL_REG_7_ATI 0x8928 -#define GL_REG_8_ATI 0x8929 -#define GL_REG_9_ATI 0x892A -#define GL_REG_10_ATI 0x892B -#define GL_REG_11_ATI 0x892C -#define GL_REG_12_ATI 0x892D -#define GL_REG_13_ATI 0x892E -#define GL_REG_14_ATI 0x892F -#define GL_REG_15_ATI 0x8930 -#define GL_REG_16_ATI 0x8931 -#define GL_REG_17_ATI 0x8932 -#define GL_REG_18_ATI 0x8933 -#define GL_REG_19_ATI 0x8934 -#define GL_REG_20_ATI 0x8935 -#define GL_REG_21_ATI 0x8936 -#define GL_REG_22_ATI 0x8937 -#define GL_REG_23_ATI 0x8938 -#define GL_REG_24_ATI 0x8939 -#define GL_REG_25_ATI 0x893A -#define GL_REG_26_ATI 0x893B -#define GL_REG_27_ATI 0x893C -#define GL_REG_28_ATI 0x893D -#define GL_REG_29_ATI 0x893E -#define GL_REG_30_ATI 0x893F -#define GL_REG_31_ATI 0x8940 -#define GL_CON_0_ATI 0x8941 -#define GL_CON_1_ATI 0x8942 -#define GL_CON_2_ATI 0x8943 -#define GL_CON_3_ATI 0x8944 -#define GL_CON_4_ATI 0x8945 -#define GL_CON_5_ATI 0x8946 -#define GL_CON_6_ATI 0x8947 -#define GL_CON_7_ATI 0x8948 -#define GL_CON_8_ATI 0x8949 -#define GL_CON_9_ATI 0x894A -#define GL_CON_10_ATI 0x894B -#define GL_CON_11_ATI 0x894C -#define GL_CON_12_ATI 0x894D -#define GL_CON_13_ATI 0x894E -#define GL_CON_14_ATI 0x894F -#define GL_CON_15_ATI 0x8950 -#define GL_CON_16_ATI 0x8951 -#define GL_CON_17_ATI 0x8952 -#define GL_CON_18_ATI 0x8953 -#define GL_CON_19_ATI 0x8954 -#define GL_CON_20_ATI 0x8955 -#define GL_CON_21_ATI 0x8956 -#define GL_CON_22_ATI 0x8957 -#define GL_CON_23_ATI 0x8958 -#define GL_CON_24_ATI 0x8959 -#define GL_CON_25_ATI 0x895A -#define GL_CON_26_ATI 0x895B -#define GL_CON_27_ATI 0x895C -#define GL_CON_28_ATI 0x895D -#define GL_CON_29_ATI 0x895E -#define GL_CON_30_ATI 0x895F -#define GL_CON_31_ATI 0x8960 -#define GL_MOV_ATI 0x8961 -#define GL_ADD_ATI 0x8963 -#define GL_MUL_ATI 0x8964 -#define GL_SUB_ATI 0x8965 -#define GL_DOT3_ATI 0x8966 -#define GL_DOT4_ATI 0x8967 -#define GL_MAD_ATI 0x8968 -#define GL_LERP_ATI 0x8969 -#define GL_CND_ATI 0x896A -#define GL_CND0_ATI 0x896B -#define GL_DOT2_ADD_ATI 0x896C -#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D -#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E -#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F -#define GL_NUM_PASSES_ATI 0x8970 -#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 -#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 -#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 -#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 -#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 -#define GL_SWIZZLE_STR_ATI 0x8976 -#define GL_SWIZZLE_STQ_ATI 0x8977 -#define GL_SWIZZLE_STR_DR_ATI 0x8978 -#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 -#define GL_SWIZZLE_STRQ_ATI 0x897A -#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B -#define GL_RED_BIT_ATI 0x00000001 -#define GL_GREEN_BIT_ATI 0x00000002 -#define GL_BLUE_BIT_ATI 0x00000004 -#define GL_2X_BIT_ATI 0x00000001 -#define GL_4X_BIT_ATI 0x00000002 -#define GL_8X_BIT_ATI 0x00000004 -#define GL_HALF_BIT_ATI 0x00000008 -#define GL_QUARTER_BIT_ATI 0x00000010 -#define GL_EIGHTH_BIT_ATI 0x00000020 -#define GL_SATURATE_BIT_ATI 0x00000040 -#define GL_COMP_BIT_ATI 0x00000002 -#define GL_NEGATE_BIT_ATI 0x00000004 -#define GL_BIAS_BIT_ATI 0x00000008 -#endif - -#ifndef GL_ATI_pn_triangles -#define GL_PN_TRIANGLES_ATI 0x87F0 -#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 -#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 -#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 -#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 -#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 -#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 -#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 -#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 -#endif - -#ifndef GL_ATI_vertex_array_object -#define GL_STATIC_ATI 0x8760 -#define GL_DYNAMIC_ATI 0x8761 -#define GL_PRESERVE_ATI 0x8762 -#define GL_DISCARD_ATI 0x8763 -#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 -#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 -#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 -#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 -#endif - -#ifndef GL_EXT_vertex_shader -#define GL_VERTEX_SHADER_EXT 0x8780 -#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 -#define GL_OP_INDEX_EXT 0x8782 -#define GL_OP_NEGATE_EXT 0x8783 -#define GL_OP_DOT3_EXT 0x8784 -#define GL_OP_DOT4_EXT 0x8785 -#define GL_OP_MUL_EXT 0x8786 -#define GL_OP_ADD_EXT 0x8787 -#define GL_OP_MADD_EXT 0x8788 -#define GL_OP_FRAC_EXT 0x8789 -#define GL_OP_MAX_EXT 0x878A -#define GL_OP_MIN_EXT 0x878B -#define GL_OP_SET_GE_EXT 0x878C -#define GL_OP_SET_LT_EXT 0x878D -#define GL_OP_CLAMP_EXT 0x878E -#define GL_OP_FLOOR_EXT 0x878F -#define GL_OP_ROUND_EXT 0x8790 -#define GL_OP_EXP_BASE_2_EXT 0x8791 -#define GL_OP_LOG_BASE_2_EXT 0x8792 -#define GL_OP_POWER_EXT 0x8793 -#define GL_OP_RECIP_EXT 0x8794 -#define GL_OP_RECIP_SQRT_EXT 0x8795 -#define GL_OP_SUB_EXT 0x8796 -#define GL_OP_CROSS_PRODUCT_EXT 0x8797 -#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 -#define GL_OP_MOV_EXT 0x8799 -#define GL_OUTPUT_VERTEX_EXT 0x879A -#define GL_OUTPUT_COLOR0_EXT 0x879B -#define GL_OUTPUT_COLOR1_EXT 0x879C -#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D -#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E -#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F -#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 -#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 -#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 -#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 -#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 -#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 -#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 -#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 -#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 -#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 -#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA -#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB -#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC -#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD -#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE -#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF -#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 -#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 -#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 -#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 -#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 -#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 -#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 -#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 -#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 -#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 -#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA -#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB -#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC -#define GL_OUTPUT_FOG_EXT 0x87BD -#define GL_SCALAR_EXT 0x87BE -#define GL_VECTOR_EXT 0x87BF -#define GL_MATRIX_EXT 0x87C0 -#define GL_VARIANT_EXT 0x87C1 -#define GL_INVARIANT_EXT 0x87C2 -#define GL_LOCAL_CONSTANT_EXT 0x87C3 -#define GL_LOCAL_EXT 0x87C4 -#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 -#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 -#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 -#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 -#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD -#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE -#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF -#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 -#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 -#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 -#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 -#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 -#define GL_X_EXT 0x87D5 -#define GL_Y_EXT 0x87D6 -#define GL_Z_EXT 0x87D7 -#define GL_W_EXT 0x87D8 -#define GL_NEGATIVE_X_EXT 0x87D9 -#define GL_NEGATIVE_Y_EXT 0x87DA -#define GL_NEGATIVE_Z_EXT 0x87DB -#define GL_NEGATIVE_W_EXT 0x87DC -#define GL_ZERO_EXT 0x87DD -#define GL_ONE_EXT 0x87DE -#define GL_NEGATIVE_ONE_EXT 0x87DF -#define GL_NORMALIZED_RANGE_EXT 0x87E0 -#define GL_FULL_RANGE_EXT 0x87E1 -#define GL_CURRENT_VERTEX_EXT 0x87E2 -#define GL_MVP_MATRIX_EXT 0x87E3 -#define GL_VARIANT_VALUE_EXT 0x87E4 -#define GL_VARIANT_DATATYPE_EXT 0x87E5 -#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 -#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 -#define GL_VARIANT_ARRAY_EXT 0x87E8 -#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 -#define GL_INVARIANT_VALUE_EXT 0x87EA -#define GL_INVARIANT_DATATYPE_EXT 0x87EB -#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC -#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED -#endif - -#ifndef GL_ATI_vertex_streams -#define GL_MAX_VERTEX_STREAMS_ATI 0x876B -#define GL_VERTEX_STREAM0_ATI 0x876C -#define GL_VERTEX_STREAM1_ATI 0x876D -#define GL_VERTEX_STREAM2_ATI 0x876E -#define GL_VERTEX_STREAM3_ATI 0x876F -#define GL_VERTEX_STREAM4_ATI 0x8770 -#define GL_VERTEX_STREAM5_ATI 0x8771 -#define GL_VERTEX_STREAM6_ATI 0x8772 -#define GL_VERTEX_STREAM7_ATI 0x8773 -#define GL_VERTEX_SOURCE_ATI 0x8774 -#endif - -#ifndef GL_ATI_element_array -#define GL_ELEMENT_ARRAY_ATI 0x8768 -#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 -#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A -#endif - -#ifndef GL_SUN_mesh_array -#define GL_QUAD_MESH_SUN 0x8614 -#define GL_TRIANGLE_MESH_SUN 0x8615 -#endif - -#ifndef GL_SUN_slice_accum -#define GL_SLICE_ACCUM_SUN 0x85CC -#endif - -#ifndef GL_NV_multisample_filter_hint -#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 -#endif - -#ifndef GL_NV_depth_clamp -#define GL_DEPTH_CLAMP_NV 0x864F -#endif - -#ifndef GL_NV_occlusion_query -#define GL_PIXEL_COUNTER_BITS_NV 0x8864 -#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 -#define GL_PIXEL_COUNT_NV 0x8866 -#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 -#endif - -#ifndef GL_NV_point_sprite -#define GL_POINT_SPRITE_NV 0x8861 -#define GL_COORD_REPLACE_NV 0x8862 -#define GL_POINT_SPRITE_R_MODE_NV 0x8863 -#endif - -#ifndef GL_NV_texture_shader3 -#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 -#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 -#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 -#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 -#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 -#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 -#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 -#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 -#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 -#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 -#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A -#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B -#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C -#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D -#define GL_HILO8_NV 0x885E -#define GL_SIGNED_HILO8_NV 0x885F -#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 -#endif - -#ifndef GL_NV_vertex_program1_1 -#endif - -#ifndef GL_EXT_shadow_funcs -#endif - -#ifndef GL_EXT_stencil_two_side -#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 -#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 -#endif - -#ifndef GL_ATI_text_fragment_shader -#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 -#endif - -#ifndef GL_APPLE_client_storage -#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 -#endif - -#ifndef GL_APPLE_element_array -#define GL_ELEMENT_ARRAY_APPLE 0x8A0C -#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D -#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E -#endif - -#ifndef GL_APPLE_fence -#define GL_DRAW_PIXELS_APPLE 0x8A0A -#define GL_FENCE_APPLE 0x8A0B -#endif - -#ifndef GL_APPLE_vertex_array_object -#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 -#endif - -#ifndef GL_APPLE_vertex_array_range -#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D -#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E -#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F -#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 -#define GL_STORAGE_CLIENT_APPLE 0x85B4 -#define GL_STORAGE_CACHED_APPLE 0x85BE -#define GL_STORAGE_SHARED_APPLE 0x85BF -#endif - -#ifndef GL_APPLE_ycbcr_422 -#define GL_YCBCR_422_APPLE 0x85B9 -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB -#endif - -#ifndef GL_S3_s3tc -#define GL_RGB_S3TC 0x83A0 -#define GL_RGB4_S3TC 0x83A1 -#define GL_RGBA_S3TC 0x83A2 -#define GL_RGBA4_S3TC 0x83A3 -#endif - -#ifndef GL_ATI_draw_buffers -#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 -#define GL_DRAW_BUFFER0_ATI 0x8825 -#define GL_DRAW_BUFFER1_ATI 0x8826 -#define GL_DRAW_BUFFER2_ATI 0x8827 -#define GL_DRAW_BUFFER3_ATI 0x8828 -#define GL_DRAW_BUFFER4_ATI 0x8829 -#define GL_DRAW_BUFFER5_ATI 0x882A -#define GL_DRAW_BUFFER6_ATI 0x882B -#define GL_DRAW_BUFFER7_ATI 0x882C -#define GL_DRAW_BUFFER8_ATI 0x882D -#define GL_DRAW_BUFFER9_ATI 0x882E -#define GL_DRAW_BUFFER10_ATI 0x882F -#define GL_DRAW_BUFFER11_ATI 0x8830 -#define GL_DRAW_BUFFER12_ATI 0x8831 -#define GL_DRAW_BUFFER13_ATI 0x8832 -#define GL_DRAW_BUFFER14_ATI 0x8833 -#define GL_DRAW_BUFFER15_ATI 0x8834 -#endif - -#ifndef GL_ATI_pixel_format_float -#define GL_TYPE_RGBA_FLOAT_ATI 0x8820 -#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 -#endif - -#ifndef GL_ATI_texture_env_combine3 -#define GL_MODULATE_ADD_ATI 0x8744 -#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 -#define GL_MODULATE_SUBTRACT_ATI 0x8746 -#endif - -#ifndef GL_ATI_texture_float -#define GL_RGBA_FLOAT32_ATI 0x8814 -#define GL_RGB_FLOAT32_ATI 0x8815 -#define GL_ALPHA_FLOAT32_ATI 0x8816 -#define GL_INTENSITY_FLOAT32_ATI 0x8817 -#define GL_LUMINANCE_FLOAT32_ATI 0x8818 -#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 -#define GL_RGBA_FLOAT16_ATI 0x881A -#define GL_RGB_FLOAT16_ATI 0x881B -#define GL_ALPHA_FLOAT16_ATI 0x881C -#define GL_INTENSITY_FLOAT16_ATI 0x881D -#define GL_LUMINANCE_FLOAT16_ATI 0x881E -#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F -#endif - -#ifndef GL_NV_float_buffer -#define GL_FLOAT_R_NV 0x8880 -#define GL_FLOAT_RG_NV 0x8881 -#define GL_FLOAT_RGB_NV 0x8882 -#define GL_FLOAT_RGBA_NV 0x8883 -#define GL_FLOAT_R16_NV 0x8884 -#define GL_FLOAT_R32_NV 0x8885 -#define GL_FLOAT_RG16_NV 0x8886 -#define GL_FLOAT_RG32_NV 0x8887 -#define GL_FLOAT_RGB16_NV 0x8888 -#define GL_FLOAT_RGB32_NV 0x8889 -#define GL_FLOAT_RGBA16_NV 0x888A -#define GL_FLOAT_RGBA32_NV 0x888B -#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C -#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D -#define GL_FLOAT_RGBA_MODE_NV 0x888E -#endif - -#ifndef GL_NV_fragment_program -#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 -#define GL_FRAGMENT_PROGRAM_NV 0x8870 -#define GL_MAX_TEXTURE_COORDS_NV 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 -#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 -#define GL_PROGRAM_ERROR_STRING_NV 0x8874 -#endif - -#ifndef GL_NV_half_float -#define GL_HALF_FLOAT_NV 0x140B -#endif - -#ifndef GL_NV_pixel_data_range -#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 -#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 -#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A -#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B -#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C -#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D -#endif - -#ifndef GL_NV_primitive_restart -#define GL_PRIMITIVE_RESTART_NV 0x8558 -#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 -#endif - -#ifndef GL_NV_texture_expand_normal -#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F -#endif - -#ifndef GL_NV_vertex_program2 -#endif - -#ifndef GL_ATI_map_object_buffer -#endif - -#ifndef GL_ATI_separate_stencil -#define GL_STENCIL_BACK_FUNC_ATI 0x8800 -#define GL_STENCIL_BACK_FAIL_ATI 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 -#endif - -#ifndef GL_ATI_vertex_attrib_array_object -#endif - -#ifndef GL_OES_read_format -#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B -#endif - -#ifndef GL_EXT_depth_bounds_test -#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 -#define GL_DEPTH_BOUNDS_EXT 0x8891 -#endif - -#ifndef GL_EXT_texture_mirror_clamp -#define GL_MIRROR_CLAMP_EXT 0x8742 -#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 -#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 -#endif - -#ifndef GL_EXT_blend_equation_separate -#define GL_BLEND_EQUATION_RGB_EXT 0x8009 -#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D -#endif - -#ifndef GL_MESA_pack_invert -#define GL_PACK_INVERT_MESA 0x8758 -#endif - -#ifndef GL_MESA_ycbcr_texture -#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB -#define GL_YCBCR_MESA 0x8757 -#endif - -#ifndef GL_EXT_pixel_buffer_object -#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB -#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF -#endif - -#ifndef GL_NV_fragment_program_option -#endif - -#ifndef GL_NV_fragment_program2 -#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 -#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 -#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 -#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 -#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 -#endif - -#ifndef GL_NV_vertex_program2_option -/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */ -/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */ -#endif - -#ifndef GL_NV_vertex_program3 -/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */ -#endif - -#ifndef GL_EXT_framebuffer_object -#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 -#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 -#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 -#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 -#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC -#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD -#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 -#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 -#define GL_FRAMEBUFFER_EXT 0x8D40 -#define GL_RENDERBUFFER_EXT 0x8D41 -#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 -#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 -#define GL_STENCIL_INDEX1_EXT 0x8D46 -#define GL_STENCIL_INDEX4_EXT 0x8D47 -#define GL_STENCIL_INDEX8_EXT 0x8D48 -#define GL_STENCIL_INDEX16_EXT 0x8D49 -#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 -#endif - -#ifndef GL_GREMEDY_string_marker -#endif - -#ifndef GL_EXT_packed_depth_stencil -#define GL_DEPTH_STENCIL_EXT 0x84F9 -#define GL_UNSIGNED_INT_24_8_EXT 0x84FA -#define GL_DEPTH24_STENCIL8_EXT 0x88F0 -#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 -#endif - -#ifndef GL_EXT_stencil_clear_tag -#define GL_STENCIL_TAG_BITS_EXT 0x88F2 -#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 -#endif - -#ifndef GL_EXT_texture_sRGB -#define GL_SRGB_EXT 0x8C40 -#define GL_SRGB8_EXT 0x8C41 -#define GL_SRGB_ALPHA_EXT 0x8C42 -#define GL_SRGB8_ALPHA8_EXT 0x8C43 -#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 -#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 -#define GL_SLUMINANCE_EXT 0x8C46 -#define GL_SLUMINANCE8_EXT 0x8C47 -#define GL_COMPRESSED_SRGB_EXT 0x8C48 -#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 -#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A -#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B -#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F -#endif - -#ifndef GL_EXT_framebuffer_blit -#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING_EXT -#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA -#endif - -#ifndef GL_EXT_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 -#define GL_MAX_SAMPLES_EXT 0x8D57 -#endif - -#ifndef GL_MESAX_texture_stack -#define GL_TEXTURE_1D_STACK_MESAX 0x8759 -#define GL_TEXTURE_2D_STACK_MESAX 0x875A -#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B -#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C -#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D -#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E -#endif - -#ifndef GL_EXT_timer_query -#define GL_TIME_ELAPSED_EXT 0x88BF -#endif - -#ifndef GL_EXT_gpu_program_parameters -#endif - -#ifndef GL_APPLE_flush_buffer_range -#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 -#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 -#endif - -#ifndef GL_NV_gpu_program4 -#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 -#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 -#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 -#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 -#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 -#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 -#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 -#endif - -#ifndef GL_NV_geometry_program4 -#define GL_LINES_ADJACENCY_EXT 0x000A -#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B -#define GL_TRIANGLES_ADJACENCY_EXT 0x000C -#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D -#define GL_GEOMETRY_PROGRAM_NV 0x8C26 -#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 -#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 -#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA -#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB -#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 -#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 -#endif - -#ifndef GL_EXT_geometry_shader4 -#define GL_GEOMETRY_SHADER_EXT 0x8DD9 -/* reuse GL_GEOMETRY_VERTICES_OUT_EXT */ -/* reuse GL_GEOMETRY_INPUT_TYPE_EXT */ -/* reuse GL_GEOMETRY_OUTPUT_TYPE_EXT */ -/* reuse GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */ -#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD -#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE -#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 -/* reuse GL_LINES_ADJACENCY_EXT */ -/* reuse GL_LINE_STRIP_ADJACENCY_EXT */ -/* reuse GL_TRIANGLES_ADJACENCY_EXT */ -/* reuse GL_TRIANGLE_STRIP_ADJACENCY_EXT */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT */ -/* reuse GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT */ -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */ -/* reuse GL_PROGRAM_POINT_SIZE_EXT */ -#endif - -#ifndef GL_NV_vertex_program4 -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD -#endif - -#ifndef GL_EXT_gpu_shader4 -#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 -#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 -#define GL_SAMPLER_BUFFER_EXT 0x8DC2 -#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 -#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 -#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 -#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 -#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 -#define GL_INT_SAMPLER_1D_EXT 0x8DC9 -#define GL_INT_SAMPLER_2D_EXT 0x8DCA -#define GL_INT_SAMPLER_3D_EXT 0x8DCB -#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC -#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD -#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE -#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF -#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 -#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 -#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 -#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 -#endif - -#ifndef GL_EXT_draw_instanced -#endif - -#ifndef GL_EXT_packed_float -#define GL_R11F_G11F_B10F_EXT 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B -#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C -#endif - -#ifndef GL_EXT_texture_array -#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 -#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 -#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A -#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B -#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C -#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D -#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF -#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E -/* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */ -#endif - -#ifndef GL_EXT_texture_buffer_object -#define GL_TEXTURE_BUFFER_EXT 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D -#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E -#endif - -#ifndef GL_EXT_texture_compression_latc -#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 -#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 -#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 -#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 -#endif - -#ifndef GL_EXT_texture_compression_rgtc -#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB -#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC -#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD -#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE -#endif - -#ifndef GL_EXT_texture_shared_exponent -#define GL_RGB9_E5_EXT 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E -#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F -#endif - -#ifndef GL_NV_depth_buffer_float -#define GL_DEPTH_COMPONENT32F_NV 0x8DAB -#define GL_DEPTH32F_STENCIL8_NV 0x8DAC -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD -#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF -#endif - -#ifndef GL_NV_fragment_program4 -#endif - -#ifndef GL_NV_framebuffer_multisample_coverage -#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB -#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 -#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 -#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 -#endif - -#ifndef GL_EXT_framebuffer_sRGB -#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 -#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA -#endif - -#ifndef GL_NV_geometry_shader4 -#endif - -#ifndef GL_NV_parameter_buffer_object -#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 -#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 -#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 -#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 -#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 -#endif - -#ifndef GL_EXT_draw_buffers2 -#endif - -#ifndef GL_NV_transform_feedback -#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 -#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 -#define GL_TEXTURE_COORD_NV 0x8C79 -#define GL_CLIP_DISTANCE_NV 0x8C7A -#define GL_VERTEX_ID_NV 0x8C7B -#define GL_PRIMITIVE_ID_NV 0x8C7C -#define GL_GENERIC_ATTRIB_NV 0x8C7D -#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 -#define GL_ACTIVE_VARYINGS_NV 0x8C81 -#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 -#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 -#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 -#define GL_PRIMITIVES_GENERATED_NV 0x8C87 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 -#define GL_RASTERIZER_DISCARD_NV 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_ATTRIBS_NV 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B -#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C -#define GL_SEPARATE_ATTRIBS_NV 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F -#define GL_LAYER_NV 0x8DAA -#define GL_NEXT_BUFFER_NV -2 -#define GL_SKIP_COMPONENTS4_NV -3 -#define GL_SKIP_COMPONENTS3_NV -4 -#define GL_SKIP_COMPONENTS2_NV -5 -#define GL_SKIP_COMPONENTS1_NV -6 -#endif - -#ifndef GL_EXT_bindable_uniform -#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 -#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 -#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 -#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED -#define GL_UNIFORM_BUFFER_EXT 0x8DEE -#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF -#endif - -#ifndef GL_EXT_texture_integer -#define GL_RGBA32UI_EXT 0x8D70 -#define GL_RGB32UI_EXT 0x8D71 -#define GL_ALPHA32UI_EXT 0x8D72 -#define GL_INTENSITY32UI_EXT 0x8D73 -#define GL_LUMINANCE32UI_EXT 0x8D74 -#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 -#define GL_RGBA16UI_EXT 0x8D76 -#define GL_RGB16UI_EXT 0x8D77 -#define GL_ALPHA16UI_EXT 0x8D78 -#define GL_INTENSITY16UI_EXT 0x8D79 -#define GL_LUMINANCE16UI_EXT 0x8D7A -#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B -#define GL_RGBA8UI_EXT 0x8D7C -#define GL_RGB8UI_EXT 0x8D7D -#define GL_ALPHA8UI_EXT 0x8D7E -#define GL_INTENSITY8UI_EXT 0x8D7F -#define GL_LUMINANCE8UI_EXT 0x8D80 -#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 -#define GL_RGBA32I_EXT 0x8D82 -#define GL_RGB32I_EXT 0x8D83 -#define GL_ALPHA32I_EXT 0x8D84 -#define GL_INTENSITY32I_EXT 0x8D85 -#define GL_LUMINANCE32I_EXT 0x8D86 -#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 -#define GL_RGBA16I_EXT 0x8D88 -#define GL_RGB16I_EXT 0x8D89 -#define GL_ALPHA16I_EXT 0x8D8A -#define GL_INTENSITY16I_EXT 0x8D8B -#define GL_LUMINANCE16I_EXT 0x8D8C -#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D -#define GL_RGBA8I_EXT 0x8D8E -#define GL_RGB8I_EXT 0x8D8F -#define GL_ALPHA8I_EXT 0x8D90 -#define GL_INTENSITY8I_EXT 0x8D91 -#define GL_LUMINANCE8I_EXT 0x8D92 -#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 -#define GL_RED_INTEGER_EXT 0x8D94 -#define GL_GREEN_INTEGER_EXT 0x8D95 -#define GL_BLUE_INTEGER_EXT 0x8D96 -#define GL_ALPHA_INTEGER_EXT 0x8D97 -#define GL_RGB_INTEGER_EXT 0x8D98 -#define GL_RGBA_INTEGER_EXT 0x8D99 -#define GL_BGR_INTEGER_EXT 0x8D9A -#define GL_BGRA_INTEGER_EXT 0x8D9B -#define GL_LUMINANCE_INTEGER_EXT 0x8D9C -#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D -#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E -#endif - -#ifndef GL_GREMEDY_frame_terminator -#endif - -#ifndef GL_NV_conditional_render -#define GL_QUERY_WAIT_NV 0x8E13 -#define GL_QUERY_NO_WAIT_NV 0x8E14 -#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 -#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 -#endif - -#ifndef GL_NV_present_video -#define GL_FRAME_NV 0x8E26 -#define GL_FIELDS_NV 0x8E27 -#define GL_CURRENT_TIME_NV 0x8E28 -#define GL_NUM_FILL_STREAMS_NV 0x8E29 -#define GL_PRESENT_TIME_NV 0x8E2A -#define GL_PRESENT_DURATION_NV 0x8E2B -#endif - -#ifndef GL_EXT_transform_feedback -#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F -#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C -#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D -#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 -#define GL_RASTERIZER_DISCARD_EXT 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 -#endif - -#ifndef GL_EXT_direct_state_access -#define GL_PROGRAM_MATRIX_EXT 0x8E2D -#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E -#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F -#endif - -#ifndef GL_EXT_vertex_array_bgra -/* reuse GL_BGRA */ -#endif - -#ifndef GL_EXT_texture_swizzle -#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 -#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 -#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 -#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 -#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 -#endif - -#ifndef GL_NV_explicit_multisample -#define GL_SAMPLE_POSITION_NV 0x8E50 -#define GL_SAMPLE_MASK_NV 0x8E51 -#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 -#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 -#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 -#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 -#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 -#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 -#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 -#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 -#endif - -#ifndef GL_NV_transform_feedback2 -#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 -#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 -#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 -#endif - -#ifndef GL_ATI_meminfo -#define GL_VBO_FREE_MEMORY_ATI 0x87FB -#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC -#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD -#endif - -#ifndef GL_AMD_performance_monitor -#define GL_COUNTER_TYPE_AMD 0x8BC0 -#define GL_COUNTER_RANGE_AMD 0x8BC1 -#define GL_UNSIGNED_INT64_AMD 0x8BC2 -#define GL_PERCENTAGE_AMD 0x8BC3 -#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 -#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 -#define GL_PERFMON_RESULT_AMD 0x8BC6 -#endif - -#ifndef GL_AMD_texture_texture4 -#endif - -#ifndef GL_AMD_vertex_shader_tesselator -#define GL_SAMPLER_BUFFER_AMD 0x9001 -#define GL_INT_SAMPLER_BUFFER_AMD 0x9002 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003 -#define GL_TESSELLATION_MODE_AMD 0x9004 -#define GL_TESSELLATION_FACTOR_AMD 0x9005 -#define GL_DISCRETE_AMD 0x9006 -#define GL_CONTINUOUS_AMD 0x9007 -#endif - -#ifndef GL_EXT_provoking_vertex -#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C -#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D -#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E -#define GL_PROVOKING_VERTEX_EXT 0x8E4F -#endif - -#ifndef GL_EXT_texture_snorm -#define GL_ALPHA_SNORM 0x9010 -#define GL_LUMINANCE_SNORM 0x9011 -#define GL_LUMINANCE_ALPHA_SNORM 0x9012 -#define GL_INTENSITY_SNORM 0x9013 -#define GL_ALPHA8_SNORM 0x9014 -#define GL_LUMINANCE8_SNORM 0x9015 -#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 -#define GL_INTENSITY8_SNORM 0x9017 -#define GL_ALPHA16_SNORM 0x9018 -#define GL_LUMINANCE16_SNORM 0x9019 -#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A -#define GL_INTENSITY16_SNORM 0x901B -/* reuse GL_RED_SNORM */ -/* reuse GL_RG_SNORM */ -/* reuse GL_RGB_SNORM */ -/* reuse GL_RGBA_SNORM */ -/* reuse GL_R8_SNORM */ -/* reuse GL_RG8_SNORM */ -/* reuse GL_RGB8_SNORM */ -/* reuse GL_RGBA8_SNORM */ -/* reuse GL_R16_SNORM */ -/* reuse GL_RG16_SNORM */ -/* reuse GL_RGB16_SNORM */ -/* reuse GL_RGBA16_SNORM */ -/* reuse GL_SIGNED_NORMALIZED */ -#endif - -#ifndef GL_AMD_draw_buffers_blend -#endif - -#ifndef GL_APPLE_texture_range -#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 -#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 -#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC -#define GL_STORAGE_PRIVATE_APPLE 0x85BD -/* reuse GL_STORAGE_CACHED_APPLE */ -/* reuse GL_STORAGE_SHARED_APPLE */ -#endif - -#ifndef GL_APPLE_float_pixels -#define GL_HALF_APPLE 0x140B -#define GL_RGBA_FLOAT32_APPLE 0x8814 -#define GL_RGB_FLOAT32_APPLE 0x8815 -#define GL_ALPHA_FLOAT32_APPLE 0x8816 -#define GL_INTENSITY_FLOAT32_APPLE 0x8817 -#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 -#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 -#define GL_RGBA_FLOAT16_APPLE 0x881A -#define GL_RGB_FLOAT16_APPLE 0x881B -#define GL_ALPHA_FLOAT16_APPLE 0x881C -#define GL_INTENSITY_FLOAT16_APPLE 0x881D -#define GL_LUMINANCE_FLOAT16_APPLE 0x881E -#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F -#define GL_COLOR_FLOAT_APPLE 0x8A0F -#endif - -#ifndef GL_APPLE_vertex_program_evaluators -#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 -#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 -#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 -#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 -#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 -#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 -#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 -#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 -#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 -#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 -#endif - -#ifndef GL_APPLE_aux_depth_stencil -#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 -#endif - -#ifndef GL_APPLE_object_purgeable -#define GL_BUFFER_OBJECT_APPLE 0x85B3 -#define GL_RELEASED_APPLE 0x8A19 -#define GL_VOLATILE_APPLE 0x8A1A -#define GL_RETAINED_APPLE 0x8A1B -#define GL_UNDEFINED_APPLE 0x8A1C -#define GL_PURGEABLE_APPLE 0x8A1D -#endif - -#ifndef GL_APPLE_row_bytes -#define GL_PACK_ROW_BYTES_APPLE 0x8A15 -#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 -#endif - -#ifndef GL_APPLE_rgb_422 -#define GL_RGB_422_APPLE 0x8A1F -/* reuse GL_UNSIGNED_SHORT_8_8_APPLE */ -/* reuse GL_UNSIGNED_SHORT_8_8_REV_APPLE */ -#endif - -#ifndef GL_NV_video_capture -#define GL_VIDEO_BUFFER_NV 0x9020 -#define GL_VIDEO_BUFFER_BINDING_NV 0x9021 -#define GL_FIELD_UPPER_NV 0x9022 -#define GL_FIELD_LOWER_NV 0x9023 -#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024 -#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025 -#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026 -#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027 -#define GL_VIDEO_BUFFER_PITCH_NV 0x9028 -#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029 -#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A -#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B -#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C -#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D -#define GL_PARTIAL_SUCCESS_NV 0x902E -#define GL_SUCCESS_NV 0x902F -#define GL_FAILURE_NV 0x9030 -#define GL_YCBYCR8_422_NV 0x9031 -#define GL_YCBAYCR8A_4224_NV 0x9032 -#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033 -#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034 -#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035 -#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036 -#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037 -#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038 -#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039 -#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A -#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B -#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C -#endif - -#ifndef GL_NV_copy_image -#endif - -#ifndef GL_EXT_separate_shader_objects -#define GL_ACTIVE_PROGRAM_EXT 0x8B8D -#endif - -#ifndef GL_NV_parameter_buffer_object2 -#endif - -#ifndef GL_NV_shader_buffer_load -#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D -#define GL_GPU_ADDRESS_NV 0x8F34 -#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 -#endif - -#ifndef GL_NV_vertex_buffer_unified_memory -#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E -#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F -#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 -#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 -#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 -#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 -#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 -#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 -#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 -#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 -#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 -#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 -#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A -#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B -#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C -#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D -#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E -#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F -#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 -#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 -#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 -#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 -#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 -#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 -#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 -#endif - -#ifndef GL_NV_texture_barrier -#endif - -#ifndef GL_AMD_shader_stencil_export -#endif - -#ifndef GL_AMD_seamless_cubemap_per_texture -/* reuse GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB */ -#endif - -#ifndef GL_AMD_conservative_depth -#endif - -#ifndef GL_EXT_shader_image_load_store -#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 -#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 -#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A -#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B -#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C -#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D -#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E -#define GL_IMAGE_1D_EXT 0x904C -#define GL_IMAGE_2D_EXT 0x904D -#define GL_IMAGE_3D_EXT 0x904E -#define GL_IMAGE_2D_RECT_EXT 0x904F -#define GL_IMAGE_CUBE_EXT 0x9050 -#define GL_IMAGE_BUFFER_EXT 0x9051 -#define GL_IMAGE_1D_ARRAY_EXT 0x9052 -#define GL_IMAGE_2D_ARRAY_EXT 0x9053 -#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 -#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 -#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 -#define GL_INT_IMAGE_1D_EXT 0x9057 -#define GL_INT_IMAGE_2D_EXT 0x9058 -#define GL_INT_IMAGE_3D_EXT 0x9059 -#define GL_INT_IMAGE_2D_RECT_EXT 0x905A -#define GL_INT_IMAGE_CUBE_EXT 0x905B -#define GL_INT_IMAGE_BUFFER_EXT 0x905C -#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D -#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E -#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F -#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 -#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 -#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 -#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 -#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 -#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 -#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 -#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 -#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 -#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 -#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A -#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B -#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C -#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D -#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E -#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 -#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 -#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 -#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 -#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 -#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 -#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 -#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 -#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 -#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 -#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 -#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 -#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF -#endif - -#ifndef GL_EXT_vertex_attrib_64bit -/* reuse GL_DOUBLE */ -#define GL_DOUBLE_VEC2_EXT 0x8FFC -#define GL_DOUBLE_VEC3_EXT 0x8FFD -#define GL_DOUBLE_VEC4_EXT 0x8FFE -#define GL_DOUBLE_MAT2_EXT 0x8F46 -#define GL_DOUBLE_MAT3_EXT 0x8F47 -#define GL_DOUBLE_MAT4_EXT 0x8F48 -#define GL_DOUBLE_MAT2x3_EXT 0x8F49 -#define GL_DOUBLE_MAT2x4_EXT 0x8F4A -#define GL_DOUBLE_MAT3x2_EXT 0x8F4B -#define GL_DOUBLE_MAT3x4_EXT 0x8F4C -#define GL_DOUBLE_MAT4x2_EXT 0x8F4D -#define GL_DOUBLE_MAT4x3_EXT 0x8F4E -#endif - -#ifndef GL_NV_gpu_program5 -#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C -#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D -#define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44 -#define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45 -#endif - -#ifndef GL_NV_gpu_shader5 -#define GL_INT64_NV 0x140E -#define GL_UNSIGNED_INT64_NV 0x140F -#define GL_INT8_NV 0x8FE0 -#define GL_INT8_VEC2_NV 0x8FE1 -#define GL_INT8_VEC3_NV 0x8FE2 -#define GL_INT8_VEC4_NV 0x8FE3 -#define GL_INT16_NV 0x8FE4 -#define GL_INT16_VEC2_NV 0x8FE5 -#define GL_INT16_VEC3_NV 0x8FE6 -#define GL_INT16_VEC4_NV 0x8FE7 -#define GL_INT64_VEC2_NV 0x8FE9 -#define GL_INT64_VEC3_NV 0x8FEA -#define GL_INT64_VEC4_NV 0x8FEB -#define GL_UNSIGNED_INT8_NV 0x8FEC -#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED -#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE -#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF -#define GL_UNSIGNED_INT16_NV 0x8FF0 -#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 -#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 -#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 -#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 -#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 -#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 -#define GL_FLOAT16_NV 0x8FF8 -#define GL_FLOAT16_VEC2_NV 0x8FF9 -#define GL_FLOAT16_VEC3_NV 0x8FFA -#define GL_FLOAT16_VEC4_NV 0x8FFB -/* reuse GL_PATCHES */ -#endif - -#ifndef GL_NV_shader_buffer_store -#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010 -/* reuse GL_READ_WRITE */ -/* reuse GL_WRITE_ONLY */ -#endif - -#ifndef GL_NV_tessellation_program5 -#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 -#define GL_TESS_CONTROL_PROGRAM_NV 0x891E -#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F -#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74 -#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75 -#endif - -#ifndef GL_NV_vertex_attrib_integer_64bit -/* reuse GL_INT64_NV */ -/* reuse GL_UNSIGNED_INT64_NV */ -#endif - -#ifndef GL_NV_multisample_coverage -#define GL_COVERAGE_SAMPLES_NV 0x80A9 -#define GL_COLOR_SAMPLES_NV 0x8E20 -#endif - -#ifndef GL_AMD_name_gen_delete -#define GL_DATA_BUFFER_AMD 0x9151 -#define GL_PERFORMANCE_MONITOR_AMD 0x9152 -#define GL_QUERY_OBJECT_AMD 0x9153 -#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154 -#define GL_SAMPLER_OBJECT_AMD 0x9155 -#endif - -#ifndef GL_AMD_debug_output -#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145 -#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147 -#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148 -#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149 -#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A -#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B -#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C -#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D -#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E -#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F -#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 -#endif - -#ifndef GL_NV_vdpau_interop -#define GL_SURFACE_STATE_NV 0x86EB -#define GL_SURFACE_REGISTERED_NV 0x86FD -#define GL_SURFACE_MAPPED_NV 0x8700 -#define GL_WRITE_DISCARD_NV 0x88BE -#endif - -#ifndef GL_AMD_transform_feedback3_lines_triangles -#endif - - -/*************************************************************/ - -#include -#ifndef GL_VERSION_2_0 -/* GL type for program/shader text */ -typedef char GLchar; -#endif - -#ifndef GL_VERSION_1_5 -/* GL types for handling large vertex buffer objects */ -#if defined(__APPLE__) -typedef long GLintptr; -typedef long GLsizeiptr; -#else -typedef ptrdiff_t GLintptr; -typedef ptrdiff_t GLsizeiptr; -#endif -#endif - -#ifndef GL_ARB_vertex_buffer_object -/* GL types for handling large vertex buffer objects */ -#if defined(__APPLE__) -typedef long GLintptrARB; -typedef long GLsizeiptrARB; -#else -typedef ptrdiff_t GLintptrARB; -typedef ptrdiff_t GLsizeiptrARB; -#endif -#endif - -#ifndef GL_ARB_shader_objects -/* GL types for program/shader text and shader object handles */ -typedef char GLcharARB; -#if defined(__APPLE__) -typedef void *GLhandleARB; -#else -typedef unsigned int GLhandleARB; -#endif -#endif - -/* GL type for "half" precision (s10e5) float data in host memory */ -#ifndef GL_ARB_half_float_pixel -typedef unsigned short GLhalfARB; -#endif - -#ifndef GL_NV_half_float -typedef unsigned short GLhalfNV; -#endif - -#ifndef GLEXT_64_TYPES_DEFINED -/* This code block is duplicated in glxext.h, so must be protected */ -#define GLEXT_64_TYPES_DEFINED -/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ -/* (as used in the GL_EXT_timer_query extension). */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#include -#elif defined(__sun__) || defined(__digital__) -#include -#if defined(__STDC__) -#if defined(__arch64__) || defined(_LP64) -typedef long int int64_t; -typedef unsigned long int uint64_t; -#else -typedef long long int int64_t; -typedef unsigned long long int uint64_t; -#endif /* __arch64__ */ -#endif /* __STDC__ */ -#elif defined( __VMS ) || defined(__sgi) -#include -#elif defined(__SCO__) || defined(__USLC__) -#include -#elif defined(__UNIXOS2__) || defined(__SOL64__) -typedef long int int32_t; -typedef long long int int64_t; -typedef unsigned long long int uint64_t; -#elif defined(_WIN32) && defined(__GNUC__) -#include -#elif defined(_WIN32) -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -/* Fallback if nothing above works */ -#include -#endif -#endif - -#ifndef GL_EXT_timer_query -typedef int64_t GLint64EXT; -typedef uint64_t GLuint64EXT; -#endif - -#ifndef GL_ARB_sync -typedef int64_t GLint64; -typedef uint64_t GLuint64; -typedef struct __GLsync *GLsync; -#endif - -#ifndef GL_ARB_cl_event -/* These incomplete types let us declare types compatible with OpenCL's cl_context and cl_event */ -struct _cl_context; -struct _cl_event; -#endif - -#ifndef GL_ARB_debug_output -typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); -#endif - -#ifndef GL_AMD_debug_output -typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); -#endif - -#ifndef GL_NV_vdpau_interop -typedef GLintptr GLvdpauSurfaceNV; -#endif - -#ifndef GL_VERSION_1_2 -#define GL_VERSION_1_2 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -GLAPI void APIENTRY glBlendEquation (GLenum mode); -GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); + * Datatypes + */ +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef signed char GLbyte; /* 1-byte signed */ +typedef short GLshort; /* 2-byte signed */ +typedef int GLint; /* 4-byte signed */ +typedef unsigned char GLubyte; /* 1-byte unsigned */ +typedef unsigned short GLushort; /* 2-byte unsigned */ +typedef unsigned int GLuint; /* 4-byte unsigned */ +typedef int GLsizei; /* 4-byte signed */ +typedef float GLfloat; /* single precision float */ +typedef float GLclampf; /* single precision float in [0,1] */ +typedef double GLdouble; /* double precision float */ +typedef double GLclampd; /* double precision float in [0,1] */ + + + +/* + * Constants + */ + +/* Boolean values */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* Data types */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A + +/* Primitives */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON 0x0009 + +/* Vertex Arrays */ +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D + +/* Matrix Mode */ +#define GL_MATRIX_MODE 0x0BA0 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 + +/* Points */ +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_RANGE 0x0B12 + +/* Lines */ +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 + +/* Polygons */ +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 + +/* Display Lists */ +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_LIST_MODE 0x0B30 + +/* Depth buffer */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_COMPONENT 0x1902 + +/* Lighting */ +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_SHININESS 0x1601 +#define GL_EMISSION 0x1600 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_SHADE_MODEL 0x0B54 +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_NORMALIZE 0x0BA1 + +/* User clipping planes */ +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 + +/* Accumulation buffer */ +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_ACCUM 0x0100 +#define GL_ADD 0x0104 +#define GL_LOAD 0x0101 +#define GL_MULT 0x0103 +#define GL_RETURN 0x0102 + +/* Alpha testing */ +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_ALPHA_TEST_FUNC 0x0BC1 + +/* Blending */ +#define GL_BLEND 0x0BE2 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND_DST 0x0BE0 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 + +/* Render Mode */ +#define GL_FEEDBACK 0x1C01 +#define GL_RENDER 0x1C00 +#define GL_SELECT 0x1C02 + +/* Feedback */ +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 + +/* Selection */ +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 + +/* Fog */ +#define GL_FOG 0x0B60 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_COLOR 0x0B66 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_LINEAR 0x2601 +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 + +/* Logic Ops */ +#define GL_LOGIC_OP 0x0BF1 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_CLEAR 0x1500 +#define GL_SET 0x150F +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_NOOP 0x1505 +#define GL_INVERT 0x150A +#define GL_AND 0x1501 +#define GL_NAND 0x150E +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_XOR 0x1506 +#define GL_EQUIV 0x1509 +#define GL_AND_REVERSE 0x1502 +#define GL_AND_INVERTED 0x1504 +#define GL_OR_REVERSE 0x150B +#define GL_OR_INVERTED 0x150D + +/* Stencil */ +#define GL_STENCIL_BITS 0x0D57 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_INDEX 0x1901 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 + +/* Buffers, Pixel Drawing/Reading */ +#define GL_NONE 0 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +/*GL_FRONT 0x0404 */ +/*GL_BACK 0x0405 */ +/*GL_FRONT_AND_BACK 0x0408 */ +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_COLOR_INDEX 0x1900 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_ALPHA_BITS 0x0D55 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_INDEX_BITS 0x0D51 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_READ_BUFFER 0x0C02 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_BITMAP 0x1A00 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_DITHER 0x0BD0 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 + +/* Implementation limits */ +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B + +/* Gets */ +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_MODE 0x0C30 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_RENDER_MODE 0x0C40 +#define GL_RGBA_MODE 0x0C31 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_VIEWPORT 0x0BA2 + +/* Evaluators */ +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 + +/* Hints */ +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* Scissor box */ +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 + +/* Pixel Mode / Transfer */ +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 + +/* Texture mapping */ +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_LINEAR 0x2400 +#define GL_EYE_PLANE 0x2502 +#define GL_SPHERE_MAP 0x2402 +#define GL_DECAL 0x2101 +#define GL_MODULATE 0x2100 +#define GL_NEAREST 0x2600 +#define GL_REPEAT 0x2901 +#define GL_CLAMP 0x2900 +#define GL_S 0x2000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 + +/* Utility */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* Errors */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 + +/* glPush/PopAttrib bits */ +#define GL_CURRENT_BIT 0x00000001 +#define GL_POINT_BIT 0x00000002 +#define GL_LINE_BIT 0x00000004 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_HINT_BIT 0x00008000 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000FFFFF + + +/* OpenGL 1.1 */ +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_ALL_CLIENT_ATTRIB_BITS 0xFFFFFFFF +#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF + + + +/* + * Miscellaneous + */ + +GLAPI void GLAPIENTRY glClearIndex( GLfloat c ); + +GLAPI void GLAPIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); + +GLAPI void GLAPIENTRY glClear( GLbitfield mask ); + +GLAPI void GLAPIENTRY glIndexMask( GLuint mask ); + +GLAPI void GLAPIENTRY glColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ); + +GLAPI void GLAPIENTRY glAlphaFunc( GLenum func, GLclampf ref ); + +GLAPI void GLAPIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor ); + +GLAPI void GLAPIENTRY glLogicOp( GLenum opcode ); + +GLAPI void GLAPIENTRY glCullFace( GLenum mode ); + +GLAPI void GLAPIENTRY glFrontFace( GLenum mode ); + +GLAPI void GLAPIENTRY glPointSize( GLfloat size ); + +GLAPI void GLAPIENTRY glLineWidth( GLfloat width ); + +GLAPI void GLAPIENTRY glLineStipple( GLint factor, GLushort pattern ); + +GLAPI void GLAPIENTRY glPolygonMode( GLenum face, GLenum mode ); + +GLAPI void GLAPIENTRY glPolygonOffset( GLfloat factor, GLfloat units ); + +GLAPI void GLAPIENTRY glPolygonStipple( const GLubyte *mask ); + +GLAPI void GLAPIENTRY glGetPolygonStipple( GLubyte *mask ); + +GLAPI void GLAPIENTRY glEdgeFlag( GLboolean flag ); + +GLAPI void GLAPIENTRY glEdgeFlagv( const GLboolean *flag ); + +GLAPI void GLAPIENTRY glScissor( GLint x, GLint y, GLsizei width, GLsizei height); + +GLAPI void GLAPIENTRY glClipPlane( GLenum plane, const GLdouble *equation ); + +GLAPI void GLAPIENTRY glGetClipPlane( GLenum plane, GLdouble *equation ); + +GLAPI void GLAPIENTRY glDrawBuffer( GLenum mode ); + +GLAPI void GLAPIENTRY glReadBuffer( GLenum mode ); + +GLAPI void GLAPIENTRY glEnable( GLenum cap ); + +GLAPI void GLAPIENTRY glDisable( GLenum cap ); + +GLAPI GLboolean GLAPIENTRY glIsEnabled( GLenum cap ); + + +GLAPI void GLAPIENTRY glEnableClientState( GLenum cap ); /* 1.1 */ + +GLAPI void GLAPIENTRY glDisableClientState( GLenum cap ); /* 1.1 */ + + +GLAPI void GLAPIENTRY glGetBooleanv( GLenum pname, GLboolean *params ); + +GLAPI void GLAPIENTRY glGetDoublev( GLenum pname, GLdouble *params ); + +GLAPI void GLAPIENTRY glGetFloatv( GLenum pname, GLfloat *params ); + +GLAPI void GLAPIENTRY glGetIntegerv( GLenum pname, GLint *params ); + + +GLAPI void GLAPIENTRY glPushAttrib( GLbitfield mask ); + +GLAPI void GLAPIENTRY glPopAttrib( void ); + + +GLAPI void GLAPIENTRY glPushClientAttrib( GLbitfield mask ); /* 1.1 */ + +GLAPI void GLAPIENTRY glPopClientAttrib( void ); /* 1.1 */ + + +GLAPI GLint GLAPIENTRY glRenderMode( GLenum mode ); + +GLAPI GLenum GLAPIENTRY glGetError( void ); + +GLAPI const GLubyte * GLAPIENTRY glGetString( GLenum name ); + +GLAPI void GLAPIENTRY glFinish( void ); + +GLAPI void GLAPIENTRY glFlush( void ); + +GLAPI void GLAPIENTRY glHint( GLenum target, GLenum mode ); + + +/* + * Depth Buffer + */ + +GLAPI void GLAPIENTRY glClearDepth( GLclampd depth ); + +GLAPI void GLAPIENTRY glDepthFunc( GLenum func ); + +GLAPI void GLAPIENTRY glDepthMask( GLboolean flag ); + +GLAPI void GLAPIENTRY glDepthRange( GLclampd near_val, GLclampd far_val ); + + +/* + * Accumulation Buffer + */ + +GLAPI void GLAPIENTRY glClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); + +GLAPI void GLAPIENTRY glAccum( GLenum op, GLfloat value ); + + +/* + * Transformation + */ + +GLAPI void GLAPIENTRY glMatrixMode( GLenum mode ); + +GLAPI void GLAPIENTRY glOrtho( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble near_val, GLdouble far_val ); + +GLAPI void GLAPIENTRY glFrustum( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble near_val, GLdouble far_val ); + +GLAPI void GLAPIENTRY glViewport( GLint x, GLint y, + GLsizei width, GLsizei height ); + +GLAPI void GLAPIENTRY glPushMatrix( void ); + +GLAPI void GLAPIENTRY glPopMatrix( void ); + +GLAPI void GLAPIENTRY glLoadIdentity( void ); + +GLAPI void GLAPIENTRY glLoadMatrixd( const GLdouble *m ); +GLAPI void GLAPIENTRY glLoadMatrixf( const GLfloat *m ); + +GLAPI void GLAPIENTRY glMultMatrixd( const GLdouble *m ); +GLAPI void GLAPIENTRY glMultMatrixf( const GLfloat *m ); + +GLAPI void GLAPIENTRY glRotated( GLdouble angle, + GLdouble x, GLdouble y, GLdouble z ); +GLAPI void GLAPIENTRY glRotatef( GLfloat angle, + GLfloat x, GLfloat y, GLfloat z ); + +GLAPI void GLAPIENTRY glScaled( GLdouble x, GLdouble y, GLdouble z ); +GLAPI void GLAPIENTRY glScalef( GLfloat x, GLfloat y, GLfloat z ); + +GLAPI void GLAPIENTRY glTranslated( GLdouble x, GLdouble y, GLdouble z ); +GLAPI void GLAPIENTRY glTranslatef( GLfloat x, GLfloat y, GLfloat z ); + + +/* + * Display Lists + */ + +GLAPI GLboolean GLAPIENTRY glIsList( GLuint list ); + +GLAPI void GLAPIENTRY glDeleteLists( GLuint list, GLsizei range ); + +GLAPI GLuint GLAPIENTRY glGenLists( GLsizei range ); + +GLAPI void GLAPIENTRY glNewList( GLuint list, GLenum mode ); + +GLAPI void GLAPIENTRY glEndList( void ); + +GLAPI void GLAPIENTRY glCallList( GLuint list ); + +GLAPI void GLAPIENTRY glCallLists( GLsizei n, GLenum type, + const GLvoid *lists ); + +GLAPI void GLAPIENTRY glListBase( GLuint base ); + + +/* + * Drawing Functions + */ + +GLAPI void GLAPIENTRY glBegin( GLenum mode ); + +GLAPI void GLAPIENTRY glEnd( void ); + + +GLAPI void GLAPIENTRY glVertex2d( GLdouble x, GLdouble y ); +GLAPI void GLAPIENTRY glVertex2f( GLfloat x, GLfloat y ); +GLAPI void GLAPIENTRY glVertex2i( GLint x, GLint y ); +GLAPI void GLAPIENTRY glVertex2s( GLshort x, GLshort y ); + +GLAPI void GLAPIENTRY glVertex3d( GLdouble x, GLdouble y, GLdouble z ); +GLAPI void GLAPIENTRY glVertex3f( GLfloat x, GLfloat y, GLfloat z ); +GLAPI void GLAPIENTRY glVertex3i( GLint x, GLint y, GLint z ); +GLAPI void GLAPIENTRY glVertex3s( GLshort x, GLshort y, GLshort z ); + +GLAPI void GLAPIENTRY glVertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); +GLAPI void GLAPIENTRY glVertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); +GLAPI void GLAPIENTRY glVertex4i( GLint x, GLint y, GLint z, GLint w ); +GLAPI void GLAPIENTRY glVertex4s( GLshort x, GLshort y, GLshort z, GLshort w ); + +GLAPI void GLAPIENTRY glVertex2dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glVertex2fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glVertex2iv( const GLint *v ); +GLAPI void GLAPIENTRY glVertex2sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glVertex3dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glVertex3fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glVertex3iv( const GLint *v ); +GLAPI void GLAPIENTRY glVertex3sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glVertex4dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glVertex4fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glVertex4iv( const GLint *v ); +GLAPI void GLAPIENTRY glVertex4sv( const GLshort *v ); + + +GLAPI void GLAPIENTRY glNormal3b( GLbyte nx, GLbyte ny, GLbyte nz ); +GLAPI void GLAPIENTRY glNormal3d( GLdouble nx, GLdouble ny, GLdouble nz ); +GLAPI void GLAPIENTRY glNormal3f( GLfloat nx, GLfloat ny, GLfloat nz ); +GLAPI void GLAPIENTRY glNormal3i( GLint nx, GLint ny, GLint nz ); +GLAPI void GLAPIENTRY glNormal3s( GLshort nx, GLshort ny, GLshort nz ); + +GLAPI void GLAPIENTRY glNormal3bv( const GLbyte *v ); +GLAPI void GLAPIENTRY glNormal3dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glNormal3fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glNormal3iv( const GLint *v ); +GLAPI void GLAPIENTRY glNormal3sv( const GLshort *v ); + + +GLAPI void GLAPIENTRY glIndexd( GLdouble c ); +GLAPI void GLAPIENTRY glIndexf( GLfloat c ); +GLAPI void GLAPIENTRY glIndexi( GLint c ); +GLAPI void GLAPIENTRY glIndexs( GLshort c ); +GLAPI void GLAPIENTRY glIndexub( GLubyte c ); /* 1.1 */ + +GLAPI void GLAPIENTRY glIndexdv( const GLdouble *c ); +GLAPI void GLAPIENTRY glIndexfv( const GLfloat *c ); +GLAPI void GLAPIENTRY glIndexiv( const GLint *c ); +GLAPI void GLAPIENTRY glIndexsv( const GLshort *c ); +GLAPI void GLAPIENTRY glIndexubv( const GLubyte *c ); /* 1.1 */ + +GLAPI void GLAPIENTRY glColor3b( GLbyte red, GLbyte green, GLbyte blue ); +GLAPI void GLAPIENTRY glColor3d( GLdouble red, GLdouble green, GLdouble blue ); +GLAPI void GLAPIENTRY glColor3f( GLfloat red, GLfloat green, GLfloat blue ); +GLAPI void GLAPIENTRY glColor3i( GLint red, GLint green, GLint blue ); +GLAPI void GLAPIENTRY glColor3s( GLshort red, GLshort green, GLshort blue ); +GLAPI void GLAPIENTRY glColor3ub( GLubyte red, GLubyte green, GLubyte blue ); +GLAPI void GLAPIENTRY glColor3ui( GLuint red, GLuint green, GLuint blue ); +GLAPI void GLAPIENTRY glColor3us( GLushort red, GLushort green, GLushort blue ); + +GLAPI void GLAPIENTRY glColor4b( GLbyte red, GLbyte green, + GLbyte blue, GLbyte alpha ); +GLAPI void GLAPIENTRY glColor4d( GLdouble red, GLdouble green, + GLdouble blue, GLdouble alpha ); +GLAPI void GLAPIENTRY glColor4f( GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ); +GLAPI void GLAPIENTRY glColor4i( GLint red, GLint green, + GLint blue, GLint alpha ); +GLAPI void GLAPIENTRY glColor4s( GLshort red, GLshort green, + GLshort blue, GLshort alpha ); +GLAPI void GLAPIENTRY glColor4ub( GLubyte red, GLubyte green, + GLubyte blue, GLubyte alpha ); +GLAPI void GLAPIENTRY glColor4ui( GLuint red, GLuint green, + GLuint blue, GLuint alpha ); +GLAPI void GLAPIENTRY glColor4us( GLushort red, GLushort green, + GLushort blue, GLushort alpha ); + + +GLAPI void GLAPIENTRY glColor3bv( const GLbyte *v ); +GLAPI void GLAPIENTRY glColor3dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glColor3fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glColor3iv( const GLint *v ); +GLAPI void GLAPIENTRY glColor3sv( const GLshort *v ); +GLAPI void GLAPIENTRY glColor3ubv( const GLubyte *v ); +GLAPI void GLAPIENTRY glColor3uiv( const GLuint *v ); +GLAPI void GLAPIENTRY glColor3usv( const GLushort *v ); + +GLAPI void GLAPIENTRY glColor4bv( const GLbyte *v ); +GLAPI void GLAPIENTRY glColor4dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glColor4fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glColor4iv( const GLint *v ); +GLAPI void GLAPIENTRY glColor4sv( const GLshort *v ); +GLAPI void GLAPIENTRY glColor4ubv( const GLubyte *v ); +GLAPI void GLAPIENTRY glColor4uiv( const GLuint *v ); +GLAPI void GLAPIENTRY glColor4usv( const GLushort *v ); + + +GLAPI void GLAPIENTRY glTexCoord1d( GLdouble s ); +GLAPI void GLAPIENTRY glTexCoord1f( GLfloat s ); +GLAPI void GLAPIENTRY glTexCoord1i( GLint s ); +GLAPI void GLAPIENTRY glTexCoord1s( GLshort s ); + +GLAPI void GLAPIENTRY glTexCoord2d( GLdouble s, GLdouble t ); +GLAPI void GLAPIENTRY glTexCoord2f( GLfloat s, GLfloat t ); +GLAPI void GLAPIENTRY glTexCoord2i( GLint s, GLint t ); +GLAPI void GLAPIENTRY glTexCoord2s( GLshort s, GLshort t ); + +GLAPI void GLAPIENTRY glTexCoord3d( GLdouble s, GLdouble t, GLdouble r ); +GLAPI void GLAPIENTRY glTexCoord3f( GLfloat s, GLfloat t, GLfloat r ); +GLAPI void GLAPIENTRY glTexCoord3i( GLint s, GLint t, GLint r ); +GLAPI void GLAPIENTRY glTexCoord3s( GLshort s, GLshort t, GLshort r ); + +GLAPI void GLAPIENTRY glTexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q ); +GLAPI void GLAPIENTRY glTexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q ); +GLAPI void GLAPIENTRY glTexCoord4i( GLint s, GLint t, GLint r, GLint q ); +GLAPI void GLAPIENTRY glTexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q ); + +GLAPI void GLAPIENTRY glTexCoord1dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glTexCoord1fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glTexCoord1iv( const GLint *v ); +GLAPI void GLAPIENTRY glTexCoord1sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glTexCoord2dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glTexCoord2fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glTexCoord2iv( const GLint *v ); +GLAPI void GLAPIENTRY glTexCoord2sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glTexCoord3dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glTexCoord3fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glTexCoord3iv( const GLint *v ); +GLAPI void GLAPIENTRY glTexCoord3sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glTexCoord4dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glTexCoord4fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glTexCoord4iv( const GLint *v ); +GLAPI void GLAPIENTRY glTexCoord4sv( const GLshort *v ); + + +GLAPI void GLAPIENTRY glRasterPos2d( GLdouble x, GLdouble y ); +GLAPI void GLAPIENTRY glRasterPos2f( GLfloat x, GLfloat y ); +GLAPI void GLAPIENTRY glRasterPos2i( GLint x, GLint y ); +GLAPI void GLAPIENTRY glRasterPos2s( GLshort x, GLshort y ); + +GLAPI void GLAPIENTRY glRasterPos3d( GLdouble x, GLdouble y, GLdouble z ); +GLAPI void GLAPIENTRY glRasterPos3f( GLfloat x, GLfloat y, GLfloat z ); +GLAPI void GLAPIENTRY glRasterPos3i( GLint x, GLint y, GLint z ); +GLAPI void GLAPIENTRY glRasterPos3s( GLshort x, GLshort y, GLshort z ); + +GLAPI void GLAPIENTRY glRasterPos4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); +GLAPI void GLAPIENTRY glRasterPos4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); +GLAPI void GLAPIENTRY glRasterPos4i( GLint x, GLint y, GLint z, GLint w ); +GLAPI void GLAPIENTRY glRasterPos4s( GLshort x, GLshort y, GLshort z, GLshort w ); + +GLAPI void GLAPIENTRY glRasterPos2dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glRasterPos2fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glRasterPos2iv( const GLint *v ); +GLAPI void GLAPIENTRY glRasterPos2sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glRasterPos3dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glRasterPos3fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glRasterPos3iv( const GLint *v ); +GLAPI void GLAPIENTRY glRasterPos3sv( const GLshort *v ); + +GLAPI void GLAPIENTRY glRasterPos4dv( const GLdouble *v ); +GLAPI void GLAPIENTRY glRasterPos4fv( const GLfloat *v ); +GLAPI void GLAPIENTRY glRasterPos4iv( const GLint *v ); +GLAPI void GLAPIENTRY glRasterPos4sv( const GLshort *v ); + + +GLAPI void GLAPIENTRY glRectd( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 ); +GLAPI void GLAPIENTRY glRectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ); +GLAPI void GLAPIENTRY glRecti( GLint x1, GLint y1, GLint x2, GLint y2 ); +GLAPI void GLAPIENTRY glRects( GLshort x1, GLshort y1, GLshort x2, GLshort y2 ); + + +GLAPI void GLAPIENTRY glRectdv( const GLdouble *v1, const GLdouble *v2 ); +GLAPI void GLAPIENTRY glRectfv( const GLfloat *v1, const GLfloat *v2 ); +GLAPI void GLAPIENTRY glRectiv( const GLint *v1, const GLint *v2 ); +GLAPI void GLAPIENTRY glRectsv( const GLshort *v1, const GLshort *v2 ); + + +/* + * Vertex Arrays (1.1) + */ + +GLAPI void GLAPIENTRY glVertexPointer( GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ); + +GLAPI void GLAPIENTRY glNormalPointer( GLenum type, GLsizei stride, + const GLvoid *ptr ); + +GLAPI void GLAPIENTRY glColorPointer( GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ); + +GLAPI void GLAPIENTRY glIndexPointer( GLenum type, GLsizei stride, + const GLvoid *ptr ); + +GLAPI void GLAPIENTRY glTexCoordPointer( GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ); + +GLAPI void GLAPIENTRY glEdgeFlagPointer( GLsizei stride, const GLvoid *ptr ); + +GLAPI void GLAPIENTRY glGetPointerv( GLenum pname, GLvoid **params ); + +GLAPI void GLAPIENTRY glArrayElement( GLint i ); + +GLAPI void GLAPIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count ); + +GLAPI void GLAPIENTRY glDrawElements( GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices ); + +GLAPI void GLAPIENTRY glInterleavedArrays( GLenum format, GLsizei stride, + const GLvoid *pointer ); + +/* + * Lighting + */ + +GLAPI void GLAPIENTRY glShadeModel( GLenum mode ); + +GLAPI void GLAPIENTRY glLightf( GLenum light, GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glLighti( GLenum light, GLenum pname, GLint param ); +GLAPI void GLAPIENTRY glLightfv( GLenum light, GLenum pname, + const GLfloat *params ); +GLAPI void GLAPIENTRY glLightiv( GLenum light, GLenum pname, + const GLint *params ); + +GLAPI void GLAPIENTRY glGetLightfv( GLenum light, GLenum pname, + GLfloat *params ); +GLAPI void GLAPIENTRY glGetLightiv( GLenum light, GLenum pname, + GLint *params ); + +GLAPI void GLAPIENTRY glLightModelf( GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glLightModeli( GLenum pname, GLint param ); +GLAPI void GLAPIENTRY glLightModelfv( GLenum pname, const GLfloat *params ); +GLAPI void GLAPIENTRY glLightModeliv( GLenum pname, const GLint *params ); + +GLAPI void GLAPIENTRY glMaterialf( GLenum face, GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glMateriali( GLenum face, GLenum pname, GLint param ); +GLAPI void GLAPIENTRY glMaterialfv( GLenum face, GLenum pname, const GLfloat *params ); +GLAPI void GLAPIENTRY glMaterialiv( GLenum face, GLenum pname, const GLint *params ); + +GLAPI void GLAPIENTRY glGetMaterialfv( GLenum face, GLenum pname, GLfloat *params ); +GLAPI void GLAPIENTRY glGetMaterialiv( GLenum face, GLenum pname, GLint *params ); + +GLAPI void GLAPIENTRY glColorMaterial( GLenum face, GLenum mode ); + + +/* + * Raster functions + */ + +GLAPI void GLAPIENTRY glPixelZoom( GLfloat xfactor, GLfloat yfactor ); + +GLAPI void GLAPIENTRY glPixelStoref( GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glPixelStorei( GLenum pname, GLint param ); + +GLAPI void GLAPIENTRY glPixelTransferf( GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glPixelTransferi( GLenum pname, GLint param ); + +GLAPI void GLAPIENTRY glPixelMapfv( GLenum map, GLsizei mapsize, + const GLfloat *values ); +GLAPI void GLAPIENTRY glPixelMapuiv( GLenum map, GLsizei mapsize, + const GLuint *values ); +GLAPI void GLAPIENTRY glPixelMapusv( GLenum map, GLsizei mapsize, + const GLushort *values ); + +GLAPI void GLAPIENTRY glGetPixelMapfv( GLenum map, GLfloat *values ); +GLAPI void GLAPIENTRY glGetPixelMapuiv( GLenum map, GLuint *values ); +GLAPI void GLAPIENTRY glGetPixelMapusv( GLenum map, GLushort *values ); + +GLAPI void GLAPIENTRY glBitmap( GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, + GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap ); + +GLAPI void GLAPIENTRY glReadPixels( GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid *pixels ); + +GLAPI void GLAPIENTRY glDrawPixels( GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ); + +GLAPI void GLAPIENTRY glCopyPixels( GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum type ); + +/* + * Stenciling + */ + +GLAPI void GLAPIENTRY glStencilFunc( GLenum func, GLint ref, GLuint mask ); + +GLAPI void GLAPIENTRY glStencilMask( GLuint mask ); + +GLAPI void GLAPIENTRY glStencilOp( GLenum fail, GLenum zfail, GLenum zpass ); + +GLAPI void GLAPIENTRY glClearStencil( GLint s ); + + + +/* + * Texture mapping + */ + +GLAPI void GLAPIENTRY glTexGend( GLenum coord, GLenum pname, GLdouble param ); +GLAPI void GLAPIENTRY glTexGenf( GLenum coord, GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glTexGeni( GLenum coord, GLenum pname, GLint param ); + +GLAPI void GLAPIENTRY glTexGendv( GLenum coord, GLenum pname, const GLdouble *params ); +GLAPI void GLAPIENTRY glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params ); +GLAPI void GLAPIENTRY glTexGeniv( GLenum coord, GLenum pname, const GLint *params ); + +GLAPI void GLAPIENTRY glGetTexGendv( GLenum coord, GLenum pname, GLdouble *params ); +GLAPI void GLAPIENTRY glGetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ); +GLAPI void GLAPIENTRY glGetTexGeniv( GLenum coord, GLenum pname, GLint *params ); + + +GLAPI void GLAPIENTRY glTexEnvf( GLenum target, GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glTexEnvi( GLenum target, GLenum pname, GLint param ); + +GLAPI void GLAPIENTRY glTexEnvfv( GLenum target, GLenum pname, const GLfloat *params ); +GLAPI void GLAPIENTRY glTexEnviv( GLenum target, GLenum pname, const GLint *params ); + +GLAPI void GLAPIENTRY glGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ); +GLAPI void GLAPIENTRY glGetTexEnviv( GLenum target, GLenum pname, GLint *params ); + + +GLAPI void GLAPIENTRY glTexParameterf( GLenum target, GLenum pname, GLfloat param ); +GLAPI void GLAPIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param ); + +GLAPI void GLAPIENTRY glTexParameterfv( GLenum target, GLenum pname, + const GLfloat *params ); +GLAPI void GLAPIENTRY glTexParameteriv( GLenum target, GLenum pname, + const GLint *params ); + +GLAPI void GLAPIENTRY glGetTexParameterfv( GLenum target, + GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexParameteriv( GLenum target, + GLenum pname, GLint *params ); + +GLAPI void GLAPIENTRY glGetTexLevelParameterfv( GLenum target, GLint level, + GLenum pname, GLfloat *params ); +GLAPI void GLAPIENTRY glGetTexLevelParameteriv( GLenum target, GLint level, + GLenum pname, GLint *params ); + + +GLAPI void GLAPIENTRY glTexImage1D( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); + +GLAPI void GLAPIENTRY glTexImage2D( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ); + +GLAPI void GLAPIENTRY glGetTexImage( GLenum target, GLint level, + GLenum format, GLenum type, + GLvoid *pixels ); + + +/* 1.1 functions */ + +GLAPI void GLAPIENTRY glGenTextures( GLsizei n, GLuint *textures ); + +GLAPI void GLAPIENTRY glDeleteTextures( GLsizei n, const GLuint *textures); + +GLAPI void GLAPIENTRY glBindTexture( GLenum target, GLuint texture ); + +GLAPI void GLAPIENTRY glPrioritizeTextures( GLsizei n, + const GLuint *textures, + const GLclampf *priorities ); + +GLAPI GLboolean GLAPIENTRY glAreTexturesResident( GLsizei n, + const GLuint *textures, + GLboolean *residences ); + +GLAPI GLboolean GLAPIENTRY glIsTexture( GLuint texture ); + + +GLAPI void GLAPIENTRY glTexSubImage1D( GLenum target, GLint level, + GLint xoffset, + GLsizei width, GLenum format, + GLenum type, const GLvoid *pixels ); + + +GLAPI void GLAPIENTRY glTexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +GLAPI void GLAPIENTRY glCopyTexImage1D( GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLint border ); + + +GLAPI void GLAPIENTRY glCopyTexImage2D( GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLint border ); + + +GLAPI void GLAPIENTRY glCopyTexSubImage1D( GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, + GLsizei width ); + + +GLAPI void GLAPIENTRY glCopyTexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ); + + +/* + * Evaluators + */ + +GLAPI void GLAPIENTRY glMap1d( GLenum target, GLdouble u1, GLdouble u2, + GLint stride, + GLint order, const GLdouble *points ); +GLAPI void GLAPIENTRY glMap1f( GLenum target, GLfloat u1, GLfloat u2, + GLint stride, + GLint order, const GLfloat *points ); + +GLAPI void GLAPIENTRY glMap2d( GLenum target, + GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, + GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, + const GLdouble *points ); +GLAPI void GLAPIENTRY glMap2f( GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points ); + +GLAPI void GLAPIENTRY glGetMapdv( GLenum target, GLenum query, GLdouble *v ); +GLAPI void GLAPIENTRY glGetMapfv( GLenum target, GLenum query, GLfloat *v ); +GLAPI void GLAPIENTRY glGetMapiv( GLenum target, GLenum query, GLint *v ); + +GLAPI void GLAPIENTRY glEvalCoord1d( GLdouble u ); +GLAPI void GLAPIENTRY glEvalCoord1f( GLfloat u ); + +GLAPI void GLAPIENTRY glEvalCoord1dv( const GLdouble *u ); +GLAPI void GLAPIENTRY glEvalCoord1fv( const GLfloat *u ); + +GLAPI void GLAPIENTRY glEvalCoord2d( GLdouble u, GLdouble v ); +GLAPI void GLAPIENTRY glEvalCoord2f( GLfloat u, GLfloat v ); + +GLAPI void GLAPIENTRY glEvalCoord2dv( const GLdouble *u ); +GLAPI void GLAPIENTRY glEvalCoord2fv( const GLfloat *u ); + +GLAPI void GLAPIENTRY glMapGrid1d( GLint un, GLdouble u1, GLdouble u2 ); +GLAPI void GLAPIENTRY glMapGrid1f( GLint un, GLfloat u1, GLfloat u2 ); + +GLAPI void GLAPIENTRY glMapGrid2d( GLint un, GLdouble u1, GLdouble u2, + GLint vn, GLdouble v1, GLdouble v2 ); +GLAPI void GLAPIENTRY glMapGrid2f( GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ); + +GLAPI void GLAPIENTRY glEvalPoint1( GLint i ); + +GLAPI void GLAPIENTRY glEvalPoint2( GLint i, GLint j ); + +GLAPI void GLAPIENTRY glEvalMesh1( GLenum mode, GLint i1, GLint i2 ); + +GLAPI void GLAPIENTRY glEvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ); + + +/* + * Fog + */ + +GLAPI void GLAPIENTRY glFogf( GLenum pname, GLfloat param ); + +GLAPI void GLAPIENTRY glFogi( GLenum pname, GLint param ); + +GLAPI void GLAPIENTRY glFogfv( GLenum pname, const GLfloat *params ); + +GLAPI void GLAPIENTRY glFogiv( GLenum pname, const GLint *params ); + + +/* + * Selection and Feedback + */ + +GLAPI void GLAPIENTRY glFeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer ); + +GLAPI void GLAPIENTRY glPassThrough( GLfloat token ); + +GLAPI void GLAPIENTRY glSelectBuffer( GLsizei size, GLuint *buffer ); + +GLAPI void GLAPIENTRY glInitNames( void ); + +GLAPI void GLAPIENTRY glLoadName( GLuint name ); + +GLAPI void GLAPIENTRY glPushName( GLuint name ); + +GLAPI void GLAPIENTRY glPopName( void ); + + + +/* + * OpenGL 1.2 + */ + +#define GL_RESCALE_NORMAL 0x803A +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_TEXTURE_BINDING_3D 0x806A + +GLAPI void GLAPIENTRY glDrawRangeElements( GLenum mode, GLuint start, + GLuint end, GLsizei count, GLenum type, const GLvoid *indices ); + +GLAPI void GLAPIENTRY glTexImage3D( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLsizei depth, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ); + +GLAPI void GLAPIENTRY glTexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, + GLenum type, const GLvoid *pixels); + +GLAPI void GLAPIENTRY glCopyTexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height ); + typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif -#ifndef GL_VERSION_1_2_DEPRECATED -#define GL_VERSION_1_2_DEPRECATED 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -GLAPI void APIENTRY glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glGetColorTable (GLenum target, GLenum format, GLenum type, GLvoid *table); -GLAPI void APIENTRY glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -GLAPI void APIENTRY glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -GLAPI void APIENTRY glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -GLAPI void APIENTRY glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params); -GLAPI void APIENTRY glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glConvolutionParameteri (GLenum target, GLenum pname, GLint params); -GLAPI void APIENTRY glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image); -GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -GLAPI void APIENTRY glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); -GLAPI void APIENTRY glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -GLAPI void APIENTRY glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -GLAPI void APIENTRY glMinmax (GLenum target, GLenum internalformat, GLboolean sink); -GLAPI void APIENTRY glResetHistogram (GLenum target); -GLAPI void APIENTRY glResetMinmax (GLenum target); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); -typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); -typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); -typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target); -typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target); -#endif -#ifndef GL_VERSION_1_3 -#define GL_VERSION_1_3 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glActiveTexture (GLenum texture); -GLAPI void APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); -GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, GLvoid *img); -#endif /* GL_GLEXT_PROTOTYPES */ +/* + * GL_ARB_imaging + */ + +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_BLEND_EQUATION 0x8009 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_COLOR 0x8005 + + +GLAPI void GLAPIENTRY glColorTable( GLenum target, GLenum internalformat, + GLsizei width, GLenum format, + GLenum type, const GLvoid *table ); + +GLAPI void GLAPIENTRY glColorSubTable( GLenum target, + GLsizei start, GLsizei count, + GLenum format, GLenum type, + const GLvoid *data ); + +GLAPI void GLAPIENTRY glColorTableParameteriv(GLenum target, GLenum pname, + const GLint *params); + +GLAPI void GLAPIENTRY glColorTableParameterfv(GLenum target, GLenum pname, + const GLfloat *params); + +GLAPI void GLAPIENTRY glCopyColorSubTable( GLenum target, GLsizei start, + GLint x, GLint y, GLsizei width ); + +GLAPI void GLAPIENTRY glCopyColorTable( GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width ); + +GLAPI void GLAPIENTRY glGetColorTable( GLenum target, GLenum format, + GLenum type, GLvoid *table ); + +GLAPI void GLAPIENTRY glGetColorTableParameterfv( GLenum target, GLenum pname, + GLfloat *params ); + +GLAPI void GLAPIENTRY glGetColorTableParameteriv( GLenum target, GLenum pname, + GLint *params ); + +GLAPI void GLAPIENTRY glBlendEquation( GLenum mode ); + +GLAPI void GLAPIENTRY glBlendColor( GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ); + +GLAPI void GLAPIENTRY glHistogram( GLenum target, GLsizei width, + GLenum internalformat, GLboolean sink ); + +GLAPI void GLAPIENTRY glResetHistogram( GLenum target ); + +GLAPI void GLAPIENTRY glGetHistogram( GLenum target, GLboolean reset, + GLenum format, GLenum type, + GLvoid *values ); + +GLAPI void GLAPIENTRY glGetHistogramParameterfv( GLenum target, GLenum pname, + GLfloat *params ); + +GLAPI void GLAPIENTRY glGetHistogramParameteriv( GLenum target, GLenum pname, + GLint *params ); + +GLAPI void GLAPIENTRY glMinmax( GLenum target, GLenum internalformat, + GLboolean sink ); + +GLAPI void GLAPIENTRY glResetMinmax( GLenum target ); + +GLAPI void GLAPIENTRY glGetMinmax( GLenum target, GLboolean reset, + GLenum format, GLenum types, + GLvoid *values ); + +GLAPI void GLAPIENTRY glGetMinmaxParameterfv( GLenum target, GLenum pname, + GLfloat *params ); + +GLAPI void GLAPIENTRY glGetMinmaxParameteriv( GLenum target, GLenum pname, + GLint *params ); + +GLAPI void GLAPIENTRY glConvolutionFilter1D( GLenum target, + GLenum internalformat, GLsizei width, GLenum format, GLenum type, + const GLvoid *image ); + +GLAPI void GLAPIENTRY glConvolutionFilter2D( GLenum target, + GLenum internalformat, GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid *image ); + +GLAPI void GLAPIENTRY glConvolutionParameterf( GLenum target, GLenum pname, + GLfloat params ); + +GLAPI void GLAPIENTRY glConvolutionParameterfv( GLenum target, GLenum pname, + const GLfloat *params ); + +GLAPI void GLAPIENTRY glConvolutionParameteri( GLenum target, GLenum pname, + GLint params ); + +GLAPI void GLAPIENTRY glConvolutionParameteriv( GLenum target, GLenum pname, + const GLint *params ); + +GLAPI void GLAPIENTRY glCopyConvolutionFilter1D( GLenum target, + GLenum internalformat, GLint x, GLint y, GLsizei width ); + +GLAPI void GLAPIENTRY glCopyConvolutionFilter2D( GLenum target, + GLenum internalformat, GLint x, GLint y, GLsizei width, + GLsizei height); + +GLAPI void GLAPIENTRY glGetConvolutionFilter( GLenum target, GLenum format, + GLenum type, GLvoid *image ); + +GLAPI void GLAPIENTRY glGetConvolutionParameterfv( GLenum target, GLenum pname, + GLfloat *params ); + +GLAPI void GLAPIENTRY glGetConvolutionParameteriv( GLenum target, GLenum pname, + GLint *params ); + +GLAPI void GLAPIENTRY glSeparableFilter2D( GLenum target, + GLenum internalformat, GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid *row, const GLvoid *column ); + +GLAPI void GLAPIENTRY glGetSeparableFilter( GLenum target, GLenum format, + GLenum type, GLvoid *row, GLvoid *column, GLvoid *span ); + + + + +/* + * OpenGL 1.3 + */ + +/* multitexture */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +/* texture_cube_map */ +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +/* texture_compression */ +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +/* multisample */ +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_MULTISAMPLE_BIT 0x20000000 +/* transpose_matrix */ +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +/* texture_env_combine */ +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_SUBTRACT 0x84E7 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +/* texture_env_dot3 */ +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +/* texture_border_clamp */ +#define GL_CLAMP_TO_BORDER 0x812D + +GLAPI void GLAPIENTRY glActiveTexture( GLenum texture ); + +GLAPI void GLAPIENTRY glClientActiveTexture( GLenum texture ); + +GLAPI void GLAPIENTRY glCompressedTexImage1D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data ); + +GLAPI void GLAPIENTRY glCompressedTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ); + +GLAPI void GLAPIENTRY glCompressedTexImage3D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data ); + +GLAPI void GLAPIENTRY glCompressedTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data ); + +GLAPI void GLAPIENTRY glCompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ); + +GLAPI void GLAPIENTRY glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data ); + +GLAPI void GLAPIENTRY glGetCompressedTexImage( GLenum target, GLint lod, GLvoid *img ); + +GLAPI void GLAPIENTRY glMultiTexCoord1d( GLenum target, GLdouble s ); + +GLAPI void GLAPIENTRY glMultiTexCoord1dv( GLenum target, const GLdouble *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord1f( GLenum target, GLfloat s ); + +GLAPI void GLAPIENTRY glMultiTexCoord1fv( GLenum target, const GLfloat *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord1i( GLenum target, GLint s ); + +GLAPI void GLAPIENTRY glMultiTexCoord1iv( GLenum target, const GLint *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord1s( GLenum target, GLshort s ); + +GLAPI void GLAPIENTRY glMultiTexCoord1sv( GLenum target, const GLshort *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord2d( GLenum target, GLdouble s, GLdouble t ); + +GLAPI void GLAPIENTRY glMultiTexCoord2dv( GLenum target, const GLdouble *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord2f( GLenum target, GLfloat s, GLfloat t ); + +GLAPI void GLAPIENTRY glMultiTexCoord2fv( GLenum target, const GLfloat *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord2i( GLenum target, GLint s, GLint t ); + +GLAPI void GLAPIENTRY glMultiTexCoord2iv( GLenum target, const GLint *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord2s( GLenum target, GLshort s, GLshort t ); + +GLAPI void GLAPIENTRY glMultiTexCoord2sv( GLenum target, const GLshort *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord3d( GLenum target, GLdouble s, GLdouble t, GLdouble r ); + +GLAPI void GLAPIENTRY glMultiTexCoord3dv( GLenum target, const GLdouble *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, GLfloat r ); + +GLAPI void GLAPIENTRY glMultiTexCoord3fv( GLenum target, const GLfloat *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord3i( GLenum target, GLint s, GLint t, GLint r ); + +GLAPI void GLAPIENTRY glMultiTexCoord3iv( GLenum target, const GLint *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord3s( GLenum target, GLshort s, GLshort t, GLshort r ); + +GLAPI void GLAPIENTRY glMultiTexCoord3sv( GLenum target, const GLshort *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord4d( GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q ); + +GLAPI void GLAPIENTRY glMultiTexCoord4dv( GLenum target, const GLdouble *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ); + +GLAPI void GLAPIENTRY glMultiTexCoord4fv( GLenum target, const GLfloat *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord4i( GLenum target, GLint s, GLint t, GLint r, GLint q ); + +GLAPI void GLAPIENTRY glMultiTexCoord4iv( GLenum target, const GLint *v ); + +GLAPI void GLAPIENTRY glMultiTexCoord4s( GLenum target, GLshort s, GLshort t, GLshort r, GLshort q ); + +GLAPI void GLAPIENTRY glMultiTexCoord4sv( GLenum target, const GLshort *v ); + + +GLAPI void GLAPIENTRY glLoadTransposeMatrixd( const GLdouble m[16] ); + +GLAPI void GLAPIENTRY glLoadTransposeMatrixf( const GLfloat m[16] ); + +GLAPI void GLAPIENTRY glMultTransposeMatrixd( const GLdouble m[16] ); + +GLAPI void GLAPIENTRY glMultTransposeMatrixf( const GLfloat m[16] ); + +GLAPI void GLAPIENTRY glSampleCoverage( GLclampf value, GLboolean invert ); + + typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); @@ -5328,699 +1978,86 @@ typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img); -#endif -#ifndef GL_VERSION_1_3_DEPRECATED -#define GL_VERSION_1_3_DEPRECATED 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glClientActiveTexture (GLenum texture); -GLAPI void APIENTRY glMultiTexCoord1d (GLenum target, GLdouble s); -GLAPI void APIENTRY glMultiTexCoord1dv (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord1f (GLenum target, GLfloat s); -GLAPI void APIENTRY glMultiTexCoord1fv (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord1i (GLenum target, GLint s); -GLAPI void APIENTRY glMultiTexCoord1iv (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord1s (GLenum target, GLshort s); -GLAPI void APIENTRY glMultiTexCoord1sv (GLenum target, const GLshort *v); -GLAPI void APIENTRY glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t); -GLAPI void APIENTRY glMultiTexCoord2dv (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t); -GLAPI void APIENTRY glMultiTexCoord2fv (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord2i (GLenum target, GLint s, GLint t); -GLAPI void APIENTRY glMultiTexCoord2iv (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord2s (GLenum target, GLshort s, GLshort t); -GLAPI void APIENTRY glMultiTexCoord2sv (GLenum target, const GLshort *v); -GLAPI void APIENTRY glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r); -GLAPI void APIENTRY glMultiTexCoord3dv (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r); -GLAPI void APIENTRY glMultiTexCoord3fv (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r); -GLAPI void APIENTRY glMultiTexCoord3iv (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r); -GLAPI void APIENTRY glMultiTexCoord3sv (GLenum target, const GLshort *v); -GLAPI void APIENTRY glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -GLAPI void APIENTRY glMultiTexCoord4dv (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -GLAPI void APIENTRY glMultiTexCoord4fv (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q); -GLAPI void APIENTRY glMultiTexCoord4iv (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -GLAPI void APIENTRY glMultiTexCoord4sv (GLenum target, const GLshort *v); -GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *m); -GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *m); -GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *m); -GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); -typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m); -typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m); -typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m); -typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m); -#endif -#ifndef GL_VERSION_1_4 -#define GL_VERSION_1_4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param); -GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param); -GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); -#endif - -#ifndef GL_VERSION_1_4_DEPRECATED -#define GL_VERSION_1_4_DEPRECATED 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFogCoordf (GLfloat coord); -GLAPI void APIENTRY glFogCoordfv (const GLfloat *coord); -GLAPI void APIENTRY glFogCoordd (GLdouble coord); -GLAPI void APIENTRY glFogCoorddv (const GLdouble *coord); -GLAPI void APIENTRY glFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue); -GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *v); -GLAPI void APIENTRY glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue); -GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *v); -GLAPI void APIENTRY glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue); -GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *v); -GLAPI void APIENTRY glSecondaryColor3i (GLint red, GLint green, GLint blue); -GLAPI void APIENTRY glSecondaryColor3iv (const GLint *v); -GLAPI void APIENTRY glSecondaryColor3s (GLshort red, GLshort green, GLshort blue); -GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *v); -GLAPI void APIENTRY glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue); -GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *v); -GLAPI void APIENTRY glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue); -GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *v); -GLAPI void APIENTRY glSecondaryColor3us (GLushort red, GLushort green, GLushort blue); -GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *v); -GLAPI void APIENTRY glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glWindowPos2d (GLdouble x, GLdouble y); -GLAPI void APIENTRY glWindowPos2dv (const GLdouble *v); -GLAPI void APIENTRY glWindowPos2f (GLfloat x, GLfloat y); -GLAPI void APIENTRY glWindowPos2fv (const GLfloat *v); -GLAPI void APIENTRY glWindowPos2i (GLint x, GLint y); -GLAPI void APIENTRY glWindowPos2iv (const GLint *v); -GLAPI void APIENTRY glWindowPos2s (GLshort x, GLshort y); -GLAPI void APIENTRY glWindowPos2sv (const GLshort *v); -GLAPI void APIENTRY glWindowPos3d (GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glWindowPos3dv (const GLdouble *v); -GLAPI void APIENTRY glWindowPos3f (GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glWindowPos3fv (const GLfloat *v); -GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z); -GLAPI void APIENTRY glWindowPos3iv (const GLint *v); -GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glWindowPos3sv (const GLshort *v); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord); -typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord); -typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord); -typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord); -typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); -typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v); -#endif - -#ifndef GL_VERSION_1_5 -#define GL_VERSION_1_5 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids); -GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); -GLAPI GLboolean APIENTRY glIsQuery (GLuint id); -GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id); -GLAPI void APIENTRY glEndQuery (GLenum target); -GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); -GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer); -GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); -GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); -GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer); -GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); -GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); -GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); -GLAPI GLvoid* APIENTRY glMapBuffer (GLenum target, GLenum access); -GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target); -GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); -typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); -typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id); -typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); -typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target); -typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); -typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); -typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); -typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); -typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); -typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); -typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); -typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); -typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params); -#endif - -#ifndef GL_VERSION_2_0 -#define GL_VERSION_2_0 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); -GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); -GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); -GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); -GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader); -GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); -GLAPI void APIENTRY glCompileShader (GLuint shader); -GLAPI GLuint APIENTRY glCreateProgram (void); -GLAPI GLuint APIENTRY glCreateShader (GLenum type); -GLAPI void APIENTRY glDeleteProgram (GLuint program); -GLAPI void APIENTRY glDeleteShader (GLuint shader); -GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); -GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index); -GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); -GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj); -GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); -GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); -GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); -GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); -GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); -GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params); -GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid* *pointer); -GLAPI GLboolean APIENTRY glIsProgram (GLuint program); -GLAPI GLboolean APIENTRY glIsShader (GLuint shader); -GLAPI void APIENTRY glLinkProgram (GLuint program); -GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); -GLAPI void APIENTRY glUseProgram (GLuint program); -GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0); -GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); -GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GLAPI void APIENTRY glUniform1i (GLint location, GLint v0); -GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); -GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); -GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glValidateProgram (GLuint program); -GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x); -GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); -GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x); -GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y); -GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); -GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y); -GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v); -GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v); -GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); -typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); -typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); -typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); -typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); -typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); -typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); -typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); -typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); -typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); -typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); -typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); -typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); -typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); -typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj); -typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); -typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); -typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); -typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); -typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); -typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); -typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader); -typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); -typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); -typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); -typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); -typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); -typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); -typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); -typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); -typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_VERSION_2_1 -#define GL_VERSION_2_1 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -#endif - -#ifndef GL_VERSION_3_0 -#define GL_VERSION_3_0 1 -/* OpenGL 3.0 also reuses entry points from these extensions: */ -/* ARB_framebuffer_object */ -/* ARB_map_buffer_range */ -/* ARB_vertex_array_object */ -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data); -GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); -GLAPI void APIENTRY glEnablei (GLenum target, GLuint index); -GLAPI void APIENTRY glDisablei (GLenum target, GLuint index); -GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index); -GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode); -GLAPI void APIENTRY glEndTransformFeedback (void); -GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); -GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode); -GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp); -GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode); -GLAPI void APIENTRY glEndConditionalRender (void); -GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); -GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x); -GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y); -GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z); -GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x); -GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y); -GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z); -GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v); -GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); -GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name); -GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); -GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0); -GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); -GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); -GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params); -GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params); -GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); -GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); -GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); -GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -GLAPI const GLubyte * APIENTRY glGetStringi (GLenum name, GLuint index); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); -typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); -typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index); -typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index); -typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index); -typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); -typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void); -typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode); -typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp); -typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode); -typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void); -typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); -typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name); -typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); -typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); -typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); -typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); -typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); -typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); -typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); -#endif - -#ifndef GL_VERSION_3_1 -#define GL_VERSION_3_1 1 -/* OpenGL 3.1 also reuses entry points from these extensions: */ -/* ARB_copy_buffer */ -/* ARB_uniform_buffer_object */ -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer); -GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer); -typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index); -#endif - -#ifndef GL_VERSION_3_2 -#define GL_VERSION_3_2 1 -/* OpenGL 3.2 also reuses entry points from these extensions: */ -/* ARB_draw_elements_base_vertex */ -/* ARB_provoking_vertex */ -/* ARB_sync */ -/* ARB_texture_multisample */ -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); -GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); -GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); -typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); -#endif - -#ifndef GL_VERSION_3_3 -#define GL_VERSION_3_3 1 -/* OpenGL 3.3 also reuses entry points from these extensions: */ -/* ARB_blend_func_extended */ -/* ARB_sampler_objects */ -/* ARB_explicit_attrib_location, but it has none */ -/* ARB_occlusion_query2 (no entry points) */ -/* ARB_shader_bit_encoding (no entry points) */ -/* ARB_texture_rgb10_a2ui (no entry points) */ -/* ARB_texture_swizzle (no entry points) */ -/* ARB_timer_query */ -/* ARB_vertex_type_2_10_10_10_rev */ -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); -#endif - -#ifndef GL_VERSION_4_0 -#define GL_VERSION_4_0 1 -/* OpenGL 4.0 also reuses entry points from these extensions: */ -/* ARB_texture_query_lod (no entry points) */ -/* ARB_draw_indirect */ -/* ARB_gpu_shader5 (no entry points) */ -/* ARB_gpu_shader_fp64 */ -/* ARB_shader_subroutine */ -/* ARB_tessellation_shader */ -/* ARB_texture_buffer_object_rgb32 (no entry points) */ -/* ARB_texture_cube_map_array (no entry points) */ -/* ARB_texture_gather (no entry points) */ -/* ARB_transform_feedback2 */ -/* ARB_transform_feedback3 */ -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMinSampleShading (GLclampf value); -GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode); -GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst); -GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLclampf value); -typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); -typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); -typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -#endif - -#ifndef GL_VERSION_4_1 -#define GL_VERSION_4_1 1 -/* OpenGL 4.1 also reuses entry points from these extensions: */ -/* ARB_ES2_compatibility */ -/* ARB_get_program_binary */ -/* ARB_separate_shader_objects */ -/* ARB_shader_precision (no entry points) */ -/* ARB_vertex_attrib_64bit */ -/* ARB_viewport_array */ -#endif +/* + * GL_ARB_multitexture (ARB extension 1 and OpenGL 1.2.1) + */ #ifndef GL_ARB_multitexture #define GL_ARB_multitexture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glActiveTextureARB (GLenum texture); -GLAPI void APIENTRY glClientActiveTextureARB (GLenum texture); -GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum target, GLdouble s); -GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum target, GLfloat s); -GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum target, GLint s); -GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum target, GLshort s); -GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum target, const GLshort *v); -GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t); -GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t); -GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum target, GLint s, GLint t); -GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t); -GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum target, const GLshort *v); -GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r); -GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r); -GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r); -GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r); -GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum target, const GLshort *v); -GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); -GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum target, const GLdouble *v); -GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum target, const GLfloat *v); -GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q); -GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum target, const GLint *v); -GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); -GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum target, const GLshort *v); -#endif /* GL_GLEXT_PROTOTYPES */ + +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 + +GLAPI void GLAPIENTRY glActiveTextureARB(GLenum texture); +GLAPI void GLAPIENTRY glClientActiveTextureARB(GLenum texture); +GLAPI void GLAPIENTRY glMultiTexCoord1dARB(GLenum target, GLdouble s); +GLAPI void GLAPIENTRY glMultiTexCoord1dvARB(GLenum target, const GLdouble *v); +GLAPI void GLAPIENTRY glMultiTexCoord1fARB(GLenum target, GLfloat s); +GLAPI void GLAPIENTRY glMultiTexCoord1fvARB(GLenum target, const GLfloat *v); +GLAPI void GLAPIENTRY glMultiTexCoord1iARB(GLenum target, GLint s); +GLAPI void GLAPIENTRY glMultiTexCoord1ivARB(GLenum target, const GLint *v); +GLAPI void GLAPIENTRY glMultiTexCoord1sARB(GLenum target, GLshort s); +GLAPI void GLAPIENTRY glMultiTexCoord1svARB(GLenum target, const GLshort *v); +GLAPI void GLAPIENTRY glMultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t); +GLAPI void GLAPIENTRY glMultiTexCoord2dvARB(GLenum target, const GLdouble *v); +GLAPI void GLAPIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t); +GLAPI void GLAPIENTRY glMultiTexCoord2fvARB(GLenum target, const GLfloat *v); +GLAPI void GLAPIENTRY glMultiTexCoord2iARB(GLenum target, GLint s, GLint t); +GLAPI void GLAPIENTRY glMultiTexCoord2ivARB(GLenum target, const GLint *v); +GLAPI void GLAPIENTRY glMultiTexCoord2sARB(GLenum target, GLshort s, GLshort t); +GLAPI void GLAPIENTRY glMultiTexCoord2svARB(GLenum target, const GLshort *v); +GLAPI void GLAPIENTRY glMultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r); +GLAPI void GLAPIENTRY glMultiTexCoord3dvARB(GLenum target, const GLdouble *v); +GLAPI void GLAPIENTRY glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r); +GLAPI void GLAPIENTRY glMultiTexCoord3fvARB(GLenum target, const GLfloat *v); +GLAPI void GLAPIENTRY glMultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r); +GLAPI void GLAPIENTRY glMultiTexCoord3ivARB(GLenum target, const GLint *v); +GLAPI void GLAPIENTRY glMultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r); +GLAPI void GLAPIENTRY glMultiTexCoord3svARB(GLenum target, const GLshort *v); +GLAPI void GLAPIENTRY glMultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void GLAPIENTRY glMultiTexCoord4dvARB(GLenum target, const GLdouble *v); +GLAPI void GLAPIENTRY glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void GLAPIENTRY glMultiTexCoord4fvARB(GLenum target, const GLfloat *v); +GLAPI void GLAPIENTRY glMultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q); +GLAPI void GLAPIENTRY glMultiTexCoord4ivARB(GLenum target, const GLint *v); +GLAPI void GLAPIENTRY glMultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void GLAPIENTRY glMultiTexCoord4svARB(GLenum target, const GLshort *v); + typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture); typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); @@ -6055,5078 +2092,92 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GL typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); -#endif -#ifndef GL_ARB_transpose_matrix -#define GL_ARB_transpose_matrix 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *m); -GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *m); -GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *m); -GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); -typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); -typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); -typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); -#endif +#endif /* GL_ARB_multitexture */ -#ifndef GL_ARB_multisample -#define GL_ARB_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glSampleCoverageARB (GLclampf value, GLboolean invert); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); -#endif -#ifndef GL_ARB_texture_env_add -#define GL_ARB_texture_env_add 1 -#endif -#ifndef GL_ARB_texture_cube_map -#define GL_ARB_texture_cube_map 1 -#endif - -#ifndef GL_ARB_texture_compression -#define GL_ARB_texture_compression 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img); -#endif - -#ifndef GL_ARB_texture_border_clamp -#define GL_ARB_texture_border_clamp 1 -#endif - -#ifndef GL_ARB_point_parameters -#define GL_ARB_point_parameters 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPointParameterfARB (GLenum pname, GLfloat param); -GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params); -#endif - -#ifndef GL_ARB_vertex_blend -#define GL_ARB_vertex_blend 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glWeightbvARB (GLint size, const GLbyte *weights); -GLAPI void APIENTRY glWeightsvARB (GLint size, const GLshort *weights); -GLAPI void APIENTRY glWeightivARB (GLint size, const GLint *weights); -GLAPI void APIENTRY glWeightfvARB (GLint size, const GLfloat *weights); -GLAPI void APIENTRY glWeightdvARB (GLint size, const GLdouble *weights); -GLAPI void APIENTRY glWeightubvARB (GLint size, const GLubyte *weights); -GLAPI void APIENTRY glWeightusvARB (GLint size, const GLushort *weights); -GLAPI void APIENTRY glWeightuivARB (GLint size, const GLuint *weights); -GLAPI void APIENTRY glWeightPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glVertexBlendARB (GLint count); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights); -typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights); -typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights); -typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights); -typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights); -typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights); -typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights); -typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights); -typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count); -#endif - -#ifndef GL_ARB_matrix_palette -#define GL_ARB_matrix_palette 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint index); -GLAPI void APIENTRY glMatrixIndexubvARB (GLint size, const GLubyte *indices); -GLAPI void APIENTRY glMatrixIndexusvARB (GLint size, const GLushort *indices); -GLAPI void APIENTRY glMatrixIndexuivARB (GLint size, const GLuint *indices); -GLAPI void APIENTRY glMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); -typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices); -typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices); -typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices); -typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_ARB_texture_env_combine -#define GL_ARB_texture_env_combine 1 -#endif - -#ifndef GL_ARB_texture_env_crossbar -#define GL_ARB_texture_env_crossbar 1 -#endif - -#ifndef GL_ARB_texture_env_dot3 -#define GL_ARB_texture_env_dot3 1 -#endif - -#ifndef GL_ARB_texture_mirrored_repeat -#define GL_ARB_texture_mirrored_repeat 1 -#endif - -#ifndef GL_ARB_depth_texture -#define GL_ARB_depth_texture 1 -#endif - -#ifndef GL_ARB_shadow -#define GL_ARB_shadow 1 -#endif - -#ifndef GL_ARB_shadow_ambient -#define GL_ARB_shadow_ambient 1 -#endif - -#ifndef GL_ARB_window_pos -#define GL_ARB_window_pos 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glWindowPos2dARB (GLdouble x, GLdouble y); -GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *v); -GLAPI void APIENTRY glWindowPos2fARB (GLfloat x, GLfloat y); -GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *v); -GLAPI void APIENTRY glWindowPos2iARB (GLint x, GLint y); -GLAPI void APIENTRY glWindowPos2ivARB (const GLint *v); -GLAPI void APIENTRY glWindowPos2sARB (GLshort x, GLshort y); -GLAPI void APIENTRY glWindowPos2svARB (const GLshort *v); -GLAPI void APIENTRY glWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *v); -GLAPI void APIENTRY glWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *v); -GLAPI void APIENTRY glWindowPos3iARB (GLint x, GLint y, GLint z); -GLAPI void APIENTRY glWindowPos3ivARB (const GLint *v); -GLAPI void APIENTRY glWindowPos3sARB (GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); -typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v); -#endif - -#ifndef GL_ARB_vertex_program -#define GL_ARB_vertex_program 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttrib1dARB (GLuint index, GLdouble x); -GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib1fARB (GLuint index, GLfloat x); -GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib1sARB (GLuint index, GLshort x); -GLAPI void APIENTRY glVertexAttrib1svARB (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y); -GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y); -GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib2sARB (GLuint index, GLshort x, GLshort y); -GLAPI void APIENTRY glVertexAttrib2svARB (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glVertexAttrib3svARB (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint index, const GLushort *v); -GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void APIENTRY glVertexAttrib4svARB (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint index, const GLushort *v); -GLAPI void APIENTRY glVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint index); -GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint index); -GLAPI void APIENTRY glProgramStringARB (GLenum target, GLenum format, GLsizei len, const GLvoid *string); -GLAPI void APIENTRY glBindProgramARB (GLenum target, GLuint program); -GLAPI void APIENTRY glDeleteProgramsARB (GLsizei n, const GLuint *programs); -GLAPI void APIENTRY glGenProgramsARB (GLsizei n, GLuint *programs); -GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params); -GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params); -GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params); -GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params); -GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params); -GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params); -GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params); -GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params); -GLAPI void APIENTRY glGetProgramivARB (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetProgramStringARB (GLenum target, GLenum pname, GLvoid *string); -GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params); -GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint index, GLenum pname, GLvoid* *pointer); -GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); -typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); -typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); -typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); -typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); -typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); -typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); -typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); -typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); -typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); -typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer); -typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program); -#endif - -#ifndef GL_ARB_fragment_program -#define GL_ARB_fragment_program 1 -/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */ -#endif - -#ifndef GL_ARB_vertex_buffer_object -#define GL_ARB_vertex_buffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindBufferARB (GLenum target, GLuint buffer); -GLAPI void APIENTRY glDeleteBuffersARB (GLsizei n, const GLuint *buffers); -GLAPI void APIENTRY glGenBuffersARB (GLsizei n, GLuint *buffers); -GLAPI GLboolean APIENTRY glIsBufferARB (GLuint buffer); -GLAPI void APIENTRY glBufferDataARB (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); -GLAPI void APIENTRY glBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); -GLAPI void APIENTRY glGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); -GLAPI GLvoid* APIENTRY glMapBufferARB (GLenum target, GLenum access); -GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum target); -GLAPI void APIENTRY glGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetBufferPointervARB (GLenum target, GLenum pname, GLvoid* *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); -typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); -typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); -typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); -typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); -typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); -typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); -typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target); -typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params); -#endif - -#ifndef GL_ARB_occlusion_query -#define GL_ARB_occlusion_query 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGenQueriesARB (GLsizei n, GLuint *ids); -GLAPI void APIENTRY glDeleteQueriesARB (GLsizei n, const GLuint *ids); -GLAPI GLboolean APIENTRY glIsQueryARB (GLuint id); -GLAPI void APIENTRY glBeginQueryARB (GLenum target, GLuint id); -GLAPI void APIENTRY glEndQueryARB (GLenum target); -GLAPI void APIENTRY glGetQueryivARB (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids); -typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids); -typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id); -typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); -typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target); -typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params); -#endif - -#ifndef GL_ARB_shader_objects -#define GL_ARB_shader_objects 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB obj); -GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum pname); -GLAPI void APIENTRY glDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj); -GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum shaderType); -GLAPI void APIENTRY glShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); -GLAPI void APIENTRY glCompileShaderARB (GLhandleARB shaderObj); -GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void); -GLAPI void APIENTRY glAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj); -GLAPI void APIENTRY glLinkProgramARB (GLhandleARB programObj); -GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB programObj); -GLAPI void APIENTRY glValidateProgramARB (GLhandleARB programObj); -GLAPI void APIENTRY glUniform1fARB (GLint location, GLfloat v0); -GLAPI void APIENTRY glUniform2fARB (GLint location, GLfloat v0, GLfloat v1); -GLAPI void APIENTRY glUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GLAPI void APIENTRY glUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GLAPI void APIENTRY glUniform1iARB (GLint location, GLint v0); -GLAPI void APIENTRY glUniform2iARB (GLint location, GLint v0, GLint v1); -GLAPI void APIENTRY glUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2); -GLAPI void APIENTRY glUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GLAPI void APIENTRY glUniform1fvARB (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform2fvARB (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform3fvARB (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform4fvARB (GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glUniform1ivARB (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniform2ivARB (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniform3ivARB (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniform4ivARB (GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); -GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); -GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name); -GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); -GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params); -GLAPI void APIENTRY glGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params); -GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); -typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname); -typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); -typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); -typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); -typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); -typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void); -typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); -typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); -typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); -typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); -typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); -typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); -typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); -typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); -typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); -typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); -typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); -typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); -typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); -typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); -typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); -typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); -#endif - -#ifndef GL_ARB_vertex_shader -#define GL_ARB_vertex_shader 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name); -GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); -GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); -typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); -typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); -#endif - -#ifndef GL_ARB_fragment_shader -#define GL_ARB_fragment_shader 1 -#endif - -#ifndef GL_ARB_shading_language_100 -#define GL_ARB_shading_language_100 1 -#endif - -#ifndef GL_ARB_texture_non_power_of_two -#define GL_ARB_texture_non_power_of_two 1 -#endif - -#ifndef GL_ARB_point_sprite -#define GL_ARB_point_sprite 1 -#endif - -#ifndef GL_ARB_fragment_program_shadow -#define GL_ARB_fragment_program_shadow 1 -#endif - -#ifndef GL_ARB_draw_buffers -#define GL_ARB_draw_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawBuffersARB (GLsizei n, const GLenum *bufs); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs); -#endif - -#ifndef GL_ARB_texture_rectangle -#define GL_ARB_texture_rectangle 1 -#endif - -#ifndef GL_ARB_color_buffer_float -#define GL_ARB_color_buffer_float 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); -#endif - -#ifndef GL_ARB_half_float_pixel -#define GL_ARB_half_float_pixel 1 -#endif - -#ifndef GL_ARB_texture_float -#define GL_ARB_texture_float 1 -#endif - -#ifndef GL_ARB_pixel_buffer_object -#define GL_ARB_pixel_buffer_object 1 -#endif - -#ifndef GL_ARB_depth_buffer_float -#define GL_ARB_depth_buffer_float 1 -#endif - -#ifndef GL_ARB_draw_instanced -#define GL_ARB_draw_instanced 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif - -#ifndef GL_ARB_framebuffer_object -#define GL_ARB_framebuffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer); -GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); -GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); -GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); -GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer); -GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); -GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); -GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); -GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target); -GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); -GLAPI void APIENTRY glGenerateMipmap (GLenum target); -GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); -typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); -typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); -typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); -typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); -typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); -typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); -typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target); -typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -#endif - -#ifndef GL_ARB_framebuffer_sRGB -#define GL_ARB_framebuffer_sRGB 1 -#endif - -#ifndef GL_ARB_geometry_shader4 -#define GL_ARB_geometry_shader4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value); -GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level); -GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); -#endif - -#ifndef GL_ARB_half_float_vertex -#define GL_ARB_half_float_vertex 1 -#endif - -#ifndef GL_ARB_instanced_arrays -#define GL_ARB_instanced_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); -#endif - -#ifndef GL_ARB_map_buffer_range -#define GL_ARB_map_buffer_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLvoid* APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); -#endif - -#ifndef GL_ARB_texture_buffer_object -#define GL_ARB_texture_buffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); -#endif - -#ifndef GL_ARB_texture_compression_rgtc -#define GL_ARB_texture_compression_rgtc 1 -#endif - -#ifndef GL_ARB_texture_rg -#define GL_ARB_texture_rg 1 -#endif - -#ifndef GL_ARB_vertex_array_object -#define GL_ARB_vertex_array_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindVertexArray (GLuint array); -GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); -GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); -GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); -typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); -typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); -typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array); -#endif - -#ifndef GL_ARB_uniform_buffer_object -#define GL_ARB_uniform_buffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices); -GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); -GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); -GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); -GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices); -typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); -typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); -typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); -typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); -#endif - -#ifndef GL_ARB_compatibility -#define GL_ARB_compatibility 1 -#endif - -#ifndef GL_ARB_copy_buffer -#define GL_ARB_copy_buffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -#endif - -#ifndef GL_ARB_shader_texture_lod -#define GL_ARB_shader_texture_lod 1 -#endif - -#ifndef GL_ARB_depth_clamp -#define GL_ARB_depth_clamp 1 -#endif - -#ifndef GL_ARB_draw_elements_base_vertex -#define GL_ARB_draw_elements_base_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); -GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); -GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex); -GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); -typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); -typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex); -typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex); -#endif - -#ifndef GL_ARB_fragment_coord_conventions -#define GL_ARB_fragment_coord_conventions 1 -#endif - -#ifndef GL_ARB_provoking_vertex -#define GL_ARB_provoking_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProvokingVertex (GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode); -#endif - -#ifndef GL_ARB_seamless_cube_map -#define GL_ARB_seamless_cube_map 1 -#endif - -#ifndef GL_ARB_sync -#define GL_ARB_sync 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags); -GLAPI GLboolean APIENTRY glIsSync (GLsync sync); -GLAPI void APIENTRY glDeleteSync (GLsync sync); -GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *params); -GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); -typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync); -typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); -typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params); -typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif - -#ifndef GL_ARB_texture_multisample -#define GL_ARB_texture_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); -GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); -GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val); -GLAPI void APIENTRY glSampleMaski (GLuint index, GLbitfield mask); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); -typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); -typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); -typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); -#endif - -#ifndef GL_ARB_vertex_array_bgra -#define GL_ARB_vertex_array_bgra 1 -#endif - -#ifndef GL_ARB_draw_buffers_blend -#define GL_ARB_draw_buffers_blend 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode); -GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst); -GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); -typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); -typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -#endif - -#ifndef GL_ARB_sample_shading -#define GL_ARB_sample_shading 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMinSampleShadingARB (GLclampf value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value); -#endif - -#ifndef GL_ARB_texture_cube_map_array -#define GL_ARB_texture_cube_map_array 1 -#endif - -#ifndef GL_ARB_texture_gather -#define GL_ARB_texture_gather 1 -#endif - -#ifndef GL_ARB_texture_query_lod -#define GL_ARB_texture_query_lod 1 -#endif - -#ifndef GL_ARB_shading_language_include -#define GL_ARB_shading_language_include 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); -GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name); -GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar* *path, const GLint *length); -GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name); -GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); -GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); -typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); -typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar* *path, const GLint *length); -typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); -typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); -typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params); -#endif - -#ifndef GL_ARB_texture_compression_bptc -#define GL_ARB_texture_compression_bptc 1 -#endif - -#ifndef GL_ARB_blend_func_extended -#define GL_ARB_blend_func_extended 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); -GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); -typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name); -#endif - -#ifndef GL_ARB_explicit_attrib_location -#define GL_ARB_explicit_attrib_location 1 -#endif - -#ifndef GL_ARB_occlusion_query2 -#define GL_ARB_occlusion_query2 1 -#endif - -#ifndef GL_ARB_sampler_objects -#define GL_ARB_sampler_objects 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); -GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); -GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler); -GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); -GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); -GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); -GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); -GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); -GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param); -GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param); -GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); -typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); -typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); -typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); -typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); -typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); -typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param); -typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param); -typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params); -#endif - -#ifndef GL_ARB_texture_rgb10_a2ui -#define GL_ARB_texture_rgb10_a2ui 1 -#endif - -#ifndef GL_ARB_texture_swizzle -#define GL_ARB_texture_swizzle 1 -#endif - -#ifndef GL_ARB_timer_query -#define GL_ARB_timer_query 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target); -GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params); -GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params); -#endif - -#ifndef GL_ARB_vertex_type_2_10_10_10_rev -#define GL_ARB_vertex_type_2_10_10_10_rev 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value); -GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value); -GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value); -GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value); -GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value); -GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value); -GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords); -GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords); -GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords); -GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords); -GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords); -GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords); -GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords); -GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords); -GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords); -GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords); -GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords); -GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords); -GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords); -GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords); -GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords); -GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords); -GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords); -GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords); -GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color); -GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color); -GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color); -GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color); -GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color); -GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color); -GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); -GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); -GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); -GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); -GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value); -typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value); -typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value); -typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords); -typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords); -typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color); -typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color); -typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color); -typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color); -typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); -typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); -typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); -#endif - -#ifndef GL_ARB_draw_indirect -#define GL_ARB_draw_indirect 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const GLvoid *indirect); -GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const GLvoid *indirect); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect); -typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect); -#endif - -#ifndef GL_ARB_gpu_shader5 -#define GL_ARB_gpu_shader5 1 -#endif - -#ifndef GL_ARB_gpu_shader_fp64 -#define GL_ARB_gpu_shader_fp64 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x); -GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y); -GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); -typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params); -#endif - -#ifndef GL_ARB_shader_subroutine -#define GL_ARB_shader_subroutine 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name); -GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name); -GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); -GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); -GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); -GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices); -GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params); -GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name); -typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name); -typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); -typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); -typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); -typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices); -typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values); -#endif - -#ifndef GL_ARB_tessellation_shader -#define GL_ARB_tessellation_shader 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value); -GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); -typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values); -#endif - -#ifndef GL_ARB_texture_buffer_object_rgb32 -#define GL_ARB_texture_buffer_object_rgb32 1 -#endif - -#ifndef GL_ARB_transform_feedback2 -#define GL_ARB_transform_feedback2 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id); -GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); -GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); -GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id); -GLAPI void APIENTRY glPauseTransformFeedback (void); -GLAPI void APIENTRY glResumeTransformFeedback (void); -GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); -typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); -typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); -typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); -typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); -typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); -typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); -#endif - -#ifndef GL_ARB_transform_feedback3 -#define GL_ARB_transform_feedback3 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream); -GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id); -GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index); -GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); -typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); -typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); -typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); -#endif - -#ifndef GL_ARB_ES2_compatibility -#define GL_ARB_ES2_compatibility 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glReleaseShaderCompiler (void); -GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length); -GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); -GLAPI void APIENTRY glDepthRangef (GLclampf n, GLclampf f); -GLAPI void APIENTRY glClearDepthf (GLclampf d); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); -typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length); -typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); -typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); -typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLclampf d); -#endif - -#ifndef GL_ARB_get_program_binary -#define GL_ARB_get_program_binary 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); -GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length); -GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); -typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); -#endif - -#ifndef GL_ARB_separate_shader_objects -#define GL_ARB_separate_shader_objects 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program); -GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program); -GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar* *strings); -GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline); -GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines); -GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines); -GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline); -GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params); -GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0); -GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0); -GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0); -GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0); -GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1); -GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1); -GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1); -GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1); -GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); -GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); -GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline); -GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); -typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); -typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar* *strings); -typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines); -typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); -typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -#endif - -#ifndef GL_ARB_vertex_attrib_64bit -#define GL_ARB_vertex_attrib_64bit 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x); -GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y); -GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params); -#endif - -#ifndef GL_ARB_viewport_array -#define GL_ARB_viewport_array 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v); -GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); -GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v); -GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); -GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v); -GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLclampd *v); -GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLclampd n, GLclampd f); -GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data); -GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v); -typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); -typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v); -typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd *v); -typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f); -typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); -typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); -#endif - -#ifndef GL_ARB_cl_event -#define GL_ARB_cl_event 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context * context, struct _cl_event * event, GLbitfield flags); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context * context, struct _cl_event * event, GLbitfield flags); -#endif - -#ifndef GL_ARB_debug_output -#define GL_ARB_debug_output 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const GLvoid *userParam); -GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam); -typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -#endif - -#ifndef GL_ARB_robustness -#define GL_ARB_robustness 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void); -GLAPI void APIENTRY glGetnMapdvARB (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v); -GLAPI void APIENTRY glGetnMapfvARB (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v); -GLAPI void APIENTRY glGetnMapivARB (GLenum target, GLenum query, GLsizei bufSize, GLint *v); -GLAPI void APIENTRY glGetnPixelMapfvARB (GLenum map, GLsizei bufSize, GLfloat *values); -GLAPI void APIENTRY glGetnPixelMapuivARB (GLenum map, GLsizei bufSize, GLuint *values); -GLAPI void APIENTRY glGetnPixelMapusvARB (GLenum map, GLsizei bufSize, GLushort *values); -GLAPI void APIENTRY glGetnPolygonStippleARB (GLsizei bufSize, GLubyte *pattern); -GLAPI void APIENTRY glGetnColorTableARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *table); -GLAPI void APIENTRY glGetnConvolutionFilterARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *image); -GLAPI void APIENTRY glGetnSeparableFilterARB (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, GLvoid *row, GLsizei columnBufSize, GLvoid *column, GLvoid *span); -GLAPI void APIENTRY glGetnHistogramARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values); -GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values); -GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *img); -GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data); -GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, GLvoid *img); -GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); -GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params); -GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params); -GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void); -typedef void (APIENTRYP PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v); -typedef void (APIENTRYP PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v); -typedef void (APIENTRYP PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v); -typedef void (APIENTRYP PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values); -typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values); -typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values); -typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern); -typedef void (APIENTRYP PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *table); -typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *image); -typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, GLvoid *row, GLsizei columnBufSize, GLvoid *column, GLvoid *span); -typedef void (APIENTRYP PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values); -typedef void (APIENTRYP PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, GLvoid *values); -typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *img); -typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data); -typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, GLvoid *img); -typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); -typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); -typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); -typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); -#endif - -#ifndef GL_ARB_shader_stencil_export -#define GL_ARB_shader_stencil_export 1 -#endif - -#ifndef GL_EXT_abgr -#define GL_EXT_abgr 1 -#endif - -#ifndef GL_EXT_blend_color -#define GL_EXT_blend_color 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendColorEXT (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -#endif - -#ifndef GL_EXT_polygon_offset -#define GL_EXT_polygon_offset 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); -#endif - -#ifndef GL_EXT_texture -#define GL_EXT_texture 1 -#endif - -#ifndef GL_EXT_texture3D -#define GL_EXT_texture3D 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -#endif - -#ifndef GL_SGIS_texture_filter4 -#define GL_SGIS_texture_filter4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights); -GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); -typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); -#endif - -#ifndef GL_EXT_subtexture -#define GL_EXT_subtexture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -#endif - -#ifndef GL_EXT_copy_texture -#define GL_EXT_copy_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -#endif - -#ifndef GL_EXT_histogram -#define GL_EXT_histogram 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -GLAPI void APIENTRY glMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink); -GLAPI void APIENTRY glResetHistogramEXT (GLenum target); -GLAPI void APIENTRY glResetMinmaxEXT (GLenum target); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); -typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); -typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); -typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); -typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target); -#endif - -#ifndef GL_EXT_convolution -#define GL_EXT_convolution 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params); -GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params); -GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *image); -GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); -typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); -typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); -#endif - -#ifndef GL_SGI_color_matrix -#define GL_SGI_color_matrix 1 -#endif - -#ifndef GL_SGI_color_table -#define GL_SGI_color_table 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glGetColorTableSGI (GLenum target, GLenum format, GLenum type, GLvoid *table); -GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); -#endif - -#ifndef GL_SGIX_pixel_texture -#define GL_SGIX_pixel_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPixelTexGenSGIX (GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); -#endif - -#ifndef GL_SGIS_pixel_texture -#define GL_SGIS_pixel_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum pname, GLint param); -GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum pname, const GLint *params); -GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum pname, GLfloat param); -GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params); -GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); -#endif - -#ifndef GL_SGIS_texture4D -#define GL_SGIS_texture4D 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); -#endif - -#ifndef GL_SGI_texture_color_table -#define GL_SGI_texture_color_table 1 -#endif - -#ifndef GL_EXT_cmyka -#define GL_EXT_cmyka 1 -#endif - -#ifndef GL_EXT_texture_object -#define GL_EXT_texture_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences); -GLAPI void APIENTRY glBindTextureEXT (GLenum target, GLuint texture); -GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures); -GLAPI void APIENTRY glGenTexturesEXT (GLsizei n, GLuint *textures); -GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint texture); -GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); -typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); -typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); -typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); -typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture); -typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); -#endif - -#ifndef GL_SGIS_detail_texture -#define GL_SGIS_detail_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points); -GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum target, GLfloat *points); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); -typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); -#endif - -#ifndef GL_SGIS_sharpen_texture -#define GL_SGIS_sharpen_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points); -GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum target, GLfloat *points); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); -typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); -#endif - -#ifndef GL_EXT_packed_pixels -#define GL_EXT_packed_pixels 1 -#endif - -#ifndef GL_SGIS_texture_lod -#define GL_SGIS_texture_lod 1 -#endif - -#ifndef GL_SGIS_multisample -#define GL_SGIS_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glSampleMaskSGIS (GLclampf value, GLboolean invert); -GLAPI void APIENTRY glSamplePatternSGIS (GLenum pattern); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); -typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); -#endif - -#ifndef GL_EXT_rescale_normal -#define GL_EXT_rescale_normal 1 -#endif - -#ifndef GL_EXT_vertex_array -#define GL_EXT_vertex_array 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glArrayElementEXT (GLint i); -GLAPI void APIENTRY glColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -GLAPI void APIENTRY glDrawArraysEXT (GLenum mode, GLint first, GLsizei count); -GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer); -GLAPI void APIENTRY glGetPointervEXT (GLenum pname, GLvoid* *params); -GLAPI void APIENTRY glIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -GLAPI void APIENTRY glNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -GLAPI void APIENTRY glTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -GLAPI void APIENTRY glVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i); -typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); -typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); -typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); -typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -#endif - -#ifndef GL_EXT_misc_attribute -#define GL_EXT_misc_attribute 1 -#endif - -#ifndef GL_SGIS_generate_mipmap -#define GL_SGIS_generate_mipmap 1 -#endif - -#ifndef GL_SGIX_clipmap -#define GL_SGIX_clipmap 1 -#endif - -#ifndef GL_SGIX_shadow -#define GL_SGIX_shadow 1 -#endif - -#ifndef GL_SGIS_texture_edge_clamp -#define GL_SGIS_texture_edge_clamp 1 -#endif - -#ifndef GL_SGIS_texture_border_clamp -#define GL_SGIS_texture_border_clamp 1 -#endif - -#ifndef GL_EXT_blend_minmax -#define GL_EXT_blend_minmax 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendEquationEXT (GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); -#endif - -#ifndef GL_EXT_blend_subtract -#define GL_EXT_blend_subtract 1 -#endif - -#ifndef GL_EXT_blend_logic_op -#define GL_EXT_blend_logic_op 1 -#endif - -#ifndef GL_SGIX_interlace -#define GL_SGIX_interlace 1 -#endif - -#ifndef GL_SGIX_pixel_tiles -#define GL_SGIX_pixel_tiles 1 -#endif - -#ifndef GL_SGIX_texture_select -#define GL_SGIX_texture_select 1 -#endif - -#ifndef GL_SGIX_sprite -#define GL_SGIX_sprite 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum pname, GLfloat param); -GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum pname, GLint param); -GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum pname, const GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); -#endif - -#ifndef GL_SGIX_texture_multi_buffer -#define GL_SGIX_texture_multi_buffer 1 -#endif - -#ifndef GL_EXT_point_parameters -#define GL_EXT_point_parameters 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPointParameterfEXT (GLenum pname, GLfloat param); -GLAPI void APIENTRY glPointParameterfvEXT (GLenum pname, const GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); -#endif - -#ifndef GL_SGIS_point_parameters -#define GL_SGIS_point_parameters 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPointParameterfSGIS (GLenum pname, GLfloat param); -GLAPI void APIENTRY glPointParameterfvSGIS (GLenum pname, const GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); -#endif - -#ifndef GL_SGIX_instruments -#define GL_SGIX_instruments 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLint APIENTRY glGetInstrumentsSGIX (void); -GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei size, GLint *buffer); -GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *marker_p); -GLAPI void APIENTRY glReadInstrumentsSGIX (GLint marker); -GLAPI void APIENTRY glStartInstrumentsSGIX (void); -GLAPI void APIENTRY glStopInstrumentsSGIX (GLint marker); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void); -typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); -typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); -typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); -typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void); -typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); -#endif - -#ifndef GL_SGIX_texture_scale_bias -#define GL_SGIX_texture_scale_bias 1 -#endif - -#ifndef GL_SGIX_framezoom -#define GL_SGIX_framezoom 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFrameZoomSGIX (GLint factor); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor); -#endif - -#ifndef GL_SGIX_tag_sample_buffer -#define GL_SGIX_tag_sample_buffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTagSampleBufferSGIX (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); -#endif - -#ifndef GL_SGIX_polynomial_ffd -#define GL_SGIX_polynomial_ffd 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); -GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); -GLAPI void APIENTRY glDeformSGIX (GLbitfield mask); -GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield mask); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); -typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); -typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask); -typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask); -#endif - -#ifndef GL_SGIX_reference_plane -#define GL_SGIX_reference_plane 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); -#endif - -#ifndef GL_SGIX_flush_raster -#define GL_SGIX_flush_raster 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFlushRasterSGIX (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void); -#endif - -#ifndef GL_SGIX_depth_texture -#define GL_SGIX_depth_texture 1 -#endif - -#ifndef GL_SGIS_fog_function -#define GL_SGIS_fog_function 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFogFuncSGIS (GLsizei n, const GLfloat *points); -GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *points); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); -typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points); -#endif - -#ifndef GL_SGIX_fog_offset -#define GL_SGIX_fog_offset 1 -#endif - -#ifndef GL_HP_image_transform -#define GL_HP_image_transform 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glImageTransformParameteriHP (GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param); -GLAPI void APIENTRY glImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); -#endif - -#ifndef GL_HP_convolution_border_modes -#define GL_HP_convolution_border_modes 1 -#endif - -#ifndef GL_SGIX_texture_add_env -#define GL_SGIX_texture_add_env 1 -#endif - -#ifndef GL_EXT_color_subtable -#define GL_EXT_color_subtable 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); -#endif - -#ifndef GL_PGI_vertex_hints -#define GL_PGI_vertex_hints 1 -#endif - -#ifndef GL_PGI_misc_hints -#define GL_PGI_misc_hints 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glHintPGI (GLenum target, GLint mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode); -#endif - -#ifndef GL_EXT_paletted_texture -#define GL_EXT_paletted_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -GLAPI void APIENTRY glGetColorTableEXT (GLenum target, GLenum format, GLenum type, GLvoid *data); -GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); -#endif - -#ifndef GL_EXT_clip_volume_hint -#define GL_EXT_clip_volume_hint 1 -#endif - -#ifndef GL_SGIX_list_priority -#define GL_SGIX_list_priority 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params); -GLAPI void APIENTRY glListParameterfSGIX (GLuint list, GLenum pname, GLfloat param); -GLAPI void APIENTRY glListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glListParameteriSGIX (GLuint list, GLenum pname, GLint param); -GLAPI void APIENTRY glListParameterivSGIX (GLuint list, GLenum pname, const GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); -#endif - -#ifndef GL_SGIX_ir_instrument1 -#define GL_SGIX_ir_instrument1 1 -#endif - -#ifndef GL_SGIX_calligraphic_fragment -#define GL_SGIX_calligraphic_fragment 1 -#endif - -#ifndef GL_SGIX_texture_lod_bias -#define GL_SGIX_texture_lod_bias 1 -#endif - -#ifndef GL_SGIX_shadow_ambient -#define GL_SGIX_shadow_ambient 1 -#endif - -#ifndef GL_EXT_index_texture -#define GL_EXT_index_texture 1 -#endif - -#ifndef GL_EXT_index_material -#define GL_EXT_index_material 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glIndexMaterialEXT (GLenum face, GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); -#endif - -#ifndef GL_EXT_index_func -#define GL_EXT_index_func 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glIndexFuncEXT (GLenum func, GLclampf ref); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); -#endif - -#ifndef GL_EXT_index_array_formats -#define GL_EXT_index_array_formats 1 -#endif - -#ifndef GL_EXT_compiled_vertex_array -#define GL_EXT_compiled_vertex_array 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count); -GLAPI void APIENTRY glUnlockArraysEXT (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); -typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void); -#endif - -#ifndef GL_EXT_cull_vertex -#define GL_EXT_cull_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCullParameterdvEXT (GLenum pname, GLdouble *params); -GLAPI void APIENTRY glCullParameterfvEXT (GLenum pname, GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); -#endif - -#ifndef GL_SGIX_ycrcb -#define GL_SGIX_ycrcb 1 -#endif - -#ifndef GL_SGIX_fragment_lighting -#define GL_SGIX_fragment_lighting 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum face, GLenum mode); -GLAPI void APIENTRY glFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param); -GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glFragmentLightiSGIX (GLenum light, GLenum pname, GLint param); -GLAPI void APIENTRY glFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params); -GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum pname, GLfloat param); -GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum pname, GLint param); -GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum pname, const GLint *params); -GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param); -GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param); -GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params); -GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params); -GLAPI void APIENTRY glLightEnviSGIX (GLenum pname, GLint param); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); -#endif - -#ifndef GL_IBM_rasterpos_clip -#define GL_IBM_rasterpos_clip 1 -#endif - -#ifndef GL_HP_texture_lighting -#define GL_HP_texture_lighting 1 -#endif - -#ifndef GL_EXT_draw_range_elements -#define GL_EXT_draw_range_elements 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -#endif - -#ifndef GL_WIN_phong_shading -#define GL_WIN_phong_shading 1 -#endif - -#ifndef GL_WIN_specular_fog -#define GL_WIN_specular_fog 1 -#endif - -#ifndef GL_EXT_light_texture -#define GL_EXT_light_texture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glApplyTextureEXT (GLenum mode); -GLAPI void APIENTRY glTextureLightEXT (GLenum pname); -GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); -typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); -typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); -#endif - -#ifndef GL_SGIX_blend_alpha_minmax -#define GL_SGIX_blend_alpha_minmax 1 -#endif - -#ifndef GL_EXT_bgra -#define GL_EXT_bgra 1 -#endif - -#ifndef GL_SGIX_async -#define GL_SGIX_async 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint marker); -GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *markerp); -GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *markerp); -GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei range); -GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range); -GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint marker); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker); -typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp); -typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp); -typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); -typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); -typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); -#endif - -#ifndef GL_SGIX_async_pixel -#define GL_SGIX_async_pixel 1 -#endif - -#ifndef GL_SGIX_async_histogram -#define GL_SGIX_async_histogram 1 -#endif - -#ifndef GL_INTEL_parallel_arrays -#define GL_INTEL_parallel_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer); -GLAPI void APIENTRY glNormalPointervINTEL (GLenum type, const GLvoid* *pointer); -GLAPI void APIENTRY glColorPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer); -GLAPI void APIENTRY glTexCoordPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); -typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); -typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); -typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); -#endif - -#ifndef GL_HP_occlusion_test -#define GL_HP_occlusion_test 1 -#endif - -#ifndef GL_EXT_pixel_transform -#define GL_EXT_pixel_transform 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param); -GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); -#endif - -#ifndef GL_EXT_pixel_transform_color_table -#define GL_EXT_pixel_transform_color_table 1 -#endif - -#ifndef GL_EXT_shared_texture_palette -#define GL_EXT_shared_texture_palette 1 -#endif - -#ifndef GL_EXT_separate_specular_color -#define GL_EXT_separate_specular_color 1 -#endif - -#ifndef GL_EXT_secondary_color -#define GL_EXT_secondary_color 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue); -GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *v); -GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue); -GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *v); -GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue); -GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *v); -GLAPI void APIENTRY glSecondaryColor3iEXT (GLint red, GLint green, GLint blue); -GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *v); -GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue); -GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *v); -GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue); -GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *v); -GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue); -GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *v); -GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue); -GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *v); -GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); -typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_EXT_texture_perturb_normal -#define GL_EXT_texture_perturb_normal 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTextureNormalEXT (GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode); -#endif - -#ifndef GL_EXT_multi_draw_arrays -#define GL_EXT_multi_draw_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); -#endif - -#ifndef GL_EXT_fog_coord -#define GL_EXT_fog_coord 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFogCoordfEXT (GLfloat coord); -GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *coord); -GLAPI void APIENTRY glFogCoorddEXT (GLdouble coord); -GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *coord); -GLAPI void APIENTRY glFogCoordPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord); -typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); -typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord); -typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); -typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_REND_screen_coordinates -#define GL_REND_screen_coordinates 1 -#endif - -#ifndef GL_EXT_coordinate_frame -#define GL_EXT_coordinate_frame 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz); -GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *v); -GLAPI void APIENTRY glTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz); -GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *v); -GLAPI void APIENTRY glTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz); -GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *v); -GLAPI void APIENTRY glTangent3iEXT (GLint tx, GLint ty, GLint tz); -GLAPI void APIENTRY glTangent3ivEXT (const GLint *v); -GLAPI void APIENTRY glTangent3sEXT (GLshort tx, GLshort ty, GLshort tz); -GLAPI void APIENTRY glTangent3svEXT (const GLshort *v); -GLAPI void APIENTRY glBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz); -GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *v); -GLAPI void APIENTRY glBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz); -GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *v); -GLAPI void APIENTRY glBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz); -GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *v); -GLAPI void APIENTRY glBinormal3iEXT (GLint bx, GLint by, GLint bz); -GLAPI void APIENTRY glBinormal3ivEXT (const GLint *v); -GLAPI void APIENTRY glBinormal3sEXT (GLshort bx, GLshort by, GLshort bz); -GLAPI void APIENTRY glBinormal3svEXT (const GLshort *v); -GLAPI void APIENTRY glTangentPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glBinormalPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); -typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); -typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); -typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); -typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); -typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); -typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); -typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); -typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); -typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); -typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); -typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); -typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_EXT_texture_env_combine -#define GL_EXT_texture_env_combine 1 -#endif - -#ifndef GL_APPLE_specular_vector -#define GL_APPLE_specular_vector 1 -#endif - -#ifndef GL_APPLE_transform_hint -#define GL_APPLE_transform_hint 1 -#endif - -#ifndef GL_SGIX_fog_scale -#define GL_SGIX_fog_scale 1 -#endif - -#ifndef GL_SUNX_constant_data -#define GL_SUNX_constant_data 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFinishTextureSUNX (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void); -#endif - -#ifndef GL_SUN_global_alpha -#define GL_SUN_global_alpha 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte factor); -GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort factor); -GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint factor); -GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat factor); -GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble factor); -GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte factor); -GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort factor); -GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint factor); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); -typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); -#endif - -#ifndef GL_SUN_triangle_list -#define GL_SUN_triangle_list 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint code); -GLAPI void APIENTRY glReplacementCodeusSUN (GLushort code); -GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte code); -GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *code); -GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *code); -GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *code); -GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum type, GLsizei stride, const GLvoid* *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); -#endif - -#ifndef GL_SUN_vertex -#define GL_SUN_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); -GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v); -GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v); -GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v); -GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v); -GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v); -GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v); -GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v); -GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); -GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); -#endif - -#ifndef GL_EXT_blend_func_separate -#define GL_EXT_blend_func_separate 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -#endif - -#ifndef GL_INGR_blend_func_separate -#define GL_INGR_blend_func_separate 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -#endif - -#ifndef GL_INGR_color_clamp -#define GL_INGR_color_clamp 1 -#endif - -#ifndef GL_INGR_interlace_read -#define GL_INGR_interlace_read 1 -#endif - -#ifndef GL_EXT_stencil_wrap -#define GL_EXT_stencil_wrap 1 -#endif - -#ifndef GL_EXT_422_pixels -#define GL_EXT_422_pixels 1 -#endif - -#ifndef GL_NV_texgen_reflection -#define GL_NV_texgen_reflection 1 -#endif - -#ifndef GL_SUN_convolution_border_modes -#define GL_SUN_convolution_border_modes 1 -#endif - -#ifndef GL_EXT_texture_env_add -#define GL_EXT_texture_env_add 1 -#endif - -#ifndef GL_EXT_texture_lod_bias -#define GL_EXT_texture_lod_bias 1 -#endif - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_EXT_texture_filter_anisotropic 1 -#endif - -#ifndef GL_EXT_vertex_weighting -#define GL_EXT_vertex_weighting 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexWeightfEXT (GLfloat weight); -GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *weight); -GLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); -typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); -typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); -#endif - -#ifndef GL_NV_light_max_exponent -#define GL_NV_light_max_exponent 1 -#endif - -#ifndef GL_NV_vertex_array_range -#define GL_NV_vertex_array_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFlushVertexArrayRangeNV (void); -GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei length, const GLvoid *pointer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); -typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer); -#endif - -#ifndef GL_NV_register_combiners -#define GL_NV_register_combiners 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCombinerParameterfvNV (GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glCombinerParameterfNV (GLenum pname, GLfloat param); -GLAPI void APIENTRY glCombinerParameterivNV (GLenum pname, const GLint *params); -GLAPI void APIENTRY glCombinerParameteriNV (GLenum pname, GLint param); -GLAPI void APIENTRY glCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -GLAPI void APIENTRY glCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); -GLAPI void APIENTRY glFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); -typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); -typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); -#endif - -#ifndef GL_NV_fog_distance -#define GL_NV_fog_distance 1 -#endif - -#ifndef GL_NV_texgen_emboss -#define GL_NV_texgen_emboss 1 -#endif - -#ifndef GL_NV_blend_square -#define GL_NV_blend_square 1 -#endif - -#ifndef GL_NV_texture_env_combine4 -#define GL_NV_texture_env_combine4 1 -#endif - -#ifndef GL_MESA_resize_buffers -#define GL_MESA_resize_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glResizeBuffersMESA (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void); -#endif - -#ifndef GL_MESA_window_pos -#define GL_MESA_window_pos 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glWindowPos2dMESA (GLdouble x, GLdouble y); -GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *v); -GLAPI void APIENTRY glWindowPos2fMESA (GLfloat x, GLfloat y); -GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *v); -GLAPI void APIENTRY glWindowPos2iMESA (GLint x, GLint y); -GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *v); -GLAPI void APIENTRY glWindowPos2sMESA (GLshort x, GLshort y); -GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *v); -GLAPI void APIENTRY glWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *v); -GLAPI void APIENTRY glWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *v); -GLAPI void APIENTRY glWindowPos3iMESA (GLint x, GLint y, GLint z); -GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *v); -GLAPI void APIENTRY glWindowPos3sMESA (GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *v); -GLAPI void APIENTRY glWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *v); -GLAPI void APIENTRY glWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *v); -GLAPI void APIENTRY glWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *v); -GLAPI void APIENTRY glWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); -typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); -typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); -typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); -typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); -typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); -#endif - -#ifndef GL_IBM_cull_vertex -#define GL_IBM_cull_vertex 1 -#endif - -#ifndef GL_IBM_multimode_draw_arrays -#define GL_IBM_multimode_draw_arrays 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); -GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); -typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); -#endif - -#ifndef GL_IBM_vertex_array_lists -#define GL_IBM_vertex_array_lists 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint stride, const GLboolean* *pointer, GLint ptrstride); -GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -GLAPI void APIENTRY glIndexPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -GLAPI void APIENTRY glNormalPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -GLAPI void APIENTRY glTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -GLAPI void APIENTRY glVertexPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); -#endif - -#ifndef GL_SGIX_subsample -#define GL_SGIX_subsample 1 -#endif - -#ifndef GL_SGIX_ycrcba -#define GL_SGIX_ycrcba 1 -#endif - -#ifndef GL_SGIX_ycrcb_subsample -#define GL_SGIX_ycrcb_subsample 1 -#endif - -#ifndef GL_SGIX_depth_pass_instrument -#define GL_SGIX_depth_pass_instrument 1 -#endif - -#ifndef GL_3DFX_texture_compression_FXT1 -#define GL_3DFX_texture_compression_FXT1 1 -#endif - -#ifndef GL_3DFX_multisample -#define GL_3DFX_multisample 1 -#endif - -#ifndef GL_3DFX_tbuffer -#define GL_3DFX_tbuffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTbufferMask3DFX (GLuint mask); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); -#endif - -#ifndef GL_EXT_multisample -#define GL_EXT_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glSampleMaskEXT (GLclampf value, GLboolean invert); -GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); -typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); -#endif - -#ifndef GL_SGIX_vertex_preclip -#define GL_SGIX_vertex_preclip 1 -#endif - -#ifndef GL_SGIX_convolution_accuracy -#define GL_SGIX_convolution_accuracy 1 -#endif - -#ifndef GL_SGIX_resample -#define GL_SGIX_resample 1 -#endif - -#ifndef GL_SGIS_point_line_texgen -#define GL_SGIS_point_line_texgen 1 -#endif - -#ifndef GL_SGIS_texture_color_mask -#define GL_SGIS_texture_color_mask 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -#endif - -#ifndef GL_SGIX_igloo_interface -#define GL_SGIX_igloo_interface 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum pname, const GLvoid *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params); -#endif - -#ifndef GL_EXT_texture_env_dot3 -#define GL_EXT_texture_env_dot3 1 -#endif - -#ifndef GL_ATI_texture_mirror_once -#define GL_ATI_texture_mirror_once 1 -#endif - -#ifndef GL_NV_fence -#define GL_NV_fence 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences); -GLAPI void APIENTRY glGenFencesNV (GLsizei n, GLuint *fences); -GLAPI GLboolean APIENTRY glIsFenceNV (GLuint fence); -GLAPI GLboolean APIENTRY glTestFenceNV (GLuint fence); -GLAPI void APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params); -GLAPI void APIENTRY glFinishFenceNV (GLuint fence); -GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); -typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); -typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); -typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); -typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); -typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); -#endif - -#ifndef GL_NV_evaluators -#define GL_NV_evaluators 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); -GLAPI void APIENTRY glMapParameterivNV (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); -GLAPI void APIENTRY glGetMapParameterivNV (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glEvalMapsNV (GLenum target, GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); -typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); -typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); -#endif - -#ifndef GL_NV_packed_depth_stencil -#define GL_NV_packed_depth_stencil 1 -#endif - -#ifndef GL_NV_register_combiners2 -#define GL_NV_register_combiners2 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); -#endif - -#ifndef GL_NV_texture_compression_vtc -#define GL_NV_texture_compression_vtc 1 -#endif - -#ifndef GL_NV_texture_rectangle -#define GL_NV_texture_rectangle 1 -#endif - -#ifndef GL_NV_texture_shader -#define GL_NV_texture_shader 1 -#endif - -#ifndef GL_NV_texture_shader2 -#define GL_NV_texture_shader2 1 -#endif - -#ifndef GL_NV_vertex_array_range2 -#define GL_NV_vertex_array_range2 1 -#endif - -#ifndef GL_NV_vertex_program -#define GL_NV_vertex_program 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences); -GLAPI void APIENTRY glBindProgramNV (GLenum target, GLuint id); -GLAPI void APIENTRY glDeleteProgramsNV (GLsizei n, const GLuint *programs); -GLAPI void APIENTRY glExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params); -GLAPI void APIENTRY glGenProgramsNV (GLsizei n, GLuint *programs); -GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params); -GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetProgramivNV (GLuint id, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program); -GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params); -GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint index, GLenum pname, GLvoid* *pointer); -GLAPI GLboolean APIENTRY glIsProgramNV (GLuint id); -GLAPI void APIENTRY glLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program); -GLAPI void APIENTRY glProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v); -GLAPI void APIENTRY glProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v); -GLAPI void APIENTRY glProgramParameters4dvNV (GLenum target, GLuint index, GLuint count, const GLdouble *v); -GLAPI void APIENTRY glProgramParameters4fvNV (GLenum target, GLuint index, GLuint count, const GLfloat *v); -GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei n, const GLuint *programs); -GLAPI void APIENTRY glTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform); -GLAPI void APIENTRY glVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glVertexAttrib1dNV (GLuint index, GLdouble x); -GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib1fNV (GLuint index, GLfloat x); -GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib1sNV (GLuint index, GLshort x); -GLAPI void APIENTRY glVertexAttrib1svNV (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y); -GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y); -GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib2sNV (GLuint index, GLshort x, GLshort y); -GLAPI void APIENTRY glVertexAttrib2svNV (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glVertexAttrib3svNV (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint index, const GLfloat *v); -GLAPI void APIENTRY glVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void APIENTRY glVertexAttrib4svNV (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v); -GLAPI void APIENTRY glVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v); -GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v); -GLAPI void APIENTRY glVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v); -GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v); -GLAPI void APIENTRY glVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v); -GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v); -GLAPI void APIENTRY glVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v); -GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); -typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); -typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); -typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); -typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); -typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); -typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); -typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id); -typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v); -typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v); -typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); -typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); -typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); -#endif - -#ifndef GL_SGIX_texture_coordinate_clamp -#define GL_SGIX_texture_coordinate_clamp 1 -#endif - -#ifndef GL_SGIX_scalebias_hint -#define GL_SGIX_scalebias_hint 1 -#endif - -#ifndef GL_OML_interlace -#define GL_OML_interlace 1 -#endif - -#ifndef GL_OML_subsample -#define GL_OML_subsample 1 -#endif - -#ifndef GL_OML_resample -#define GL_OML_resample 1 -#endif - -#ifndef GL_NV_copy_depth_to_color -#define GL_NV_copy_depth_to_color 1 -#endif - -#ifndef GL_ATI_envmap_bumpmap -#define GL_ATI_envmap_bumpmap 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexBumpParameterivATI (GLenum pname, const GLint *param); -GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum pname, const GLfloat *param); -GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum pname, GLint *param); -GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum pname, GLfloat *param); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param); -typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param); -typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); -typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); -#endif - -#ifndef GL_ATI_fragment_shader -#define GL_ATI_fragment_shader 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint range); -GLAPI void APIENTRY glBindFragmentShaderATI (GLuint id); -GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint id); -GLAPI void APIENTRY glBeginFragmentShaderATI (void); -GLAPI void APIENTRY glEndFragmentShaderATI (void); -GLAPI void APIENTRY glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle); -GLAPI void APIENTRY glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle); -GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); -GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); -GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); -GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); -GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); -GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); -GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); -typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); -typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); -typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void); -typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void); -typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); -typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); -typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); -typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); -typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); -typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); -typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); -typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); -typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value); -#endif - -#ifndef GL_ATI_pn_triangles -#define GL_ATI_pn_triangles 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPNTrianglesiATI (GLenum pname, GLint param); -GLAPI void APIENTRY glPNTrianglesfATI (GLenum pname, GLfloat param); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); -#endif - -#ifndef GL_ATI_vertex_array_object -#define GL_ATI_vertex_array_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei size, const GLvoid *pointer, GLenum usage); -GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint buffer); -GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); -GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params); -GLAPI void APIENTRY glFreeObjectBufferATI (GLuint buffer); -GLAPI void APIENTRY glArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); -GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params); -GLAPI void APIENTRY glVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); -GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage); -typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); -typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); -typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); -typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params); -#endif - -#ifndef GL_EXT_vertex_shader -#define GL_EXT_vertex_shader 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBeginVertexShaderEXT (void); -GLAPI void APIENTRY glEndVertexShaderEXT (void); -GLAPI void APIENTRY glBindVertexShaderEXT (GLuint id); -GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint range); -GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint id); -GLAPI void APIENTRY glShaderOp1EXT (GLenum op, GLuint res, GLuint arg1); -GLAPI void APIENTRY glShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2); -GLAPI void APIENTRY glShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); -GLAPI void APIENTRY glSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); -GLAPI void APIENTRY glWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); -GLAPI void APIENTRY glInsertComponentEXT (GLuint res, GLuint src, GLuint num); -GLAPI void APIENTRY glExtractComponentEXT (GLuint res, GLuint src, GLuint num); -GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); -GLAPI void APIENTRY glSetInvariantEXT (GLuint id, GLenum type, const GLvoid *addr); -GLAPI void APIENTRY glSetLocalConstantEXT (GLuint id, GLenum type, const GLvoid *addr); -GLAPI void APIENTRY glVariantbvEXT (GLuint id, const GLbyte *addr); -GLAPI void APIENTRY glVariantsvEXT (GLuint id, const GLshort *addr); -GLAPI void APIENTRY glVariantivEXT (GLuint id, const GLint *addr); -GLAPI void APIENTRY glVariantfvEXT (GLuint id, const GLfloat *addr); -GLAPI void APIENTRY glVariantdvEXT (GLuint id, const GLdouble *addr); -GLAPI void APIENTRY glVariantubvEXT (GLuint id, const GLubyte *addr); -GLAPI void APIENTRY glVariantusvEXT (GLuint id, const GLushort *addr); -GLAPI void APIENTRY glVariantuivEXT (GLuint id, const GLuint *addr); -GLAPI void APIENTRY glVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); -GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint id); -GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint id); -GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum light, GLenum value); -GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum face, GLenum value); -GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value); -GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum unit, GLenum value); -GLAPI GLuint APIENTRY glBindParameterEXT (GLenum value); -GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint id, GLenum cap); -GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data); -GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data); -GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data); -GLAPI void APIENTRY glGetVariantPointervEXT (GLuint id, GLenum value, GLvoid* *data); -GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data); -GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data); -GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data); -GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data); -GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data); -GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void); -typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void); -typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); -typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); -typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); -typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); -typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); -typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); -typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); -typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); -typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); -typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); -typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); -typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); -typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); -typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr); -typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr); -typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr); -typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr); -typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr); -typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr); -typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr); -typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr); -typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); -typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); -typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); -typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); -typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); -typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); -typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); -typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value); -typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); -typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); -typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); -typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data); -typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); -typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); -typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); -typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); -#endif - -#ifndef GL_ATI_vertex_streams -#define GL_ATI_vertex_streams 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexStream1sATI (GLenum stream, GLshort x); -GLAPI void APIENTRY glVertexStream1svATI (GLenum stream, const GLshort *coords); -GLAPI void APIENTRY glVertexStream1iATI (GLenum stream, GLint x); -GLAPI void APIENTRY glVertexStream1ivATI (GLenum stream, const GLint *coords); -GLAPI void APIENTRY glVertexStream1fATI (GLenum stream, GLfloat x); -GLAPI void APIENTRY glVertexStream1fvATI (GLenum stream, const GLfloat *coords); -GLAPI void APIENTRY glVertexStream1dATI (GLenum stream, GLdouble x); -GLAPI void APIENTRY glVertexStream1dvATI (GLenum stream, const GLdouble *coords); -GLAPI void APIENTRY glVertexStream2sATI (GLenum stream, GLshort x, GLshort y); -GLAPI void APIENTRY glVertexStream2svATI (GLenum stream, const GLshort *coords); -GLAPI void APIENTRY glVertexStream2iATI (GLenum stream, GLint x, GLint y); -GLAPI void APIENTRY glVertexStream2ivATI (GLenum stream, const GLint *coords); -GLAPI void APIENTRY glVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y); -GLAPI void APIENTRY glVertexStream2fvATI (GLenum stream, const GLfloat *coords); -GLAPI void APIENTRY glVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y); -GLAPI void APIENTRY glVertexStream2dvATI (GLenum stream, const GLdouble *coords); -GLAPI void APIENTRY glVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z); -GLAPI void APIENTRY glVertexStream3svATI (GLenum stream, const GLshort *coords); -GLAPI void APIENTRY glVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z); -GLAPI void APIENTRY glVertexStream3ivATI (GLenum stream, const GLint *coords); -GLAPI void APIENTRY glVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glVertexStream3fvATI (GLenum stream, const GLfloat *coords); -GLAPI void APIENTRY glVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glVertexStream3dvATI (GLenum stream, const GLdouble *coords); -GLAPI void APIENTRY glVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); -GLAPI void APIENTRY glVertexStream4svATI (GLenum stream, const GLshort *coords); -GLAPI void APIENTRY glVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glVertexStream4ivATI (GLenum stream, const GLint *coords); -GLAPI void APIENTRY glVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glVertexStream4fvATI (GLenum stream, const GLfloat *coords); -GLAPI void APIENTRY glVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glVertexStream4dvATI (GLenum stream, const GLdouble *coords); -GLAPI void APIENTRY glNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); -GLAPI void APIENTRY glNormalStream3bvATI (GLenum stream, const GLbyte *coords); -GLAPI void APIENTRY glNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz); -GLAPI void APIENTRY glNormalStream3svATI (GLenum stream, const GLshort *coords); -GLAPI void APIENTRY glNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz); -GLAPI void APIENTRY glNormalStream3ivATI (GLenum stream, const GLint *coords); -GLAPI void APIENTRY glNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); -GLAPI void APIENTRY glNormalStream3fvATI (GLenum stream, const GLfloat *coords); -GLAPI void APIENTRY glNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); -GLAPI void APIENTRY glNormalStream3dvATI (GLenum stream, const GLdouble *coords); -GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum stream); -GLAPI void APIENTRY glVertexBlendEnviATI (GLenum pname, GLint param); -GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); -typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords); -typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); -typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords); -typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); -typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); -typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz); -typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); -typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); -typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); -typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); -typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); -typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); -typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); -#endif - -#ifndef GL_ATI_element_array -#define GL_ATI_element_array 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glElementPointerATI (GLenum type, const GLvoid *pointer); -GLAPI void APIENTRY glDrawElementArrayATI (GLenum mode, GLsizei count); -GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); -typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); -#endif - -#ifndef GL_SUN_mesh_array -#define GL_SUN_mesh_array 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width); -#endif - -#ifndef GL_SUN_slice_accum -#define GL_SUN_slice_accum 1 -#endif - -#ifndef GL_NV_multisample_filter_hint -#define GL_NV_multisample_filter_hint 1 -#endif - -#ifndef GL_NV_depth_clamp -#define GL_NV_depth_clamp 1 -#endif - -#ifndef GL_NV_occlusion_query -#define GL_NV_occlusion_query 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei n, GLuint *ids); -GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids); -GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint id); -GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint id); -GLAPI void APIENTRY glEndOcclusionQueryNV (void); -GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); -typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); -typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); -typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); -typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void); -typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); -#endif - -#ifndef GL_NV_point_sprite -#define GL_NV_point_sprite 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPointParameteriNV (GLenum pname, GLint param); -GLAPI void APIENTRY glPointParameterivNV (GLenum pname, const GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params); -#endif - -#ifndef GL_NV_texture_shader3 -#define GL_NV_texture_shader3 1 -#endif - -#ifndef GL_NV_vertex_program1_1 -#define GL_NV_vertex_program1_1 1 -#endif - -#ifndef GL_EXT_shadow_funcs -#define GL_EXT_shadow_funcs 1 -#endif - -#ifndef GL_EXT_stencil_two_side -#define GL_EXT_stencil_two_side 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum face); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); -#endif - -#ifndef GL_ATI_text_fragment_shader -#define GL_ATI_text_fragment_shader 1 -#endif - -#ifndef GL_APPLE_client_storage -#define GL_APPLE_client_storage 1 -#endif - -#ifndef GL_APPLE_element_array -#define GL_APPLE_element_array 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glElementPointerAPPLE (GLenum type, const GLvoid *pointer); -GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count); -GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); -GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); -typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); -typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); -#endif - -#ifndef GL_APPLE_fence -#define GL_APPLE_fence 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGenFencesAPPLE (GLsizei n, GLuint *fences); -GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei n, const GLuint *fences); -GLAPI void APIENTRY glSetFenceAPPLE (GLuint fence); -GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint fence); -GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint fence); -GLAPI void APIENTRY glFinishFenceAPPLE (GLuint fence); -GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum object, GLuint name); -GLAPI void APIENTRY glFinishObjectAPPLE (GLenum object, GLint name); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences); -typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences); -typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence); -typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence); -typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence); -typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); -typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); -typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); -#endif - -#ifndef GL_APPLE_vertex_array_object -#define GL_APPLE_vertex_array_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint array); -GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays); -GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei n, GLuint *arrays); -GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint array); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); -typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); -typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays); -typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); -#endif - -#ifndef GL_APPLE_vertex_array_range -#define GL_APPLE_vertex_array_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer); -GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer); -GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum pname, GLint param); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); -typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); -typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); -#endif - -#ifndef GL_APPLE_ycbcr_422 -#define GL_APPLE_ycbcr_422 1 -#endif - -#ifndef GL_S3_s3tc -#define GL_S3_s3tc 1 -#endif - -#ifndef GL_ATI_draw_buffers -#define GL_ATI_draw_buffers 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawBuffersATI (GLsizei n, const GLenum *bufs); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs); -#endif - -#ifndef GL_ATI_pixel_format_float -#define GL_ATI_pixel_format_float 1 -/* This is really a WGL extension, but defines some associated GL enums. - * ATI does not export "GL_ATI_pixel_format_float" in the GL_EXTENSIONS string. +/* + * Define this token if you want "old-style" header file behaviour (extensions + * defined in gl.h). Otherwise, extensions will be included from glext.h. */ +#if !defined(NO_SDL_GLEXT) && !defined(GL_GLEXT_LEGACY) +#include "SDL_opengl_glext.h" +#endif /* GL_GLEXT_LEGACY */ + + + +/* + * ???. GL_MESA_packed_depth_stencil + * XXX obsolete + */ +#ifndef GL_MESA_packed_depth_stencil +#define GL_MESA_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_MESA 0x8750 +#define GL_UNSIGNED_INT_24_8_MESA 0x8751 +#define GL_UNSIGNED_INT_8_24_REV_MESA 0x8752 +#define GL_UNSIGNED_SHORT_15_1_MESA 0x8753 +#define GL_UNSIGNED_SHORT_1_15_REV_MESA 0x8754 + +#endif /* GL_MESA_packed_depth_stencil */ + + +#ifndef GL_ATI_blend_equation_separate +#define GL_ATI_blend_equation_separate 1 + +#define GL_ALPHA_BLEND_EQUATION_ATI 0x883D + +GLAPI void GLAPIENTRY glBlendEquationSeparateATI( GLenum modeRGB, GLenum modeA ); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEATIPROC) (GLenum modeRGB, GLenum modeA); + +#endif /* GL_ATI_blend_equation_separate */ + + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +typedef void* GLeglImageOES; #endif -#ifndef GL_ATI_texture_env_combine3 -#define GL_ATI_texture_env_combine3 1 -#endif - -#ifndef GL_ATI_texture_float -#define GL_ATI_texture_float 1 -#endif - -#ifndef GL_NV_float_buffer -#define GL_NV_float_buffer 1 -#endif - -#ifndef GL_NV_fragment_program -#define GL_NV_fragment_program 1 -/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */ +#ifndef GL_OES_EGL_image +#define GL_OES_EGL_image 1 #ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); -GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); -GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); -GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); -typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); -typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); -typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); +GLAPI void APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); +GLAPI void APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); #endif - -#ifndef GL_NV_half_float -#define GL_NV_half_float 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y); -GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z); -GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); -GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); -GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue); -GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); -GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV s); -GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV s, GLhalfNV t); -GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r); -GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); -GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum target, GLhalfNV s); -GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v); -GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t); -GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v); -GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); -GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v); -GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); -GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v); -GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog); -GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog); -GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue); -GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight); -GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight); -GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x); -GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y); -GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint index, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); -GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint index, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); -GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint index, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v); -GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y); -typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z); -typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); -typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); -typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); -typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); -typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s); -typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t); -typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r); -typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); -typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s); -typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t); -typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); -typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); -typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); -typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); -typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); -typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); -typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); -typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); -typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); -#endif - -#ifndef GL_NV_pixel_data_range -#define GL_NV_pixel_data_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, GLvoid *pointer); -GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); -typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); -#endif - -#ifndef GL_NV_primitive_restart -#define GL_NV_primitive_restart 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPrimitiveRestartNV (void); -GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void); -typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); -#endif - -#ifndef GL_NV_texture_expand_normal -#define GL_NV_texture_expand_normal 1 -#endif - -#ifndef GL_NV_vertex_program2 -#define GL_NV_vertex_program2 1 -#endif - -#ifndef GL_ATI_map_object_buffer -#define GL_ATI_map_object_buffer 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint buffer); -GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint buffer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); -#endif - -#ifndef GL_ATI_separate_stencil -#define GL_ATI_separate_stencil 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); -#endif - -#ifndef GL_ATI_vertex_attrib_array_object -#define GL_ATI_vertex_attrib_array_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); -GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params); -#endif - -#ifndef GL_OES_read_format -#define GL_OES_read_format 1 -#endif - -#ifndef GL_EXT_depth_bounds_test -#define GL_EXT_depth_bounds_test 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDepthBoundsEXT (GLclampd zmin, GLclampd zmax); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); -#endif - -#ifndef GL_EXT_texture_mirror_clamp -#define GL_EXT_texture_mirror_clamp 1 -#endif - -#ifndef GL_EXT_blend_equation_separate -#define GL_EXT_blend_equation_separate 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); -#endif - -#ifndef GL_MESA_pack_invert -#define GL_MESA_pack_invert 1 -#endif - -#ifndef GL_MESA_ycbcr_texture -#define GL_MESA_ycbcr_texture 1 -#endif - -#ifndef GL_EXT_pixel_buffer_object -#define GL_EXT_pixel_buffer_object 1 -#endif - -#ifndef GL_NV_fragment_program_option -#define GL_NV_fragment_program_option 1 -#endif - -#ifndef GL_NV_fragment_program2 -#define GL_NV_fragment_program2 1 -#endif - -#ifndef GL_NV_vertex_program2_option -#define GL_NV_vertex_program2_option 1 -#endif - -#ifndef GL_NV_vertex_program3 -#define GL_NV_vertex_program3 1 -#endif - -#ifndef GL_EXT_framebuffer_object -#define GL_EXT_framebuffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint renderbuffer); -GLAPI void APIENTRY glBindRenderbufferEXT (GLenum target, GLuint renderbuffer); -GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei n, const GLuint *renderbuffers); -GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers); -GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params); -GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint framebuffer); -GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer); -GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers); -GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers); -GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum target); -GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum attachment, GLenum pname, GLint *params); -GLAPI void APIENTRY glGenerateMipmapEXT (GLenum target); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); -typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); -typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); -typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); -typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); -typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); -typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); -typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); -#endif - -#ifndef GL_GREMEDY_string_marker -#define GL_GREMEDY_string_marker 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei len, const GLvoid *string); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string); -#endif - -#ifndef GL_EXT_packed_depth_stencil -#define GL_EXT_packed_depth_stencil 1 -#endif - -#ifndef GL_EXT_stencil_clear_tag -#define GL_EXT_stencil_clear_tag 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glStencilClearTagEXT (GLsizei stencilTagBits, GLuint stencilClearTag); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag); -#endif - -#ifndef GL_EXT_texture_sRGB -#define GL_EXT_texture_sRGB 1 -#endif - -#ifndef GL_EXT_framebuffer_blit -#define GL_EXT_framebuffer_blit 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif - -#ifndef GL_EXT_framebuffer_multisample -#define GL_EXT_framebuffer_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif - -#ifndef GL_MESAX_texture_stack -#define GL_MESAX_texture_stack 1 -#endif - -#ifndef GL_EXT_timer_query -#define GL_EXT_timer_query 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64EXT *params); -GLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64EXT *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); -typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); -#endif - -#ifndef GL_EXT_gpu_program_parameters -#define GL_EXT_gpu_program_parameters 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params); -GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params); -#endif - -#ifndef GL_APPLE_flush_buffer_range -#define GL_APPLE_flush_buffer_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBufferParameteriAPPLE (GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); -#endif - -#ifndef GL_NV_gpu_program4 -#define GL_NV_gpu_program4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params); -GLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params); -GLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params); -GLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params); -GLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params); -GLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params); -GLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params); -GLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params); -GLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params); -GLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params); -GLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params); -GLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); -typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); -typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params); -#endif - -#ifndef GL_NV_geometry_program4 -#define GL_NV_geometry_program4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit); -GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level); -GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); -#endif - -#ifndef GL_EXT_geometry_shader4 -#define GL_EXT_geometry_shader4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); -#endif - -#ifndef GL_NV_vertex_program4 -#define GL_NV_vertex_program4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x); -GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y); -GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z); -GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x); -GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y); -GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z); -GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v); -GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); -#endif - -#ifndef GL_EXT_gpu_shader4 -#define GL_EXT_gpu_shader4 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params); -GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name); -GLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name); -GLAPI void APIENTRY glUniform1uiEXT (GLint location, GLuint v0); -GLAPI void APIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1); -GLAPI void APIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2); -GLAPI void APIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); -typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); -typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); -typedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); -typedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); -typedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); -#endif - -#ifndef GL_EXT_draw_instanced -#define GL_EXT_draw_instanced 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount); -GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); -typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); -#endif - -#ifndef GL_EXT_packed_float -#define GL_EXT_packed_float 1 -#endif - -#ifndef GL_EXT_texture_array -#define GL_EXT_texture_array 1 -#endif - -#ifndef GL_EXT_texture_buffer_object -#define GL_EXT_texture_buffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); -#endif - -#ifndef GL_EXT_texture_compression_latc -#define GL_EXT_texture_compression_latc 1 -#endif - -#ifndef GL_EXT_texture_compression_rgtc -#define GL_EXT_texture_compression_rgtc 1 -#endif - -#ifndef GL_EXT_texture_shared_exponent -#define GL_EXT_texture_shared_exponent 1 -#endif - -#ifndef GL_NV_depth_buffer_float -#define GL_NV_depth_buffer_float 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar); -GLAPI void APIENTRY glClearDepthdNV (GLdouble depth); -GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); -typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); -typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); -#endif - -#ifndef GL_NV_fragment_program4 -#define GL_NV_fragment_program4 1 -#endif - -#ifndef GL_NV_framebuffer_multisample_coverage -#define GL_NV_framebuffer_multisample_coverage 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); -#endif - -#ifndef GL_EXT_framebuffer_sRGB -#define GL_EXT_framebuffer_sRGB 1 -#endif - -#ifndef GL_NV_geometry_shader4 -#define GL_NV_geometry_shader4 1 +typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); #endif -#ifndef GL_NV_parameter_buffer_object -#define GL_NV_parameter_buffer_object 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); -GLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); -GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); -typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); -typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); -#endif - -#ifndef GL_EXT_draw_buffers2 -#define GL_EXT_draw_buffers2 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -GLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data); -GLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data); -GLAPI void APIENTRY glEnableIndexedEXT (GLenum target, GLuint index); -GLAPI void APIENTRY glDisableIndexedEXT (GLenum target, GLuint index); -GLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -typedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data); -typedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data); -typedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); -typedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); -typedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); -#endif - -#ifndef GL_NV_transform_feedback -#define GL_NV_transform_feedback 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode); -GLAPI void APIENTRY glEndTransformFeedbackNV (void); -GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode); -GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset); -GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer); -GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); -GLAPI void APIENTRY glActiveVaryingNV (GLuint program, const GLchar *name); -GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name); -GLAPI void APIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -GLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location); -GLAPI void APIENTRY glTransformFeedbackStreamAttribsNV (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); -typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); -typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); -typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); -typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); -typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); -typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode); -#endif - -#ifndef GL_EXT_bindable_uniform -#define GL_EXT_bindable_uniform 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer); -GLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location); -GLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint program, GLint location); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); -typedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); -typedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); -#endif - -#ifndef GL_EXT_texture_integer -#define GL_EXT_texture_integer 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params); -GLAPI void APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params); -GLAPI void APIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha); -GLAPI void APIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); -typedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); -#endif - -#ifndef GL_GREMEDY_frame_terminator -#define GL_GREMEDY_frame_terminator 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glFrameTerminatorGREMEDY (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void); -#endif - -#ifndef GL_NV_conditional_render -#define GL_NV_conditional_render 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode); -GLAPI void APIENTRY glEndConditionalRenderNV (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); -typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void); -#endif - -#ifndef GL_NV_present_video -#define GL_NV_present_video 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); -GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); -GLAPI void APIENTRY glGetVideoivNV (GLuint video_slot, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVideouivNV (GLuint video_slot, GLenum pname, GLuint *params); -GLAPI void APIENTRY glGetVideoi64vNV (GLuint video_slot, GLenum pname, GLint64EXT *params); -GLAPI void APIENTRY glGetVideoui64vNV (GLuint video_slot, GLenum pname, GLuint64EXT *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); -typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); -typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params); -typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params); -#endif - -#ifndef GL_EXT_transform_feedback -#define GL_EXT_transform_feedback 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum primitiveMode); -GLAPI void APIENTRY glEndTransformFeedbackEXT (void); -GLAPI void APIENTRY glBindBufferRangeEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -GLAPI void APIENTRY glBindBufferOffsetEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset); -GLAPI void APIENTRY glBindBufferBaseEXT (GLenum target, GLuint index, GLuint buffer); -GLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode); -GLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); -typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); -typedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); -typedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode); -typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -#endif - -#ifndef GL_EXT_direct_state_access -#define GL_EXT_direct_state_access 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield mask); -GLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield mask); -GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m); -GLAPI void APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m); -GLAPI void APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m); -GLAPI void APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m); -GLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum mode); -GLAPI void APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z); -GLAPI void APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -GLAPI void APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -GLAPI void APIENTRY glMatrixPopEXT (GLenum mode); -GLAPI void APIENTRY glMatrixPushEXT (GLenum mode); -GLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m); -GLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m); -GLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m); -GLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m); -GLAPI void APIENTRY glTextureParameterfEXT (GLuint texture, GLenum target, GLenum pname, GLfloat param); -GLAPI void APIENTRY glTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glTextureParameteriEXT (GLuint texture, GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -GLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetTextureImageEXT (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -GLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params); -GLAPI void APIENTRY glTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glMultiTexParameterfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param); -GLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glMultiTexParameteriEXT (GLenum texunit, GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -GLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -GLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -GLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params); -GLAPI void APIENTRY glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void APIENTRY glBindMultiTextureEXT (GLenum texunit, GLenum target, GLuint texture); -GLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum array, GLuint index); -GLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum array, GLuint index); -GLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glMultiTexEnvfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param); -GLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glMultiTexEnviEXT (GLenum texunit, GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glMultiTexGendEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); -GLAPI void APIENTRY glMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params); -GLAPI void APIENTRY glMultiTexGenfEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); -GLAPI void APIENTRY glMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glMultiTexGeniEXT (GLenum texunit, GLenum coord, GLenum pname, GLint param); -GLAPI void APIENTRY glMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, const GLint *params); -GLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params); -GLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum target, GLuint index, GLfloat *data); -GLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum target, GLuint index, GLdouble *data); -GLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum target, GLuint index, GLvoid* *data); -GLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint texture, GLenum target, GLint lod, GLvoid *img); -GLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits); -GLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target, GLint lod, GLvoid *img); -GLAPI void APIENTRY glNamedProgramStringEXT (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string); -GLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint program, GLenum target, GLuint index, const GLdouble *params); -GLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint program, GLenum target, GLuint index, const GLfloat *params); -GLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint program, GLenum target, GLuint index, GLdouble *params); -GLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint program, GLenum target, GLuint index, GLfloat *params); -GLAPI void APIENTRY glGetNamedProgramivEXT (GLuint program, GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint program, GLenum target, GLenum pname, GLvoid *string); -GLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params); -GLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint program, GLenum target, GLuint index, const GLint *params); -GLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params); -GLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint program, GLenum target, GLuint index, const GLuint *params); -GLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params); -GLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint program, GLenum target, GLuint index, GLint *params); -GLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint program, GLenum target, GLuint index, GLuint *params); -GLAPI void APIENTRY glTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, const GLuint *params); -GLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, GLuint *params); -GLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); -GLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, const GLuint *params); -GLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, GLuint *params); -GLAPI void APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0); -GLAPI void APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1); -GLAPI void APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GLAPI void APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GLAPI void APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0); -GLAPI void APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1); -GLAPI void APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -GLAPI void APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GLAPI void APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GLAPI void APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0); -GLAPI void APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1); -GLAPI void APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -GLAPI void APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GLAPI void APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GLAPI void APIENTRY glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage); -GLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data); -GLAPI GLvoid* APIENTRY glMapNamedBufferEXT (GLuint buffer, GLenum access); -GLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint buffer); -GLAPI GLvoid* APIENTRY glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); -GLAPI void APIENTRY glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length); -GLAPI void APIENTRY glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -GLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint buffer, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint buffer, GLenum pname, GLvoid* *params); -GLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data); -GLAPI void APIENTRY glTextureBufferEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); -GLAPI void APIENTRY glMultiTexBufferEXT (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); -GLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); -GLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint renderbuffer, GLenum pname, GLint *params); -GLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint framebuffer, GLenum target); -GLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -GLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); -GLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint texture, GLenum target); -GLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum texunit, GLenum target); -GLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint framebuffer, GLenum mode); -GLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint framebuffer, GLsizei n, const GLenum *bufs); -GLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint framebuffer, GLenum mode); -GLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params); -GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); -GLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); -GLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); -GLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); -GLAPI void APIENTRY glTextureRenderbufferEXT (GLuint texture, GLenum target, GLuint renderbuffer); -GLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum texunit, GLenum target, GLuint renderbuffer); -GLAPI void APIENTRY glProgramUniform1dEXT (GLuint program, GLint location, GLdouble x); -GLAPI void APIENTRY glProgramUniform2dEXT (GLuint program, GLint location, GLdouble x, GLdouble y); -GLAPI void APIENTRY glProgramUniform3dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glProgramUniform4dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glProgramUniform1dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform2dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform3dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniform4dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix2x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix2x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix3x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix3x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix4x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -GLAPI void APIENTRY glProgramUniformMatrix4x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); -typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); -typedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m); -typedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m); -typedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m); -typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m); -typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode); -typedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); -typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -typedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -typedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode); -typedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode); -typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m); -typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m); -typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m); -typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m); -typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); -typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); -typedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); -typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); -typedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); -typedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params); -typedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); -typedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data); -typedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data); -typedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid* *data); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, GLvoid *img); -typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits); -typedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, GLvoid *img); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params); -typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params); -typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params); -typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid *string); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params); -typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params); -typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params); -typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params); -typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params); -typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params); -typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage); -typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data); -typedef GLvoid* (APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); -typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); -typedef GLvoid* (APIENTRYP PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); -typedef void (APIENTRYP PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, GLvoid* *params); -typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data); -typedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params); -typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); -typedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); -typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); -typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs); -typedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); -typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); -typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); -typedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); -#endif - -#ifndef GL_EXT_vertex_array_bgra -#define GL_EXT_vertex_array_bgra 1 -#endif -#ifndef GL_EXT_texture_swizzle -#define GL_EXT_texture_swizzle 1 -#endif +/** + ** NOTE!!!!! If you add new functions to this file, or update + ** glext.h be sure to regenerate the gl_mangle.h file. See comments + ** in that file for details. + **/ -#ifndef GL_NV_explicit_multisample -#define GL_NV_explicit_multisample 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetMultisamplefvNV (GLenum pname, GLuint index, GLfloat *val); -GLAPI void APIENTRY glSampleMaskIndexedNV (GLuint index, GLbitfield mask); -GLAPI void APIENTRY glTexRenderbufferNV (GLenum target, GLuint renderbuffer); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val); -typedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); -typedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); -#endif -#ifndef GL_NV_transform_feedback2 -#define GL_NV_transform_feedback2 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindTransformFeedbackNV (GLenum target, GLuint id); -GLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei n, const GLuint *ids); -GLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei n, GLuint *ids); -GLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint id); -GLAPI void APIENTRY glPauseTransformFeedbackNV (void); -GLAPI void APIENTRY glResumeTransformFeedbackNV (void); -GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); -typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids); -typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids); -typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); -typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void); -typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void); -typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); -#endif -#ifndef GL_ATI_meminfo -#define GL_ATI_meminfo 1 +/********************************************************************** + * Begin system-specific stuff + */ +#if defined(PRAGMA_EXPORT_SUPPORTED) +#pragma export off #endif -#ifndef GL_AMD_performance_monitor -#define GL_AMD_performance_monitor 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data); -GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); -GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); -GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); -GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor); -GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor); -GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); -typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); -typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); -typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); -typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#endif - -#ifndef GL_AMD_texture_texture4 -#define GL_AMD_texture_texture4 1 -#endif - -#ifndef GL_AMD_vertex_shader_tesselator -#define GL_AMD_vertex_shader_tesselator 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTessellationFactorAMD (GLfloat factor); -GLAPI void APIENTRY glTessellationModeAMD (GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor); -typedef void (APIENTRYP PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); -#endif - -#ifndef GL_EXT_provoking_vertex -#define GL_EXT_provoking_vertex 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); -#endif - -#ifndef GL_EXT_texture_snorm -#define GL_EXT_texture_snorm 1 -#endif - -#ifndef GL_AMD_draw_buffers_blend -#define GL_AMD_draw_buffers_blend 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint buf, GLenum src, GLenum dst); -GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint buf, GLenum mode); -GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); -typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); -typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -#endif - -#ifndef GL_APPLE_texture_range -#define GL_APPLE_texture_range 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTextureRangeAPPLE (GLenum target, GLsizei length, const GLvoid *pointer); -GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum target, GLenum pname, GLvoid* *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid* *params); -#endif - -#ifndef GL_APPLE_float_pixels -#define GL_APPLE_float_pixels 1 -#endif - -#ifndef GL_APPLE_vertex_program_evaluators -#define GL_APPLE_vertex_program_evaluators 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint index, GLenum pname); -GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint index, GLenum pname); -GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint index, GLenum pname); -GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); -typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); -typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); -typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -#endif - -#ifndef GL_APPLE_aux_depth_stencil -#define GL_APPLE_aux_depth_stencil 1 -#endif - -#ifndef GL_APPLE_object_purgeable -#define GL_APPLE_object_purgeable 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum objectType, GLuint name, GLenum option); -GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum objectType, GLuint name, GLenum option); -GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum objectType, GLuint name, GLenum pname, GLint *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); -typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); -typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params); -#endif - -#ifndef GL_APPLE_row_bytes -#define GL_APPLE_row_bytes 1 -#endif - -#ifndef GL_APPLE_rgb_422 -#define GL_APPLE_rgb_422 1 -#endif - -#ifndef GL_NV_video_capture -#define GL_NV_video_capture 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBeginVideoCaptureNV (GLuint video_capture_slot); -GLAPI void APIENTRY glBindVideoCaptureStreamBufferNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); -GLAPI void APIENTRY glBindVideoCaptureStreamTextureNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); -GLAPI void APIENTRY glEndVideoCaptureNV (GLuint video_capture_slot); -GLAPI void APIENTRY glGetVideoCaptureivNV (GLuint video_capture_slot, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVideoCaptureStreamivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVideoCaptureStreamfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params); -GLAPI void APIENTRY glGetVideoCaptureStreamdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params); -GLAPI GLenum APIENTRY glVideoCaptureNV (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time); -GLAPI void APIENTRY glVideoCaptureStreamParameterivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params); -GLAPI void APIENTRY glVideoCaptureStreamParameterfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params); -GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot); -typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); -typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); -typedef void (APIENTRYP PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot); -typedef void (APIENTRYP PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params); -typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params); -typedef GLenum (APIENTRYP PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time); -typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params); -typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params); -typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params); -#endif - -#ifndef GL_NV_copy_image -#define GL_NV_copy_image 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glCopyImageSubDataNV (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); -#endif - -#ifndef GL_EXT_separate_shader_objects -#define GL_EXT_separate_shader_objects 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program); -GLAPI void APIENTRY glActiveProgramEXT (GLuint program); -GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); -typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); -typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string); -#endif - -#ifndef GL_NV_parameter_buffer_object2 -#define GL_NV_parameter_buffer_object2 1 -#endif - -#ifndef GL_NV_shader_buffer_load -#define GL_NV_shader_buffer_load 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access); -GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target); -GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target); -GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access); -GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer); -GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer); -GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params); -GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params); -GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result); -GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value); -GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params); -GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value); -GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); -typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); -typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); -typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); -typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); -typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params); -typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params); -typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result); -typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); -typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -#endif - -#ifndef GL_NV_vertex_buffer_unified_memory -#define GL_NV_vertex_buffer_unified_memory 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); -GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride); -GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride); -GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride); -GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride); -GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride); -GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride); -GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride); -GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride); -GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); -GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride); -GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); -typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); -typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); -typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); -typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result); -#endif - -#ifndef GL_NV_texture_barrier -#define GL_NV_texture_barrier 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTextureBarrierNV (void); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void); -#endif - -#ifndef GL_AMD_shader_stencil_export -#define GL_AMD_shader_stencil_export 1 -#endif - -#ifndef GL_AMD_seamless_cubemap_per_texture -#define GL_AMD_seamless_cubemap_per_texture 1 -#endif - -#ifndef GL_AMD_conservative_depth -#define GL_AMD_conservative_depth 1 -#endif - -#ifndef GL_EXT_shader_image_load_store -#define GL_EXT_shader_image_load_store 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glBindImageTextureEXT (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); -GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); -typedef void (APIENTRYP PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); -#endif - -#ifndef GL_EXT_vertex_attrib_64bit -#define GL_EXT_vertex_attrib_64bit 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribL1dEXT (GLuint index, GLdouble x); -GLAPI void APIENTRY glVertexAttribL2dEXT (GLuint index, GLdouble x, GLdouble y); -GLAPI void APIENTRY glVertexAttribL3dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z); -GLAPI void APIENTRY glVertexAttribL4dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -GLAPI void APIENTRY glVertexAttribL1dvEXT (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribL2dvEXT (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribL3dvEXT (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribL4dvEXT (GLuint index, const GLdouble *v); -GLAPI void APIENTRY glVertexAttribLPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -GLAPI void APIENTRY glGetVertexAttribLdvEXT (GLuint index, GLenum pname, GLdouble *params); -GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble *params); -typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); -#endif - -#ifndef GL_NV_gpu_program5 -#define GL_NV_gpu_program5 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glProgramSubroutineParametersuivNV (GLenum target, GLsizei count, const GLuint *params); -GLAPI void APIENTRY glGetProgramSubroutineParameteruivNV (GLenum target, GLuint index, GLuint *param); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC) (GLenum target, GLsizei count, const GLuint *params); -typedef void (APIENTRYP PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC) (GLenum target, GLuint index, GLuint *param); -#endif - -#ifndef GL_NV_gpu_shader5 -#define GL_NV_gpu_shader5 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x); -GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y); -GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); -GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x); -GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y); -GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params); -GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x); -GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); -GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); -GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x); -GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); -GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); -typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); -typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); -typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); -typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); -typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); -#endif - -#ifndef GL_NV_shader_buffer_store -#define GL_NV_shader_buffer_store 1 -#endif - -#ifndef GL_NV_tessellation_program5 -#define GL_NV_tessellation_program5 1 -#endif - -#ifndef GL_NV_vertex_attrib_integer_64bit -#define GL_NV_vertex_attrib_integer_64bit 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x); -GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y); -GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); -GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v); -GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v); -GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v); -GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v); -GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x); -GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y); -GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v); -GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v); -GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v); -GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v); -GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params); -GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params); -GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params); -typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); -#endif - -#ifndef GL_NV_multisample_coverage -#define GL_NV_multisample_coverage 1 -#endif - -#ifndef GL_AMD_name_gen_delete -#define GL_AMD_name_gen_delete 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGenNamesAMD (GLenum identifier, GLuint num, GLuint *names); -GLAPI void APIENTRY glDeleteNamesAMD (GLenum identifier, GLuint num, const GLuint *names); -GLAPI GLboolean APIENTRY glIsNameAMD (GLenum identifier, GLuint name); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint *names); -typedef void (APIENTRYP PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint *names); -typedef GLboolean (APIENTRYP PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name); -#endif - -#ifndef GL_AMD_debug_output -#define GL_AMD_debug_output 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf); -GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, GLvoid *userParam); -GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf); -typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, GLvoid *userParam); -typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message); -#endif - -#ifndef GL_NV_vdpau_interop -#define GL_NV_vdpau_interop 1 -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVDPAUInitNV (const GLvoid *vdpDevice, const GLvoid *getProcAddress); -GLAPI void APIENTRY glVDPAUFiniNV (void); -GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -GLAPI void APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface); -GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface); -GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access); -GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); -GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); -#endif /* GL_GLEXT_PROTOTYPES */ -typedef void (APIENTRYP PFNGLVDPAUINITNVPROC) (const GLvoid *vdpDevice, const GLvoid *getProcAddress); -typedef void (APIENTRYP PFNGLVDPAUFININVPROC) (void); -typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -typedef void (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); -typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); -typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); -typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); -typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); -#endif - -#ifndef GL_AMD_transform_feedback3_lines_triangles -#define GL_AMD_transform_feedback3_lines_triangles 1 -#endif +/* + * End system-specific stuff + **********************************************************************/ #ifdef __cplusplus } #endif -#endif -/* *INDENT-ON* */ -#endif /* NO_SDL_GLEXT */ +#endif /* __gl_h_ */ #endif /* !__IPHONEOS__ */ -#endif /* _SDL_opengl_h */ +#endif /* SDL_opengl_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_opengl_glext.h b/external/SDL2/SDL_opengl_glext.h new file mode 100644 index 0000000..6a402b1 --- /dev/null +++ b/external/SDL2/SDL_opengl_glext.h @@ -0,0 +1,11180 @@ +#ifndef __glext_h_ +#define __glext_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2013-2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 26745 $ on $Date: 2014-05-21 03:12:26 -0700 (Wed, 21 May 2014) $ +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#ifndef NOMINMAX /* don't define min() and max(). */ +#define NOMINMAX +#endif +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +#define GL_GLEXT_VERSION 20140521 + +/* Generated C header for: + * API: gl + * Profile: compatibility + * Versions considered: .* + * Versions emitted: 1\.[2-9]|[234]\.[0-9] + * Default extensions included: gl + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_RESCALE_NORMAL 0x803A +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_VERSION_1_2 */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_MULTISAMPLE_BIT 0x20000000 +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_SUBTRACT 0x84E7 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, void *img); +typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveTexture (GLenum texture); +GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); +GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, void *img); +GLAPI void APIENTRY glClientActiveTexture (GLenum texture); +GLAPI void APIENTRY glMultiTexCoord1d (GLenum target, GLdouble s); +GLAPI void APIENTRY glMultiTexCoord1dv (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord1f (GLenum target, GLfloat s); +GLAPI void APIENTRY glMultiTexCoord1fv (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord1i (GLenum target, GLint s); +GLAPI void APIENTRY glMultiTexCoord1iv (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord1s (GLenum target, GLshort s); +GLAPI void APIENTRY glMultiTexCoord1sv (GLenum target, const GLshort *v); +GLAPI void APIENTRY glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t); +GLAPI void APIENTRY glMultiTexCoord2dv (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t); +GLAPI void APIENTRY glMultiTexCoord2fv (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord2i (GLenum target, GLint s, GLint t); +GLAPI void APIENTRY glMultiTexCoord2iv (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord2s (GLenum target, GLshort s, GLshort t); +GLAPI void APIENTRY glMultiTexCoord2sv (GLenum target, const GLshort *v); +GLAPI void APIENTRY glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r); +GLAPI void APIENTRY glMultiTexCoord3dv (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r); +GLAPI void APIENTRY glMultiTexCoord3fv (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r); +GLAPI void APIENTRY glMultiTexCoord3iv (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r); +GLAPI void APIENTRY glMultiTexCoord3sv (GLenum target, const GLshort *v); +GLAPI void APIENTRY glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void APIENTRY glMultiTexCoord4dv (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void APIENTRY glMultiTexCoord4fv (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q); +GLAPI void APIENTRY glMultiTexCoord4iv (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void APIENTRY glMultiTexCoord4sv (GLenum target, const GLshort *v); +GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *m); +GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *m); +GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *m); +GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m); +#endif +#endif /* GL_VERSION_1_3 */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); +GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); +GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param); +GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params); +GLAPI void APIENTRY glFogCoordf (GLfloat coord); +GLAPI void APIENTRY glFogCoordfv (const GLfloat *coord); +GLAPI void APIENTRY glFogCoordd (GLdouble coord); +GLAPI void APIENTRY glFogCoorddv (const GLdouble *coord); +GLAPI void APIENTRY glFogCoordPointer (GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue); +GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *v); +GLAPI void APIENTRY glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue); +GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *v); +GLAPI void APIENTRY glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue); +GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *v); +GLAPI void APIENTRY glSecondaryColor3i (GLint red, GLint green, GLint blue); +GLAPI void APIENTRY glSecondaryColor3iv (const GLint *v); +GLAPI void APIENTRY glSecondaryColor3s (GLshort red, GLshort green, GLshort blue); +GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *v); +GLAPI void APIENTRY glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue); +GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *v); +GLAPI void APIENTRY glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue); +GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *v); +GLAPI void APIENTRY glSecondaryColor3us (GLushort red, GLushort green, GLushort blue); +GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *v); +GLAPI void APIENTRY glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glWindowPos2d (GLdouble x, GLdouble y); +GLAPI void APIENTRY glWindowPos2dv (const GLdouble *v); +GLAPI void APIENTRY glWindowPos2f (GLfloat x, GLfloat y); +GLAPI void APIENTRY glWindowPos2fv (const GLfloat *v); +GLAPI void APIENTRY glWindowPos2i (GLint x, GLint y); +GLAPI void APIENTRY glWindowPos2iv (const GLint *v); +GLAPI void APIENTRY glWindowPos2s (GLshort x, GLshort y); +GLAPI void APIENTRY glWindowPos2sv (const GLshort *v); +GLAPI void APIENTRY glWindowPos3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glWindowPos3dv (const GLdouble *v); +GLAPI void APIENTRY glWindowPos3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glWindowPos3fv (const GLfloat *v); +GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z); +GLAPI void APIENTRY glWindowPos3iv (const GLint *v); +GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glWindowPos3sv (const GLshort *v); +GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void APIENTRY glBlendEquation (GLenum mode); +#endif +#endif /* GL_VERSION_1_4 */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 +#include +#ifdef __MACOSX__ +typedef long GLsizeiptr; +typedef long GLintptr; +#else +typedef ptrdiff_t GLsizeiptr; +typedef ptrdiff_t GLintptr; +#endif +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_FOG_COORD_SRC 0x8450 +#define GL_FOG_COORD 0x8451 +#define GL_CURRENT_FOG_COORD 0x8453 +#define GL_FOG_COORD_ARRAY_TYPE 0x8454 +#define GL_FOG_COORD_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORD_ARRAY_POINTER 0x8456 +#define GL_FOG_COORD_ARRAY 0x8457 +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D +#define GL_SRC0_RGB 0x8580 +#define GL_SRC1_RGB 0x8581 +#define GL_SRC2_RGB 0x8582 +#define GL_SRC0_ALPHA 0x8588 +#define GL_SRC2_ALPHA 0x858A +typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data); +typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids); +GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); +GLAPI GLboolean APIENTRY glIsQuery (GLuint id); +GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id); +GLAPI void APIENTRY glEndQuery (GLenum target); +GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); +GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); +GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer); +GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, void *data); +GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access); +GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target); +GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); +#endif +#endif /* GL_VERSION_1_5 */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 +typedef char GLchar; +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_TEXTURE_COORDS 0x8871 +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); +GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader); +GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); +GLAPI void APIENTRY glCompileShader (GLuint shader); +GLAPI GLuint APIENTRY glCreateProgram (void); +GLAPI GLuint APIENTRY glCreateShader (GLenum type); +GLAPI void APIENTRY glDeleteProgram (GLuint program); +GLAPI void APIENTRY glDeleteShader (GLuint shader); +GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); +GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index); +GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); +GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); +GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); +GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); +GLAPI GLboolean APIENTRY glIsProgram (GLuint program); +GLAPI GLboolean APIENTRY glIsShader (GLuint shader); +GLAPI void APIENTRY glLinkProgram (GLuint program); +GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GLAPI void APIENTRY glUseProgram (GLuint program); +GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0); +GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glUniform1i (GLint location, GLint v0); +GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glValidateProgram (GLuint program); +GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); +GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x); +GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); +GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y); +GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +#endif +#endif /* GL_VERSION_2_0 */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +#endif +#endif /* GL_VERSION_2_1 */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 +typedef unsigned short GLhalf; +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_INDEX 0x8222 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_ALPHA_INTEGER 0x8D97 +typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); +typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index); +typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); +typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp); +typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode); +typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); +typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void *(APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); +typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data); +GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); +GLAPI void APIENTRY glEnablei (GLenum target, GLuint index); +GLAPI void APIENTRY glDisablei (GLenum target, GLuint index); +GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index); +GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode); +GLAPI void APIENTRY glEndTransformFeedback (void); +GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); +GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp); +GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode); +GLAPI void APIENTRY glEndConditionalRender (void); +GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); +GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x); +GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y); +GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z); +GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x); +GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y); +GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z); +GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v); +GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); +GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name); +GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); +GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0); +GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); +GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); +GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); +GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index); +GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); +GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); +GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer); +GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); +GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); +GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target); +GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); +GLAPI void APIENTRY glGenerateMipmap (GLenum target); +GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void *APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glBindVertexArray (GLuint array); +GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); +GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); +GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array); +#endif +#endif /* GL_VERSION_3_0 */ + +#ifndef GL_VERSION_3_1 +#define GL_VERSION_3_1 1 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index); +typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); +typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index); +GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); +GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); +GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +#endif +#endif /* GL_VERSION_3_1 */ + +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 +typedef struct __GLsync *GLsync; +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glxext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GL_EXT_timer_query extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif +typedef uint64_t GLuint64; +typedef int64_t GLint64; +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_DEPTH_CLAMP 0x864F +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex); +typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode); +typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync); +typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); +typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); +typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); +typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex); +GLAPI void APIENTRY glProvokingVertex (GLenum mode); +GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags); +GLAPI GLboolean APIENTRY glIsSync (GLsync sync); +GLAPI void APIENTRY glDeleteSync (GLsync sync); +GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); +GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); +GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val); +GLAPI void APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask); +#endif +#endif /* GL_VERSION_3_2 */ + +#ifndef GL_VERSION_3_3 +#define GL_VERSION_3_3 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 +#define GL_INT_2_10_10_10_REV 0x8D9F +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); +typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params); +typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value); +typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value); +typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords); +typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords); +typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color); +typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color); +typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color); +typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); +GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler); +GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); +GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); +GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param); +GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param); +GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params); +GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target); +GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params); +GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); +GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value); +GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value); +GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value); +GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value); +GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value); +GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value); +GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords); +GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords); +GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords); +GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords); +GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords); +GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords); +GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords); +GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords); +GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords); +GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords); +GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords); +GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords); +GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords); +GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords); +GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords); +GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords); +GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords); +GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords); +GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color); +GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color); +GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color); +GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color); +GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color); +GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color); +#endif +#endif /* GL_VERSION_3_3 */ + +#ifndef GL_VERSION_4_0 +#define GL_VERSION_4_0 1 +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MAX_VERTEX_STREAMS 0x8E71 +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B +#define GL_PATCHES 0x000E +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_ISOLINES 0x8E7A +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value); +typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); +typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); +typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params); +typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name); +typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices); +typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values); +typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values); +typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); +typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); +typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMinSampleShading (GLfloat value); +GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode); +GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst); +GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect); +GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect); +GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x); +GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y); +GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params); +GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name); +GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name); +GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); +GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices); +GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params); +GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values); +GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value); +GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values); +GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id); +GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); +GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); +GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id); +GLAPI void APIENTRY glPauseTransformFeedback (void); +GLAPI void APIENTRY glResumeTransformFeedback (void); +GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id); +GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream); +GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id); +GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index); +GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params); +#endif +#endif /* GL_VERSION_4_0 */ + +#ifndef GL_VERSION_4_1 +#define GL_VERSION_4_1 1 +#define GL_FIXED 0x140C +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_RGB565 0x8D62 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_MAX_VIEWPORTS 0x825B +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_UNDEFINED_VERTEX 0x8260 +typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); +typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); +typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings); +typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines); +typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v); +typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f); +typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); +typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glReleaseShaderCompiler (void); +GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f); +GLAPI void APIENTRY glClearDepthf (GLfloat d); +GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); +GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program); +GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program); +GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings); +GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline); +GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines); +GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines); +GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline); +GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params); +GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0); +GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0); +GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0); +GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0); +GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1); +GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); +GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); +GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline); +GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v); +GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v); +GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f); +GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data); +GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data); +#endif +#endif /* GL_VERSION_4_1 */ + +#ifndef GL_VERSION_4_2 +#define GL_VERSION_4_2 1 +#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 +#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 +#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 +#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A +#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B +#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C +#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D +#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C +#define GL_MAX_IMAGE_SAMPLES 0x906D +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); +GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers); +GLAPI void APIENTRY glTexStorage1D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount); +GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount); +#endif +#endif /* GL_VERSION_4_2 */ + +#ifndef GL_VERSION_4_3 +#define GL_VERSION_4_3 1 +typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9 +#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_BUFFER 0x82E0 +#define GL_SHADER 0x82E1 +#define GL_PROGRAM 0x82E2 +#define GL_QUERY 0x82E3 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_SAMPLER 0x82E6 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_INTERNALFORMAT_SUPPORTED 0x826F +#define GL_INTERNALFORMAT_PREFERRED 0x8270 +#define GL_INTERNALFORMAT_RED_SIZE 0x8271 +#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272 +#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273 +#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274 +#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275 +#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276 +#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277 +#define GL_INTERNALFORMAT_RED_TYPE 0x8278 +#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279 +#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A +#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B +#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C +#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D +#define GL_MAX_WIDTH 0x827E +#define GL_MAX_HEIGHT 0x827F +#define GL_MAX_DEPTH 0x8280 +#define GL_MAX_LAYERS 0x8281 +#define GL_MAX_COMBINED_DIMENSIONS 0x8282 +#define GL_COLOR_COMPONENTS 0x8283 +#define GL_DEPTH_COMPONENTS 0x8284 +#define GL_STENCIL_COMPONENTS 0x8285 +#define GL_COLOR_RENDERABLE 0x8286 +#define GL_DEPTH_RENDERABLE 0x8287 +#define GL_STENCIL_RENDERABLE 0x8288 +#define GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#define GL_FRAMEBUFFER_BLEND 0x828B +#define GL_READ_PIXELS 0x828C +#define GL_READ_PIXELS_FORMAT 0x828D +#define GL_READ_PIXELS_TYPE 0x828E +#define GL_TEXTURE_IMAGE_FORMAT 0x828F +#define GL_TEXTURE_IMAGE_TYPE 0x8290 +#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291 +#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292 +#define GL_MIPMAP 0x8293 +#define GL_MANUAL_GENERATE_MIPMAP 0x8294 +#define GL_AUTO_GENERATE_MIPMAP 0x8295 +#define GL_COLOR_ENCODING 0x8296 +#define GL_SRGB_READ 0x8297 +#define GL_SRGB_WRITE 0x8298 +#define GL_FILTER 0x829A +#define GL_VERTEX_TEXTURE 0x829B +#define GL_TESS_CONTROL_TEXTURE 0x829C +#define GL_TESS_EVALUATION_TEXTURE 0x829D +#define GL_GEOMETRY_TEXTURE 0x829E +#define GL_FRAGMENT_TEXTURE 0x829F +#define GL_COMPUTE_TEXTURE 0x82A0 +#define GL_TEXTURE_SHADOW 0x82A1 +#define GL_TEXTURE_GATHER 0x82A2 +#define GL_TEXTURE_GATHER_SHADOW 0x82A3 +#define GL_SHADER_IMAGE_LOAD 0x82A4 +#define GL_SHADER_IMAGE_STORE 0x82A5 +#define GL_SHADER_IMAGE_ATOMIC 0x82A6 +#define GL_IMAGE_TEXEL_SIZE 0x82A7 +#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8 +#define GL_IMAGE_PIXEL_FORMAT 0x82A9 +#define GL_IMAGE_PIXEL_TYPE 0x82AA +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF +#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1 +#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2 +#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3 +#define GL_CLEAR_BUFFER 0x82B4 +#define GL_TEXTURE_VIEW 0x82B5 +#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6 +#define GL_FULL_SUPPORT 0x82B7 +#define GL_CAVEAT_SUPPORT 0x82B8 +#define GL_IMAGE_CLASS_4_X_32 0x82B9 +#define GL_IMAGE_CLASS_2_X_32 0x82BA +#define GL_IMAGE_CLASS_1_X_32 0x82BB +#define GL_IMAGE_CLASS_4_X_16 0x82BC +#define GL_IMAGE_CLASS_2_X_16 0x82BD +#define GL_IMAGE_CLASS_1_X_16 0x82BE +#define GL_IMAGE_CLASS_4_X_8 0x82BF +#define GL_IMAGE_CLASS_2_X_8 0x82C0 +#define GL_IMAGE_CLASS_1_X_8 0x82C1 +#define GL_IMAGE_CLASS_11_11_10 0x82C2 +#define GL_IMAGE_CLASS_10_10_10_2 0x82C3 +#define GL_VIEW_CLASS_128_BITS 0x82C4 +#define GL_VIEW_CLASS_96_BITS 0x82C5 +#define GL_VIEW_CLASS_64_BITS 0x82C6 +#define GL_VIEW_CLASS_48_BITS 0x82C7 +#define GL_VIEW_CLASS_32_BITS 0x82C8 +#define GL_VIEW_CLASS_24_BITS 0x82C9 +#define GL_VIEW_CLASS_16_BITS 0x82CA +#define GL_VIEW_CLASS_8_BITS 0x82CB +#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC +#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD +#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE +#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF +#define GL_VIEW_CLASS_RGTC1_RED 0x82D0 +#define GL_VIEW_CLASS_RGTC2_RG 0x82D1 +#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_VERTEX_SUBROUTINE 0x92E8 +#define GL_TESS_CONTROL_SUBROUTINE 0x92E9 +#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA +#define GL_GEOMETRY_SUBROUTINE 0x92EB +#define GL_FRAGMENT_SUBROUTINE 0x92EC +#define GL_COMPUTE_SUBROUTINE 0x92ED +#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE +#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF +#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0 +#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1 +#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2 +#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8 +#define GL_NAME_LENGTH 0x92F9 +#define GL_TYPE 0x92FA +#define GL_ARRAY_SIZE 0x92FB +#define GL_OFFSET 0x92FC +#define GL_BLOCK_INDEX 0x92FD +#define GL_ARRAY_STRIDE 0x92FE +#define GL_MATRIX_STRIDE 0x92FF +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_LOCATION 0x930E +#define GL_LOCATION_INDEX 0x930F +#define GL_IS_PER_PATCH 0x92E7 +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB +#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC +#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD +#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_DISPLAY_LIST 0x82E7 +typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); +typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params); +typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); +typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); +typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); +typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect); +GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params); +GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level); +GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer); +GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); +GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name); +GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name); +GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name); +GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); +GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex); +GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor); +GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); +GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GLAPI void APIENTRY glPopDebugGroup (void); +GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif +#endif /* GL_VERSION_4_3 */ + +#ifndef GL_VERSION_4_4 +#define GL_VERSION_4_4 1 +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A +#define GL_MAP_PERSISTENT_BIT 0x0040 +#define GL_MAP_COHERENT_BIT 0x0080 +#define GL_DYNAMIC_STORAGE_BIT 0x0100 +#define GL_CLIENT_STORAGE_BIT 0x0200 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000 +#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F +#define GL_BUFFER_STORAGE_FLAGS 0x8220 +#define GL_CLEAR_TEXTURE 0x9365 +#define GL_LOCATION_COMPONENT 0x934A +#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B +#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C +#define GL_QUERY_BUFFER 0x9192 +#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000 +#define GL_QUERY_BUFFER_BINDING 0x9193 +#define GL_QUERY_RESULT_NO_WAIT 0x9194 +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 +typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers); +typedef void (APIENTRYP PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes); +typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); +typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); +typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferStorage (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +GLAPI void APIENTRY glClearTexImage (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glBindBuffersBase (GLenum target, GLuint first, GLsizei count, const GLuint *buffers); +GLAPI void APIENTRY glBindBuffersRange (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes); +GLAPI void APIENTRY glBindTextures (GLuint first, GLsizei count, const GLuint *textures); +GLAPI void APIENTRY glBindSamplers (GLuint first, GLsizei count, const GLuint *samplers); +GLAPI void APIENTRY glBindImageTextures (GLuint first, GLsizei count, const GLuint *textures); +GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides); +#endif +#endif /* GL_VERSION_4_4 */ + +#ifndef GL_ARB_ES2_compatibility +#define GL_ARB_ES2_compatibility 1 +#endif /* GL_ARB_ES2_compatibility */ + +#ifndef GL_ARB_ES3_compatibility +#define GL_ARB_ES3_compatibility 1 +#endif /* GL_ARB_ES3_compatibility */ + +#ifndef GL_ARB_arrays_of_arrays +#define GL_ARB_arrays_of_arrays 1 +#endif /* GL_ARB_arrays_of_arrays */ + +#ifndef GL_ARB_base_instance +#define GL_ARB_base_instance 1 +#endif /* GL_ARB_base_instance */ + +#ifndef GL_ARB_bindless_texture +#define GL_ARB_bindless_texture 1 +typedef uint64_t GLuint64EXT; +#define GL_UNSIGNED_INT64_ARB 0x140F +typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture); +typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle); +typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint64 APIENTRY glGetTextureHandleARB (GLuint texture); +GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleARB (GLuint texture, GLuint sampler); +GLAPI void APIENTRY glMakeTextureHandleResidentARB (GLuint64 handle); +GLAPI void APIENTRY glMakeTextureHandleNonResidentARB (GLuint64 handle); +GLAPI GLuint64 APIENTRY glGetImageHandleARB (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +GLAPI void APIENTRY glMakeImageHandleResidentARB (GLuint64 handle, GLenum access); +GLAPI void APIENTRY glMakeImageHandleNonResidentARB (GLuint64 handle); +GLAPI void APIENTRY glUniformHandleui64ARB (GLint location, GLuint64 value); +GLAPI void APIENTRY glUniformHandleui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniformHandleui64ARB (GLuint program, GLint location, GLuint64 value); +GLAPI void APIENTRY glProgramUniformHandleui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +GLAPI GLboolean APIENTRY glIsTextureHandleResidentARB (GLuint64 handle); +GLAPI GLboolean APIENTRY glIsImageHandleResidentARB (GLuint64 handle); +GLAPI void APIENTRY glVertexAttribL1ui64ARB (GLuint index, GLuint64EXT x); +GLAPI void APIENTRY glVertexAttribL1ui64vARB (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glGetVertexAttribLui64vARB (GLuint index, GLenum pname, GLuint64EXT *params); +#endif +#endif /* GL_ARB_bindless_texture */ + +#ifndef GL_ARB_blend_func_extended +#define GL_ARB_blend_func_extended 1 +#endif /* GL_ARB_blend_func_extended */ + +#ifndef GL_ARB_buffer_storage +#define GL_ARB_buffer_storage 1 +#endif /* GL_ARB_buffer_storage */ + +#ifndef GL_ARB_cl_event +#define GL_ARB_cl_event 1 +struct _cl_context; +struct _cl_event; +#define GL_SYNC_CL_EVENT_ARB 0x8240 +#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 +typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context *context, struct _cl_event *event, GLbitfield flags); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context *context, struct _cl_event *event, GLbitfield flags); +#endif +#endif /* GL_ARB_cl_event */ + +#ifndef GL_ARB_clear_buffer_object +#define GL_ARB_clear_buffer_object 1 +#endif /* GL_ARB_clear_buffer_object */ + +#ifndef GL_ARB_clear_texture +#define GL_ARB_clear_texture 1 +#endif /* GL_ARB_clear_texture */ + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D +typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp); +#endif +#endif /* GL_ARB_color_buffer_float */ + +#ifndef GL_ARB_compatibility +#define GL_ARB_compatibility 1 +#endif /* GL_ARB_compatibility */ + +#ifndef GL_ARB_compressed_texture_pixel_storage +#define GL_ARB_compressed_texture_pixel_storage 1 +#endif /* GL_ARB_compressed_texture_pixel_storage */ + +#ifndef GL_ARB_compute_shader +#define GL_ARB_compute_shader 1 +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#endif /* GL_ARB_compute_shader */ + +#ifndef GL_ARB_compute_variable_group_size +#define GL_ARB_compute_variable_group_size 1 +#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344 +#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB +#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345 +#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDispatchComputeGroupSizeARB (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z); +#endif +#endif /* GL_ARB_compute_variable_group_size */ + +#ifndef GL_ARB_conservative_depth +#define GL_ARB_conservative_depth 1 +#endif /* GL_ARB_conservative_depth */ + +#ifndef GL_ARB_copy_buffer +#define GL_ARB_copy_buffer 1 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#endif /* GL_ARB_copy_buffer */ + +#ifndef GL_ARB_copy_image +#define GL_ARB_copy_image 1 +#endif /* GL_ARB_copy_image */ + +#ifndef GL_ARB_debug_output +#define GL_ARB_debug_output 1 +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 +typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const void *userParam); +GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +#endif +#endif /* GL_ARB_debug_output */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 +#endif /* GL_ARB_depth_buffer_float */ + +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 +#endif /* GL_ARB_depth_clamp */ + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B +#endif /* GL_ARB_depth_texture */ + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 +typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawBuffersARB (GLsizei n, const GLenum *bufs); +#endif +#endif /* GL_ARB_draw_buffers */ + +#ifndef GL_ARB_draw_buffers_blend +#define GL_ARB_draw_buffers_blend 1 +typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode); +GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst); +GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#endif +#endif /* GL_ARB_draw_buffers_blend */ + +#ifndef GL_ARB_draw_elements_base_vertex +#define GL_ARB_draw_elements_base_vertex 1 +#endif /* GL_ARB_draw_elements_base_vertex */ + +#ifndef GL_ARB_draw_indirect +#define GL_ARB_draw_indirect 1 +#endif /* GL_ARB_draw_indirect */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#endif +#endif /* GL_ARB_draw_instanced */ + +#ifndef GL_ARB_enhanced_layouts +#define GL_ARB_enhanced_layouts 1 +#endif /* GL_ARB_enhanced_layouts */ + +#ifndef GL_ARB_explicit_attrib_location +#define GL_ARB_explicit_attrib_location 1 +#endif /* GL_ARB_explicit_attrib_location */ + +#ifndef GL_ARB_explicit_uniform_location +#define GL_ARB_explicit_uniform_location 1 +#endif /* GL_ARB_explicit_uniform_location */ + +#ifndef GL_ARB_fragment_coord_conventions +#define GL_ARB_fragment_coord_conventions 1 +#endif /* GL_ARB_fragment_coord_conventions */ + +#ifndef GL_ARB_fragment_layer_viewport +#define GL_ARB_fragment_layer_viewport 1 +#endif /* GL_ARB_fragment_layer_viewport */ + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string); +typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramStringARB (GLenum target, GLenum format, GLsizei len, const void *string); +GLAPI void APIENTRY glBindProgramARB (GLenum target, GLuint program); +GLAPI void APIENTRY glDeleteProgramsARB (GLsizei n, const GLuint *programs); +GLAPI void APIENTRY glGenProgramsARB (GLsizei n, GLuint *programs); +GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params); +GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params); +GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params); +GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params); +GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params); +GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params); +GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params); +GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params); +GLAPI void APIENTRY glGetProgramivARB (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetProgramStringARB (GLenum target, GLenum pname, void *string); +GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program); +#endif +#endif /* GL_ARB_fragment_program */ + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 +#endif /* GL_ARB_fragment_program_shadow */ + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#endif /* GL_ARB_fragment_shader */ + +#ifndef GL_ARB_framebuffer_no_attachments +#define GL_ARB_framebuffer_no_attachments 1 +#endif /* GL_ARB_framebuffer_no_attachments */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 +#endif /* GL_ARB_framebuffer_object */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 +#endif /* GL_ARB_framebuffer_sRGB */ + +#ifndef GL_KHR_context_flush_control +#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC +#endif /* GL_KHR_context_flush_control */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 +#define GL_LINES_ADJACENCY_ARB 0x000A +#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B +#define GL_TRIANGLES_ADJACENCY_ARB 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value); +GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#endif +#endif /* GL_ARB_geometry_shader4 */ + +#ifndef GL_ARB_get_program_binary +#define GL_ARB_get_program_binary 1 +#endif /* GL_ARB_get_program_binary */ + +#ifndef GL_ARB_gpu_shader5 +#define GL_ARB_gpu_shader5 1 +#endif /* GL_ARB_gpu_shader5 */ + +#ifndef GL_ARB_gpu_shader_fp64 +#define GL_ARB_gpu_shader_fp64 1 +#endif /* GL_ARB_gpu_shader_fp64 */ + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 +typedef unsigned short GLhalfARB; +#define GL_HALF_FLOAT_ARB 0x140B +#endif /* GL_ARB_half_float_pixel */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 +#endif /* GL_ARB_half_float_vertex */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_EQUATION 0x8009 +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 +typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, void *image); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); +typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); +GLAPI void APIENTRY glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glGetColorTable (GLenum target, GLenum format, GLenum type, void *table); +GLAPI void APIENTRY glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); +GLAPI void APIENTRY glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); +GLAPI void APIENTRY glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params); +GLAPI void APIENTRY glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glConvolutionParameteri (GLenum target, GLenum pname, GLint params); +GLAPI void APIENTRY glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, void *image); +GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetSeparableFilter (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); +GLAPI void APIENTRY glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); +GLAPI void APIENTRY glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +GLAPI void APIENTRY glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +GLAPI void APIENTRY glMinmax (GLenum target, GLenum internalformat, GLboolean sink); +GLAPI void APIENTRY glResetHistogram (GLenum target); +GLAPI void APIENTRY glResetMinmax (GLenum target); +#endif +#endif /* GL_ARB_imaging */ + +#ifndef GL_ARB_indirect_parameters +#define GL_ARB_indirect_parameters 1 +#define GL_PARAMETER_BUFFER_ARB 0x80EE +#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#endif +#endif /* GL_ARB_indirect_parameters */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE +typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor); +#endif +#endif /* GL_ARB_instanced_arrays */ + +#ifndef GL_ARB_internalformat_query +#define GL_ARB_internalformat_query 1 +#endif /* GL_ARB_internalformat_query */ + +#ifndef GL_ARB_internalformat_query2 +#define GL_ARB_internalformat_query2 1 +#define GL_SRGB_DECODE_ARB 0x8299 +#endif /* GL_ARB_internalformat_query2 */ + +#ifndef GL_ARB_invalidate_subdata +#define GL_ARB_invalidate_subdata 1 +#endif /* GL_ARB_invalidate_subdata */ + +#ifndef GL_ARB_map_buffer_alignment +#define GL_ARB_map_buffer_alignment 1 +#endif /* GL_ARB_map_buffer_alignment */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 +#endif /* GL_ARB_map_buffer_range */ + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 +typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices); +typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices); +typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices); +typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint index); +GLAPI void APIENTRY glMatrixIndexubvARB (GLint size, const GLubyte *indices); +GLAPI void APIENTRY glMatrixIndexusvARB (GLint size, const GLushort *indices); +GLAPI void APIENTRY glMatrixIndexuivARB (GLint size, const GLuint *indices); +GLAPI void APIENTRY glMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer); +#endif +#endif /* GL_ARB_matrix_palette */ + +#ifndef GL_ARB_multi_bind +#define GL_ARB_multi_bind 1 +#endif /* GL_ARB_multi_bind */ + +#ifndef GL_ARB_multi_draw_indirect +#define GL_ARB_multi_draw_indirect 1 +#endif /* GL_ARB_multi_draw_indirect */ + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLfloat value, GLboolean invert); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSampleCoverageARB (GLfloat value, GLboolean invert); +#endif +#endif /* GL_ARB_multisample */ + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveTextureARB (GLenum texture); +GLAPI void APIENTRY glClientActiveTextureARB (GLenum texture); +GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum target, GLdouble s); +GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum target, GLfloat s); +GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum target, GLint s); +GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum target, GLshort s); +GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum target, const GLshort *v); +GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t); +GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t); +GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum target, GLint s, GLint t); +GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t); +GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum target, const GLshort *v); +GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r); +GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r); +GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r); +GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r); +GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum target, const GLshort *v); +GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum target, const GLdouble *v); +GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum target, const GLfloat *v); +GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q); +GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum target, const GLint *v); +GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum target, const GLshort *v); +#endif +#endif /* GL_ARB_multitexture */ + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 +typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenQueriesARB (GLsizei n, GLuint *ids); +GLAPI void APIENTRY glDeleteQueriesARB (GLsizei n, const GLuint *ids); +GLAPI GLboolean APIENTRY glIsQueryARB (GLuint id); +GLAPI void APIENTRY glBeginQueryARB (GLenum target, GLuint id); +GLAPI void APIENTRY glEndQueryARB (GLenum target); +GLAPI void APIENTRY glGetQueryivARB (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params); +#endif +#endif /* GL_ARB_occlusion_query */ + +#ifndef GL_ARB_occlusion_query2 +#define GL_ARB_occlusion_query2 1 +#endif /* GL_ARB_occlusion_query2 */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF +#endif /* GL_ARB_pixel_buffer_object */ + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 +typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameterfARB (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params); +#endif +#endif /* GL_ARB_point_parameters */ + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 +#endif /* GL_ARB_point_sprite */ + +#ifndef GL_ARB_program_interface_query +#define GL_ARB_program_interface_query 1 +#endif /* GL_ARB_program_interface_query */ + +#ifndef GL_ARB_provoking_vertex +#define GL_ARB_provoking_vertex 1 +#endif /* GL_ARB_provoking_vertex */ + +#ifndef GL_ARB_query_buffer_object +#define GL_ARB_query_buffer_object 1 +#endif /* GL_ARB_query_buffer_object */ + +#ifndef GL_ARB_robust_buffer_access_behavior +#define GL_ARB_robust_buffer_access_behavior 1 +#endif /* GL_ARB_robust_buffer_access_behavior */ + +#ifndef GL_ARB_robustness +#define GL_ARB_robustness 1 +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 +typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void); +typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img); +typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void *img); +typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); +typedef void (APIENTRYP PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v); +typedef void (APIENTRYP PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v); +typedef void (APIENTRYP PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v); +typedef void (APIENTRYP PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values); +typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values); +typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values); +typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern); +typedef void (APIENTRYP PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table); +typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image); +typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span); +typedef void (APIENTRYP PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values); +typedef void (APIENTRYP PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void); +GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img); +GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, void *img); +GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params); +GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params); +GLAPI void APIENTRY glGetnMapdvARB (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v); +GLAPI void APIENTRY glGetnMapfvARB (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v); +GLAPI void APIENTRY glGetnMapivARB (GLenum target, GLenum query, GLsizei bufSize, GLint *v); +GLAPI void APIENTRY glGetnPixelMapfvARB (GLenum map, GLsizei bufSize, GLfloat *values); +GLAPI void APIENTRY glGetnPixelMapuivARB (GLenum map, GLsizei bufSize, GLuint *values); +GLAPI void APIENTRY glGetnPixelMapusvARB (GLenum map, GLsizei bufSize, GLushort *values); +GLAPI void APIENTRY glGetnPolygonStippleARB (GLsizei bufSize, GLubyte *pattern); +GLAPI void APIENTRY glGetnColorTableARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table); +GLAPI void APIENTRY glGetnConvolutionFilterARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image); +GLAPI void APIENTRY glGetnSeparableFilterARB (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span); +GLAPI void APIENTRY glGetnHistogramARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values); +GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values); +#endif +#endif /* GL_ARB_robustness */ + +#ifndef GL_ARB_robustness_isolation +#define GL_ARB_robustness_isolation 1 +#endif /* GL_ARB_robustness_isolation */ + +#ifndef GL_ARB_sample_shading +#define GL_ARB_sample_shading 1 +#define GL_SAMPLE_SHADING_ARB 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 +typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value); +#endif +#endif /* GL_ARB_sample_shading */ + +#ifndef GL_ARB_sampler_objects +#define GL_ARB_sampler_objects 1 +#endif /* GL_ARB_sampler_objects */ + +#ifndef GL_ARB_seamless_cube_map +#define GL_ARB_seamless_cube_map 1 +#endif /* GL_ARB_seamless_cube_map */ + +#ifndef GL_ARB_seamless_cubemap_per_texture +#define GL_ARB_seamless_cubemap_per_texture 1 +#endif /* GL_ARB_seamless_cubemap_per_texture */ + +#ifndef GL_ARB_separate_shader_objects +#define GL_ARB_separate_shader_objects 1 +#endif /* GL_ARB_separate_shader_objects */ + +#ifndef GL_ARB_shader_atomic_counters +#define GL_ARB_shader_atomic_counters 1 +#endif /* GL_ARB_shader_atomic_counters */ + +#ifndef GL_ARB_shader_bit_encoding +#define GL_ARB_shader_bit_encoding 1 +#endif /* GL_ARB_shader_bit_encoding */ + +#ifndef GL_ARB_shader_draw_parameters +#define GL_ARB_shader_draw_parameters 1 +#endif /* GL_ARB_shader_draw_parameters */ + +#ifndef GL_ARB_shader_group_vote +#define GL_ARB_shader_group_vote 1 +#endif /* GL_ARB_shader_group_vote */ + +#ifndef GL_ARB_shader_image_load_store +#define GL_ARB_shader_image_load_store 1 +#endif /* GL_ARB_shader_image_load_store */ + +#ifndef GL_ARB_shader_image_size +#define GL_ARB_shader_image_size 1 +#endif /* GL_ARB_shader_image_size */ + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif +typedef char GLcharARB; +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length); +typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); +typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); +typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); +typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB obj); +GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum pname); +GLAPI void APIENTRY glDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj); +GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum shaderType); +GLAPI void APIENTRY glShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length); +GLAPI void APIENTRY glCompileShaderARB (GLhandleARB shaderObj); +GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void); +GLAPI void APIENTRY glAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj); +GLAPI void APIENTRY glLinkProgramARB (GLhandleARB programObj); +GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB programObj); +GLAPI void APIENTRY glValidateProgramARB (GLhandleARB programObj); +GLAPI void APIENTRY glUniform1fARB (GLint location, GLfloat v0); +GLAPI void APIENTRY glUniform2fARB (GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glUniform1iARB (GLint location, GLint v0); +GLAPI void APIENTRY glUniform2iARB (GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glUniform1fvARB (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform2fvARB (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform3fvARB (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform4fvARB (GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glUniform1ivARB (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform2ivARB (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform3ivARB (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniform4ivARB (GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); +GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); +GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name); +GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params); +GLAPI void APIENTRY glGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params); +GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); +#endif +#endif /* GL_ARB_shader_objects */ + +#ifndef GL_ARB_shader_precision +#define GL_ARB_shader_precision 1 +#endif /* GL_ARB_shader_precision */ + +#ifndef GL_ARB_shader_stencil_export +#define GL_ARB_shader_stencil_export 1 +#endif /* GL_ARB_shader_stencil_export */ + +#ifndef GL_ARB_shader_storage_buffer_object +#define GL_ARB_shader_storage_buffer_object 1 +#endif /* GL_ARB_shader_storage_buffer_object */ + +#ifndef GL_ARB_shader_subroutine +#define GL_ARB_shader_subroutine 1 +#endif /* GL_ARB_shader_subroutine */ + +#ifndef GL_ARB_shader_texture_lod +#define GL_ARB_shader_texture_lod 1 +#endif /* GL_ARB_shader_texture_lod */ + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C +#endif /* GL_ARB_shading_language_100 */ + +#ifndef GL_ARB_shading_language_420pack +#define GL_ARB_shading_language_420pack 1 +#endif /* GL_ARB_shading_language_420pack */ + +#ifndef GL_ARB_shading_language_include +#define GL_ARB_shading_language_include 1 +#define GL_SHADER_INCLUDE_ARB 0x8DAE +#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 +#define GL_NAMED_STRING_TYPE_ARB 0x8DEA +typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); +typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); +typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length); +typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name); +typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); +typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string); +GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name); +GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length); +GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name); +GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string); +GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params); +#endif +#endif /* GL_ARB_shading_language_include */ + +#ifndef GL_ARB_shading_language_packing +#define GL_ARB_shading_language_packing 1 +#endif /* GL_ARB_shading_language_packing */ + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E +#endif /* GL_ARB_shadow */ + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF +#endif /* GL_ARB_shadow_ambient */ + +#ifndef GL_ARB_sparse_texture +#define GL_ARB_sparse_texture 1 +#define GL_TEXTURE_SPARSE_ARB 0x91A6 +#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7 +#define GL_MIN_SPARSE_LEVEL_ARB 0x919B +#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8 +#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195 +#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196 +#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197 +#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198 +#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199 +#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A +#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9 +typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +#endif +#endif /* GL_ARB_sparse_texture */ + +#ifndef GL_ARB_stencil_texturing +#define GL_ARB_stencil_texturing 1 +#endif /* GL_ARB_stencil_texturing */ + +#ifndef GL_ARB_sync +#define GL_ARB_sync 1 +#endif /* GL_ARB_sync */ + +#ifndef GL_ARB_tessellation_shader +#define GL_ARB_tessellation_shader 1 +#endif /* GL_ARB_tessellation_shader */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 +#define GL_CLAMP_TO_BORDER_ARB 0x812D +#endif /* GL_ARB_texture_border_clamp */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E +typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer); +#endif +#endif /* GL_ARB_texture_buffer_object */ + +#ifndef GL_ARB_texture_buffer_object_rgb32 +#define GL_ARB_texture_buffer_object_rgb32 1 +#endif /* GL_ARB_texture_buffer_object_rgb32 */ + +#ifndef GL_ARB_texture_buffer_range +#define GL_ARB_texture_buffer_range 1 +#endif /* GL_ARB_texture_buffer_range */ + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void *img); +#endif +#endif /* GL_ARB_texture_compression */ + +#ifndef GL_ARB_texture_compression_bptc +#define GL_ARB_texture_compression_bptc 1 +#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F +#endif /* GL_ARB_texture_compression_bptc */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 +#endif /* GL_ARB_texture_compression_rgtc */ + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif /* GL_ARB_texture_cube_map */ + +#ifndef GL_ARB_texture_cube_map_array +#define GL_ARB_texture_cube_map_array 1 +#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#endif /* GL_ARB_texture_cube_map_array */ + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 +#endif /* GL_ARB_texture_env_add */ + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#endif /* GL_ARB_texture_env_combine */ + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 +#endif /* GL_ARB_texture_env_crossbar */ + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF +#endif /* GL_ARB_texture_env_dot3 */ + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#endif /* GL_ARB_texture_float */ + +#ifndef GL_ARB_texture_gather +#define GL_ARB_texture_gather 1 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F +#endif /* GL_ARB_texture_gather */ + +#ifndef GL_ARB_texture_mirror_clamp_to_edge +#define GL_ARB_texture_mirror_clamp_to_edge 1 +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 +#define GL_MIRRORED_REPEAT_ARB 0x8370 +#endif /* GL_ARB_texture_mirrored_repeat */ + +#ifndef GL_ARB_texture_multisample +#define GL_ARB_texture_multisample 1 +#endif /* GL_ARB_texture_multisample */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 +#endif /* GL_ARB_texture_non_power_of_two */ + +#ifndef GL_ARB_texture_query_levels +#define GL_ARB_texture_query_levels 1 +#endif /* GL_ARB_texture_query_levels */ + +#ifndef GL_ARB_texture_query_lod +#define GL_ARB_texture_query_lod 1 +#endif /* GL_ARB_texture_query_lod */ + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#endif /* GL_ARB_texture_rectangle */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 +#endif /* GL_ARB_texture_rg */ + +#ifndef GL_ARB_texture_rgb10_a2ui +#define GL_ARB_texture_rgb10_a2ui 1 +#endif /* GL_ARB_texture_rgb10_a2ui */ + +#ifndef GL_ARB_texture_stencil8 +#define GL_ARB_texture_stencil8 1 +#endif /* GL_ARB_texture_stencil8 */ + +#ifndef GL_ARB_texture_storage +#define GL_ARB_texture_storage 1 +#endif /* GL_ARB_texture_storage */ + +#ifndef GL_ARB_texture_storage_multisample +#define GL_ARB_texture_storage_multisample 1 +#endif /* GL_ARB_texture_storage_multisample */ + +#ifndef GL_ARB_texture_swizzle +#define GL_ARB_texture_swizzle 1 +#endif /* GL_ARB_texture_swizzle */ + +#ifndef GL_ARB_texture_view +#define GL_ARB_texture_view 1 +#endif /* GL_ARB_texture_view */ + +#ifndef GL_ARB_timer_query +#define GL_ARB_timer_query 1 +#endif /* GL_ARB_timer_query */ + +#ifndef GL_ARB_transform_feedback2 +#define GL_ARB_transform_feedback2 1 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#endif /* GL_ARB_transform_feedback2 */ + +#ifndef GL_ARB_transform_feedback3 +#define GL_ARB_transform_feedback3 1 +#endif /* GL_ARB_transform_feedback3 */ + +#ifndef GL_ARB_transform_feedback_instanced +#define GL_ARB_transform_feedback_instanced 1 +#endif /* GL_ARB_transform_feedback_instanced */ + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *m); +GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *m); +GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *m); +GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m); +#endif +#endif /* GL_ARB_transpose_matrix */ + +#ifndef GL_ARB_uniform_buffer_object +#define GL_ARB_uniform_buffer_object 1 +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#endif /* GL_ARB_uniform_buffer_object */ + +#ifndef GL_ARB_vertex_array_bgra +#define GL_ARB_vertex_array_bgra 1 +#endif /* GL_ARB_vertex_array_bgra */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 +#endif /* GL_ARB_vertex_array_object */ + +#ifndef GL_ARB_vertex_attrib_64bit +#define GL_ARB_vertex_attrib_64bit 1 +#endif /* GL_ARB_vertex_attrib_64bit */ + +#ifndef GL_ARB_vertex_attrib_binding +#define GL_ARB_vertex_attrib_binding 1 +#endif /* GL_ARB_vertex_attrib_binding */ + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F +typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights); +typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights); +typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights); +typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights); +typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights); +typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights); +typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights); +typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights); +typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWeightbvARB (GLint size, const GLbyte *weights); +GLAPI void APIENTRY glWeightsvARB (GLint size, const GLshort *weights); +GLAPI void APIENTRY glWeightivARB (GLint size, const GLint *weights); +GLAPI void APIENTRY glWeightfvARB (GLint size, const GLfloat *weights); +GLAPI void APIENTRY glWeightdvARB (GLint size, const GLdouble *weights); +GLAPI void APIENTRY glWeightubvARB (GLint size, const GLubyte *weights); +GLAPI void APIENTRY glWeightusvARB (GLint size, const GLushort *weights); +GLAPI void APIENTRY glWeightuivARB (GLint size, const GLuint *weights); +GLAPI void APIENTRY glWeightPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glVertexBlendARB (GLint count); +#endif +#endif /* GL_ARB_vertex_blend */ + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 +#ifdef __MACOSX__ /* The OS X headers haven't caught up with Khronos yet */ +typedef long GLsizeiptrARB; +typedef long GLintptrARB; +#else +typedef ptrdiff_t GLsizeiptrARB; +typedef ptrdiff_t GLintptrARB; +#endif +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA +typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); +typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data); +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data); +typedef void *(APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, void **params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindBufferARB (GLenum target, GLuint buffer); +GLAPI void APIENTRY glDeleteBuffersARB (GLsizei n, const GLuint *buffers); +GLAPI void APIENTRY glGenBuffersARB (GLsizei n, GLuint *buffers); +GLAPI GLboolean APIENTRY glIsBufferARB (GLuint buffer); +GLAPI void APIENTRY glBufferDataARB (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage); +GLAPI void APIENTRY glBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data); +GLAPI void APIENTRY glGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data); +GLAPI void *APIENTRY glMapBufferARB (GLenum target, GLenum access); +GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum target); +GLAPI void APIENTRY glGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetBufferPointervARB (GLenum target, GLenum pname, void **params); +#endif +#endif /* GL_ARB_vertex_buffer_object */ + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void **pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttrib1dARB (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib1fARB (GLuint index, GLfloat x); +GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib1sARB (GLuint index, GLshort x); +GLAPI void APIENTRY glVertexAttrib1svARB (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y); +GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib2sARB (GLuint index, GLshort x, GLshort y); +GLAPI void APIENTRY glVertexAttrib2svARB (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glVertexAttrib3svARB (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void APIENTRY glVertexAttrib4svARB (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint index); +GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint index); +GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint index, GLenum pname, void **pointer); +#endif +#endif /* GL_ARB_vertex_program */ + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name); +GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name); +#endif +#endif /* GL_ARB_vertex_shader */ + +#ifndef GL_ARB_vertex_type_10f_11f_11f_rev +#define GL_ARB_vertex_type_10f_11f_11f_rev 1 +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ + +#ifndef GL_ARB_vertex_type_2_10_10_10_rev +#define GL_ARB_vertex_type_2_10_10_10_rev 1 +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ + +#ifndef GL_ARB_viewport_array +#define GL_ARB_viewport_array 1 +#endif /* GL_ARB_viewport_array */ + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 +typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWindowPos2dARB (GLdouble x, GLdouble y); +GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *v); +GLAPI void APIENTRY glWindowPos2fARB (GLfloat x, GLfloat y); +GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *v); +GLAPI void APIENTRY glWindowPos2iARB (GLint x, GLint y); +GLAPI void APIENTRY glWindowPos2ivARB (const GLint *v); +GLAPI void APIENTRY glWindowPos2sARB (GLshort x, GLshort y); +GLAPI void APIENTRY glWindowPos2svARB (const GLshort *v); +GLAPI void APIENTRY glWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *v); +GLAPI void APIENTRY glWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *v); +GLAPI void APIENTRY glWindowPos3iARB (GLint x, GLint y, GLint z); +GLAPI void APIENTRY glWindowPos3ivARB (const GLint *v); +GLAPI void APIENTRY glWindowPos3sARB (GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v); +#endif +#endif /* GL_ARB_window_pos */ + +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 +#endif /* GL_KHR_debug */ + +#ifndef GL_KHR_texture_compression_astc_hdr +#define GL_KHR_texture_compression_astc_hdr 1 +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif /* GL_KHR_texture_compression_astc_hdr */ + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_KHR_texture_compression_astc_ldr 1 +#endif /* GL_KHR_texture_compression_astc_ldr */ + +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 +typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1BVOESPROC) (GLenum texture, const GLbyte *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2BOESPROC) (GLenum texture, GLbyte s, GLbyte t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2BVOESPROC) (GLenum texture, const GLbyte *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3BVOESPROC) (GLenum texture, const GLbyte *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4BVOESPROC) (GLenum texture, const GLbyte *coords); +typedef void (APIENTRYP PFNGLTEXCOORD1BOESPROC) (GLbyte s); +typedef void (APIENTRYP PFNGLTEXCOORD1BVOESPROC) (const GLbyte *coords); +typedef void (APIENTRYP PFNGLTEXCOORD2BOESPROC) (GLbyte s, GLbyte t); +typedef void (APIENTRYP PFNGLTEXCOORD2BVOESPROC) (const GLbyte *coords); +typedef void (APIENTRYP PFNGLTEXCOORD3BOESPROC) (GLbyte s, GLbyte t, GLbyte r); +typedef void (APIENTRYP PFNGLTEXCOORD3BVOESPROC) (const GLbyte *coords); +typedef void (APIENTRYP PFNGLTEXCOORD4BOESPROC) (GLbyte s, GLbyte t, GLbyte r, GLbyte q); +typedef void (APIENTRYP PFNGLTEXCOORD4BVOESPROC) (const GLbyte *coords); +typedef void (APIENTRYP PFNGLVERTEX2BOESPROC) (GLbyte x); +typedef void (APIENTRYP PFNGLVERTEX2BVOESPROC) (const GLbyte *coords); +typedef void (APIENTRYP PFNGLVERTEX3BOESPROC) (GLbyte x, GLbyte y); +typedef void (APIENTRYP PFNGLVERTEX3BVOESPROC) (const GLbyte *coords); +typedef void (APIENTRYP PFNGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z); +typedef void (APIENTRYP PFNGLVERTEX4BVOESPROC) (const GLbyte *coords); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiTexCoord1bOES (GLenum texture, GLbyte s); +GLAPI void APIENTRY glMultiTexCoord1bvOES (GLenum texture, const GLbyte *coords); +GLAPI void APIENTRY glMultiTexCoord2bOES (GLenum texture, GLbyte s, GLbyte t); +GLAPI void APIENTRY glMultiTexCoord2bvOES (GLenum texture, const GLbyte *coords); +GLAPI void APIENTRY glMultiTexCoord3bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r); +GLAPI void APIENTRY glMultiTexCoord3bvOES (GLenum texture, const GLbyte *coords); +GLAPI void APIENTRY glMultiTexCoord4bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q); +GLAPI void APIENTRY glMultiTexCoord4bvOES (GLenum texture, const GLbyte *coords); +GLAPI void APIENTRY glTexCoord1bOES (GLbyte s); +GLAPI void APIENTRY glTexCoord1bvOES (const GLbyte *coords); +GLAPI void APIENTRY glTexCoord2bOES (GLbyte s, GLbyte t); +GLAPI void APIENTRY glTexCoord2bvOES (const GLbyte *coords); +GLAPI void APIENTRY glTexCoord3bOES (GLbyte s, GLbyte t, GLbyte r); +GLAPI void APIENTRY glTexCoord3bvOES (const GLbyte *coords); +GLAPI void APIENTRY glTexCoord4bOES (GLbyte s, GLbyte t, GLbyte r, GLbyte q); +GLAPI void APIENTRY glTexCoord4bvOES (const GLbyte *coords); +GLAPI void APIENTRY glVertex2bOES (GLbyte x); +GLAPI void APIENTRY glVertex2bvOES (const GLbyte *coords); +GLAPI void APIENTRY glVertex3bOES (GLbyte x, GLbyte y); +GLAPI void APIENTRY glVertex3bvOES (const GLbyte *coords); +GLAPI void APIENTRY glVertex4bOES (GLbyte x, GLbyte y, GLbyte z); +GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords); +#endif +#endif /* GL_OES_byte_coordinates */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif /* GL_OES_compressed_paletted_texture */ + +#ifndef GL_OES_fixed_point +#define GL_OES_fixed_point 1 +typedef GLint GLfixed; +#define GL_FIXED_OES 0x140C +typedef void (APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref); +typedef void (APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +typedef void (APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLfixed depth); +typedef void (APIENTRYP PFNGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation); +typedef void (APIENTRYP PFNGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +typedef void (APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLfixed n, GLfixed f); +typedef void (APIENTRYP PFNGLFOGXOESPROC) (GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *param); +typedef void (APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); +typedef void (APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum plane, GLfixed *equation); +typedef void (APIENTRYP PFNGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *param); +typedef void (APIENTRYP PFNGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params); +typedef void (APIENTRYP PFNGLLINEWIDTHXOESPROC) (GLfixed width); +typedef void (APIENTRYP PFNGLLOADMATRIXXOESPROC) (const GLfixed *m); +typedef void (APIENTRYP PFNGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *param); +typedef void (APIENTRYP PFNGLMULTMATRIXXOESPROC) (const GLfixed *m); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +typedef void (APIENTRYP PFNGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz); +typedef void (APIENTRYP PFNGLORTHOXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); +typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params); +typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size); +typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units); +typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert); +typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); +typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); +typedef void (APIENTRYP PFNGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); +typedef void (APIENTRYP PFNGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); +typedef void (APIENTRYP PFNGLACCUMXOESPROC) (GLenum op, GLfixed value); +typedef void (APIENTRYP PFNGLBITMAPXOESPROC) (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap); +typedef void (APIENTRYP PFNGLBLENDCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +typedef void (APIENTRYP PFNGLCLEARACCUMXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +typedef void (APIENTRYP PFNGLCOLOR3XOESPROC) (GLfixed red, GLfixed green, GLfixed blue); +typedef void (APIENTRYP PFNGLCOLOR3XVOESPROC) (const GLfixed *components); +typedef void (APIENTRYP PFNGLCOLOR4XVOESPROC) (const GLfixed *components); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); +typedef void (APIENTRYP PFNGLEVALCOORD1XOESPROC) (GLfixed u); +typedef void (APIENTRYP PFNGLEVALCOORD1XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLEVALCOORD2XOESPROC) (GLfixed u, GLfixed v); +typedef void (APIENTRYP PFNGLEVALCOORD2XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLFEEDBACKBUFFERXOESPROC) (GLsizei n, GLenum type, const GLfixed *buffer); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLGETLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLGETMAPXVOESPROC) (GLenum target, GLenum query, GLfixed *v); +typedef void (APIENTRYP PFNGLGETMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLGETPIXELMAPXVPROC) (GLenum map, GLint size, GLfixed *values); +typedef void (APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERXVOESPROC) (GLenum target, GLint level, GLenum pname, GLfixed *params); +typedef void (APIENTRYP PFNGLINDEXXOESPROC) (GLfixed component); +typedef void (APIENTRYP PFNGLINDEXXVOESPROC) (const GLfixed *component); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXXOESPROC) (const GLfixed *m); +typedef void (APIENTRYP PFNGLMAP1XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points); +typedef void (APIENTRYP PFNGLMAP2XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points); +typedef void (APIENTRYP PFNGLMAPGRID1XOESPROC) (GLint n, GLfixed u1, GLfixed u2); +typedef void (APIENTRYP PFNGLMAPGRID2XOESPROC) (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXXOESPROC) (const GLfixed *m); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1XOESPROC) (GLenum texture, GLfixed s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1XVOESPROC) (GLenum texture, const GLfixed *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2XOESPROC) (GLenum texture, GLfixed s, GLfixed t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2XVOESPROC) (GLenum texture, const GLfixed *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3XVOESPROC) (GLenum texture, const GLfixed *coords); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4XVOESPROC) (GLenum texture, const GLfixed *coords); +typedef void (APIENTRYP PFNGLNORMAL3XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLPASSTHROUGHXOESPROC) (GLfixed token); +typedef void (APIENTRYP PFNGLPIXELMAPXPROC) (GLenum map, GLint size, const GLfixed *values); +typedef void (APIENTRYP PFNGLPIXELSTOREXPROC) (GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLPIXELTRANSFERXOESPROC) (GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLPIXELZOOMXOESPROC) (GLfixed xfactor, GLfixed yfactor); +typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESXOESPROC) (GLsizei n, const GLuint *textures, const GLfixed *priorities); +typedef void (APIENTRYP PFNGLRASTERPOS2XOESPROC) (GLfixed x, GLfixed y); +typedef void (APIENTRYP PFNGLRASTERPOS2XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLRASTERPOS3XOESPROC) (GLfixed x, GLfixed y, GLfixed z); +typedef void (APIENTRYP PFNGLRASTERPOS3XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLRASTERPOS4XOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed w); +typedef void (APIENTRYP PFNGLRASTERPOS4XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLRECTXOESPROC) (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2); +typedef void (APIENTRYP PFNGLRECTXVOESPROC) (const GLfixed *v1, const GLfixed *v2); +typedef void (APIENTRYP PFNGLTEXCOORD1XOESPROC) (GLfixed s); +typedef void (APIENTRYP PFNGLTEXCOORD1XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLTEXCOORD2XOESPROC) (GLfixed s, GLfixed t); +typedef void (APIENTRYP PFNGLTEXCOORD2XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLTEXCOORD3XOESPROC) (GLfixed s, GLfixed t, GLfixed r); +typedef void (APIENTRYP PFNGLTEXCOORD3XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLTEXCOORD4XOESPROC) (GLfixed s, GLfixed t, GLfixed r, GLfixed q); +typedef void (APIENTRYP PFNGLTEXCOORD4XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param); +typedef void (APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params); +typedef void (APIENTRYP PFNGLVERTEX2XOESPROC) (GLfixed x); +typedef void (APIENTRYP PFNGLVERTEX2XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLVERTEX3XOESPROC) (GLfixed x, GLfixed y); +typedef void (APIENTRYP PFNGLVERTEX3XVOESPROC) (const GLfixed *coords); +typedef void (APIENTRYP PFNGLVERTEX4XOESPROC) (GLfixed x, GLfixed y, GLfixed z); +typedef void (APIENTRYP PFNGLVERTEX4XVOESPROC) (const GLfixed *coords); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glAlphaFuncxOES (GLenum func, GLfixed ref); +GLAPI void APIENTRY glClearColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +GLAPI void APIENTRY glClearDepthxOES (GLfixed depth); +GLAPI void APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation); +GLAPI void APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +GLAPI void APIENTRY glDepthRangexOES (GLfixed n, GLfixed f); +GLAPI void APIENTRY glFogxOES (GLenum pname, GLfixed param); +GLAPI void APIENTRY glFogxvOES (GLenum pname, const GLfixed *param); +GLAPI void APIENTRY glFrustumxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); +GLAPI void APIENTRY glGetClipPlanexOES (GLenum plane, GLfixed *equation); +GLAPI void APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params); +GLAPI void APIENTRY glGetTexEnvxvOES (GLenum target, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glLightModelxOES (GLenum pname, GLfixed param); +GLAPI void APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *param); +GLAPI void APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param); +GLAPI void APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params); +GLAPI void APIENTRY glLineWidthxOES (GLfixed width); +GLAPI void APIENTRY glLoadMatrixxOES (const GLfixed *m); +GLAPI void APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param); +GLAPI void APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *param); +GLAPI void APIENTRY glMultMatrixxOES (const GLfixed *m); +GLAPI void APIENTRY glMultiTexCoord4xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +GLAPI void APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz); +GLAPI void APIENTRY glOrthoxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); +GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params); +GLAPI void APIENTRY glPointSizexOES (GLfixed size); +GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units); +GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert); +GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z); +GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param); +GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params); +GLAPI void APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param); +GLAPI void APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params); +GLAPI void APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z); +GLAPI void APIENTRY glAccumxOES (GLenum op, GLfixed value); +GLAPI void APIENTRY glBitmapxOES (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap); +GLAPI void APIENTRY glBlendColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +GLAPI void APIENTRY glClearAccumxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +GLAPI void APIENTRY glColor3xOES (GLfixed red, GLfixed green, GLfixed blue); +GLAPI void APIENTRY glColor3xvOES (const GLfixed *components); +GLAPI void APIENTRY glColor4xvOES (const GLfixed *components); +GLAPI void APIENTRY glConvolutionParameterxOES (GLenum target, GLenum pname, GLfixed param); +GLAPI void APIENTRY glConvolutionParameterxvOES (GLenum target, GLenum pname, const GLfixed *params); +GLAPI void APIENTRY glEvalCoord1xOES (GLfixed u); +GLAPI void APIENTRY glEvalCoord1xvOES (const GLfixed *coords); +GLAPI void APIENTRY glEvalCoord2xOES (GLfixed u, GLfixed v); +GLAPI void APIENTRY glEvalCoord2xvOES (const GLfixed *coords); +GLAPI void APIENTRY glFeedbackBufferxOES (GLsizei n, GLenum type, const GLfixed *buffer); +GLAPI void APIENTRY glGetConvolutionParameterxvOES (GLenum target, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glGetHistogramParameterxvOES (GLenum target, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glGetLightxOES (GLenum light, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glGetMapxvOES (GLenum target, GLenum query, GLfixed *v); +GLAPI void APIENTRY glGetMaterialxOES (GLenum face, GLenum pname, GLfixed param); +GLAPI void APIENTRY glGetPixelMapxv (GLenum map, GLint size, GLfixed *values); +GLAPI void APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glGetTexLevelParameterxvOES (GLenum target, GLint level, GLenum pname, GLfixed *params); +GLAPI void APIENTRY glIndexxOES (GLfixed component); +GLAPI void APIENTRY glIndexxvOES (const GLfixed *component); +GLAPI void APIENTRY glLoadTransposeMatrixxOES (const GLfixed *m); +GLAPI void APIENTRY glMap1xOES (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points); +GLAPI void APIENTRY glMap2xOES (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points); +GLAPI void APIENTRY glMapGrid1xOES (GLint n, GLfixed u1, GLfixed u2); +GLAPI void APIENTRY glMapGrid2xOES (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2); +GLAPI void APIENTRY glMultTransposeMatrixxOES (const GLfixed *m); +GLAPI void APIENTRY glMultiTexCoord1xOES (GLenum texture, GLfixed s); +GLAPI void APIENTRY glMultiTexCoord1xvOES (GLenum texture, const GLfixed *coords); +GLAPI void APIENTRY glMultiTexCoord2xOES (GLenum texture, GLfixed s, GLfixed t); +GLAPI void APIENTRY glMultiTexCoord2xvOES (GLenum texture, const GLfixed *coords); +GLAPI void APIENTRY glMultiTexCoord3xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r); +GLAPI void APIENTRY glMultiTexCoord3xvOES (GLenum texture, const GLfixed *coords); +GLAPI void APIENTRY glMultiTexCoord4xvOES (GLenum texture, const GLfixed *coords); +GLAPI void APIENTRY glNormal3xvOES (const GLfixed *coords); +GLAPI void APIENTRY glPassThroughxOES (GLfixed token); +GLAPI void APIENTRY glPixelMapx (GLenum map, GLint size, const GLfixed *values); +GLAPI void APIENTRY glPixelStorex (GLenum pname, GLfixed param); +GLAPI void APIENTRY glPixelTransferxOES (GLenum pname, GLfixed param); +GLAPI void APIENTRY glPixelZoomxOES (GLfixed xfactor, GLfixed yfactor); +GLAPI void APIENTRY glPrioritizeTexturesxOES (GLsizei n, const GLuint *textures, const GLfixed *priorities); +GLAPI void APIENTRY glRasterPos2xOES (GLfixed x, GLfixed y); +GLAPI void APIENTRY glRasterPos2xvOES (const GLfixed *coords); +GLAPI void APIENTRY glRasterPos3xOES (GLfixed x, GLfixed y, GLfixed z); +GLAPI void APIENTRY glRasterPos3xvOES (const GLfixed *coords); +GLAPI void APIENTRY glRasterPos4xOES (GLfixed x, GLfixed y, GLfixed z, GLfixed w); +GLAPI void APIENTRY glRasterPos4xvOES (const GLfixed *coords); +GLAPI void APIENTRY glRectxOES (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2); +GLAPI void APIENTRY glRectxvOES (const GLfixed *v1, const GLfixed *v2); +GLAPI void APIENTRY glTexCoord1xOES (GLfixed s); +GLAPI void APIENTRY glTexCoord1xvOES (const GLfixed *coords); +GLAPI void APIENTRY glTexCoord2xOES (GLfixed s, GLfixed t); +GLAPI void APIENTRY glTexCoord2xvOES (const GLfixed *coords); +GLAPI void APIENTRY glTexCoord3xOES (GLfixed s, GLfixed t, GLfixed r); +GLAPI void APIENTRY glTexCoord3xvOES (const GLfixed *coords); +GLAPI void APIENTRY glTexCoord4xOES (GLfixed s, GLfixed t, GLfixed r, GLfixed q); +GLAPI void APIENTRY glTexCoord4xvOES (const GLfixed *coords); +GLAPI void APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param); +GLAPI void APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params); +GLAPI void APIENTRY glVertex2xOES (GLfixed x); +GLAPI void APIENTRY glVertex2xvOES (const GLfixed *coords); +GLAPI void APIENTRY glVertex3xOES (GLfixed x, GLfixed y); +GLAPI void APIENTRY glVertex3xvOES (const GLfixed *coords); +GLAPI void APIENTRY glVertex4xOES (GLfixed x, GLfixed y, GLfixed z); +GLAPI void APIENTRY glVertex4xvOES (const GLfixed *coords); +#endif +#endif /* GL_OES_fixed_point */ + +#ifndef GL_OES_query_matrix +#define GL_OES_query_matrix 1 +typedef GLbitfield (APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed *mantissa, GLint *exponent); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLbitfield APIENTRY glQueryMatrixxOES (GLfixed *mantissa, GLint *exponent); +#endif +#endif /* GL_OES_query_matrix */ + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B +#endif /* GL_OES_read_format */ + +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 +typedef void (APIENTRYP PFNGLCLEARDEPTHFOESPROC) (GLclampf depth); +typedef void (APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation); +typedef void (APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); +typedef void (APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +typedef void (APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat *equation); +typedef void (APIENTRYP PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glClearDepthfOES (GLclampf depth); +GLAPI void APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation); +GLAPI void APIENTRY glDepthRangefOES (GLclampf n, GLclampf f); +GLAPI void APIENTRY glFrustumfOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +GLAPI void APIENTRY glGetClipPlanefOES (GLenum plane, GLfloat *equation); +GLAPI void APIENTRY glOrthofOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +#endif +#endif /* GL_OES_single_precision */ + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 +#endif /* GL_3DFX_multisample */ + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 +typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTbufferMask3DFX (GLuint mask); +#endif +#endif /* GL_3DFX_tbuffer */ + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 +#endif /* GL_3DFX_texture_compression_FXT1 */ + +#ifndef GL_AMD_blend_minmax_factor +#define GL_AMD_blend_minmax_factor 1 +#define GL_FACTOR_MIN_AMD 0x901C +#define GL_FACTOR_MAX_AMD 0x901D +#endif /* GL_AMD_blend_minmax_factor */ + +#ifndef GL_AMD_conservative_depth +#define GL_AMD_conservative_depth 1 +#endif /* GL_AMD_conservative_depth */ + +#ifndef GL_AMD_debug_output +#define GL_AMD_debug_output 1 +typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147 +#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148 +#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149 +#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A +#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B +#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C +#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D +#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E +#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F +#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 +typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf); +GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam); +GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message); +#endif +#endif /* GL_AMD_debug_output */ + +#ifndef GL_AMD_depth_clamp_separate +#define GL_AMD_depth_clamp_separate 1 +#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E +#define GL_DEPTH_CLAMP_FAR_AMD 0x901F +#endif /* GL_AMD_depth_clamp_separate */ + +#ifndef GL_AMD_draw_buffers_blend +#define GL_AMD_draw_buffers_blend 1 +typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint buf, GLenum src, GLenum dst); +GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint buf, GLenum mode); +GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +#endif +#endif /* GL_AMD_draw_buffers_blend */ + +#ifndef GL_AMD_gcn_shader +#define GL_AMD_gcn_shader 1 +#endif /* GL_AMD_gcn_shader */ + +#ifndef GL_AMD_gpu_shader_int64 +#define GL_AMD_gpu_shader_int64 1 +typedef int64_t GLint64EXT; +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F +#define GL_INT8_NV 0x8FE0 +#define GL_INT8_VEC2_NV 0x8FE1 +#define GL_INT8_VEC3_NV 0x8FE2 +#define GL_INT8_VEC4_NV 0x8FE3 +#define GL_INT16_NV 0x8FE4 +#define GL_INT16_VEC2_NV 0x8FE5 +#define GL_INT16_VEC3_NV 0x8FE6 +#define GL_INT16_VEC4_NV 0x8FE7 +#define GL_INT64_VEC2_NV 0x8FE9 +#define GL_INT64_VEC3_NV 0x8FEA +#define GL_INT64_VEC4_NV 0x8FEB +#define GL_UNSIGNED_INT8_NV 0x8FEC +#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED +#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE +#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF +#define GL_UNSIGNED_INT16_NV 0x8FF0 +#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 +#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 +#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 +#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB +typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); +typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); +typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); +typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params); +typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x); +GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y); +GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x); +GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y); +GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params); +GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params); +GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x); +GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value); +GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x); +GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#endif +#endif /* GL_AMD_gpu_shader_int64 */ + +#ifndef GL_AMD_interleaved_elements +#define GL_AMD_interleaved_elements 1 +#define GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4 +#define GL_VERTEX_ID_SWIZZLE_AMD 0x91A5 +typedef void (APIENTRYP PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GLenum pname, GLint param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribParameteriAMD (GLuint index, GLenum pname, GLint param); +#endif +#endif /* GL_AMD_interleaved_elements */ + +#ifndef GL_AMD_multi_draw_indirect +#define GL_AMD_multi_draw_indirect 1 +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysIndirectAMD (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride); +#endif +#endif /* GL_AMD_multi_draw_indirect */ + +#ifndef GL_AMD_name_gen_delete +#define GL_AMD_name_gen_delete 1 +#define GL_DATA_BUFFER_AMD 0x9151 +#define GL_PERFORMANCE_MONITOR_AMD 0x9152 +#define GL_QUERY_OBJECT_AMD 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154 +#define GL_SAMPLER_OBJECT_AMD 0x9155 +typedef void (APIENTRYP PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint *names); +typedef void (APIENTRYP PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint *names); +typedef GLboolean (APIENTRYP PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenNamesAMD (GLenum identifier, GLuint num, GLuint *names); +GLAPI void APIENTRY glDeleteNamesAMD (GLenum identifier, GLuint num, const GLuint *names); +GLAPI GLboolean APIENTRY glIsNameAMD (GLenum identifier, GLuint name); +#endif +#endif /* GL_AMD_name_gen_delete */ + +#ifndef GL_AMD_occlusion_query_event +#define GL_AMD_occlusion_query_event 1 +#define GL_OCCLUSION_QUERY_EVENT_MASK_AMD 0x874F +#define GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD 0x00000001 +#define GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD 0x00000002 +#define GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD 0x00000004 +#define GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD 0x00000008 +#define GL_QUERY_ALL_EVENT_BITS_AMD 0xFFFFFFFF +typedef void (APIENTRYP PFNGLQUERYOBJECTPARAMETERUIAMDPROC) (GLenum target, GLuint id, GLenum pname, GLuint param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glQueryObjectParameteruiAMD (GLenum target, GLuint id, GLenum pname, GLuint param); +#endif +#endif /* GL_AMD_occlusion_query_event */ + +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 +typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data); +typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); +typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data); +GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); +GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); +GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); +GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor); +GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor); +GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif +#endif /* GL_AMD_performance_monitor */ + +#ifndef GL_AMD_pinned_memory +#define GL_AMD_pinned_memory 1 +#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160 +#endif /* GL_AMD_pinned_memory */ + +#ifndef GL_AMD_query_buffer_object +#define GL_AMD_query_buffer_object 1 +#define GL_QUERY_BUFFER_AMD 0x9192 +#define GL_QUERY_BUFFER_BINDING_AMD 0x9193 +#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194 +#endif /* GL_AMD_query_buffer_object */ + +#ifndef GL_AMD_sample_positions +#define GL_AMD_sample_positions 1 +#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F +typedef void (APIENTRYP PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat *val); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLfloat *val); +#endif +#endif /* GL_AMD_sample_positions */ + +#ifndef GL_AMD_seamless_cubemap_per_texture +#define GL_AMD_seamless_cubemap_per_texture 1 +#endif /* GL_AMD_seamless_cubemap_per_texture */ + +#ifndef GL_AMD_shader_atomic_counter_ops +#define GL_AMD_shader_atomic_counter_ops 1 +#endif /* GL_AMD_shader_atomic_counter_ops */ + +#ifndef GL_AMD_shader_stencil_export +#define GL_AMD_shader_stencil_export 1 +#endif /* GL_AMD_shader_stencil_export */ + +#ifndef GL_AMD_shader_trinary_minmax +#define GL_AMD_shader_trinary_minmax 1 +#endif /* GL_AMD_shader_trinary_minmax */ + +#ifndef GL_AMD_sparse_texture +#define GL_AMD_sparse_texture 1 +#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195 +#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196 +#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197 +#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198 +#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199 +#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A +#define GL_MIN_SPARSE_LEVEL_AMD 0x919B +#define GL_MIN_LOD_WARNING_AMD 0x919C +#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001 +typedef void (APIENTRYP PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags); +typedef void (APIENTRYP PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexStorageSparseAMD (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags); +GLAPI void APIENTRY glTextureStorageSparseAMD (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags); +#endif +#endif /* GL_AMD_sparse_texture */ + +#ifndef GL_AMD_stencil_operation_extended +#define GL_AMD_stencil_operation_extended 1 +#define GL_SET_AMD 0x874A +#define GL_REPLACE_VALUE_AMD 0x874B +#define GL_STENCIL_OP_VALUE_AMD 0x874C +#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D +typedef void (APIENTRYP PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value); +#endif +#endif /* GL_AMD_stencil_operation_extended */ + +#ifndef GL_AMD_texture_texture4 +#define GL_AMD_texture_texture4 1 +#endif /* GL_AMD_texture_texture4 */ + +#ifndef GL_AMD_transform_feedback3_lines_triangles +#define GL_AMD_transform_feedback3_lines_triangles 1 +#endif /* GL_AMD_transform_feedback3_lines_triangles */ + +#ifndef GL_AMD_transform_feedback4 +#define GL_AMD_transform_feedback4 1 +#define GL_STREAM_RASTERIZATION_AMD 0x91A0 +#endif /* GL_AMD_transform_feedback4 */ + +#ifndef GL_AMD_vertex_shader_layer +#define GL_AMD_vertex_shader_layer 1 +#endif /* GL_AMD_vertex_shader_layer */ + +#ifndef GL_AMD_vertex_shader_tessellator +#define GL_AMD_vertex_shader_tessellator 1 +#define GL_SAMPLER_BUFFER_AMD 0x9001 +#define GL_INT_SAMPLER_BUFFER_AMD 0x9002 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003 +#define GL_TESSELLATION_MODE_AMD 0x9004 +#define GL_TESSELLATION_FACTOR_AMD 0x9005 +#define GL_DISCRETE_AMD 0x9006 +#define GL_CONTINUOUS_AMD 0x9007 +typedef void (APIENTRYP PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor); +typedef void (APIENTRYP PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTessellationFactorAMD (GLfloat factor); +GLAPI void APIENTRY glTessellationModeAMD (GLenum mode); +#endif +#endif /* GL_AMD_vertex_shader_tessellator */ + +#ifndef GL_AMD_vertex_shader_viewport_index +#define GL_AMD_vertex_shader_viewport_index 1 +#endif /* GL_AMD_vertex_shader_viewport_index */ + +#ifndef GL_APPLE_aux_depth_stencil +#define GL_APPLE_aux_depth_stencil 1 +#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 +#endif /* GL_APPLE_aux_depth_stencil */ + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 +#endif /* GL_APPLE_client_storage */ + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 +#define GL_ELEMENT_ARRAY_APPLE 0x8A0C +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E +typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void *pointer); +typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glElementPointerAPPLE (GLenum type, const void *pointer); +GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); +#endif +#endif /* GL_APPLE_element_array */ + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B +typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences); +typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences); +typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); +typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenFencesAPPLE (GLsizei n, GLuint *fences); +GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei n, const GLuint *fences); +GLAPI void APIENTRY glSetFenceAPPLE (GLuint fence); +GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint fence); +GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint fence); +GLAPI void APIENTRY glFinishFenceAPPLE (GLuint fence); +GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum object, GLuint name); +GLAPI void APIENTRY glFinishObjectAPPLE (GLenum object, GLint name); +#endif +#endif /* GL_APPLE_fence */ + +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels 1 +#define GL_HALF_APPLE 0x140B +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#define GL_COLOR_FLOAT_APPLE 0x8A0F +#endif /* GL_APPLE_float_pixels */ + +#ifndef GL_APPLE_flush_buffer_range +#define GL_APPLE_flush_buffer_range 1 +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 +typedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferParameteriAPPLE (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size); +#endif +#endif /* GL_APPLE_flush_buffer_range */ + +#ifndef GL_APPLE_object_purgeable +#define GL_APPLE_object_purgeable 1 +#define GL_BUFFER_OBJECT_APPLE 0x85B3 +#define GL_RELEASED_APPLE 0x8A19 +#define GL_VOLATILE_APPLE 0x8A1A +#define GL_RETAINED_APPLE 0x8A1B +#define GL_UNDEFINED_APPLE 0x8A1C +#define GL_PURGEABLE_APPLE 0x8A1D +typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum objectType, GLuint name, GLenum option); +GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum objectType, GLuint name, GLenum option); +GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum objectType, GLuint name, GLenum pname, GLint *params); +#endif +#endif /* GL_APPLE_object_purgeable */ + +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 +#define GL_RGB_422_APPLE 0x8A1F +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#define GL_RGB_RAW_422_APPLE 0x8A51 +#endif /* GL_APPLE_rgb_422 */ + +#ifndef GL_APPLE_row_bytes +#define GL_APPLE_row_bytes 1 +#define GL_PACK_ROW_BYTES_APPLE 0x8A15 +#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 +#endif /* GL_APPLE_row_bytes */ + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 +#endif /* GL_APPLE_specular_vector */ + +#ifndef GL_APPLE_texture_range +#define GL_APPLE_texture_range 1 +#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 +#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 +#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC +#define GL_STORAGE_PRIVATE_APPLE 0x85BD +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF +typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const void *pointer); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, void **params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureRangeAPPLE (GLenum target, GLsizei length, const void *pointer); +GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum target, GLenum pname, void **params); +#endif +#endif /* GL_APPLE_texture_range */ + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 +#define GL_TRANSFORM_HINT_APPLE 0x85B1 +#endif /* GL_APPLE_transform_hint */ + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 +typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint array); +GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays); +GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei n, GLuint *arrays); +GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint array); +#endif +#endif /* GL_APPLE_vertex_array_object */ + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CLIENT_APPLE 0x85B4 +typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer); +typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer); +typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei length, void *pointer); +GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei length, void *pointer); +GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum pname, GLint param); +#endif +#endif /* GL_APPLE_vertex_array_range */ + +#ifndef GL_APPLE_vertex_program_evaluators +#define GL_APPLE_vertex_program_evaluators 1 +#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 +#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 +#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 +#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 +#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 +#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 +#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 +#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 +#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 +#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint index, GLenum pname); +GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint index, GLenum pname); +GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint index, GLenum pname); +GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +#endif +#endif /* GL_APPLE_vertex_program_evaluators */ + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 +#define GL_YCBCR_422_APPLE 0x85B9 +#endif /* GL_APPLE_ycbcr_422 */ + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 +typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawBuffersATI (GLsizei n, const GLenum *bufs); +#endif +#endif /* GL_ATI_draw_buffers */ + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A +typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void *pointer); +typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glElementPointerATI (GLenum type, const void *pointer); +GLAPI void APIENTRY glDrawElementArrayATI (GLenum mode, GLsizei count); +GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count); +#endif +#endif /* GL_ATI_element_array */ + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C +typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param); +typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexBumpParameterivATI (GLenum pname, const GLint *param); +GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum pname, const GLfloat *param); +GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum pname, GLint *param); +GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum pname, GLfloat *param); +#endif +#endif /* GL_ATI_envmap_bumpmap */ + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_REG_6_ATI 0x8927 +#define GL_REG_7_ATI 0x8928 +#define GL_REG_8_ATI 0x8929 +#define GL_REG_9_ATI 0x892A +#define GL_REG_10_ATI 0x892B +#define GL_REG_11_ATI 0x892C +#define GL_REG_12_ATI 0x892D +#define GL_REG_13_ATI 0x892E +#define GL_REG_14_ATI 0x892F +#define GL_REG_15_ATI 0x8930 +#define GL_REG_16_ATI 0x8931 +#define GL_REG_17_ATI 0x8932 +#define GL_REG_18_ATI 0x8933 +#define GL_REG_19_ATI 0x8934 +#define GL_REG_20_ATI 0x8935 +#define GL_REG_21_ATI 0x8936 +#define GL_REG_22_ATI 0x8937 +#define GL_REG_23_ATI 0x8938 +#define GL_REG_24_ATI 0x8939 +#define GL_REG_25_ATI 0x893A +#define GL_REG_26_ATI 0x893B +#define GL_REG_27_ATI 0x893C +#define GL_REG_28_ATI 0x893D +#define GL_REG_29_ATI 0x893E +#define GL_REG_30_ATI 0x893F +#define GL_REG_31_ATI 0x8940 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_CON_8_ATI 0x8949 +#define GL_CON_9_ATI 0x894A +#define GL_CON_10_ATI 0x894B +#define GL_CON_11_ATI 0x894C +#define GL_CON_12_ATI 0x894D +#define GL_CON_13_ATI 0x894E +#define GL_CON_14_ATI 0x894F +#define GL_CON_15_ATI 0x8950 +#define GL_CON_16_ATI 0x8951 +#define GL_CON_17_ATI 0x8952 +#define GL_CON_18_ATI 0x8953 +#define GL_CON_19_ATI 0x8954 +#define GL_CON_20_ATI 0x8955 +#define GL_CON_21_ATI 0x8956 +#define GL_CON_22_ATI 0x8957 +#define GL_CON_23_ATI 0x8958 +#define GL_CON_24_ATI 0x8959 +#define GL_CON_25_ATI 0x895A +#define GL_CON_26_ATI 0x895B +#define GL_CON_27_ATI 0x895C +#define GL_CON_28_ATI 0x895D +#define GL_CON_29_ATI 0x895E +#define GL_CON_30_ATI 0x895F +#define GL_CON_31_ATI 0x8960 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B +#define GL_RED_BIT_ATI 0x00000001 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint range); +GLAPI void APIENTRY glBindFragmentShaderATI (GLuint id); +GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint id); +GLAPI void APIENTRY glBeginFragmentShaderATI (void); +GLAPI void APIENTRY glEndFragmentShaderATI (void); +GLAPI void APIENTRY glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle); +GLAPI void APIENTRY glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle); +GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value); +#endif +#endif /* GL_ATI_fragment_shader */ + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 +typedef void *(APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void *APIENTRY glMapObjectBufferATI (GLuint buffer); +GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint buffer); +#endif +#endif /* GL_ATI_map_object_buffer */ + +#ifndef GL_ATI_meminfo +#define GL_ATI_meminfo 1 +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD +#endif /* GL_ATI_meminfo */ + +#ifndef GL_ATI_pixel_format_float +#define GL_ATI_pixel_format_float 1 +#define GL_RGBA_FLOAT_MODE_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 +#endif /* GL_ATI_pixel_format_float */ + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 +typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPNTrianglesiATI (GLenum pname, GLint param); +GLAPI void APIENTRY glPNTrianglesfATI (GLenum pname, GLfloat param); +#endif +#endif /* GL_ATI_pn_triangles */ + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +#endif +#endif /* GL_ATI_separate_stencil */ + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 +#endif /* GL_ATI_text_fragment_shader */ + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 +#endif /* GL_ATI_texture_env_combine3 */ + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F +#endif /* GL_ATI_texture_float */ + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 +#endif /* GL_ATI_texture_mirror_once */ + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 +typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void *pointer, GLenum usage); +typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve); +typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei size, const void *pointer, GLenum usage); +GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint buffer); +GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve); +GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glFreeObjectBufferATI (GLuint buffer); +GLAPI void APIENTRY glArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params); +GLAPI void APIENTRY glVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params); +#endif +#endif /* GL_ATI_vertex_array_object */ + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 +typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); +GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params); +#endif +#endif /* GL_ATI_vertex_attrib_array_object */ + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_STREAM0_ATI 0x876C +#define GL_VERTEX_STREAM1_ATI 0x876D +#define GL_VERTEX_STREAM2_ATI 0x876E +#define GL_VERTEX_STREAM3_ATI 0x876F +#define GL_VERTEX_STREAM4_ATI 0x8770 +#define GL_VERTEX_STREAM5_ATI 0x8771 +#define GL_VERTEX_STREAM6_ATI 0x8772 +#define GL_VERTEX_STREAM7_ATI 0x8773 +#define GL_VERTEX_SOURCE_ATI 0x8774 +typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexStream1sATI (GLenum stream, GLshort x); +GLAPI void APIENTRY glVertexStream1svATI (GLenum stream, const GLshort *coords); +GLAPI void APIENTRY glVertexStream1iATI (GLenum stream, GLint x); +GLAPI void APIENTRY glVertexStream1ivATI (GLenum stream, const GLint *coords); +GLAPI void APIENTRY glVertexStream1fATI (GLenum stream, GLfloat x); +GLAPI void APIENTRY glVertexStream1fvATI (GLenum stream, const GLfloat *coords); +GLAPI void APIENTRY glVertexStream1dATI (GLenum stream, GLdouble x); +GLAPI void APIENTRY glVertexStream1dvATI (GLenum stream, const GLdouble *coords); +GLAPI void APIENTRY glVertexStream2sATI (GLenum stream, GLshort x, GLshort y); +GLAPI void APIENTRY glVertexStream2svATI (GLenum stream, const GLshort *coords); +GLAPI void APIENTRY glVertexStream2iATI (GLenum stream, GLint x, GLint y); +GLAPI void APIENTRY glVertexStream2ivATI (GLenum stream, const GLint *coords); +GLAPI void APIENTRY glVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y); +GLAPI void APIENTRY glVertexStream2fvATI (GLenum stream, const GLfloat *coords); +GLAPI void APIENTRY glVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexStream2dvATI (GLenum stream, const GLdouble *coords); +GLAPI void APIENTRY glVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glVertexStream3svATI (GLenum stream, const GLshort *coords); +GLAPI void APIENTRY glVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z); +GLAPI void APIENTRY glVertexStream3ivATI (GLenum stream, const GLint *coords); +GLAPI void APIENTRY glVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glVertexStream3fvATI (GLenum stream, const GLfloat *coords); +GLAPI void APIENTRY glVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexStream3dvATI (GLenum stream, const GLdouble *coords); +GLAPI void APIENTRY glVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void APIENTRY glVertexStream4svATI (GLenum stream, const GLshort *coords); +GLAPI void APIENTRY glVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glVertexStream4ivATI (GLenum stream, const GLint *coords); +GLAPI void APIENTRY glVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glVertexStream4fvATI (GLenum stream, const GLfloat *coords); +GLAPI void APIENTRY glVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexStream4dvATI (GLenum stream, const GLdouble *coords); +GLAPI void APIENTRY glNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); +GLAPI void APIENTRY glNormalStream3bvATI (GLenum stream, const GLbyte *coords); +GLAPI void APIENTRY glNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz); +GLAPI void APIENTRY glNormalStream3svATI (GLenum stream, const GLshort *coords); +GLAPI void APIENTRY glNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz); +GLAPI void APIENTRY glNormalStream3ivATI (GLenum stream, const GLint *coords); +GLAPI void APIENTRY glNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); +GLAPI void APIENTRY glNormalStream3fvATI (GLenum stream, const GLfloat *coords); +GLAPI void APIENTRY glNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); +GLAPI void APIENTRY glNormalStream3dvATI (GLenum stream, const GLdouble *coords); +GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum stream); +GLAPI void APIENTRY glVertexBlendEnviATI (GLenum pname, GLint param); +GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param); +#endif +#endif /* GL_ATI_vertex_streams */ + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF +#endif /* GL_EXT_422_pixels */ + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 +#define GL_ABGR_EXT 0x8000 +#endif /* GL_EXT_abgr */ + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 +#endif /* GL_EXT_bgra */ + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF +typedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); +typedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); +typedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer); +GLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location); +GLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint program, GLint location); +#endif +#endif /* GL_EXT_bindable_uniform */ + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 +typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendColorEXT (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#endif +#endif /* GL_EXT_blend_color */ + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 +#define GL_BLEND_EQUATION_RGB_EXT 0x8009 +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha); +#endif +#endif /* GL_EXT_blend_equation_separate */ + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif +#endif /* GL_EXT_blend_func_separate */ + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 +#endif /* GL_EXT_blend_logic_op */ + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_BLEND_EQUATION_EXT 0x8009 +typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationEXT (GLenum mode); +#endif +#endif /* GL_EXT_blend_minmax */ + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#endif /* GL_EXT_blend_subtract */ + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 +#endif /* GL_EXT_clip_volume_hint */ + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F +#endif /* GL_EXT_cmyka */ + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 +typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +#endif +#endif /* GL_EXT_color_subtable */ + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 +typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count); +GLAPI void APIENTRY glUnlockArraysEXT (void); +#endif +#endif /* GL_EXT_compiled_vertex_array */ + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *image); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); +typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); +GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); +GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params); +GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params); +GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, void *image); +GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); +GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); +#endif +#endif /* GL_EXT_convolution */ + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 +typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); +typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); +typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); +typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); +typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); +typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); +typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); +typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); +typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); +typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); +typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz); +GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *v); +GLAPI void APIENTRY glTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz); +GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *v); +GLAPI void APIENTRY glTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz); +GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *v); +GLAPI void APIENTRY glTangent3iEXT (GLint tx, GLint ty, GLint tz); +GLAPI void APIENTRY glTangent3ivEXT (const GLint *v); +GLAPI void APIENTRY glTangent3sEXT (GLshort tx, GLshort ty, GLshort tz); +GLAPI void APIENTRY glTangent3svEXT (const GLshort *v); +GLAPI void APIENTRY glBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz); +GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *v); +GLAPI void APIENTRY glBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz); +GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *v); +GLAPI void APIENTRY glBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz); +GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *v); +GLAPI void APIENTRY glBinormal3iEXT (GLint bx, GLint by, GLint bz); +GLAPI void APIENTRY glBinormal3ivEXT (const GLint *v); +GLAPI void APIENTRY glBinormal3sEXT (GLshort bx, GLshort by, GLshort bz); +GLAPI void APIENTRY glBinormal3svEXT (const GLshort *v); +GLAPI void APIENTRY glTangentPointerEXT (GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glBinormalPointerEXT (GLenum type, GLsizei stride, const void *pointer); +#endif +#endif /* GL_EXT_coordinate_frame */ + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_EXT_copy_texture */ + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC +typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCullParameterdvEXT (GLenum pname, GLdouble *params); +GLAPI void APIENTRY glCullParameterfvEXT (GLenum pname, GLfloat *params); +#endif +#endif /* GL_EXT_cull_vertex */ + +#ifndef GL_EXT_debug_label +#define GL_EXT_debug_label 1 +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +typedef void (APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif +#endif /* GL_EXT_debug_label */ + +#ifndef GL_EXT_debug_marker +#define GL_EXT_debug_marker 1 +typedef void (APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); +GLAPI void APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); +GLAPI void APIENTRY glPopGroupMarkerEXT (void); +#endif +#endif /* GL_EXT_debug_marker */ + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 +typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDepthBoundsEXT (GLclampd zmin, GLclampd zmax); +#endif +#endif /* GL_EXT_depth_bounds_test */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F +typedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params); +typedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data); +typedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data); +typedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, void **data); +typedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data); +typedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, void *img); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, void *img); +typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m); +typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m); +typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void **params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params); +typedef void (APIENTRYP PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void *string); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); +typedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); +typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, void **param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (APIENTRYP PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum mode); +GLAPI void APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void APIENTRY glMatrixPopEXT (GLenum mode); +GLAPI void APIENTRY glMatrixPushEXT (GLenum mode); +GLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield mask); +GLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield mask); +GLAPI void APIENTRY glTextureParameterfEXT (GLuint texture, GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glTextureParameteriEXT (GLuint texture, GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetTextureImageEXT (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +GLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void APIENTRY glTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glBindMultiTextureEXT (GLenum texunit, GLenum target, GLuint texture); +GLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glMultiTexEnvfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glMultiTexEnviEXT (GLenum texunit, GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMultiTexGendEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +GLAPI void APIENTRY glMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params); +GLAPI void APIENTRY glMultiTexGenfEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +GLAPI void APIENTRY glMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glMultiTexGeniEXT (GLenum texunit, GLenum coord, GLenum pname, GLint param); +GLAPI void APIENTRY glMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, const GLint *params); +GLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, GLint *params); +GLAPI void APIENTRY glMultiTexParameteriEXT (GLenum texunit, GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMultiTexParameterfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +GLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void APIENTRY glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum target, GLuint index, GLfloat *data); +GLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum target, GLuint index, GLdouble *data); +GLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum target, GLuint index, void **data); +GLAPI void APIENTRY glEnableIndexedEXT (GLenum target, GLuint index); +GLAPI void APIENTRY glDisableIndexedEXT (GLenum target, GLuint index); +GLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index); +GLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data); +GLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data); +GLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint texture, GLenum target, GLint lod, void *img); +GLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits); +GLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target, GLint lod, void *img); +GLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m); +GLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m); +GLAPI void APIENTRY glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +GLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void *APIENTRY glMapNamedBufferEXT (GLuint buffer, GLenum access); +GLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint buffer); +GLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint buffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint buffer, GLenum pname, void **params); +GLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); +GLAPI void APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0); +GLAPI void APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GLAPI void APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI void APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI void APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0); +GLAPI void APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1); +GLAPI void APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GLAPI void APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI void APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GLAPI void APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI void APIENTRY glTextureBufferEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glMultiTexBufferEXT (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +GLAPI void APIENTRY glTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0); +GLAPI void APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params); +GLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint program, GLenum target, GLuint index, const GLint *params); +GLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params); +GLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint program, GLenum target, GLuint index, const GLuint *params); +GLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint program, GLenum target, GLuint index, GLint *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint program, GLenum target, GLuint index, GLuint *params); +GLAPI void APIENTRY glEnableClientStateiEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glDisableClientStateiEXT (GLenum array, GLuint index); +GLAPI void APIENTRY glGetFloati_vEXT (GLenum pname, GLuint index, GLfloat *params); +GLAPI void APIENTRY glGetDoublei_vEXT (GLenum pname, GLuint index, GLdouble *params); +GLAPI void APIENTRY glGetPointeri_vEXT (GLenum pname, GLuint index, void **params); +GLAPI void APIENTRY glNamedProgramStringEXT (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string); +GLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint program, GLenum target, GLuint index, const GLdouble *params); +GLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint program, GLenum target, GLuint index, const GLfloat *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint program, GLenum target, GLuint index, GLdouble *params); +GLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint program, GLenum target, GLuint index, GLfloat *params); +GLAPI void APIENTRY glGetNamedProgramivEXT (GLuint program, GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint program, GLenum target, GLenum pname, void *string); +GLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint renderbuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint framebuffer, GLenum target); +GLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params); +GLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint texture, GLenum target); +GLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum texunit, GLenum target); +GLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint framebuffer, GLenum mode); +GLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint framebuffer, GLsizei n, const GLenum *bufs); +GLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint framebuffer, GLenum mode); +GLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +GLAPI void APIENTRY glTextureRenderbufferEXT (GLuint texture, GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum texunit, GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glVertexArrayVertexOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayEdgeFlagOffsetEXT (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayIndexOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayNormalOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayMultiTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayFogCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArraySecondaryColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayVertexAttribOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glVertexArrayVertexAttribIOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glEnableVertexArrayEXT (GLuint vaobj, GLenum array); +GLAPI void APIENTRY glDisableVertexArrayEXT (GLuint vaobj, GLenum array); +GLAPI void APIENTRY glEnableVertexArrayAttribEXT (GLuint vaobj, GLuint index); +GLAPI void APIENTRY glDisableVertexArrayAttribEXT (GLuint vaobj, GLuint index); +GLAPI void APIENTRY glGetVertexArrayIntegervEXT (GLuint vaobj, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetVertexArrayPointervEXT (GLuint vaobj, GLenum pname, void **param); +GLAPI void APIENTRY glGetVertexArrayIntegeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, GLint *param); +GLAPI void APIENTRY glGetVertexArrayPointeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, void **param); +GLAPI void *APIENTRY glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI void APIENTRY glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length); +GLAPI void APIENTRY glNamedBufferStorageEXT (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +GLAPI void APIENTRY glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glNamedFramebufferParameteriEXT (GLuint framebuffer, GLenum pname, GLint param); +GLAPI void APIENTRY glGetNamedFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params); +GLAPI void APIENTRY glProgramUniform1dEXT (GLuint program, GLint location, GLdouble x); +GLAPI void APIENTRY glProgramUniform2dEXT (GLuint program, GLint location, GLdouble x, GLdouble y); +GLAPI void APIENTRY glProgramUniform3dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glProgramUniform4dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glProgramUniform1dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform2dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform3dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniform4dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix2x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix3x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glProgramUniformMatrix4x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value); +GLAPI void APIENTRY glTextureBufferRangeEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glTextureStorage2DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glTextureStorage3DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI void APIENTRY glVertexArrayBindVertexBufferEXT (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GLAPI void APIENTRY glVertexArrayVertexAttribFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayVertexAttribIFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor); +GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor); +#endif +#endif /* GL_EXT_direct_state_access */ + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 +typedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +#endif +#endif /* GL_EXT_draw_buffers2 */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +#endif +#endif /* GL_EXT_draw_instanced */ + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +#endif +#endif /* GL_EXT_draw_range_elements */ + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 +typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); +typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFogCoordfEXT (GLfloat coord); +GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *coord); +GLAPI void APIENTRY glFogCoorddEXT (GLdouble coord); +GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *coord); +GLAPI void APIENTRY glFogCoordPointerEXT (GLenum type, GLsizei stride, const void *pointer); +#endif +#endif /* GL_EXT_fog_coord */ + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +#endif /* GL_EXT_framebuffer_blit */ + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif /* GL_EXT_framebuffer_multisample */ + +#ifndef GL_EXT_framebuffer_multisample_blit_scaled +#define GL_EXT_framebuffer_multisample_blit_scaled 1 +#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA +#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB +#endif /* GL_EXT_framebuffer_multisample_blit_scaled */ + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 +typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); +typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint renderbuffer); +GLAPI void APIENTRY glBindRenderbufferEXT (GLenum target, GLuint renderbuffer); +GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei n, const GLuint *renderbuffers); +GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers); +GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint framebuffer); +GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer); +GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers); +GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers); +GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum target); +GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum attachment, GLenum pname, GLint *params); +GLAPI void APIENTRY glGenerateMipmapEXT (GLenum target); +#endif +#endif /* GL_EXT_framebuffer_object */ + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif /* GL_EXT_framebuffer_sRGB */ + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_LINES_ADJACENCY_EXT 0x000A +#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B +#define GL_TRIANGLES_ADJACENCY_EXT 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); +#endif +#endif /* GL_EXT_geometry_shader4 */ + +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters 1 +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params); +GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params); +#endif +#endif /* GL_EXT_gpu_program_parameters */ + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 +typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); +typedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params); +GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name); +GLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name); +GLAPI void APIENTRY glUniform1uiEXT (GLint location, GLuint v0); +GLAPI void APIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1); +GLAPI void APIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI void APIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value); +#endif +#endif /* GL_EXT_gpu_shader4 */ + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 +#define GL_TABLE_TOO_LARGE_EXT 0x8031 +typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); +GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +GLAPI void APIENTRY glMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink); +GLAPI void APIENTRY glResetHistogramEXT (GLenum target); +GLAPI void APIENTRY glResetMinmaxEXT (GLenum target); +#endif +#endif /* GL_EXT_histogram */ + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 +#define GL_IUI_V2F_EXT 0x81AD +#define GL_IUI_V3F_EXT 0x81AE +#define GL_IUI_N3F_V2F_EXT 0x81AF +#define GL_IUI_N3F_V3F_EXT 0x81B0 +#define GL_T2F_IUI_V2F_EXT 0x81B1 +#define GL_T2F_IUI_V3F_EXT 0x81B2 +#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 +#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 +#endif /* GL_EXT_index_array_formats */ + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 +#define GL_INDEX_TEST_EXT 0x81B5 +#define GL_INDEX_TEST_FUNC_EXT 0x81B6 +#define GL_INDEX_TEST_REF_EXT 0x81B7 +typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glIndexFuncEXT (GLenum func, GLclampf ref); +#endif +#endif /* GL_EXT_index_func */ + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 +#define GL_INDEX_MATERIAL_EXT 0x81B8 +#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 +#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA +typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glIndexMaterialEXT (GLenum face, GLenum mode); +#endif +#endif /* GL_EXT_index_material */ + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 +#endif /* GL_EXT_index_texture */ + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glApplyTextureEXT (GLenum mode); +GLAPI void APIENTRY glTextureLightEXT (GLenum pname); +GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode); +#endif +#endif /* GL_EXT_light_texture */ + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 +#endif /* GL_EXT_misc_attribute */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); +#endif +#endif /* GL_EXT_multi_draw_arrays */ + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 +typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSampleMaskEXT (GLclampf value, GLboolean invert); +GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern); +#endif +#endif /* GL_EXT_multisample */ + +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 +#endif /* GL_EXT_packed_depth_stencil */ + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C +#endif /* GL_EXT_packed_float */ + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 +#endif /* GL_EXT_packed_pixels */ + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table); +typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void *data); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table); +GLAPI void APIENTRY glGetColorTableEXT (GLenum target, GLenum format, GLenum type, void *data); +GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); +#endif +#endif /* GL_EXT_paletted_texture */ + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF +#endif /* GL_EXT_pixel_buffer_object */ + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glGetPixelTransformParameterivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetPixelTransformParameterfvEXT (GLenum target, GLenum pname, GLfloat *params); +#endif +#endif /* GL_EXT_pixel_transform */ + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 +#endif /* GL_EXT_pixel_transform_color_table */ + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameterfEXT (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPointParameterfvEXT (GLenum pname, const GLfloat *params); +#endif +#endif /* GL_EXT_point_parameters */ + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 +typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias); +#endif +#endif /* GL_EXT_polygon_offset */ + +#ifndef GL_EXT_provoking_vertex +#define GL_EXT_provoking_vertex 1 +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_PROVOKING_VERTEX_EXT 0x8E4F +typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode); +#endif +#endif /* GL_EXT_provoking_vertex */ + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 +#define GL_RESCALE_NORMAL_EXT 0x803A +#endif /* GL_EXT_rescale_normal */ + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue); +GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *v); +GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue); +GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *v); +GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue); +GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *v); +GLAPI void APIENTRY glSecondaryColor3iEXT (GLint red, GLint green, GLint blue); +GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *v); +GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue); +GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *v); +GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue); +GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *v); +GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue); +GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *v); +GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue); +GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *v); +GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer); +#endif +#endif /* GL_EXT_secondary_color */ + +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 +#define GL_ACTIVE_PROGRAM_EXT 0x8B8D +typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); +typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program); +GLAPI void APIENTRY glActiveProgramEXT (GLuint program); +GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string); +#endif +#endif /* GL_EXT_separate_shader_objects */ + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA +#endif /* GL_EXT_separate_specular_color */ + +#ifndef GL_EXT_shader_image_load_formatted +#define GL_EXT_shader_image_load_formatted 1 +#endif /* GL_EXT_shader_image_load_formatted */ + +#ifndef GL_EXT_shader_image_load_store +#define GL_EXT_shader_image_load_store 1 +#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 +#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A +#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B +#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C +#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D +#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E +#define GL_IMAGE_1D_EXT 0x904C +#define GL_IMAGE_2D_EXT 0x904D +#define GL_IMAGE_3D_EXT 0x904E +#define GL_IMAGE_2D_RECT_EXT 0x904F +#define GL_IMAGE_CUBE_EXT 0x9050 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_IMAGE_1D_ARRAY_EXT 0x9052 +#define GL_IMAGE_2D_ARRAY_EXT 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 +#define GL_INT_IMAGE_1D_EXT 0x9057 +#define GL_INT_IMAGE_2D_EXT 0x9058 +#define GL_INT_IMAGE_3D_EXT 0x9059 +#define GL_INT_IMAGE_2D_RECT_EXT 0x905A +#define GL_INT_IMAGE_CUBE_EXT 0x905B +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D +#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C +#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D +#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 +#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 +#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF +typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); +typedef void (APIENTRYP PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindImageTextureEXT (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); +GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers); +#endif +#endif /* GL_EXT_shader_image_load_store */ + +#ifndef GL_EXT_shader_integer_mix +#define GL_EXT_shader_integer_mix 1 +#endif /* GL_EXT_shader_integer_mix */ + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 +#endif /* GL_EXT_shadow_funcs */ + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB +#endif /* GL_EXT_shared_texture_palette */ + +#ifndef GL_EXT_stencil_clear_tag +#define GL_EXT_stencil_clear_tag 1 +#define GL_STENCIL_TAG_BITS_EXT 0x88F2 +#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 +typedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glStencilClearTagEXT (GLsizei stencilTagBits, GLuint stencilClearTag); +#endif +#endif /* GL_EXT_stencil_clear_tag */ + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 +typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum face); +#endif +#endif /* GL_EXT_stencil_two_side */ + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 +#endif /* GL_EXT_stencil_wrap */ + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 +typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +#endif +#endif /* GL_EXT_subtexture */ + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 +#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#endif /* GL_EXT_texture */ + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +#endif +#endif /* GL_EXT_texture3D */ + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#endif /* GL_EXT_texture_array */ + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E +typedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer); +#endif +#endif /* GL_EXT_texture_buffer_object */ + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 +#endif /* GL_EXT_texture_compression_latc */ + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE +#endif /* GL_EXT_texture_compression_rgtc */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif /* GL_EXT_texture_compression_s3tc */ + +#ifndef GL_EXT_texture_cube_map +#define GL_EXT_texture_cube_map 1 +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C +#endif /* GL_EXT_texture_cube_map */ + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 +#endif /* GL_EXT_texture_env_add */ + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A +#endif /* GL_EXT_texture_env_combine */ + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 +#endif /* GL_EXT_texture_env_dot3 */ + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif /* GL_EXT_texture_filter_anisotropic */ + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E +typedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params); +GLAPI void APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params); +GLAPI void APIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha); +GLAPI void APIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha); +#endif +#endif /* GL_EXT_texture_integer */ + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 +#endif /* GL_EXT_texture_lod_bias */ + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 +#endif /* GL_EXT_texture_mirror_clamp */ + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences); +GLAPI void APIENTRY glBindTextureEXT (GLenum target, GLuint texture); +GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures); +GLAPI void APIENTRY glGenTexturesEXT (GLsizei n, GLuint *textures); +GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint texture); +GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities); +#endif +#endif /* GL_EXT_texture_object */ + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF +typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureNormalEXT (GLenum mode); +#endif +#endif /* GL_EXT_texture_perturb_normal */ + +#ifndef GL_EXT_texture_sRGB +#define GL_EXT_texture_sRGB 1 +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F +#endif /* GL_EXT_texture_sRGB */ + +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A +#endif /* GL_EXT_texture_sRGB_decode */ + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F +#endif /* GL_EXT_texture_shared_exponent */ + +#ifndef GL_EXT_texture_snorm +#define GL_EXT_texture_snorm 1 +#define GL_ALPHA_SNORM 0x9010 +#define GL_LUMINANCE_SNORM 0x9011 +#define GL_LUMINANCE_ALPHA_SNORM 0x9012 +#define GL_INTENSITY_SNORM 0x9013 +#define GL_ALPHA8_SNORM 0x9014 +#define GL_LUMINANCE8_SNORM 0x9015 +#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 +#define GL_INTENSITY8_SNORM 0x9017 +#define GL_ALPHA16_SNORM 0x9018 +#define GL_LUMINANCE16_SNORM 0x9019 +#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A +#define GL_INTENSITY16_SNORM 0x901B +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#endif /* GL_EXT_texture_snorm */ + +#ifndef GL_EXT_texture_swizzle +#define GL_EXT_texture_swizzle 1 +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 +#endif /* GL_EXT_texture_swizzle */ + +#ifndef GL_EXT_timer_query +#define GL_EXT_timer_query 1 +#define GL_TIME_ELAPSED_EXT 0x88BF +typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params); +#endif +#endif /* GL_EXT_timer_query */ + +#ifndef GL_EXT_transform_feedback +#define GL_EXT_transform_feedback 1 +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); +typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); +typedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum primitiveMode); +GLAPI void APIENTRY glEndTransformFeedbackEXT (void); +GLAPI void APIENTRY glBindBufferRangeEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glBindBufferOffsetEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +GLAPI void APIENTRY glBindBufferBaseEXT (GLenum target, GLuint index, GLuint buffer); +GLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +#endif +#endif /* GL_EXT_transform_feedback */ + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); +typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, void **params); +typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glArrayElementEXT (GLint i); +GLAPI void APIENTRY glColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +GLAPI void APIENTRY glDrawArraysEXT (GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer); +GLAPI void APIENTRY glGetPointervEXT (GLenum pname, void **params); +GLAPI void APIENTRY glIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer); +GLAPI void APIENTRY glNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer); +GLAPI void APIENTRY glTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +GLAPI void APIENTRY glVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +#endif +#endif /* GL_EXT_vertex_array */ + +#ifndef GL_EXT_vertex_array_bgra +#define GL_EXT_vertex_array_bgra 1 +#endif /* GL_EXT_vertex_array_bgra */ + +#ifndef GL_EXT_vertex_attrib_64bit +#define GL_EXT_vertex_attrib_64bit 1 +#define GL_DOUBLE_VEC2_EXT 0x8FFC +#define GL_DOUBLE_VEC3_EXT 0x8FFD +#define GL_DOUBLE_VEC4_EXT 0x8FFE +#define GL_DOUBLE_MAT2_EXT 0x8F46 +#define GL_DOUBLE_MAT3_EXT 0x8F47 +#define GL_DOUBLE_MAT4_EXT 0x8F48 +#define GL_DOUBLE_MAT2x3_EXT 0x8F49 +#define GL_DOUBLE_MAT2x4_EXT 0x8F4A +#define GL_DOUBLE_MAT3x2_EXT 0x8F4B +#define GL_DOUBLE_MAT3x4_EXT 0x8F4C +#define GL_DOUBLE_MAT4x2_EXT 0x8F4D +#define GL_DOUBLE_MAT4x3_EXT 0x8F4E +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribL1dEXT (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttribL2dEXT (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttribL3dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttribL4dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttribL1dvEXT (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL2dvEXT (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL3dvEXT (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribL4dvEXT (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribLPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribLdvEXT (GLuint index, GLenum pname, GLdouble *params); +#endif +#endif /* GL_EXT_vertex_attrib_64bit */ + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED +typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); +typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const void *addr); +typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const void *addr); +typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr); +typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr); +typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr); +typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr); +typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr); +typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr); +typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr); +typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr); +typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const void *addr); +typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, void **data); +typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginVertexShaderEXT (void); +GLAPI void APIENTRY glEndVertexShaderEXT (void); +GLAPI void APIENTRY glBindVertexShaderEXT (GLuint id); +GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint range); +GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint id); +GLAPI void APIENTRY glShaderOp1EXT (GLenum op, GLuint res, GLuint arg1); +GLAPI void APIENTRY glShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +GLAPI void APIENTRY glShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +GLAPI void APIENTRY glSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +GLAPI void APIENTRY glWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +GLAPI void APIENTRY glInsertComponentEXT (GLuint res, GLuint src, GLuint num); +GLAPI void APIENTRY glExtractComponentEXT (GLuint res, GLuint src, GLuint num); +GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); +GLAPI void APIENTRY glSetInvariantEXT (GLuint id, GLenum type, const void *addr); +GLAPI void APIENTRY glSetLocalConstantEXT (GLuint id, GLenum type, const void *addr); +GLAPI void APIENTRY glVariantbvEXT (GLuint id, const GLbyte *addr); +GLAPI void APIENTRY glVariantsvEXT (GLuint id, const GLshort *addr); +GLAPI void APIENTRY glVariantivEXT (GLuint id, const GLint *addr); +GLAPI void APIENTRY glVariantfvEXT (GLuint id, const GLfloat *addr); +GLAPI void APIENTRY glVariantdvEXT (GLuint id, const GLdouble *addr); +GLAPI void APIENTRY glVariantubvEXT (GLuint id, const GLubyte *addr); +GLAPI void APIENTRY glVariantusvEXT (GLuint id, const GLushort *addr); +GLAPI void APIENTRY glVariantuivEXT (GLuint id, const GLuint *addr); +GLAPI void APIENTRY glVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const void *addr); +GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint id); +GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint id); +GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum light, GLenum value); +GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum face, GLenum value); +GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value); +GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum unit, GLenum value); +GLAPI GLuint APIENTRY glBindParameterEXT (GLenum value); +GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint id, GLenum cap); +GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data); +GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data); +GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data); +GLAPI void APIENTRY glGetVariantPointervEXT (GLuint id, GLenum value, void **data); +GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data); +GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data); +GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data); +GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data); +GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data); +GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data); +#endif +#endif /* GL_EXT_vertex_shader */ + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 +#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6 +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW0_EXT 0x1700 +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 +typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexWeightfEXT (GLfloat weight); +GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *weight); +GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer); +#endif +#endif /* GL_EXT_vertex_weighting */ + +#ifndef GL_EXT_x11_sync_object +#define GL_EXT_x11_sync_object 1 +#define GL_SYNC_X11_FENCE_EXT 0x90E1 +typedef GLsync (APIENTRYP PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLsync APIENTRY glImportSyncEXT (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags); +#endif +#endif /* GL_EXT_x11_sync_object */ + +#ifndef GL_GREMEDY_frame_terminator +#define GL_GREMEDY_frame_terminator 1 +typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFrameTerminatorGREMEDY (void); +#endif +#endif /* GL_GREMEDY_frame_terminator */ + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 +typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void *string); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei len, const void *string); +#endif +#endif /* GL_GREMEDY_string_marker */ + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 +#define GL_IGNORE_BORDER_HP 0x8150 +#define GL_CONSTANT_BORDER_HP 0x8151 +#define GL_REPLICATE_BORDER_HP 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 +#endif /* GL_HP_convolution_border_modes */ + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 +#define GL_IMAGE_SCALE_X_HP 0x8155 +#define GL_IMAGE_SCALE_Y_HP 0x8156 +#define GL_IMAGE_TRANSLATE_X_HP 0x8157 +#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 +#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 +#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A +#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B +#define GL_IMAGE_MAG_FILTER_HP 0x815C +#define GL_IMAGE_MIN_FILTER_HP 0x815D +#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E +#define GL_CUBIC_HP 0x815F +#define GL_AVERAGE_HP 0x8160 +#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 +#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 +#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glImageTransformParameteriHP (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params); +#endif +#endif /* GL_HP_image_transform */ + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 +#endif /* GL_HP_occlusion_test */ + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 +#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 +#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 +#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 +#endif /* GL_HP_texture_lighting */ + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 +#define GL_CULL_VERTEX_IBM 103050 +#endif /* GL_IBM_cull_vertex */ + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 +typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride); +#endif +#endif /* GL_IBM_multimode_draw_arrays */ + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 +#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 +#endif /* GL_IBM_rasterpos_clip */ + +#ifndef GL_IBM_static_data +#define GL_IBM_static_data 1 +#define GL_ALL_STATIC_DATA_IBM 103060 +#define GL_STATIC_VERTEX_ARRAY_IBM 103061 +typedef void (APIENTRYP PFNGLFLUSHSTATICDATAIBMPROC) (GLenum target); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFlushStaticDataIBM (GLenum target); +#endif +#endif /* GL_IBM_static_data */ + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_IBM_texture_mirrored_repeat 1 +#define GL_MIRRORED_REPEAT_IBM 0x8370 +#endif /* GL_IBM_texture_mirrored_repeat */ + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 +typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint stride, const GLboolean **pointer, GLint ptrstride); +GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride); +GLAPI void APIENTRY glIndexPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride); +GLAPI void APIENTRY glNormalPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride); +GLAPI void APIENTRY glTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +GLAPI void APIENTRY glVertexPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride); +#endif +#endif /* GL_IBM_vertex_array_lists */ + +#ifndef GL_INGR_blend_func_separate +#define GL_INGR_blend_func_separate 1 +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif +#endif /* GL_INGR_blend_func_separate */ + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 +#endif /* GL_INGR_color_clamp */ + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 +#define GL_INTERLACE_READ_INGR 0x8568 +#endif /* GL_INGR_interlace_read */ + +#ifndef GL_INTEL_fragment_shader_ordering +#define GL_INTEL_fragment_shader_ordering 1 +#endif /* GL_INTEL_fragment_shader_ordering */ + +#ifndef GL_INTEL_map_texture +#define GL_INTEL_map_texture 1 +#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF +#define GL_LAYOUT_DEFAULT_INTEL 0 +#define GL_LAYOUT_LINEAR_INTEL 1 +#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2 +typedef void (APIENTRYP PFNGLSYNCTEXTUREINTELPROC) (GLuint texture); +typedef void (APIENTRYP PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level); +typedef void *(APIENTRYP PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSyncTextureINTEL (GLuint texture); +GLAPI void APIENTRY glUnmapTexture2DINTEL (GLuint texture, GLint level); +GLAPI void *APIENTRY glMapTexture2DINTEL (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout); +#endif +#endif /* GL_INTEL_map_texture */ + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 +typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer); +typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void **pointer); +typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer); +typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexPointervINTEL (GLint size, GLenum type, const void **pointer); +GLAPI void APIENTRY glNormalPointervINTEL (GLenum type, const void **pointer); +GLAPI void APIENTRY glColorPointervINTEL (GLint size, GLenum type, const void **pointer); +GLAPI void APIENTRY glTexCoordPointervINTEL (GLint size, GLenum type, const void **pointer); +#endif +#endif /* GL_INTEL_parallel_arrays */ + +#ifndef GL_INTEL_performance_query +#define GL_INTEL_performance_query 1 +#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000 +#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001 +#define GL_PERFQUERY_WAIT_INTEL 0x83FB +#define GL_PERFQUERY_FLUSH_INTEL 0x83FA +#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9 +#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0 +#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1 +#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2 +#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3 +#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4 +#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5 +#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8 +#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9 +#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA +#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB +#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC +#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD +#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE +#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF +#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500 +typedef void (APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle); +typedef void (APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId); +typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId); +typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); +typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId); +typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle); +GLAPI void APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle); +GLAPI void APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle); +GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle); +GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId); +GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId); +GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); +GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId); +GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); +#endif +#endif /* GL_INTEL_performance_query */ + +#ifndef GL_MESAX_texture_stack +#define GL_MESAX_texture_stack 1 +#define GL_TEXTURE_1D_STACK_MESAX 0x8759 +#define GL_TEXTURE_2D_STACK_MESAX 0x875A +#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B +#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C +#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D +#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E +#endif /* GL_MESAX_texture_stack */ + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 +#define GL_PACK_INVERT_MESA 0x8758 +#endif /* GL_MESA_pack_invert */ + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 +typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glResizeBuffersMESA (void); +#endif +#endif /* GL_MESA_resize_buffers */ + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 +typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWindowPos2dMESA (GLdouble x, GLdouble y); +GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *v); +GLAPI void APIENTRY glWindowPos2fMESA (GLfloat x, GLfloat y); +GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *v); +GLAPI void APIENTRY glWindowPos2iMESA (GLint x, GLint y); +GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *v); +GLAPI void APIENTRY glWindowPos2sMESA (GLshort x, GLshort y); +GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *v); +GLAPI void APIENTRY glWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *v); +GLAPI void APIENTRY glWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *v); +GLAPI void APIENTRY glWindowPos3iMESA (GLint x, GLint y, GLint z); +GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *v); +GLAPI void APIENTRY glWindowPos3sMESA (GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *v); +GLAPI void APIENTRY glWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *v); +GLAPI void APIENTRY glWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *v); +GLAPI void APIENTRY glWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *v); +GLAPI void APIENTRY glWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v); +#endif +#endif /* GL_MESA_window_pos */ + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 +#endif /* GL_MESA_ycbcr_texture */ + +#ifndef GL_NVX_conditional_render +#define GL_NVX_conditional_render 1 +typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id); +typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVXPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginConditionalRenderNVX (GLuint id); +GLAPI void APIENTRY glEndConditionalRenderNVX (void); +#endif +#endif /* GL_NVX_conditional_render */ + +#ifndef GL_NVX_gpu_memory_info +#define GL_NVX_gpu_memory_info 1 +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B +#endif /* GL_NVX_gpu_memory_info */ + +#ifndef GL_NV_bindless_multi_draw_indirect +#define GL_NV_bindless_multi_draw_indirect 1 +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +#endif +#endif /* GL_NV_bindless_multi_draw_indirect */ + +#ifndef GL_NV_bindless_texture +#define GL_NV_bindless_texture 1 +typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture); +typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle); +typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint64 APIENTRY glGetTextureHandleNV (GLuint texture); +GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler); +GLAPI void APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle); +GLAPI void APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle); +GLAPI GLuint64 APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +GLAPI void APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access); +GLAPI void APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle); +GLAPI void APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value); +GLAPI void APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value); +GLAPI void APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +GLAPI GLboolean APIENTRY glIsTextureHandleResidentNV (GLuint64 handle); +GLAPI GLboolean APIENTRY glIsImageHandleResidentNV (GLuint64 handle); +#endif +#endif /* GL_NV_bindless_texture */ + +#ifndef GL_NV_blend_equation_advanced +#define GL_NV_blend_equation_advanced 1 +#define GL_BLEND_OVERLAP_NV 0x9281 +#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280 +#define GL_BLUE_NV 0x1905 +#define GL_COLORBURN_NV 0x929A +#define GL_COLORDODGE_NV 0x9299 +#define GL_CONJOINT_NV 0x9284 +#define GL_CONTRAST_NV 0x92A1 +#define GL_DARKEN_NV 0x9297 +#define GL_DIFFERENCE_NV 0x929E +#define GL_DISJOINT_NV 0x9283 +#define GL_DST_ATOP_NV 0x928F +#define GL_DST_IN_NV 0x928B +#define GL_DST_NV 0x9287 +#define GL_DST_OUT_NV 0x928D +#define GL_DST_OVER_NV 0x9289 +#define GL_EXCLUSION_NV 0x92A0 +#define GL_GREEN_NV 0x1904 +#define GL_HARDLIGHT_NV 0x929B +#define GL_HARDMIX_NV 0x92A9 +#define GL_HSL_COLOR_NV 0x92AF +#define GL_HSL_HUE_NV 0x92AD +#define GL_HSL_LUMINOSITY_NV 0x92B0 +#define GL_HSL_SATURATION_NV 0x92AE +#define GL_INVERT_OVG_NV 0x92B4 +#define GL_INVERT_RGB_NV 0x92A3 +#define GL_LIGHTEN_NV 0x9298 +#define GL_LINEARBURN_NV 0x92A5 +#define GL_LINEARDODGE_NV 0x92A4 +#define GL_LINEARLIGHT_NV 0x92A7 +#define GL_MINUS_CLAMPED_NV 0x92B3 +#define GL_MINUS_NV 0x929F +#define GL_MULTIPLY_NV 0x9294 +#define GL_OVERLAY_NV 0x9296 +#define GL_PINLIGHT_NV 0x92A8 +#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2 +#define GL_PLUS_CLAMPED_NV 0x92B1 +#define GL_PLUS_DARKER_NV 0x9292 +#define GL_PLUS_NV 0x9291 +#define GL_RED_NV 0x1903 +#define GL_SCREEN_NV 0x9295 +#define GL_SOFTLIGHT_NV 0x929C +#define GL_SRC_ATOP_NV 0x928E +#define GL_SRC_IN_NV 0x928A +#define GL_SRC_NV 0x9286 +#define GL_SRC_OUT_NV 0x928C +#define GL_SRC_OVER_NV 0x9288 +#define GL_UNCORRELATED_NV 0x9282 +#define GL_VIVIDLIGHT_NV 0x92A6 +#define GL_XOR_NV 0x1506 +typedef void (APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLBLENDBARRIERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendParameteriNV (GLenum pname, GLint value); +GLAPI void APIENTRY glBlendBarrierNV (void); +#endif +#endif /* GL_NV_blend_equation_advanced */ + +#ifndef GL_NV_blend_equation_advanced_coherent +#define GL_NV_blend_equation_advanced_coherent 1 +#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285 +#endif /* GL_NV_blend_equation_advanced_coherent */ + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 +#endif /* GL_NV_blend_square */ + +#ifndef GL_NV_compute_program5 +#define GL_NV_compute_program5 1 +#define GL_COMPUTE_PROGRAM_NV 0x90FB +#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC +#endif /* GL_NV_compute_program5 */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 +typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode); +GLAPI void APIENTRY glEndConditionalRenderNV (void); +#endif +#endif /* GL_NV_conditional_render */ + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F +#endif /* GL_NV_copy_depth_to_color */ + +#ifndef GL_NV_copy_image +#define GL_NV_copy_image 1 +typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCopyImageSubDataNV (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +#endif +#endif /* GL_NV_copy_image */ + +#ifndef GL_NV_deep_texture3D +#define GL_NV_deep_texture3D 1 +#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0 +#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1 +#endif /* GL_NV_deep_texture3D */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF +typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); +typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar); +GLAPI void APIENTRY glClearDepthdNV (GLdouble depth); +GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax); +#endif +#endif /* GL_NV_depth_buffer_float */ + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 +#define GL_DEPTH_CLAMP_NV 0x864F +#endif /* GL_NV_depth_clamp */ + +#ifndef GL_NV_draw_texture +#define GL_NV_draw_texture 1 +typedef void (APIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawTextureNV (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +#endif +#endif /* GL_NV_draw_texture */ + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 +typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points); +typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points); +typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points); +GLAPI void APIENTRY glMapParameterivNV (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points); +GLAPI void APIENTRY glGetMapParameterivNV (GLenum target, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glEvalMapsNV (GLenum target, GLenum mode); +#endif +#endif /* GL_NV_evaluators */ + +#ifndef GL_NV_explicit_multisample +#define GL_NV_explicit_multisample 1 +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 +typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val); +typedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); +typedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetMultisamplefvNV (GLenum pname, GLuint index, GLfloat *val); +GLAPI void APIENTRY glSampleMaskIndexedNV (GLuint index, GLbitfield mask); +GLAPI void APIENTRY glTexRenderbufferNV (GLenum target, GLuint renderbuffer); +#endif +#endif /* GL_NV_explicit_multisample */ + +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences); +GLAPI void APIENTRY glGenFencesNV (GLsizei n, GLuint *fences); +GLAPI GLboolean APIENTRY glIsFenceNV (GLuint fence); +GLAPI GLboolean APIENTRY glTestFenceNV (GLuint fence); +GLAPI void APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params); +GLAPI void APIENTRY glFinishFenceNV (GLuint fence); +GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition); +#endif +#endif /* GL_NV_fence */ + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E +#endif /* GL_NV_float_buffer */ + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C +#endif /* GL_NV_fog_distance */ + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); +typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); +GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); +GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); +GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); +#endif +#endif /* GL_NV_fragment_program */ + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 +#endif /* GL_NV_fragment_program2 */ + +#ifndef GL_NV_fragment_program4 +#define GL_NV_fragment_program4 1 +#endif /* GL_NV_fragment_program4 */ + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 +#endif /* GL_NV_fragment_program_option */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif /* GL_NV_framebuffer_multisample_coverage */ + +#ifndef GL_NV_geometry_program4 +#define GL_NV_geometry_program4 1 +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 +typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit); +GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +#endif +#endif /* GL_NV_geometry_program4 */ + +#ifndef GL_NV_geometry_shader4 +#define GL_NV_geometry_shader4 1 +#endif /* GL_NV_geometry_shader4 */ + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 +#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params); +GLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params); +GLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params); +GLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params); +GLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params); +GLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params); +GLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params); +GLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params); +GLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params); +GLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params); +GLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params); +GLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params); +#endif +#endif /* GL_NV_gpu_program4 */ + +#ifndef GL_NV_gpu_program5 +#define GL_NV_gpu_program5 1 +#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C +#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F +#define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44 +#define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45 +typedef void (APIENTRYP PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC) (GLenum target, GLsizei count, const GLuint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC) (GLenum target, GLuint index, GLuint *param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramSubroutineParametersuivNV (GLenum target, GLsizei count, const GLuint *params); +GLAPI void APIENTRY glGetProgramSubroutineParameteruivNV (GLenum target, GLuint index, GLuint *param); +#endif +#endif /* GL_NV_gpu_program5 */ + +#ifndef GL_NV_gpu_program5_mem_extended +#define GL_NV_gpu_program5_mem_extended 1 +#endif /* GL_NV_gpu_program5_mem_extended */ + +#ifndef GL_NV_gpu_shader5 +#define GL_NV_gpu_shader5 1 +#endif /* GL_NV_gpu_shader5 */ + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 +typedef unsigned short GLhalfNV; +#define GL_HALF_FLOAT_NV 0x140B +typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y); +typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z); +typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); +typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); +typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s); +typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t); +typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r); +typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); +typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y); +GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z); +GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); +GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); +GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV s); +GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV s, GLhalfNV t); +GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r); +GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum target, GLhalfNV s); +GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v); +GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t); +GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v); +GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); +GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v); +GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v); +GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog); +GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog); +GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight); +GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight); +GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x); +GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y); +GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint index, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); +GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint index, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint index, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v); +GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v); +#endif +#endif /* GL_NV_half_float */ + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif /* GL_NV_light_max_exponent */ + +#ifndef GL_NV_multisample_coverage +#define GL_NV_multisample_coverage 1 +#define GL_COLOR_SAMPLES_NV 0x8E20 +#endif /* GL_NV_multisample_coverage */ + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 +#endif /* GL_NV_multisample_filter_hint */ + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 +typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei n, GLuint *ids); +GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids); +GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint id); +GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint id); +GLAPI void APIENTRY glEndOcclusionQueryNV (void); +GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params); +#endif +#endif /* GL_NV_occlusion_query */ + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA +#endif /* GL_NV_packed_depth_stencil */ + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 +#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 +#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 +#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 +typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params); +typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params); +typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params); +GLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params); +GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params); +#endif +#endif /* GL_NV_parameter_buffer_object */ + +#ifndef GL_NV_parameter_buffer_object2 +#define GL_NV_parameter_buffer_object2 1 +#endif /* GL_NV_parameter_buffer_object2 */ + +#ifndef GL_NV_path_rendering +#define GL_NV_path_rendering 1 +#define GL_PATH_FORMAT_SVG_NV 0x9070 +#define GL_PATH_FORMAT_PS_NV 0x9071 +#define GL_STANDARD_FONT_NAME_NV 0x9072 +#define GL_SYSTEM_FONT_NAME_NV 0x9073 +#define GL_FILE_NAME_NV 0x9074 +#define GL_PATH_STROKE_WIDTH_NV 0x9075 +#define GL_PATH_END_CAPS_NV 0x9076 +#define GL_PATH_INITIAL_END_CAP_NV 0x9077 +#define GL_PATH_TERMINAL_END_CAP_NV 0x9078 +#define GL_PATH_JOIN_STYLE_NV 0x9079 +#define GL_PATH_MITER_LIMIT_NV 0x907A +#define GL_PATH_DASH_CAPS_NV 0x907B +#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C +#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D +#define GL_PATH_DASH_OFFSET_NV 0x907E +#define GL_PATH_CLIENT_LENGTH_NV 0x907F +#define GL_PATH_FILL_MODE_NV 0x9080 +#define GL_PATH_FILL_MASK_NV 0x9081 +#define GL_PATH_FILL_COVER_MODE_NV 0x9082 +#define GL_PATH_STROKE_COVER_MODE_NV 0x9083 +#define GL_PATH_STROKE_MASK_NV 0x9084 +#define GL_COUNT_UP_NV 0x9088 +#define GL_COUNT_DOWN_NV 0x9089 +#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A +#define GL_CONVEX_HULL_NV 0x908B +#define GL_BOUNDING_BOX_NV 0x908D +#define GL_TRANSLATE_X_NV 0x908E +#define GL_TRANSLATE_Y_NV 0x908F +#define GL_TRANSLATE_2D_NV 0x9090 +#define GL_TRANSLATE_3D_NV 0x9091 +#define GL_AFFINE_2D_NV 0x9092 +#define GL_AFFINE_3D_NV 0x9094 +#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096 +#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098 +#define GL_UTF8_NV 0x909A +#define GL_UTF16_NV 0x909B +#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C +#define GL_PATH_COMMAND_COUNT_NV 0x909D +#define GL_PATH_COORD_COUNT_NV 0x909E +#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F +#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0 +#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1 +#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2 +#define GL_SQUARE_NV 0x90A3 +#define GL_ROUND_NV 0x90A4 +#define GL_TRIANGULAR_NV 0x90A5 +#define GL_BEVEL_NV 0x90A6 +#define GL_MITER_REVERT_NV 0x90A7 +#define GL_MITER_TRUNCATE_NV 0x90A8 +#define GL_SKIP_MISSING_GLYPH_NV 0x90A9 +#define GL_USE_MISSING_GLYPH_NV 0x90AA +#define GL_PATH_ERROR_POSITION_NV 0x90AB +#define GL_PATH_FOG_GEN_MODE_NV 0x90AC +#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD +#define GL_ADJACENT_PAIRS_NV 0x90AE +#define GL_FIRST_TO_REST_NV 0x90AF +#define GL_PATH_GEN_MODE_NV 0x90B0 +#define GL_PATH_GEN_COEFF_NV 0x90B1 +#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2 +#define GL_PATH_GEN_COMPONENTS_NV 0x90B3 +#define GL_PATH_STENCIL_FUNC_NV 0x90B7 +#define GL_PATH_STENCIL_REF_NV 0x90B8 +#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9 +#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD +#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE +#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF +#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4 +#define GL_MOVE_TO_RESETS_NV 0x90B5 +#define GL_MOVE_TO_CONTINUES_NV 0x90B6 +#define GL_CLOSE_PATH_NV 0x00 +#define GL_MOVE_TO_NV 0x02 +#define GL_RELATIVE_MOVE_TO_NV 0x03 +#define GL_LINE_TO_NV 0x04 +#define GL_RELATIVE_LINE_TO_NV 0x05 +#define GL_HORIZONTAL_LINE_TO_NV 0x06 +#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 +#define GL_VERTICAL_LINE_TO_NV 0x08 +#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09 +#define GL_QUADRATIC_CURVE_TO_NV 0x0A +#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B +#define GL_CUBIC_CURVE_TO_NV 0x0C +#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D +#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E +#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F +#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10 +#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11 +#define GL_SMALL_CCW_ARC_TO_NV 0x12 +#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13 +#define GL_SMALL_CW_ARC_TO_NV 0x14 +#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15 +#define GL_LARGE_CCW_ARC_TO_NV 0x16 +#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17 +#define GL_LARGE_CW_ARC_TO_NV 0x18 +#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19 +#define GL_RESTART_PATH_NV 0xF0 +#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2 +#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4 +#define GL_RECT_NV 0xF6 +#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8 +#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA +#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC +#define GL_ARC_TO_NV 0xFE +#define GL_RELATIVE_ARC_TO_NV 0xFF +#define GL_BOLD_BIT_NV 0x01 +#define GL_ITALIC_BIT_NV 0x02 +#define GL_GLYPH_WIDTH_BIT_NV 0x01 +#define GL_GLYPH_HEIGHT_BIT_NV 0x02 +#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 +#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08 +#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10 +#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20 +#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40 +#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80 +#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100 +#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000 +#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000 +#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000 +#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000 +#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000 +#define GL_FONT_ASCENDER_BIT_NV 0x00200000 +#define GL_FONT_DESCENDER_BIT_NV 0x00400000 +#define GL_FONT_HEIGHT_BIT_NV 0x00800000 +#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000 +#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000 +#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000 +#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 +#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000 +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +typedef GLuint (APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range); +typedef void (APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range); +typedef GLboolean (APIENTRYP PFNGLISPATHNVPROC) (GLuint path); +typedef void (APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); +typedef void (APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString); +typedef void (APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); +typedef void (APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath); +typedef void (APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +typedef void (APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value); +typedef void (APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value); +typedef void (APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value); +typedef void (APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value); +typedef void (APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray); +typedef void (APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units); +typedef void (APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func); +typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs); +typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs); +typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode); +typedef void (APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value); +typedef void (APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value); +typedef void (APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands); +typedef void (APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords); +typedef void (APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray); +typedef void (APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +typedef void (APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); +typedef void (APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +typedef void (APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value); +typedef void (APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value); +typedef void (APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value); +typedef void (APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value); +typedef GLboolean (APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); +typedef GLboolean (APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); +typedef GLfloat (APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments); +typedef GLboolean (APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glGenPathsNV (GLsizei range); +GLAPI void APIENTRY glDeletePathsNV (GLuint path, GLsizei range); +GLAPI GLboolean APIENTRY glIsPathNV (GLuint path); +GLAPI void APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); +GLAPI void APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString); +GLAPI void APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GLAPI void APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +GLAPI void APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); +GLAPI void APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath); +GLAPI void APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +GLAPI void APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value); +GLAPI void APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value); +GLAPI void APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value); +GLAPI void APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value); +GLAPI void APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray); +GLAPI void APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units); +GLAPI void APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask); +GLAPI void APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask); +GLAPI void APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glPathCoverDepthFuncNV (GLenum func); +GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs); +GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs); +GLAPI void APIENTRY glPathFogGenNV (GLenum genMode); +GLAPI void APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode); +GLAPI void APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode); +GLAPI void APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +GLAPI void APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value); +GLAPI void APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value); +GLAPI void APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands); +GLAPI void APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords); +GLAPI void APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray); +GLAPI void APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +GLAPI void APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); +GLAPI void APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +GLAPI void APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value); +GLAPI void APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value); +GLAPI void APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value); +GLAPI void APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value); +GLAPI GLboolean APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y); +GLAPI GLboolean APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y); +GLAPI GLfloat APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments); +GLAPI GLboolean APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +#endif +#endif /* GL_NV_path_rendering */ + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D +typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, const void *pointer); +typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, const void *pointer); +GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target); +#endif +#endif /* GL_NV_pixel_data_range */ + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 +typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameteriNV (GLenum pname, GLint param); +GLAPI void APIENTRY glPointParameterivNV (GLenum pname, const GLint *params); +#endif +#endif /* GL_NV_point_sprite */ + +#ifndef GL_NV_present_video +#define GL_NV_present_video 1 +#define GL_FRAME_NV 0x8E26 +#define GL_FIELDS_NV 0x8E27 +#define GL_CURRENT_TIME_NV 0x8E28 +#define GL_NUM_FILL_STREAMS_NV 0x8E29 +#define GL_PRESENT_TIME_NV 0x8E2A +#define GL_PRESENT_DURATION_NV 0x8E2B +typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); +typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); +typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params); +typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); +GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); +GLAPI void APIENTRY glGetVideoivNV (GLuint video_slot, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVideouivNV (GLuint video_slot, GLenum pname, GLuint *params); +GLAPI void APIENTRY glGetVideoi64vNV (GLuint video_slot, GLenum pname, GLint64EXT *params); +GLAPI void APIENTRY glGetVideoui64vNV (GLuint video_slot, GLenum pname, GLuint64EXT *params); +#endif +#endif /* GL_NV_present_video */ + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void); +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPrimitiveRestartNV (void); +GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index); +#endif +#endif /* GL_NV_primitive_restart */ + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCombinerParameterfvNV (GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glCombinerParameterfNV (GLenum pname, GLfloat param); +GLAPI void APIENTRY glCombinerParameterivNV (GLenum pname, const GLint *params); +GLAPI void APIENTRY glCombinerParameteriNV (GLenum pname, GLint param); +GLAPI void APIENTRY glCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +GLAPI void APIENTRY glCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +GLAPI void APIENTRY glFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params); +#endif +#endif /* GL_NV_register_combiners */ + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 +typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params); +#endif +#endif /* GL_NV_register_combiners2 */ + +#ifndef GL_NV_shader_atomic_counters +#define GL_NV_shader_atomic_counters 1 +#endif /* GL_NV_shader_atomic_counters */ + +#ifndef GL_NV_shader_atomic_float +#define GL_NV_shader_atomic_float 1 +#endif /* GL_NV_shader_atomic_float */ + +#ifndef GL_NV_shader_buffer_load +#define GL_NV_shader_buffer_load 1 +#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D +#define GL_GPU_ADDRESS_NV 0x8F34 +#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 +typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); +typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); +typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); +typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); +typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); +typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result); +typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); +typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access); +GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target); +GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target); +GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access); +GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer); +GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer); +GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params); +GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params); +GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result); +GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value); +GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value); +GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value); +GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value); +#endif +#endif /* GL_NV_shader_buffer_load */ + +#ifndef GL_NV_shader_buffer_store +#define GL_NV_shader_buffer_store 1 +#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010 +#endif /* GL_NV_shader_buffer_store */ + +#ifndef GL_NV_shader_storage_buffer_object +#define GL_NV_shader_storage_buffer_object 1 +#endif /* GL_NV_shader_storage_buffer_object */ + +#ifndef GL_NV_shader_thread_group +#define GL_NV_shader_thread_group 1 +#define GL_WARP_SIZE_NV 0x9339 +#define GL_WARPS_PER_SM_NV 0x933A +#define GL_SM_COUNT_NV 0x933B +#endif /* GL_NV_shader_thread_group */ + +#ifndef GL_NV_shader_thread_shuffle +#define GL_NV_shader_thread_shuffle 1 +#endif /* GL_NV_shader_thread_shuffle */ + +#ifndef GL_NV_tessellation_program5 +#define GL_NV_tessellation_program5 1 +#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 +#define GL_TESS_CONTROL_PROGRAM_NV 0x891E +#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F +#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74 +#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75 +#endif /* GL_NV_tessellation_program5 */ + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F +#endif /* GL_NV_texgen_emboss */ + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 +#endif /* GL_NV_texgen_reflection */ + +#ifndef GL_NV_texture_barrier +#define GL_NV_texture_barrier 1 +typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureBarrierNV (void); +#endif +#endif /* GL_NV_texture_barrier */ + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 +#endif /* GL_NV_texture_compression_vtc */ + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B +#endif /* GL_NV_texture_env_combine4 */ + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F +#endif /* GL_NV_texture_expand_normal */ + +#ifndef GL_NV_texture_multisample +#define GL_NV_texture_multisample 1 +#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045 +#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046 +typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexImage2DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +GLAPI void APIENTRY glTexImage3DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +GLAPI void APIENTRY glTextureImage2DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +GLAPI void APIENTRY glTextureImage3DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +GLAPI void APIENTRY glTextureImage2DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +#endif +#endif /* GL_NV_texture_multisample */ + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 +#endif /* GL_NV_texture_rectangle */ + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F +#endif /* GL_NV_texture_shader */ + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#endif /* GL_NV_texture_shader2 */ + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 +#endif /* GL_NV_texture_shader3 */ + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F +#define GL_LAYER_NV 0x8DAA +#define GL_NEXT_BUFFER_NV -2 +#define GL_SKIP_COMPONENTS4_NV -3 +#define GL_SKIP_COMPONENTS3_NV -4 +#define GL_SKIP_COMPONENTS2_NV -5 +#define GL_SKIP_COMPONENTS1_NV -6 +typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); +typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); +typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); +typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); +typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode); +GLAPI void APIENTRY glEndTransformFeedbackNV (void); +GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode); +GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer); +GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); +GLAPI void APIENTRY glActiveVaryingNV (GLuint program, const GLchar *name); +GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name); +GLAPI void APIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location); +GLAPI void APIENTRY glTransformFeedbackStreamAttribsNV (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode); +#endif +#endif /* GL_NV_transform_feedback */ + +#ifndef GL_NV_transform_feedback2 +#define GL_NV_transform_feedback2 1 +#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 +typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids); +typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void); +typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void); +typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindTransformFeedbackNV (GLenum target, GLuint id); +GLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei n, const GLuint *ids); +GLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei n, GLuint *ids); +GLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint id); +GLAPI void APIENTRY glPauseTransformFeedbackNV (void); +GLAPI void APIENTRY glResumeTransformFeedbackNV (void); +GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id); +#endif +#endif /* GL_NV_transform_feedback2 */ + +#ifndef GL_NV_vdpau_interop +#define GL_NV_vdpau_interop 1 +typedef GLintptr GLvdpauSurfaceNV; +#define GL_SURFACE_STATE_NV 0x86EB +#define GL_SURFACE_REGISTERED_NV 0x86FD +#define GL_SURFACE_MAPPED_NV 0x8700 +#define GL_WRITE_DISCARD_NV 0x88BE +typedef void (APIENTRYP PFNGLVDPAUINITNVPROC) (const void *vdpDevice, const void *getProcAddress); +typedef void (APIENTRYP PFNGLVDPAUFININVPROC) (void); +typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef GLboolean (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); +typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); +typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); +typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); +typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVDPAUInitNV (const void *vdpDevice, const void *getProcAddress); +GLAPI void APIENTRY glVDPAUFiniNV (void); +GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +GLAPI GLboolean APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface); +GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface); +GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access); +GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); +GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); +#endif +#endif /* GL_NV_vdpau_interop */ + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const void *pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFlushVertexArrayRangeNV (void); +GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei length, const void *pointer); +#endif +#endif /* GL_NV_vertex_array_range */ + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +#endif /* GL_NV_vertex_array_range2 */ + +#ifndef GL_NV_vertex_attrib_integer_64bit +#define GL_NV_vertex_attrib_integer_64bit 1 +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x); +GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y); +GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v); +GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x); +GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y); +GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v); +GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params); +GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params); +GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride); +#endif +#endif /* GL_NV_vertex_attrib_integer_64bit */ + +#ifndef GL_NV_vertex_buffer_unified_memory +#define GL_NV_vertex_buffer_unified_memory 1 +#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E +#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F +#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 +#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 +#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 +#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 +#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 +#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 +#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 +#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 +#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 +#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 +#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A +#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B +#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C +#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D +#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E +#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F +#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 +#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 +#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 +#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 +#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 +#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 +#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 +typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); +typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride); +GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride); +GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride); +GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride); +GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride); +GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result); +#endif +#endif /* GL_NV_vertex_buffer_unified_memory */ + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F +typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); +typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); +typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); +typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, void **pointer); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences); +GLAPI void APIENTRY glBindProgramNV (GLenum target, GLuint id); +GLAPI void APIENTRY glDeleteProgramsNV (GLsizei n, const GLuint *programs); +GLAPI void APIENTRY glExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params); +GLAPI void APIENTRY glGenProgramsNV (GLsizei n, GLuint *programs); +GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetProgramivNV (GLuint id, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program); +GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params); +GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint index, GLenum pname, void **pointer); +GLAPI GLboolean APIENTRY glIsProgramNV (GLuint id); +GLAPI void APIENTRY glLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program); +GLAPI void APIENTRY glProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v); +GLAPI void APIENTRY glProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v); +GLAPI void APIENTRY glProgramParameters4dvNV (GLenum target, GLuint index, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glProgramParameters4fvNV (GLenum target, GLuint index, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei n, const GLuint *programs); +GLAPI void APIENTRY glTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform); +GLAPI void APIENTRY glVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glVertexAttrib1dNV (GLuint index, GLdouble x); +GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib1fNV (GLuint index, GLfloat x); +GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib1sNV (GLuint index, GLshort x); +GLAPI void APIENTRY glVertexAttrib1svNV (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y); +GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y); +GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib2sNV (GLuint index, GLshort x, GLshort y); +GLAPI void APIENTRY glVertexAttrib2svNV (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z); +GLAPI void APIENTRY glVertexAttrib3svNV (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint index, const GLdouble *v); +GLAPI void APIENTRY glVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint index, const GLfloat *v); +GLAPI void APIENTRY glVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void APIENTRY glVertexAttrib4svNV (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v); +GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v); +GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v); +GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v); +GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v); +#endif +#endif /* GL_NV_vertex_program */ + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 +#endif /* GL_NV_vertex_program1_1 */ + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 +#endif /* GL_NV_vertex_program2 */ + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 +#endif /* GL_NV_vertex_program2_option */ + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 +#endif /* GL_NV_vertex_program3 */ + +#ifndef GL_NV_vertex_program4 +#define GL_NV_vertex_program4 1 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x); +GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y); +GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z); +GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x); +GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y); +GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z); +GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params); +#endif +#endif /* GL_NV_vertex_program4 */ + +#ifndef GL_NV_video_capture +#define GL_NV_video_capture 1 +#define GL_VIDEO_BUFFER_NV 0x9020 +#define GL_VIDEO_BUFFER_BINDING_NV 0x9021 +#define GL_FIELD_UPPER_NV 0x9022 +#define GL_FIELD_LOWER_NV 0x9023 +#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024 +#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025 +#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026 +#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027 +#define GL_VIDEO_BUFFER_PITCH_NV 0x9028 +#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029 +#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A +#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B +#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C +#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D +#define GL_PARTIAL_SUCCESS_NV 0x902E +#define GL_SUCCESS_NV 0x902F +#define GL_FAILURE_NV 0x9030 +#define GL_YCBYCR8_422_NV 0x9031 +#define GL_YCBAYCR8A_4224_NV 0x9032 +#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033 +#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034 +#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035 +#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036 +#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037 +#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038 +#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039 +#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A +#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B +#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C +typedef void (APIENTRYP PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); +typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (APIENTRYP PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params); +typedef GLenum (APIENTRYP PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time); +typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginVideoCaptureNV (GLuint video_capture_slot); +GLAPI void APIENTRY glBindVideoCaptureStreamBufferNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); +GLAPI void APIENTRY glBindVideoCaptureStreamTextureNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); +GLAPI void APIENTRY glEndVideoCaptureNV (GLuint video_capture_slot); +GLAPI void APIENTRY glGetVideoCaptureivNV (GLuint video_capture_slot, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVideoCaptureStreamivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVideoCaptureStreamfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetVideoCaptureStreamdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params); +GLAPI GLenum APIENTRY glVideoCaptureNV (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time); +GLAPI void APIENTRY glVideoCaptureStreamParameterivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params); +GLAPI void APIENTRY glVideoCaptureStreamParameterfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params); +#endif +#endif /* GL_NV_video_capture */ + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 +#endif /* GL_OML_interlace */ + +#ifndef GL_OML_resample +#define GL_OML_resample 1 +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 +#endif /* GL_OML_resample */ + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 +#endif /* GL_OML_subsample */ + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 +#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD +#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 +#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C +#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E +#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F +#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 +#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 +#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 +#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 +#define GL_CLIP_NEAR_HINT_PGI 0x1A220 +#define GL_CLIP_FAR_HINT_PGI 0x1A221 +#define GL_WIDE_LINE_HINT_PGI 0x1A222 +#define GL_BACK_NORMALS_HINT_PGI 0x1A223 +typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glHintPGI (GLenum target, GLint mode); +#endif +#endif /* GL_PGI_misc_hints */ + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 +#define GL_VERTEX_DATA_HINT_PGI 0x1A22A +#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B +#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C +#define GL_MAX_VERTEX_HINT_PGI 0x1A22D +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#endif /* GL_PGI_vertex_hints */ + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 +#endif /* GL_REND_screen_coordinates */ + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#define GL_RGBA_DXT5_S3TC 0x83A4 +#define GL_RGBA4_DXT5_S3TC 0x83A5 +#endif /* GL_S3_s3tc */ + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 +#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 +#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 +#define GL_LINEAR_DETAIL_SGIS 0x8097 +#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 +#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 +#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A +#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B +#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C +typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points); +GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum target, GLfloat *points); +#endif +#endif /* GL_SGIS_detail_texture */ + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 +#define GL_FOG_FUNC_SGIS 0x812A +#define GL_FOG_FUNC_POINTS_SGIS 0x812B +#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C +typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); +typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFogFuncSGIS (GLsizei n, const GLfloat *points); +GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *points); +#endif +#endif /* GL_SGIS_fog_function */ + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#endif /* GL_SGIS_generate_mipmap */ + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSampleMaskSGIS (GLclampf value, GLboolean invert); +GLAPI void APIENTRY glSamplePatternSGIS (GLenum pattern); +#endif +#endif /* GL_SGIS_multisample */ + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 +#define GL_PIXEL_TEXTURE_SGIS 0x8353 +#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 +#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 +#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum pname, GLint param); +GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum pname, const GLint *params); +GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params); +GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params); +#endif +#endif /* GL_SGIS_pixel_texture */ + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 +#endif /* GL_SGIS_point_line_texgen */ + +#ifndef GL_SGIS_point_parameters +#define GL_SGIS_point_parameters 1 +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameterfSGIS (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPointParameterfvSGIS (GLenum pname, const GLfloat *params); +#endif +#endif /* GL_SGIS_point_parameters */ + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 +#define GL_LINEAR_SHARPEN_SGIS 0x80AD +#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE +#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF +#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 +typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points); +GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum target, GLfloat *points); +#endif +#endif /* GL_SGIS_sharpen_texture */ + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 +#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 +#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 +#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 +#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 +#define GL_TEXTURE_4D_SGIS 0x8134 +#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 +#define GL_TEXTURE_4DSIZE_SGIS 0x8136 +#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 +#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 +#define GL_TEXTURE_4D_BINDING_SGIS 0x814F +typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels); +#endif +#endif /* GL_SGIS_texture4D */ + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 +#define GL_CLAMP_TO_BORDER_SGIS 0x812D +#endif /* GL_SGIS_texture_border_clamp */ + +#ifndef GL_SGIS_texture_color_mask +#define GL_SGIS_texture_color_mask 1 +#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF +typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#endif +#endif /* GL_SGIS_texture_color_mask */ + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 +#define GL_CLAMP_TO_EDGE_SGIS 0x812F +#endif /* GL_SGIS_texture_edge_clamp */ + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 +#define GL_FILTER4_SGIS 0x8146 +#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 +typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); +typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights); +GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); +#endif +#endif /* GL_SGIS_texture_filter4 */ + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D +#endif /* GL_SGIS_texture_lod */ + +#ifndef GL_SGIS_texture_select +#define GL_SGIS_texture_select 1 +#define GL_DUAL_ALPHA4_SGIS 0x8110 +#define GL_DUAL_ALPHA8_SGIS 0x8111 +#define GL_DUAL_ALPHA12_SGIS 0x8112 +#define GL_DUAL_ALPHA16_SGIS 0x8113 +#define GL_DUAL_LUMINANCE4_SGIS 0x8114 +#define GL_DUAL_LUMINANCE8_SGIS 0x8115 +#define GL_DUAL_LUMINANCE12_SGIS 0x8116 +#define GL_DUAL_LUMINANCE16_SGIS 0x8117 +#define GL_DUAL_INTENSITY4_SGIS 0x8118 +#define GL_DUAL_INTENSITY8_SGIS 0x8119 +#define GL_DUAL_INTENSITY12_SGIS 0x811A +#define GL_DUAL_INTENSITY16_SGIS 0x811B +#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C +#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D +#define GL_QUAD_ALPHA4_SGIS 0x811E +#define GL_QUAD_ALPHA8_SGIS 0x811F +#define GL_QUAD_LUMINANCE4_SGIS 0x8120 +#define GL_QUAD_LUMINANCE8_SGIS 0x8121 +#define GL_QUAD_INTENSITY4_SGIS 0x8122 +#define GL_QUAD_INTENSITY8_SGIS 0x8123 +#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 +#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 +#endif /* GL_SGIS_texture_select */ + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 +#define GL_ASYNC_MARKER_SGIX 0x8329 +typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp); +typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp); +typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint marker); +GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *markerp); +GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *markerp); +GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei range); +GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range); +GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint marker); +#endif +#endif /* GL_SGIX_async */ + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D +#endif /* GL_SGIX_async_histogram */ + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 +#endif /* GL_SGIX_async_pixel */ + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 +#endif /* GL_SGIX_blend_alpha_minmax */ + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_SGIX_calligraphic_fragment 1 +#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 +#endif /* GL_SGIX_calligraphic_fragment */ + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 +#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 +#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 +#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 +#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 +#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 +#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 +#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 +#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 +#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 +#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D +#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E +#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F +#endif /* GL_SGIX_clipmap */ + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 +#define GL_CONVOLUTION_HINT_SGIX 0x8316 +#endif /* GL_SGIX_convolution_accuracy */ + +#ifndef GL_SGIX_depth_pass_instrument +#define GL_SGIX_depth_pass_instrument 1 +#endif /* GL_SGIX_depth_pass_instrument */ + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 +#endif /* GL_SGIX_depth_texture */ + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 +typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFlushRasterSGIX (void); +#endif +#endif /* GL_SGIX_flush_raster */ + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 +#endif /* GL_SGIX_fog_offset */ + +#ifndef GL_SGIX_fragment_lighting +#define GL_SGIX_fragment_lighting 1 +#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 +#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 +#define GL_LIGHT_ENV_MODE_SGIX 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B +#define GL_FRAGMENT_LIGHT0_SGIX 0x840C +#define GL_FRAGMENT_LIGHT1_SGIX 0x840D +#define GL_FRAGMENT_LIGHT2_SGIX 0x840E +#define GL_FRAGMENT_LIGHT3_SGIX 0x840F +#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 +#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 +#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 +#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 +typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum face, GLenum mode); +GLAPI void APIENTRY glFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param); +GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glFragmentLightiSGIX (GLenum light, GLenum pname, GLint param); +GLAPI void APIENTRY glFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params); +GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum pname, GLfloat param); +GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum pname, GLint param); +GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum pname, const GLint *params); +GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param); +GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param); +GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params); +GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params); +GLAPI void APIENTRY glLightEnviSGIX (GLenum pname, GLint param); +#endif +#endif /* GL_SGIX_fragment_lighting */ + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 +#define GL_FRAMEZOOM_SGIX 0x818B +#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C +#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D +typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFrameZoomSGIX (GLint factor); +#endif +#endif /* GL_SGIX_framezoom */ + +#ifndef GL_SGIX_igloo_interface +#define GL_SGIX_igloo_interface 1 +typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const void *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum pname, const void *params); +#endif +#endif /* GL_SGIX_igloo_interface */ + +#ifndef GL_SGIX_instruments +#define GL_SGIX_instruments 1 +#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 +#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 +typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); +typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); +typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); +typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLint APIENTRY glGetInstrumentsSGIX (void); +GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei size, GLint *buffer); +GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *marker_p); +GLAPI void APIENTRY glReadInstrumentsSGIX (GLint marker); +GLAPI void APIENTRY glStartInstrumentsSGIX (void); +GLAPI void APIENTRY glStopInstrumentsSGIX (GLint marker); +#endif +#endif /* GL_SGIX_instruments */ + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 +#define GL_INTERLACE_SGIX 0x8094 +#endif /* GL_SGIX_interlace */ + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 +#define GL_IR_INSTRUMENT1_SGIX 0x817F +#endif /* GL_SGIX_ir_instrument1 */ + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 +#define GL_LIST_PRIORITY_SGIX 0x8182 +typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params); +GLAPI void APIENTRY glListParameterfSGIX (GLuint list, GLenum pname, GLfloat param); +GLAPI void APIENTRY glListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glListParameteriSGIX (GLuint list, GLenum pname, GLint param); +GLAPI void APIENTRY glListParameterivSGIX (GLuint list, GLenum pname, const GLint *params); +#endif +#endif /* GL_SGIX_list_priority */ + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 +#define GL_PIXEL_TEX_GEN_SGIX 0x8139 +#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B +typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelTexGenSGIX (GLenum mode); +#endif +#endif /* GL_SGIX_pixel_texture */ + +#ifndef GL_SGIX_pixel_tiles +#define GL_SGIX_pixel_tiles 1 +#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E +#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F +#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 +#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 +#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 +#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 +#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 +#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 +#endif /* GL_SGIX_pixel_tiles */ + +#ifndef GL_SGIX_polynomial_ffd +#define GL_SGIX_polynomial_ffd 1 +#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 +#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 +#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 +#define GL_TEXTURE_DEFORMATION_SGIX 0x8195 +#define GL_DEFORMATIONS_MASK_SGIX 0x8196 +#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 +typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); +typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); +typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); +GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); +GLAPI void APIENTRY glDeformSGIX (GLbitfield mask); +GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield mask); +#endif +#endif /* GL_SGIX_polynomial_ffd */ + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 +#define GL_REFERENCE_PLANE_SGIX 0x817D +#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E +typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation); +#endif +#endif /* GL_SGIX_reference_plane */ + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 +#define GL_PACK_RESAMPLE_SGIX 0x842C +#define GL_UNPACK_RESAMPLE_SGIX 0x842D +#define GL_RESAMPLE_REPLICATE_SGIX 0x842E +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#endif /* GL_SGIX_resample */ + +#ifndef GL_SGIX_scalebias_hint +#define GL_SGIX_scalebias_hint 1 +#define GL_SCALEBIAS_HINT_SGIX 0x8322 +#endif /* GL_SGIX_scalebias_hint */ + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D +#endif /* GL_SGIX_shadow */ + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 +#define GL_SHADOW_AMBIENT_SGIX 0x80BF +#endif /* GL_SGIX_shadow_ambient */ + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 +#define GL_SPRITE_SGIX 0x8148 +#define GL_SPRITE_MODE_SGIX 0x8149 +#define GL_SPRITE_AXIS_SGIX 0x814A +#define GL_SPRITE_TRANSLATION_SGIX 0x814B +#define GL_SPRITE_AXIAL_SGIX 0x814C +#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D +#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E +typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum pname, GLfloat param); +GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum pname, GLint param); +GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum pname, const GLint *params); +#endif +#endif /* GL_SGIX_sprite */ + +#ifndef GL_SGIX_subsample +#define GL_SGIX_subsample 1 +#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 +#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 +#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 +#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 +#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 +#endif /* GL_SGIX_subsample */ + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 +typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTagSampleBufferSGIX (void); +#endif +#endif /* GL_SGIX_tag_sample_buffer */ + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 +#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE +#endif /* GL_SGIX_texture_add_env */ + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B +#endif /* GL_SGIX_texture_coordinate_clamp */ + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 +#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E +#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F +#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 +#endif /* GL_SGIX_texture_lod_bias */ + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E +#endif /* GL_SGIX_texture_multi_buffer */ + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C +#endif /* GL_SGIX_texture_scale_bias */ + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF +#endif /* GL_SGIX_vertex_preclip */ + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 +#define GL_YCRCB_422_SGIX 0x81BB +#define GL_YCRCB_444_SGIX 0x81BC +#endif /* GL_SGIX_ycrcb */ + +#ifndef GL_SGIX_ycrcb_subsample +#define GL_SGIX_ycrcb_subsample 1 +#endif /* GL_SGIX_ycrcb_subsample */ + +#ifndef GL_SGIX_ycrcba +#define GL_SGIX_ycrcba 1 +#define GL_YCRCB_SGIX 0x8318 +#define GL_YCRCBA_SGIX 0x8319 +#endif /* GL_SGIX_ycrcba */ + +#ifndef GL_SGI_color_matrix +#define GL_SGI_color_matrix 1 +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB +#endif /* GL_SGI_color_matrix */ + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF +typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void *table); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); +GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void APIENTRY glColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params); +GLAPI void APIENTRY glCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glGetColorTableSGI (GLenum target, GLenum format, GLenum type, void *table); +GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params); +GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params); +#endif +#endif /* GL_SGI_color_table */ + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD +#endif /* GL_SGI_texture_color_table */ + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 +typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFinishTextureSUNX (void); +#endif +#endif /* GL_SUNX_constant_data */ + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 +#define GL_WRAP_BORDER_SUN 0x81D4 +#endif /* GL_SUN_convolution_border_modes */ + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte factor); +GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort factor); +GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint factor); +GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat factor); +GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble factor); +GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte factor); +GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort factor); +GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint factor); +#endif +#endif /* GL_SUN_global_alpha */ + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 +typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width); +#endif +#endif /* GL_SUN_mesh_array */ + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 +#define GL_SLICE_ACCUM_SUN 0x85CC +#endif /* GL_SUN_slice_accum */ + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 +#define GL_RESTART_SUN 0x0001 +#define GL_REPLACE_MIDDLE_SUN 0x0002 +#define GL_REPLACE_OLDEST_SUN 0x0003 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void **pointer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint code); +GLAPI void APIENTRY glReplacementCodeusSUN (GLushort code); +GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte code); +GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *code); +GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *code); +GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *code); +GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum type, GLsizei stride, const void **pointer); +#endif +#endif /* GL_SUN_triangle_list */ + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v); +GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v); +GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v); +GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v); +GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v); +GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v); +GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v); +GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +#endif +#endif /* GL_SUN_vertex */ + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB +#endif /* GL_WIN_phong_shading */ + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC +#endif /* GL_WIN_specular_fog */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/SDL2/SDL_opengles.h b/external/SDL2/SDL_opengles.h index f33e190..8511b96 100644 --- a/external/SDL2/SDL_opengles.h +++ b/external/SDL2/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,9 +21,10 @@ /** * \file SDL_opengles.h - * + * * This is a simple file to encapsulate the OpenGL ES 1.X API headers. */ +#include "SDL_config.h" #ifdef __IPHONEOS__ #include diff --git a/external/SDL2/SDL_opengles2.h b/external/SDL2/SDL_opengles2.h index 3d172c3..172fcb3 100644 --- a/external/SDL2/SDL_opengles2.h +++ b/external/SDL2/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -20,19 +20,33 @@ */ /** - * \file SDL_opengles.h - * + * \file SDL_opengles2.h + * * This is a simple file to encapsulate the OpenGL ES 2.0 API headers. */ +#include "SDL_config.h" + +#if !defined(_MSC_VER) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) #ifdef __IPHONEOS__ #include #include #else +#include #include #include #endif +#else /* _MSC_VER */ + +/* OpenGL ES2 headers for Visual Studio */ +#include "SDL_opengles2_khrplatform.h" +#include "SDL_opengles2_gl2platform.h" +#include "SDL_opengles2_gl2.h" +#include "SDL_opengles2_gl2ext.h" + +#endif /* _MSC_VER */ + #ifndef APIENTRY -#define APIENTRY +#define APIENTRY GL_APIENTRY #endif diff --git a/external/SDL2/SDL_opengles2_gl2.h b/external/SDL2/SDL_opengles2_gl2.h new file mode 100644 index 0000000..c62fb0a --- /dev/null +++ b/external/SDL2/SDL_opengles2_gl2.h @@ -0,0 +1,621 @@ +#ifndef __gl2_h_ +#define __gl2_h_ + +/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */ + +/*#include */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +typedef void GLvoid; +typedef char GLchar; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef khronos_int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; + +/* GL types for handling large vertex buffer objects */ +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_2_0 1 + +/* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + +/* AlphaFunction (not supported in ES20) */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* BlendEquationSeparate */ +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ +#define GL_BLEND_EQUATION_ALPHA 0x883D + +/* BlendSubtract */ +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* Separate Blend Functions */ +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 + +/* Buffer Objects */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 + +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 + +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 + +/* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetPName */ +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +/* GL_SCISSOR_TEST */ +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +/* GL_POLYGON_OFFSET_FILL */ +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + +/* PixelFormat */ +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* Shaders */ +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D + +/* StencilFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ +#define GL_TEXTURE 0x1702 + +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 + +/* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 + +/* Uniform Types */ +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 + +/* Vertex Arrays */ +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F + +/* Read Format */ +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + +/* Shader Source */ +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA + +/* Shader Binary */ +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 + +/* Shader Precision-Specified Types */ +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 + +/* Framebuffer Object. */ +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 + +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 + +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 + +#define GL_NONE 0 + +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD + +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +/*------------------------------------------------------------------------- + * GL core functions. + *-----------------------------------------------------------------------*/ + +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode ); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); +GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); +GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); +GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#ifdef __cplusplus +} +#endif + +#endif /* __gl2_h_ */ + diff --git a/external/SDL2/SDL_opengles2_gl2ext.h b/external/SDL2/SDL_opengles2_gl2ext.h new file mode 100644 index 0000000..e8ca8b1 --- /dev/null +++ b/external/SDL2/SDL_opengles2_gl2ext.h @@ -0,0 +1,2050 @@ +#ifndef __gl2ext_h_ +#define __gl2ext_h_ + +/* $Revision: 22801 $ on $Date:: 2013-08-21 03:20:48 -0700 #$ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +#ifndef GL_APIENTRYP +# define GL_APIENTRYP GL_APIENTRY* +#endif + +/* New types shared by several extensions */ + +#ifndef __gl3_h_ +/* These are defined with respect to in the + * Apple extension spec, but they are also used by non-APPLE + * extensions, and in the Khronos header we use the Khronos + * portable types in khrplatform.h, which must be defined. + */ +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync *GLsync; +#endif + + +/*------------------------------------------------------------------------* + * OES extension tokens + *------------------------------------------------------------------------*/ + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_ETC1_RGB8_OES 0x8D64 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#endif + +/* GL_OES_depth_texture */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +typedef void* GLeglImageOES; +#endif + +/* GL_OES_EGL_image_external */ +#ifndef GL_OES_EGL_image_external +/* GLeglImageOES defined in GL_OES_EGL_image already. */ +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#define GL_SAMPLER_EXTERNAL_OES 0x8D66 +#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 +#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 +#endif + +/* GL_OES_element_index_uint */ +#ifndef GL_OES_element_index_uint +#define GL_UNSIGNED_INT 0x1405 +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_OES_get_program_binary +#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE +#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif + +/* GL_OES_required_internalformat */ +#ifndef GL_OES_required_internalformat +#define GL_ALPHA8_OES 0x803C +#define GL_DEPTH_COMPONENT16_OES 0x81A5 +/* reuse GL_DEPTH_COMPONENT24_OES */ +/* reuse GL_DEPTH24_STENCIL8_OES */ +/* reuse GL_DEPTH_COMPONENT32_OES */ +#define GL_LUMINANCE4_ALPHA4_OES 0x8043 +#define GL_LUMINANCE8_ALPHA8_OES 0x8045 +#define GL_LUMINANCE8_OES 0x8040 +#define GL_RGBA4_OES 0x8056 +#define GL_RGB5_A1_OES 0x8057 +#define GL_RGB565_OES 0x8D62 +/* reuse GL_RGB8_OES */ +/* reuse GL_RGBA8_OES */ +/* reuse GL_RGB10_EXT */ +/* reuse GL_RGB10_A2_EXT */ +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 +#endif + +/* GL_OES_standard_derivatives */ +#ifndef GL_OES_standard_derivatives +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_STENCIL_INDEX1_OES 0x8D46 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_STENCIL_INDEX4_OES 0x8D47 +#endif + +#ifndef GL_OES_surfaceless_context +#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 +#endif + +/* GL_OES_texture_3D */ +#ifndef GL_OES_texture_3D +#define GL_TEXTURE_WRAP_R_OES 0x8072 +#define GL_TEXTURE_3D_OES 0x806F +#define GL_TEXTURE_BINDING_3D_OES 0x806A +#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 +#define GL_SAMPLER_3D_OES 0x8B5F +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 +#endif + +/* GL_OES_texture_float */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_texture_float_linear */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_texture_half_float */ +#ifndef GL_OES_texture_half_float +#define GL_HALF_FLOAT_OES 0x8D61 +#endif + +/* GL_OES_texture_half_float_linear */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_texture_npot */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_vertex_array_object */ +#ifndef GL_OES_vertex_array_object +#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 +#endif + +/* GL_OES_vertex_half_float */ +/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */ + +/* GL_OES_vertex_type_10_10_10_2 */ +#ifndef GL_OES_vertex_type_10_10_10_2 +#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 +#define GL_INT_10_10_10_2_OES 0x8DF7 +#endif + +/*------------------------------------------------------------------------* + * KHR extension tokens + *------------------------------------------------------------------------*/ + +#ifndef GL_KHR_debug +typedef void (GL_APIENTRYP GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245 +#define GL_DEBUG_SOURCE_API_KHR 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A +#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B +#define GL_DEBUG_TYPE_ERROR_KHR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250 +#define GL_DEBUG_TYPE_OTHER_KHR 0x8251 +#define GL_DEBUG_TYPE_MARKER_KHR 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D +#define GL_BUFFER_KHR 0x82E0 +#define GL_SHADER_KHR 0x82E1 +#define GL_PROGRAM_KHR 0x82E2 +#define GL_QUERY_KHR 0x82E3 +/* PROGRAM_PIPELINE only in GL */ +#define GL_SAMPLER_KHR 0x82E6 +/* DISPLAY_LIST only in GL */ +#define GL_MAX_LABEL_LENGTH_KHR 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147 +#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148 +#define GL_DEBUG_OUTPUT_KHR 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002 +#define GL_STACK_OVERFLOW_KHR 0x0503 +#define GL_STACK_UNDERFLOW_KHR 0x0504 +#endif + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif + +/*------------------------------------------------------------------------* + * AMD extension tokens + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_3DC_X_AMD 0x87F9 +#define GL_3DC_XY_AMD 0x87FA +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_ATC_RGB_AMD 0x8C92 +#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE +#endif + +/* GL_AMD_performance_monitor */ +#ifndef GL_AMD_performance_monitor +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 +#endif + +/* GL_AMD_program_binary_Z400 */ +#ifndef GL_AMD_program_binary_Z400 +#define GL_Z400_BINARY_AMD 0x8740 +#endif + +/*------------------------------------------------------------------------* + * ANGLE extension tokens + *------------------------------------------------------------------------*/ + +/* GL_ANGLE_depth_texture */ +#ifndef GL_ANGLE_depth_texture +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif + +/* GL_ANGLE_framebuffer_blit */ +#ifndef GL_ANGLE_framebuffer_blit +#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA +#endif + +/* GL_ANGLE_framebuffer_multisample */ +#ifndef GL_ANGLE_framebuffer_multisample +#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 +#define GL_MAX_SAMPLES_ANGLE 0x8D57 +#endif + +/* GL_ANGLE_instanced_arrays */ +#ifndef GL_ANGLE_instanced_arrays +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE +#endif + +/* GL_ANGLE_pack_reverse_row_order */ +#ifndef GL_ANGLE_pack_reverse_row_order +#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 +#endif + +/* GL_ANGLE_program_binary */ +#ifndef GL_ANGLE_program_binary +#define GL_PROGRAM_BINARY_ANGLE 0x93A6 +#endif + +/* GL_ANGLE_texture_compression_dxt3 */ +#ifndef GL_ANGLE_texture_compression_dxt3 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 +#endif + +/* GL_ANGLE_texture_compression_dxt5 */ +#ifndef GL_ANGLE_texture_compression_dxt5 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 +#endif + +/* GL_ANGLE_texture_usage */ +#ifndef GL_ANGLE_texture_usage +#define GL_TEXTURE_USAGE_ANGLE 0x93A2 +#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 +#endif + +/* GL_ANGLE_translated_shader_source */ +#ifndef GL_ANGLE_translated_shader_source +#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 +#endif + +/*------------------------------------------------------------------------* + * APPLE extension tokens + *------------------------------------------------------------------------*/ + +/* GL_APPLE_copy_texture_levels */ +/* No new tokens introduced by this extension. */ + +/* GL_APPLE_framebuffer_multisample */ +#ifndef GL_APPLE_framebuffer_multisample +#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 +#define GL_MAX_SAMPLES_APPLE 0x8D57 +#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA +#endif + +/* GL_APPLE_rgb_422 */ +#ifndef GL_APPLE_rgb_422 +#define GL_RGB_422_APPLE 0x8A1F +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif + +/* GL_APPLE_sync */ +#ifndef GL_APPLE_sync + +#define GL_SYNC_OBJECT_APPLE 0x8A53 +#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111 +#define GL_OBJECT_TYPE_APPLE 0x9112 +#define GL_SYNC_CONDITION_APPLE 0x9113 +#define GL_SYNC_STATUS_APPLE 0x9114 +#define GL_SYNC_FLAGS_APPLE 0x9115 +#define GL_SYNC_FENCE_APPLE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117 +#define GL_UNSIGNALED_APPLE 0x9118 +#define GL_SIGNALED_APPLE 0x9119 +#define GL_ALREADY_SIGNALED_APPLE 0x911A +#define GL_TIMEOUT_EXPIRED_APPLE 0x911B +#define GL_CONDITION_SATISFIED_APPLE 0x911C +#define GL_WAIT_FAILED_APPLE 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001 +#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull +#endif + +/* GL_APPLE_texture_format_BGRA8888 */ +#ifndef GL_APPLE_texture_format_BGRA8888 +#define GL_BGRA_EXT 0x80E1 +#endif + +/* GL_APPLE_texture_max_level */ +#ifndef GL_APPLE_texture_max_level +#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D +#endif + +/*------------------------------------------------------------------------* + * ARM extension tokens + *------------------------------------------------------------------------*/ + +/* GL_ARM_mali_program_binary */ +#ifndef GL_ARM_mali_program_binary +#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61 +#endif + +/* GL_ARM_mali_shader_binary */ +#ifndef GL_ARM_mali_shader_binary +#define GL_MALI_SHADER_BINARY_ARM 0x8F60 +#endif + +/* GL_ARM_rgba8 */ +/* No new tokens introduced by this extension. */ + +/*------------------------------------------------------------------------* + * EXT extension tokens + *------------------------------------------------------------------------*/ + +/* GL_EXT_blend_minmax */ +#ifndef GL_EXT_blend_minmax +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#endif + +/* GL_EXT_color_buffer_half_float */ +#ifndef GL_EXT_color_buffer_half_float +#define GL_RGBA16F_EXT 0x881A +#define GL_RGB16F_EXT 0x881B +#define GL_RG16F_EXT 0x822F +#define GL_R16F_EXT 0x822D +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211 +#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17 +#endif + +/* GL_EXT_debug_label */ +#ifndef GL_EXT_debug_label +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +#endif + +/* GL_EXT_debug_marker */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_discard_framebuffer */ +#ifndef GL_EXT_discard_framebuffer +#define GL_COLOR_EXT 0x1800 +#define GL_DEPTH_EXT 0x1801 +#define GL_STENCIL_EXT 0x1802 +#endif + +#ifndef GL_EXT_disjoint_timer_query +#define GL_QUERY_COUNTER_BITS_EXT 0x8864 +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 +#define GL_TIME_ELAPSED_EXT 0x88BF +#define GL_TIMESTAMP_EXT 0x8E28 +#define GL_GPU_DISJOINT_EXT 0x8FBB +#endif + +#ifndef GL_EXT_draw_buffers +#define GL_EXT_draw_buffers 1 +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 +#define GL_DRAW_BUFFER0_EXT 0x8825 +#define GL_DRAW_BUFFER1_EXT 0x8826 +#define GL_DRAW_BUFFER2_EXT 0x8827 +#define GL_DRAW_BUFFER3_EXT 0x8828 +#define GL_DRAW_BUFFER4_EXT 0x8829 +#define GL_DRAW_BUFFER5_EXT 0x882A +#define GL_DRAW_BUFFER6_EXT 0x882B +#define GL_DRAW_BUFFER7_EXT 0x882C +#define GL_DRAW_BUFFER8_EXT 0x882D +#define GL_DRAW_BUFFER9_EXT 0x882E +#define GL_DRAW_BUFFER10_EXT 0x882F +#define GL_DRAW_BUFFER11_EXT 0x8830 +#define GL_DRAW_BUFFER12_EXT 0x8831 +#define GL_DRAW_BUFFER13_EXT 0x8832 +#define GL_DRAW_BUFFER14_EXT 0x8833 +#define GL_DRAW_BUFFER15_EXT 0x8834 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#endif + +/* GL_EXT_map_buffer_range */ +#ifndef GL_EXT_map_buffer_range +#define GL_MAP_READ_BIT_EXT 0x0001 +#define GL_MAP_WRITE_BIT_EXT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 +#endif + +/* GL_EXT_multisampled_render_to_texture */ +#ifndef GL_EXT_multisampled_render_to_texture +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C +/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 +#endif + +/* GL_EXT_multiview_draw_buffers */ +#ifndef GL_EXT_multiview_draw_buffers +#define GL_COLOR_ATTACHMENT_EXT 0x90F0 +#define GL_MULTIVIEW_EXT 0x90F1 +#define GL_DRAW_BUFFER_EXT 0x0C01 +#define GL_READ_BUFFER_EXT 0x0C02 +#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2 +#endif + +/* GL_EXT_multi_draw_arrays */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_occlusion_query_boolean */ +#ifndef GL_EXT_occlusion_query_boolean +#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 +#endif + +/* GL_EXT_read_format_bgra */ +#ifndef GL_EXT_read_format_bgra +#define GL_BGRA_EXT 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 +#endif + +/* GL_EXT_robustness */ +#ifndef GL_EXT_robustness +/* reuse GL_NO_ERROR */ +#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 +#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 +#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 +#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 +#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 +#endif + +/* GL_EXT_separate_shader_objects */ +#ifndef GL_EXT_separate_shader_objects +#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 +#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE_EXT 0x8258 +#define GL_ACTIVE_PROGRAM_EXT 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A +#endif + +/* GL_EXT_shader_framebuffer_fetch */ +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 +#endif + +/* GL_EXT_shader_texture_lod */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_shadow_samplers */ +#ifndef GL_EXT_shadow_samplers +#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C +#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D +#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E +#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 +#endif + +/* GL_EXT_sRGB */ +#ifndef GL_EXT_sRGB +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 +#endif + +/* GL_EXT_sRGB_write_control */ +#ifndef GL_EXT_sRGB_write_control +#define GL_EXT_sRGB_write_control 1 +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#endif + +/* GL_EXT_texture_compression_dxt1 */ +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#endif + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_BGRA_EXT 0x80E1 +#endif + +/* GL_EXT_texture_rg */ +#ifndef GL_EXT_texture_rg +#define GL_RED_EXT 0x1903 +#define GL_RG_EXT 0x8227 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#endif + +/* GL_EXT_texture_sRGB_decode */ +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A +#endif + +/* GL_EXT_texture_storage */ +#ifndef GL_EXT_texture_storage +#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F +#define GL_ALPHA8_EXT 0x803C +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_RGBA32F_EXT 0x8814 +#define GL_RGB32F_EXT 0x8815 +#define GL_ALPHA32F_EXT 0x8816 +#define GL_LUMINANCE32F_EXT 0x8818 +#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 +/* reuse GL_RGBA16F_EXT */ +/* reuse GL_RGB16F_EXT */ +#define GL_ALPHA16F_EXT 0x881C +#define GL_LUMINANCE16F_EXT 0x881E +#define GL_LUMINANCE_ALPHA16F_EXT 0x881F +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGB10_EXT 0x8052 +#define GL_BGRA8_EXT 0x93A1 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +#define GL_R16F_EXT 0x822D +#define GL_RG16F_EXT 0x822F +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 +#endif + +/* GL_EXT_unpack_subimage */ +#ifndef GL_EXT_unpack_subimage +#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2 +#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4 +#endif + +/*------------------------------------------------------------------------* + * DMP extension tokens + *------------------------------------------------------------------------*/ + +/* GL_DMP_shader_binary */ +#ifndef GL_DMP_shader_binary +#define GL_SHADER_BINARY_DMP 0x9250 +#endif + +/*------------------------------------------------------------------------* + * FJ extension tokens + *------------------------------------------------------------------------*/ + +/* GL_FJ_shader_binary_GCCSO */ +#ifndef GL_FJ_shader_binary_GCCSO +#define GL_GCCSO_SHADER_BINARY_FJ 0x9260 +#endif + +/*------------------------------------------------------------------------* + * IMG extension tokens + *------------------------------------------------------------------------*/ + +/* GL_IMG_program_binary */ +#ifndef GL_IMG_program_binary +#define GL_SGX_PROGRAM_BINARY_IMG 0x9130 +#endif + +/* GL_IMG_read_format */ +#ifndef GL_IMG_read_format +#define GL_BGRA_IMG 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365 +#endif + +/* GL_IMG_shader_binary */ +#ifndef GL_IMG_shader_binary +#define GL_SGX_BINARY_IMG 0x8C0A +#endif + +/* GL_IMG_texture_compression_pvrtc */ +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 +#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 +#endif + +/* GL_IMG_texture_compression_pvrtc2 */ +#ifndef GL_IMG_texture_compression_pvrtc2 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 +#endif + +/* GL_IMG_multisampled_render_to_texture */ +#ifndef GL_IMG_multisampled_render_to_texture +#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134 +#define GL_MAX_SAMPLES_IMG 0x9135 +#define GL_TEXTURE_SAMPLES_IMG 0x9136 +#endif + +/*------------------------------------------------------------------------* + * NV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_NV_coverage_sample */ +#ifndef GL_NV_coverage_sample +#define GL_COVERAGE_COMPONENT_NV 0x8ED0 +#define GL_COVERAGE_COMPONENT4_NV 0x8ED1 +#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2 +#define GL_COVERAGE_BUFFERS_NV 0x8ED3 +#define GL_COVERAGE_SAMPLES_NV 0x8ED4 +#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 +#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 +#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7 +#define GL_COVERAGE_BUFFER_BIT_NV 0x00008000 +#endif + +/* GL_NV_depth_nonlinear */ +#ifndef GL_NV_depth_nonlinear +#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C +#endif + +/* GL_NV_draw_buffers */ +#ifndef GL_NV_draw_buffers +#define GL_MAX_DRAW_BUFFERS_NV 0x8824 +#define GL_DRAW_BUFFER0_NV 0x8825 +#define GL_DRAW_BUFFER1_NV 0x8826 +#define GL_DRAW_BUFFER2_NV 0x8827 +#define GL_DRAW_BUFFER3_NV 0x8828 +#define GL_DRAW_BUFFER4_NV 0x8829 +#define GL_DRAW_BUFFER5_NV 0x882A +#define GL_DRAW_BUFFER6_NV 0x882B +#define GL_DRAW_BUFFER7_NV 0x882C +#define GL_DRAW_BUFFER8_NV 0x882D +#define GL_DRAW_BUFFER9_NV 0x882E +#define GL_DRAW_BUFFER10_NV 0x882F +#define GL_DRAW_BUFFER11_NV 0x8830 +#define GL_DRAW_BUFFER12_NV 0x8831 +#define GL_DRAW_BUFFER13_NV 0x8832 +#define GL_DRAW_BUFFER14_NV 0x8833 +#define GL_DRAW_BUFFER15_NV 0x8834 +#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 +#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 +#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 +#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 +#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 +#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 +#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 +#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 +#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 +#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 +#define GL_COLOR_ATTACHMENT10_NV 0x8CEA +#define GL_COLOR_ATTACHMENT11_NV 0x8CEB +#define GL_COLOR_ATTACHMENT12_NV 0x8CEC +#define GL_COLOR_ATTACHMENT13_NV 0x8CED +#define GL_COLOR_ATTACHMENT14_NV 0x8CEE +#define GL_COLOR_ATTACHMENT15_NV 0x8CEF +#endif + +/* GL_NV_draw_instanced */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_fbo_color_attachments */ +#ifndef GL_NV_fbo_color_attachments +#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF +/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */ +#endif + +/* GL_NV_fence */ +#ifndef GL_NV_fence +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +#endif + +/* GL_NV_framebuffer_blit */ +#ifndef GL_NV_framebuffer_blit +#define GL_READ_FRAMEBUFFER_NV 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA +#endif + +/* GL_NV_framebuffer_multisample */ +#ifndef GL_NV_framebuffer_multisample +#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56 +#define GL_MAX_SAMPLES_NV 0x8D57 +#endif + +/* GL_NV_generate_mipmap_sRGB */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_instanced_arrays */ +#ifndef GL_NV_instanced_arrays +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE +#endif + +/* GL_NV_read_buffer */ +#ifndef GL_NV_read_buffer +#define GL_READ_BUFFER_NV 0x0C02 +#endif + +/* GL_NV_read_buffer_front */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_read_depth */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_read_depth_stencil */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_read_stencil */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_shadow_samplers_array */ +#ifndef GL_NV_shadow_samplers_array +#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4 +#endif + +/* GL_NV_shadow_samplers_cube */ +#ifndef GL_NV_shadow_samplers_cube +#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5 +#endif + +/* GL_NV_sRGB_formats */ +#ifndef GL_NV_sRGB_formats +#define GL_SLUMINANCE_NV 0x8C46 +#define GL_SLUMINANCE_ALPHA_NV 0x8C44 +#define GL_SRGB8_NV 0x8C41 +#define GL_SLUMINANCE8_NV 0x8C47 +#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45 +#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F +#define GL_ETC1_SRGB8_NV 0x88EE +#endif + +/* GL_NV_texture_border_clamp */ +#ifndef GL_NV_texture_border_clamp +#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 +#define GL_CLAMP_TO_BORDER_NV 0x812D +#endif + +/* GL_NV_texture_compression_s3tc_update */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_texture_npot_2D_mipmap */ +/* No new tokens introduced by this extension. */ + +/*------------------------------------------------------------------------* + * QCOM extension tokens + *------------------------------------------------------------------------*/ + +/* GL_QCOM_alpha_test */ +#ifndef GL_QCOM_alpha_test +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 +#endif + +/* GL_QCOM_binning_control */ +#ifndef GL_QCOM_binning_control +#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 +#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 +#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 +#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 +#endif + +/* GL_QCOM_driver_control */ +/* No new tokens introduced by this extension. */ + +/* GL_QCOM_extended_get */ +#ifndef GL_QCOM_extended_get +#define GL_TEXTURE_WIDTH_QCOM 0x8BD2 +#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3 +#define GL_TEXTURE_DEPTH_QCOM 0x8BD4 +#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5 +#define GL_TEXTURE_FORMAT_QCOM 0x8BD6 +#define GL_TEXTURE_TYPE_QCOM 0x8BD7 +#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8 +#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9 +#define GL_TEXTURE_TARGET_QCOM 0x8BDA +#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB +#define GL_STATE_RESTORE 0x8BDC +#endif + +/* GL_QCOM_extended_get2 */ +/* No new tokens introduced by this extension. */ + +/* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_perfmon_global_mode +#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 +#endif + +/* GL_QCOM_writeonly_rendering */ +#ifndef GL_QCOM_writeonly_rendering +#define GL_WRITEONLY_RENDERING_QCOM 0x8823 +#endif + +/* GL_QCOM_tiled_rendering */ +#ifndef GL_QCOM_tiled_rendering +#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 +#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002 +#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004 +#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008 +#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010 +#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020 +#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040 +#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080 +#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100 +#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200 +#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400 +#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800 +#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000 +#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000 +#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000 +#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000 +#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000 +#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000 +#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000 +#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000 +#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000 +#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000 +#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000 +#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000 +#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000 +#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000 +#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000 +#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000 +#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000 +#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000 +#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000 +#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 +#endif + +/*------------------------------------------------------------------------* + * VIV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_VIV_shader_binary */ +#ifndef GL_VIV_shader_binary +#define GL_SHADER_BINARY_VIV 0x8FC4 +#endif + +/*------------------------------------------------------------------------* + * End of extension tokens, start of corresponding extension functions + *------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------* + * OES extension functions + *------------------------------------------------------------------------*/ + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_OES_compressed_ETC1_RGB8_texture 1 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_OES_depth24 1 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_OES_depth32 1 +#endif + +/* GL_OES_depth_texture */ +#ifndef GL_OES_depth_texture +#define GL_OES_depth_texture 1 +#endif + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +#define GL_OES_EGL_image 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); +GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); +#endif +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); +#endif + +/* GL_OES_EGL_image_external */ +#ifndef GL_OES_EGL_image_external +#define GL_OES_EGL_image_external 1 +/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */ +#endif + +/* GL_OES_element_index_uint */ +#ifndef GL_OES_element_index_uint +#define GL_OES_element_index_uint 1 +#endif + +/* GL_OES_fbo_render_mipmap */ +#ifndef GL_OES_fbo_render_mipmap +#define GL_OES_fbo_render_mipmap 1 +#endif + +/* GL_OES_fragment_precision_high */ +#ifndef GL_OES_fragment_precision_high +#define GL_OES_fragment_precision_high 1 +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_OES_get_program_binary +#define GL_OES_get_program_binary 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); +GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); +#endif +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_OES_mapbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); +GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid **params); +#endif +typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid **params); +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_OES_packed_depth_stencil 1 +#endif + +/* GL_OES_required_internalformat */ +#ifndef GL_OES_required_internalformat +#define GL_OES_required_internalformat 1 +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_OES_rgb8_rgba8 1 +#endif + +/* GL_OES_standard_derivatives */ +#ifndef GL_OES_standard_derivatives +#define GL_OES_standard_derivatives 1 +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_OES_stencil1 1 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_OES_stencil4 1 +#endif + +#ifndef GL_OES_surfaceless_context +#define GL_OES_surfaceless_context 1 +#endif + +/* GL_OES_texture_3D */ +#ifndef GL_OES_texture_3D +#define GL_OES_texture_3D 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#endif +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#endif + +/* GL_OES_texture_float */ +#ifndef GL_OES_texture_float +#define GL_OES_texture_float 1 +#endif + +/* GL_OES_texture_float_linear */ +#ifndef GL_OES_texture_float_linear +#define GL_OES_texture_float_linear 1 +#endif + +/* GL_OES_texture_half_float */ +#ifndef GL_OES_texture_half_float +#define GL_OES_texture_half_float 1 +#endif + +/* GL_OES_texture_half_float_linear */ +#ifndef GL_OES_texture_half_float_linear +#define GL_OES_texture_half_float_linear 1 +#endif + +/* GL_OES_texture_npot */ +#ifndef GL_OES_texture_npot +#define GL_OES_texture_npot 1 +#endif + +/* GL_OES_vertex_array_object */ +#ifndef GL_OES_vertex_array_object +#define GL_OES_vertex_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array); +GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays); +GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays); +GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array); +#endif +typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); +#endif + +/* GL_OES_vertex_half_float */ +#ifndef GL_OES_vertex_half_float +#define GL_OES_vertex_half_float 1 +#endif + +/* GL_OES_vertex_type_10_10_10_2 */ +#ifndef GL_OES_vertex_type_10_10_10_2 +#define GL_OES_vertex_type_10_10_10_2 1 +#endif + +/*------------------------------------------------------------------------* + * KHR extension functions + *------------------------------------------------------------------------*/ + +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam); +GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void); +GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, GLvoid **params); +#endif +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam); +typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void); +typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, GLvoid **params); +#endif + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_KHR_texture_compression_astc_ldr 1 +#endif + + +/*------------------------------------------------------------------------* + * AMD extension functions + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_AMD_compressed_3DC_texture 1 +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_AMD_compressed_ATC_texture 1 +#endif + +/* AMD_performance_monitor */ +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); +GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); +GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor); +GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif + +/* GL_AMD_program_binary_Z400 */ +#ifndef GL_AMD_program_binary_Z400 +#define GL_AMD_program_binary_Z400 1 +#endif + +/*------------------------------------------------------------------------* + * ANGLE extension functions + *------------------------------------------------------------------------*/ + +/* GL_ANGLE_depth_texture */ +#ifndef GL_ANGLE_depth_texture +#define GL_ANGLE_depth_texture 1 +#endif + +/* GL_ANGLE_framebuffer_blit */ +#ifndef GL_ANGLE_framebuffer_blit +#define GL_ANGLE_framebuffer_blit 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + +/* GL_ANGLE_framebuffer_multisample */ +#ifndef GL_ANGLE_framebuffer_multisample +#define GL_ANGLE_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + +#ifndef GL_ANGLE_instanced_arrays +#define GL_ANGLE_instanced_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); +#endif + +/* GL_ANGLE_pack_reverse_row_order */ +#ifndef GL_ANGLE_pack_reverse_row_order +#define GL_ANGLE_pack_reverse_row_order 1 +#endif + +/* GL_ANGLE_program_binary */ +#ifndef GL_ANGLE_program_binary +#define GL_ANGLE_program_binary 1 +#endif + +/* GL_ANGLE_texture_compression_dxt3 */ +#ifndef GL_ANGLE_texture_compression_dxt3 +#define GL_ANGLE_texture_compression_dxt3 1 +#endif + +/* GL_ANGLE_texture_compression_dxt5 */ +#ifndef GL_ANGLE_texture_compression_dxt5 +#define GL_ANGLE_texture_compression_dxt5 1 +#endif + +/* GL_ANGLE_texture_usage */ +#ifndef GL_ANGLE_texture_usage +#define GL_ANGLE_texture_usage 1 +#endif + +#ifndef GL_ANGLE_translated_shader_source +#define GL_ANGLE_translated_shader_source 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); +#endif +typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); +#endif + +/*------------------------------------------------------------------------* + * APPLE extension functions + *------------------------------------------------------------------------*/ + +/* GL_APPLE_copy_texture_levels */ +#ifndef GL_APPLE_copy_texture_levels +#define GL_APPLE_copy_texture_levels 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); +#endif +typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); +#endif + +/* GL_APPLE_framebuffer_multisample */ +#ifndef GL_APPLE_framebuffer_multisample +#define GL_APPLE_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); +#endif + +/* GL_APPLE_rgb_422 */ +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 +#endif + +/* GL_APPLE_sync */ +#ifndef GL_APPLE_sync +#define GL_APPLE_sync 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync); +GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync); +GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params); +GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +#endif +typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync); +typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync); +typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params); +typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +#endif + +/* GL_APPLE_texture_format_BGRA8888 */ +#ifndef GL_APPLE_texture_format_BGRA8888 +#define GL_APPLE_texture_format_BGRA8888 1 +#endif + +/* GL_APPLE_texture_max_level */ +#ifndef GL_APPLE_texture_max_level +#define GL_APPLE_texture_max_level 1 +#endif + +/*------------------------------------------------------------------------* + * ARM extension functions + *------------------------------------------------------------------------*/ + +/* GL_ARM_mali_program_binary */ +#ifndef GL_ARM_mali_program_binary +#define GL_ARM_mali_program_binary 1 +#endif + +/* GL_ARM_mali_shader_binary */ +#ifndef GL_ARM_mali_shader_binary +#define GL_ARM_mali_shader_binary 1 +#endif + +/* GL_ARM_rgba8 */ +#ifndef GL_ARM_rgba8 +#define GL_ARM_rgba8 1 +#endif + +/*------------------------------------------------------------------------* + * EXT extension functions + *------------------------------------------------------------------------*/ + +/* GL_EXT_blend_minmax */ +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#endif + +/* GL_EXT_color_buffer_half_float */ +#ifndef GL_EXT_color_buffer_half_float +#define GL_EXT_color_buffer_half_float 1 +#endif + +/* GL_EXT_debug_label */ +#ifndef GL_EXT_debug_label +#define GL_EXT_debug_label 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif +typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif + +/* GL_EXT_debug_marker */ +#ifndef GL_EXT_debug_marker +#define GL_EXT_debug_marker 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); +GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); +GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void); +#endif +typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); +#endif + +/* GL_EXT_discard_framebuffer */ +#ifndef GL_EXT_discard_framebuffer +#define GL_EXT_discard_framebuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); +#endif +typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +#endif + +#ifndef GL_EXT_disjoint_timer_query +#define GL_EXT_disjoint_timer_query 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids); +GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id); +GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target); +GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target); +GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params); +#endif +typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target); +typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params); +#endif /* GL_EXT_disjoint_timer_query */ + +#ifndef GL_EXT_draw_buffers +#define GL_EXT_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); +#endif /* GL_EXT_draw_buffers */ + +/* GL_EXT_map_buffer_range */ +#ifndef GL_EXT_map_buffer_range +#define GL_EXT_map_buffer_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length); +#endif +typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +#endif + +/* GL_EXT_multisampled_render_to_texture */ +#ifndef GL_EXT_multisampled_render_to_texture +#define GL_EXT_multisampled_render_to_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif + +/* GL_EXT_multiview_draw_buffers */ +#ifndef GL_EXT_multiview_draw_buffers +#define GL_EXT_multiview_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index); +GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices); +GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data); +#endif +typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); +typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); +#endif + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +#endif + +/* GL_EXT_occlusion_query_boolean */ +#ifndef GL_EXT_occlusion_query_boolean +#define GL_EXT_occlusion_query_boolean 1 +/* All entry points also exist in GL_EXT_disjoint_timer_query */ +#endif + +/* GL_EXT_read_format_bgra */ +#ifndef GL_EXT_read_format_bgra +#define GL_EXT_read_format_bgra 1 +#endif + +/* GL_EXT_robustness */ +#ifndef GL_EXT_robustness +#define GL_EXT_robustness 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void); +GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data); +GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params); +#endif +typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void); +typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +#endif + +/* GL_EXT_separate_shader_objects */ +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program); +GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); +GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); +GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); +GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); +GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x); +GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y); +GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z); +GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x); +GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +#endif +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); +typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); +typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +#endif + +/* GL_EXT_shader_framebuffer_fetch */ +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_EXT_shader_framebuffer_fetch 1 +#endif + +/* GL_EXT_shader_texture_lod */ +#ifndef GL_EXT_shader_texture_lod +#define GL_EXT_shader_texture_lod 1 +#endif + +/* GL_EXT_shadow_samplers */ +#ifndef GL_EXT_shadow_samplers +#define GL_EXT_shadow_samplers 1 +#endif + +/* GL_EXT_sRGB */ +#ifndef GL_EXT_sRGB +#define GL_EXT_sRGB 1 +#endif + +/* GL_EXT_texture_compression_dxt1 */ +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 +#endif + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_EXT_texture_format_BGRA8888 1 +#endif + +/* GL_EXT_texture_rg */ +#ifndef GL_EXT_texture_rg +#define GL_EXT_texture_rg 1 +#endif + +/* GL_EXT_texture_storage */ +#ifndef GL_EXT_texture_storage +#define GL_EXT_texture_storage 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#endif +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_EXT_texture_type_2_10_10_10_REV 1 +#endif + +/* GL_EXT_unpack_subimage */ +#ifndef GL_EXT_unpack_subimage +#define GL_EXT_unpack_subimage 1 +#endif + +/*------------------------------------------------------------------------* + * DMP extension functions + *------------------------------------------------------------------------*/ + +/* GL_DMP_shader_binary */ +#ifndef GL_DMP_shader_binary +#define GL_DMP_shader_binary 1 +#endif + +/*------------------------------------------------------------------------* + * FJ extension functions + *------------------------------------------------------------------------*/ + +/* GL_FJ_shader_binary_GCCSO */ +#ifndef GL_FJ_shader_binary_GCCSO +#define GL_FJ_shader_binary_GCCSO 1 +#endif + +/*------------------------------------------------------------------------* + * IMG extension functions + *------------------------------------------------------------------------*/ + +/* GL_IMG_program_binary */ +#ifndef GL_IMG_program_binary +#define GL_IMG_program_binary 1 +#endif + +/* GL_IMG_read_format */ +#ifndef GL_IMG_read_format +#define GL_IMG_read_format 1 +#endif + +/* GL_IMG_shader_binary */ +#ifndef GL_IMG_shader_binary +#define GL_IMG_shader_binary 1 +#endif + +/* GL_IMG_texture_compression_pvrtc */ +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_IMG_texture_compression_pvrtc 1 +#endif + +/* GL_IMG_texture_compression_pvrtc2 */ +#ifndef GL_IMG_texture_compression_pvrtc2 +#define GL_IMG_texture_compression_pvrtc2 1 +#endif + +/* GL_IMG_multisampled_render_to_texture */ +#ifndef GL_IMG_multisampled_render_to_texture +#define GL_IMG_multisampled_render_to_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif + +/*------------------------------------------------------------------------* + * NV extension functions + *------------------------------------------------------------------------*/ + +/* GL_NV_coverage_sample */ +#ifndef GL_NV_coverage_sample +#define GL_NV_coverage_sample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask); +GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation); +#endif +typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask); +typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation); +#endif + +/* GL_NV_depth_nonlinear */ +#ifndef GL_NV_depth_nonlinear +#define GL_NV_depth_nonlinear 1 +#endif + +/* GL_NV_draw_buffers */ +#ifndef GL_NV_draw_buffers +#define GL_NV_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); +#endif + +/* GL_NV_draw_instanced */ +#ifndef GL_NV_draw_instanced +#define GL_NV_draw_instanced 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +#endif + +/* GL_NV_fbo_color_attachments */ +#ifndef GL_NV_fbo_color_attachments +#define GL_NV_fbo_color_attachments 1 +#endif + +/* GL_NV_fence */ +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences); +GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences); +GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence); +GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence); +GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence); +GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition); +#endif +typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#endif + +/* GL_NV_framebuffer_blit */ +#ifndef GL_NV_framebuffer_blit +#define GL_NV_framebuffer_blit 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + +/* GL_NV_framebuffer_multisample */ +#ifndef GL_NV_framebuffer_multisample +#define GL_NV_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + +/* GL_NV_generate_mipmap_sRGB */ +#ifndef GL_NV_generate_mipmap_sRGB +#define GL_NV_generate_mipmap_sRGB 1 +#endif + +/* GL_NV_instanced_arrays */ +#ifndef GL_NV_instanced_arrays +#define GL_NV_instanced_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor); +#endif +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor); +#endif + +/* GL_NV_read_buffer */ +#ifndef GL_NV_read_buffer +#define GL_NV_read_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode); +#endif +typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); +#endif + +/* GL_NV_read_buffer_front */ +#ifndef GL_NV_read_buffer_front +#define GL_NV_read_buffer_front 1 +#endif + +/* GL_NV_read_depth */ +#ifndef GL_NV_read_depth +#define GL_NV_read_depth 1 +#endif + +/* GL_NV_read_depth_stencil */ +#ifndef GL_NV_read_depth_stencil +#define GL_NV_read_depth_stencil 1 +#endif + +/* GL_NV_read_stencil */ +#ifndef GL_NV_read_stencil +#define GL_NV_read_stencil 1 +#endif + +/* GL_NV_shadow_samplers_array */ +#ifndef GL_NV_shadow_samplers_array +#define GL_NV_shadow_samplers_array 1 +#endif + +/* GL_NV_shadow_samplers_cube */ +#ifndef GL_NV_shadow_samplers_cube +#define GL_NV_shadow_samplers_cube 1 +#endif + +/* GL_NV_sRGB_formats */ +#ifndef GL_NV_sRGB_formats +#define GL_NV_sRGB_formats 1 +#endif + +/* GL_NV_texture_border_clamp */ +#ifndef GL_NV_texture_border_clamp +#define GL_NV_texture_border_clamp 1 +#endif + +/* GL_NV_texture_compression_s3tc_update */ +#ifndef GL_NV_texture_compression_s3tc_update +#define GL_NV_texture_compression_s3tc_update 1 +#endif + +/* GL_NV_texture_npot_2D_mipmap */ +#ifndef GL_NV_texture_npot_2D_mipmap +#define GL_NV_texture_npot_2D_mipmap 1 +#endif + +/*------------------------------------------------------------------------* + * QCOM extension functions + *------------------------------------------------------------------------*/ + +/* GL_QCOM_alpha_test */ +#ifndef GL_QCOM_alpha_test +#define GL_QCOM_alpha_test 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); +#endif +typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); +#endif + +/* GL_QCOM_binning_control */ +#ifndef GL_QCOM_binning_control +#define GL_QCOM_binning_control 1 +#endif + +/* GL_QCOM_driver_control */ +#ifndef GL_QCOM_driver_control +#define GL_QCOM_driver_control 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls); +GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); +GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl); +GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl); +#endif +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); +typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +#endif + +/* GL_QCOM_extended_get */ +#ifndef GL_QCOM_extended_get +#define GL_QCOM_extended_get 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures); +GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); +GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); +GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); +GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); +GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params); +#endif +typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures); +typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); +typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params); +#endif + +/* GL_QCOM_extended_get2 */ +#ifndef GL_QCOM_extended_get2 +#define GL_QCOM_extended_get2 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders); +GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms); +GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program); +GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length); +#endif +typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders); +typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms); +typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length); +#endif + +/* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_perfmon_global_mode +#define GL_QCOM_perfmon_global_mode 1 +#endif + +/* GL_QCOM_writeonly_rendering */ +#ifndef GL_QCOM_writeonly_rendering +#define GL_QCOM_writeonly_rendering 1 +#endif + +/* GL_QCOM_tiled_rendering */ +#ifndef GL_QCOM_tiled_rendering +#define GL_QCOM_tiled_rendering 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); +GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); +#endif +typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); +typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); +#endif + +/*------------------------------------------------------------------------* + * VIV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_VIV_shader_binary */ +#ifndef GL_VIV_shader_binary +#define GL_VIV_shader_binary 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __gl2ext_h_ */ diff --git a/external/SDL2/SDL_opengles2_gl2platform.h b/external/SDL2/SDL_opengles2_gl2platform.h new file mode 100644 index 0000000..c325686 --- /dev/null +++ b/external/SDL2/SDL_opengles2_gl2platform.h @@ -0,0 +1,30 @@ +#ifndef __gl2platform_h_ +#define __gl2platform_h_ + +/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */ + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "OpenGL-ES" component "Registry". + */ + +/*#include */ + +#ifndef GL_APICALL +#define GL_APICALL KHRONOS_APICALL +#endif + +#ifndef GL_APIENTRY +#define GL_APIENTRY KHRONOS_APIENTRY +#endif + +#endif /* __gl2platform_h_ */ diff --git a/external/SDL2/SDL_opengles2_khrplatform.h b/external/SDL2/SDL_opengles2_khrplatform.h new file mode 100644 index 0000000..c9e6f17 --- /dev/null +++ b/external/SDL2/SDL_opengles2_khrplatform.h @@ -0,0 +1,282 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by sending them to the public Khronos Bugzilla + * (http://khronos.org/bugzilla) by filing a bug against product + * "Khronos (general)" component "Registry". + * + * A predefined template which fills in some of the bug fields can be + * reached using http://tinyurl.com/khrplatform-h-bugreport, but you + * must create a Bugzilla login first. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/external/SDL2/SDL_pixels.h b/external/SDL2/SDL_pixels.h index e732152..5d2c0c8 100644 --- a/external/SDL2/SDL_pixels.h +++ b/external/SDL2/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,33 +21,34 @@ /** * \file SDL_pixels.h - * + * * Header for the enumerated pixel format definitions. */ -#ifndef _SDL_pixels_h -#define _SDL_pixels_h +#ifndef SDL_pixels_h_ +#define SDL_pixels_h_ + +#include "SDL_stdinc.h" +#include "SDL_endian.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \name Transparency definitions - * + * * These define alpha as the opacity of a surface. */ -/*@{*/ +/* @{ */ #define SDL_ALPHA_OPAQUE 255 #define SDL_ALPHA_TRANSPARENT 0 -/*@}*/ +/* @} */ /** Pixel type. */ -enum +typedef enum { SDL_PIXELTYPE_UNKNOWN, SDL_PIXELTYPE_INDEX1, @@ -61,18 +62,18 @@ enum SDL_PIXELTYPE_ARRAYU32, SDL_PIXELTYPE_ARRAYF16, SDL_PIXELTYPE_ARRAYF32 -}; +} SDL_PixelType; /** Bitmap pixel order, high bit -> low bit. */ -enum +typedef enum { SDL_BITMAPORDER_NONE, SDL_BITMAPORDER_4321, SDL_BITMAPORDER_1234 -}; +} SDL_BitmapOrder; /** Packed component order, high bit -> low bit. */ -enum +typedef enum { SDL_PACKEDORDER_NONE, SDL_PACKEDORDER_XRGB, @@ -83,10 +84,12 @@ enum SDL_PACKEDORDER_BGRX, SDL_PACKEDORDER_ABGR, SDL_PACKEDORDER_BGRA -}; +} SDL_PackedOrder; /** Array component order, low byte -> high byte. */ -enum +/* !!! FIXME: in 2.1, make these not overlap differently with + !!! FIXME: SDL_PACKEDORDER_*, so we can simplify SDL_ISPIXELFORMAT_ALPHA */ +typedef enum { SDL_ARRAYORDER_NONE, SDL_ARRAYORDER_RGB, @@ -95,10 +98,10 @@ enum SDL_ARRAYORDER_BGR, SDL_ARRAYORDER_BGRA, SDL_ARRAYORDER_ABGR -}; +} SDL_ArrayOrder; /** Packed component layout. */ -enum +typedef enum { SDL_PACKEDLAYOUT_NONE, SDL_PACKEDLAYOUT_332, @@ -109,7 +112,7 @@ enum SDL_PACKEDLAYOUT_8888, SDL_PACKEDLAYOUT_2101010, SDL_PACKEDLAYOUT_1010102 -}; +} SDL_PackedLayout; #define SDL_DEFINE_PIXELFOURCC(A, B, C, D) SDL_FOURCC(A, B, C, D) @@ -117,11 +120,11 @@ enum ((1 << 28) | ((type) << 24) | ((order) << 20) | ((layout) << 16) | \ ((bits) << 8) | ((bytes) << 0)) -#define SDL_PIXELFLAG(X) (((X) >> 28) & 0x0F) -#define SDL_PIXELTYPE(X) (((X) >> 24) & 0x0F) -#define SDL_PIXELORDER(X) (((X) >> 20) & 0x0F) -#define SDL_PIXELLAYOUT(X) (((X) >> 16) & 0x0F) -#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF) +#define SDL_PIXELFLAG(X) (((X) >> 28) & 0x0F) +#define SDL_PIXELTYPE(X) (((X) >> 24) & 0x0F) +#define SDL_PIXELORDER(X) (((X) >> 20) & 0x0F) +#define SDL_PIXELLAYOUT(X) (((X) >> 16) & 0x0F) +#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF) #define SDL_BYTESPERPIXEL(X) \ (SDL_ISPIXELFORMAT_FOURCC(X) ? \ ((((X) == SDL_PIXELFORMAT_YUY2) || \ @@ -134,19 +137,38 @@ enum (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8))) -#define SDL_ISPIXELFORMAT_ALPHA(format) \ +#define SDL_ISPIXELFORMAT_PACKED(format) \ (!SDL_ISPIXELFORMAT_FOURCC(format) && \ + ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED8) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED16) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32))) + +#define SDL_ISPIXELFORMAT_ARRAY(format) \ + (!SDL_ISPIXELFORMAT_FOURCC(format) && \ + ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU8) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU16) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU32) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF16) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF32))) + +#define SDL_ISPIXELFORMAT_ALPHA(format) \ + ((SDL_ISPIXELFORMAT_PACKED(format) && \ ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) || \ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) || \ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \ - (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA))) + (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA))) || \ + (SDL_ISPIXELFORMAT_ARRAY(format) && \ + ((SDL_PIXELORDER(format) == SDL_ARRAYORDER_ARGB) || \ + (SDL_PIXELORDER(format) == SDL_ARRAYORDER_RGBA) || \ + (SDL_PIXELORDER(format) == SDL_ARRAYORDER_ABGR) || \ + (SDL_PIXELORDER(format) == SDL_ARRAYORDER_BGRA)))) /* The flag is set to 1 because 0x1? is not in the printable ASCII range */ #define SDL_ISPIXELFORMAT_FOURCC(format) \ ((format) && (SDL_PIXELFLAG(format) != 1)) /* Note: If you modify this list, update SDL_GetPixelFormatName() */ -enum +typedef enum { SDL_PIXELFORMAT_UNKNOWN, SDL_PIXELFORMAT_INDEX1LSB = @@ -166,15 +188,22 @@ enum SDL_PIXELFORMAT_RGB332 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_332, 8, 1), - SDL_PIXELFORMAT_RGB444 = + SDL_PIXELFORMAT_XRGB4444 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_4444, 12, 2), - SDL_PIXELFORMAT_RGB555 = + SDL_PIXELFORMAT_RGB444 = SDL_PIXELFORMAT_XRGB4444, + SDL_PIXELFORMAT_XBGR4444 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, + SDL_PACKEDLAYOUT_4444, 12, 2), + SDL_PIXELFORMAT_BGR444 = SDL_PIXELFORMAT_XBGR4444, + SDL_PIXELFORMAT_XRGB1555 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_1555, 15, 2), - SDL_PIXELFORMAT_BGR555 = + SDL_PIXELFORMAT_RGB555 = SDL_PIXELFORMAT_XRGB1555, + SDL_PIXELFORMAT_XBGR1555 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_1555, 15, 2), + SDL_PIXELFORMAT_BGR555 = SDL_PIXELFORMAT_XBGR1555, SDL_PIXELFORMAT_ARGB4444 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_4444, 16, 2), @@ -211,15 +240,17 @@ enum SDL_PIXELFORMAT_BGR24 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0, 24, 3), - SDL_PIXELFORMAT_RGB888 = + SDL_PIXELFORMAT_XRGB8888 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_8888, 24, 4), + SDL_PIXELFORMAT_RGB888 = SDL_PIXELFORMAT_XRGB8888, SDL_PIXELFORMAT_RGBX8888 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX, SDL_PACKEDLAYOUT_8888, 24, 4), - SDL_PIXELFORMAT_BGR888 = + SDL_PIXELFORMAT_XBGR8888 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_8888, 24, 4), + SDL_PIXELFORMAT_BGR888 = SDL_PIXELFORMAT_XBGR8888, SDL_PIXELFORMAT_BGRX8888 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX, SDL_PACKEDLAYOUT_8888, 24, 4), @@ -239,6 +270,19 @@ enum SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_2101010, 32, 4), + /* Aliases for RGBA byte arrays of color data, for the current platform */ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888, + SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888, + SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888, +#else + SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888, + SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888, + SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888, +#endif + SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */ SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'), SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */ @@ -248,9 +292,20 @@ enum SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'), SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ - SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U') -}; + SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'), + SDL_PIXELFORMAT_NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */ + SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'), + SDL_PIXELFORMAT_NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */ + SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), + SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */ + SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') +} SDL_PixelFormatEnum; +/** + * The bits of this structure can be directly reinterpreted as an integer-packed + * color which uses the SDL_PIXELFORMAT_RGBA32 format (SDL_PIXELFORMAT_ABGR8888 + * on little-endian systems and SDL_PIXELFORMAT_RGBA8888 on big-endian systems). + */ typedef struct SDL_Color { Uint8 r; @@ -295,16 +350,31 @@ typedef struct SDL_PixelFormat } SDL_PixelFormat; /** - * \brief Get the human readable name of a pixel format + * Get the human readable name of a pixel format. + * + * \param format the pixel format to query + * \returns the human readable name of the specified pixel format or + * `SDL_PIXELFORMAT_UNKNOWN` if the format isn't recognized. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(Uint32 format); /** - * \brief Convert one of the enumerated pixel formats to a bpp and RGBA masks. - * - * \return SDL_TRUE, or SDL_FALSE if the conversion wasn't possible. - * - * \sa SDL_MasksToPixelFormatEnum() + * Convert one of the enumerated pixel formats to a bpp value and RGBA masks. + * + * \param format one of the SDL_PixelFormatEnum values + * \param bpp a bits per pixel value; usually 15, 16, or 32 + * \param Rmask a pointer filled in with the red mask for the format + * \param Gmask a pointer filled in with the green mask for the format + * \param Bmask a pointer filled in with the blue mask for the format + * \param Amask a pointer filled in with the alpha mask for the format + * \returns SDL_TRUE on success or SDL_FALSE if the conversion wasn't + * possible; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_MasksToPixelFormatEnum */ extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, @@ -314,12 +384,21 @@ extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(Uint32 format, Uint32 * Amask); /** - * \brief Convert a bpp and RGBA masks to an enumerated pixel format. - * - * \return The pixel format, or ::SDL_PIXELFORMAT_UNKNOWN if the conversion - * wasn't possible. - * - * \sa SDL_PixelFormatEnumToMasks() + * Convert a bpp value and RGBA masks to an enumerated pixel format. + * + * This will return `SDL_PIXELFORMAT_UNKNOWN` if the conversion wasn't + * possible. + * + * \param bpp a bits per pixel value; usually 15, 16, or 32 + * \param Rmask the red mask for the format + * \param Gmask the green mask for the format + * \param Bmask the blue mask for the format + * \param Amask the alpha mask for the format + * \returns one of the SDL_PixelFormatEnum values + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_PixelFormatEnumToMasks */ extern DECLSPEC Uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, @@ -328,84 +407,213 @@ extern DECLSPEC Uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp, Uint32 Amask); /** - * \brief Create an SDL_PixelFormat structure from a pixel format enum. + * Create an SDL_PixelFormat structure corresponding to a pixel format. + * + * Returned structure may come from a shared global cache (i.e. not newly + * allocated), and hence should not be modified, especially the palette. Weird + * errors such as `Blit combination not supported` may occur. + * + * \param pixel_format one of the SDL_PixelFormatEnum values + * \returns the new SDL_PixelFormat structure or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreeFormat */ extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_AllocFormat(Uint32 pixel_format); /** - * \brief Free an SDL_PixelFormat structure. + * Free an SDL_PixelFormat structure allocated by SDL_AllocFormat(). + * + * \param format the SDL_PixelFormat structure to free + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocFormat */ extern DECLSPEC void SDLCALL SDL_FreeFormat(SDL_PixelFormat *format); /** - * \brief Create a palette structure with the specified number of color - * entries. - * - * \return A new palette, or NULL if there wasn't enough memory. - * - * \note The palette entries are initialized to white. - * - * \sa SDL_FreePalette() + * Create a palette structure with the specified number of color entries. + * + * The palette entries are initialized to white. + * + * \param ncolors represents the number of color entries in the color palette + * \returns a new SDL_Palette structure on success or NULL on failure (e.g. if + * there wasn't enough memory); call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreePalette */ extern DECLSPEC SDL_Palette *SDLCALL SDL_AllocPalette(int ncolors); /** - * \brief Set the palette for a pixel format structure. + * Set the palette for a pixel format structure. + * + * \param format the SDL_PixelFormat structure that will use the palette + * \param palette the SDL_Palette structure that will be used + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocPalette + * \sa SDL_FreePalette */ extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette); /** - * \brief Set a range of colors in a palette. - * - * \param palette The palette to modify. - * \param colors An array of colors to copy into the palette. - * \param firstcolor The index of the first palette entry to modify. - * \param ncolors The number of entries to modify. - * - * \return 0 on success, or -1 if not all of the colors could be set. + * Set a range of colors in a palette. + * + * \param palette the SDL_Palette structure to modify + * \param colors an array of SDL_Color structures to copy into the palette + * \param firstcolor the index of the first palette entry to modify + * \param ncolors the number of entries to modify + * \returns 0 on success or a negative error code if not all of the colors + * could be set; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocPalette + * \sa SDL_CreateRGBSurface */ extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors, int firstcolor, int ncolors); /** - * \brief Free a palette created with SDL_AllocPalette(). - * - * \sa SDL_AllocPalette() + * Free a palette created with SDL_AllocPalette(). + * + * \param palette the SDL_Palette structure to be freed + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocPalette */ extern DECLSPEC void SDLCALL SDL_FreePalette(SDL_Palette * palette); /** - * \brief Maps an RGB triple to an opaque pixel value for a given pixel format. - * - * \sa SDL_MapRGBA + * Map an RGB triple to an opaque pixel value for a given pixel format. + * + * This function maps the RGB color value to the specified pixel format and + * returns the pixel value best approximating the given RGB color value for + * the given pixel format. + * + * If the format has a palette (8-bit) the index of the closest matching color + * in the palette will be returned. + * + * If the specified pixel format has an alpha component it will be returned as + * all 1 bits (fully opaque). + * + * If the pixel format bpp (color depth) is less than 32-bpp then the unused + * upper bits of the return value can safely be ignored (e.g., with a 16-bpp + * format the return value can be assigned to a Uint16, and similarly a Uint8 + * for an 8-bpp format). + * + * \param format an SDL_PixelFormat structure describing the pixel format + * \param r the red component of the pixel in the range 0-255 + * \param g the green component of the pixel in the range 0-255 + * \param b the blue component of the pixel in the range 0-255 + * \returns a pixel value + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRGB + * \sa SDL_GetRGBA + * \sa SDL_MapRGBA */ extern DECLSPEC Uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b); /** - * \brief Maps an RGBA quadruple to a pixel value for a given pixel format. - * - * \sa SDL_MapRGB + * Map an RGBA quadruple to a pixel value for a given pixel format. + * + * This function maps the RGBA color value to the specified pixel format and + * returns the pixel value best approximating the given RGBA color value for + * the given pixel format. + * + * If the specified pixel format has no alpha component the alpha value will + * be ignored (as it will be in formats with a palette). + * + * If the format has a palette (8-bit) the index of the closest matching color + * in the palette will be returned. + * + * If the pixel format bpp (color depth) is less than 32-bpp then the unused + * upper bits of the return value can safely be ignored (e.g., with a 16-bpp + * format the return value can be assigned to a Uint16, and similarly a Uint8 + * for an 8-bpp format). + * + * \param format an SDL_PixelFormat structure describing the format of the + * pixel + * \param r the red component of the pixel in the range 0-255 + * \param g the green component of the pixel in the range 0-255 + * \param b the blue component of the pixel in the range 0-255 + * \param a the alpha component of the pixel in the range 0-255 + * \returns a pixel value + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRGB + * \sa SDL_GetRGBA + * \sa SDL_MapRGB */ extern DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /** - * \brief Get the RGB components from a pixel of the specified format. - * - * \sa SDL_GetRGBA + * Get RGB values from a pixel in the specified format. + * + * This function uses the entire 8-bit [0..255] range when converting color + * components from pixel formats with less than 8-bits per RGB component + * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff, + * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]). + * + * \param pixel a pixel value + * \param format an SDL_PixelFormat structure describing the format of the + * pixel + * \param r a pointer filled in with the red component + * \param g a pointer filled in with the green component + * \param b a pointer filled in with the blue component + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRGBA + * \sa SDL_MapRGB + * \sa SDL_MapRGBA */ extern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g, Uint8 * b); /** - * \brief Get the RGBA components from a pixel of the specified format. - * - * \sa SDL_GetRGB + * Get RGBA values from a pixel in the specified format. + * + * This function uses the entire 8-bit [0..255] range when converting color + * components from pixel formats with less than 8-bits per RGB component + * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff, + * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]). + * + * If the surface has no alpha component, the alpha will be returned as 0xff + * (100% opaque). + * + * \param pixel a pixel value + * \param format an SDL_PixelFormat structure describing the format of the + * pixel + * \param r a pointer filled in with the red component + * \param g a pointer filled in with the green component + * \param b a pointer filled in with the blue component + * \param a a pointer filled in with the alpha component + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRGB + * \sa SDL_MapRGB + * \sa SDL_MapRGBA */ extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format, @@ -413,19 +621,24 @@ extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, Uint8 * a); /** - * \brief Calculate a 256 entry gamma ramp for a gamma value. + * Calculate a 256 entry gamma ramp for a gamma value. + * + * \param gamma a gamma value where 0.0 is black and 1.0 is identity + * \param ramp an array of 256 values filled in with the gamma ramp + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowGammaRamp */ extern DECLSPEC void SDLCALL SDL_CalculateGammaRamp(float gamma, Uint16 * ramp); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_pixels_h */ +#endif /* SDL_pixels_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_platform.h b/external/SDL2/SDL_platform.h index d03bd38..79b8b6f 100644 --- a/external/SDL2/SDL_platform.h +++ b/external/SDL2/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,52 +21,48 @@ /** * \file SDL_platform.h - * + * * Try to get a standard set of platform defines. */ -#ifndef _SDL_platform_h -#define _SDL_platform_h +#ifndef SDL_platform_h_ +#define SDL_platform_h_ #if defined(_AIX) #undef __AIX__ -#define __AIX__ 1 -#endif -#if defined(__BEOS__) -#undef __BEOS__ -#define __BEOS__ 1 +#define __AIX__ 1 #endif #if defined(__HAIKU__) #undef __HAIKU__ -#define __HAIKU__ 1 +#define __HAIKU__ 1 #endif #if defined(bsdi) || defined(__bsdi) || defined(__bsdi__) #undef __BSDI__ -#define __BSDI__ 1 +#define __BSDI__ 1 #endif #if defined(_arch_dreamcast) #undef __DREAMCAST__ -#define __DREAMCAST__ 1 +#define __DREAMCAST__ 1 #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) #undef __FREEBSD__ -#define __FREEBSD__ 1 +#define __FREEBSD__ 1 #endif #if defined(hpux) || defined(__hpux) || defined(__hpux__) #undef __HPUX__ -#define __HPUX__ 1 +#define __HPUX__ 1 #endif #if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE) #undef __IRIX__ -#define __IRIX__ 1 +#define __IRIX__ 1 #endif -#if defined(linux) || defined(__linux) || defined(__linux__) +#if (defined(linux) || defined(__linux) || defined(__linux__)) #undef __LINUX__ -#define __LINUX__ 1 +#define __LINUX__ 1 #endif -#if defined(ANDROID) +#if defined(ANDROID) || defined(__ANDROID__) #undef __ANDROID__ -#undef __LINUX__ /*do we need to do this?*/ +#undef __LINUX__ /* do we need to do this? */ #define __ANDROID__ 1 #endif @@ -74,76 +70,166 @@ /* lets us know what version of Mac OS X we're compiling on */ #include "AvailabilityMacros.h" #include "TargetConditionals.h" + +/* Fix building with older SDKs that don't define these + See this for more information: + https://stackoverflow.com/questions/12132933/preprocessor-macro-for-os-x-targets +*/ +#ifndef TARGET_OS_MACCATALYST +#define TARGET_OS_MACCATALYST 0 +#endif +#ifndef TARGET_OS_IOS +#define TARGET_OS_IOS 0 +#endif +#ifndef TARGET_OS_IPHONE +#define TARGET_OS_IPHONE 0 +#endif +#ifndef TARGET_OS_TV +#define TARGET_OS_TV 0 +#endif +#ifndef TARGET_OS_SIMULATOR +#define TARGET_OS_SIMULATOR 0 +#endif + +#if TARGET_OS_TV +#undef __TVOS__ +#define __TVOS__ 1 +#endif #if TARGET_OS_IPHONE -/* if compiling for iPhone */ +/* if compiling for iOS */ #undef __IPHONEOS__ #define __IPHONEOS__ 1 #undef __MACOSX__ #else -/* if not compiling for iPhone */ +/* if not compiling for iOS */ #undef __MACOSX__ -#define __MACOSX__ 1 +#define __MACOSX__ 1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 +# error SDL for Mac OS X only supports deploying on 10.6 and above. +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */ #endif /* TARGET_OS_IPHONE */ #endif /* defined(__APPLE__) */ #if defined(__NetBSD__) #undef __NETBSD__ -#define __NETBSD__ 1 +#define __NETBSD__ 1 #endif #if defined(__OpenBSD__) #undef __OPENBSD__ -#define __OPENBSD__ 1 +#define __OPENBSD__ 1 #endif -#if defined(__OS2__) +#if defined(__OS2__) || defined(__EMX__) #undef __OS2__ -#define __OS2__ 1 +#define __OS2__ 1 #endif #if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE) #undef __OSF__ -#define __OSF__ 1 +#define __OSF__ 1 #endif #if defined(__QNXNTO__) #undef __QNXNTO__ -#define __QNXNTO__ 1 +#define __QNXNTO__ 1 #endif #if defined(riscos) || defined(__riscos) || defined(__riscos__) #undef __RISCOS__ -#define __RISCOS__ 1 +#define __RISCOS__ 1 #endif -#if defined(__SVR4) +#if defined(__sun) && defined(__SVR4) #undef __SOLARIS__ -#define __SOLARIS__ 1 +#define __SOLARIS__ 1 #endif -#if defined(WIN32) || defined(_WIN32) + +#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +/* Try to find out if we're compiling for WinRT or non-WinRT */ +#if defined(_MSC_VER) && defined(__has_include) +#if __has_include() +#define HAVE_WINAPIFAMILY_H 1 +#else +#define HAVE_WINAPIFAMILY_H 0 +#endif + +/* If _USING_V110_SDK71_ is defined it means we are using the Windows XP toolset. */ +#elif defined(_MSC_VER) && (_MSC_VER >= 1700 && !_USING_V110_SDK71_) /* _MSC_VER == 1700 for Visual Studio 2012 */ +#define HAVE_WINAPIFAMILY_H 1 +#else +#define HAVE_WINAPIFAMILY_H 0 +#endif + +#if HAVE_WINAPIFAMILY_H +#include +#define WINAPI_FAMILY_WINRT (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) +#else +#define WINAPI_FAMILY_WINRT 0 +#endif /* HAVE_WINAPIFAMILY_H */ + +#if WINAPI_FAMILY_WINRT +#undef __WINRT__ +#define __WINRT__ 1 +#else +#undef __WINDOWS__ +#define __WINDOWS__ 1 +#endif +#endif /* defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) */ + +#if defined(__WINDOWS__) #undef __WIN32__ -#define __WIN32__ 1 +#define __WIN32__ 1 #endif #if defined(__PSP__) #undef __PSP__ -#define __PSP__ 1 +#define __PSP__ 1 +#endif + +/* The NACL compiler defines __native_client__ and __pnacl__ + * Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi + */ +#if defined(__native_client__) +#undef __LINUX__ +#undef __NACL__ +#define __NACL__ 1 +#endif +#if defined(__pnacl__) +#undef __LINUX__ +#undef __PNACL__ +#define __PNACL__ 1 +/* PNACL with newlib supports static linking only */ +#define __SDL_NOGETPROCADDR__ +#endif + +#if defined(__vita__) +#define __VITA__ 1 #endif #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief Gets the name of the platform. + * Get the name of the platform. + * + * Here are the names returned for some (but not all) supported platforms: + * + * - "Windows" + * - "Mac OS X" + * - "Linux" + * - "iOS" + * - "Android" + * + * \returns the name of the platform. If the correct platform name is not + * available, returns a string beginning with the text "Unknown". + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC const char * SDLCALL SDL_GetPlatform (void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_platform_h */ +#endif /* SDL_platform_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_power.h b/external/SDL2/SDL_power.h index d796aee..ecb3f4b 100644 --- a/external/SDL2/SDL_power.h +++ b/external/SDL2/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,12 +19,12 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_power_h -#define _SDL_power_h +#ifndef SDL_power_h_ +#define SDL_power_h_ /** * \file SDL_power.h - * + * * Header for the SDL power management routines. */ @@ -33,13 +33,11 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief The basic state for the system's power supply. + * The basic state for the system's power supply. */ typedef enum { @@ -52,28 +50,39 @@ typedef enum /** - * \brief Get the current power supply details. - * - * \param secs Seconds of battery life left. You can pass a NULL here if - * you don't care. Will return -1 if we can't determine a - * value, or we're not running on a battery. - * - * \param pct Percentage of battery life left, between 0 and 100. You can - * pass a NULL here if you don't care. Will return -1 if we - * can't determine a value, or we're not running on a battery. - * - * \return The state of the battery (if any). + * Get the current power supply details. + * + * You should never take a battery status as absolute truth. Batteries + * (especially failing batteries) are delicate hardware, and the values + * reported here are best estimates based on what that hardware reports. It's + * not uncommon for older batteries to lose stored power much faster than it + * reports, or completely drain when reporting it has 20 percent left, etc. + * + * Battery status can change at any time; if you are concerned with power + * state, you should call this function frequently, and perhaps ignore changes + * until they seem to be stable for a few seconds. + * + * It's possible a platform can only report battery percentage or time left + * but not both. + * + * \param secs seconds of battery life left, you can pass a NULL here if you + * don't care, will return -1 if we can't determine a value, or + * we're not running on a battery + * \param pct percentage of battery life left, between 0 and 100, you can pass + * a NULL here if you don't care, will return -1 if we can't + * determine a value, or we're not running on a battery + * \returns an SDL_PowerState enum representing the current battery state. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *secs, int *pct); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_power_h */ +#endif /* SDL_power_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_quit.h b/external/SDL2/SDL_quit.h index 5c7d343..4090f7f 100644 --- a/external/SDL2/SDL_quit.h +++ b/external/SDL2/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,23 +21,23 @@ /** * \file SDL_quit.h - * + * * Include file for SDL quit event handling. */ -#ifndef _SDL_quit_h -#define _SDL_quit_h +#ifndef SDL_quit_h_ +#define SDL_quit_h_ #include "SDL_stdinc.h" #include "SDL_error.h" /** * \file SDL_quit.h - * + * * An ::SDL_QUIT event is generated when the user tries to close the application * window. If it is ignored or filtered out, the window will remain open. * If it is not ignored or filtered, it is queued normally and the window - * is allowed to close. When the window is closed, screen updates will + * is allowed to close. When the window is closed, screen updates will * complete, but have no effect. * * SDL_Init() installs signal handlers for SIGINT (keyboard interrupt) @@ -46,7 +46,7 @@ * to determine the cause of an ::SDL_QUIT event, but setting a signal * handler in your application will override the default generation of * quit events for that signal. - * + * * \sa SDL_Quit() */ @@ -55,4 +55,4 @@ #define SDL_QuitRequested() \ (SDL_PumpEvents(), (SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUIT,SDL_QUIT) > 0)) -#endif /* _SDL_quit_h */ +#endif /* SDL_quit_h_ */ diff --git a/external/SDL2/SDL_rect.h b/external/SDL2/SDL_rect.h index a509c70..6616ba6 100644 --- a/external/SDL2/SDL_rect.h +++ b/external/SDL2/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_rect.h - * + * * Header file for SDL_rect definition and management functions. */ -#ifndef _SDL_rect_h -#define _SDL_rect_h +#ifndef SDL_rect_h_ +#define SDL_rect_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -36,31 +36,43 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief The structure that defines a point + * The structure that defines a point (integer) * - * \sa SDL_EnclosePoints + * \sa SDL_EnclosePoints + * \sa SDL_PointInRect */ -typedef struct +typedef struct SDL_Point { int x; int y; } SDL_Point; /** - * \brief A rectangle, with the origin at the upper left. - * - * \sa SDL_RectEmpty - * \sa SDL_RectEquals - * \sa SDL_HasIntersection - * \sa SDL_IntersectRect - * \sa SDL_UnionRect - * \sa SDL_EnclosePoints + * The structure that defines a point (floating point) + * + * \sa SDL_EnclosePoints + * \sa SDL_PointInRect + */ +typedef struct SDL_FPoint +{ + float x; + float y; +} SDL_FPoint; + + +/** + * A rectangle, with the origin at the upper left (integer). + * + * \sa SDL_RectEmpty + * \sa SDL_RectEquals + * \sa SDL_HasIntersection + * \sa SDL_IntersectRect + * \sa SDL_UnionRect + * \sa SDL_EnclosePoints */ typedef struct SDL_Rect { @@ -68,46 +80,110 @@ typedef struct SDL_Rect int w, h; } SDL_Rect; -/** - * \brief Returns true if the rectangle has no area. - */ -#define SDL_RectEmpty(X) ((!(X)) || ((X)->w <= 0) || ((X)->h <= 0)) /** - * \brief Returns true if the two rectangles are equal. + * A rectangle, with the origin at the upper left (floating point). */ -#define SDL_RectEquals(A, B) (((A)) && ((B)) && \ - ((A)->x == (B)->x) && ((A)->y == (B)->y) && \ - ((A)->w == (B)->w) && ((A)->h == (B)->h)) +typedef struct SDL_FRect +{ + float x; + float y; + float w; + float h; +} SDL_FRect; + /** - * \brief Determine whether two rectangles intersect. - * - * \return SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * Returns true if point resides inside a rectangle. + */ +SDL_FORCE_INLINE SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r) +{ + return ( (p->x >= r->x) && (p->x < (r->x + r->w)) && + (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? SDL_TRUE : SDL_FALSE; +} + +/** + * Returns true if the rectangle has no area. + */ +SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r) +{ + return ((!r) || (r->w <= 0) || (r->h <= 0)) ? SDL_TRUE : SDL_FALSE; +} + +/** + * Returns true if the two rectangles are equal. + */ +SDL_FORCE_INLINE SDL_bool SDL_RectEquals(const SDL_Rect *a, const SDL_Rect *b) +{ + return (a && b && (a->x == b->x) && (a->y == b->y) && + (a->w == b->w) && (a->h == b->h)) ? SDL_TRUE : SDL_FALSE; +} + +/** + * Determine whether two rectangles intersect. + * + * If either pointer is NULL the function will return SDL_FALSE. + * + * \param A an SDL_Rect structure representing the first rectangle + * \param B an SDL_Rect structure representing the second rectangle + * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_IntersectRect */ extern DECLSPEC SDL_bool SDLCALL SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B); /** - * \brief Calculate the intersection of two rectangles. - * - * \return SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * Calculate the intersection of two rectangles. + * + * If `result` is NULL then this function will return SDL_FALSE. + * + * \param A an SDL_Rect structure representing the first rectangle + * \param B an SDL_Rect structure representing the second rectangle + * \param result an SDL_Rect structure filled in with the intersection of + * rectangles `A` and `B` + * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HasIntersection */ extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result); /** - * \brief Calculate the union of two rectangles. + * Calculate the union of two rectangles. + * + * \param A an SDL_Rect structure representing the first rectangle + * \param B an SDL_Rect structure representing the second rectangle + * \param result an SDL_Rect structure filled in with the union of rectangles + * `A` and `B` + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result); /** - * \brief Calculate a minimal rectangle enclosing a set of points + * Calculate a minimal rectangle enclosing a set of points. * - * \return SDL_TRUE if any points were within the clipping rect + * If `clip` is not NULL then only points inside of the clipping rectangle are + * considered. + * + * \param points an array of SDL_Point structures representing points to be + * enclosed + * \param count the number of structures in the `points` array + * \param clip an SDL_Rect used for clipping or NULL to enclose all points + * \param result an SDL_Rect structure filled in with the minimal enclosing + * rectangle + * \returns SDL_TRUE if any points were enclosed or SDL_FALSE if all the + * points were outside of the clipping rectangle. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_bool SDLCALL SDL_EnclosePoints(const SDL_Point * points, int count, @@ -115,9 +191,22 @@ extern DECLSPEC SDL_bool SDLCALL SDL_EnclosePoints(const SDL_Point * points, SDL_Rect * result); /** - * \brief Calculate the intersection of a rectangle and line segment. - * - * \return SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * Calculate the intersection of a rectangle and line segment. + * + * This function is used to clip a line segment to a rectangle. A line segment + * contained entirely within the rectangle or that does not intersect will + * remain unchanged. A line segment that crosses the rectangle at either or + * both ends will be clipped to the boundary of the rectangle and the new + * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary. + * + * \param rect an SDL_Rect structure representing the rectangle to intersect + * \param X1 a pointer to the starting X-coordinate of the line + * \param Y1 a pointer to the starting Y-coordinate of the line + * \param X2 a pointer to the ending X-coordinate of the line + * \param Y2 a pointer to the ending Y-coordinate of the line + * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, @@ -126,12 +215,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRectAndLine(const SDL_Rect * /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_rect_h */ +#endif /* SDL_rect_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_render.h b/external/SDL2/SDL_render.h index 591de81..a7e4908 100644 --- a/external/SDL2/SDL_render.h +++ b/external/SDL2/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_render.h - * + * * Header file for SDL 2D rendering functions. * * This API supports the following features: @@ -37,13 +37,16 @@ * them, and may also be stretched with linear interpolation. * * This API is designed to accelerate simple 2D operations. You may - * want more functionality such as rotation and particle effects and + * want more functionality such as polygons and particle effects and * in that case you should use SDL's OpenGL/Direct3D support or one * of the many good 3D engines. + * + * These functions must be called from the main thread. + * See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995 */ -#ifndef _SDL_render_h -#define _SDL_render_h +#ifndef SDL_render_h_ +#define SDL_render_h_ #include "SDL_stdinc.h" #include "SDL_rect.h" @@ -52,27 +55,25 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief Flags used when creating a rendering context + * Flags used when creating a rendering context */ typedef enum { - SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */ - SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware + SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */ + SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware acceleration */ - SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronized + SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronized with the refresh rate */ SDL_RENDERER_TARGETTEXTURE = 0x00000008 /**< The renderer supports rendering to texture */ } SDL_RendererFlags; /** - * \brief Information on the capabilities of a render driver or context. + * Information on the capabilities of a render driver or context. */ typedef struct SDL_RendererInfo { @@ -80,12 +81,32 @@ typedef struct SDL_RendererInfo Uint32 flags; /**< Supported ::SDL_RendererFlags */ Uint32 num_texture_formats; /**< The number of available texture formats */ Uint32 texture_formats[16]; /**< The available texture formats */ - int max_texture_width; /**< The maximimum texture width */ - int max_texture_height; /**< The maximimum texture height */ + int max_texture_width; /**< The maximum texture width */ + int max_texture_height; /**< The maximum texture height */ } SDL_RendererInfo; /** - * \brief The access pattern allowed for a texture. + * Vertex structure + */ +typedef struct SDL_Vertex +{ + SDL_FPoint position; /**< Vertex position, in SDL_Renderer coordinates */ + SDL_Color color; /**< Vertex color */ + SDL_FPoint tex_coord; /**< Normalized texture coordinates, if needed */ +} SDL_Vertex; + +/** + * The scaling mode for a texture. + */ +typedef enum +{ + SDL_ScaleModeNearest, /**< nearest pixel sampling */ + SDL_ScaleModeLinear, /**< linear filtering */ + SDL_ScaleModeBest /**< anisotropic filtering */ +} SDL_ScaleMode; + +/** + * The access pattern allowed for a texture. */ typedef enum { @@ -95,7 +116,7 @@ typedef enum } SDL_TextureAccess; /** - * \brief The texture channel modulation used in SDL_RenderCopy(). + * The texture channel modulation used in SDL_RenderCopy(). */ typedef enum { @@ -105,7 +126,7 @@ typedef enum } SDL_TextureModulate; /** - * \brief Flip constants for SDL_RenderCopyEx + * Flip constants for SDL_RenderCopyEx */ typedef enum { @@ -115,58 +136,71 @@ typedef enum } SDL_RendererFlip; /** - * \brief A structure representing rendering state + * A structure representing rendering state */ struct SDL_Renderer; typedef struct SDL_Renderer SDL_Renderer; /** - * \brief An efficient driver-specific representation of pixel data + * An efficient driver-specific representation of pixel data */ struct SDL_Texture; typedef struct SDL_Texture SDL_Texture; - /* Function prototypes */ /** - * \brief Get the number of 2D rendering drivers available for the current - * display. - * - * A render driver is a set of code that handles rendering and texture - * management on a particular display. Normally there is only one, but - * some drivers may have several available with different capabilities. - * - * \sa SDL_GetRenderDriverInfo() - * \sa SDL_CreateRenderer() + * Get the number of 2D rendering drivers available for the current display. + * + * A render driver is a set of code that handles rendering and texture + * management on a particular display. Normally there is only one, but some + * drivers may have several available with different capabilities. + * + * There may be none if SDL was compiled without render support. + * + * \returns a number >= 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_GetRenderDriverInfo */ extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); /** - * \brief Get information about a specific 2D rendering driver for the current - * display. - * - * \param index The index of the driver to query information about. - * \param info A pointer to an SDL_RendererInfo struct to be filled with - * information on the rendering driver. - * - * \return 0 on success, -1 if the index was out of range. - * - * \sa SDL_CreateRenderer() + * Get info about a specific 2D rendering driver for the current display. + * + * \param index the index of the driver to query information about + * \param info an SDL_RendererInfo structure to be filled with information on + * the rendering driver + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_GetNumRenderDrivers */ extern DECLSPEC int SDLCALL SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info); /** - * \brief Create a window and default renderer + * Create a window and default renderer. * - * \param width The width of the window - * \param height The height of the window - * \param window_flags The flags used to create the window - * \param window A pointer filled with the window, or NULL on error - * \param renderer A pointer filled with the renderer, or NULL on error + * \param width the width of the window + * \param height the height of the window + * \param window_flags the flags used to create the window (see + * SDL_CreateWindow()) + * \param window a pointer filled with the window, or NULL on error + * \param renderer a pointer filled with the renderer, or NULL on error + * \returns 0 on success, or -1 on error; call SDL_GetError() for more + * information. * - * \return 0 on success, or -1 on error + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_CreateWindow */ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer( int width, int height, Uint32 window_flags, @@ -174,60 +208,116 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer( /** - * \brief Create a 2D rendering context for a window. - * - * \param window The window where rendering is displayed. - * \param index The index of the rendering driver to initialize, or -1 to - * initialize the first one supporting the requested flags. - * \param flags ::SDL_RendererFlags. - * - * \return A valid rendering context or NULL if there was an error. - * - * \sa SDL_CreateSoftwareRenderer() - * \sa SDL_GetRendererInfo() - * \sa SDL_DestroyRenderer() + * Create a 2D rendering context for a window. + * + * \param window the window where rendering is displayed + * \param index the index of the rendering driver to initialize, or -1 to + * initialize the first one supporting the requested flags + * \param flags 0, or one or more SDL_RendererFlags OR'd together + * \returns a valid rendering context or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateSoftwareRenderer + * \sa SDL_DestroyRenderer + * \sa SDL_GetNumRenderDrivers + * \sa SDL_GetRendererInfo */ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags); /** - * \brief Create a 2D software rendering context for a surface. - * - * \param surface The surface where rendering is done. - * - * \return A valid rendering context or NULL if there was an error. - * - * \sa SDL_CreateRenderer() - * \sa SDL_DestroyRenderer() + * Create a 2D software rendering context for a surface. + * + * Two other API which can be used to create SDL_Renderer: + * SDL_CreateRenderer() and SDL_CreateWindowAndRenderer(). These can _also_ + * create a software renderer, but they are intended to be used with an + * SDL_Window as the final destination and not an SDL_Surface. + * + * \param surface the SDL_Surface structure representing the surface where + * rendering is done + * \returns a valid rendering context or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer + * \sa SDL_CreateWindowRenderer + * \sa SDL_DestroyRenderer */ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface * surface); /** - * \brief Get the renderer associated with a window. + * Get the renderer associated with a window. + * + * \param window the window to query + * \returns the rendering context on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer */ extern DECLSPEC SDL_Renderer * SDLCALL SDL_GetRenderer(SDL_Window * window); /** - * \brief Get information about a rendering context. + * Get information about a rendering context. + * + * \param renderer the rendering context + * \param info an SDL_RendererInfo structure filled with information about the + * current renderer + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer */ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info); /** - * \brief Create a texture for a rendering context. - * - * \param format The format of the texture. - * \param access One of the enumerated values in ::SDL_TextureAccess. - * \param w The width of the texture in pixels. - * \param h The height of the texture in pixels. - * - * \return The created texture is returned, or 0 if no rendering context was - * active, the format was unsupported, or the width or height were out - * of range. - * - * \sa SDL_QueryTexture() - * \sa SDL_UpdateTexture() - * \sa SDL_DestroyTexture() + * Get the output size in pixels of a rendering context. + * + * Due to high-dpi displays, you might end up with a rendering context that + * has more pixels than the window that contains it, so use this instead of + * SDL_GetWindowSize() to decide how much drawing area you have. + * + * \param renderer the rendering context + * \param w an int filled with the width + * \param h an int filled with the height + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRenderer + */ +extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer * renderer, + int *w, int *h); + +/** + * Create a texture for a rendering context. + * + * You can set the texture scaling method by setting + * `SDL_HINT_RENDER_SCALE_QUALITY` before creating the texture. + * + * \param renderer the rendering context + * \param format one of the enumerated values in SDL_PixelFormatEnum + * \param access one of the enumerated values in SDL_TextureAccess + * \param w the width of the texture in pixels + * \param h the height of the texture in pixels + * \returns a pointer to the created texture or NULL if no rendering context + * was active, the format was unsupported, or the width or height + * were out of range; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateTextureFromSurface + * \sa SDL_DestroyTexture + * \sa SDL_QueryTexture + * \sa SDL_UpdateTexture */ extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, @@ -235,455 +325,1063 @@ extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer, int h); /** - * \brief Create a texture from an existing surface. - * - * \param surface The surface containing pixel data used to fill the texture. - * - * \return The created texture is returned, or 0 on error. - * - * \note The surface is not modified or freed by this function. - * - * \sa SDL_QueryTexture() - * \sa SDL_DestroyTexture() + * Create a texture from an existing surface. + * + * The surface is not modified or freed by this function. + * + * The SDL_TextureAccess hint for the created texture is + * `SDL_TEXTUREACCESS_STATIC`. + * + * The pixel format of the created texture may be different from the pixel + * format of the surface. Use SDL_QueryTexture() to query the pixel format of + * the texture. + * + * \param renderer the rendering context + * \param surface the SDL_Surface structure containing pixel data used to fill + * the texture + * \returns the created texture or NULL on failure; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateTexture + * \sa SDL_DestroyTexture + * \sa SDL_QueryTexture */ extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface); /** - * \brief Query the attributes of a texture - * - * \param texture A texture to be queried. - * \param format A pointer filled in with the raw format of the texture. The - * actual format may differ, but pixel transfers will use this - * format. - * \param access A pointer filled in with the actual access to the texture. - * \param w A pointer filled in with the width of the texture in pixels. - * \param h A pointer filled in with the height of the texture in pixels. - * - * \return 0 on success, or -1 if the texture is not valid. + * Query the attributes of a texture. + * + * \param texture the texture to query + * \param format a pointer filled in with the raw format of the texture; the + * actual format may differ, but pixel transfers will use this + * format (one of the SDL_PixelFormatEnum values) + * \param access a pointer filled in with the actual access to the texture + * (one of the SDL_TextureAccess values) + * \param w a pointer filled in with the width of the texture in pixels + * \param h a pointer filled in with the height of the texture in pixels + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateTexture */ extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access, int *w, int *h); /** - * \brief Set an additional color value used in render copy operations. - * - * \param texture The texture to update. - * \param r The red color value multiplied into copy operations. - * \param g The green color value multiplied into copy operations. - * \param b The blue color value multiplied into copy operations. - * - * \return 0 on success, or -1 if the texture is not valid or color modulation - * is not supported. - * - * \sa SDL_GetTextureColorMod() + * Set an additional color value multiplied into render copy operations. + * + * When this texture is rendered, during the copy operation each source color + * channel is modulated by the appropriate color value according to the + * following formula: + * + * `srcC = srcC * (color / 255)` + * + * Color modulation is not always supported by the renderer; it will return -1 + * if color modulation is not supported. + * + * \param texture the texture to update + * \param r the red color value multiplied into copy operations + * \param g the green color value multiplied into copy operations + * \param b the blue color value multiplied into copy operations + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTextureColorMod + * \sa SDL_SetTextureAlphaMod */ extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b); /** - * \brief Get the additional color value used in render copy operations. - * - * \param texture The texture to query. - * \param r A pointer filled in with the current red color value. - * \param g A pointer filled in with the current green color value. - * \param b A pointer filled in with the current blue color value. - * - * \return 0 on success, or -1 if the texture is not valid. - * - * \sa SDL_SetTextureColorMod() + * Get the additional color value multiplied into render copy operations. + * + * \param texture the texture to query + * \param r a pointer filled in with the current red color value + * \param g a pointer filled in with the current green color value + * \param b a pointer filled in with the current blue color value + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTextureAlphaMod + * \sa SDL_SetTextureColorMod */ extern DECLSPEC int SDLCALL SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g, Uint8 * b); /** - * \brief Set an additional alpha value used in render copy operations. - * - * \param texture The texture to update. - * \param alpha The alpha value multiplied into copy operations. - * - * \return 0 on success, or -1 if the texture is not valid or alpha modulation - * is not supported. - * - * \sa SDL_GetTextureAlphaMod() + * Set an additional alpha value multiplied into render copy operations. + * + * When this texture is rendered, during the copy operation the source alpha + * value is modulated by this alpha value according to the following formula: + * + * `srcA = srcA * (alpha / 255)` + * + * Alpha modulation is not always supported by the renderer; it will return -1 + * if alpha modulation is not supported. + * + * \param texture the texture to update + * \param alpha the source alpha value multiplied into copy operations + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTextureAlphaMod + * \sa SDL_SetTextureColorMod */ extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha); /** - * \brief Get the additional alpha value used in render copy operations. - * - * \param texture The texture to query. - * \param alpha A pointer filled in with the current alpha value. - * - * \return 0 on success, or -1 if the texture is not valid. - * - * \sa SDL_SetTextureAlphaMod() + * Get the additional alpha value multiplied into render copy operations. + * + * \param texture the texture to query + * \param alpha a pointer filled in with the current alpha value + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTextureColorMod + * \sa SDL_SetTextureAlphaMod */ extern DECLSPEC int SDLCALL SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha); /** - * \brief Set the blend mode used for texture copy operations. - * - * \param texture The texture to update. - * \param blendMode ::SDL_BlendMode to use for texture blending. - * - * \return 0 on success, or -1 if the texture is not valid or the blend mode is - * not supported. - * - * \note If the blend mode is not supported, the closest supported mode is - * chosen. - * - * \sa SDL_GetTextureBlendMode() + * Set the blend mode for a texture, used by SDL_RenderCopy(). + * + * If the blend mode is not supported, the closest supported mode is chosen + * and this function returns -1. + * + * \param texture the texture to update + * \param blendMode the SDL_BlendMode to use for texture blending + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTextureBlendMode + * \sa SDL_RenderCopy */ extern DECLSPEC int SDLCALL SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode); /** - * \brief Get the blend mode used for texture copy operations. - * - * \param texture The texture to query. - * \param blendMode A pointer filled in with the current blend mode. - * - * \return 0 on success, or -1 if the texture is not valid. - * - * \sa SDL_SetTextureBlendMode() + * Get the blend mode used for texture copy operations. + * + * \param texture the texture to query + * \param blendMode a pointer filled in with the current SDL_BlendMode + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetTextureBlendMode */ extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode); /** - * \brief Update the given texture rectangle with new pixel data. - * - * \param texture The texture to update - * \param rect A pointer to the rectangle of pixels to update, or NULL to - * update the entire texture. - * \param pixels The raw pixel data. - * \param pitch The number of bytes between rows of pixel data. - * - * \return 0 on success, or -1 if the texture is not valid. - * - * \note This is a fairly slow function. + * Set the scale mode used for texture scale operations. + * + * If the scale mode is not supported, the closest supported mode is chosen. + * + * \param texture The texture to update. + * \param scaleMode the SDL_ScaleMode to use for texture scaling. + * \returns 0 on success, or -1 if the texture is not valid. + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_GetTextureScaleMode + */ +extern DECLSPEC int SDLCALL SDL_SetTextureScaleMode(SDL_Texture * texture, + SDL_ScaleMode scaleMode); + +/** + * Get the scale mode used for texture scale operations. + * + * \param texture the texture to query. + * \param scaleMode a pointer filled in with the current scale mode. + * \return 0 on success, or -1 if the texture is not valid. + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_SetTextureScaleMode + */ +extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture * texture, + SDL_ScaleMode *scaleMode); + +/** + * Associate a user-specified pointer with a texture. + * + * \param texture the texture to update. + * \param userdata the pointer to associate with the texture. + * \returns 0 on success, or -1 if the texture is not valid. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_GetTextureUserData + */ +extern DECLSPEC int SDLCALL SDL_SetTextureUserData(SDL_Texture * texture, + void *userdata); + +/** + * Get the user-specified pointer associated with a texture + * + * \param texture the texture to query. + * \return the pointer associated with the texture, or NULL if the texture is + * not valid. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_SetTextureUserData + */ +extern DECLSPEC void * SDLCALL SDL_GetTextureUserData(SDL_Texture * texture); + +/** + * Update the given texture rectangle with new pixel data. + * + * The pixel data must be in the pixel format of the texture. Use + * SDL_QueryTexture() to query the pixel format of the texture. + * + * This is a fairly slow function, intended for use with static textures that + * do not change often. + * + * If the texture is intended to be updated often, it is preferred to create + * the texture as streaming and use the locking functions referenced below. + * While this function will work with streaming textures, for optimization + * reasons you may not get the pixels back if you lock the texture afterward. + * + * \param texture the texture to update + * \param rect an SDL_Rect structure representing the area to update, or NULL + * to update the entire texture + * \param pixels the raw pixel data in the format of the texture + * \param pitch the number of bytes in a row of pixel data, including padding + * between lines + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateTexture + * \sa SDL_LockTexture + * \sa SDL_UnlockTexture */ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch); /** - * \brief Lock a portion of the texture for write-only pixel access. - * - * \param texture The texture to lock for access, which was created with - * ::SDL_TEXTUREACCESS_STREAMING. - * \param rect A pointer to the rectangle to lock for access. If the rect - * is NULL, the entire texture will be locked. - * \param pixels This is filled in with a pointer to the locked pixels, - * appropriately offset by the locked area. - * \param pitch This is filled in with the pitch of the locked pixels. - * - * \return 0 on success, or -1 if the texture is not valid or was not created with ::SDL_TEXTUREACCESS_STREAMING. - * - * \sa SDL_UnlockTexture() + * Update a rectangle within a planar YV12 or IYUV texture with new pixel + * data. + * + * You can use SDL_UpdateTexture() as long as your pixel data is a contiguous + * block of Y and U/V planes in the proper order, but this function is + * available if your pixel data is not contiguous. + * + * \param texture the texture to update + * \param rect a pointer to the rectangle of pixels to update, or NULL to + * update the entire texture + * \param Yplane the raw pixel data for the Y plane + * \param Ypitch the number of bytes between rows of pixel data for the Y + * plane + * \param Uplane the raw pixel data for the U plane + * \param Upitch the number of bytes between rows of pixel data for the U + * plane + * \param Vplane the raw pixel data for the V plane + * \param Vpitch the number of bytes between rows of pixel data for the V + * plane + * \returns 0 on success or -1 if the texture is not valid; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.1. + * + * \sa SDL_UpdateTexture + */ +extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture * texture, + const SDL_Rect * rect, + const Uint8 *Yplane, int Ypitch, + const Uint8 *Uplane, int Upitch, + const Uint8 *Vplane, int Vpitch); + +/** + * Update a rectangle within a planar NV12 or NV21 texture with new pixels. + * + * You can use SDL_UpdateTexture() as long as your pixel data is a contiguous + * block of NV12/21 planes in the proper order, but this function is available + * if your pixel data is not contiguous. + * + * \param texture the texture to update + * \param rect a pointer to the rectangle of pixels to update, or NULL to + * update the entire texture. + * \param Yplane the raw pixel data for the Y plane. + * \param Ypitch the number of bytes between rows of pixel data for the Y + * plane. + * \param UVplane the raw pixel data for the UV plane. + * \param UVpitch the number of bytes between rows of pixel data for the UV + * plane. + * \return 0 on success, or -1 if the texture is not valid. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC int SDLCALL SDL_UpdateNVTexture(SDL_Texture * texture, + const SDL_Rect * rect, + const Uint8 *Yplane, int Ypitch, + const Uint8 *UVplane, int UVpitch); + +/** + * Lock a portion of the texture for **write-only** pixel access. + * + * As an optimization, the pixels made available for editing don't necessarily + * contain the old texture data. This is a write-only operation, and if you + * need to keep a copy of the texture data you should do that at the + * application level. + * + * You must use SDL_UnlockTexture() to unlock the pixels and apply any + * changes. + * + * \param texture the texture to lock for access, which was created with + * `SDL_TEXTUREACCESS_STREAMING` + * \param rect an SDL_Rect structure representing the area to lock for access; + * NULL to lock the entire texture + * \param pixels this is filled in with a pointer to the locked pixels, + * appropriately offset by the locked area + * \param pitch this is filled in with the pitch of the locked pixels; the + * pitch is the length of one row in bytes + * \returns 0 on success or a negative error code if the texture is not valid + * or was not created with `SDL_TEXTUREACCESS_STREAMING`; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_UnlockTexture */ extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); /** - * \brief Unlock a texture, uploading the changes to video memory, if needed. - * - * \sa SDL_LockTexture() + * Lock a portion of the texture for **write-only** pixel access, and expose + * it as a SDL surface. + * + * Besides providing an SDL_Surface instead of raw pixel data, this function + * operates like SDL_LockTexture. + * + * As an optimization, the pixels made available for editing don't necessarily + * contain the old texture data. This is a write-only operation, and if you + * need to keep a copy of the texture data you should do that at the + * application level. + * + * You must use SDL_UnlockTexture() to unlock the pixels and apply any + * changes. + * + * The returned surface is freed internally after calling SDL_UnlockTexture() + * or SDL_DestroyTexture(). The caller should not free it. + * + * \param texture the texture to lock for access, which was created with + * `SDL_TEXTUREACCESS_STREAMING` + * \param rect a pointer to the rectangle to lock for access. If the rect is + * NULL, the entire texture will be locked + * \param surface this is filled in with an SDL surface representing the + * locked area + * \returns 0 on success, or -1 if the texture is not valid or was not created + * with `SDL_TEXTUREACCESS_STREAMING` + * + * \since This function is available since SDL 2.0.12. + * + * \sa SDL_LockTexture + * \sa SDL_UnlockTexture + */ +extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture, + const SDL_Rect *rect, + SDL_Surface **surface); + +/** + * Unlock a texture, uploading the changes to video memory, if needed. + * + * **Warning**: Please note that SDL_LockTexture() is intended to be + * write-only; it will not guarantee the previous contents of the texture will + * be provided. You must fully initialize any area of a texture that you lock + * before unlocking it, as the pixels might otherwise be uninitialized memory. + * + * Which is to say: locking and immediately unlocking a texture can result in + * corrupted textures, depending on the renderer in use. + * + * \param texture a texture locked by SDL_LockTexture() + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LockTexture */ extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture * texture); /** - * \brief Determines whether a window supports the use of render targets + * Determine whether a renderer supports the use of render targets. * - * \param renderer The renderer that will be checked + * \param renderer the renderer that will be checked + * \returns SDL_TRUE if supported or SDL_FALSE if not. * - * \return SDL_TRUE if supported, SDL_FALSE if not. + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetRenderTarget */ extern DECLSPEC SDL_bool SDLCALL SDL_RenderTargetSupported(SDL_Renderer *renderer); /** - * \brief Set a texture as the current rendering target. + * Set a texture as the current rendering target. * - * \param texture The targeted texture, which must be created with the SDL_TEXTUREACCESS_TARGET flag, or NULL for the default render target + * Before using this function, you should check the + * `SDL_RENDERER_TARGETTEXTURE` bit in the flags of SDL_RendererInfo to see if + * render targets are supported. * - * \return 0 on success, or -1 on error + * The default render target is the window for which the renderer was created. + * To stop rendering to a texture and render to the window again, call this + * function with a NULL `texture`. * - * \sa SDL_GetRenderTarget() + * \param renderer the rendering context + * \param texture the targeted texture, which must be created with the + * `SDL_TEXTUREACCESS_TARGET` flag, or NULL to render to the + * window instead of a texture. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRenderTarget */ extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture); /** - * \brief Get the current render target or NULL for the default render target. + * Get the current render target. * - * \return The current render target + * The default render target is the window for which the renderer was created, + * and is reported a NULL here. * - * \sa SDL_SetRenderTarget() + * \param renderer the rendering context + * \returns the current render target or NULL for the default render target. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetRenderTarget */ extern DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer); /** - * \brief Set device independent resolution for rendering + * Set a device independent resolution for rendering. * - * \param w The width of the logical resolution - * \param h The height of the logical resolution + * This function uses the viewport and scaling functionality to allow a fixed + * logical resolution for rendering, regardless of the actual output + * resolution. If the actual output resolution doesn't have the same aspect + * ratio the output rendering will be centered within the output display. * - * This function uses the viewport and scaling functionality to allow a fixed logical - * resolution for rendering, regardless of the actual output resolution. If the actual - * output resolution doesn't have the same aspect ratio the output rendering will be - * centered within the output display. + * If the output display is a window, mouse and touch events in the window + * will be filtered and scaled so they seem to arrive within the logical + * resolution. The SDL_HINT_MOUSE_RELATIVE_SCALING hint controls whether + * relative motion events are also scaled. * - * If the output display is a window, mouse events in the window will be filtered - * and scaled so they seem to arrive within the logical resolution. + * If this function results in scaling or subpixel drawing by the rendering + * backend, it will be handled using the appropriate quality hints. * - * \note If this function results in scaling or subpixel drawing by the - * rendering backend, it will be handled using the appropriate - * quality hints. + * \param renderer the renderer for which resolution should be set + * \param w the width of the logical resolution + * \param h the height of the logical resolution + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * - * \sa SDL_RenderGetLogicalSize() - * \sa SDL_RenderSetScale() - * \sa SDL_RenderSetViewport() + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderGetLogicalSize */ extern DECLSPEC int SDLCALL SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h); /** - * \brief Get device independent resolution for rendering + * Get device independent resolution for rendering. * - * \param w A pointer filled with the width of the logical resolution - * \param h A pointer filled with the height of the logical resolution + * This may return 0 for `w` and `h` if the SDL_Renderer has never had its + * logical size set by SDL_RenderSetLogicalSize() and never had a render + * target set. * - * \sa SDL_RenderSetLogicalSize() + * \param renderer a rendering context + * \param w an int to be filled with the width + * \param h an int to be filled with the height + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderSetLogicalSize */ -extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *y); +extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h); /** - * \brief Set the drawing area for rendering on the current target. + * Set whether to force integer scales for resolution-independent rendering. * - * \param rect The rectangle representing the drawing area, or NULL to set the viewport to the entire target. + * This function restricts the logical viewport to integer values - that is, + * when a resolution is between two multiples of a logical size, the viewport + * size is rounded down to the lower multiple. * - * The x,y of the viewport rect represents the origin for rendering. + * \param renderer the renderer for which integer scaling should be set + * \param enable enable or disable the integer scaling for rendering + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * - * \note When the window is resized, the current viewport is automatically - * centered within the new window size. + * \since This function is available since SDL 2.0.5. * - * \sa SDL_RenderGetViewport() - * \sa SDL_RenderSetLogicalSize() + * \sa SDL_RenderGetIntegerScale + * \sa SDL_RenderSetLogicalSize + */ +extern DECLSPEC int SDLCALL SDL_RenderSetIntegerScale(SDL_Renderer * renderer, + SDL_bool enable); + +/** + * Get whether integer scales are forced for resolution-independent rendering. + * + * \param renderer the renderer from which integer scaling should be queried + * \returns SDL_TRUE if integer scales are forced or SDL_FALSE if not and on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_RenderSetIntegerScale + */ +extern DECLSPEC SDL_bool SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer); + +/** + * Set the drawing area for rendering on the current target. + * + * When the window is resized, the viewport is reset to fill the entire new + * window size. + * + * \param renderer the rendering context + * \param rect the SDL_Rect structure representing the drawing area, or NULL + * to set the viewport to the entire target + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderGetViewport */ extern DECLSPEC int SDLCALL SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect); /** - * \brief Get the drawing area for the current target. + * Get the drawing area for the current target. * - * \sa SDL_RenderSetViewport() + * \param renderer the rendering context + * \param rect an SDL_Rect structure filled in with the current drawing area + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderSetViewport */ extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer, SDL_Rect * rect); /** - * \brief Set the drawing scale for rendering on the current target. + * Set the clip rectangle for rendering on the specified target. * - * \param scaleX The horizontal scaling factor - * \param scaleY The vertical scaling factor + * \param renderer the rendering context for which clip rectangle should be + * set + * \param rect an SDL_Rect structure representing the clip area, relative to + * the viewport, or NULL to disable clipping + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * - * The drawing coordinates are scaled by the x/y scaling factors - * before they are used by the renderer. This allows resolution - * independent drawing with a single coordinate system. + * \since This function is available since SDL 2.0.0. * - * \note If this results in scaling or subpixel drawing by the - * rendering backend, it will be handled using the appropriate - * quality hints. For best results use integer scaling factors. + * \sa SDL_RenderGetClipRect + * \sa SDL_RenderIsClipEnabled + */ +extern DECLSPEC int SDLCALL SDL_RenderSetClipRect(SDL_Renderer * renderer, + const SDL_Rect * rect); + +/** + * Get the clip rectangle for the current target. * - * \sa SDL_RenderGetScale() - * \sa SDL_RenderSetLogicalSize() + * \param renderer the rendering context from which clip rectangle should be + * queried + * \param rect an SDL_Rect structure filled in with the current clipping area + * or an empty rectangle if clipping is disabled + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderIsClipEnabled + * \sa SDL_RenderSetClipRect + */ +extern DECLSPEC void SDLCALL SDL_RenderGetClipRect(SDL_Renderer * renderer, + SDL_Rect * rect); + +/** + * Get whether clipping is enabled on the given renderer. + * + * \param renderer the renderer from which clip state should be queried + * \returns SDL_TRUE if clipping is enabled or SDL_FALSE if not; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_RenderGetClipRect + * \sa SDL_RenderSetClipRect + */ +extern DECLSPEC SDL_bool SDLCALL SDL_RenderIsClipEnabled(SDL_Renderer * renderer); + + +/** + * Set the drawing scale for rendering on the current target. + * + * The drawing coordinates are scaled by the x/y scaling factors before they + * are used by the renderer. This allows resolution independent drawing with a + * single coordinate system. + * + * If this results in scaling or subpixel drawing by the rendering backend, it + * will be handled using the appropriate quality hints. For best results use + * integer scaling factors. + * + * \param renderer a rendering context + * \param scaleX the horizontal scaling factor + * \param scaleY the vertical scaling factor + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderGetScale + * \sa SDL_RenderSetLogicalSize */ extern DECLSPEC int SDLCALL SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY); /** - * \brief Get the drawing scale for the current target. + * Get the drawing scale for the current target. * - * \param scaleX A pointer filled in with the horizontal scaling factor - * \param scaleY A pointer filled in with the vertical scaling factor + * \param renderer the renderer from which drawing scale should be queried + * \param scaleX a pointer filled in with the horizontal scaling factor + * \param scaleY a pointer filled in with the vertical scaling factor * - * \sa SDL_RenderSetScale() + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderSetScale */ extern DECLSPEC void SDLCALL SDL_RenderGetScale(SDL_Renderer * renderer, float *scaleX, float *scaleY); /** - * \brief Set the color used for drawing operations (Rect, Line and Clear). - * - * \param r The red value used to draw on the rendering target. - * \param g The green value used to draw on the rendering target. - * \param b The blue value used to draw on the rendering target. - * \param a The alpha value used to draw on the rendering target, usually - * ::SDL_ALPHA_OPAQUE (255). - * - * \return 0 on success, or -1 on error + * Get logical coordinates of point in renderer when given real coordinates of + * point in window. + * + * Logical coordinates will differ from real coordinates when render is scaled + * and logical renderer size set + * + * \param renderer the renderer from which the logical coordinates should be + * calcualted + * \param windowX the real X coordinate in the window + * \param windowY the real Y coordinate in the window + * \param logicalX the pointer filled with the logical x coordinate + * \param logicalY the pointer filled with the logical y coordinate + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_RenderGetScale + * \sa SDL_RenderSetScale + * \sa SDL_RenderGetLogicalSize + * \sa SDL_RenderSetLogicalSize */ -extern DECLSPEC int SDL_SetRenderDrawColor(SDL_Renderer * renderer, +extern DECLSPEC void SDLCALL SDL_RenderWindowToLogical(SDL_Renderer * renderer, + int windowX, int windowY, + float *logicalX, float *logicalY); + + /** + * Get real coordinates of point in window when given logical coordinates of point in renderer. + * Logical coordinates will differ from real coordinates when render is scaled and logical renderer size set + * + * \param renderer the renderer from which the window coordinates should be calculated + * \param logicalX the logical x coordinate + * \param logicalY the logical y coordinate + * \param windowX the pointer filled with the real X coordinate in the window + * \param windowY the pointer filled with the real Y coordinate in the window + + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_RenderGetScale + * \sa SDL_RenderSetScale + * \sa SDL_RenderGetLogicalSize + * \sa SDL_RenderSetLogicalSize + */ +extern DECLSPEC void SDLCALL SDL_RenderLogicalToWindow(SDL_Renderer * renderer, + float logicalX, float logicalY, + int *windowX, int *windowY); + +/** + * Set the color used for drawing operations (Rect, Line and Clear). + * + * Set the color for drawing or filling rectangles, lines, and points, and for + * SDL_RenderClear(). + * + * \param renderer the rendering context + * \param r the red value used to draw on the rendering target + * \param g the green value used to draw on the rendering target + * \param b the blue value used to draw on the rendering target + * \param a the alpha value used to draw on the rendering target; usually + * `SDL_ALPHA_OPAQUE` (255). Use SDL_SetRenderDrawBlendMode to + * specify how the alpha channel is used + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRenderDrawColor + * \sa SDL_RenderClear + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + */ +extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /** - * \brief Get the color used for drawing operations (Rect, Line and Clear). - * - * \param r A pointer to the red value used to draw on the rendering target. - * \param g A pointer to the green value used to draw on the rendering target. - * \param b A pointer to the blue value used to draw on the rendering target. - * \param a A pointer to the alpha value used to draw on the rendering target, - * usually ::SDL_ALPHA_OPAQUE (255). - * - * \return 0 on success, or -1 on error + * Get the color used for drawing operations (Rect, Line and Clear). + * + * \param renderer the rendering context + * \param r a pointer filled in with the red value used to draw on the + * rendering target + * \param g a pointer filled in with the green value used to draw on the + * rendering target + * \param b a pointer filled in with the blue value used to draw on the + * rendering target + * \param a a pointer filled in with the alpha value used to draw on the + * rendering target; usually `SDL_ALPHA_OPAQUE` (255) + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetRenderDrawColor */ -extern DECLSPEC int SDL_GetRenderDrawColor(SDL_Renderer * renderer, +extern DECLSPEC int SDLCALL SDL_GetRenderDrawColor(SDL_Renderer * renderer, Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a); /** - * \brief Set the blend mode used for drawing operations (Fill and Line). - * - * \param blendMode ::SDL_BlendMode to use for blending. - * - * \return 0 on success, or -1 on error - * - * \note If the blend mode is not supported, the closest supported mode is - * chosen. - * - * \sa SDL_GetRenderDrawBlendMode() + * Set the blend mode used for drawing operations (Fill and Line). + * + * If the blend mode is not supported, the closest supported mode is chosen. + * + * \param renderer the rendering context + * \param blendMode the SDL_BlendMode to use for blending + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRenderDrawBlendMode + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects */ extern DECLSPEC int SDLCALL SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode); /** - * \brief Get the blend mode used for drawing operations. - * - * \param blendMode A pointer filled in with the current blend mode. - * - * \return 0 on success, or -1 on error - * - * \sa SDL_SetRenderDrawBlendMode() + * Get the blend mode used for drawing operations. + * + * \param renderer the rendering context + * \param blendMode a pointer filled in with the current SDL_BlendMode + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetRenderDrawBlendMode */ extern DECLSPEC int SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode *blendMode); /** - * \brief Clear the current rendering target with the drawing color + * Clear the current rendering target with the drawing color. * - * This function clears the entire rendering target, ignoring the viewport. + * This function clears the entire rendering target, ignoring the viewport and + * the clip rectangle. + * + * \param renderer the rendering context + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer); /** - * \brief Draw a point on the current rendering target. - * - * \param x The x coordinate of the point. - * \param y The y coordinate of the point. - * - * \return 0 on success, or -1 on error + * Draw a point on the current rendering target. + * + * SDL_RenderDrawPoint() draws a single point. If you want to draw multiple, + * use SDL_RenderDrawPoints() instead. + * + * \param renderer the rendering context + * \param x the x coordinate of the point + * \param y the y coordinate of the point + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y); /** - * \brief Draw multiple points on the current rendering target. - * - * \param points The points to draw - * \param count The number of points to draw - * - * \return 0 on success, or -1 on error + * Draw multiple points on the current rendering target. + * + * \param renderer the rendering context + * \param points an array of SDL_Point structures that represent the points to + * draw + * \param count the number of points to draw + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, int count); /** - * \brief Draw a line on the current rendering target. - * - * \param x1 The x coordinate of the start point. - * \param y1 The y coordinate of the start point. - * \param x2 The x coordinate of the end point. - * \param y2 The y coordinate of the end point. - * - * \return 0 on success, or -1 on error + * Draw a line on the current rendering target. + * + * SDL_RenderDrawLine() draws the line to include both end points. If you want + * to draw multiple, connecting lines use SDL_RenderDrawLines() instead. + * + * \param renderer the rendering context + * \param x1 the x coordinate of the start point + * \param y1 the y coordinate of the start point + * \param x2 the x coordinate of the end point + * \param y2 the y coordinate of the end point + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2); /** - * \brief Draw a series of connected lines on the current rendering target. - * - * \param points The points along the lines - * \param count The number of points, drawing count-1 lines - * - * \return 0 on success, or -1 on error + * Draw a series of connected lines on the current rendering target. + * + * \param renderer the rendering context + * \param points an array of SDL_Point structures representing points along + * the lines + * \param count the number of points, drawing count-1 lines + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, int count); /** - * \brief Draw a rectangle on the current rendering target. - * - * \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target. - * - * \return 0 on success, or -1 on error + * Draw a rectangle on the current rendering target. + * + * \param renderer the rendering context + * \param rect an SDL_Rect structure representing the rectangle to draw, or + * NULL to outline the entire rendering target + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect); /** - * \brief Draw some number of rectangles on the current rendering target. - * - * \param rects A pointer to an array of destination rectangles. - * \param count The number of rectangles. - * - * \return 0 on success, or -1 on error + * Draw some number of rectangles on the current rendering target. + * + * \param renderer the rendering context + * \param rects an array of SDL_Rect structures representing the rectangles to + * be drawn + * \param count the number of rectangles + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count); /** - * \brief Fill a rectangle on the current rendering target with the drawing color. - * - * \param rect A pointer to the destination rectangle, or NULL for the entire - * rendering target. - * - * \return 0 on success, or -1 on error + * Fill a rectangle on the current rendering target with the drawing color. + * + * The current drawing color is set by SDL_SetRenderDrawColor(), and the + * color's alpha value is ignored unless blending is enabled with the + * appropriate call to SDL_SetRenderDrawBlendMode(). + * + * \param renderer the rendering context + * \param rect the SDL_Rect structure representing the rectangle to fill, or + * NULL for the entire rendering target + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRects + * \sa SDL_RenderPresent + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC int SDLCALL SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect); /** - * \brief Fill some number of rectangles on the current rendering target with the drawing color. - * - * \param rects A pointer to an array of destination rectangles. - * \param count The number of rectangles. - * - * \return 0 on success, or -1 on error + * Fill some number of rectangles on the current rendering target with the + * drawing color. + * + * \param renderer the rendering context + * \param rects an array of SDL_Rect structures representing the rectangles to + * be filled + * \param count the number of rectangles + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderPresent */ extern DECLSPEC int SDLCALL SDL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count); /** - * \brief Copy a portion of the texture to the current rendering target. - * - * \param texture The source texture. - * \param srcrect A pointer to the source rectangle, or NULL for the entire - * texture. - * \param dstrect A pointer to the destination rectangle, or NULL for the - * entire rendering target. - * - * \return 0 on success, or -1 on error + * Copy a portion of the texture to the current rendering target. + * + * The texture is blended with the destination based on its blend mode set + * with SDL_SetTextureBlendMode(). + * + * The texture color is affected based on its color modulation set by + * SDL_SetTextureColorMod(). + * + * The texture alpha is affected based on its alpha modulation set by + * SDL_SetTextureAlphaMod(). + * + * \param renderer the rendering context + * \param texture the source texture + * \param srcrect the source SDL_Rect structure or NULL for the entire texture + * \param dstrect the destination SDL_Rect structure or NULL for the entire + * rendering target; the texture will be stretched to fill the + * given rectangle + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderCopyEx + * \sa SDL_SetTextureAlphaMod + * \sa SDL_SetTextureBlendMode + * \sa SDL_SetTextureColorMod */ extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, @@ -691,18 +1389,43 @@ extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer, const SDL_Rect * dstrect); /** - * \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center + * Copy a portion of the texture to the current rendering, with optional + * rotation and flipping. * - * \param texture The source texture. - * \param srcrect A pointer to the source rectangle, or NULL for the entire - * texture. - * \param dstrect A pointer to the destination rectangle, or NULL for the - * entire rendering target. - * \param angle An angle in degrees that indicates the rotation that will be applied to dstrect - * \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done aroud dstrect.w/2, dstrect.h/2) - * \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture - * - * \return 0 on success, or -1 on error + * Copy a portion of the texture to the current rendering target, optionally + * rotating it by angle around the given center and also flipping it + * top-bottom and/or left-right. + * + * The texture is blended with the destination based on its blend mode set + * with SDL_SetTextureBlendMode(). + * + * The texture color is affected based on its color modulation set by + * SDL_SetTextureColorMod(). + * + * The texture alpha is affected based on its alpha modulation set by + * SDL_SetTextureAlphaMod(). + * + * \param renderer the rendering context + * \param texture the source texture + * \param srcrect the source SDL_Rect structure or NULL for the entire texture + * \param dstrect the destination SDL_Rect structure or NULL for the entire + * rendering target + * \param angle an angle in degrees that indicates the rotation that will be + * applied to dstrect, rotating it in a clockwise direction + * \param center a pointer to a point indicating the point around which + * dstrect will be rotated (if NULL, rotation will be done + * around `dstrect.w / 2`, `dstrect.h / 2`) + * \param flip a SDL_RendererFlip value stating which flipping actions should + * be performed on the texture + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderCopy + * \sa SDL_SetTextureAlphaMod + * \sa SDL_SetTextureBlendMode + * \sa SDL_SetTextureColorMod */ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, @@ -712,19 +1435,249 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, const SDL_Point *center, const SDL_RendererFlip flip); + /** - * \brief Read pixels from the current rendering target. - * - * \param rect A pointer to the rectangle to read, or NULL for the entire - * render target. - * \param format The desired format of the pixel data, or 0 to use the format - * of the rendering target - * \param pixels A pointer to be filled in with the pixel data - * \param pitch The pitch of the pixels parameter. - * - * \return 0 on success, or -1 if pixel reading is not supported. - * - * \warning This is a very slow operation, and should not be used frequently. + * Draw a point on the current rendering target at subpixel precision. + * + * \param renderer The renderer which should draw a point. + * \param x The x coordinate of the point. + * \param y The y coordinate of the point. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer, + float x, float y); + +/** + * Draw multiple points on the current rendering target at subpixel precision. + * + * \param renderer The renderer which should draw multiple points. + * \param points The points to draw + * \param count The number of points to draw + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * Draw a line on the current rendering target at subpixel precision. + * + * \param renderer The renderer which should draw a line. + * \param x1 The x coordinate of the start point. + * \param y1 The y coordinate of the start point. + * \param x2 The x coordinate of the end point. + * \param y2 The y coordinate of the end point. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer, + float x1, float y1, float x2, float y2); + +/** + * Draw a series of connected lines on the current rendering target at + * subpixel precision. + * + * \param renderer The renderer which should draw multiple lines. + * \param points The points along the lines + * \param count The number of points, drawing count-1 lines + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * Draw a rectangle on the current rendering target at subpixel precision. + * + * \param renderer The renderer which should draw a rectangle. + * \param rect A pointer to the destination rectangle, or NULL to outline the + * entire rendering target. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * Draw some number of rectangles on the current rendering target at subpixel + * precision. + * + * \param renderer The renderer which should draw multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * Fill a rectangle on the current rendering target with the drawing color at + * subpixel precision. + * + * \param renderer The renderer which should fill a rectangle. + * \param rect A pointer to the destination rectangle, or NULL for the entire + * rendering target. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * Fill some number of rectangles on the current rendering target with the + * drawing color at subpixel precision. + * + * \param renderer The renderer which should fill multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * Copy a portion of the texture to the current rendering target at subpixel + * precision. + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect); + +/** + * Copy a portion of the source texture to the current rendering target, with + * rotation and flipping, at subpixel precision. + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \param angle An angle in degrees that indicates the rotation that will be + * applied to dstrect, rotating it in a clockwise direction + * \param center A pointer to a point indicating the point around which + * dstrect will be rotated (if NULL, rotation will be done + * around dstrect.w/2, dstrect.h/2). + * \param flip An SDL_RendererFlip value stating which flipping actions should + * be performed on the texture + * \return 0 on success, or -1 on error + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect, + const double angle, + const SDL_FPoint *center, + const SDL_RendererFlip flip); + +/** + * Render a list of triangles, optionally using a texture and indices into the + * vertex array Color and alpha modulation is done per vertex + * (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored). + * + * \param texture (optional) The SDL texture to use. + * \param vertices Vertices. + * \param num_vertices Number of vertices. + * \param indices (optional) An array of integer indices into the 'vertices' + * array, if NULL all vertices will be rendered in sequential + * order. + * \param num_indices Number of indices. + * \return 0 on success, or -1 if the operation is not supported + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_RenderGeometryRaw + * \sa SDL_Vertex + */ +extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, + SDL_Texture *texture, + const SDL_Vertex *vertices, int num_vertices, + const int *indices, int num_indices); + +/** + * Render a list of triangles, optionally using a texture and indices into the + * vertex arrays Color and alpha modulation is done per vertex + * (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored). + * + * \param texture (optional) The SDL texture to use. + * \param xy Vertex positions + * \param xy_stride Byte size to move from one element to the next element + * \param color Vertex colors (as SDL_Color) + * \param color_stride Byte size to move from one element to the next element + * \param uv Vertex normalized texture coordinates + * \param uv_stride Byte size to move from one element to the next element + * \param num_vertices Number of vertices. + * \param indices (optional) An array of indices into the 'vertices' arrays, + * if NULL all vertices will be rendered in sequential order. + * \param num_indices Number of indices. + * \param size_indices Index size: 1 (byte), 2 (short), 4 (int) + * \return 0 on success, or -1 if the operation is not supported + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_RenderGeometry + * \sa SDL_Vertex + */ +extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, + SDL_Texture *texture, + const float *xy, int xy_stride, + const SDL_Color *color, int color_stride, + const float *uv, int uv_stride, + int num_vertices, + const void *indices, int num_indices, int size_indices); + +/** + * Read pixels from the current rendering target to an array of pixels. + * + * **WARNING**: This is a very slow operation, and should not be used + * frequently. + * + * `pitch` specifies the number of bytes between rows in the destination + * `pixels` data. This allows you to write to a subrectangle or have padded + * rows in the destination. Generally, `pitch` should equal the number of + * pixels per row in the `pixels` data times the number of bytes per pixel, + * but it might contain additional padding (for example, 24bit RGB Windows + * Bitmap data pads all rows to multiples of 4 bytes). + * + * \param renderer the rendering context + * \param rect an SDL_Rect structure representing the area to read, or NULL + * for the entire render target + * \param format an SDL_PixelFormatEnum value of the desired format of the + * pixel data, or 0 to use the format of the rendering target + * \param pixels a pointer to the pixel data to copy into + * \param pitch the pitch of the `pixels` parameter + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, @@ -732,57 +1685,206 @@ extern DECLSPEC int SDLCALL SDL_RenderReadPixels(SDL_Renderer * renderer, void *pixels, int pitch); /** - * \brief Update the screen with rendering performed. + * Update the screen with any rendering performed since the previous call. + * + * SDL's rendering functions operate on a backbuffer; that is, calling a + * rendering function such as SDL_RenderDrawLine() does not directly put a + * line on the screen, but rather updates the backbuffer. As such, you compose + * your entire scene and *present* the composed backbuffer to the screen as a + * complete picture. + * + * Therefore, when using SDL's rendering API, one does all drawing intended + * for the frame, and then calls this function once per frame to present the + * final drawing to the user. + * + * The backbuffer should be considered invalidated after each present; do not + * assume that previous contents will exist between frames. You are strongly + * encouraged to call SDL_RenderClear() to initialize the backbuffer before + * starting each new frame's drawing, even if you plan to overwrite every + * pixel. + * + * \param renderer the rendering context + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RenderClear + * \sa SDL_RenderDrawLine + * \sa SDL_RenderDrawLines + * \sa SDL_RenderDrawPoint + * \sa SDL_RenderDrawPoints + * \sa SDL_RenderDrawRect + * \sa SDL_RenderDrawRects + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects + * \sa SDL_SetRenderDrawBlendMode + * \sa SDL_SetRenderDrawColor */ extern DECLSPEC void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer); /** - * \brief Destroy the specified texture. - * - * \sa SDL_CreateTexture() - * \sa SDL_CreateTextureFromSurface() + * Destroy the specified texture. + * + * Passing NULL or an otherwise invalid texture will set the SDL error message + * to "Invalid texture". + * + * \param texture the texture to destroy + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateTexture + * \sa SDL_CreateTextureFromSurface */ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture); /** - * \brief Destroy the rendering context for a window and free associated - * textures. - * - * \sa SDL_CreateRenderer() + * Destroy the rendering context for a window and free associated textures. + * + * \param renderer the rendering context + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRenderer */ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer); +/** + * Force the rendering context to flush any pending commands to the underlying + * rendering API. + * + * You do not need to (and in fact, shouldn't) call this function unless you + * are planning to call into OpenGL/Direct3D/Metal/whatever directly in + * addition to using an SDL_Renderer. + * + * This is for a very-specific case: if you are using SDL's render API, you + * asked for a specific renderer backend (OpenGL, Direct3D, etc), you set + * SDL_HINT_RENDER_BATCHING to "1", and you plan to make OpenGL/D3D/whatever + * calls in addition to SDL render API calls. If all of this applies, you + * should call SDL_RenderFlush() between calls to SDL's render API and the + * low-level API you're using in cooperation. + * + * In all other cases, you can ignore this function. This is only here to get + * maximum performance out of a specific situation. In all other cases, SDL + * will do the right thing, perhaps at a performance loss. + * + * This function is first available in SDL 2.0.10, and is not needed in 2.0.9 + * and earlier, as earlier versions did not queue rendering commands at all, + * instead flushing them to the OS immediately. + * + * \param renderer the rendering context + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer); + /** - * \brief Bind the texture to the current OpenGL/ES/ES2 context for use with - * OpenGL instructions. + * Bind an OpenGL/ES/ES2 texture to the current context. * - * \param texture The SDL texture to bind - * \param texw A pointer to a float that will be filled with the texture width - * \param texh A pointer to a float that will be filled with the texture height + * This is for use with OpenGL instructions when rendering OpenGL primitives + * directly. * - * \return 0 on success, or -1 if the operation is not supported + * If not NULL, `texw` and `texh` will be filled with the width and height + * values suitable for the provided texture. In most cases, both will be 1.0, + * however, on systems that support the GL_ARB_texture_rectangle extension, + * these values will actually be the pixel width and height used to create the + * texture, so this factor needs to be taken into account when providing + * texture coordinates to OpenGL. + * + * You need a renderer to create an SDL_Texture, therefore you can only use + * this function with an implicit OpenGL context from SDL_CreateRenderer(), + * not with your own OpenGL context. If you need control over your OpenGL + * context, you need to write your own texture-loading methods. + * + * Also note that SDL may upload RGB textures as BGR (or vice-versa), and + * re-order the color channels in the shaders phase, so the uploaded texture + * may have swapped color channels. + * + * \param texture the texture to bind to the current OpenGL/ES/ES2 context + * \param texw a pointer to a float value which will be filled with the + * texture width or NULL if you don't need that value + * \param texh a pointer to a float value which will be filled with the + * texture height or NULL if you don't need that value + * \returns 0 on success, or -1 if the operation is not supported; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_MakeCurrent + * \sa SDL_GL_UnbindTexture */ extern DECLSPEC int SDLCALL SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh); /** - * \brief Unbind a texture from the current OpenGL/ES/ES2 context. + * Unbind an OpenGL/ES/ES2 texture from the current context. * - * \param texture The SDL texture to unbind + * See SDL_GL_BindTexture() for examples on how to use these functions * - * \return 0 on success, or -1 if the operation is not supported + * \param texture the texture to unbind from the current OpenGL/ES/ES2 context + * \returns 0 on success, or -1 if the operation is not supported + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_BindTexture + * \sa SDL_GL_MakeCurrent */ extern DECLSPEC int SDLCALL SDL_GL_UnbindTexture(SDL_Texture *texture); +/** + * Get the CAMetalLayer associated with the given Metal renderer. + * + * This function returns `void *`, so SDL doesn't have to include Metal's + * headers, but it can be safely cast to a `CAMetalLayer *`. + * + * \param renderer The renderer to query + * \returns a `CAMetalLayer *` on success, or NULL if the renderer isn't a + * Metal renderer + * + * \since This function is available since SDL 2.0.8. + * + * \sa SDL_RenderGetMetalCommandEncoder + */ +extern DECLSPEC void *SDLCALL SDL_RenderGetMetalLayer(SDL_Renderer * renderer); + +/** + * Get the Metal command encoder for the current frame + * + * This function returns `void *`, so SDL doesn't have to include Metal's + * headers, but it can be safely cast to an `id`. + * + * Note that as of SDL 2.0.18, this will return NULL if Metal refuses to give + * SDL a drawable to render to, which might happen if the window is + * hidden/minimized/offscreen. This doesn't apply to command encoders for + * render targets, just the window's backbacker. Check your return values! + * + * \param renderer The renderer to query + * \returns an `id` on success, or NULL if the + * renderer isn't a Metal renderer or there was an error. + * + * \since This function is available since SDL 2.0.8. + * + * \sa SDL_RenderGetMetalLayer + */ +extern DECLSPEC void *SDLCALL SDL_RenderGetMetalCommandEncoder(SDL_Renderer * renderer); + +/** + * Toggle VSync of the given renderer. + * + * \param renderer The renderer to toggle + * \param vsync 1 for on, 0 for off. All other values are reserved + * \returns a 0 int on success, or non-zero on failure + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_RenderSetVSync(SDL_Renderer* renderer, int vsync); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_render_h */ +#endif /* SDL_render_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_revision.h b/external/SDL2/SDL_revision.h index d70fd69..3253d6d 100644 --- a/external/SDL2/SDL_revision.h +++ b/external/SDL2/SDL_revision.h @@ -1,2 +1,2 @@ -#define SDL_REVISION "hg-0:aaaaaaaaaaah" +#define SDL_REVISION "https://github.com/libsdl-org/SDL.git@b424665e0899769b200231ba943353a5fee1b6b6" #define SDL_REVISION_NUMBER 0 diff --git a/external/SDL2/SDL_rwops.h b/external/SDL2/SDL_rwops.h index 61c3092..71e5c8d 100644 --- a/external/SDL2/SDL_rwops.h +++ b/external/SDL2/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,13 +21,13 @@ /** * \file SDL_rwops.h - * + * * This file provides a general interface for SDL to read and write * data streams. It can easily be extended to files, memory, etc. */ -#ifndef _SDL_rwops_h -#define _SDL_rwops_h +#ifndef SDL_rwops_h_ +#define SDL_rwops_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -35,18 +35,19 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* RWops Types */ -#define SDL_RWOPS_UNKNOWN 0 /* Unknown stream type */ -#define SDL_RWOPS_WINFILE 1 /* Win32 file */ -#define SDL_RWOPS_STDFILE 2 /* Stdio file */ -#define SDL_RWOPS_JNIFILE 3 /* Android asset */ -#define SDL_RWOPS_MEMORY 4 /* Memory stream */ -#define SDL_RWOPS_MEMORY_RO 5 /* Read-Only memory stream */ +#define SDL_RWOPS_UNKNOWN 0U /**< Unknown stream type */ +#define SDL_RWOPS_WINFILE 1U /**< Win32 file */ +#define SDL_RWOPS_STDFILE 2U /**< Stdio file */ +#define SDL_RWOPS_JNIFILE 3U /**< Android asset */ +#define SDL_RWOPS_MEMORY 4U /**< Memory stream */ +#define SDL_RWOPS_MEMORY_RO 5U /**< Read-Only memory stream */ +#if defined(__VITA__) +#define SDL_RWOPS_VITAFILE 6U /**< Vita file */ +#endif /** * This is the read/write operation structure -- very basic. @@ -61,7 +62,7 @@ typedef struct SDL_RWops /** * Seek to \c offset relative to \c whence, one of stdio's whence values: * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END - * + * * \return the final offset in the data stream, or -1 on error. */ Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset, @@ -70,7 +71,7 @@ typedef struct SDL_RWops /** * Read up to \c maxnum objects each of size \c size from the data * stream to the area pointed at by \c ptr. - * + * * \return the number of objects read, or 0 at error or end of file. */ size_t (SDLCALL * read) (struct SDL_RWops * context, void *ptr, @@ -79,7 +80,7 @@ typedef struct SDL_RWops /** * Write exactly \c num objects each of size \c size from the area * pointed at by \c ptr to data stream. - * + * * \return the number of objects written, or 0 at error or end of file. */ size_t (SDLCALL * write) (struct SDL_RWops * context, const void *ptr, @@ -87,7 +88,7 @@ typedef struct SDL_RWops /** * Close and free an allocated SDL_RWops structure. - * + * * \return 0 if successful or -1 on write error when flushing data. */ int (SDLCALL * close) (struct SDL_RWops * context); @@ -95,18 +96,10 @@ typedef struct SDL_RWops Uint32 type; union { -#if defined(ANDROID) +#if defined(__ANDROID__) struct { - void *fileNameRef; - void *inputStreamRef; - void *readableByteChannelRef; - void *readMethod; - void *assetFileDescriptorRef; - long position; - long size; - long offset; - int fd; + void *asset; } androidio; #elif defined(__WIN32__) struct @@ -120,6 +113,17 @@ typedef struct SDL_RWops size_t left; } buffer; } windowsio; +#elif defined(__VITA__) + struct + { + int h; + struct + { + void *data; + size_t size; + size_t left; + } buffer; + } vitaio; #endif #ifdef HAVE_STDIO_H @@ -138,6 +142,7 @@ typedef struct SDL_RWops struct { void *data1; + void *data2; } unknown; } hidden; @@ -146,90 +151,705 @@ typedef struct SDL_RWops /** * \name RWFrom functions - * + * * Functions to create SDL_RWops structures from various data streams. */ -/*@{*/ +/* @{ */ +/** + * Use this function to create a new SDL_RWops structure for reading from + * and/or writing to a named file. + * + * The `mode` string is treated roughly the same as in a call to the C + * library's fopen(), even if SDL doesn't happen to use fopen() behind the + * scenes. + * + * Available `mode` strings: + * + * - "r": Open a file for reading. The file must exist. + * - "w": Create an empty file for writing. If a file with the same name + * already exists its content is erased and the file is treated as a new + * empty file. + * - "a": Append to a file. Writing operations append data at the end of the + * file. The file is created if it does not exist. + * - "r+": Open a file for update both reading and writing. The file must + * exist. + * - "w+": Create an empty file for both reading and writing. If a file with + * the same name already exists its content is erased and the file is + * treated as a new empty file. + * - "a+": Open a file for reading and appending. All writing operations are + * performed at the end of the file, protecting the previous content to be + * overwritten. You can reposition (fseek, rewind) the internal pointer to + * anywhere in the file for reading, but writing operations will move it + * back to the end of file. The file is created if it does not exist. + * + * **NOTE**: In order to open a file as a binary file, a "b" character has to + * be included in the `mode` string. This additional "b" character can either + * be appended at the end of the string (thus making the following compound + * modes: "rb", "wb", "ab", "r+b", "w+b", "a+b") or be inserted between the + * letter and the "+" sign for the mixed modes ("rb+", "wb+", "ab+"). + * Additional characters may follow the sequence, although they should have no + * effect. For example, "t" is sometimes appended to make explicit the file is + * a text file. + * + * This function supports Unicode filenames, but they must be encoded in UTF-8 + * format, regardless of the underlying operating system. + * + * As a fallback, SDL_RWFromFile() will transparently open a matching filename + * in an Android app's `assets`. + * + * Closing the SDL_RWops will close the file handle SDL is holding internally. + * + * \param file a UTF-8 string representing the filename to open + * \param mode an ASCII string representing the mode to be used for opening + * the file. + * \returns a pointer to the SDL_RWops structure that is created, or NULL on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWtell + * \sa SDL_RWwrite + */ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file, const char *mode); #ifdef HAVE_STDIO_H -extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(FILE * fp, - SDL_bool autoclose); + +extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(FILE * fp, SDL_bool autoclose); + #else + +/** + * Use this function to create an SDL_RWops structure from a standard I/O file + * pointer (stdio.h's `FILE*`). + * + * This function is not available on Windows, since files opened in an + * application on that platform cannot be used by a dynamically linked + * library. + * + * On some platforms, the first parameter is a `void*`, on others, it's a + * `FILE*`, depending on what system headers are available to SDL. It is + * always intended to be the `FILE*` type from the C runtime's stdio.h. + * + * \param fp the `FILE*` that feeds the SDL_RWops stream + * \param autoclose SDL_TRUE to close the `FILE*` when closing the SDL_RWops, + * SDL_FALSE to leave the `FILE*` open when the RWops is + * closed + * \returns a pointer to the SDL_RWops structure that is created, or NULL on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWtell + * \sa SDL_RWwrite + */ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(void * fp, SDL_bool autoclose); #endif +/** + * Use this function to prepare a read-write memory buffer for use with + * SDL_RWops. + * + * This function sets up an SDL_RWops struct based on a memory area of a + * certain size, for both read and write access. + * + * This memory buffer is not copied by the RWops; the pointer you provide must + * remain valid until you close the stream. Closing the stream will not free + * the original buffer. + * + * If you need to make sure the RWops never writes to the memory buffer, you + * should use SDL_RWFromConstMem() with a read-only buffer of memory instead. + * + * \param mem a pointer to a buffer to feed an SDL_RWops stream + * \param size the buffer size, in bytes + * \returns a pointer to a new SDL_RWops structure, or NULL if it fails; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWtell + * \sa SDL_RWwrite + */ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, int size); + +/** + * Use this function to prepare a read-only memory buffer for use with RWops. + * + * This function sets up an SDL_RWops struct based on a memory area of a + * certain size. It assumes the memory area is not writable. + * + * Attempting to write to this RWops stream will report an error without + * writing to the memory buffer. + * + * This memory buffer is not copied by the RWops; the pointer you provide must + * remain valid until you close the stream. Closing the stream will not free + * the original buffer. + * + * If you need to write to a memory buffer, you should use SDL_RWFromMem() + * with a writable buffer of memory instead. + * + * \param mem a pointer to a read-only buffer to feed an SDL_RWops stream + * \param size the buffer size, in bytes + * \returns a pointer to a new SDL_RWops structure, or NULL if it fails; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWtell + */ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem, int size); -/*@}*//*RWFrom functions*/ +/* @} *//* RWFrom functions */ -extern DECLSPEC SDL_RWops *SDLCALL SDL_AllocRW(void); -extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); - -#define RW_SEEK_SET 0 /**< Seek from the beginning of data */ -#define RW_SEEK_CUR 1 /**< Seek relative to current read point */ -#define RW_SEEK_END 2 /**< Seek relative to the end of data */ - /** - * \name Read/write macros - * - * Macros to easily read and write from an SDL_RWops structure. + * Use this function to allocate an empty, unpopulated SDL_RWops structure. + * + * Applications do not need to use this function unless they are providing + * their own SDL_RWops implementation. If you just need a SDL_RWops to + * read/write a common data source, you should use the built-in + * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc. + * + * You must free the returned pointer with SDL_FreeRW(). Depending on your + * operating system and compiler, there may be a difference between the + * malloc() and free() your program uses and the versions SDL calls + * internally. Trying to mix the two can cause crashing such as segmentation + * faults. Since all SDL_RWops must free themselves when their **close** + * method is called, all SDL_RWops must be allocated through this function, so + * they can all be freed correctly with SDL_FreeRW(). + * + * \returns a pointer to the allocated memory on success, or NULL on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreeRW */ -/*@{*/ -#define SDL_RWsize(ctx) (ctx)->size(ctx) -#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) -#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) -#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) -#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) -#define SDL_RWclose(ctx) (ctx)->close(ctx) -/*@}*//*Read/write macros*/ +extern DECLSPEC SDL_RWops *SDLCALL SDL_AllocRW(void); +/** + * Use this function to free an SDL_RWops structure allocated by + * SDL_AllocRW(). + * + * Applications do not need to use this function unless they are providing + * their own SDL_RWops implementation. If you just need a SDL_RWops to + * read/write a common data source, you should use the built-in + * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc, and + * call the **close** method on those SDL_RWops pointers when you are done + * with them. + * + * Only use SDL_FreeRW() on pointers returned by SDL_AllocRW(). The pointer is + * invalid as soon as this function returns. Any extra memory allocated during + * creation of the SDL_RWops is not freed by SDL_FreeRW(); the programmer must + * be responsible for managing that memory in their **close** method. + * + * \param area the SDL_RWops structure to be freed + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocRW + */ +extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); -/** +#define RW_SEEK_SET 0 /**< Seek from the beginning of data */ +#define RW_SEEK_CUR 1 /**< Seek relative to current read point */ +#define RW_SEEK_END 2 /**< Seek relative to the end of data */ + +/** + * Use this function to get the size of the data stream in an SDL_RWops. + * + * Prior to SDL 2.0.10, this function was a macro. + * + * \param context the SDL_RWops to get the size of the data stream from + * \returns the size of the data stream in the SDL_RWops on success, -1 if + * unknown or a negative error code on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context); + +/** + * Seek within an SDL_RWops data stream. + * + * This function seeks to byte `offset`, relative to `whence`. + * + * `whence` may be any of the following values: + * + * - `RW_SEEK_SET`: seek from the beginning of data + * - `RW_SEEK_CUR`: seek relative to current read point + * - `RW_SEEK_END`: seek relative to the end of data + * + * If this stream can not seek, it will return -1. + * + * SDL_RWseek() is actually a wrapper function that calls the SDL_RWops's + * `seek` method appropriately, to simplify application development. + * + * Prior to SDL 2.0.10, this function was a macro. + * + * \param context a pointer to an SDL_RWops structure + * \param offset an offset in bytes, relative to **whence** location; can be + * negative + * \param whence any of `RW_SEEK_SET`, `RW_SEEK_CUR`, `RW_SEEK_END` + * \returns the final offset in the data stream after the seek or -1 on error. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWtell + * \sa SDL_RWwrite + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, + Sint64 offset, int whence); + +/** + * Determine the current read/write offset in an SDL_RWops data stream. + * + * SDL_RWtell is actually a wrapper function that calls the SDL_RWops's `seek` + * method, with an offset of 0 bytes from `RW_SEEK_CUR`, to simplify + * application development. + * + * Prior to SDL 2.0.10, this function was a macro. + * + * \param context a SDL_RWops data stream object from which to get the current + * offset + * \returns the current offset in the stream, or -1 if the information can not + * be determined. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWwrite + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context); + +/** + * Read from a data source. + * + * This function reads up to `maxnum` objects each of size `size` from the + * data source to the area pointed at by `ptr`. This function may read less + * objects than requested. It will return zero when there has been an error or + * the data stream is completely read. + * + * SDL_RWread() is actually a function wrapper that calls the SDL_RWops's + * `read` method appropriately, to simplify application development. + * + * Prior to SDL 2.0.10, this function was a macro. + * + * \param context a pointer to an SDL_RWops structure + * \param ptr a pointer to a buffer to read data into + * \param size the size of each object to read, in bytes + * \param maxnum the maximum number of objects to be read + * \returns the number of objects read, or 0 at error or end of file; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWseek + * \sa SDL_RWwrite + */ +extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, + void *ptr, size_t size, + size_t maxnum); + +/** + * Write to an SDL_RWops data stream. + * + * This function writes exactly `num` objects each of size `size` from the + * area pointed at by `ptr` to the stream. If this fails for any reason, it'll + * return less than `num` to demonstrate how far the write progressed. On + * success, it returns `num`. + * + * SDL_RWwrite is actually a function wrapper that calls the SDL_RWops's + * `write` method appropriately, to simplify application development. + * + * Prior to SDL 2.0.10, this function was a macro. + * + * \param context a pointer to an SDL_RWops structure + * \param ptr a pointer to a buffer containing data to write + * \param size the size of an object to write, in bytes + * \param num the number of objects to write + * \returns the number of objects written, which will be less than **num** on + * error; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_RWclose + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + */ +extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, + const void *ptr, size_t size, + size_t num); + +/** + * Close and free an allocated SDL_RWops structure. + * + * SDL_RWclose() closes and cleans up the SDL_RWops stream. It releases any + * resources used by the stream and frees the SDL_RWops itself with + * SDL_FreeRW(). This returns 0 on success, or -1 if the stream failed to + * flush to its output (e.g. to disk). + * + * Note that if this fails to flush the stream to disk, this function reports + * an error, but the SDL_RWops is still invalid once this function returns. + * + * Prior to SDL 2.0.10, this function was a macro. + * + * \param context SDL_RWops structure to close + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.10. + * + * \sa SDL_RWFromConstMem + * \sa SDL_RWFromFile + * \sa SDL_RWFromFP + * \sa SDL_RWFromMem + * \sa SDL_RWread + * \sa SDL_RWseek + * \sa SDL_RWwrite + */ +extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context); + +/** + * Load all the data from an SDL data stream. + * + * The data is allocated with a zero byte at the end (null terminated) for + * convenience. This extra byte is not included in the value reported via + * `datasize`. + * + * The data should be freed with SDL_free(). + * + * \param src the SDL_RWops to read all available data from + * \param datasize if not NULL, will store the number of bytes read + * \param freesrc if non-zero, calls SDL_RWclose() on `src` before returning + * \returns the data, or NULL if there was an error. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src, + size_t *datasize, + int freesrc); + +/** + * Load all the data from a file path. + * + * The data is allocated with a zero byte at the end (null terminated) for + * convenience. This extra byte is not included in the value reported via + * `datasize`. + * + * The data should be freed with SDL_free(). + * + * Prior to SDL 2.0.10, this function was a macro wrapping around + * SDL_LoadFile_RW. + * + * \param file the path to read all available data from + * \param datasize if not NULL, will store the number of bytes read + * \returns the data, or NULL if there was an error. + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); + +/** * \name Read endian functions - * + * * Read an item of the specified endianness and return in native format. */ -/*@{*/ -extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src); -extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src); -extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src); -extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src); -extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src); -extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src); -extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src); -/*@}*//*Read endian functions*/ +/* @{ */ -/** +/** + * Use this function to read a byte from an SDL_RWops. + * + * \param src the SDL_RWops to read from + * \returns the read byte on success or 0 on failure; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteU8 + */ +extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src); + +/** + * Use this function to read 16 bits of little-endian data from an SDL_RWops + * and return in native format. + * + * SDL byteswaps the data only if necessary, so the data returned will be in + * the native byte order. + * + * \param src the stream from which to read data + * \returns 16 bits of data in the native byte order of the platform. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadBE16 + */ +extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src); + +/** + * Use this function to read 16 bits of big-endian data from an SDL_RWops and + * return in native format. + * + * SDL byteswaps the data only if necessary, so the data returned will be in + * the native byte order. + * + * \param src the stream from which to read data + * \returns 16 bits of data in the native byte order of the platform. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadLE16 + */ +extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src); + +/** + * Use this function to read 32 bits of little-endian data from an SDL_RWops + * and return in native format. + * + * SDL byteswaps the data only if necessary, so the data returned will be in + * the native byte order. + * + * \param src the stream from which to read data + * \returns 32 bits of data in the native byte order of the platform. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadBE32 + */ +extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src); + +/** + * Use this function to read 32 bits of big-endian data from an SDL_RWops and + * return in native format. + * + * SDL byteswaps the data only if necessary, so the data returned will be in + * the native byte order. + * + * \param src the stream from which to read data + * \returns 32 bits of data in the native byte order of the platform. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadLE32 + */ +extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src); + +/** + * Use this function to read 64 bits of little-endian data from an SDL_RWops + * and return in native format. + * + * SDL byteswaps the data only if necessary, so the data returned will be in + * the native byte order. + * + * \param src the stream from which to read data + * \returns 64 bits of data in the native byte order of the platform. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadBE64 + */ +extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src); + +/** + * Use this function to read 64 bits of big-endian data from an SDL_RWops and + * return in native format. + * + * SDL byteswaps the data only if necessary, so the data returned will be in + * the native byte order. + * + * \param src the stream from which to read data + * \returns 64 bits of data in the native byte order of the platform. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadLE64 + */ +extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src); +/* @} *//* Read endian functions */ + +/** * \name Write endian functions - * + * * Write an item of native format to the specified endianness. */ -/*@{*/ -extern DECLSPEC size_t SDLCALL SDL_WriteU8(SDL_RWops * dst, Uint8 value); -extern DECLSPEC size_t SDLCALL SDL_WriteLE16(SDL_RWops * dst, Uint16 value); -extern DECLSPEC size_t SDLCALL SDL_WriteBE16(SDL_RWops * dst, Uint16 value); -extern DECLSPEC size_t SDLCALL SDL_WriteLE32(SDL_RWops * dst, Uint32 value); -extern DECLSPEC size_t SDLCALL SDL_WriteBE32(SDL_RWops * dst, Uint32 value); -extern DECLSPEC size_t SDLCALL SDL_WriteLE64(SDL_RWops * dst, Uint64 value); -extern DECLSPEC size_t SDLCALL SDL_WriteBE64(SDL_RWops * dst, Uint64 value); -/*@}*//*Write endian functions*/ +/* @{ */ +/** + * Use this function to write a byte to an SDL_RWops. + * + * \param dst the SDL_RWops to write to + * \param value the byte value to write + * \returns 1 on success or 0 on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ReadU8 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteU8(SDL_RWops * dst, Uint8 value); + +/** + * Use this function to write 16 bits in native format to a SDL_RWops as + * little-endian data. + * + * SDL byteswaps the data only if necessary, so the application always + * specifies native format, and the data written will be in little-endian + * format. + * + * \param dst the stream to which data will be written + * \param value the data to be written, in native format + * \returns 1 on successful write, 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteBE16 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteLE16(SDL_RWops * dst, Uint16 value); + +/** + * Use this function to write 16 bits in native format to a SDL_RWops as + * big-endian data. + * + * SDL byteswaps the data only if necessary, so the application always + * specifies native format, and the data written will be in big-endian format. + * + * \param dst the stream to which data will be written + * \param value the data to be written, in native format + * \returns 1 on successful write, 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteLE16 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteBE16(SDL_RWops * dst, Uint16 value); + +/** + * Use this function to write 32 bits in native format to a SDL_RWops as + * little-endian data. + * + * SDL byteswaps the data only if necessary, so the application always + * specifies native format, and the data written will be in little-endian + * format. + * + * \param dst the stream to which data will be written + * \param value the data to be written, in native format + * \returns 1 on successful write, 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteBE32 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteLE32(SDL_RWops * dst, Uint32 value); + +/** + * Use this function to write 32 bits in native format to a SDL_RWops as + * big-endian data. + * + * SDL byteswaps the data only if necessary, so the application always + * specifies native format, and the data written will be in big-endian format. + * + * \param dst the stream to which data will be written + * \param value the data to be written, in native format + * \returns 1 on successful write, 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteLE32 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteBE32(SDL_RWops * dst, Uint32 value); + +/** + * Use this function to write 64 bits in native format to a SDL_RWops as + * little-endian data. + * + * SDL byteswaps the data only if necessary, so the application always + * specifies native format, and the data written will be in little-endian + * format. + * + * \param dst the stream to which data will be written + * \param value the data to be written, in native format + * \returns 1 on successful write, 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteBE64 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteLE64(SDL_RWops * dst, Uint64 value); + +/** + * Use this function to write 64 bits in native format to a SDL_RWops as + * big-endian data. + * + * SDL byteswaps the data only if necessary, so the application always + * specifies native format, and the data written will be in big-endian format. + * + * \param dst the stream to which data will be written + * \param value the data to be written, in native format + * \returns 1 on successful write, 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_WriteLE64 + */ +extern DECLSPEC size_t SDLCALL SDL_WriteBE64(SDL_RWops * dst, Uint64 value); +/* @} *//* Write endian functions */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_rwops_h */ +#endif /* SDL_rwops_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_scancode.h b/external/SDL2/SDL_scancode.h index 26b8f36..5b2c67c 100644 --- a/external/SDL2/SDL_scancode.h +++ b/external/SDL2/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,35 +21,35 @@ /** * \file SDL_scancode.h - * + * * Defines keyboard scancodes. */ -#ifndef _SDL_scancode_h -#define _SDL_scancode_h +#ifndef SDL_scancode_h_ +#define SDL_scancode_h_ #include "SDL_stdinc.h" /** * \brief The SDL keyboard scancode representation. - * + * * Values of this type are used to represent keyboard keys, among other places * in the \link SDL_Keysym::scancode key.keysym.scancode \endlink field of the * SDL_Event structure. - * + * * The values in this enumeration are based on the USB usage page standard: - * http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf + * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf */ typedef enum { SDL_SCANCODE_UNKNOWN = 0, - /** + /** * \name Usage page 0x07 - * + * * These values are from usage page 0x07 (USB keyboard page). */ - /*@{*/ + /* @{ */ SDL_SCANCODE_A = 4, SDL_SCANCODE_B = 5, @@ -99,49 +99,49 @@ typedef enum SDL_SCANCODE_EQUALS = 46, SDL_SCANCODE_LEFTBRACKET = 47, SDL_SCANCODE_RIGHTBRACKET = 48, - SDL_SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return - * key on ISO keyboards and at the right end - * of the QWERTY row on ANSI keyboards. - * Produces REVERSE SOLIDUS (backslash) and - * VERTICAL LINE in a US layout, REVERSE - * SOLIDUS and VERTICAL LINE in a UK Mac - * layout, NUMBER SIGN and TILDE in a UK + SDL_SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return + * key on ISO keyboards and at the right end + * of the QWERTY row on ANSI keyboards. + * Produces REVERSE SOLIDUS (backslash) and + * VERTICAL LINE in a US layout, REVERSE + * SOLIDUS and VERTICAL LINE in a UK Mac + * layout, NUMBER SIGN and TILDE in a UK * Windows layout, DOLLAR SIGN and POUND SIGN - * in a Swiss German layout, NUMBER SIGN and - * APOSTROPHE in a German layout, GRAVE - * ACCENT and POUND SIGN in a French Mac - * layout, and ASTERISK and MICRO SIGN in a + * in a Swiss German layout, NUMBER SIGN and + * APOSTROPHE in a German layout, GRAVE + * ACCENT and POUND SIGN in a French Mac + * layout, and ASTERISK and MICRO SIGN in a * French Windows layout. */ - SDL_SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code - * instead of 49 for the same key, but all - * OSes I've seen treat the two codes + SDL_SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code + * instead of 49 for the same key, but all + * OSes I've seen treat the two codes * identically. So, as an implementor, unless - * your keyboard generates both of those + * your keyboard generates both of those * codes and your OS treats them differently, * you should generate SDL_SCANCODE_BACKSLASH - * instead of this code. As a user, you - * should not rely on this code because SDL - * will never generate it with most (all?) - * keyboards. + * instead of this code. As a user, you + * should not rely on this code because SDL + * will never generate it with most (all?) + * keyboards. */ SDL_SCANCODE_SEMICOLON = 51, SDL_SCANCODE_APOSTROPHE = 52, - SDL_SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI - * and ISO keyboards). Produces GRAVE ACCENT and - * TILDE in a US Windows layout and in US and UK - * Mac layouts on ANSI keyboards, GRAVE ACCENT - * and NOT SIGN in a UK Windows layout, SECTION - * SIGN and PLUS-MINUS SIGN in US and UK Mac - * layouts on ISO keyboards, SECTION SIGN and - * DEGREE SIGN in a Swiss German layout (Mac: - * only on ISO keyboards), CIRCUMFLEX ACCENT and - * DEGREE SIGN in a German layout (Mac: only on + SDL_SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI + * and ISO keyboards). Produces GRAVE ACCENT and + * TILDE in a US Windows layout and in US and UK + * Mac layouts on ANSI keyboards, GRAVE ACCENT + * and NOT SIGN in a UK Windows layout, SECTION + * SIGN and PLUS-MINUS SIGN in US and UK Mac + * layouts on ISO keyboards, SECTION SIGN and + * DEGREE SIGN in a Swiss German layout (Mac: + * only on ISO keyboards), CIRCUMFLEX ACCENT and + * DEGREE SIGN in a German layout (Mac: only on * ISO keyboards), SUPERSCRIPT TWO and TILDE in a - * French Windows layout, COMMERCIAL AT and - * NUMBER SIGN in a French Mac layout on ISO + * French Windows layout, COMMERCIAL AT and + * NUMBER SIGN in a French Mac layout on ISO * keyboards, and LESS-THAN SIGN and GREATER-THAN - * SIGN in a Swiss German, German, or French Mac + * SIGN in a Swiss German, German, or French Mac * layout on ANSI keyboards. */ SDL_SCANCODE_COMMA = 54, @@ -178,7 +178,7 @@ typedef enum SDL_SCANCODE_DOWN = 81, SDL_SCANCODE_UP = 82, - SDL_SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards + SDL_SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards */ SDL_SCANCODE_KP_DIVIDE = 84, SDL_SCANCODE_KP_MULTIPLY = 85, @@ -197,19 +197,19 @@ typedef enum SDL_SCANCODE_KP_0 = 98, SDL_SCANCODE_KP_PERIOD = 99, - SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO - * keyboards have over ANSI ones, - * located between left shift and Y. + SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO + * keyboards have over ANSI ones, + * located between left shift and Y. * Produces GRAVE ACCENT and TILDE in a * US or UK Mac layout, REVERSE SOLIDUS - * (backslash) and VERTICAL LINE in a - * US or UK Windows layout, and + * (backslash) and VERTICAL LINE in a + * US or UK Windows layout, and * LESS-THAN SIGN and GREATER-THAN SIGN * in a Swiss German, German, or French * layout. */ SDL_SCANCODE_APPLICATION = 101, /**< windows contextual menu, compose */ - SDL_SCANCODE_POWER = 102, /**< The USB document says this is a status flag, - * not a physical key - but some Mac keyboards + SDL_SCANCODE_POWER = 102, /**< The USB document says this is a status flag, + * not a physical key - but some Mac keyboards * do have a power key. */ SDL_SCANCODE_KP_EQUALS = 103, SDL_SCANCODE_F13 = 104, @@ -245,7 +245,7 @@ typedef enum SDL_SCANCODE_KP_COMMA = 133, SDL_SCANCODE_KP_EQUALSAS400 = 134, - SDL_SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see + SDL_SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see footnotes in USB doc */ SDL_SCANCODE_INTERNATIONAL2 = 136, SDL_SCANCODE_INTERNATIONAL3 = 137, /**< Yen */ @@ -334,19 +334,19 @@ typedef enum SDL_SCANCODE_RALT = 230, /**< alt gr, option */ SDL_SCANCODE_RGUI = 231, /**< windows, command (apple), meta */ - SDL_SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered - * by any of the above, but since there's a + SDL_SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered + * by any of the above, but since there's a * special KMOD_MODE for it I'm adding it here */ - - /*@}*//*Usage page 0x07*/ + + /* @} *//* Usage page 0x07 */ /** * \name Usage page 0x0C - * + * * These values are mapped from usage page 0x0C (USB consumer page). */ - /*@{*/ + /* @{ */ SDL_SCANCODE_AUDIONEXT = 258, SDL_SCANCODE_AUDIOPREV = 259, @@ -365,37 +365,49 @@ typedef enum SDL_SCANCODE_AC_STOP = 272, SDL_SCANCODE_AC_REFRESH = 273, SDL_SCANCODE_AC_BOOKMARKS = 274, - - /*@}*//*Usage page 0x0C*/ + + /* @} *//* Usage page 0x0C */ /** * \name Walther keys - * + * * These are values that Christian Walther added (for mac keyboard?). */ - /*@{*/ + /* @{ */ SDL_SCANCODE_BRIGHTNESSDOWN = 275, SDL_SCANCODE_BRIGHTNESSUP = 276, - SDL_SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display + SDL_SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display switch, video mode switch */ SDL_SCANCODE_KBDILLUMTOGGLE = 278, SDL_SCANCODE_KBDILLUMDOWN = 279, SDL_SCANCODE_KBDILLUMUP = 280, SDL_SCANCODE_EJECT = 281, SDL_SCANCODE_SLEEP = 282, - - SDL_SCANCODE_APP1 = 283, - SDL_SCANCODE_APP2 = 284, - /*@}*//*Walther keys*/ + SDL_SCANCODE_APP1 = 283, + SDL_SCANCODE_APP2 = 284, + + /* @} *//* Walther keys */ + + /** + * \name Usage page 0x0C (additional media keys) + * + * These values are mapped from usage page 0x0C (USB consumer page). + */ + /* @{ */ + + SDL_SCANCODE_AUDIOREWIND = 285, + SDL_SCANCODE_AUDIOFASTFORWARD = 286, + + /* @} *//* Usage page 0x0C (additional media keys) */ /* Add any other keys here. */ - SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes + SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes for array bounds */ } SDL_Scancode; -#endif /* _SDL_scancode_h */ +#endif /* SDL_scancode_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_sensor.h b/external/SDL2/SDL_sensor.h new file mode 100644 index 0000000..a2f30e0 --- /dev/null +++ b/external/SDL2/SDL_sensor.h @@ -0,0 +1,301 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_sensor.h + * + * Include file for SDL sensor event handling + * + */ + +#ifndef SDL_sensor_h_ +#define SDL_sensor_h_ + +#include "SDL_stdinc.h" +#include "SDL_error.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** + * \brief SDL_sensor.h + * + * In order to use these functions, SDL_Init() must have been called + * with the ::SDL_INIT_SENSOR flag. This causes SDL to scan the system + * for sensors, and load appropriate drivers. + */ + +struct _SDL_Sensor; +typedef struct _SDL_Sensor SDL_Sensor; + +/** + * This is a unique ID for a sensor for the time it is connected to the system, + * and is never reused for the lifetime of the application. + * + * The ID value starts at 0 and increments from there. The value -1 is an invalid ID. + */ +typedef Sint32 SDL_SensorID; + +/* The different sensors defined by SDL + * + * Additional sensors may be available, using platform dependent semantics. + * + * Hare are the additional Android sensors: + * https://developer.android.com/reference/android/hardware/SensorEvent.html#values + */ +typedef enum +{ + SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */ + SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */ + SDL_SENSOR_ACCEL, /**< Accelerometer */ + SDL_SENSOR_GYRO /**< Gyroscope */ +} SDL_SensorType; + +/** + * Accelerometer sensor + * + * The accelerometer returns the current acceleration in SI meters per + * second squared. This measurement includes the force of gravity, so + * a device at rest will have an value of SDL_STANDARD_GRAVITY away + * from the center of the earth. + * + * values[0]: Acceleration on the x axis + * values[1]: Acceleration on the y axis + * values[2]: Acceleration on the z axis + * + * For phones held in portrait mode and game controllers held in front of you, + * the axes are defined as follows: + * -X ... +X : left ... right + * -Y ... +Y : bottom ... top + * -Z ... +Z : farther ... closer + * + * The axis data is not changed when the phone is rotated. + * + * \sa SDL_GetDisplayOrientation() + */ +#define SDL_STANDARD_GRAVITY 9.80665f + +/** + * Gyroscope sensor + * + * The gyroscope returns the current rate of rotation in radians per second. + * The rotation is positive in the counter-clockwise direction. That is, + * an observer looking from a positive location on one of the axes would + * see positive rotation on that axis when it appeared to be rotating + * counter-clockwise. + * + * values[0]: Angular speed around the x axis (pitch) + * values[1]: Angular speed around the y axis (yaw) + * values[2]: Angular speed around the z axis (roll) + * + * For phones held in portrait mode and game controllers held in front of you, + * the axes are defined as follows: + * -X ... +X : left ... right + * -Y ... +Y : bottom ... top + * -Z ... +Z : farther ... closer + * + * The axis data is not changed when the phone or controller is rotated. + * + * \sa SDL_GetDisplayOrientation() + */ + +/* Function prototypes */ + +/** + * Locking for multi-threaded access to the sensor API + * + * If you are using the sensor API or handling events from multiple threads + * you should use these locking functions to protect access to the sensors. + * + * In particular, you are guaranteed that the sensor list won't change, so the + * API functions that take a sensor index will be valid, and sensor events + * will not be delivered. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC void SDLCALL SDL_LockSensors(void); +extern DECLSPEC void SDLCALL SDL_UnlockSensors(void); + +/** + * Count the number of sensors attached to the system right now. + * + * \returns the number of sensors detected. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_NumSensors(void); + +/** + * Get the implementation dependent name of a sensor. + * + * \param device_index The sensor to obtain name from + * \returns the sensor name, or NULL if `device_index` is out of range. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC const char *SDLCALL SDL_SensorGetDeviceName(int device_index); + +/** + * Get the type of a sensor. + * + * \param device_index The sensor to get the type from + * \returns the SDL_SensorType, or `SDL_SENSOR_INVALID` if `device_index` is + * out of range. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetDeviceType(int device_index); + +/** + * Get the platform dependent type of a sensor. + * + * \param device_index The sensor to check + * \returns the sensor platform dependent type, or -1 if `device_index` is out + * of range. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_SensorGetDeviceNonPortableType(int device_index); + +/** + * Get the instance ID of a sensor. + * + * \param device_index The sensor to get instance id from + * \returns the sensor instance ID, or -1 if `device_index` is out of range. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetDeviceInstanceID(int device_index); + +/** + * Open a sensor for use. + * + * \param device_index The sensor to open + * \returns an SDL_Sensor sensor object, or NULL if an error occurred. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorOpen(int device_index); + +/** + * Return the SDL_Sensor associated with an instance id. + * + * \param instance_id The sensor from instance id + * \returns an SDL_Sensor object. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorFromInstanceID(SDL_SensorID instance_id); + +/** + * Get the implementation dependent name of a sensor + * + * \param sensor The SDL_Sensor object + * \returns the sensor name, or NULL if `sensor` is NULL. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC const char *SDLCALL SDL_SensorGetName(SDL_Sensor *sensor); + +/** + * Get the type of a sensor. + * + * \param sensor The SDL_Sensor object to inspect + * \returns the SDL_SensorType type, or `SDL_SENSOR_INVALID` if `sensor` is + * NULL. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetType(SDL_Sensor *sensor); + +/** + * Get the platform dependent type of a sensor. + * + * \param sensor The SDL_Sensor object to inspect + * \returns the sensor platform dependent type, or -1 if `sensor` is NULL. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_SensorGetNonPortableType(SDL_Sensor *sensor); + +/** + * Get the instance ID of a sensor. + * + * \param sensor The SDL_Sensor object to inspect + * \returns the sensor instance ID, or -1 if `sensor` is NULL. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetInstanceID(SDL_Sensor *sensor); + +/** + * Get the current state of an opened sensor. + * + * The number of values and interpretation of the data is sensor dependent. + * + * \param sensor The SDL_Sensor object to query + * \param data A pointer filled with the current sensor state + * \param num_values The number of values to write to data + * \returns 0 or -1 if an error occurred. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values); + +/** + * Close a sensor previously opened with SDL_SensorOpen(). + * + * \param sensor The SDL_Sensor object to close + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC void SDLCALL SDL_SensorClose(SDL_Sensor * sensor); + +/** + * Update the current state of the open sensors. + * + * This is called automatically by the event loop if sensor events are + * enabled. + * + * This needs to be called from the thread that initialized the sensor + * subsystem. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC void SDLCALL SDL_SensorUpdate(void); + + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#include "close_code.h" + +#endif /* SDL_sensor_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_shape.h b/external/SDL2/SDL_shape.h index bd37242..1bca927 100644 --- a/external/SDL2/SDL_shape.h +++ b/external/SDL2/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,8 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_shape_h -#define _SDL_shape_h +#ifndef SDL_shape_h_ +#define SDL_shape_h_ #include "SDL_stdinc.h" #include "SDL_pixels.h" @@ -31,9 +31,7 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** \file SDL_shape.h @@ -46,90 +44,102 @@ extern "C" { #define SDL_WINDOW_LACKS_SHAPE -3 /** - * \brief Create a window that can be shaped with the specified position, dimensions, and flags. - * - * \param title The title of the window, in UTF-8 encoding. - * \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or - * ::SDL_WINDOWPOS_UNDEFINED. - * \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or - * ::SDL_WINDOWPOS_UNDEFINED. - * \param w The width of the window. - * \param h The height of the window. - * \param flags The flags for the window, a mask of SDL_WINDOW_BORDERLESS with any of the following: - * ::SDL_WINDOW_OPENGL, ::SDL_WINDOW_INPUT_GRABBED, - * ::SDL_WINDOW_SHOWN, ::SDL_WINDOW_RESIZABLE, - * ::SDL_WINDOW_MAXIMIZED, ::SDL_WINDOW_MINIMIZED, - * ::SDL_WINDOW_BORDERLESS is always set, and ::SDL_WINDOW_FULLSCREEN is always unset. - * - * \return The window created, or NULL if window creation failed. - * - * \sa SDL_DestroyWindow() + * Create a window that can be shaped with the specified position, dimensions, + * and flags. + * + * \param title The title of the window, in UTF-8 encoding. + * \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or + * ::SDL_WINDOWPOS_UNDEFINED. + * \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or + * ::SDL_WINDOWPOS_UNDEFINED. + * \param w The width of the window. + * \param h The height of the window. + * \param flags The flags for the window, a mask of SDL_WINDOW_BORDERLESS with + * any of the following: ::SDL_WINDOW_OPENGL, + * ::SDL_WINDOW_INPUT_GRABBED, ::SDL_WINDOW_HIDDEN, + * ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED, + * ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_BORDERLESS is always set, + * and ::SDL_WINDOW_FULLSCREEN is always unset. + * \return the window created, or NULL if window creation failed. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DestroyWindow */ extern DECLSPEC SDL_Window * SDLCALL SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags); /** - * \brief Return whether the given window is a shaped window. + * Return whether the given window is a shaped window. * * \param window The window to query for being shaped. + * \return SDL_TRUE if the window is a window that can be shaped, SDL_FALSE if + * the window is unshaped or NULL. + * + * \since This function is available since SDL 2.0.0. * - * \return SDL_TRUE if the window is a window that can be shaped, SDL_FALSE if the window is unshaped or NULL. * \sa SDL_CreateShapedWindow */ extern DECLSPEC SDL_bool SDLCALL SDL_IsShapedWindow(const SDL_Window *window); /** \brief An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */ typedef enum { - /** \brief The default mode, a binarized alpha cutoff of 1. */ - ShapeModeDefault, - /** \brief A binarized alpha cutoff with a given integer value. */ - ShapeModeBinarizeAlpha, - /** \brief A binarized alpha cutoff with a given integer value, but with the opposite comparison. */ - ShapeModeReverseBinarizeAlpha, - /** \brief A color key is applied. */ - ShapeModeColorKey + /** \brief The default mode, a binarized alpha cutoff of 1. */ + ShapeModeDefault, + /** \brief A binarized alpha cutoff with a given integer value. */ + ShapeModeBinarizeAlpha, + /** \brief A binarized alpha cutoff with a given integer value, but with the opposite comparison. */ + ShapeModeReverseBinarizeAlpha, + /** \brief A color key is applied. */ + ShapeModeColorKey } WindowShapeMode; #define SDL_SHAPEMODEALPHA(mode) (mode == ShapeModeDefault || mode == ShapeModeBinarizeAlpha || mode == ShapeModeReverseBinarizeAlpha) /** \brief A union containing parameters for shaped windows. */ typedef union { - /** \brief a cutoff alpha value for binarization of the window shape's alpha channel. */ - Uint8 binarizationCutoff; - SDL_Color colorKey; + /** \brief A cutoff alpha value for binarization of the window shape's alpha channel. */ + Uint8 binarizationCutoff; + SDL_Color colorKey; } SDL_WindowShapeParams; /** \brief A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */ typedef struct SDL_WindowShapeMode { - /** \brief The mode of these window-shape parameters. */ - WindowShapeMode mode; - /** \brief Window-shape parameters. */ - SDL_WindowShapeParams parameters; + /** \brief The mode of these window-shape parameters. */ + WindowShapeMode mode; + /** \brief Window-shape parameters. */ + SDL_WindowShapeParams parameters; } SDL_WindowShapeMode; /** - * \brief Set the shape and parameters of a shaped window. + * Set the shape and parameters of a shaped window. * * \param window The shaped window whose parameters should be set. * \param shape A surface encoding the desired shape for the window. * \param shape_mode The parameters to set for the shaped window. + * \return 0 on success, SDL_INVALID_SHAPE_ARGUMENT on an invalid shape + * argument, or SDL_NONSHAPEABLE_WINDOW if the SDL_Window given does + * not reference a valid shaped window. * - * \return 0 on success, SDL_INVALID_SHAPE_ARGUMENT on invalid an invalid shape argument, or SDL_NONSHAPEABLE_WINDOW - * if the SDL_Window* given does not reference a valid shaped window. + * \since This function is available since SDL 2.0.0. * * \sa SDL_WindowShapeMode - * \sa SDL_GetShapedWindowMode. + * \sa SDL_GetShapedWindowMode */ extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode); /** - * \brief Get the shape parameters of a shaped window. + * Get the shape parameters of a shaped window. * * \param window The shaped window whose parameters should be retrieved. - * \param shape_mode An empty shape-mode structure to fill, or NULL to check whether the window has a shape. + * \param shape_mode An empty shape-mode structure to fill, or NULL to check + * whether the window has a shape. + * \return 0 if the window has a shape and, provided shape_mode was not NULL, + * shape_mode has been filled with the mode data, + * SDL_NONSHAPEABLE_WINDOW if the SDL_Window given is not a shaped + * window, or SDL_WINDOW_LACKS_SHAPE if the SDL_Window given is a + * shapeable window currently lacking a shape. * - * \return 0 if the window has a shape and, provided shape_mode was not NULL, shape_mode has been filled with the mode - * data, SDL_NONSHAPEABLE_WINDOW if the SDL_Window given is not a shaped window, or SDL_WINDOW_LACKS_SHAPE if - * the SDL_Window* given is a shapeable window currently lacking a shape. + * \since This function is available since SDL 2.0.0. * * \sa SDL_WindowShapeMode * \sa SDL_SetWindowShape @@ -138,10 +148,8 @@ extern DECLSPEC int SDLCALL SDL_GetShapedWindowMode(SDL_Window *window,SDL_Windo /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_shape_h */ +#endif /* SDL_shape_h_ */ diff --git a/external/SDL2/SDL_stdinc.h b/external/SDL2/SDL_stdinc.h index f1e0edb..c0d194c 100644 --- a/external/SDL2/SDL_stdinc.h +++ b/external/SDL2/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,15 +21,20 @@ /** * \file SDL_stdinc.h - * + * * This is a general header that includes C language support. */ -#ifndef _SDL_stdinc_h -#define _SDL_stdinc_h +#ifndef SDL_stdinc_h_ +#define SDL_stdinc_h_ #include "SDL_config.h" +#ifdef __APPLE__ +#ifndef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE 1 /* for memset_pattern4() */ +#endif +#endif #ifdef HAVE_SYS_TYPES_H #include @@ -63,6 +68,9 @@ #ifdef HAVE_STRINGS_H # include #endif +#ifdef HAVE_WCHAR_H +# include +#endif #if defined(HAVE_INTTYPES_H) # include #elif defined(HAVE_STDINT_H) @@ -72,132 +80,18 @@ # include #endif #ifdef HAVE_MATH_H +# if defined(__WINRT__) +/* Defining _USE_MATH_DEFINES is required to get M_PI to be defined on + WinRT. See http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx + for more information. +*/ +# define _USE_MATH_DEFINES +# endif # include #endif -#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H) -# include +#ifdef HAVE_FLOAT_H +# include #endif - -/** - * The number of elements in an array. - */ -#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) -#define SDL_TABLESIZE(table) SDL_arraysize(table) - -/** - * \name Cast operators - * - * Use proper C++ casts when compiled as C++ to be compatible with the option - * -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above). - */ -/*@{*/ -#ifdef __cplusplus -#define SDL_reinterpret_cast(type, expression) reinterpret_cast(expression) -#define SDL_static_cast(type, expression) static_cast(expression) -#else -#define SDL_reinterpret_cast(type, expression) ((type)(expression)) -#define SDL_static_cast(type, expression) ((type)(expression)) -#endif -/*@}*//*Cast operators*/ - -/* Define a four character code as a Uint32 */ -#define SDL_FOURCC(A, B, C, D) \ - ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \ - (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \ - (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \ - (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24)) - -/** - * \name Basic data types - */ -/*@{*/ - -typedef enum -{ - SDL_FALSE = 0, - SDL_TRUE = 1 -} SDL_bool; - -/** - * \brief A signed 8-bit integer type. - */ -typedef int8_t Sint8; -/** - * \brief An unsigned 8-bit integer type. - */ -typedef uint8_t Uint8; -/** - * \brief A signed 16-bit integer type. - */ -typedef int16_t Sint16; -/** - * \brief An unsigned 16-bit integer type. - */ -typedef uint16_t Uint16; -/** - * \brief A signed 32-bit integer type. - */ -typedef int32_t Sint32; -/** - * \brief An unsigned 32-bit integer type. - */ -typedef uint32_t Uint32; - -/** - * \brief A signed 64-bit integer type. - */ -typedef int64_t Sint64; -/** - * \brief An unsigned 64-bit integer type. - */ -typedef uint64_t Uint64; - -/*@}*//*Basic data types*/ - - -#define SDL_COMPILE_TIME_ASSERT(name, x) \ - typedef int SDL_dummy_ ## name[(x) * 2 - 1] -/** \cond */ -#ifndef DOXYGEN_SHOULD_IGNORE_THIS -SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); -SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); -SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); -SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); -SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); -SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); -SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8); -SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); -#endif /* DOXYGEN_SHOULD_IGNORE_THIS */ -/** \endcond */ - -/* Check to make sure enums are the size of ints, for structure packing. - For both Watcom C/C++ and Borland C/C++ the compiler option that makes - enums having the size of an int must be enabled. - This is "-b" for Borland C/C++ and "-ei" for Watcom C/C++ (v11). -*/ - -/** \cond */ -#ifndef DOXYGEN_SHOULD_IGNORE_THIS -#if !defined(__ANDROID__) - /* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */ -typedef enum -{ - DUMMY_ENUM_VALUE -} SDL_DUMMY_ENUM; - -SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int)); -#endif -#endif /* DOXYGEN_SHOULD_IGNORE_THIS */ -/** \endcond */ - -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -/* *INDENT-OFF* */ -extern "C" { -/* *INDENT-ON* */ -#endif - #if defined(HAVE_ALLOCA) && !defined(alloca) # if defined(HAVE_ALLOCA_H) # include @@ -220,6 +114,287 @@ void *alloca(unsigned); char *alloca(); # endif #endif + +/** + * Check if the compiler supports a given builtin. + * Supported by virtually all clang versions and recent gcc. Use this + * instead of checking the clang version if possible. + */ +#ifdef __has_builtin +#define _SDL_HAS_BUILTIN(x) __has_builtin(x) +#else +#define _SDL_HAS_BUILTIN(x) 0 +#endif + +/** + * The number of elements in an array. + */ +#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) +#define SDL_TABLESIZE(table) SDL_arraysize(table) + +/** + * Macro useful for building other macros with strings in them + * + * e.g. #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n") + */ +#define SDL_STRINGIFY_ARG(arg) #arg + +/** + * \name Cast operators + * + * Use proper C++ casts when compiled as C++ to be compatible with the option + * -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above). + */ +/* @{ */ +#ifdef __cplusplus +#define SDL_reinterpret_cast(type, expression) reinterpret_cast(expression) +#define SDL_static_cast(type, expression) static_cast(expression) +#define SDL_const_cast(type, expression) const_cast(expression) +#else +#define SDL_reinterpret_cast(type, expression) ((type)(expression)) +#define SDL_static_cast(type, expression) ((type)(expression)) +#define SDL_const_cast(type, expression) ((type)(expression)) +#endif +/* @} *//* Cast operators */ + +/* Define a four character code as a Uint32 */ +#define SDL_FOURCC(A, B, C, D) \ + ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \ + (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \ + (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \ + (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24)) + +/** + * \name Basic data types + */ +/* @{ */ + +#ifdef __CC_ARM +/* ARM's compiler throws warnings if we use an enum: like "SDL_bool x = a < b;" */ +#define SDL_FALSE 0 +#define SDL_TRUE 1 +typedef int SDL_bool; +#else +typedef enum +{ + SDL_FALSE = 0, + SDL_TRUE = 1 +} SDL_bool; +#endif + +/** + * \brief A signed 8-bit integer type. + */ +#define SDL_MAX_SINT8 ((Sint8)0x7F) /* 127 */ +#define SDL_MIN_SINT8 ((Sint8)(~0x7F)) /* -128 */ +typedef int8_t Sint8; +/** + * \brief An unsigned 8-bit integer type. + */ +#define SDL_MAX_UINT8 ((Uint8)0xFF) /* 255 */ +#define SDL_MIN_UINT8 ((Uint8)0x00) /* 0 */ +typedef uint8_t Uint8; +/** + * \brief A signed 16-bit integer type. + */ +#define SDL_MAX_SINT16 ((Sint16)0x7FFF) /* 32767 */ +#define SDL_MIN_SINT16 ((Sint16)(~0x7FFF)) /* -32768 */ +typedef int16_t Sint16; +/** + * \brief An unsigned 16-bit integer type. + */ +#define SDL_MAX_UINT16 ((Uint16)0xFFFF) /* 65535 */ +#define SDL_MIN_UINT16 ((Uint16)0x0000) /* 0 */ +typedef uint16_t Uint16; +/** + * \brief A signed 32-bit integer type. + */ +#define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) /* 2147483647 */ +#define SDL_MIN_SINT32 ((Sint32)(~0x7FFFFFFF)) /* -2147483648 */ +typedef int32_t Sint32; +/** + * \brief An unsigned 32-bit integer type. + */ +#define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu) /* 4294967295 */ +#define SDL_MIN_UINT32 ((Uint32)0x00000000) /* 0 */ +typedef uint32_t Uint32; + +/** + * \brief A signed 64-bit integer type. + */ +#define SDL_MAX_SINT64 ((Sint64)0x7FFFFFFFFFFFFFFFll) /* 9223372036854775807 */ +#define SDL_MIN_SINT64 ((Sint64)(~0x7FFFFFFFFFFFFFFFll)) /* -9223372036854775808 */ +typedef int64_t Sint64; +/** + * \brief An unsigned 64-bit integer type. + */ +#define SDL_MAX_UINT64 ((Uint64)0xFFFFFFFFFFFFFFFFull) /* 18446744073709551615 */ +#define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */ +typedef uint64_t Uint64; + +/* @} *//* Basic data types */ + +/* Make sure we have macros for printing width-based integers. + * should define these but this is not true all platforms. + * (for example win32) */ +#ifndef SDL_PRIs64 +#ifdef PRIs64 +#define SDL_PRIs64 PRIs64 +#elif defined(__WIN32__) +#define SDL_PRIs64 "I64d" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIs64 "ld" +#else +#define SDL_PRIs64 "lld" +#endif +#endif +#ifndef SDL_PRIu64 +#ifdef PRIu64 +#define SDL_PRIu64 PRIu64 +#elif defined(__WIN32__) +#define SDL_PRIu64 "I64u" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIu64 "lu" +#else +#define SDL_PRIu64 "llu" +#endif +#endif +#ifndef SDL_PRIx64 +#ifdef PRIx64 +#define SDL_PRIx64 PRIx64 +#elif defined(__WIN32__) +#define SDL_PRIx64 "I64x" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIx64 "lx" +#else +#define SDL_PRIx64 "llx" +#endif +#endif +#ifndef SDL_PRIX64 +#ifdef PRIX64 +#define SDL_PRIX64 PRIX64 +#elif defined(__WIN32__) +#define SDL_PRIX64 "I64X" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIX64 "lX" +#else +#define SDL_PRIX64 "llX" +#endif +#endif +#ifndef SDL_PRIs32 +#ifdef PRId32 +#define SDL_PRIs32 PRId32 +#else +#define SDL_PRIs32 "d" +#endif +#endif +#ifndef SDL_PRIu32 +#ifdef PRIu32 +#define SDL_PRIu32 PRIu32 +#else +#define SDL_PRIu32 "u" +#endif +#endif +#ifndef SDL_PRIx32 +#ifdef PRIx32 +#define SDL_PRIx32 PRIx32 +#else +#define SDL_PRIx32 "x" +#endif +#endif +#ifndef SDL_PRIX32 +#ifdef PRIX32 +#define SDL_PRIX32 PRIX32 +#else +#define SDL_PRIX32 "X" +#endif +#endif + +/* Annotations to help code analysis tools */ +#ifdef SDL_DISABLE_ANALYZE_MACROS +#define SDL_IN_BYTECAP(x) +#define SDL_INOUT_Z_CAP(x) +#define SDL_OUT_Z_CAP(x) +#define SDL_OUT_CAP(x) +#define SDL_OUT_BYTECAP(x) +#define SDL_OUT_Z_BYTECAP(x) +#define SDL_PRINTF_FORMAT_STRING +#define SDL_SCANF_FORMAT_STRING +#define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) +#define SDL_SCANF_VARARG_FUNC( fmtargnumber ) +#else +#if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ +#include + +#define SDL_IN_BYTECAP(x) _In_bytecount_(x) +#define SDL_INOUT_Z_CAP(x) _Inout_z_cap_(x) +#define SDL_OUT_Z_CAP(x) _Out_z_cap_(x) +#define SDL_OUT_CAP(x) _Out_cap_(x) +#define SDL_OUT_BYTECAP(x) _Out_bytecap_(x) +#define SDL_OUT_Z_BYTECAP(x) _Out_z_bytecap_(x) + +#define SDL_PRINTF_FORMAT_STRING _Printf_format_string_ +#define SDL_SCANF_FORMAT_STRING _Scanf_format_string_impl_ +#else +#define SDL_IN_BYTECAP(x) +#define SDL_INOUT_Z_CAP(x) +#define SDL_OUT_Z_CAP(x) +#define SDL_OUT_CAP(x) +#define SDL_OUT_BYTECAP(x) +#define SDL_OUT_Z_BYTECAP(x) +#define SDL_PRINTF_FORMAT_STRING +#define SDL_SCANF_FORMAT_STRING +#endif +#if defined(__GNUC__) +#define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 ))) +#define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) +#else +#define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) +#define SDL_SCANF_VARARG_FUNC( fmtargnumber ) +#endif +#endif /* SDL_DISABLE_ANALYZE_MACROS */ + +#define SDL_COMPILE_TIME_ASSERT(name, x) \ + typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1] +/** \cond */ +#ifndef DOXYGEN_SHOULD_IGNORE_THIS +SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); +SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); +SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); +SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); +SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); +SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); +SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8); +SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); +#endif /* DOXYGEN_SHOULD_IGNORE_THIS */ +/** \endcond */ + +/* Check to make sure enums are the size of ints, for structure packing. + For both Watcom C/C++ and Borland C/C++ the compiler option that makes + enums having the size of an int must be enabled. + This is "-b" for Borland C/C++ and "-ei" for Watcom C/C++ (v11). +*/ + +/** \cond */ +#ifndef DOXYGEN_SHOULD_IGNORE_THIS +#if !defined(__ANDROID__) && !defined(__VITA__) + /* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */ +typedef enum +{ + DUMMY_ENUM_VALUE +} SDL_DUMMY_ENUM; + +SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int)); +#endif +#endif /* DOXYGEN_SHOULD_IGNORE_THIS */ +/** \endcond */ + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef HAVE_ALLOCA #define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count)) #define SDL_stack_free(data) @@ -228,539 +403,234 @@ char *alloca(); #define SDL_stack_free(data) SDL_free(data) #endif - -/* SDL stdinc inline functions: - - The theory here is that by default we forcibly inline what we can, and your - app will use the inline version by default. However we expose a non-inline - version too, so the symbol is always available in the library even if your app - bypassed the inline version. The SDL_*_inline versions aren't guaranteed to - exist, so never call them directly; use SDL_* instead, and trust the system - to give you the right thing. - - The benefit here is that you can dlsym() these functions, which you - couldn't if you had macros, you can link against a foreign build of SDL - even if you configured differently, and you can drop the unconfigured SDL - headers into a project without #defining HAVE_MALLOC (etc) and still link. -*/ - extern DECLSPEC void *SDLCALL SDL_malloc(size_t size); -#ifdef HAVE_MALLOC -SDL_FORCE_INLINE void *SDL_malloc_inline(size_t size) { return malloc(size); } -#define SDL_malloc SDL_malloc_inline -#endif - extern DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size); -#ifdef HAVE_CALLOC -SDL_FORCE_INLINE void *SDL_calloc_inline(size_t nmemb, size_t size) { return calloc(nmemb, size); } -#define SDL_calloc SDL_calloc_inline -#endif - extern DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size); -#ifdef HAVE_REALLOC -SDL_FORCE_INLINE void *SDL_realloc_inline(void *mem, size_t size) { return realloc(mem, size); } -#define SDL_realloc SDL_realloc_inline -#endif - extern DECLSPEC void SDLCALL SDL_free(void *mem); -#ifdef HAVE_FREE -SDL_FORCE_INLINE void SDL_free_inline(void *mem) { free(mem); } -#define SDL_free SDL_free_inline -#endif + +typedef void *(SDLCALL *SDL_malloc_func)(size_t size); +typedef void *(SDLCALL *SDL_calloc_func)(size_t nmemb, size_t size); +typedef void *(SDLCALL *SDL_realloc_func)(void *mem, size_t size); +typedef void (SDLCALL *SDL_free_func)(void *mem); + +/** + * Get the current set of SDL memory functions + * + * \since This function is available since SDL 2.0.7. + */ +extern DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func, + SDL_calloc_func *calloc_func, + SDL_realloc_func *realloc_func, + SDL_free_func *free_func); + +/** + * Replace SDL's memory allocation functions with a custom set + * + * \since This function is available since SDL 2.0.7. + */ +extern DECLSPEC int SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func, + SDL_calloc_func calloc_func, + SDL_realloc_func realloc_func, + SDL_free_func free_func); + +/** + * Get the number of outstanding (unfreed) allocations + * + * \since This function is available since SDL 2.0.7. + */ +extern DECLSPEC int SDLCALL SDL_GetNumAllocations(void); extern DECLSPEC char *SDLCALL SDL_getenv(const char *name); -#ifdef HAVE_GETENV -SDL_FORCE_INLINE char *SDL_getenv_inline(const char *name) { return getenv(name); } -#define SDL_getenv SDL_getenv_inline -#endif - extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite); -#ifdef HAVE_SETENV -SDL_FORCE_INLINE int SDL_setenv_inline(const char *name, const char *value, int overwrite) { return setenv(name, value, overwrite); } -#define SDL_setenv SDL_setenv_inline -#endif extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *)); -#ifdef HAVE_QSORT -SDL_FORCE_INLINE void SDL_qsort_inline(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *)) { return qsort(base, nmemb, size, compare); } -#define SDL_qsort SDL_qsort_inline -#endif extern DECLSPEC int SDLCALL SDL_abs(int x); -#ifdef HAVE_ABS -SDL_FORCE_INLINE int SDL_abs_inline(int x) { return abs(x); } -#else -SDL_FORCE_INLINE int SDL_abs_inline(int x) { return ((x) < 0 ? -(x) : (x)); } -#endif -#define SDL_abs SDL_abs_inline -/* !!! FIXME: these have side effects. You probably shouldn't use them. */ -/* !!! FIXME: Maybe we do forceinline functions of SDL_mini, SDL_minf, etc? */ +/* NOTE: these double-evaluate their arguments, so you should never have side effects in the parameters */ #define SDL_min(x, y) (((x) < (y)) ? (x) : (y)) #define SDL_max(x, y) (((x) > (y)) ? (x) : (y)) +#define SDL_clamp(x, a, b) (((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x))) +extern DECLSPEC int SDLCALL SDL_isalpha(int x); +extern DECLSPEC int SDLCALL SDL_isalnum(int x); +extern DECLSPEC int SDLCALL SDL_isblank(int x); +extern DECLSPEC int SDLCALL SDL_iscntrl(int x); extern DECLSPEC int SDLCALL SDL_isdigit(int x); +extern DECLSPEC int SDLCALL SDL_isxdigit(int x); +extern DECLSPEC int SDLCALL SDL_ispunct(int x); extern DECLSPEC int SDLCALL SDL_isspace(int x); +extern DECLSPEC int SDLCALL SDL_isupper(int x); +extern DECLSPEC int SDLCALL SDL_islower(int x); +extern DECLSPEC int SDLCALL SDL_isprint(int x); +extern DECLSPEC int SDLCALL SDL_isgraph(int x); extern DECLSPEC int SDLCALL SDL_toupper(int x); extern DECLSPEC int SDLCALL SDL_tolower(int x); -#ifdef HAVE_CTYPE_H -SDL_FORCE_INLINE int SDL_isdigit_inline(int x) { return isdigit(x); } -SDL_FORCE_INLINE int SDL_isspace_inline(int x) { return isspace(x); } -SDL_FORCE_INLINE int SDL_toupper_inline(int x) { return toupper(x); } -SDL_FORCE_INLINE int SDL_tolower_inline(int x) { return tolower(x); } -#else -SDL_FORCE_INLINE int SDL_isdigit_inline(int x) { return ((x) >= '0') && ((x) <= '9'); } -SDL_FORCE_INLINE int SDL_isspace_inline(int x) { return ((x) == ' ') || ((x) == '\t') || ((x) == '\r') || ((x) == '\n'); } -SDL_FORCE_INLINE int SDL_toupper_inline(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A'+((x)-'a')) : (x); } -SDL_FORCE_INLINE int SDL_tolower_inline(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a'+((x)-'A')) : (x); } -#endif -#define SDL_isdigit SDL_isdigit_inline -#define SDL_isspace SDL_isspace_inline -#define SDL_toupper SDL_toupper_inline -#define SDL_tolower SDL_tolower_inline -extern DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len); -#ifdef HAVE_MEMSET -SDL_FORCE_INLINE void *SDL_memset_inline(void *dst, int c, size_t len) { return memset(dst, c, len); } -#define SDL_memset SDL_memset_inline -#endif +extern DECLSPEC Uint32 SDLCALL SDL_crc32(Uint32 crc, const void *data, size_t len); + +extern DECLSPEC void *SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len); #define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x))) #define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x))) +#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x))) -/* !!! FIXME: does this _really_ beat memset() on any modern platform? */ -SDL_FORCE_INLINE void SDL_memset4(void *dst, int val, size_t len) +/* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */ +SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords) { -#if defined(__GNUC__) && defined(i386) +#ifdef __APPLE__ + memset_pattern4(dst, &val, dwords * 4); +#elif defined(__GNUC__) && defined(__i386__) int u0, u1, u2; __asm__ __volatile__ ( "cld \n\t" "rep ; stosl \n\t" : "=&D" (u0), "=&a" (u1), "=&c" (u2) - : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, len)) + : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, dwords)) : "memory" ); -/* !!! FIXME: amd64? */ #else - size_t _n = (len + 3) / 4; + size_t _n = (dwords + 3) / 4; Uint32 *_p = SDL_static_cast(Uint32 *, dst); Uint32 _val = (val); - if (len == 0) + if (dwords == 0) { return; - switch (len % 4) - { - case 0: do { *_p++ = _val; - case 3: *_p++ = _val; - case 2: *_p++ = _val; + } + switch (dwords % 4) { + case 0: do { *_p++ = _val; SDL_FALLTHROUGH; + case 3: *_p++ = _val; SDL_FALLTHROUGH; + case 2: *_p++ = _val; SDL_FALLTHROUGH; case 1: *_p++ = _val; } while ( --_n ); } #endif } +extern DECLSPEC void *SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); -extern DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len); -#if defined(__MACOSX__) -SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len) -{ - /* We can count on memcpy existing on Mac OS X and being well-tuned. */ - return memcpy(dst, src, len); -} -#define SDL_memcpy SDL_memcpy_inline -#elif defined(__GNUC__) && defined(i386) && !defined(__WIN32__) -SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len) -{ - /* !!! FIXME: does this _really_ beat memcpy() on any modern platform? */ - /* !!! FIXME: shouldn't we just force the inputs to ecx/edi/esi instead of this tapdance with outputs? */ - /* !!! FIXME: amd64? */ - int u0, u1, u2; - __asm__ __volatile__ ( - "cld \n\t" - "rep ; movsl \n\t" - "testb $2,%b4 \n\t" - "je 1f \n\t" - "movsw \n" - "1:\ttestb $1,%b4 \n\t" - "je 2f \n\t" - "movsb \n" - "2:" - : "=&c" (u0), "=&D" (u1), "=&S" (u2) - : "0" (SDL_static_cast(unsigned, len)/4), "q" (len), "1" (dst), "2" (src) - : "memory" - ); - return dst; -} -#define SDL_memcpy SDL_memcpy_inline -#elif defined(HAVE_MEMCPY) -SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len) -{ - return memcpy(dst, src, len); -} -#define SDL_memcpy SDL_memcpy_inline -#elif defined(HAVE_BCOPY) /* !!! FIXME: is there _really_ ever a time where you have bcopy and not memcpy? */ -SDL_FORCE_INLINE void *SDL_memcpy_inline(void *dst, const void *src, size_t len) -{ - bcopy(src, dst, len); - return dst; -} -#define SDL_memcpy SDL_memcpy_inline -#endif - - -SDL_FORCE_INLINE void *SDL_memcpy4(void *dst, const void *src, size_t dwords) -{ -#if defined(__GNUC__) && defined(i386) - /* !!! FIXME: does this _really_ beat memcpy() on any modern platform? */ - /* !!! FIXME: shouldn't we just force the inputs to ecx/edi/esi instead of this tapdance with outputs? */ - int ecx, edi, esi; - __asm__ __volatile__ ( - "cld \n\t" - "rep ; movsl \n\t" - : "=&c" (ecx), "=&D" (edi), "=&S" (esi) - : "0" (SDL_static_cast(unsigned, dwords)), "1" (dst), "2" (src) - : "memory" - ); - return dst; -#else - return SDL_memcpy(dst, src, dwords * 4); -#endif -} - -extern DECLSPEC void *SDLCALL SDL_memmove(void *dst, const void *src, size_t len); -#ifdef HAVE_MEMMOVE -SDL_FORCE_INLINE void *SDL_memmove_inline(void *dst, const void *src, size_t len) { return memmove(dst, src, len); } -#define SDL_memmove SDL_memmove_inline -#endif - +extern DECLSPEC void *SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len); -#ifdef HAVE_MEMCMP -SDL_FORCE_INLINE int SDL_memcmp_inline(const void *s1, const void *s2, size_t len) { return memcmp(s1, s2, len); } -#define SDL_memcmp SDL_memcmp_inline -#endif - -extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str); -#ifdef HAVE_STRLEN -SDL_FORCE_INLINE size_t SDL_strlen_inline(const char *str) { return strlen(str); } -#define SDL_strlen SDL_strlen_inline -#endif extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr); -#ifdef HAVE_WCSLEN -SDL_FORCE_INLINE size_t SDL_wcslen_inline(const wchar_t *wstr) { return wcslen(wstr); } -#define SDL_wcslen SDL_wcslen_inline -#endif +extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); +extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); +extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr); +extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle); -extern DECLSPEC size_t SDLCALL SDL_wcslcpy(wchar_t *dst, const wchar_t *src, size_t maxlen); -#ifdef HAVE_WCSLCPY -SDL_FORCE_INLINE size_t SDL_wcslcpy_inline(wchar_t *dst, const wchar_t *src, size_t maxlen) { return wcslcpy(dst, src, maxlen); } -#define SDL_wcslcpy SDL_wcslcpy_inline -#endif - -extern DECLSPEC size_t SDLCALL SDL_wcslcat(wchar_t *dst, const wchar_t *src, size_t maxlen); -#ifdef HAVE_WCSLCAT -SDL_FORCE_INLINE size_t SDL_wcslcat_inline(wchar_t *dst, const wchar_t *src, size_t maxlen) { return wcslcat(dst, src, maxlen); } -#define SDL_wcslcat SDL_wcslcat_inline -#endif - -extern DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen); -#ifdef HAVE_STRLCPY -SDL_FORCE_INLINE size_t SDL_strlcpy_inline(char *dst, const char *src, size_t maxlen) { return strlcpy(dst, src, maxlen); } -#define SDL_strlcpy SDL_strlcpy_inline -#else -#endif - -extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(char *dst, const char *src, size_t dst_bytes); - -extern DECLSPEC size_t SDLCALL SDL_strlcat(char *dst, const char *src, size_t maxlen); -#ifdef HAVE_STRLCAT -SDL_FORCE_INLINE size_t SDL_strlcat_inline(char *dst, const char *src, size_t maxlen) { return strlcat(dst, src, maxlen); } -#define SDL_strlcat SDL_strlcat_inline -#endif +extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2); +extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen); +extern DECLSPEC int SDLCALL SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2); +extern DECLSPEC int SDLCALL SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t len); +extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str); +extern DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen); +extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes); +extern DECLSPEC size_t SDLCALL SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen); extern DECLSPEC char *SDLCALL SDL_strdup(const char *str); -#ifdef HAVE_STRDUP -SDL_FORCE_INLINE char *SDL_strdup_inline(const char *str) { return strdup(str); } -#define SDL_strdup SDL_strdup_inline -#endif - extern DECLSPEC char *SDLCALL SDL_strrev(char *str); -#ifdef HAVE__STRREV -SDL_FORCE_INLINE char *SDL_strrev_inline(char *str) { return _strrev(str); } -#define SDL_strrev SDL_strrev_inline -#endif - extern DECLSPEC char *SDLCALL SDL_strupr(char *str); -#ifdef HAVE__STRUPR -SDL_FORCE_INLINE char *SDL_strupr_inline(char *str) { return _strupr(str); } -#define SDL_strupr SDL_strupr_inline -#endif - extern DECLSPEC char *SDLCALL SDL_strlwr(char *str); -#ifdef HAVE__STRLWR -SDL_FORCE_INLINE char *SDL_strlwr_inline(char *str) { return _strlwr(str); } -#define SDL_strlwr SDL_strlwr_inline -#endif - extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c); -#ifdef HAVE_STRCHR -SDL_FORCE_INLINE char *SDL_strchr_inline(const char *str, int c) { return (char*)strchr(str, c); } -#define SDL_strchr SDL_strchr_inline -#elif defined(HAVE_INDEX) /* !!! FIXME: is there anywhere that has this but not strchr? */ -SDL_FORCE_INLINE char *SDL_strchr_inline(const char *str, int c) { return index(str, c); } -#define SDL_strchr SDL_strchr_inline -#endif - extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c); -#ifdef HAVE_STRRCHR -SDL_FORCE_INLINE char *SDL_strrchr_inline(const char *str, int c) { return (char*)strrchr(str, c); } -#define SDL_strrchr SDL_strrchr_inline -#elif defined(HAVE_RINDEX) /* !!! FIXME: is there anywhere that has this but not strrchr? */ -SDL_FORCE_INLINE char *SDL_strrchr_inline(const char *str, int c) { return (char*)rindex(str, c); } -#define SDL_strrchr SDL_strrchr_inline -#endif - extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle); -#ifdef HAVE_STRSTR -SDL_FORCE_INLINE char *SDL_strstr_inline(const char *haystack, const char *needle) { return (char*)strstr(haystack, needle); } -#define SDL_strstr SDL_strstr_inline -#endif - -extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix); -#ifdef HAVE__LTOA -SDL_FORCE_INLINE char *SDL_ltoa_inline(long value, char *str, int radix) { return _ltoa(value, str, radix); } -#define SDL_ltoa SDL_ltoa_inline -#endif +extern DECLSPEC char *SDLCALL SDL_strtokr(char *s1, const char *s2, char **saveptr); +extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str); extern DECLSPEC char *SDLCALL SDL_itoa(int value, char *str, int radix); -#ifdef HAVE_ITOA -SDL_FORCE_INLINE char *SDL_itoa_inline(int value, char *str, int radix) { return itoa(value, str, radix); } -#else -SDL_FORCE_INLINE char *SDL_itoa_inline(int value, char *str, int radix) { return SDL_ltoa((long)value, str, radix); } -#endif -#define SDL_itoa SDL_itoa_inline - -extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix); -#ifdef HAVE__ULTOA -SDL_FORCE_INLINE char *SDL_ultoa_inline(unsigned long value, char *str, int radix) { return _ultoa(value, str, radix); } -#define SDL_ultoa SDL_ultoa_inline -#endif - extern DECLSPEC char *SDLCALL SDL_uitoa(unsigned int value, char *str, int radix); -#ifdef HAVE__UITOA -SDL_FORCE_INLINE char *SDL_uitoa_inline(unsigned int value, char *str, int radix) { return _uitoa(value, str, radix); } -#else -SDL_FORCE_INLINE char *SDL_uitoa_inline(unsigned int value, char *str, int radix) { return SDL_ultoa((unsigned long)value, str, radix); } -#endif -#define SDL_uitoa SDL_uitoa_inline - - -extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base); -#ifdef HAVE_STRTOL -SDL_FORCE_INLINE long SDL_strtol_inline(const char *str, char **endp, int base) { return strtol(str, endp, base); } -#define SDL_strtol SDL_strtol_inline -#endif - -extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base); -#ifdef HAVE_STRTOUL -SDL_FORCE_INLINE unsigned long SDLCALL SDL_strtoul_inline(const char *str, char **endp, int base) { return strtoul(str, endp, base); } -#define SDL_strtoul SDL_strtoul_inline -#endif - +extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix); +extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix); extern DECLSPEC char *SDLCALL SDL_lltoa(Sint64 value, char *str, int radix); -#ifdef HAVE__I64TOA -SDL_FORCE_INLINE char *SDL_lltoa_inline(Sint64 value, char *str, int radix) { return _i64toa(value, str, radix); } -#define SDL_lltoa SDL_lltoa_inline -#endif - extern DECLSPEC char *SDLCALL SDL_ulltoa(Uint64 value, char *str, int radix); -#ifdef HAVE__UI64TOA -SDL_FORCE_INLINE char *SDL_ulltoa_inline(Uint64 value, char *str, int radix) { return _ui64toa(value, str, radix); } -#define SDL_ulltoa SDL_ulltoa_inline -#endif - -extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *str, char **endp, int base); -#ifdef HAVE_STRTOLL -SDL_FORCE_INLINE Sint64 SDL_strtoll_inline(const char *str, char **endp, int base) { return strtoll(str, endp, base); } -#define SDL_strtoll SDL_strtoll_inline -#endif - -extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *str, char **endp, int base); -#ifdef HAVE_STRTOULL -SDL_FORCE_INLINE Uint64 SDL_strtoull_inline(const char *str, char **endp, int base) { return strtoull(str, endp, base); } -#define SDL_strtoull SDL_strtoull_inline -#endif - -extern DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp); -#ifdef HAVE_STRTOD -SDL_FORCE_INLINE double SDL_strtod_inline(const char *str, char **endp) { return strtod(str, endp); } -#define SDL_strtod SDL_strtod_inline -#endif extern DECLSPEC int SDLCALL SDL_atoi(const char *str); -#ifdef HAVE_ATOI -SDL_FORCE_INLINE int SDL_atoi_inline(const char *str) { return atoi(str); } -#else -SDL_FORCE_INLINE int SDL_atoi_inline(const char *str) { return SDL_strtol(str, NULL, 0); } -#endif -#define SDL_atoi SDL_atoi_inline - extern DECLSPEC double SDLCALL SDL_atof(const char *str); -#ifdef HAVE_ATOF -SDL_FORCE_INLINE double SDL_atof_inline(const char *str) { return (double) atof(str); } -#else -SDL_FORCE_INLINE double SDL_atof_inline(const char *str) { return SDL_strtod(str, NULL); } -#endif -#define SDL_atof SDL_atof_inline - +extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base); +extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base); +extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *str, char **endp, int base); +extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *str, char **endp, int base); +extern DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp); extern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2); -#ifdef HAVE_STRCMP -SDL_FORCE_INLINE int SDL_strcmp_inline(const char *str1, const char *str2) { return strcmp(str1, str2); } -#define SDL_strcmp SDL_strcmp_inline -#endif - extern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen); -#ifdef HAVE_STRNCMP -SDL_FORCE_INLINE int SDL_strncmp_inline(const char *str1, const char *str2, size_t maxlen) { return strncmp(str1, str2, maxlen); } -#define SDL_strncmp SDL_strncmp_inline -#endif - extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); -#ifdef HAVE_STRCASECMP -SDL_FORCE_INLINE int SDL_strcasecmp_inline(const char *str1, const char *str2) { return strcasecmp(str1, str2); } -#define SDL_strcasecmp SDL_strcasecmp_inline -#elif defined(HAVE__STRICMP) -SDL_FORCE_INLINE int SDL_strcasecmp_inline(const char *str1, const char *str2) { return _stricmp(str1, str2); } -#define SDL_strcasecmp SDL_strcasecmp_inline -#endif - extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len); -#ifdef HAVE_STRNCASECMP -SDL_FORCE_INLINE int SDL_strncasecmp_inline(const char *str1, const char *str2, size_t len) { return strncasecmp(str1, str2, len); } -#define SDL_strncasecmp SDL_strncasecmp_inline -#elif defined(HAVE__STRNICMP) -SDL_FORCE_INLINE int SDL_strncasecmp_inline(const char *str1, const char *str2, size_t len) { return _strnicmp(str1, str2, len); } -#define SDL_strncasecmp SDL_strncasecmp_inline -#endif -/* Not doing SDL_*_inline functions for these, because of the varargs. */ -extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, const char *fmt, ...); -#ifdef HAVE_SSCANF -#define SDL_sscanf sscanf -#endif - -extern DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...); -#ifdef HAVE_SNPRINTF -#define SDL_snprintf snprintf -#endif - -extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap); -#ifdef HAVE_VSNPRINTF -SDL_FORCE_INLINE int SDL_vsnprintf_inline(char *text, size_t maxlen, const char *fmt, va_list ap) { return vsnprintf(text, maxlen, fmt, ap); } -#define SDL_vsnprintf SDL_vsnprintf_inline -#endif +extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); +extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap); +extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3); +extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap); +extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap); #ifndef HAVE_M_PI #ifndef M_PI -#define M_PI 3.14159265358979323846264338327950288 /* pi */ +#define M_PI 3.14159265358979323846264338327950288 /**< pi */ #endif #endif +/** + * Use this function to compute arc cosine of `x`. + * + * The definition of `y = acos(x)` is `x = cos(y)`. + * + * Domain: `-1 <= x <= 1` + * + * Range: `0 <= y <= Pi` + * + * \param x floating point value, in radians. + * \returns arc cosine of `x`. + * + * \since This function is available since SDL 2.0.2. + */ +extern DECLSPEC double SDLCALL SDL_acos(double x); +extern DECLSPEC float SDLCALL SDL_acosf(float x); +extern DECLSPEC double SDLCALL SDL_asin(double x); +extern DECLSPEC float SDLCALL SDL_asinf(float x); extern DECLSPEC double SDLCALL SDL_atan(double x); -#ifdef HAVE_ATAN -SDL_FORCE_INLINE double SDL_atan_inline(double x) { return atan(x); } -#define SDL_atan SDL_atan_inline -#endif - -extern DECLSPEC double SDLCALL SDL_atan2(double x, double y); -#ifdef HAVE_ATAN2 -SDL_FORCE_INLINE double SDL_atan2_inline(double x, double y) { return atan2(x, y); } -#define SDL_atan2 SDL_atan2_inline -#endif - +extern DECLSPEC float SDLCALL SDL_atanf(float x); +extern DECLSPEC double SDLCALL SDL_atan2(double y, double x); +extern DECLSPEC float SDLCALL SDL_atan2f(float y, float x); extern DECLSPEC double SDLCALL SDL_ceil(double x); -#ifdef HAVE_CEIL -SDL_FORCE_INLINE double SDL_ceil_inline(double x) { return ceil(x); } -#else -SDL_FORCE_INLINE double SDL_ceil_inline(double x) { return (double)(int)((x)+0.5); } -#endif -#define SDL_ceil SDL_ceil_inline - +extern DECLSPEC float SDLCALL SDL_ceilf(float x); extern DECLSPEC double SDLCALL SDL_copysign(double x, double y); -#ifdef HAVE_COPYSIGN -SDL_FORCE_INLINE double SDL_copysign_inline(double x, double y) { return copysign(x, y); } -#define SDL_copysign SDL_copysign_inline -#endif - +extern DECLSPEC float SDLCALL SDL_copysignf(float x, float y); extern DECLSPEC double SDLCALL SDL_cos(double x); -#ifdef HAVE_COS -SDL_FORCE_INLINE double SDL_cos_inline(double x) { return cos(x); } -#define SDL_cos SDL_cos_inline -#endif - extern DECLSPEC float SDLCALL SDL_cosf(float x); -#ifdef HAVE_COSF -SDL_FORCE_INLINE float SDL_cosf_inline(float x) { return cosf(x); } -#else -SDL_FORCE_INLINE float SDL_cosf_inline(float x) { return (float)SDL_cos((double)x); } -#endif -#define SDL_cosf SDL_cosf_inline - +extern DECLSPEC double SDLCALL SDL_exp(double x); +extern DECLSPEC float SDLCALL SDL_expf(float x); extern DECLSPEC double SDLCALL SDL_fabs(double x); -#ifdef HAVE_FABS -SDL_FORCE_INLINE double SDL_fabs_inline(double x) { return fabs(x); } -#define SDL_fabs SDL_fabs_inline -#endif - +extern DECLSPEC float SDLCALL SDL_fabsf(float x); extern DECLSPEC double SDLCALL SDL_floor(double x); -#ifdef HAVE_FLOOR -SDL_FORCE_INLINE double SDL_floor_inline(double x) { return floor(x); } -#define SDL_floor SDL_floor_inline -#endif - +extern DECLSPEC float SDLCALL SDL_floorf(float x); +extern DECLSPEC double SDLCALL SDL_trunc(double x); +extern DECLSPEC float SDLCALL SDL_truncf(float x); +extern DECLSPEC double SDLCALL SDL_fmod(double x, double y); +extern DECLSPEC float SDLCALL SDL_fmodf(float x, float y); extern DECLSPEC double SDLCALL SDL_log(double x); -#ifdef HAVE_LOG -SDL_FORCE_INLINE double SDL_log_inline(double x) { return log(x); } -#define SDL_log SDL_log_inline -#endif - +extern DECLSPEC float SDLCALL SDL_logf(float x); +extern DECLSPEC double SDLCALL SDL_log10(double x); +extern DECLSPEC float SDLCALL SDL_log10f(float x); extern DECLSPEC double SDLCALL SDL_pow(double x, double y); -#ifdef HAVE_POW -SDL_FORCE_INLINE double SDL_pow_inline(double x, double y) { return pow(x, y); } -#define SDL_pow SDL_pow_inline -#endif - +extern DECLSPEC float SDLCALL SDL_powf(float x, float y); +extern DECLSPEC double SDLCALL SDL_round(double x); +extern DECLSPEC float SDLCALL SDL_roundf(float x); +extern DECLSPEC long SDLCALL SDL_lround(double x); +extern DECLSPEC long SDLCALL SDL_lroundf(float x); extern DECLSPEC double SDLCALL SDL_scalbn(double x, int n); -#ifdef HAVE_SCALBN -SDL_FORCE_INLINE double SDL_scalbn_inline(double x, int n) { return scalbn(x, n); } -#define SDL_scalbn SDL_scalbn_inline -#endif - +extern DECLSPEC float SDLCALL SDL_scalbnf(float x, int n); extern DECLSPEC double SDLCALL SDL_sin(double x); -#ifdef HAVE_SIN -SDL_FORCE_INLINE double SDL_sin_inline(double x) { return sin(x); } -#define SDL_sin SDL_sin_inline -#endif - extern DECLSPEC float SDLCALL SDL_sinf(float x); -#ifdef HAVE_SINF -SDL_FORCE_INLINE float SDL_sinf_inline(float x) { return sinf(x); } -#else -SDL_FORCE_INLINE float SDL_sinf_inline(float x) { return (float)SDL_sin((double)x); } -#endif -#define SDL_sinf SDL_sinf_inline - extern DECLSPEC double SDLCALL SDL_sqrt(double x); -#ifdef HAVE_SQRT -SDL_FORCE_INLINE double SDL_sqrt_inline(double x) { return sqrt(x); } -#define SDL_sqrt SDL_sqrt_inline -#endif +extern DECLSPEC float SDLCALL SDL_sqrtf(float x); +extern DECLSPEC double SDLCALL SDL_tan(double x); +extern DECLSPEC float SDLCALL SDL_tanf(float x); /* The SDL implementation of iconv() returns these error codes */ -#define SDL_ICONV_ERROR (size_t)-1 -#define SDL_ICONV_E2BIG (size_t)-2 -#define SDL_ICONV_EILSEQ (size_t)-3 -#define SDL_ICONV_EINVAL (size_t)-4 +#define SDL_ICONV_ERROR (size_t)-1 +#define SDL_ICONV_E2BIG (size_t)-2 +#define SDL_ICONV_EILSEQ (size_t)-3 +#define SDL_ICONV_EINVAL (size_t)-4 /* SDL_iconv_* are now always real symbols/types, not macros or inlined. */ typedef struct _SDL_iconv_t *SDL_iconv_t; @@ -770,26 +640,80 @@ extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd); extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, size_t * inbytesleft, char **outbuf, size_t * outbytesleft); + /** - * This function converts a string between encodings in one pass, returning a - * string that must be freed with SDL_free() or NULL on error. + * This function converts a string between encodings in one pass, returning a + * string that must be freed with SDL_free() or NULL on error. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf, size_t inbytesleft); -#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) + +/* force builds using Clang's static analysis tools to use literal C runtime + here, since there are possibly tests that are ineffective otherwise. */ +#if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS) + +/* The analyzer knows about strlcpy even when the system doesn't provide it */ +#ifndef HAVE_STRLCPY +size_t strlcpy(char* dst, const char* src, size_t size); +#endif + +/* The analyzer knows about strlcat even when the system doesn't provide it */ +#ifndef HAVE_STRLCAT +size_t strlcat(char* dst, const char* src, size_t size); +#endif + +#define SDL_malloc malloc +#define SDL_calloc calloc +#define SDL_realloc realloc +#define SDL_free free +#define SDL_memset memset +#define SDL_memcpy memcpy +#define SDL_memmove memmove +#define SDL_memcmp memcmp +#define SDL_strlcpy strlcpy +#define SDL_strlcat strlcat +#define SDL_strlen strlen +#define SDL_wcslen wcslen +#define SDL_wcslcpy wcslcpy +#define SDL_wcslcat wcslcat +#define SDL_strdup strdup +#define SDL_wcsdup wcsdup +#define SDL_strchr strchr +#define SDL_strrchr strrchr +#define SDL_strstr strstr +#define SDL_wcsstr wcsstr +#define SDL_strtokr strtok_r +#define SDL_strcmp strcmp +#define SDL_wcscmp wcscmp +#define SDL_strncmp strncmp +#define SDL_wcsncmp wcsncmp +#define SDL_strcasecmp strcasecmp +#define SDL_strncasecmp strncasecmp +#define SDL_sscanf sscanf +#define SDL_vsscanf vsscanf +#define SDL_snprintf snprintf +#define SDL_vsnprintf vsnprintf +#endif + +SDL_FORCE_INLINE void *SDL_memcpy4(SDL_OUT_BYTECAP(dwords*4) void *dst, SDL_IN_BYTECAP(dwords*4) const void *src, size_t dwords) +{ + return SDL_memcpy(dst, src, dwords * 4); +} /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_stdinc_h */ +#endif /* SDL_stdinc_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_surface.h b/external/SDL2/SDL_surface.h index 275beb6..4412376 100644 --- a/external/SDL2/SDL_surface.h +++ b/external/SDL2/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_surface.h - * - * Header file for ::SDL_surface definition and management functions. + * + * Header file for ::SDL_Surface definition and management functions. */ -#ifndef _SDL_surface_h -#define _SDL_surface_h +#ifndef SDL_surface_h_ +#define SDL_surface_h_ #include "SDL_stdinc.h" #include "SDL_pixels.h" @@ -37,30 +37,29 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \name Surface flags - * - * These are the currently supported flags for the ::SDL_surface. - * + * + * These are the currently supported flags for the ::SDL_Surface. + * * \internal * Used internally (read-only). */ -/*@{*/ +/* @{ */ #define SDL_SWSURFACE 0 /**< Just here for compatibility */ #define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ #define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ #define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ -/*@}*//*Surface flags*/ +#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ +/* @} *//* Surface flags */ /** * Evaluates to true if the surface needs to be locked before access. */ -#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0) +#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0) /** * \brief A collection of pixels used in software blitting. @@ -81,7 +80,9 @@ typedef struct SDL_Surface /** information needed for surfaces requiring locks */ int locked; /**< Read-only */ - void *lock_data; /**< Read-only */ + + /** list of BlitMap that hold a reference to this surface */ + void *list_blitmap; /**< Private */ /** clipping information */ SDL_Rect clip_rect; /**< Read-only */ @@ -96,23 +97,123 @@ typedef struct SDL_Surface /** * \brief The type of function used for surface blitting functions. */ -typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, - struct SDL_Surface * dst, SDL_Rect * dstrect); +typedef int (SDLCALL *SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, + struct SDL_Surface * dst, SDL_Rect * dstrect); /** - * Allocate and free an RGB surface. - * - * If the depth is 4 or 8 bits, an empty palette is allocated for the surface. - * If the depth is greater than 8 bits, the pixel format is set using the - * flags '[RGB]mask'. - * - * If the function runs out of memory, it will return NULL. - * - * \param flags The \c flags are obsolete and should be set to 0. + * \brief The formula used for converting between YUV and RGB + */ +typedef enum +{ + SDL_YUV_CONVERSION_JPEG, /**< Full range JPEG */ + SDL_YUV_CONVERSION_BT601, /**< BT.601 (the default) */ + SDL_YUV_CONVERSION_BT709, /**< BT.709 */ + SDL_YUV_CONVERSION_AUTOMATIC /**< BT.601 for SD content, BT.709 for HD content */ +} SDL_YUV_CONVERSION_MODE; + +/** + * Allocate a new RGB surface. + * + * If `depth` is 4 or 8 bits, an empty palette is allocated for the surface. + * If `depth` is greater than 8 bits, the pixel format is set using the + * [RGBA]mask parameters. + * + * The [RGBA]mask parameters are the bitmasks used to extract that color from + * a pixel. For instance, `Rmask` being 0xFF000000 means the red data is + * stored in the most significant byte. Using zeros for the RGB masks sets a + * default value, based on the depth. For example: + * + * ```c++ + * SDL_CreateRGBSurface(0,w,h,32,0,0,0,0); + * ``` + * + * However, using zero for the Amask results in an Amask of 0. + * + * By default surfaces with an alpha mask are set up for blending as with: + * + * ```c++ + * SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND) + * ``` + * + * You can change this by calling SDL_SetSurfaceBlendMode() and selecting a + * different `blendMode`. + * + * \param flags the flags are unused and should be set to 0 + * \param width the width of the surface + * \param height the height of the surface + * \param depth the depth of the surface in bits + * \param Rmask the red mask for the pixels + * \param Gmask the green mask for the pixels + * \param Bmask the blue mask for the pixels + * \param Amask the alpha mask for the pixels + * \returns the new SDL_Surface structure that is created or NULL if it fails; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRGBSurfaceFrom + * \sa SDL_CreateRGBSurfaceWithFormat + * \sa SDL_FreeSurface */ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface (Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + + +/* !!! FIXME for 2.1: why does this ask for depth? Format provides that. */ + +/** + * Allocate a new RGB surface with a specific pixel format. + * + * This function operates mostly like SDL_CreateRGBSurface(), except instead + * of providing pixel color masks, you provide it with a predefined format + * from SDL_PixelFormatEnum. + * + * \param flags the flags are unused and should be set to 0 + * \param width the width of the surface + * \param height the height of the surface + * \param depth the depth of the surface in bits + * \param format the SDL_PixelFormatEnum for the new surface's pixel format. + * \returns the new SDL_Surface structure that is created or NULL if it fails; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_CreateRGBSurface + * \sa SDL_CreateRGBSurfaceFrom + * \sa SDL_FreeSurface + */ +extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormat + (Uint32 flags, int width, int height, int depth, Uint32 format); + +/** + * Allocate a new RGB surface with existing pixel data. + * + * This function operates mostly like SDL_CreateRGBSurface(), except it does + * not allocate memory for the pixel data, instead the caller provides an + * existing buffer of data for the surface to use. + * + * No copy is made of the pixel data. Pixel data is not managed automatically; + * you must free the surface before you free the pixel data. + * + * \param pixels a pointer to existing pixel data + * \param width the width of the surface + * \param height the height of the surface + * \param depth the depth of the surface in bits + * \param pitch the pitch of the surface in bytes + * \param Rmask the red mask for the pixels + * \param Gmask the green mask for the pixels + * \param Bmask the blue mask for the pixels + * \param Amask the alpha mask for the pixels + * \returns the new SDL_Surface structure that is created or NULL if it fails; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRGBSurface + * \sa SDL_CreateRGBSurfaceWithFormat + * \sa SDL_FreeSurface + */ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, @@ -122,244 +223,496 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + +/* !!! FIXME for 2.1: why does this ask for depth? Format provides that. */ + +/** + * Allocate a new RGB surface with with a specific pixel format and existing + * pixel data. + * + * This function operates mostly like SDL_CreateRGBSurfaceFrom(), except + * instead of providing pixel color masks, you provide it with a predefined + * format from SDL_PixelFormatEnum. + * + * No copy is made of the pixel data. Pixel data is not managed automatically; + * you must free the surface before you free the pixel data. + * + * \param pixels a pointer to existing pixel data + * \param width the width of the surface + * \param height the height of the surface + * \param depth the depth of the surface in bits + * \param pitch the pitch of the surface in bytes + * \param format the SDL_PixelFormatEnum for the new surface's pixel format. + * \returns the new SDL_Surface structure that is created or NULL if it fails; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_CreateRGBSurfaceFrom + * \sa SDL_CreateRGBSurfaceWithFormat + * \sa SDL_FreeSurface + */ +extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormatFrom + (void *pixels, int width, int height, int depth, int pitch, Uint32 format); + +/** + * Free an RGB surface. + * + * It is safe to pass NULL to this function. + * + * \param surface the SDL_Surface to free. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateRGBSurface + * \sa SDL_CreateRGBSurfaceFrom + * \sa SDL_LoadBMP + * \sa SDL_LoadBMP_RW + */ extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface); /** - * \brief Set the palette used by a surface. - * - * \return 0, or -1 if the surface format doesn't use a palette. - * - * \note A single palette can be shared with many surfaces. + * Set the palette used by a surface. + * + * A single palette can be shared with many surfaces. + * + * \param surface the SDL_Surface structure to update + * \param palette the SDL_Palette structure to use + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette); /** - * \brief Sets up a surface for directly accessing the pixels. - * - * Between calls to SDL_LockSurface() / SDL_UnlockSurface(), you can write - * to and read from \c surface->pixels, using the pixel format stored in - * \c surface->format. Once you are done accessing the surface, you should - * use SDL_UnlockSurface() to release it. - * - * Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates - * to 0, then you can read and write to the surface at any time, and the - * pixel format of the surface will not change. - * - * No operating system or library calls should be made between lock/unlock - * pairs, as critical system locks may be held during this time. - * - * SDL_LockSurface() returns 0, or -1 if the surface couldn't be locked. - * - * \sa SDL_UnlockSurface() + * Set up a surface for directly accessing the pixels. + * + * Between calls to SDL_LockSurface() / SDL_UnlockSurface(), you can write to + * and read from `surface->pixels`, using the pixel format stored in + * `surface->format`. Once you are done accessing the surface, you should use + * SDL_UnlockSurface() to release it. + * + * Not all surfaces require locking. If `SDL_MUSTLOCK(surface)` evaluates to + * 0, then you can read and write to the surface at any time, and the pixel + * format of the surface will not change. + * + * \param surface the SDL_Surface structure to be locked + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_MUSTLOCK + * \sa SDL_UnlockSurface */ extern DECLSPEC int SDLCALL SDL_LockSurface(SDL_Surface * surface); -/** \sa SDL_LockSurface() */ + +/** + * Release a surface after directly accessing the pixels. + * + * \param surface the SDL_Surface structure to be unlocked + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LockSurface + */ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface * surface); /** - * Load a surface from a seekable SDL data stream (memory or file). - * - * If \c freesrc is non-zero, the stream will be closed after being read. - * - * The new surface should be freed with SDL_FreeSurface(). - * - * \return the new surface, or NULL if there was an error. + * Load a BMP image from a seekable SDL data stream. + * + * The new surface should be freed with SDL_FreeSurface(). Not doing so will + * result in a memory leak. + * + * src is an open SDL_RWops buffer, typically loaded with SDL_RWFromFile. + * Alternitavely, you might also use the macro SDL_LoadBMP to load a bitmap + * from a file, convert it to an SDL_Surface and then close the file. + * + * \param src the data stream for the surface + * \param freesrc non-zero to close the stream after being read + * \returns a pointer to a new SDL_Surface structure or NULL if there was an + * error; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FreeSurface + * \sa SDL_RWFromFile + * \sa SDL_LoadBMP + * \sa SDL_SaveBMP_RW */ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops * src, int freesrc); /** - * Load a surface from a file. - * - * Convenience macro. + * Load a surface from a file. + * + * Convenience macro. */ -#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) +#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) /** - * Save a surface to a seekable SDL data stream (memory or file). - * - * If \c freedst is non-zero, the stream will be closed after being written. - * - * \return 0 if successful or -1 if there was an error. + * Save a surface to a seekable SDL data stream in BMP format. + * + * Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the + * BMP directly. Other RGB formats with 8-bit or higher get converted to a + * 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit + * surface before they are saved. YUV and paletted 1-bit and 4-bit formats are + * not supported. + * + * \param surface the SDL_Surface structure containing the image to be saved + * \param dst a data stream to save to + * \param freedst non-zero to close the stream after being written + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_LoadBMP_RW + * \sa SDL_SaveBMP */ extern DECLSPEC int SDLCALL SDL_SaveBMP_RW (SDL_Surface * surface, SDL_RWops * dst, int freedst); -/** +/** * Save a surface to a file. - * + * * Convenience macro. */ #define SDL_SaveBMP(surface, file) \ - SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) + SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) /** - * \brief Sets the RLE acceleration hint for a surface. - * - * \return 0 on success, or -1 if the surface is not valid - * - * \note If RLE is enabled, colorkey and alpha blending blits are much faster, - * but the surface must be locked before directly accessing the pixels. + * Set the RLE acceleration hint for a surface. + * + * If RLE is enabled, color key and alpha blending blits are much faster, but + * the surface must be locked before directly accessing the pixels. + * + * \param surface the SDL_Surface structure to optimize + * \param flag 0 to disable, non-zero to enable RLE acceleration + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface + * \sa SDL_LockSurface + * \sa SDL_UnlockSurface */ extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface * surface, int flag); /** - * \brief Sets the color key (transparent pixel) in a blittable surface. - * - * \param surface The surface to update - * \param flag Non-zero to enable colorkey and 0 to disable colorkey - * \param key The transparent pixel in the native surface format - * - * \return 0 on success, or -1 if the surface is not valid + * Returns whether the surface is RLE enabled * - * You can pass SDL_RLEACCEL to enable RLE accelerated blits. + * It is safe to pass a NULL `surface` here; it will return SDL_FALSE. + * + * \param surface the SDL_Surface structure to query + * \returns SDL_TRUE if the surface is RLE enabled, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + * + * \sa SDL_SetSurfaceRLE + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasSurfaceRLE(SDL_Surface * surface); + +/** + * Set the color key (transparent pixel) in a surface. + * + * The color key defines a pixel value that will be treated as transparent in + * a blit. For example, one can use this to specify that cyan pixels should be + * considered transparent, and therefore not rendered. + * + * It is a pixel of the format used by the surface, as generated by + * SDL_MapRGB(). + * + * RLE acceleration can substantially speed up blitting of images with large + * horizontal runs of transparent pixels. See SDL_SetSurfaceRLE() for details. + * + * \param surface the SDL_Surface structure to update + * \param flag SDL_TRUE to enable color key, SDL_FALSE to disable color key + * \param key the transparent pixel + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface + * \sa SDL_GetColorKey */ extern DECLSPEC int SDLCALL SDL_SetColorKey(SDL_Surface * surface, int flag, Uint32 key); /** - * \brief Gets the color key (transparent pixel) in a blittable surface. - * - * \param surface The surface to update - * \param key A pointer filled in with the transparent pixel in the native - * surface format - * - * \return 0 on success, or -1 if the surface is not valid or colorkey is not - * enabled. + * Returns whether the surface has a color key + * + * It is safe to pass a NULL `surface` here; it will return SDL_FALSE. + * + * \param surface the SDL_Surface structure to query + * \return SDL_TRUE if the surface has a color key, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.9. + * + * \sa SDL_SetColorKey + * \sa SDL_GetColorKey + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasColorKey(SDL_Surface * surface); + +/** + * Get the color key (transparent pixel) for a surface. + * + * The color key is a pixel of the format used by the surface, as generated by + * SDL_MapRGB(). + * + * If the surface doesn't have color key enabled this function returns -1. + * + * \param surface the SDL_Surface structure to query + * \param key a pointer filled in with the transparent pixel + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface + * \sa SDL_SetColorKey */ extern DECLSPEC int SDLCALL SDL_GetColorKey(SDL_Surface * surface, Uint32 * key); /** - * \brief Set an additional color value used in blit operations. - * - * \param surface The surface to update. - * \param r The red color value multiplied into blit operations. - * \param g The green color value multiplied into blit operations. - * \param b The blue color value multiplied into blit operations. - * - * \return 0 on success, or -1 if the surface is not valid. - * - * \sa SDL_GetSurfaceColorMod() + * Set an additional color value multiplied into blit operations. + * + * When this surface is blitted, during the blit operation each source color + * channel is modulated by the appropriate color value according to the + * following formula: + * + * `srcC = srcC * (color / 255)` + * + * \param surface the SDL_Surface structure to update + * \param r the red color value multiplied into blit operations + * \param g the green color value multiplied into blit operations + * \param b the blue color value multiplied into blit operations + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetSurfaceColorMod + * \sa SDL_SetSurfaceAlphaMod */ extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface * surface, Uint8 r, Uint8 g, Uint8 b); /** - * \brief Get the additional color value used in blit operations. - * - * \param surface The surface to query. - * \param r A pointer filled in with the current red color value. - * \param g A pointer filled in with the current green color value. - * \param b A pointer filled in with the current blue color value. - * - * \return 0 on success, or -1 if the surface is not valid. - * - * \sa SDL_SetSurfaceColorMod() + * Get the additional color value multiplied into blit operations. + * + * \param surface the SDL_Surface structure to query + * \param r a pointer filled in with the current red color value + * \param g a pointer filled in with the current green color value + * \param b a pointer filled in with the current blue color value + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetSurfaceAlphaMod + * \sa SDL_SetSurfaceColorMod */ extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface * surface, Uint8 * r, Uint8 * g, Uint8 * b); /** - * \brief Set an additional alpha value used in blit operations. - * - * \param surface The surface to update. - * \param alpha The alpha value multiplied into blit operations. - * - * \return 0 on success, or -1 if the surface is not valid. - * - * \sa SDL_GetSurfaceAlphaMod() + * Set an additional alpha value used in blit operations. + * + * When this surface is blitted, during the blit operation the source alpha + * value is modulated by this alpha value according to the following formula: + * + * `srcA = srcA * (alpha / 255)` + * + * \param surface the SDL_Surface structure to update + * \param alpha the alpha value multiplied into blit operations + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetSurfaceAlphaMod + * \sa SDL_SetSurfaceColorMod */ extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface * surface, Uint8 alpha); /** - * \brief Get the additional alpha value used in blit operations. - * - * \param surface The surface to query. - * \param alpha A pointer filled in with the current alpha value. - * - * \return 0 on success, or -1 if the surface is not valid. - * - * \sa SDL_SetSurfaceAlphaMod() + * Get the additional alpha value used in blit operations. + * + * \param surface the SDL_Surface structure to query + * \param alpha a pointer filled in with the current alpha value + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetSurfaceColorMod + * \sa SDL_SetSurfaceAlphaMod */ extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface * surface, Uint8 * alpha); /** - * \brief Set the blend mode used for blit operations. - * - * \param surface The surface to update. - * \param blendMode ::SDL_BlendMode to use for blit blending. - * - * \return 0 on success, or -1 if the parameters are not valid. - * - * \sa SDL_GetSurfaceBlendMode() + * Set the blend mode used for blit operations. + * + * To copy a surface to another surface (or texture) without blending with the + * existing data, the blendmode of the SOURCE surface should be set to + * `SDL_BLENDMODE_NONE`. + * + * \param surface the SDL_Surface structure to update + * \param blendMode the SDL_BlendMode to use for blit blending + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetSurfaceBlendMode */ extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode blendMode); /** - * \brief Get the blend mode used for blit operations. - * - * \param surface The surface to query. - * \param blendMode A pointer filled in with the current blend mode. - * - * \return 0 on success, or -1 if the surface is not valid. - * - * \sa SDL_SetSurfaceBlendMode() + * Get the blend mode used for blit operations. + * + * \param surface the SDL_Surface structure to query + * \param blendMode a pointer filled in with the current SDL_BlendMode + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetSurfaceBlendMode */ extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode *blendMode); /** - * Sets the clipping rectangle for the destination surface in a blit. - * - * If the clip rectangle is NULL, clipping will be disabled. - * - * If the clip rectangle doesn't intersect the surface, the function will - * return SDL_FALSE and blits will be completely clipped. Otherwise the - * function returns SDL_TRUE and blits to the surface will be clipped to - * the intersection of the surface area and the clipping rectangle. - * - * Note that blits are automatically clipped to the edges of the source - * and destination surfaces. + * Set the clipping rectangle for a surface. + * + * When `surface` is the destination of a blit, only the area within the clip + * rectangle is drawn into. + * + * Note that blits are automatically clipped to the edges of the source and + * destination surfaces. + * + * \param surface the SDL_Surface structure to be clipped + * \param rect the SDL_Rect structure representing the clipping rectangle, or + * NULL to disable clipping + * \returns SDL_TRUE if the rectangle intersects the surface, otherwise + * SDL_FALSE and blits will be completely clipped. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface + * \sa SDL_GetClipRect */ extern DECLSPEC SDL_bool SDLCALL SDL_SetClipRect(SDL_Surface * surface, const SDL_Rect * rect); /** - * Gets the clipping rectangle for the destination surface in a blit. - * - * \c rect must be a pointer to a valid rectangle which will be filled - * with the correct values. + * Get the clipping rectangle for a surface. + * + * When `surface` is the destination of a blit, only the area within the clip + * rectangle is drawn into. + * + * \param surface the SDL_Surface structure representing the surface to be + * clipped + * \param rect an SDL_Rect structure filled in with the clipping rectangle for + * the surface + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface + * \sa SDL_SetClipRect */ extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface * surface, SDL_Rect * rect); +/* + * Creates a new surface identical to the existing surface. + * + * The returned surface should be freed with SDL_FreeSurface(). + * + * \param surface the surface to duplicate. + * \returns a copy of the surface, or NULL on failure; call SDL_GetError() for + * more information. + */ +extern DECLSPEC SDL_Surface *SDLCALL SDL_DuplicateSurface(SDL_Surface * surface); + /** - * Creates a new surface of the specified format, and then copies and maps - * the given surface to it so the blit of the converted surface will be as - * fast as possible. If this function fails, it returns NULL. - * - * The \c flags parameter is passed to SDL_CreateRGBSurface() and has those - * semantics. You can also pass ::SDL_RLEACCEL in the flags parameter and - * SDL will try to RLE accelerate colorkey and alpha blits in the resulting - * surface. + * Copy an existing surface to a new surface of the specified format. + * + * This function is used to optimize images for faster *repeat* blitting. This + * is accomplished by converting the original and storing the result as a new + * surface. The new, optimized surface can then be used as the source for + * future blits, making them faster. + * + * \param src the existing SDL_Surface structure to convert + * \param fmt the SDL_PixelFormat structure that the new surface is optimized + * for + * \param flags the flags are unused and should be set to 0; this is a + * leftover from SDL 1.2's API + * \returns the new SDL_Surface structure that is created or NULL if it fails; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocFormat + * \sa SDL_ConvertSurfaceFormat + * \sa SDL_CreateRGBSurface */ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface - (SDL_Surface * src, SDL_PixelFormat * fmt, Uint32 flags); + (SDL_Surface * src, const SDL_PixelFormat * fmt, Uint32 flags); + +/** + * Copy an existing surface to a new surface of the specified format enum. + * + * This function operates just like SDL_ConvertSurface(), but accepts an + * SDL_PixelFormatEnum value instead of an SDL_PixelFormat structure. As such, + * it might be easier to call but it doesn't have access to palette + * information for the destination surface, in case that would be important. + * + * \param src the existing SDL_Surface structure to convert + * \param pixel_format the SDL_PixelFormatEnum that the new surface is + * optimized for + * \param flags the flags are unused and should be set to 0; this is a + * leftover from SDL 1.2's API + * \returns the new SDL_Surface structure that is created or NULL if it fails; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AllocFormat + * \sa SDL_ConvertSurface + * \sa SDL_CreateRGBSurface + */ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat (SDL_Surface * src, Uint32 pixel_format, Uint32 flags); /** - * \brief Copy a block of pixels of one format to another format - * - * \return 0 on success, or -1 if there was an error + * Copy a block of pixels of one format to another format. + * + * \param width the width of the block to copy, in pixels + * \param height the height of the block to copy, in pixels + * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format + * \param src a pointer to the source pixels + * \param src_pitch the pitch of the source pixels, in bytes + * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format + * \param dst a pointer to be filled in with new pixel data + * \param dst_pitch the pitch of the destination pixels, in bytes + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, Uint32 src_format, @@ -368,135 +721,275 @@ extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, void * dst, int dst_pitch); /** - * Performs a fast fill of the given rectangle with \c color. - * - * If \c rect is NULL, the whole surface will be filled with \c color. - * - * The color should be a pixel of the format used by the surface, and - * can be generated by the SDL_MapRGB() function. - * - * \return 0 on success, or -1 on error. + * Premultiply the alpha on a block of pixels. + * + * This is safe to use with src == dst, but not for other overlapping areas. + * + * This function is currently only implemented for SDL_PIXELFORMAT_ARGB8888. + * + * \param width the width of the block to convert, in pixels + * \param height the height of the block to convert, in pixels + * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format + * \param src a pointer to the source pixels + * \param src_pitch the pitch of the source pixels, in bytes + * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format + * \param dst a pointer to be filled in with premultiplied pixel data + * \param dst_pitch the pitch of the destination pixels, in bytes + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_PremultiplyAlpha(int width, int height, + Uint32 src_format, + const void * src, int src_pitch, + Uint32 dst_format, + void * dst, int dst_pitch); + +/** + * Perform a fast fill of a rectangle with a specific color. + * + * `color` should be a pixel of the format used by the surface, and can be + * generated by SDL_MapRGB() or SDL_MapRGBA(). If the color value contains an + * alpha component then the destination is simply filled with that alpha + * information, no blending takes place. + * + * If there is a clip rectangle set on the destination (set via + * SDL_SetClipRect()), then this function will fill based on the intersection + * of the clip rectangle and `rect`. + * + * \param dst the SDL_Surface structure that is the drawing target + * \param rect the SDL_Rect structure representing the rectangle to fill, or + * NULL to fill the entire surface + * \param color the color to fill with + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FillRects */ extern DECLSPEC int SDLCALL SDL_FillRect (SDL_Surface * dst, const SDL_Rect * rect, Uint32 color); + +/** + * Perform a fast fill of a set of rectangles with a specific color. + * + * `color` should be a pixel of the format used by the surface, and can be + * generated by SDL_MapRGB() or SDL_MapRGBA(). If the color value contains an + * alpha component then the destination is simply filled with that alpha + * information, no blending takes place. + * + * If there is a clip rectangle set on the destination (set via + * SDL_SetClipRect()), then this function will fill based on the intersection + * of the clip rectangle and `rect`. + * + * \param dst the SDL_Surface structure that is the drawing target + * \param rects an array of SDL_Rects representing the rectangles to fill. + * \param count the number of rectangles in the array + * \param color the color to fill with + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_FillRect + */ extern DECLSPEC int SDLCALL SDL_FillRects (SDL_Surface * dst, const SDL_Rect * rects, int count, Uint32 color); +/* !!! FIXME: merge this documentation with the wiki */ /** * Performs a fast blit from the source surface to the destination surface. - * + * * This assumes that the source and destination rectangles are * the same size. If either \c srcrect or \c dstrect are NULL, the entire * surface (\c src or \c dst) is copied. The final blit rectangles are saved * in \c srcrect and \c dstrect after all clipping is performed. - * - * \return If the blit is successful, it returns 0, otherwise it returns -1. + * + * \returns 0 if the blit is successful, otherwise it returns -1. * * The blit function should not be called on a locked surface. * - * The blit semantics for surfaces with and without alpha and colorkey + * The blit semantics for surfaces with and without blending and colorkey * are defined as follows: * \verbatim RGBA->RGB: - SDL_SRCALPHA set: - alpha-blend (using alpha-channel). + Source surface blend mode set to SDL_BLENDMODE_BLEND: + alpha-blend (using the source alpha-channel and per-surface alpha) SDL_SRCCOLORKEY ignored. - SDL_SRCALPHA not set: + Source surface blend mode set to SDL_BLENDMODE_NONE: copy RGB. if SDL_SRCCOLORKEY set, only copy the pixels matching the - RGB values of the source colour key, ignoring alpha in the + RGB values of the source color key, ignoring alpha in the comparison. - + RGB->RGBA: - SDL_SRCALPHA set: - alpha-blend (using the source per-surface alpha value); - set destination alpha to opaque. - SDL_SRCALPHA not set: + Source surface blend mode set to SDL_BLENDMODE_BLEND: + alpha-blend (using the source per-surface alpha) + Source surface blend mode set to SDL_BLENDMODE_NONE: copy RGB, set destination alpha to source per-surface alpha value. both: if SDL_SRCCOLORKEY set, only copy the pixels matching the - source colour key. - + source color key. + RGBA->RGBA: - SDL_SRCALPHA set: - alpha-blend (using the source alpha channel) the RGB values; - leave destination alpha untouched. [Note: is this correct?] + Source surface blend mode set to SDL_BLENDMODE_BLEND: + alpha-blend (using the source alpha-channel and per-surface alpha) SDL_SRCCOLORKEY ignored. - SDL_SRCALPHA not set: + Source surface blend mode set to SDL_BLENDMODE_NONE: copy all of RGBA to the destination. if SDL_SRCCOLORKEY set, only copy the pixels matching the - RGB values of the source colour key, ignoring alpha in the - comparison. - - RGB->RGB: - SDL_SRCALPHA set: - alpha-blend (using the source per-surface alpha value). - SDL_SRCALPHA not set: + RGB values of the source color key, ignoring alpha in the + comparison. + + RGB->RGB: + Source surface blend mode set to SDL_BLENDMODE_BLEND: + alpha-blend (using the source per-surface alpha) + Source surface blend mode set to SDL_BLENDMODE_NONE: copy RGB. both: if SDL_SRCCOLORKEY set, only copy the pixels matching the - source colour key. + source color key. \endverbatim - * + * * You should call SDL_BlitSurface() unless you know exactly how SDL * blitting works internally and how to use the other blit functions. */ #define SDL_BlitSurface SDL_UpperBlit /** - * This is the public blit function, SDL_BlitSurface(), and it performs - * rectangle validation and clipping before passing it to SDL_LowerBlit() + * Perform a fast blit from the source surface to the destination surface. + * + * SDL_UpperBlit() has been replaced by SDL_BlitSurface(), which is merely a + * macro for this function with a less confusing name. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface */ extern DECLSPEC int SDLCALL SDL_UpperBlit (SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); /** - * This is a semi-private blit function and it performs low-level surface - * blitting only. + * Perform low-level surface blitting only. + * + * This is a semi-private blit function and it performs low-level surface + * blitting, assuming the input rectangles have already been clipped. + * + * Unless you know what you're doing, you should be using SDL_BlitSurface() + * instead. + * + * \param src the SDL_Surface structure to be copied from + * \param srcrect the SDL_Rect structure representing the rectangle to be + * copied, or NULL to copy the entire surface + * \param dst the SDL_Surface structure that is the blit target + * \param dstrect the SDL_Rect structure representing the rectangle that is + * copied into + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitSurface */ extern DECLSPEC int SDLCALL SDL_LowerBlit (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); + /** - * \brief Perform a fast, low quality, stretch blit between two surfaces of the - * same pixel format. - * - * \note This function uses a static buffer, and is not thread-safe. + * Perform a fast, low quality, stretch blit between two surfaces of the same + * format. + * + * Please use SDL_BlitScaled() instead. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, const SDL_Rect * dstrect); +/** + * Perform bilinear scaling between two surfaces of the same format, 32BPP. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface * src, + const SDL_Rect * srcrect, + SDL_Surface * dst, + const SDL_Rect * dstrect); + + #define SDL_BlitScaled SDL_UpperBlitScaled /** - * This is the public scaled blit function, SDL_BlitScaled(), and it performs - * rectangle validation and clipping before passing it to SDL_LowerBlitScaled() + * Perform a scaled surface copy to a destination surface. + * + * SDL_UpperBlitScaled() has been replaced by SDL_BlitScaled(), which is + * merely a macro for this function with a less confusing name. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitScaled */ extern DECLSPEC int SDLCALL SDL_UpperBlitScaled (SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); /** - * This is a semi-private blit function and it performs low-level surface - * scaled blitting only. + * Perform low-level surface scaled blitting only. + * + * This is a semi-private function and it performs low-level surface blitting, + * assuming the input rectangles have already been clipped. + * + * \param src the SDL_Surface structure to be copied from + * \param srcrect the SDL_Rect structure representing the rectangle to be + * copied + * \param dst the SDL_Surface structure that is the blit target + * \param dstrect the SDL_Rect structure representing the rectangle that is + * copied into + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_BlitScaled */ extern DECLSPEC int SDLCALL SDL_LowerBlitScaled (SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); +/** + * Set the YUV conversion mode + * + * \since This function is available since SDL 2.0.8. + */ +extern DECLSPEC void SDLCALL SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode); + +/** + * Get the YUV conversion mode + * + * \since This function is available since SDL 2.0.8. + */ +extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionMode(void); + +/** + * Get the YUV conversion mode, returning the correct mode for the resolution + * when the current conversion mode is SDL_YUV_CONVERSION_AUTOMATIC + * + * \since This function is available since SDL 2.0.8. + */ +extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionModeForResolution(int width, int height); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_surface_h */ +#endif /* SDL_surface_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_system.h b/external/SDL2/SDL_system.h index 5ae9e40..e2fa7b5 100644 --- a/external/SDL2/SDL_system.h +++ b/external/SDL2/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,86 +21,543 @@ /** * \file SDL_system.h - * + * * Include file for platform specific SDL API functions */ -#ifndef _SDL_system_h -#define _SDL_system_h +#ifndef SDL_system_h_ +#define SDL_system_h_ #include "SDL_stdinc.h" - -#if defined(__IPHONEOS__) && __IPHONEOS__ -#include "SDL_video.h" #include "SDL_keyboard.h" -#endif +#include "SDL_render.h" +#include "SDL_video.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif -/* Platform specific functions for iOS */ -#if defined(__IPHONEOS__) && __IPHONEOS__ +/* Platform specific functions for Windows */ +#ifdef __WIN32__ + +typedef void (SDLCALL * SDL_WindowsMessageHook)(void *userdata, void *hWnd, unsigned int message, Uint64 wParam, Sint64 lParam); + +/** + * Set a callback for every Windows message, run before TranslateMessage(). + * + * \param callback The SDL_WindowsMessageHook function to call. + * \param userdata a pointer to pass to every iteration of `callback` + * + * \since This function is available since SDL 2.0.4. + */ +extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata); + +/** + * Get the D3D9 adapter index that matches the specified display index. + * + * The returned adapter index can be passed to `IDirect3D9::CreateDevice` and + * controls on which monitor a full screen application will appear. + * + * \param displayIndex the display index for which to get the D3D9 adapter + * index + * \returns the D3D9 adapter index on success or a negative error code on + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.1. + */ +extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex( int displayIndex ); + +typedef struct IDirect3DDevice9 IDirect3DDevice9; + +/** + * Get the D3D9 device associated with a renderer. + * + * Once you are done using the device, you should release it to avoid a + * resource leak. + * + * \param renderer the renderer from which to get the associated D3D device + * \returns the D3D9 device associated with given renderer or NULL if it is + * not a D3D9 renderer; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.1. + */ +extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer); + +typedef struct ID3D11Device ID3D11Device; + +/** + * Get the D3D11 device associated with a renderer. + * + * Once you are done using the device, you should release it to avoid a + * resource leak. + * + * \param renderer the renderer from which to get the associated D3D11 device + * \returns the D3D11 device associated with given renderer or NULL if it is + * not a D3D11 renderer; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC ID3D11Device* SDLCALL SDL_RenderGetD3D11Device(SDL_Renderer * renderer); + +/** + * Get the DXGI Adapter and Output indices for the specified display index. + * + * The DXGI Adapter and Output indices can be passed to `EnumAdapters` and + * `EnumOutputs` respectively to get the objects required to create a DX10 or + * DX11 device and swap chain. + * + * Before SDL 2.0.4 this function did not return a value. Since SDL 2.0.4 it + * returns an SDL_bool. + * + * \param displayIndex the display index for which to get both indices + * \param adapterIndex a pointer to be filled in with the adapter index + * \param outputIndex a pointer to be filled in with the output index + * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.2. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex ); + +#endif /* __WIN32__ */ + + +/* Platform specific functions for Linux */ +#ifdef __LINUX__ + +/** + * Sets the UNIX nice value for a thread. + * + * This uses setpriority() if possible, and RealtimeKit if available. + * + * \param threadID the Unix thread ID to change priority of. + * \param priority The new, Unix-specific, priority value. + * \returns 0 on success, or -1 on error. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority); + +/** + * Sets the priority (not nice level) and scheduling policy for a thread. + * + * This uses setpriority() if possible, and RealtimeKit if available. + * + * \param threadID The Unix thread ID to change priority of. + * \param sdlPriority The new SDL_ThreadPriority value. + * \param schedPolicy The new scheduling policy (SCHED_FIFO, SCHED_RR, + * SCHED_OTHER, etc...) + * \returns 0 on success, or -1 on error. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); + +#endif /* __LINUX__ */ + +/* Platform specific functions for iOS */ +#ifdef __IPHONEOS__ + +#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam) + +/** + * Use this function to set the animation callback on Apple iOS. + * + * The function prototype for `callback` is: + * + * ```c + * void callback(void* callbackParam); + * ``` + * + * Where its parameter, `callbackParam`, is what was passed as `callbackParam` + * to SDL_iPhoneSetAnimationCallback(). + * + * This function is only available on Apple iOS. + * + * For more information see: + * [README-ios.md](https://hg.libsdl.org/SDL/file/default/docs/README-ios.md) + * + * This functions is also accessible using the macro + * SDL_iOSSetAnimationCallback() since SDL 2.0.4. + * + * \param window the window for which the animation callback should be set + * \param interval the number of frames after which **callback** will be + * called + * \param callback the function to call for every frame. + * \param callbackParam a pointer that is passed to `callback`. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_iPhoneSetEventPump + */ extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam); + +#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled) + +/** + * Use this function to enable or disable the SDL event pump on Apple iOS. + * + * This function is only available on Apple iOS. + * + * This functions is also accessible using the macro SDL_iOSSetEventPump() + * since SDL 2.0.4. + * + * \param enabled SDL_TRUE to enable the event pump, SDL_FALSE to disable it + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_iPhoneSetAnimationCallback + */ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); #endif /* __IPHONEOS__ */ /* Platform specific functions for Android */ -#if defined(__ANDROID__) && __ANDROID__ +#ifdef __ANDROID__ -/* Get the JNI environment for the current thread - This returns JNIEnv*, but the prototype is void* so we don't need jni.h +/** + * Get the Android Java Native Interface Environment of the current thread. + * + * This is the JNIEnv one needs to access the Java virtual machine from native + * code, and is needed for many Android APIs to be usable from C. + * + * The prototype of the function in SDL's code actually declare a void* return + * type, even if the implementation returns a pointer to a JNIEnv. The + * rationale being that the SDL headers can avoid including jni.h. + * + * \returns a pointer to Java native interface object (JNIEnv) to which the + * current thread is attached, or 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AndroidGetActivity */ -extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(); +extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(void); -/* Get the SDL Activity object for the application - This returns jobject, but the prototype is void* so we don't need jni.h +/** + * Retrieve the Java instance of the Android activity class. + * + * The prototype of the function in SDL's code actually declares a void* + * return type, even if the implementation returns a jobject. The rationale + * being that the SDL headers can avoid including jni.h. + * + * The jobject returned by the function is a local reference and must be + * released by the caller. See the PushLocalFrame() and PopLocalFrame() or + * DeleteLocalRef() functions of the Java native interface: + * + * https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html + * + * \returns the jobject representing the instance of the Activity class of the + * Android application, or NULL on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AndroidGetJNIEnv */ -extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(); +extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void); -/* See the official Android developer guide for more information: +/** + * Query Android API level of the current device. + * + * - API level 31: Android 12 + * - API level 30: Android 11 + * - API level 29: Android 10 + * - API level 28: Android 9 + * - API level 27: Android 8.1 + * - API level 26: Android 8.0 + * - API level 25: Android 7.1 + * - API level 24: Android 7.0 + * - API level 23: Android 6.0 + * - API level 22: Android 5.1 + * - API level 21: Android 5.0 + * - API level 20: Android 4.4W + * - API level 19: Android 4.4 + * - API level 18: Android 4.3 + * - API level 17: Android 4.2 + * - API level 16: Android 4.1 + * - API level 15: Android 4.0.3 + * - API level 14: Android 4.0 + * - API level 13: Android 3.2 + * - API level 12: Android 3.1 + * - API level 11: Android 3.0 + * - API level 10: Android 2.3.3 + * + * \returns the Android API level. + * + * \since This function is available since SDL 2.0.12. + */ +extern DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); + +/** + * Query if the application is running on Android TV. + * + * \returns SDL_TRUE if this is Android TV, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.8. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void); + +/** + * Query if the application is running on a Chromebook. + * + * \returns SDL_TRUE if this is a Chromebook, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void); + +/** + * Query if the application is running on a Samsung DeX docking station. + * + * \returns SDL_TRUE if this is a DeX docking station, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void); + +/** + * Trigger the Android system back button behavior. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void); + +/** + See the official Android developer guide for more information: http://developer.android.com/guide/topics/data/data-storage.html */ #define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01 #define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02 -/* Get the path used for internal storage for this application. - This path is unique to your application and cannot be written to - by other applications. +/** + * Get the path used for internal storage for this application. + * + * This path is unique to your application and cannot be written to by other + * applications. + * + * Your internal storage path is typically: + * `/data/data/your.app.package/files`. + * + * \returns the path used for internal storage or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AndroidGetExternalStorageState */ -extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(); +extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(void); -/* Get the current state of external storage, a bitmask of these values: - SDL_ANDROID_EXTERNAL_STORAGE_READ - SDL_ANDROID_EXTERNAL_STORAGE_WRITE - If external storage is currently unavailable, this will return 0. -*/ -extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(); - -/* Get the path used for external storage for this application. - This path is unique to your application, but is public and can be - written to by other applications. +/** + * Get the current state of external storage. + * + * The current state of external storage, a bitmask of these values: + * `SDL_ANDROID_EXTERNAL_STORAGE_READ`, `SDL_ANDROID_EXTERNAL_STORAGE_WRITE`. + * + * If external storage is currently unavailable, this will return 0. + * + * \returns the current state of external storage on success or 0 on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AndroidGetExternalStoragePath */ -extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(); +extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(void); + +/** + * Get the path used for external storage for this application. + * + * This path is unique to your application, but is public and can be written + * to by other applications. + * + * Your external storage path is typically: + * `/storage/sdcard0/Android/data/your.app.package/files`. + * + * \returns the path used for external storage for this application on success + * or NULL on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AndroidGetExternalStorageState + */ +extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void); + +/** + * Request permissions at runtime. + * + * This blocks the calling thread until the permission is granted or denied. + * + * \param permission The permission to request. + * \returns SDL_TRUE if the permission was granted, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.14. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission); + +/** + * Shows an Android toast notification. + * + * Toasts are a sort of lightweight notification that are unique to Android. + * + * https://developer.android.com/guide/topics/ui/notifiers/toasts + * + * Shows toast in UI thread. + * + * For the `gravity` parameter, choose a value from here, or -1 if you don't + * have a preference: + * + * https://developer.android.com/reference/android/view/Gravity + * + * \param message text message to be shown + * \param duration 0=short, 1=long + * \param gravity where the notification should appear on the screen. + * \param xoffset set this parameter only when gravity >=0 + * \param yoffset set this parameter only when gravity >=0 + * \returns 0 if success, -1 if any error occurs. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset); #endif /* __ANDROID__ */ +/* Platform specific functions for WinRT */ +#ifdef __WINRT__ + +/** + * \brief WinRT / Windows Phone path types + */ +typedef enum +{ + /** \brief The installed app's root directory. + Files here are likely to be read-only. */ + SDL_WINRT_PATH_INSTALLED_LOCATION, + + /** \brief The app's local data store. Files may be written here */ + SDL_WINRT_PATH_LOCAL_FOLDER, + + /** \brief The app's roaming data store. Unsupported on Windows Phone. + Files written here may be copied to other machines via a network + connection. + */ + SDL_WINRT_PATH_ROAMING_FOLDER, + + /** \brief The app's temporary data store. Unsupported on Windows Phone. + Files written here may be deleted at any time. */ + SDL_WINRT_PATH_TEMP_FOLDER +} SDL_WinRT_Path; + + +/** + * \brief WinRT Device Family + */ +typedef enum +{ + /** \brief Unknown family */ + SDL_WINRT_DEVICEFAMILY_UNKNOWN, + + /** \brief Desktop family*/ + SDL_WINRT_DEVICEFAMILY_DESKTOP, + + /** \brief Mobile family (for example smartphone) */ + SDL_WINRT_DEVICEFAMILY_MOBILE, + + /** \brief XBox family */ + SDL_WINRT_DEVICEFAMILY_XBOX, +} SDL_WinRT_DeviceFamily; + + +/** + * Retrieve a WinRT defined path on the local file system. + * + * Not all paths are available on all versions of Windows. This is especially + * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path + * for more information on which path types are supported where. + * + * Documentation on most app-specific path types on WinRT can be found on + * MSDN, at the URL: + * + * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx + * + * \param pathType the type of path to retrieve, one of SDL_WinRT_Path + * \returns a UCS-2 string (16-bit, wide-char) containing the path, or NULL if + * the path is not available for any reason; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.3. + * + * \sa SDL_WinRTGetFSPathUTF8 + */ +extern DECLSPEC const wchar_t * SDLCALL SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType); + +/** + * Retrieve a WinRT defined path on the local file system. + * + * Not all paths are available on all versions of Windows. This is especially + * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path + * for more information on which path types are supported where. + * + * Documentation on most app-specific path types on WinRT can be found on + * MSDN, at the URL: + * + * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx + * + * \param pathType the type of path to retrieve, one of SDL_WinRT_Path + * \returns a UTF-8 string (8-bit, multi-byte) containing the path, or NULL if + * the path is not available for any reason; call SDL_GetError() for + * more information. + * + * \since This function is available since SDL 2.0.3. + * + * \sa SDL_WinRTGetFSPathUNICODE + */ +extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType); + +/** + * Detects the device family of WinRT plattform at runtime. + * + * \returns a value from the SDL_WinRT_DeviceFamily enum. + * + * \since This function is available since SDL 2.0.8. + */ +extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily(); + +#endif /* __WINRT__ */ + +/** + * Query if the current device is a tablet. + * + * If SDL can't determine this, it will return SDL_FALSE. + * + * \returns SDL_TRUE if the device is a tablet, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_IsTablet(void); + +/* Functions used by iOS application delegates to notify SDL about state changes */ +extern DECLSPEC void SDLCALL SDL_OnApplicationWillTerminate(void); +extern DECLSPEC void SDLCALL SDL_OnApplicationDidReceiveMemoryWarning(void); +extern DECLSPEC void SDLCALL SDL_OnApplicationWillResignActive(void); +extern DECLSPEC void SDLCALL SDL_OnApplicationDidEnterBackground(void); +extern DECLSPEC void SDLCALL SDL_OnApplicationWillEnterForeground(void); +extern DECLSPEC void SDLCALL SDL_OnApplicationDidBecomeActive(void); +#ifdef __IPHONEOS__ +extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void); +#endif /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_system_h */ +#endif /* SDL_system_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_syswm.h b/external/SDL2/SDL_syswm.h index 786e12e..f7cd670 100644 --- a/external/SDL2/SDL_syswm.h +++ b/external/SDL2/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,43 +21,44 @@ /** * \file SDL_syswm.h - * + * * Include file for SDL custom system window manager hooks. */ -#ifndef _SDL_syswm_h -#define _SDL_syswm_h +#ifndef SDL_syswm_h_ +#define SDL_syswm_h_ #include "SDL_stdinc.h" #include "SDL_error.h" #include "SDL_video.h" #include "SDL_version.h" -#include "begin_code.h" -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -/* *INDENT-OFF* */ -extern "C" { -/* *INDENT-ON* */ -#endif - /** - * \file SDL_syswm.h - * + * \brief SDL_syswm.h + * * Your application has access to a special type of event ::SDL_SYSWMEVENT, * which contains window-manager specific information and arrives whenever * an unhandled window event occurs. This event is ignored by default, but * you can enable it with SDL_EventState(). */ -#ifdef SDL_PROTOTYPES_ONLY struct SDL_SysWMinfo; -#else + +#if !defined(SDL_PROTOTYPES_ONLY) #if defined(SDL_VIDEO_DRIVER_WINDOWS) +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX /* don't define min() and max(). */ +#define NOMINMAX +#endif #include #endif +#if defined(SDL_VIDEO_DRIVER_WINRT) +#include +#endif + /* This is the structure for custom window manager events */ #if defined(SDL_VIDEO_DRIVER_X11) #if defined(__APPLE__) && defined(__MACH__) @@ -81,7 +82,7 @@ struct SDL_SysWMinfo; #if defined(SDL_VIDEO_DRIVER_COCOA) #ifdef __OBJC__ -#include +@class NSWindow; #else typedef struct _NSWindow NSWindow; #endif @@ -92,10 +93,43 @@ typedef struct _NSWindow NSWindow; #include #else typedef struct _UIWindow UIWindow; +typedef struct _UIViewController UIViewController; #endif +typedef Uint32 GLuint; #endif -/** +#if defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL) +#define SDL_METALVIEW_TAG 255 +#endif + +#if defined(SDL_VIDEO_DRIVER_ANDROID) +typedef struct ANativeWindow ANativeWindow; +typedef void *EGLSurface; +#endif + +#if defined(SDL_VIDEO_DRIVER_VIVANTE) +#include "SDL_egl.h" +#endif + +#if defined(SDL_VIDEO_DRIVER_OS2) +#define INCL_WIN +#include +#endif +#endif /* SDL_PROTOTYPES_ONLY */ + +#if defined(SDL_VIDEO_DRIVER_KMSDRM) +struct gbm_device; +#endif + + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(SDL_PROTOTYPES_ONLY) +/** * These are the various supported windowing subsystems */ typedef enum @@ -106,6 +140,15 @@ typedef enum SDL_SYSWM_DIRECTFB, SDL_SYSWM_COCOA, SDL_SYSWM_UIKIT, + SDL_SYSWM_WAYLAND, + SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ + SDL_SYSWM_WINRT, + SDL_SYSWM_ANDROID, + SDL_SYSWM_VIVANTE, + SDL_SYSWM_OS2, + SDL_SYSWM_HAIKU, + SDL_SYSWM_KMSDRM, + SDL_SYSWM_RISCOS } SDL_SYSWM_TYPE; /** @@ -138,14 +181,36 @@ struct SDL_SysWMmsg #if defined(SDL_VIDEO_DRIVER_COCOA) struct { + /* Latest version of Xcode clang complains about empty structs in C v. C++: + error: empty struct has size 0 in C, size 1 in C++ + */ + int dummy; /* No Cocoa window events yet */ } cocoa; #endif #if defined(SDL_VIDEO_DRIVER_UIKIT) struct { + int dummy; /* No UIKit window events yet */ } uikit; +#endif +#if defined(SDL_VIDEO_DRIVER_VIVANTE) + struct + { + int dummy; + /* No Vivante window events yet */ + } vivante; +#endif +#if defined(SDL_VIDEO_DRIVER_OS2) + struct + { + BOOL fFrame; /**< TRUE if hwnd is a frame window */ + HWND hwnd; /**< The window receiving the message */ + ULONG msg; /**< The message identifier */ + MPARAM mp1; /**< The first first message parameter */ + MPARAM mp2; /**< The second first message parameter */ + } os2; #endif /* Can't have an empty union */ int dummy; @@ -168,8 +233,16 @@ struct SDL_SysWMinfo struct { HWND window; /**< The window handle */ + HDC hdc; /**< The window device context */ + HINSTANCE hinstance; /**< The instance handle */ } win; #endif +#if defined(SDL_VIDEO_DRIVER_WINRT) + struct + { + IInspectable * window; /**< The WinRT CoreWindow */ + } winrt; +#endif #if defined(SDL_VIDEO_DRIVER_X11) struct { @@ -188,17 +261,89 @@ struct SDL_SysWMinfo #if defined(SDL_VIDEO_DRIVER_COCOA) struct { - NSWindow *window; /* The Cocoa window */ +#if defined(__OBJC__) && defined(__has_feature) + #if __has_feature(objc_arc) + NSWindow __unsafe_unretained *window; /**< The Cocoa window */ + #else + NSWindow *window; /**< The Cocoa window */ + #endif +#else + NSWindow *window; /**< The Cocoa window */ +#endif } cocoa; #endif #if defined(SDL_VIDEO_DRIVER_UIKIT) struct { - UIWindow *window; /* The UIKit window */ +#if defined(__OBJC__) && defined(__has_feature) + #if __has_feature(objc_arc) + UIWindow __unsafe_unretained *window; /**< The UIKit window */ + #else + UIWindow *window; /**< The UIKit window */ + #endif +#else + UIWindow *window; /**< The UIKit window */ +#endif + GLuint framebuffer; /**< The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */ + GLuint colorbuffer; /**< The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */ + GLuint resolveFramebuffer; /**< The Framebuffer Object which holds the resolve color Renderbuffer, when MSAA is used. */ } uikit; #endif - /* Can't have an empty union */ - int dummy; +#if defined(SDL_VIDEO_DRIVER_WAYLAND) + struct + { + struct wl_display *display; /**< Wayland display */ + struct wl_surface *surface; /**< Wayland surface */ + void *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */ + struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */ + struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */ + struct xdg_toplevel *xdg_toplevel; /**< Wayland xdg toplevel role */ + } wl; +#endif +#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ + struct + { + void *connection; /**< Mir display server connection */ + void *surface; /**< Mir surface */ + } mir; +#endif + +#if defined(SDL_VIDEO_DRIVER_ANDROID) + struct + { + ANativeWindow *window; + EGLSurface surface; + } android; +#endif + +#if defined(SDL_VIDEO_DRIVER_OS2) + struct + { + HWND hwnd; /**< The window handle */ + HWND hwndFrame; /**< The frame window handle */ + } os2; +#endif + +#if defined(SDL_VIDEO_DRIVER_VIVANTE) + struct + { + EGLNativeDisplayType display; + EGLNativeWindowType window; + } vivante; +#endif + +#if defined(SDL_VIDEO_DRIVER_KMSDRM) + struct + { + int dev_index; /**< Device index (ex: the X in /dev/dri/cardX) */ + int drm_fd; /**< DRM FD (unavailable on Vulkan windows) */ + struct gbm_device *gbm_dev; /**< GBM device (unavailable on Vulkan windows) */ + } kmsdrm; +#endif + + /* Make sure this union is always 64 bytes (8 64-bit pointers). */ + /* Be careful not to overflow this if you add a new target! */ + Uint8 dummy[64]; } info; }; @@ -206,23 +351,23 @@ struct SDL_SysWMinfo typedef struct SDL_SysWMinfo SDL_SysWMinfo; -/* Function prototypes */ + /** - * \brief This function allows access to driver-dependent window information. - * - * \param window The window about which information is being requested - * \param info This structure must be initialized with the SDL version, and is - * then filled in with information about the given window. - * - * \return SDL_TRUE if the function is implemented and the version member of - * the \c info struct is valid, SDL_FALSE otherwise. - * - * You typically use this function like this: - * \code - * SDL_SysWMinfo info; - * SDL_VERSION(&info.version); - * if ( SDL_GetWindowWMInfo(&info) ) { ... } - * \endcode + * Get driver-specific information about a window. + * + * You must include SDL_syswm.h for the declaration of SDL_SysWMinfo. + * + * The caller must initialize the `info` structure's version by using + * `SDL_VERSION(&info.version)`, and then this function will fill in the rest + * of the structure with information about the given window. + * + * \param window the window about which information is being requested + * \param info an SDL_SysWMinfo structure filled in with window information + * \returns SDL_TRUE if the function is implemented and the `version` member + * of the `info` struct is valid, or SDL_FALSE if the information + * could not be retrieved; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowWMInfo(SDL_Window * window, SDL_SysWMinfo * info); @@ -230,12 +375,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowWMInfo(SDL_Window * window, /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_syswm_h */ +#endif /* SDL_syswm_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test.h b/external/SDL2/SDL_test.h index 15e7689..8cc9d61 100644 --- a/external/SDL2/SDL_test.h +++ b/external/SDL2/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,52 +21,49 @@ /** * \file SDL_test.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -#ifndef _SDL_test_h -#define _SDL_test_h +#ifndef SDL_test_h_ +#define SDL_test_h_ #include "SDL.h" -#include "SDL_test_common.h" -#include "SDL_test_font.h" -#include "SDL_test_random.h" -#include "SDL_test_fuzzer.h" -#include "SDL_test_crc32.h" -#include "SDL_test_md5.h" -#include "SDL_test_log.h" #include "SDL_test_assert.h" +#include "SDL_test_common.h" +#include "SDL_test_compare.h" +#include "SDL_test_crc32.h" +#include "SDL_test_font.h" +#include "SDL_test_fuzzer.h" #include "SDL_test_harness.h" #include "SDL_test_images.h" -#include "SDL_test_compare.h" +#include "SDL_test_log.h" +#include "SDL_test_md5.h" +#include "SDL_test_memory.h" +#include "SDL_test_random.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* Global definitions */ -/* - * Note: Maximum size of SDLTest log message is less than SDLs limit - * to ensure we can fit additional information such as the timestamp. +/* + * Note: Maximum size of SDLTest log message is less than SDL's limit + * to ensure we can fit additional information such as the timestamp. */ -#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584 +#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584 /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_h */ +#endif /* SDL_test_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_assert.h b/external/SDL2/SDL_test_assert.h index 17b6d26..7342305 100644 --- a/external/SDL2/SDL_test_assert.h +++ b/external/SDL2/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,38 +21,36 @@ /** * \file SDL_test_assert.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* * * Assert API for test code and test cases * */ -#ifndef _SDL_test_assert_h -#define _SDL_test_assert_h +#ifndef SDL_test_assert_h_ +#define SDL_test_assert_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \brief Fails the assert. */ -#define ASSERT_FAIL 0 +#define ASSERT_FAIL 0 /** * \brief Passes the assert. */ -#define ASSERT_PASS 1 +#define ASSERT_PASS 1 /** * \brief Assert that logs and break execution flow on failures. @@ -60,7 +58,7 @@ extern "C" { * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertDescription Message to log with the assert describing it. */ -void SDLTest_Assert(int assertCondition, const char *assertDescription, ...); +void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); /** * \brief Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters. @@ -68,26 +66,26 @@ void SDLTest_Assert(int assertCondition, const char *assertDescription, ...); * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertDescription Message to log with the assert describing it. * - * \returns Returns the assertCondition so it can be used to externally to break execution flow if desired. + * \returns the assertCondition so it can be used to externally to break execution flow if desired. */ -int SDLTest_AssertCheck(int assertCondition, const char *assertDescription, ...); +int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); /** - * \brief Explicitely pass without checking an assertion condition. Updates assertion counter. + * \brief Explicitly pass without checking an assertion condition. Updates assertion counter. * * \param assertDescription Message to log with the assert describing it. */ -void SDLTest_AssertPass(const char *assertDescription, ...); +void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(1); /** * \brief Resets the assert summary counters to zero. */ -void SDLTest_ResetAssertSummary(); +void SDLTest_ResetAssertSummary(void); /** * \brief Logs summary of all assertions (total, pass, fail) since last reset as INFO or ERROR. */ -void SDLTest_LogAssertSummary(); +void SDLTest_LogAssertSummary(void); /** @@ -95,15 +93,13 @@ void SDLTest_LogAssertSummary(); * * \returns TEST_RESULT_PASSED, TEST_RESULT_FAILED, or TEST_RESULT_NO_ASSERT */ -int SDLTest_AssertSummaryToTestResult(); +int SDLTest_AssertSummaryToTestResult(void); #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_assert_h */ +#endif /* SDL_test_assert_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_common.h b/external/SDL2/SDL_test_common.h index 9e9122f..0f50967 100644 --- a/external/SDL2/SDL_test_common.h +++ b/external/SDL2/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_test_common.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. @@ -29,14 +29,17 @@ /* Ported from original test\common.h file. */ -#ifndef _SDL_test_common_h -#define _SDL_test_common_h +#ifndef SDL_test_common_h_ +#define SDL_test_common_h_ #include "SDL.h" #if defined(__PSP__) #define DEFAULT_WINDOW_WIDTH 480 #define DEFAULT_WINDOW_HEIGHT 272 +#elif defined(__VITA__) +#define DEFAULT_WINDOW_WIDTH 960 +#define DEFAULT_WINDOW_HEIGHT 544 #else #define DEFAULT_WINDOW_WIDTH 640 #define DEFAULT_WINDOW_HEIGHT 480 @@ -61,6 +64,7 @@ typedef struct const char *window_title; const char *window_icon; Uint32 window_flags; + SDL_bool flash_on_focus_loss; int window_x; int window_y; int window_w; @@ -69,6 +73,9 @@ typedef struct int window_minH; int window_maxW; int window_maxH; + int logical_w; + int logical_h; + float scale; int depth; int refresh_rate; int num_windows; @@ -79,6 +86,7 @@ typedef struct Uint32 render_flags; SDL_bool skip_renderer; SDL_Renderer **renderers; + SDL_Texture **targets; /* Audio info */ const char *audiodriver; @@ -104,14 +112,18 @@ typedef struct int gl_accelerated; int gl_major_version; int gl_minor_version; + int gl_debug; + int gl_profile_mask; + + /* Additional fields added in 2.0.18 */ + SDL_Rect confine; + } SDLTest_CommonState; #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* Function prototypes */ @@ -122,7 +134,7 @@ extern "C" { * \param argv Array of command line parameters * \param flags Flags indicating which subsystem to initialize (i.e. SDL_INIT_VIDEO | SDL_INIT_AUDIO) * - * \returns Returns a newly allocated common state object. + * \returns a newly allocated common state object. */ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); @@ -132,16 +144,35 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); * \param state The common state describing the test window to create. * \param index The index of the argument to process in argv[]. * - * \returns The number of arguments processed (i.e. 1 for --fullscreen, 2 for --video [videodriver], or -1 on error. + * \returns the number of arguments processed (i.e. 1 for --fullscreen, 2 for --video [videodriver], or -1 on error. */ int SDLTest_CommonArg(SDLTest_CommonState * state, int index); + +/** + * \brief Logs command line usage info. + * + * This logs the appropriate command line options for the subsystems in use + * plus other common options, and then any application-specific options. + * This uses the SDL_Log() function and splits up output to be friendly to + * 80-character-wide terminals. + * + * \param state The common state describing the test window for the app. + * \param argv0 argv[0], as passed to main/SDL_main. + * \param options an array of strings for application specific options. The last element of the array should be NULL. + */ +void SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options); + /** * \brief Returns common usage information * - * \param state The common state describing the test window to create. + * You should (probably) be using SDLTest_CommonLogUsage() instead, but this + * function remains for binary compatibility. Strings returned from this + * function are valid until SDLTest_CommonQuit() is called, in which case + * those strings' memory is freed and can no longer be used. * - * \returns String with usage information + * \param state The common state describing the test window to create. + * \returns a string with usage information */ const char *SDLTest_CommonUsage(SDLTest_CommonState * state); @@ -150,10 +181,21 @@ const char *SDLTest_CommonUsage(SDLTest_CommonState * state); * * \param state The common state describing the test window to create. * - * \returns True if initialization succeeded, false otherwise + * \returns SDL_TRUE if initialization succeeded, false otherwise */ SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state); +/** + * \brief Easy argument handling when test app doesn't need any custom args. + * + * \param state The common state describing the test window to create. + * \param argc argc, as supplied to SDL_main + * \param argv argv, as supplied to SDL_main + * + * \returns SDL_FALSE if app should quit, true otherwise. + */ +SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState * state, const int argc, char **argv); + /** * \brief Common event handler for test windows. * @@ -172,15 +214,22 @@ void SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *do */ void SDLTest_CommonQuit(SDLTest_CommonState * state); +/** + * \brief Draws various window information (position, size, etc.) to the renderer. + * + * \param renderer The renderer to draw to. + * \param window The window whose information should be displayed. + * \param usedHeight Returns the height used, so the caller can draw more below. + * + */ +void SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window, int * usedHeight); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_common_h */ +#endif /* SDL_test_common_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_compare.h b/external/SDL2/SDL_test_compare.h index e145f69..8a7a070 100644 --- a/external/SDL2/SDL_test_compare.h +++ b/external/SDL2/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,20 +21,20 @@ /** * \file SDL_test_compare.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* Defines comparison functions (i.e. for surfaces). - + */ -#ifndef _SDL_test_compare_h -#define _SDL_test_compare_h +#ifndef SDL_test_compare_h_ +#define SDL_test_compare_h_ #include "SDL.h" @@ -43,9 +43,7 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** @@ -53,21 +51,19 @@ extern "C" { * * \param surface Surface used in comparison * \param referenceSurface Test Surface used in comparison - * \param allowable_error Allowable difference (squared) in blending accuracy. + * \param allowable_error Allowable difference (=sum of squared difference for each RGB component) in blending accuracy. * - * \returns 0 if comparison succeeded, >0 (=number of pixels where comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ. + * \returns 0 if comparison succeeded, >0 (=number of pixels for which the comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ. */ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error); - + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_compare_h */ +#endif /* SDL_test_compare_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_crc32.h b/external/SDL2/SDL_test_crc32.h index 0685a37..049da74 100644 --- a/external/SDL2/SDL_test_crc32.h +++ b/external/SDL2/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,27 +21,25 @@ /** * \file SDL_test_crc32.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* Implements CRC32 calculations (default output is Perl String::CRC32 compatible). - + */ -#ifndef _SDL_test_crc32_h -#define _SDL_test_crc32_h +#ifndef SDL_test_crc32_h_ +#define SDL_test_crc32_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif @@ -50,20 +48,20 @@ extern "C" { /* Definition shared by all CRC routines */ #ifndef CrcUint32 - #define CrcUint32 unsigned int + #define CrcUint32 unsigned int #endif #ifndef CrcUint8 - #define CrcUint8 unsigned char + #define CrcUint8 unsigned char #endif #ifdef ORIGINAL_METHOD - #define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ + #define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ #else #define CRC32_POLY 0xEDB88320 /* Perl String::CRC32 compatible */ #endif -/** - * Data structure for CRC32 (checksum) computation +/** + * Data structure for CRC32 (checksum) computation */ typedef struct { CrcUint32 crc32_table[256]; /* CRC table */ @@ -71,31 +69,31 @@ extern "C" { /* ---------- Function Prototypes ------------- */ -/** - * /brief Initialize the CRC context +/** + * \brief Initialize the CRC context * * Note: The function initializes the crc table required for all crc calculations. * - * /param crcContext pointer to context variable + * \param crcContext pointer to context variable * - * /returns 0 for OK, -1 on error + * \returns 0 for OK, -1 on error * */ int SDLTest_Crc32Init(SDLTest_Crc32Context * crcContext); /** - * /brief calculate a crc32 from a data block - * - * /param crcContext pointer to context variable - * /param inBuf input buffer to checksum - * /param inLen length of input buffer - * /param crc32 pointer to Uint32 to store the final CRC into + * \brief calculate a crc32 from a data block * - * /returns 0 for OK, -1 on error + * \param crcContext pointer to context variable + * \param inBuf input buffer to checksum + * \param inLen length of input buffer + * \param crc32 pointer to Uint32 to store the final CRC into + * + * \returns 0 for OK, -1 on error * */ -int SDLTest_crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32); +int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32); /* Same routine broken down into three steps */ int SDLTest_Crc32CalcStart(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32); @@ -104,11 +102,11 @@ int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, /** - * /brief clean up CRC context + * \brief clean up CRC context * - * /param crcContext pointer to context variable + * \param crcContext pointer to context variable * - * /returns 0 for OK, -1 on error + * \returns 0 for OK, -1 on error * */ @@ -117,12 +115,10 @@ int SDLTest_Crc32Done(SDLTest_Crc32Context * crcContext); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_crc32_h */ +#endif /* SDL_test_crc32_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_font.h b/external/SDL2/SDL_test_font.h index d894601..c5cbbbb 100644 --- a/external/SDL2/SDL_test_font.h +++ b/external/SDL2/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,25 +21,37 @@ /** * \file SDL_test_font.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -#ifndef _SDL_test_font_h -#define _SDL_test_font_h +#ifndef SDL_test_font_h_ +#define SDL_test_font_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* Function prototypes */ +#define FONT_CHARACTER_SIZE 8 + +/** + * \brief Draw a string in the currently set font. + * + * \param renderer The renderer to draw on. + * \param x The X coordinate of the upper left corner of the character. + * \param y The Y coordinate of the upper left corner of the character. + * \param c The character to draw. + * + * \returns 0 on success, -1 on failure. + */ +int SDLTest_DrawCharacter(SDL_Renderer *renderer, int x, int y, char c); + /** * \brief Draw a string in the currently set font. * @@ -48,19 +60,22 @@ extern "C" { * \param y The Y coordinate of the upper left corner of the string. * \param s The string to draw. * - * \returns Returns 0 on success, -1 on failure. + * \returns 0 on success, -1 on failure. */ -int SDLTest_DrawString(SDL_Renderer * renderer, int x, int y, const char *s); +int SDLTest_DrawString(SDL_Renderer *renderer, int x, int y, const char *s); +/** + * \brief Cleanup textures used by font drawing functions. + */ +void SDLTest_CleanupTextDrawing(void); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_font_h */ +#endif /* SDL_test_font_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_fuzzer.h b/external/SDL2/SDL_test_fuzzer.h index db30a1d..bbe8eb8 100644 --- a/external/SDL2/SDL_test_fuzzer.h +++ b/external/SDL2/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,27 +21,25 @@ /** * \file SDL_test_fuzzer.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* Data generators for fuzzing test data in a reproducible way. - + */ -#ifndef _SDL_test_fuzzer_h -#define _SDL_test_fuzzer_h +#ifndef SDL_test_fuzzer_h_ +#define SDL_test_fuzzer_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif @@ -59,7 +57,7 @@ extern "C" { /** * Initializes the fuzzer for a test * - * /param execKey Execution "Key" that initializes the random number generator uniquely for the test. + * \param execKey Execution "Key" that initializes the random number generator uniquely for the test. * */ void SDLTest_FuzzerInit(Uint64 execKey); @@ -68,84 +66,84 @@ void SDLTest_FuzzerInit(Uint64 execKey); /** * Returns a random Uint8 * - * \returns Generated integer + * \returns a generated integer */ -Uint8 SDLTest_RandomUint8(); +Uint8 SDLTest_RandomUint8(void); /** * Returns a random Sint8 * - * \returns Generated signed integer + * \returns a generated signed integer */ -Sint8 SDLTest_RandomSint8(); +Sint8 SDLTest_RandomSint8(void); /** * Returns a random Uint16 * - * \returns Generated integer + * \returns a generated integer */ -Uint16 SDLTest_RandomUint16(); +Uint16 SDLTest_RandomUint16(void); /** * Returns a random Sint16 * - * \returns Generated signed integer + * \returns a generated signed integer */ -Sint16 SDLTest_RandomSint16(); +Sint16 SDLTest_RandomSint16(void); /** * Returns a random integer * - * \returns Generated integer + * \returns a generated integer */ -Sint32 SDLTest_RandomSint32(); +Sint32 SDLTest_RandomSint32(void); /** * Returns a random positive integer * - * \returns Generated integer + * \returns a generated integer */ -Uint32 SDLTest_RandomUint32(); +Uint32 SDLTest_RandomUint32(void); /** * Returns random Uint64. * - * \returns Generated integer + * \returns a generated integer */ -Uint64 SDLTest_RandomUint64(); +Uint64 SDLTest_RandomUint64(void); /** * Returns random Sint64. * - * \returns Generated signed integer + * \returns a generated signed integer */ -Sint64 SDLTest_RandomSint64(); +Sint64 SDLTest_RandomSint64(void); /** - * \returns random float in range [0.0 - 1.0[ + * \returns a random float in range [0.0 - 1.0] */ -float SDLTest_RandomUnitFloat(); +float SDLTest_RandomUnitFloat(void); /** - * \returns random double in range [0.0 - 1.0[ + * \returns a random double in range [0.0 - 1.0] */ -double SDLTest_RandomUnitDouble(); +double SDLTest_RandomUnitDouble(void); /** - * \returns random float. + * \returns a random float. * */ -float SDLTest_RandomFloat(); +float SDLTest_RandomFloat(void); /** - * \returns random double. + * \returns a random double. * */ -double SDLTest_RandomDouble(); +double SDLTest_RandomDouble(void); /** * Returns a random boundary value for Uint8 within the given boundaries. @@ -164,7 +162,7 @@ double SDLTest_RandomDouble(); * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or 0 with error set + * \returns a random boundary value for the given range and domain or 0 with error set */ Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain); @@ -185,7 +183,7 @@ Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_boo * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or 0 with error set + * \returns a random boundary value for the given range and domain or 0 with error set */ Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain); @@ -206,7 +204,7 @@ Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or 0 with error set + * \returns a random boundary value for the given range and domain or 0 with error set */ Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain); @@ -227,7 +225,7 @@ Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or 0 with error set + * \returns a random boundary value for the given range and domain or 0 with error set */ Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain); @@ -248,7 +246,7 @@ Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or SINT8_MIN with error set + * \returns a random boundary value for the given range and domain or SINT8_MIN with error set */ Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain); @@ -270,7 +268,7 @@ Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_boo * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or SINT16_MIN with error set + * \returns a random boundary value for the given range and domain or SINT16_MIN with error set */ Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain); @@ -291,7 +289,7 @@ Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or SINT32_MIN with error set + * \returns a random boundary value for the given range and domain or SINT32_MIN with error set */ Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain); @@ -312,7 +310,7 @@ Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL * \param boundary2 Upper boundary limit * \param validDomain Should the generated boundary be valid (=within the bounds) or not? * - * \returns Random boundary value for the given range and domain or SINT64_MIN with error set + * \returns a random boundary value for the given range and domain or SINT64_MIN with error set */ Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain); @@ -320,27 +318,27 @@ Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL /** * Returns integer in range [min, max] (inclusive). * Min and max values can be negative values. - * If Max in smaller tham min, then the values are swapped. + * If Max in smaller than min, then the values are swapped. * Min and max are the same value, that value will be returned. * * \param min Minimum inclusive value of returned random number * \param max Maximum inclusive value of returned random number * - * \returns Generated random integer in range + * \returns a generated random integer in range */ Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max); /** * Generates random null-terminated string. The minimum length for - * the string is 1 character, maximum length for the string is 255 + * the string is 1 character, maximum length for the string is 255 * characters and it can contain ASCII characters from 32 to 126. * * Note: Returned string needs to be deallocated. * - * \returns Newly allocated random string; or NULL if length was invalid or string could not be allocated. + * \returns a newly allocated random string; or NULL if length was invalid or string could not be allocated. */ -char * SDLTest_RandomAsciiString(); +char * SDLTest_RandomAsciiString(void); /** @@ -352,7 +350,7 @@ char * SDLTest_RandomAsciiString(); * * \param maxLength The maximum length of the generated string. * - * \returns Newly allocated random string; or NULL if maxLength was invalid or string could not be allocated. + * \returns a newly allocated random string; or NULL if maxLength was invalid or string could not be allocated. */ char * SDLTest_RandomAsciiStringWithMaximumLength(int maxLength); @@ -366,23 +364,23 @@ char * SDLTest_RandomAsciiStringWithMaximumLength(int maxLength); * * \param size The length of the generated string * - * \returns Newly allocated random string; or NULL if size was invalid or string could not be allocated. + * \returns a newly allocated random string; or NULL if size was invalid or string could not be allocated. */ char * SDLTest_RandomAsciiStringOfSize(int size); /** - * Returns the invocation count for the fuzzer since last ...FuzzerInit. + * Get the invocation count for the fuzzer since last ...FuzzerInit. + * + * \returns the invocation count. */ -int SDLTest_GetFuzzerInvocationCount(); +int SDLTest_GetFuzzerInvocationCount(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_fuzzer_h */ +#endif /* SDL_test_fuzzer_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_harness.h b/external/SDL2/SDL_test_harness.h index e5fe673..1fd4236 100644 --- a/external/SDL2/SDL_test_harness.h +++ b/external/SDL2/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_test_harness.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. @@ -29,76 +29,86 @@ /* Defines types for test case definitions and the test execution harness API. - + Based on original GSOC code by Markus Kauppila */ -#ifndef _SDL_test_harness_h -#define _SDL_test_harness_h +#ifndef SDL_test_h_arness_h +#define SDL_test_h_arness_h #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif -//! Definitions for test case structures +/* ! Definitions for test case structures */ #define TEST_ENABLED 1 #define TEST_DISABLED 0 -//! Definition of all the possible test return values of the test case method -#define TEST_ABORTED -1 -#define TEST_COMPLETED 0 -#define TEST_SKIPPED 1 +/* ! Definition of all the possible test return values of the test case method */ +#define TEST_ABORTED -1 +#define TEST_STARTED 0 +#define TEST_COMPLETED 1 +#define TEST_SKIPPED 2 -//! Definition of all the possible test results for the harness -#define TEST_RESULT_PASSED 0 -#define TEST_RESULT_FAILED 1 -#define TEST_RESULT_NO_ASSERT 2 -#define TEST_RESULT_SKIPPED 3 -#define TEST_RESULT_SETUP_FAILURE 4 +/* ! Definition of all the possible test results for the harness */ +#define TEST_RESULT_PASSED 0 +#define TEST_RESULT_FAILED 1 +#define TEST_RESULT_NO_ASSERT 2 +#define TEST_RESULT_SKIPPED 3 +#define TEST_RESULT_SETUP_FAILURE 4 -//!< Function pointer to a test case setup function (run before every test) +/* !< Function pointer to a test case setup function (run before every test) */ typedef void (*SDLTest_TestCaseSetUpFp)(void *arg); -//!< Function pointer to a test case function -typedef void (*SDLTest_TestCaseFp)(void *arg); +/* !< Function pointer to a test case function */ +typedef int (*SDLTest_TestCaseFp)(void *arg); -//!< Function pointer to a test case teardown function (run after every test) +/* !< Function pointer to a test case teardown function (run after every test) */ typedef void (*SDLTest_TestCaseTearDownFp)(void *arg); /** * Holds information about a single test case. */ typedef struct SDLTest_TestCaseReference { - /*!< Func2Stress */ - SDLTest_TestCaseFp testCase; - /*!< Short name (or function name) "Func2Stress" */ - char *name; - /*!< Long name or full description "This test pushes func2() to the limit." */ - char *description; - /*!< Set to TEST_ENABLED or TEST_DISABLED (test won't be run) */ - int enabled; + /* !< Func2Stress */ + SDLTest_TestCaseFp testCase; + /* !< Short name (or function name) "Func2Stress" */ + const char *name; + /* !< Long name or full description "This test pushes func2() to the limit." */ + const char *description; + /* !< Set to TEST_ENABLED or TEST_DISABLED (test won't be run) */ + int enabled; } SDLTest_TestCaseReference; /** * Holds information about a test suite (multiple test cases). */ typedef struct SDLTest_TestSuiteReference { - /*!< "PlatformSuite" */ - char *name; - /*!< The function that is run before each test. NULL skips. */ - SDLTest_TestCaseSetUpFp testSetUp; - /*!< The test cases that are run as part of the suite. Last item should be NULL. */ - const SDLTest_TestCaseReference **testCases; - /*!< The function that is run after each test. NULL skips. */ - SDLTest_TestCaseTearDownFp testTearDown; + /* !< "PlatformSuite" */ + const char *name; + /* !< The function that is run before each test. NULL skips. */ + SDLTest_TestCaseSetUpFp testSetUp; + /* !< The test cases that are run as part of the suite. Last item should be NULL. */ + const SDLTest_TestCaseReference **testCases; + /* !< The function that is run after each test. NULL skips. */ + SDLTest_TestCaseTearDownFp testTearDown; } SDLTest_TestSuiteReference; +/** + * \brief Generates a random run seed string for the harness. The generated seed will contain alphanumeric characters (0-9A-Z). + * + * Note: The returned string needs to be deallocated by the caller. + * + * \param length The length of the seed string to generate + * + * \returns the generated seed string + */ +char *SDLTest_GenerateRunSeed(const int length); + /** * \brief Execute a test suite using the given run seed and execution key. * @@ -108,19 +118,17 @@ typedef struct SDLTest_TestSuiteReference { * \param filter Filter specification. NULL disables. Case sensitive. * \param testIterations Number of iterations to run each test case. * - * \returns Test run result; 0 when all tests passed, 1 if any tests failed. + * \returns the test run result: 0 when all tests passed, 1 if any tests failed. */ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations); - + /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_harness_h */ +#endif /* SDL_test_h_arness_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_images.h b/external/SDL2/SDL_test_images.h index ea72229..e2bfc36 100644 --- a/external/SDL2/SDL_test_images.h +++ b/external/SDL2/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,29 +21,27 @@ /** * \file SDL_test_images.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* Defines some images for tests. - + */ -#ifndef _SDL_test_images_h -#define _SDL_test_images_h +#ifndef SDL_test_images_h_ +#define SDL_test_images_h_ #include "SDL.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** @@ -52,31 +50,29 @@ extern "C" { typedef struct SDLTest_SurfaceImage_s { int width; int height; - unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ + unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ const char *pixel_data; } SDLTest_SurfaceImage_t; /* Test images */ -SDL_Surface *SDLTest_ImageBlit(); -SDL_Surface *SDLTest_ImageBlitColor(); -SDL_Surface *SDLTest_ImageBlitAlpha(); -SDL_Surface *SDLTest_ImageBlitBlendAdd(); -SDL_Surface *SDLTest_ImageBlitBlend(); -SDL_Surface *SDLTest_ImageBlitBlendMod(); -SDL_Surface *SDLTest_ImageBlitBlendNone(); -SDL_Surface *SDLTest_ImageBlitBlendAll(); -SDL_Surface *SDLTest_ImageFace(); -SDL_Surface *SDLTest_ImagePrimitives(); -SDL_Surface *SDLTest_ImagePrimitivesBlend(); +SDL_Surface *SDLTest_ImageBlit(void); +SDL_Surface *SDLTest_ImageBlitColor(void); +SDL_Surface *SDLTest_ImageBlitAlpha(void); +SDL_Surface *SDLTest_ImageBlitBlendAdd(void); +SDL_Surface *SDLTest_ImageBlitBlend(void); +SDL_Surface *SDLTest_ImageBlitBlendMod(void); +SDL_Surface *SDLTest_ImageBlitBlendNone(void); +SDL_Surface *SDLTest_ImageBlitBlendAll(void); +SDL_Surface *SDLTest_ImageFace(void); +SDL_Surface *SDLTest_ImagePrimitives(void); +SDL_Surface *SDLTest_ImagePrimitivesBlend(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_images_h */ +#endif /* SDL_test_images_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_log.h b/external/SDL2/SDL_test_log.h index c6dbad6..e3d39ad 100644 --- a/external/SDL2/SDL_test_log.h +++ b/external/SDL2/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,27 +21,25 @@ /** * \file SDL_test_log.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* * * Wrapper to log in the TEST category * */ -#ifndef _SDL_test_log_h -#define _SDL_test_log_h +#ifndef SDL_test_log_h_ +#define SDL_test_log_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** @@ -49,23 +47,21 @@ extern "C" { * * \param fmt Message to be logged */ -void SDLTest_Log(const char *fmt, ...); +void SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); /** * \brief Prints given message with a timestamp in the TEST category and the ERROR priority. * * \param fmt Message to be logged */ -void SDLTest_LogError(const char *fmt, ...); +void SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_log_h */ +#endif /* SDL_test_log_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_md5.h b/external/SDL2/SDL_test_md5.h index 8949f4b..17b1d2b 100644 --- a/external/SDL2/SDL_test_md5.h +++ b/external/SDL2/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_test_md5.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. @@ -53,15 +53,13 @@ *********************************************************************** */ -#ifndef _SDL_test_md5_h -#define _SDL_test_md5_h +#ifndef SDL_test_md5_h_ +#define SDL_test_md5_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* ------------ Definitions --------- */ @@ -71,46 +69,46 @@ extern "C" { /* Data structure for MD5 (Message-Digest) computation */ typedef struct { - MD5UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ - MD5UINT4 buf[4]; /* scratch buffer */ - unsigned char in[64]; /* input buffer */ - unsigned char digest[16]; /* actual digest after Md5Final call */ + MD5UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + MD5UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after Md5Final call */ } SDLTest_Md5Context; /* ---------- Function Prototypes ------------- */ -/** - * /brief initialize the context +/** + * \brief initialize the context * - * /param mdContext pointer to context variable + * \param mdContext pointer to context variable * * Note: The function initializes the message-digest context - * mdContext. Call before each new use of the context - + * mdContext. Call before each new use of the context - * all fields are set to zero. */ void SDLTest_Md5Init(SDLTest_Md5Context * mdContext); /** - * /brief update digest from variable length data - * - * /param mdContext pointer to context variable - * /param inBuf pointer to data array/string - * /param inLen length of data array/string + * \brief update digest from variable length data * - * Note: The function updates the message-digest context to account + * \param mdContext pointer to context variable + * \param inBuf pointer to data array/string + * \param inLen length of data array/string + * + * Note: The function updates the message-digest context to account * for the presence of each of the characters inBuf[0..inLen-1] * in the message whose digest is being computed. */ void SDLTest_Md5Update(SDLTest_Md5Context * mdContext, unsigned char *inBuf, - unsigned int inLen); + unsigned int inLen); -/* - * /brief complete digest computation +/** + * \brief complete digest computation * - * /param mdContext pointer to context variable + * \param mdContext pointer to context variable * * Note: The function terminates the message-digest computation and * ends with the desired message digest in mdContext.digest[0..15]. @@ -122,12 +120,10 @@ extern "C" { /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_md5_h */ +#endif /* SDL_test_md5_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_memory.h b/external/SDL2/SDL_test_memory.h new file mode 100644 index 0000000..cc2edc1 --- /dev/null +++ b/external/SDL2/SDL_test_memory.h @@ -0,0 +1,63 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_test_memory.h + * + * Include file for SDL test framework. + * + * This code is a part of the SDL2_test library, not the main SDL library. + */ + +#ifndef SDL_test_memory_h_ +#define SDL_test_memory_h_ + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Start tracking SDL memory allocations + * + * \note This should be called before any other SDL functions for complete tracking coverage + */ +int SDLTest_TrackAllocations(void); + +/** + * \brief Print a log of any outstanding allocations + * + * \note This can be called after SDL_Quit() + */ +void SDLTest_LogAllocations(void); + + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_test_memory_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_test_random.h b/external/SDL2/SDL_test_random.h index 8b20b6a..b1d6060 100644 --- a/external/SDL2/SDL_test_random.h +++ b/external/SDL2/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,31 +21,29 @@ /** * \file SDL_test_random.h - * + * * Include file for SDL test framework. * * This code is a part of the SDL2_test library, not the main SDL library. */ -/* +/* - A "32-bit Multiply with carry random number generator. Very fast. - Includes a list of recommended multipliers. + A "32-bit Multiply with carry random number generator. Very fast. + Includes a list of recommended multipliers. multiply-with-carry generator: x(n) = a*x(n-1) + carry mod 2^32. period: (a*2^31)-1 - + */ -#ifndef _SDL_test_random_h -#define _SDL_test_random_h +#ifndef SDL_test_random_h_ +#define SDL_test_random_h_ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* --- Definitions */ @@ -53,7 +51,7 @@ extern "C" { /* * Macros that return a random number in a specific format. */ -#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c)) +#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c)) /* * Context structure for the random number generator state. @@ -70,7 +68,7 @@ extern "C" { /* --- Function prototypes */ /** - * \brief Initialize random number generator with two integers. + * \brief Initialize random number generator with two integers. * * Note: The random sequence of numbers returned by ...Random() is the * same for the same two integers and has a period of 2^31. @@ -81,10 +79,10 @@ extern "C" { * */ void SDLTest_RandomInit(SDLTest_RandomContext * rndContext, unsigned int xi, - unsigned int ci); + unsigned int ci); /** - * \brief Initialize random number generator based on current system time. + * \brief Initialize random number generator based on current system time. * * \param rndContext pointer to context structure * @@ -93,14 +91,14 @@ extern "C" { /** - * \brief Initialize random number generator based on current system time. + * \brief Initialize random number generator based on current system time. * * Note: ...RandomInit() or ...RandomInitTime() must have been called * before using this function. * * \param rndContext pointer to context structure * - * \returns A random number (32bit unsigned integer) + * \returns a random number (32bit unsigned integer) * */ unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext); @@ -108,12 +106,10 @@ extern "C" { /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_test_random_h */ +#endif /* SDL_test_random_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_thread.h b/external/SDL2/SDL_thread.h index 273419b..35e680d 100644 --- a/external/SDL2/SDL_thread.h +++ b/external/SDL2/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,12 +19,12 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_thread_h -#define _SDL_thread_h +#ifndef SDL_thread_h_ +#define SDL_thread_h_ /** * \file SDL_thread.h - * + * * Header for the SDL thread management routines. */ @@ -32,14 +32,24 @@ #include "SDL_error.h" /* Thread synchronization primitives */ +#include "SDL_atomic.h" #include "SDL_mutex.h" +#if defined(__WIN32__) +#include /* _beginthreadex() and _endthreadex() */ +#endif +#if defined(__OS2__) /* for _beginthread() and _endthread() */ +#ifndef __EMX__ +#include +#else +#include +#endif +#endif + #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /* The SDL thread structure, defined in SDL_thread.c */ @@ -49,134 +59,406 @@ typedef struct SDL_Thread SDL_Thread; /* The SDL thread ID */ typedef unsigned long SDL_threadID; -/* The SDL thread priority +/* Thread local storage ID, 0 is the invalid ID */ +typedef unsigned int SDL_TLSID; + +/** + * The SDL thread priority. * - * Note: On many systems you require special privileges to set high priority. + * SDL will make system changes as necessary in order to apply the thread priority. + * Code which attempts to control thread state related to priority should be aware + * that calling SDL_SetThreadPriority may alter such state. + * SDL_HINT_THREAD_PRIORITY_POLICY can be used to control aspects of this behavior. + * + * \note On many systems you require special privileges to set high or time critical priority. */ typedef enum { SDL_THREAD_PRIORITY_LOW, SDL_THREAD_PRIORITY_NORMAL, - SDL_THREAD_PRIORITY_HIGH + SDL_THREAD_PRIORITY_HIGH, + SDL_THREAD_PRIORITY_TIME_CRITICAL } SDL_ThreadPriority; -/* The function passed to SDL_CreateThread() - It is passed a void* user context parameter and returns an int. +/** + * The function passed to SDL_CreateThread(). + * + * \param data what was passed as `data` to SDL_CreateThread() + * \returns a value that can be reported through SDL_WaitThread(). */ typedef int (SDLCALL * SDL_ThreadFunction) (void *data); -#if defined(__WIN32__) && !defined(HAVE_LIBC) + +#if defined(__WIN32__) /** * \file SDL_thread.h - * + * * We compile SDL into a DLL. This means, that it's the DLL which * creates a new thread for the calling process with the SDL_CreateThread() - * API. There is a problem with this, that only the RTL of the SDL.DLL will - * be initialized for those threads, and not the RTL of the calling + * API. There is a problem with this, that only the RTL of the SDL2.DLL will + * be initialized for those threads, and not the RTL of the calling * application! - * + * * To solve this, we make a little hack here. - * + * * We'll always use the caller's _beginthread() and _endthread() APIs to - * start a new thread. This way, if it's the SDL.DLL which uses this API, - * then the RTL of SDL.DLL will be used to create the new thread, and if it's + * start a new thread. This way, if it's the SDL2.DLL which uses this API, + * then the RTL of SDL2.DLL will be used to create the new thread, and if it's * the application, then the RTL of the application will be used. - * + * * So, in short: - * Always use the _beginthread() and _endthread() of the calling runtime + * Always use the _beginthread() and _endthread() of the calling runtime * library! */ #define SDL_PASSED_BEGINTHREAD_ENDTHREAD -#include /* This has _beginthread() and _endthread() defined! */ -typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned, - unsigned (__stdcall * - func) (void - *), - void *arg, unsigned, - unsigned *threadID); +typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread) + (void *, unsigned, unsigned (__stdcall *func)(void *), + void * /*arg*/, unsigned, unsigned * /* threadID */); typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code); -/** - * Create a thread. - */ +#ifndef SDL_beginthread +#define SDL_beginthread _beginthreadex +#endif +#ifndef SDL_endthread +#define SDL_endthread _endthreadex +#endif + extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread); -/** - * Create a thread. +extern DECLSPEC SDL_Thread *SDLCALL +SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *), + const char *name, const size_t stacksize, void *data, + pfnSDL_CurrentBeginThread pfnBeginThread, + pfnSDL_CurrentEndThread pfnEndThread); + + +#if defined(SDL_CreateThread) && SDL_DYNAMIC_API +#undef SDL_CreateThread +#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#undef SDL_CreateThreadWithStackSize +#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#else +#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)SDL_endthread) +#endif + +#elif defined(__OS2__) +/* + * just like the windows case above: We compile SDL2 + * into a dll with Watcom's runtime statically linked. */ -#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, _beginthreadex, _endthreadex) +#define SDL_PASSED_BEGINTHREAD_ENDTHREAD + +typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void * /*arg*/); +typedef void (*pfnSDL_CurrentEndThread)(void); + +#ifndef SDL_beginthread +#define SDL_beginthread _beginthread +#endif +#ifndef SDL_endthread +#define SDL_endthread _endthread +#endif + +extern DECLSPEC SDL_Thread *SDLCALL +SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data, + pfnSDL_CurrentBeginThread pfnBeginThread, + pfnSDL_CurrentEndThread pfnEndThread); +extern DECLSPEC SDL_Thread *SDLCALL +SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data, + pfnSDL_CurrentBeginThread pfnBeginThread, + pfnSDL_CurrentEndThread pfnEndThread); + +#if defined(SDL_CreateThread) && SDL_DYNAMIC_API +#undef SDL_CreateThread +#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#undef SDL_CreateThreadWithStackSize +#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#else +#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) +#endif #else /** - * Create a thread. + * Create a new thread with a default stack size. * - * Thread naming is a little complicated: Most systems have very small - * limits for the string length (BeOS has 32 bytes, Linux currently has 16, - * Visual C++ 6.0 has nine!), and possibly other arbitrary rules. You'll - * have to see what happens with your system's debugger. The name should be - * UTF-8 (but using the naming limits of C identifiers is a better bet). - * There are no requirements for thread naming conventions, so long as the - * string is null-terminated UTF-8, but these guidelines are helpful in - * choosing a name: + * This is equivalent to calling: * - * http://stackoverflow.com/questions/149932/naming-conventions-for-threads + * ```c + * SDL_CreateThreadWithStackSize(fn, name, 0, data); + * ``` * - * If a system imposes requirements, SDL will try to munge the string for - * it (truncate, etc), but the original string contents will be available - * from SDL_GetThreadName(). + * \param fn the SDL_ThreadFunction function to call in the new thread + * \param name the name of the thread + * \param data a pointer that is passed to `fn` + * \returns an opaque pointer to the new thread object on success, NULL if the + * new thread could not be created; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateThreadWithStackSize + * \sa SDL_WaitThread */ extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); +/** + * Create a new thread with a specific stack size. + * + * SDL makes an attempt to report `name` to the system, so that debuggers can + * display it. Not all platforms support this. + * + * Thread naming is a little complicated: Most systems have very small limits + * for the string length (Haiku has 32 bytes, Linux currently has 16, Visual + * C++ 6.0 has _nine_!), and possibly other arbitrary rules. You'll have to + * see what happens with your system's debugger. The name should be UTF-8 (but + * using the naming limits of C identifiers is a better bet). There are no + * requirements for thread naming conventions, so long as the string is + * null-terminated UTF-8, but these guidelines are helpful in choosing a name: + * + * https://stackoverflow.com/questions/149932/naming-conventions-for-threads + * + * If a system imposes requirements, SDL will try to munge the string for it + * (truncate, etc), but the original string contents will be available from + * SDL_GetThreadName(). + * + * The size (in bytes) of the new stack can be specified. Zero means "use the + * system default" which might be wildly different between platforms. x86 + * Linux generally defaults to eight megabytes, an embedded device might be a + * few kilobytes instead. You generally need to specify a stack that is a + * multiple of the system's page size (in many cases, this is 4 kilobytes, but + * check your system documentation). + * + * In SDL 2.1, stack size will be folded into the original SDL_CreateThread + * function, but for backwards compatibility, this is currently a separate + * function. + * + * \param fn the SDL_ThreadFunction function to call in the new thread + * \param name the name of the thread + * \param stacksize the size, in bytes, to allocate for the new thread stack. + * \param data a pointer that is passed to `fn` + * \returns an opaque pointer to the new thread object on success, NULL if the + * new thread could not be created; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.9. + * + * \sa SDL_WaitThread + */ +extern DECLSPEC SDL_Thread *SDLCALL +SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data); + #endif /** - * Get the thread name, as it was specified in SDL_CreateThread(). - * This function returns a pointer to a UTF-8 string that names the - * specified thread, or NULL if it doesn't have a name. This is internal - * memory, not to be free()'d by the caller, and remains valid until the - * specified thread is cleaned up by SDL_WaitThread(). + * Get the thread name as it was specified in SDL_CreateThread(). + * + * This is internal memory, not to be freed by the caller, and remains valid + * until the specified thread is cleaned up by SDL_WaitThread(). + * + * \param thread the thread to query + * \returns a pointer to a UTF-8 string that names the specified thread, or + * NULL if it doesn't have a name. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateThread */ extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread); /** - * Get the thread identifier for the current thread. + * Get the thread identifier for the current thread. + * + * This thread identifier is as reported by the underlying operating system. + * If SDL is running on a platform that does not support threads the return + * value will always be zero. + * + * This function also returns a valid thread ID when called from the main + * thread. + * + * \returns the ID of the current thread. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetThreadID */ extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void); /** - * Get the thread identifier for the specified thread. - * - * Equivalent to SDL_ThreadID() if the specified thread is NULL. + * Get the thread identifier for the specified thread. + * + * This thread identifier is as reported by the underlying operating system. + * If SDL is running on a platform that does not support threads the return + * value will always be zero. + * + * \param thread the thread to query + * \returns the ID of the specified thread, or the ID of the current thread if + * `thread` is NULL. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ThreadID */ extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); /** - * Set the priority for the current thread + * Set the priority for the current thread. + * + * Note that some platforms will not let you alter the priority (or at least, + * promote the thread to a higher priority) at all, and some require you to be + * an administrator account. Be prepared for this to fail. + * + * \param priority the SDL_ThreadPriority to set + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority); /** - * Wait for a thread to finish. - * - * The return code for the thread function is placed in the area - * pointed to by \c status, if \c status is not NULL. + * Wait for a thread to finish. + * + * Threads that haven't been detached will remain (as a "zombie") until this + * function cleans them up. Not doing so is a resource leak. + * + * Once a thread has been cleaned up through this function, the SDL_Thread + * that references it becomes invalid and should not be referenced again. As + * such, only one thread may call SDL_WaitThread() on another. + * + * The return code for the thread function is placed in the area pointed to by + * `status`, if `status` is not NULL. + * + * You may not wait on a thread that has been used in a call to + * SDL_DetachThread(). Use either that function or this one, but not both, or + * behavior is undefined. + * + * It is safe to pass a NULL thread to this function; it is a no-op. + * + * Note that the thread pointer is freed by this function and is not valid + * afterward. + * + * \param thread the SDL_Thread pointer that was returned from the + * SDL_CreateThread() call that started this thread + * \param status pointer to an integer that will receive the value returned + * from the thread function by its 'return', or NULL to not + * receive such value back. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateThread + * \sa SDL_DetachThread */ extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status); +/** + * Let a thread clean up on exit without intervention. + * + * A thread may be "detached" to signify that it should not remain until + * another thread has called SDL_WaitThread() on it. Detaching a thread is + * useful for long-running threads that nothing needs to synchronize with or + * further manage. When a detached thread is done, it simply goes away. + * + * There is no way to recover the return code of a detached thread. If you + * need this, don't detach the thread and instead use SDL_WaitThread(). + * + * Once a thread is detached, you should usually assume the SDL_Thread isn't + * safe to reference again, as it will become invalid immediately upon the + * detached thread's exit, instead of remaining until someone has called + * SDL_WaitThread() to finally clean it up. As such, don't detach the same + * thread more than once. + * + * If a thread has already exited when passed to SDL_DetachThread(), it will + * stop waiting for a call to SDL_WaitThread() and clean up immediately. It is + * not safe to detach a thread that might be used with SDL_WaitThread(). + * + * You may not call SDL_WaitThread() on a thread that has been detached. Use + * either that function or this one, but not both, or behavior is undefined. + * + * It is safe to pass NULL to this function; it is a no-op. + * + * \param thread the SDL_Thread pointer that was returned from the + * SDL_CreateThread() call that started this thread + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_CreateThread + * \sa SDL_WaitThread + */ +extern DECLSPEC void SDLCALL SDL_DetachThread(SDL_Thread * thread); + +/** + * Create a piece of thread-local storage. + * + * This creates an identifier that is globally visible to all threads but + * refers to data that is thread-specific. + * + * \returns the newly created thread local storage identifier or 0 on error. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_TLSGet + * \sa SDL_TLSSet + */ +extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate(void); + +/** + * Get the current thread's value associated with a thread local storage ID. + * + * \param id the thread local storage ID + * \returns the value associated with the ID for the current thread or NULL if + * no value has been set; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_TLSCreate + * \sa SDL_TLSSet + */ +extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id); + +/** + * Set the current thread's value associated with a thread local storage ID. + * + * The function prototype for `destructor` is: + * + * ```c + * void destructor(void *value) + * ``` + * + * where its parameter `value` is what was passed as `value` to SDL_TLSSet(). + * + * \param id the thread local storage ID + * \param value the value to associate with the ID for the current thread + * \param destructor a function called when the thread exits, to free the + * value + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_TLSCreate + * \sa SDL_TLSGet + */ +extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void*)); + +/** + * Cleanup all TLS data for this thread. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC void SDLCALL SDL_TLSCleanup(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_thread_h */ +#endif /* SDL_thread_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_timer.h b/external/SDL2/SDL_timer.h index 4a2a272..62f81d4 100644 --- a/external/SDL2/SDL_timer.h +++ b/external/SDL2/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,12 +19,12 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef _SDL_timer_h -#define _SDL_timer_h +#ifndef SDL_timer_h_ +#define SDL_timer_h_ /** * \file SDL_timer.h - * + * * Header for the SDL time management routines. */ @@ -34,40 +34,125 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief Get the number of milliseconds since the SDL library initialization. - * - * \note This value wraps if the program runs for more than ~49 days. + * Get the number of milliseconds since SDL library initialization. + * + * This value wraps if the program runs for more than ~49 days. + * + * This function is not recommended as of SDL 2.0.18; use SDL_GetTicks64() + * instead, where the value doesn't wrap every ~49 days. There are places in + * SDL where we provide a 32-bit timestamp that can not change without + * breaking binary compatibility, though, so this function isn't officially + * deprecated. + * + * \returns an unsigned 32-bit value representing the number of milliseconds + * since the SDL library initialized. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_TICKS_PASSED */ extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void); /** - * \brief Get the current value of the high resolution counter + * Get the number of milliseconds since SDL library initialization. + * + * Note that you should not use the SDL_TICKS_PASSED macro with values + * returned by this function, as that macro does clever math to compensate for + * the 32-bit overflow every ~49 days that SDL_GetTicks() suffers from. 64-bit + * values from this function can be safely compared directly. + * + * For example, if you want to wait 100 ms, you could do this: + * + * ```c + * const Uint64 timeout = SDL_GetTicks64() + 100; + * while (SDL_GetTicks64() < timeout) { + * // ... do work until timeout has elapsed + * } + * ``` + * + * \returns an unsigned 64-bit value representing the number of milliseconds + * since the SDL library initialized. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC Uint64 SDLCALL SDL_GetTicks64(void); + +/** + * Compare 32-bit SDL ticks values, and return true if `A` has passed `B`. + * + * This should be used with results from SDL_GetTicks(), as this macro + * attempts to deal with the 32-bit counter wrapping back to zero every ~49 + * days, but should _not_ be used with SDL_GetTicks64(), which does not have + * that problem. + * + * For example, with SDL_GetTicks(), if you want to wait 100 ms, you could + * do this: + * + * ```c + * const Uint32 timeout = SDL_GetTicks() + 100; + * while (!SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { + * // ... do work until timeout has elapsed + * } + * ``` + * + * Note that this does not handle tick differences greater + * than 2^31 so take care when using the above kind of code + * with large timeout delays (tens of days). + */ +#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0) + +/** + * Get the current value of the high resolution counter. + * + * This function is typically used for profiling. + * + * The counter values are only meaningful relative to each other. Differences + * between values can be converted to times by using + * SDL_GetPerformanceFrequency(). + * + * \returns the current counter value. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetPerformanceFrequency */ extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void); /** - * \brief Get the count per second of the high resolution counter + * Get the count per second of the high resolution counter. + * + * \returns a platform-specific count per second. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetPerformanceCounter */ extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void); /** - * \brief Wait a specified number of milliseconds before returning. + * Wait a specified number of milliseconds before returning. + * + * This function waits a specified number of milliseconds before returning. It + * waits at least the specified time, but possibly longer due to OS + * scheduling. + * + * \param ms the number of milliseconds to delay + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms); /** - * Function prototype for the timer callback function. - * - * The callback function is passed the current timer interval and returns - * the next timer interval. If the returned value is the same as the one - * passed in, the periodic alarm continues, otherwise a new alarm is - * scheduled. If the callback returns 0, the periodic alarm is cancelled. + * Function prototype for the timer callback function. + * + * The callback function is passed the current timer interval and returns + * the next timer interval. If the returned value is the same as the one + * passed in, the periodic alarm continues, otherwise a new alarm is + * scheduled. If the callback returns 0, the periodic alarm is cancelled. */ typedef Uint32 (SDLCALL * SDL_TimerCallback) (Uint32 interval, void *param); @@ -77,32 +162,61 @@ typedef Uint32 (SDLCALL * SDL_TimerCallback) (Uint32 interval, void *param); typedef int SDL_TimerID; /** - * \brief Add a new timer to the pool of timers already running. + * Call a callback function at a future time. * - * \return A timer ID, or NULL when an error occurs. + * If you use this function, you must pass `SDL_INIT_TIMER` to SDL_Init(). + * + * The callback function is passed the current timer interval and the user + * supplied parameter from the SDL_AddTimer() call and should return the next + * timer interval. If the value returned from the callback is 0, the timer is + * canceled. + * + * The callback is run on a separate thread. + * + * Timers take into account the amount of time it took to execute the + * callback. For example, if the callback took 250 ms to execute and returned + * 1000 (ms), the timer would only wait another 750 ms before its next + * iteration. + * + * Timing may be inexact due to OS scheduling. Be sure to note the current + * time with SDL_GetTicks() or SDL_GetPerformanceCounter() in case your + * callback needs to adjust for variances. + * + * \param interval the timer delay, in milliseconds, passed to `callback` + * \param callback the SDL_TimerCallback function to call when the specified + * `interval` elapses + * \param param a pointer that is passed to `callback` + * \returns a timer ID or 0 if an error occurs; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RemoveTimer */ extern DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param); /** - * \brief Remove a timer knowing its ID. + * Remove a timer created with SDL_AddTimer(). * - * \return A boolean value indicating success or failure. + * \param id the ID of the timer to remove + * \returns SDL_TRUE if the timer is removed or SDL_FALSE if the timer wasn't + * found. * - * \warning It is not safe to remove a timer multiple times. + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_AddTimer */ extern DECLSPEC SDL_bool SDLCALL SDL_RemoveTimer(SDL_TimerID id); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_timer_h */ +#endif /* SDL_timer_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_touch.h b/external/SDL2/SDL_touch.h index 55176a1..9b00716 100644 --- a/external/SDL2/SDL_touch.h +++ b/external/SDL2/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_touch.h - * + * * Include file for SDL touch event handling. */ -#ifndef _SDL_touch_h -#define _SDL_touch_h +#ifndef SDL_touch_h_ +#define SDL_touch_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -35,14 +35,20 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif typedef Sint64 SDL_TouchID; typedef Sint64 SDL_FingerID; +typedef enum +{ + SDL_TOUCH_DEVICE_INVALID = -1, + SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */ +} SDL_TouchDeviceType; + typedef struct SDL_Finger { SDL_FingerID id; @@ -54,37 +60,83 @@ typedef struct SDL_Finger /* Used as the device ID for mouse events simulated with touch input */ #define SDL_TOUCH_MOUSEID ((Uint32)-1) +/* Used as the SDL_TouchID for touch events simulated with mouse input */ +#define SDL_MOUSE_TOUCHID ((Sint64)-1) -/* Function prototypes */ /** - * \brief Get the number of registered touch devices. + * Get the number of registered touch devices. + * + * On some platforms SDL first sees the touch device if it was actually used. + * Therefore SDL_GetNumTouchDevices() may return 0 although devices are + * available. After using all devices at least once the number will be + * correct. + * + * This was fixed for Android in SDL 2.0.1. + * + * \returns the number of registered touch devices. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTouchDevice */ -extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(); +extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); /** - * \brief Get the touch ID with the given index, or 0 if the index is invalid. + * Get the touch ID with the given index. + * + * \param index the touch device index + * \returns the touch ID with the given index on success or 0 if the index is + * invalid; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumTouchDevices */ extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); /** - * \brief Get the number of active fingers for a given touch device. + * Get the type of the given touch device. + * + * \since This function is available since SDL 2.0.10. + */ +extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID); + +/** + * Get the number of active fingers for a given touch device. + * + * \param touchID the ID of a touch device + * \returns the number of active fingers for a given touch device on success + * or 0 on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetTouchFinger */ extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID); /** - * \brief Get the finger object of the given touch, with the given index. + * Get the finger object for specified touch device ID and finger index. + * + * The returned resource is owned by SDL and should not be deallocated. + * + * \param touchID the ID of the requested touch device + * \param index the index of the requested finger + * \returns a pointer to the SDL_Finger object or NULL if no object at the + * given ID and index could be found. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_RecordGesture */ extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_touch_h */ +#endif /* SDL_touch_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_types.h b/external/SDL2/SDL_types.h index 636df1e..355fb50 100644 --- a/external/SDL2/SDL_types.h +++ b/external/SDL2/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ /** * \file SDL_types.h - * + * * \deprecated */ diff --git a/external/SDL2/SDL_version.h b/external/SDL2/SDL_version.h index e32ea20..2716eba 100644 --- a/external/SDL2/SDL_version.h +++ b/external/SDL2/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,34 +21,32 @@ /** * \file SDL_version.h - * + * * This header defines the current SDL version. */ -#ifndef _SDL_version_h -#define _SDL_version_h +#ifndef SDL_version_h_ +#define SDL_version_h_ #include "SDL_stdinc.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** - * \brief Information the version of SDL in use. - * - * Represents the library's version as three levels: major revision - * (increments with massive changes, additions, and enhancements), - * minor revision (increments with backwards-compatible changes to the - * major revision), and patchlevel (increments with fixes to the minor - * revision). - * - * \sa SDL_VERSION - * \sa SDL_GetVersion + * Information about the version of SDL in use. + * + * Represents the library's version as three levels: major revision + * (increments with massive changes, additions, and enhancements), + * minor revision (increments with backwards-compatible changes to the + * major revision), and patchlevel (increments with fixes to the minor + * revision). + * + * \sa SDL_VERSION + * \sa SDL_GetVersion */ typedef struct SDL_version { @@ -59,30 +57,30 @@ typedef struct SDL_version /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ -#define SDL_MAJOR_VERSION 2 -#define SDL_MINOR_VERSION 0 -#define SDL_PATCHLEVEL 0 +#define SDL_MAJOR_VERSION 2 +#define SDL_MINOR_VERSION 0 +#define SDL_PATCHLEVEL 20 /** - * \brief Macro to determine SDL version program was compiled against. - * - * This macro fills in a SDL_version structure with the version of the - * library you compiled against. This is determined by what header the - * compiler uses. Note that if you dynamically linked the library, you might - * have a slightly newer or older version at runtime. That version can be - * determined with SDL_GetVersion(), which, unlike SDL_VERSION(), - * is not a macro. - * - * \param x A pointer to a SDL_version struct to initialize. - * - * \sa SDL_version - * \sa SDL_GetVersion + * Macro to determine SDL version program was compiled against. + * + * This macro fills in a SDL_version structure with the version of the + * library you compiled against. This is determined by what header the + * compiler uses. Note that if you dynamically linked the library, you might + * have a slightly newer or older version at runtime. That version can be + * determined with SDL_GetVersion(), which, unlike SDL_VERSION(), + * is not a macro. + * + * \param x A pointer to a SDL_version struct to initialize. + * + * \sa SDL_version + * \sa SDL_GetVersion */ -#define SDL_VERSION(x) \ -{ \ - (x)->major = SDL_MAJOR_VERSION; \ - (x)->minor = SDL_MINOR_VERSION; \ - (x)->patch = SDL_PATCHLEVEL; \ +#define SDL_VERSION(x) \ +{ \ + (x)->major = SDL_MAJOR_VERSION; \ + (x)->minor = SDL_MINOR_VERSION; \ + (x)->patch = SDL_PATCHLEVEL; \ } /** @@ -90,77 +88,101 @@ typedef struct SDL_version * \verbatim (1,2,3) -> (1203) \endverbatim - * + * * This assumes that there will never be more than 100 patchlevels. */ -#define SDL_VERSIONNUM(X, Y, Z) \ - ((X)*1000 + (Y)*100 + (Z)) +#define SDL_VERSIONNUM(X, Y, Z) \ + ((X)*1000 + (Y)*100 + (Z)) /** * This is the version number macro for the current SDL version. */ #define SDL_COMPILEDVERSION \ - SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) + SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) /** * This macro will evaluate to true if compiled with SDL at least X.Y.Z. */ #define SDL_VERSION_ATLEAST(X, Y, Z) \ - (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) + (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) /** - * \brief Get the version of SDL that is linked against your program. + * Get the version of SDL that is linked against your program. * - * If you are linking to SDL dynamically, then it is possible that the - * current version will be different than the version you compiled against. - * This function returns the current version, while SDL_VERSION() is a - * macro that tells you what version you compiled with. - * - * \code - * SDL_version compiled; - * SDL_version linked; - * - * SDL_VERSION(&compiled); - * SDL_GetVersion(&linked); - * printf("We compiled against SDL version %d.%d.%d ...\n", - * compiled.major, compiled.minor, compiled.patch); - * printf("But we linked against SDL version %d.%d.%d.\n", - * linked.major, linked.minor, linked.patch); - * \endcode - * - * This function may be called safely at any time, even before SDL_Init(). - * - * \sa SDL_VERSION + * If you are linking to SDL dynamically, then it is possible that the current + * version will be different than the version you compiled against. This + * function returns the current version, while SDL_VERSION() is a macro that + * tells you what version you compiled with. + * + * This function may be called safely at any time, even before SDL_Init(). + * + * \param ver the SDL_version structure that contains the version information + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRevision */ extern DECLSPEC void SDLCALL SDL_GetVersion(SDL_version * ver); /** - * \brief Get the code revision of SDL that is linked against your program. + * Get the code revision of SDL that is linked against your program. * - * Returns an arbitrary string (a hash value) uniquely identifying the - * exact revision of the SDL library in use, and is only useful in comparing - * against other revisions. It is NOT an incrementing number. + * This value is the revision of the code you are linked with and may be + * different from the code you are compiling with, which is found in the + * constant SDL_REVISION. + * + * The revision is arbitrary string (a hash value) uniquely identifying the + * exact revision of the SDL library in use, and is only useful in comparing + * against other revisions. It is NOT an incrementing number. + * + * If SDL wasn't built from a git repository with the appropriate tools, this + * will return an empty string. + * + * Prior to SDL 2.0.16, before development moved to GitHub, this returned a + * hash for a Mercurial repository. + * + * You shouldn't use this function for anything but logging it for debugging + * purposes. The string is not intended to be reliable in any way. + * + * \returns an arbitrary string, uniquely identifying the exact revision of + * the SDL library in use. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetVersion */ extern DECLSPEC const char *SDLCALL SDL_GetRevision(void); /** - * \brief Get the revision number of SDL that is linked against your program. + * Obsolete function, do not use. * - * Returns a number uniquely identifying the exact revision of the SDL - * library in use. It is an incrementing number based on commits to - * hg.libsdl.org. + * When SDL was hosted in a Mercurial repository, and was built carefully, + * this would return the revision number that the build was created from. This + * number was not reliable for several reasons, but more importantly, SDL is + * now hosted in a git repository, which does not offer numbers at all, only + * hashes. This function only ever returns zero now. Don't use it. + * + * Before SDL 2.0.16, this might have returned an unreliable, but non-zero + * number. + * + * \deprecated Use SDL_GetRevision() instead; if SDL was carefully built, it + * will return a git hash. + * + * \returns zero, always, in modern SDL releases. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetRevision */ -extern DECLSPEC int SDLCALL SDL_GetRevisionNumber(void); +extern SDL_DEPRECATED DECLSPEC int SDLCALL SDL_GetRevisionNumber(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_version_h */ +#endif /* SDL_version_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_video.h b/external/SDL2/SDL_video.h index 4873da3..e43cb27 100644 --- a/external/SDL2/SDL_video.h +++ b/external/SDL2/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,12 +21,12 @@ /** * \file SDL_video.h - * + * * Header file for SDL video functions. */ -#ifndef _SDL_video_h -#define _SDL_video_h +#ifndef SDL_video_h_ +#define SDL_video_h_ #include "SDL_stdinc.h" #include "SDL_pixels.h" @@ -36,14 +36,12 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif /** * \brief The structure that defines a display mode - * + * * \sa SDL_GetNumDisplayModes() * \sa SDL_GetDisplayMode() * \sa SDL_GetDesktopDisplayMode() @@ -55,21 +53,24 @@ extern "C" { typedef struct { Uint32 format; /**< pixel format */ - int w; /**< width */ - int h; /**< height */ + int w; /**< width, in screen coordinates */ + int h; /**< height, in screen coordinates */ int refresh_rate; /**< refresh rate (or zero for unspecified) */ void *driverdata; /**< driver-specific data, initialize to 0 */ } SDL_DisplayMode; /** * \brief The type used to identify a window - * + * * \sa SDL_CreateWindow() * \sa SDL_CreateWindowFrom() * \sa SDL_DestroyWindow() + * \sa SDL_FlashWindow() * \sa SDL_GetWindowData() * \sa SDL_GetWindowFlags() * \sa SDL_GetWindowGrab() + * \sa SDL_GetWindowKeyboardGrab() + * \sa SDL_GetWindowMouseGrab() * \sa SDL_GetWindowPosition() * \sa SDL_GetWindowSize() * \sa SDL_GetWindowTitle() @@ -81,10 +82,13 @@ typedef struct * \sa SDL_SetWindowData() * \sa SDL_SetWindowFullscreen() * \sa SDL_SetWindowGrab() + * \sa SDL_SetWindowKeyboardGrab() + * \sa SDL_SetWindowMouseGrab() * \sa SDL_SetWindowIcon() * \sa SDL_SetWindowPosition() * \sa SDL_SetWindowSize() * \sa SDL_SetWindowBordered() + * \sa SDL_SetWindowResizable() * \sa SDL_SetWindowTitle() * \sa SDL_ShowWindow() */ @@ -92,7 +96,7 @@ typedef struct SDL_Window SDL_Window; /** * \brief The flags on a window - * + * * \sa SDL_GetWindowFlags() */ typedef enum @@ -105,17 +109,31 @@ typedef enum SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */ SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */ SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */ - SDL_WINDOW_INPUT_GRABBED = 0x00000100, /**< window has grabbed input focus */ + SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */ SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */ SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */ - SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ), - SDL_WINDOW_FOREIGN = 0x00000800 /**< window not created by SDL */ + SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ), + SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */ + SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported. + On macOS NSHighResolutionCapable must be set true in the + application's Info.plist for this to have any effect. */ + SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ + SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */ + SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */ + SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */ + SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */ + SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */ + SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */ + SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */ + SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */ + + SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */ } SDL_WindowFlags; /** * \brief Used to indicate that you don't care what the window position is. */ -#define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000 +#define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000u #define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X)) #define SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED_DISPLAY(0) #define SDL_WINDOWPOS_ISUNDEFINED(X) \ @@ -124,7 +142,7 @@ typedef enum /** * \brief Used to indicate that the window position should be centered. */ -#define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000 +#define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000u #define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X)) #define SDL_WINDOWPOS_CENTERED SDL_WINDOWPOS_CENTERED_DISPLAY(0) #define SDL_WINDOWPOS_ISCENTERED(X) \ @@ -138,12 +156,14 @@ typedef enum SDL_WINDOWEVENT_NONE, /**< Never used */ SDL_WINDOWEVENT_SHOWN, /**< Window has been shown */ SDL_WINDOWEVENT_HIDDEN, /**< Window has been hidden */ - SDL_WINDOWEVENT_EXPOSED, /**< Window has been exposed and should be + SDL_WINDOWEVENT_EXPOSED, /**< Window has been exposed and should be redrawn */ - SDL_WINDOWEVENT_MOVED, /**< Window has been moved to data1, data2 + SDL_WINDOWEVENT_MOVED, /**< Window has been moved to data1, data2 */ SDL_WINDOWEVENT_RESIZED, /**< Window has been resized to data1xdata2 */ - SDL_WINDOWEVENT_SIZE_CHANGED, /**< The window size has changed, either as a result of an API call or through the system or user changing the window size. */ + SDL_WINDOWEVENT_SIZE_CHANGED, /**< The window size has changed, either as + a result of an API call or through the + system or user changing the window size. */ SDL_WINDOWEVENT_MINIMIZED, /**< Window has been minimized */ SDL_WINDOWEVENT_MAXIMIZED, /**< Window has been maximized */ SDL_WINDOWEVENT_RESTORED, /**< Window has been restored to normal size @@ -152,10 +172,46 @@ typedef enum SDL_WINDOWEVENT_LEAVE, /**< Window has lost mouse focus */ SDL_WINDOWEVENT_FOCUS_GAINED, /**< Window has gained keyboard focus */ SDL_WINDOWEVENT_FOCUS_LOST, /**< Window has lost keyboard focus */ - SDL_WINDOWEVENT_CLOSE /**< The window manager requests that the - window be closed */ + SDL_WINDOWEVENT_CLOSE, /**< The window manager requests that the window be closed */ + SDL_WINDOWEVENT_TAKE_FOCUS, /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */ + SDL_WINDOWEVENT_HIT_TEST, /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */ + SDL_WINDOWEVENT_ICCPROF_CHANGED,/**< The ICC profile of the window's display has changed. */ + SDL_WINDOWEVENT_DISPLAY_CHANGED /**< Window has been moved to display data1. */ } SDL_WindowEventID; +/** + * \brief Event subtype for display events + */ +typedef enum +{ + SDL_DISPLAYEVENT_NONE, /**< Never used */ + SDL_DISPLAYEVENT_ORIENTATION, /**< Display orientation has changed to data1 */ + SDL_DISPLAYEVENT_CONNECTED, /**< Display has been added to the system */ + SDL_DISPLAYEVENT_DISCONNECTED /**< Display has been removed from the system */ +} SDL_DisplayEventID; + +/** + * \brief Display orientation + */ +typedef enum +{ + SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */ + SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */ + SDL_ORIENTATION_LANDSCAPE_FLIPPED, /**< The display is in landscape mode, with the left side up, relative to portrait mode */ + SDL_ORIENTATION_PORTRAIT, /**< The display is in portrait mode */ + SDL_ORIENTATION_PORTRAIT_FLIPPED /**< The display is in portrait mode, upside down */ +} SDL_DisplayOrientation; + +/** + * \brief Window flash operation + */ +typedef enum +{ + SDL_FLASH_CANCEL, /**< Cancel any window flash state */ + SDL_FLASH_BRIEFLY, /**< Flash the window briefly to get attention */ + SDL_FLASH_UNTIL_FOCUSED /**< Flash the window until it gets focus */ +} SDL_FlashOperation; + /** * \brief An opaque handle to an OpenGL context. */ @@ -188,14 +244,18 @@ typedef enum SDL_GL_CONTEXT_EGL, SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_PROFILE_MASK, - SDL_GL_SHARE_WITH_CURRENT_CONTEXT + SDL_GL_SHARE_WITH_CURRENT_CONTEXT, + SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, + SDL_GL_CONTEXT_RELEASE_BEHAVIOR, + SDL_GL_CONTEXT_RESET_NOTIFICATION, + SDL_GL_CONTEXT_NO_ERROR } SDL_GLattr; typedef enum { SDL_GL_CONTEXT_PROFILE_CORE = 0x0001, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002, - SDL_GL_CONTEXT_PROFILE_ES = 0x0004 + SDL_GL_CONTEXT_PROFILE_ES = 0x0004 /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */ } SDL_GLprofile; typedef enum @@ -206,551 +266,1314 @@ typedef enum SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008 } SDL_GLcontextFlag; +typedef enum +{ + SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000, + SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001 +} SDL_GLcontextReleaseFlag; + +typedef enum +{ + SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000, + SDL_GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001 +} SDL_GLContextResetNotification; /* Function prototypes */ /** - * \brief Get the number of video drivers compiled into SDL - * - * \sa SDL_GetVideoDriver() + * Get the number of video drivers compiled into SDL. + * + * \returns a number >= 1 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetVideoDriver */ extern DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void); /** - * \brief Get the name of a built in video driver. - * - * \note The video drivers are presented in the order in which they are - * normally checked during initialization. - * - * \sa SDL_GetNumVideoDrivers() + * Get the name of a built in video driver. + * + * The video drivers are presented in the order in which they are normally + * checked during initialization. + * + * \param index the index of a video driver + * \returns the name of the video driver with the given **index**. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumVideoDrivers */ extern DECLSPEC const char *SDLCALL SDL_GetVideoDriver(int index); /** - * \brief Initialize the video subsystem, optionally specifying a video driver. - * - * \param driver_name Initialize a specific driver by name, or NULL for the - * default video driver. - * - * \return 0 on success, -1 on error - * - * This function initializes the video subsystem; setting up a connection - * to the window manager, etc, and determines the available display modes - * and pixel formats, but does not initialize a window or graphics mode. - * - * \sa SDL_VideoQuit() + * Initialize the video subsystem, optionally specifying a video driver. + * + * This function initializes the video subsystem, setting up a connection to + * the window manager, etc, and determines the available display modes and + * pixel formats, but does not initialize a window or graphics mode. + * + * If you use this function and you haven't used the SDL_INIT_VIDEO flag with + * either SDL_Init() or SDL_InitSubSystem(), you should call SDL_VideoQuit() + * before calling SDL_Quit(). + * + * It is safe to call this function multiple times. SDL_VideoInit() will call + * SDL_VideoQuit() itself if the video subsystem has already been initialized. + * + * You can use SDL_GetNumVideoDrivers() and SDL_GetVideoDriver() to find a + * specific `driver_name`. + * + * \param driver_name the name of a video driver to initialize, or NULL for + * the default driver + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumVideoDrivers + * \sa SDL_GetVideoDriver + * \sa SDL_InitSubSystem + * \sa SDL_VideoQuit */ extern DECLSPEC int SDLCALL SDL_VideoInit(const char *driver_name); /** - * \brief Shuts down the video subsystem. - * - * This function closes all windows, and restores the original video mode. - * - * \sa SDL_VideoInit() + * Shut down the video subsystem, if initialized with SDL_VideoInit(). + * + * This function closes all windows, and restores the original video mode. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_VideoInit */ extern DECLSPEC void SDLCALL SDL_VideoQuit(void); /** - * \brief Returns the name of the currently initialized video driver. - * - * \return The name of the current video driver or NULL if no driver - * has been initialized - * - * \sa SDL_GetNumVideoDrivers() - * \sa SDL_GetVideoDriver() + * Get the name of the currently initialized video driver. + * + * \returns the name of the current video driver or NULL if no driver has been + * initialized. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumVideoDrivers + * \sa SDL_GetVideoDriver */ extern DECLSPEC const char *SDLCALL SDL_GetCurrentVideoDriver(void); /** - * \brief Returns the number of available video displays. - * - * \sa SDL_GetDisplayBounds() + * Get the number of available video displays. + * + * \returns a number >= 1 or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetDisplayBounds */ extern DECLSPEC int SDLCALL SDL_GetNumVideoDisplays(void); /** - * \brief Get the name of a display in UTF-8 encoding - * - * \return The name of a display, or NULL for an invalid display index. - * - * \sa SDL_GetNumVideoDisplays() + * Get the name of a display in UTF-8 encoding. + * + * \param displayIndex the index of display from which the name should be + * queried + * \returns the name of a display or NULL for an invalid display index or + * failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumVideoDisplays */ extern DECLSPEC const char * SDLCALL SDL_GetDisplayName(int displayIndex); /** - * \brief Get the desktop area represented by a display, with the primary - * display located at 0,0 - * - * \return 0 on success, or -1 if the index is out of range. - * - * \sa SDL_GetNumVideoDisplays() + * Get the desktop area represented by a display. + * + * The primary display (`displayIndex` zero) is always located at 0,0. + * + * \param displayIndex the index of the display to query + * \param rect the SDL_Rect structure filled in with the display bounds + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumVideoDisplays */ extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect); /** - * \brief Returns the number of available display modes. - * - * \sa SDL_GetDisplayMode() + * Get the usable desktop area represented by a display. + * + * The primary display (`displayIndex` zero) is always located at 0,0. + * + * This is the same area as SDL_GetDisplayBounds() reports, but with portions + * reserved by the system removed. For example, on Apple's macOS, this + * subtracts the area occupied by the menu bar and dock. + * + * Setting a window to be fullscreen generally bypasses these unusable areas, + * so these are good guidelines for the maximum space available to a + * non-fullscreen window. + * + * The parameter `rect` is ignored if it is NULL. + * + * This function also returns -1 if the parameter `displayIndex` is out of + * range. + * + * \param displayIndex the index of the display to query the usable bounds + * from + * \param rect the SDL_Rect structure filled in with the display bounds + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_GetDisplayBounds + * \sa SDL_GetNumVideoDisplays + */ +extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect); + +/** + * Get the dots/pixels-per-inch for a display. + * + * Diagonal, horizontal and vertical DPI can all be optionally returned if the + * appropriate parameter is non-NULL. + * + * A failure of this function usually means that either no DPI information is + * available or the `displayIndex` is out of range. + * + * \param displayIndex the index of the display from which DPI information + * should be queried + * \param ddpi a pointer filled in with the diagonal DPI of the display; may + * be NULL + * \param hdpi a pointer filled in with the horizontal DPI of the display; may + * be NULL + * \param vdpi a pointer filled in with the vertical DPI of the display; may + * be NULL + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_GetNumVideoDisplays + */ +extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi); + +/** + * Get the orientation of a display. + * + * \param displayIndex the index of the display to query + * \returns The SDL_DisplayOrientation enum value of the display, or + * `SDL_ORIENTATION_UNKNOWN` if it isn't available. + * + * \since This function is available since SDL 2.0.9. + * + * \sa SDL_GetNumVideoDisplays + */ +extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetDisplayOrientation(int displayIndex); + +/** + * Get the number of available display modes. + * + * The `displayIndex` needs to be in the range from 0 to + * SDL_GetNumVideoDisplays() - 1. + * + * \param displayIndex the index of the display to query + * \returns a number >= 1 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetDisplayMode + * \sa SDL_GetNumVideoDisplays */ extern DECLSPEC int SDLCALL SDL_GetNumDisplayModes(int displayIndex); /** - * \brief Fill in information about a specific display mode. - * - * \note The display modes are sorted in this priority: - * \li bits per pixel -> more colors to fewer colors - * \li width -> largest to smallest - * \li height -> largest to smallest - * \li refresh rate -> highest to lowest - * - * \sa SDL_GetNumDisplayModes() + * Get information about a specific display mode. + * + * The display modes are sorted in this priority: + * + * - width -> largest to smallest + * - height -> largest to smallest + * - bits per pixel -> more colors to fewer colors + * - packed pixel layout -> largest to smallest + * - refresh rate -> highest to lowest + * + * \param displayIndex the index of the display to query + * \param modeIndex the index of the display mode to query + * \param mode an SDL_DisplayMode structure filled in with the mode at + * `modeIndex` + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetNumDisplayModes */ extern DECLSPEC int SDLCALL SDL_GetDisplayMode(int displayIndex, int modeIndex, SDL_DisplayMode * mode); /** - * \brief Fill in information about the desktop display mode. + * Get information about the desktop's display mode. + * + * There's a difference between this function and SDL_GetCurrentDisplayMode() + * when SDL runs fullscreen and has changed the resolution. In that case this + * function will return the previous native display mode, and not the current + * display mode. + * + * \param displayIndex the index of the display to query + * \param mode an SDL_DisplayMode structure filled in with the current display + * mode + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetCurrentDisplayMode + * \sa SDL_GetDisplayMode + * \sa SDL_SetWindowDisplayMode */ extern DECLSPEC int SDLCALL SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode); /** - * \brief Fill in information about the current display mode. + * Get information about the current display mode. + * + * There's a difference between this function and SDL_GetDesktopDisplayMode() + * when SDL runs fullscreen and has changed the resolution. In that case this + * function will return the current display mode, and not the previous native + * display mode. + * + * \param displayIndex the index of the display to query + * \param mode an SDL_DisplayMode structure filled in with the current display + * mode + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetDesktopDisplayMode + * \sa SDL_GetDisplayMode + * \sa SDL_GetNumVideoDisplays + * \sa SDL_SetWindowDisplayMode */ extern DECLSPEC int SDLCALL SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode); /** - * \brief Get the closest match to the requested display mode. - * - * \param mode The desired display mode - * \param closest A pointer to a display mode to be filled in with the closest - * match of the available display modes. - * - * \return The passed in value \c closest, or NULL if no matching video mode - * was available. - * - * The available display modes are scanned, and \c closest is filled in with the - * closest mode matching the requested mode and returned. The mode format and - * refresh_rate default to the desktop mode if they are 0. The modes are - * scanned with size being first priority, format being second priority, and - * finally checking the refresh_rate. If all the available modes are too - * small, then NULL is returned. - * - * \sa SDL_GetNumDisplayModes() - * \sa SDL_GetDisplayMode() + * Get the closest match to the requested display mode. + * + * The available display modes are scanned and `closest` is filled in with the + * closest mode matching the requested mode and returned. The mode format and + * refresh rate default to the desktop mode if they are set to 0. The modes + * are scanned with size being first priority, format being second priority, + * and finally checking the refresh rate. If all the available modes are too + * small, then NULL is returned. + * + * \param displayIndex the index of the display to query + * \param mode an SDL_DisplayMode structure containing the desired display + * mode + * \param closest an SDL_DisplayMode structure filled in with the closest + * match of the available display modes + * \returns the passed in value `closest` or NULL if no matching video mode + * was available; call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetDisplayMode + * \sa SDL_GetNumDisplayModes */ extern DECLSPEC SDL_DisplayMode * SDLCALL SDL_GetClosestDisplayMode(int displayIndex, const SDL_DisplayMode * mode, SDL_DisplayMode * closest); /** - * \brief Get the display index associated with a window. - * - * \return the display index of the display containing the center of the - * window, or -1 on error. + * Get the index of the display associated with a window. + * + * \param window the window to query + * \returns the index of the display containing the center of the window on + * success or a negative error code on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetDisplayBounds + * \sa SDL_GetNumVideoDisplays */ extern DECLSPEC int SDLCALL SDL_GetWindowDisplayIndex(SDL_Window * window); /** - * \brief Set the display mode used when a fullscreen window is visible. + * Set the display mode to use when a window is visible at fullscreen. * - * By default the window's dimensions and the desktop format and refresh rate - * are used. - * - * \param mode The mode to use, or NULL for the default mode. - * - * \return 0 on success, or -1 if setting the display mode failed. - * - * \sa SDL_GetWindowDisplayMode() - * \sa SDL_SetWindowFullscreen() + * This only affects the display mode used when the window is fullscreen. To + * change the window size when the window is not fullscreen, use + * SDL_SetWindowSize(). + * + * \param window the window to affect + * \param mode the SDL_DisplayMode structure representing the mode to use, or + * NULL to use the window's dimensions and the desktop's format + * and refresh rate + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowDisplayMode + * \sa SDL_SetWindowFullscreen */ extern DECLSPEC int SDLCALL SDL_SetWindowDisplayMode(SDL_Window * window, - const SDL_DisplayMode - * mode); + const SDL_DisplayMode * mode); /** - * \brief Fill in information about the display mode used when a fullscreen - * window is visible. + * Query the display mode to use when a window is visible at fullscreen. * - * \sa SDL_SetWindowDisplayMode() - * \sa SDL_SetWindowFullscreen() + * \param window the window to query + * \param mode an SDL_DisplayMode structure filled in with the fullscreen + * display mode + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowDisplayMode + * \sa SDL_SetWindowFullscreen */ extern DECLSPEC int SDLCALL SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode); /** - * \brief Get the pixel format associated with the window. + * Get the raw ICC profile data for the screen the window is currently on. + * + * Data returned should be freed with SDL_free. + * + * \param window the window to query + * \param size the size of the ICC profile + * \returns the raw ICC profile data on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.18. + */ +extern DECLSPEC void* SDLCALL SDL_GetWindowICCProfile(SDL_Window * window, size_t* size); + +/** + * Get the pixel format associated with the window. + * + * \param window the window to query + * \returns the pixel format of the window on success or + * SDL_PIXELFORMAT_UNKNOWN on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window); /** - * \brief Create a window with the specified position, dimensions, and flags. - * - * \param title The title of the window, in UTF-8 encoding. - * \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or - * ::SDL_WINDOWPOS_UNDEFINED. - * \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or - * ::SDL_WINDOWPOS_UNDEFINED. - * \param w The width of the window. - * \param h The height of the window. - * \param flags The flags for the window, a mask of any of the following: - * ::SDL_WINDOW_FULLSCREEN, ::SDL_WINDOW_OPENGL, - * ::SDL_WINDOW_SHOWN, ::SDL_WINDOW_BORDERLESS, - * ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED, - * ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_INPUT_GRABBED. - * - * \return The id of the window created, or zero if window creation failed. - * - * \sa SDL_DestroyWindow() + * Create a window with the specified position, dimensions, and flags. + * + * `flags` may be any of the following OR'd together: + * + * - `SDL_WINDOW_FULLSCREEN`: fullscreen window + * - `SDL_WINDOW_FULLSCREEN_DESKTOP`: fullscreen window at desktop resolution + * - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context + * - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance + * - `SDL_WINDOW_METAL`: window usable with a Metal instance + * - `SDL_WINDOW_HIDDEN`: window is not visible + * - `SDL_WINDOW_BORDERLESS`: no window decoration + * - `SDL_WINDOW_RESIZABLE`: window can be resized + * - `SDL_WINDOW_MINIMIZED`: window is minimized + * - `SDL_WINDOW_MAXIMIZED`: window is maximized + * - `SDL_WINDOW_INPUT_GRABBED`: window has grabbed input focus + * - `SDL_WINDOW_ALLOW_HIGHDPI`: window should be created in high-DPI mode if + * supported (>= SDL 2.0.1) + * + * `SDL_WINDOW_SHOWN` is ignored by SDL_CreateWindow(). The SDL_Window is + * implicitly shown if SDL_WINDOW_HIDDEN is not set. `SDL_WINDOW_SHOWN` may be + * queried later using SDL_GetWindowFlags(). + * + * On Apple's macOS, you **must** set the NSHighResolutionCapable Info.plist + * property to YES, otherwise you will not receive a High-DPI OpenGL canvas. + * + * If the window is created with the `SDL_WINDOW_ALLOW_HIGHDPI` flag, its size + * in pixels may differ from its size in screen coordinates on platforms with + * high-DPI support (e.g. iOS and macOS). Use SDL_GetWindowSize() to query the + * client area's size in screen coordinates, and SDL_GL_GetDrawableSize() or + * SDL_GetRendererOutputSize() to query the drawable size in pixels. + * + * If the window is set fullscreen, the width and height parameters `w` and + * `h` will not be used. However, invalid size parameters (e.g. too large) may + * still fail. Window size is actually limited to 16384 x 16384 for all + * platforms at window creation. + * + * If the window is created with any of the SDL_WINDOW_OPENGL or + * SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function + * (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the + * corresponding UnloadLibrary function is called by SDL_DestroyWindow(). + * + * If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver, + * SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail. + * + * If SDL_WINDOW_METAL is specified on an OS that does not support Metal, + * SDL_CreateWindow() will fail. + * + * On non-Apple devices, SDL requires you to either not link to the Vulkan + * loader or link to a dynamic library version. This limitation may be removed + * in a future version of SDL. + * + * \param title the title of the window, in UTF-8 encoding + * \param x the x position of the window, `SDL_WINDOWPOS_CENTERED`, or + * `SDL_WINDOWPOS_UNDEFINED` + * \param y the y position of the window, `SDL_WINDOWPOS_CENTERED`, or + * `SDL_WINDOWPOS_UNDEFINED` + * \param w the width of the window, in screen coordinates + * \param h the height of the window, in screen coordinates + * \param flags 0, or one or more SDL_WindowFlags OR'd together + * \returns the window that was created or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateWindowFrom + * \sa SDL_DestroyWindow */ extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags); /** - * \brief Create an SDL window from an existing native window. - * - * \param data A pointer to driver-dependent window creation data - * - * \return The id of the window created, or zero if window creation failed. - * - * \sa SDL_DestroyWindow() + * Create an SDL window from an existing native window. + * + * In some cases (e.g. OpenGL) and on some platforms (e.g. Microsoft Windows) + * the hint `SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT` needs to be configured + * before using SDL_CreateWindowFrom(). + * + * \param data a pointer to driver-dependent window creation data, typically + * your native window cast to a void* + * \returns the window that was created or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateWindow + * \sa SDL_DestroyWindow */ extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowFrom(const void *data); /** - * \brief Get the numeric ID of a window, for logging purposes. + * Get the numeric ID of a window. + * + * The numeric ID is what SDL_WindowEvent references, and is necessary to map + * these events to specific SDL_Window objects. + * + * \param window the window to query + * \returns the ID of the window on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowFromID */ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowID(SDL_Window * window); /** - * \brief Get a window from a stored ID, or NULL if it doesn't exist. + * Get a window from a stored ID. + * + * The numeric ID is what SDL_WindowEvent references, and is necessary to map + * these events to specific SDL_Window objects. + * + * \param id the ID of the window + * \returns the window associated with `id` or NULL if it doesn't exist; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowID */ extern DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromID(Uint32 id); /** - * \brief Get the window flags. + * Get the window flags. + * + * \param window the window to query + * \returns a mask of the SDL_WindowFlags associated with `window` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateWindow + * \sa SDL_HideWindow + * \sa SDL_MaximizeWindow + * \sa SDL_MinimizeWindow + * \sa SDL_SetWindowFullscreen + * \sa SDL_SetWindowGrab + * \sa SDL_ShowWindow */ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window * window); /** - * \brief Set the title of a window, in UTF-8 format. - * - * \sa SDL_GetWindowTitle() + * Set the title of a window. + * + * This string is expected to be in UTF-8 encoding. + * + * \param window the window to change + * \param title the desired window title in UTF-8 format + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowTitle */ extern DECLSPEC void SDLCALL SDL_SetWindowTitle(SDL_Window * window, const char *title); /** - * \brief Get the title of a window, in UTF-8 format. - * - * \sa SDL_SetWindowTitle() + * Get the title of a window. + * + * \param window the window to query + * \returns the title of the window in UTF-8 format or "" if there is no + * title. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowTitle */ extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window * window); /** - * \brief Set the icon for a window. - * - * \param icon The icon for the window. + * Set the icon for a window. + * + * \param window the window to change + * \param icon an SDL_Surface structure containing the icon for the window + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_SetWindowIcon(SDL_Window * window, SDL_Surface * icon); /** - * \brief Associate an arbitrary named pointer with a window. - * - * \param window The window to associate with the pointer. - * \param name The name of the pointer. - * \param userdata The associated pointer. + * Associate an arbitrary named pointer with a window. * - * \return The previous value associated with 'name' + * `name` is case-sensitive. * - * \note The name is case-sensitive. + * \param window the window to associate with the pointer + * \param name the name of the pointer + * \param userdata the associated pointer + * \returns the previous value associated with `name`. * - * \sa SDL_GetWindowData() + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowData */ extern DECLSPEC void* SDLCALL SDL_SetWindowData(SDL_Window * window, const char *name, void *userdata); /** - * \brief Retrieve the data pointer associated with a window. - * - * \param window The window to query. - * \param name The name of the pointer. + * Retrieve the data pointer associated with a window. * - * \return The value associated with 'name' - * - * \sa SDL_SetWindowData() + * \param window the window to query + * \param name the name of the pointer + * \returns the value associated with `name`. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowData */ extern DECLSPEC void *SDLCALL SDL_GetWindowData(SDL_Window * window, const char *name); /** - * \brief Set the position of a window. - * - * \param window The window to reposition. - * \param x The x coordinate of the window, ::SDL_WINDOWPOS_CENTERED, or - ::SDL_WINDOWPOS_UNDEFINED. - * \param y The y coordinate of the window, ::SDL_WINDOWPOS_CENTERED, or - ::SDL_WINDOWPOS_UNDEFINED. - * - * \note The window coordinate origin is the upper left of the display. - * - * \sa SDL_GetWindowPosition() + * Set the position of a window. + * + * The window coordinate origin is the upper left of the display. + * + * \param window the window to reposition + * \param x the x coordinate of the window in screen coordinates, or + * `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED` + * \param y the y coordinate of the window in screen coordinates, or + * `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED` + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowPosition */ extern DECLSPEC void SDLCALL SDL_SetWindowPosition(SDL_Window * window, int x, int y); /** - * \brief Get the position of a window. - * - * \param x Pointer to variable for storing the x position, may be NULL - * \param y Pointer to variable for storing the y position, may be NULL + * Get the position of a window. * - * \sa SDL_SetWindowPosition() + * If you do not need the value for one of the positions a NULL may be passed + * in the `x` or `y` parameter. + * + * \param window the window to query + * \param x a pointer filled in with the x position of the window, in screen + * coordinates, may be NULL + * \param y a pointer filled in with the y position of the window, in screen + * coordinates, may be NULL + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowPosition */ extern DECLSPEC void SDLCALL SDL_GetWindowPosition(SDL_Window * window, int *x, int *y); /** - * \brief Set the size of a window's client area. - * - * \param w The width of the window, must be >0 - * \param h The height of the window, must be >0 + * Set the size of a window's client area. * - * \note You can't change the size of a fullscreen window, it automatically - * matches the size of the display mode. - * - * \sa SDL_GetWindowSize() + * The window size in screen coordinates may differ from the size in pixels, + * if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform + * with high-dpi support (e.g. iOS or macOS). Use SDL_GL_GetDrawableSize() or + * SDL_GetRendererOutputSize() to get the real client area size in pixels. + * + * Fullscreen windows automatically match the size of the display mode, and + * you should use SDL_SetWindowDisplayMode() to change their size. + * + * \param window the window to change + * \param w the width of the window in pixels, in screen coordinates, must be + * > 0 + * \param h the height of the window in pixels, in screen coordinates, must be + * > 0 + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowSize + * \sa SDL_SetWindowDisplayMode */ extern DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window * window, int w, int h); /** - * \brief Get the size of a window's client area. - * - * \param w Pointer to variable for storing the width, may be NULL - * \param h Pointer to variable for storing the height, may be NULL - * - * \sa SDL_SetWindowSize() + * Get the size of a window's client area. + * + * NULL can safely be passed as the `w` or `h` parameter if the width or + * height value is not desired. + * + * The window size in screen coordinates may differ from the size in pixels, + * if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform + * with high-dpi support (e.g. iOS or macOS). Use SDL_GL_GetDrawableSize(), + * SDL_Vulkan_GetDrawableSize(), or SDL_GetRendererOutputSize() to get the + * real client area size in pixels. + * + * \param window the window to query the width and height from + * \param w a pointer filled in with the width of the window, in screen + * coordinates, may be NULL + * \param h a pointer filled in with the height of the window, in screen + * coordinates, may be NULL + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_GetDrawableSize + * \sa SDL_Vulkan_GetDrawableSize + * \sa SDL_SetWindowSize */ extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window * window, int *w, int *h); - + /** - * \brief Set the minimum size of a window's client area. - * - * \param min_w The minimum width of the window, must be >0 - * \param min_h The minimum height of the window, must be >0 + * Get the size of a window's borders (decorations) around the client area. * - * \note You can't change the minimum size of a fullscreen window, it - * automatically matches the size of the display mode. + * Note: If this function fails (returns -1), the size values will be + * initialized to 0, 0, 0, 0 (if a non-NULL pointer is provided), as if the + * window in question was borderless. * - * \sa SDL_GetWindowMinimumSize() - * \sa SDL_SetWindowMaximumSize() + * Note: This function may fail on systems where the window has not yet been + * decorated by the display server (for example, immediately after calling + * SDL_CreateWindow). It is recommended that you wait at least until the + * window has been presented and composited, so that the window system has a + * chance to decorate the window and provide the border dimensions to SDL. + * + * This function also returns -1 if getting the information is not supported. + * + * \param window the window to query the size values of the border + * (decorations) from + * \param top pointer to variable for storing the size of the top border; NULL + * is permitted + * \param left pointer to variable for storing the size of the left border; + * NULL is permitted + * \param bottom pointer to variable for storing the size of the bottom + * border; NULL is permitted + * \param right pointer to variable for storing the size of the right border; + * NULL is permitted + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_GetWindowSize + */ +extern DECLSPEC int SDLCALL SDL_GetWindowBordersSize(SDL_Window * window, + int *top, int *left, + int *bottom, int *right); + +/** + * Set the minimum size of a window's client area. + * + * \param window the window to change + * \param min_w the minimum width of the window in pixels + * \param min_h the minimum height of the window in pixels + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowMinimumSize + * \sa SDL_SetWindowMaximumSize */ extern DECLSPEC void SDLCALL SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h); - + /** - * \brief Get the minimum size of a window's client area. - * - * \param w Pointer to variable for storing the minimum width, may be NULL - * \param h Pointer to variable for storing the minimum height, may be NULL - * - * \sa SDL_GetWindowMaximumSize() - * \sa SDL_SetWindowMinimumSize() + * Get the minimum size of a window's client area. + * + * \param window the window to query + * \param w a pointer filled in with the minimum width of the window, may be + * NULL + * \param h a pointer filled in with the minimum height of the window, may be + * NULL + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowMaximumSize + * \sa SDL_SetWindowMinimumSize */ extern DECLSPEC void SDLCALL SDL_GetWindowMinimumSize(SDL_Window * window, int *w, int *h); /** - * \brief Set the maximum size of a window's client area. + * Set the maximum size of a window's client area. * - * \param max_w The maximum width of the window, must be >0 - * \param max_h The maximum height of the window, must be >0 + * \param window the window to change + * \param max_w the maximum width of the window in pixels + * \param max_h the maximum height of the window in pixels * - * \note You can't change the maximum size of a fullscreen window, it - * automatically matches the size of the display mode. + * \since This function is available since SDL 2.0.0. * - * \sa SDL_GetWindowMaximumSize() - * \sa SDL_SetWindowMinimumSize() + * \sa SDL_GetWindowMaximumSize + * \sa SDL_SetWindowMinimumSize */ extern DECLSPEC void SDLCALL SDL_SetWindowMaximumSize(SDL_Window * window, int max_w, int max_h); - + /** - * \brief Get the maximum size of a window's client area. - * - * \param w Pointer to variable for storing the maximum width, may be NULL - * \param h Pointer to variable for storing the maximum height, may be NULL + * Get the maximum size of a window's client area. * - * \sa SDL_GetWindowMinimumSize() - * \sa SDL_SetWindowMaximumSize() + * \param window the window to query + * \param w a pointer filled in with the maximum width of the window, may be + * NULL + * \param h a pointer filled in with the maximum height of the window, may be + * NULL + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowMinimumSize + * \sa SDL_SetWindowMaximumSize */ extern DECLSPEC void SDLCALL SDL_GetWindowMaximumSize(SDL_Window * window, int *w, int *h); /** - * \brief Set the border state of a window. + * Set the border state of a window. * - * This will add or remove the window's SDL_WINDOW_BORDERLESS flag and - * add or remove the border from the actual window. This is a no-op if the - * window's border already matches the requested state. + * This will add or remove the window's `SDL_WINDOW_BORDERLESS` flag and add + * or remove the border from the actual window. This is a no-op if the + * window's border already matches the requested state. * - * \param window The window of which to change the border state. - * \param bordered SDL_FALSE to remove border, SDL_TRUE to add border. + * You can't change the border state of a fullscreen window. * - * \note You can't change the border state of a fullscreen window. - * - * \sa SDL_GetWindowFlags() + * \param window the window of which to change the border state + * \param bordered SDL_FALSE to remove border, SDL_TRUE to add border + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowFlags */ extern DECLSPEC void SDLCALL SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered); /** - * \brief Show a window. - * - * \sa SDL_HideWindow() + * Set the user-resizable state of a window. + * + * This will add or remove the window's `SDL_WINDOW_RESIZABLE` flag and + * allow/disallow user resizing of the window. This is a no-op if the window's + * resizable state already matches the requested state. + * + * You can't change the resizable state of a fullscreen window. + * + * \param window the window of which to change the resizable state + * \param resizable SDL_TRUE to allow resizing, SDL_FALSE to disallow + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_GetWindowFlags + */ +extern DECLSPEC void SDLCALL SDL_SetWindowResizable(SDL_Window * window, + SDL_bool resizable); + +/** + * Set the window to always be above the others. + * + * This will add or remove the window's `SDL_WINDOW_ALWAYS_ON_TOP` flag. This + * will bring the window to the front and keep the window above the rest. + * + * \param window The window of which to change the always on top state + * \param on_top SDL_TRUE to set the window always on top, SDL_FALSE to + * disable + * + * \since This function is available since SDL 2.0.16. + * + * \sa SDL_GetWindowFlags + */ +extern DECLSPEC void SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window * window, + SDL_bool on_top); + +/** + * Show a window. + * + * \param window the window to show + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_HideWindow + * \sa SDL_RaiseWindow */ extern DECLSPEC void SDLCALL SDL_ShowWindow(SDL_Window * window); /** - * \brief Hide a window. - * - * \sa SDL_ShowWindow() + * Hide a window. + * + * \param window the window to hide + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_ShowWindow */ extern DECLSPEC void SDLCALL SDL_HideWindow(SDL_Window * window); /** - * \brief Raise a window above other windows and set the input focus. + * Raise a window above other windows and set the input focus. + * + * \param window the window to raise + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_RaiseWindow(SDL_Window * window); /** - * \brief Make a window as large as possible. - * - * \sa SDL_RestoreWindow() + * Make a window as large as possible. + * + * \param window the window to maximize + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_MinimizeWindow + * \sa SDL_RestoreWindow */ extern DECLSPEC void SDLCALL SDL_MaximizeWindow(SDL_Window * window); /** - * \brief Minimize a window to an iconic representation. - * - * \sa SDL_RestoreWindow() + * Minimize a window to an iconic representation. + * + * \param window the window to minimize + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_MaximizeWindow + * \sa SDL_RestoreWindow */ extern DECLSPEC void SDLCALL SDL_MinimizeWindow(SDL_Window * window); /** - * \brief Restore the size and position of a minimized or maximized window. - * - * \sa SDL_MaximizeWindow() - * \sa SDL_MinimizeWindow() + * Restore the size and position of a minimized or maximized window. + * + * \param window the window to restore + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_MaximizeWindow + * \sa SDL_MinimizeWindow */ extern DECLSPEC void SDLCALL SDL_RestoreWindow(SDL_Window * window); /** - * \brief Set a window's fullscreen state. - * - * \return 0 on success, or -1 if setting the display mode failed. - * - * \sa SDL_SetWindowDisplayMode() - * \sa SDL_GetWindowDisplayMode() + * Set a window's fullscreen state. + * + * `flags` may be `SDL_WINDOW_FULLSCREEN`, for "real" fullscreen with a + * videomode change; `SDL_WINDOW_FULLSCREEN_DESKTOP` for "fake" fullscreen + * that takes the size of the desktop; and 0 for windowed mode. + * + * \param window the window to change + * \param flags `SDL_WINDOW_FULLSCREEN`, `SDL_WINDOW_FULLSCREEN_DESKTOP` or 0 + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowDisplayMode + * \sa SDL_SetWindowDisplayMode */ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags); /** - * \brief Get the SDL surface associated with the window. + * Get the SDL surface associated with the window. * - * \return The window's framebuffer surface, or NULL on error. + * A new surface will be created with the optimal format for the window, if + * necessary. This surface will be freed when the window is destroyed. Do not + * free this surface. * - * A new surface will be created with the optimal format for the window, - * if necessary. This surface will be freed when the window is destroyed. + * This surface will be invalidated if the window is resized. After resizing a + * window this function must be called again to return a valid surface. * - * \note You may not combine this with 3D or the rendering API on this window. + * You may not combine this with 3D or the rendering API on this window. * - * \sa SDL_UpdateWindowSurface() - * \sa SDL_UpdateWindowSurfaceRects() + * This function is affected by `SDL_HINT_FRAMEBUFFER_ACCELERATION`. + * + * \param window the window to query + * \returns the surface associated with the window, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_UpdateWindowSurface + * \sa SDL_UpdateWindowSurfaceRects */ extern DECLSPEC SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window * window); /** - * \brief Copy the window surface to the screen. + * Copy the window surface to the screen. * - * \return 0 on success, or -1 on error. + * This is the function you use to reflect any changes to the surface on the + * screen. * - * \sa SDL_GetWindowSurface() - * \sa SDL_UpdateWindowSurfaceRects() + * This function is equivalent to the SDL 1.2 API SDL_Flip(). + * + * \param window the window to update + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowSurface + * \sa SDL_UpdateWindowSurfaceRects */ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window); /** - * \brief Copy a number of rectangles on the window surface to the screen. + * Copy areas of the window surface to the screen. * - * \return 0 on success, or -1 on error. + * This is the function you use to reflect changes to portions of the surface + * on the screen. * - * \sa SDL_GetWindowSurface() - * \sa SDL_UpdateWindowSurfaceRect() + * This function is equivalent to the SDL 1.2 API SDL_UpdateRects(). + * + * \param window the window to update + * \param rects an array of SDL_Rect structures representing areas of the + * surface to copy + * \param numrects the number of rectangles + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowSurface + * \sa SDL_UpdateWindowSurface */ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects, int numrects); /** - * \brief Set a window's input grab mode. - * - * \param grabbed This is SDL_TRUE to grab input, and SDL_FALSE to release input. - * - * \sa SDL_GetWindowGrab() + * Set a window's input grab mode. + * + * When input is grabbed, the mouse is confined to the window. This function + * will also grab the keyboard if `SDL_HINT_GRAB_KEYBOARD` is set. To grab the + * keyboard without also grabbing the mouse, use SDL_SetWindowKeyboardGrab(). + * + * If the caller enables a grab while another window is currently grabbed, the + * other window loses its grab in favor of the caller's window. + * + * \param window the window for which the input grab mode should be set + * \param grabbed SDL_TRUE to grab input or SDL_FALSE to release input + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetGrabbedWindow + * \sa SDL_GetWindowGrab */ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window, SDL_bool grabbed); /** - * \brief Get a window's input grab mode. - * - * \return This returns SDL_TRUE if input is grabbed, and SDL_FALSE otherwise. - * - * \sa SDL_SetWindowGrab() + * Set a window's keyboard grab mode. + * + * Keyboard grab enables capture of system keyboard shortcuts like Alt+Tab or + * the Meta/Super key. Note that not all system keyboard shortcuts can be + * captured by applications (one example is Ctrl+Alt+Del on Windows). + * + * This is primarily intended for specialized applications such as VNC clients + * or VM frontends. Normal games should not use keyboard grab. + * + * When keyboard grab is enabled, SDL will continue to handle Alt+Tab when the + * window is full-screen to ensure the user is not trapped in your + * application. If you have a custom keyboard shortcut to exit fullscreen + * mode, you may suppress this behavior with + * `SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED`. + * + * If the caller enables a grab while another window is currently grabbed, the + * other window loses its grab in favor of the caller's window. + * + * \param window The window for which the keyboard grab mode should be set. + * \param grabbed This is SDL_TRUE to grab keyboard, and SDL_FALSE to release. + * + * \since This function is available since SDL 2.0.16. + * + * \sa SDL_GetWindowKeyboardGrab + * \sa SDL_SetWindowMouseGrab + * \sa SDL_SetWindowGrab + */ +extern DECLSPEC void SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window * window, + SDL_bool grabbed); + +/** + * Set a window's mouse grab mode. + * + * Mouse grab confines the mouse cursor to the window. + * + * \param window The window for which the mouse grab mode should be set. + * + * \since This function is available since SDL 2.0.16. + * + * \sa SDL_GetWindowMouseGrab + * \sa SDL_SetWindowKeyboardGrab + * \sa SDL_SetWindowGrab + */ +extern DECLSPEC void SDLCALL SDL_SetWindowMouseGrab(SDL_Window * window, + SDL_bool grabbed); + +/** + * Get a window's input grab mode. + * + * \param window the window to query + * \returns SDL_TRUE if input is grabbed, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowGrab */ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window); /** - * \brief Set the brightness (gamma correction) for a window. - * - * \return 0 on success, or -1 if setting the brightness isn't supported. - * - * \sa SDL_GetWindowBrightness() - * \sa SDL_SetWindowGammaRamp() + * Get a window's keyboard grab mode. + * + * \param window the window to query + * \returns SDL_TRUE if keyboard is grabbed, and SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.16. + * + * \sa SDL_SetWindowKeyboardGrab + * \sa SDL_GetWindowGrab + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window * window); + +/** + * Get a window's mouse grab mode. + * + * \param window the window to query + * \returns SDL_TRUE if mouse is grabbed, and SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.16. + * + * \sa SDL_SetWindowKeyboardGrab + * \sa SDL_GetWindowGrab + */ +extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window * window); + +/** + * Get the window that currently has an input grab enabled. + * + * \returns the window if input is grabbed or NULL otherwise. + * + * \since This function is available since SDL 2.0.4. + * + * \sa SDL_GetWindowGrab + * \sa SDL_SetWindowGrab + */ +extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void); + +/** + * Confines the cursor to the specified area of a window. + * + * Note that this does NOT grab the cursor, it only defines the area a cursor + * is restricted to when the window has mouse focus. + * + * \param window The window that will be associated with the barrier. + * \param rect A rectangle area in window-relative coordinates. If NULL the + * barrier for the specified window will be destroyed. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_GetWindowMouseRect + * \sa SDL_SetWindowMouseGrab + */ +extern DECLSPEC int SDLCALL SDL_SetWindowMouseRect(SDL_Window * window, const SDL_Rect * rect); + +/** + * Get the mouse confinement rectangle of a window. + * + * \param window The window to query + * \returns A pointer to the mouse confinement rectangle of a window, or NULL + * if there isn't one. + * + * \since This function is available since SDL 2.0.18. + * + * \sa SDL_SetWindowMouseRect + */ +extern DECLSPEC const SDL_Rect * SDLCALL SDL_GetWindowMouseRect(SDL_Window * window); + +/** + * Set the brightness (gamma multiplier) for a given window's display. + * + * Despite the name and signature, this method sets the brightness of the + * entire display, not an individual window. A window is considered to be + * owned by the display that contains the window's center pixel. (The index of + * this display can be retrieved using SDL_GetWindowDisplayIndex().) The + * brightness set will not follow the window if it is moved to another + * display. + * + * Many platforms will refuse to set the display brightness in modern times. + * You are better off using a shader to adjust gamma during rendering, or + * something similar. + * + * \param window the window used to select the display whose brightness will + * be changed + * \param brightness the brightness (gamma multiplier) value to set where 0.0 + * is completely dark and 1.0 is normal brightness + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowBrightness + * \sa SDL_SetWindowGammaRamp */ extern DECLSPEC int SDLCALL SDL_SetWindowBrightness(SDL_Window * window, float brightness); /** - * \brief Get the brightness (gamma correction) for a window. - * - * \return The last brightness value passed to SDL_SetWindowBrightness() - * - * \sa SDL_SetWindowBrightness() + * Get the brightness (gamma multiplier) for a given window's display. + * + * Despite the name and signature, this method retrieves the brightness of the + * entire display, not an individual window. A window is considered to be + * owned by the display that contains the window's center pixel. (The index of + * this display can be retrieved using SDL_GetWindowDisplayIndex().) + * + * \param window the window used to select the display whose brightness will + * be queried + * \returns the brightness for the display where 0.0 is completely dark and + * 1.0 is normal brightness. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowBrightness */ extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window); /** - * \brief Set the gamma ramp for a window. - * - * \param red The translation table for the red channel, or NULL. - * \param green The translation table for the green channel, or NULL. - * \param blue The translation table for the blue channel, or NULL. - * - * \return 0 on success, or -1 if gamma ramps are unsupported. - * - * Set the gamma translation table for the red, green, and blue channels - * of the video hardware. Each table is an array of 256 16-bit quantities, - * representing a mapping between the input and output for that channel. - * The input is the index into the array, and the output is the 16-bit - * gamma value at that index, scaled to the output color precision. + * Set the opacity for a window. * - * \sa SDL_GetWindowGammaRamp() + * The parameter `opacity` will be clamped internally between 0.0f + * (transparent) and 1.0f (opaque). + * + * This function also returns -1 if setting the opacity isn't supported. + * + * \param window the window which will be made transparent or opaque + * \param opacity the opacity value (0.0f - transparent, 1.0f - opaque) + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_GetWindowOpacity + */ +extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window * window, float opacity); + +/** + * Get the opacity of a window. + * + * If transparency isn't supported on this platform, opacity will be reported + * as 1.0f without error. + * + * The parameter `opacity` is ignored if it is NULL. + * + * This function also returns -1 if an invalid window was provided. + * + * \param window the window to get the current opacity value from + * \param out_opacity the float filled in (0.0f - transparent, 1.0f - opaque) + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_SetWindowOpacity + */ +extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity); + +/** + * Set the window as a modal for another window. + * + * \param modal_window the window that should be set modal + * \param parent_window the parent window for the modal window + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + */ +extern DECLSPEC int SDLCALL SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window); + +/** + * Explicitly set input focus to the window. + * + * You almost certainly want SDL_RaiseWindow() instead of this function. Use + * this with caution, as you might give focus to a window that is completely + * obscured by other windows. + * + * \param window the window that should get the input focus + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.5. + * + * \sa SDL_RaiseWindow + */ +extern DECLSPEC int SDLCALL SDL_SetWindowInputFocus(SDL_Window * window); + +/** + * Set the gamma ramp for the display that owns a given window. + * + * Set the gamma translation table for the red, green, and blue channels of + * the video hardware. Each table is an array of 256 16-bit quantities, + * representing a mapping between the input and output for that channel. The + * input is the index into the array, and the output is the 16-bit gamma value + * at that index, scaled to the output color precision. + * + * Despite the name and signature, this method sets the gamma ramp of the + * entire display, not an individual window. A window is considered to be + * owned by the display that contains the window's center pixel. (The index of + * this display can be retrieved using SDL_GetWindowDisplayIndex().) The gamma + * ramp set will not follow the window if it is moved to another display. + * + * \param window the window used to select the display whose gamma ramp will + * be changed + * \param red a 256 element array of 16-bit quantities representing the + * translation table for the red channel, or NULL + * \param green a 256 element array of 16-bit quantities representing the + * translation table for the green channel, or NULL + * \param blue a 256 element array of 16-bit quantities representing the + * translation table for the blue channel, or NULL + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GetWindowGammaRamp */ extern DECLSPEC int SDLCALL SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red, @@ -758,18 +1581,27 @@ extern DECLSPEC int SDLCALL SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * blue); /** - * \brief Get the gamma ramp for a window. - * - * \param red A pointer to a 256 element array of 16-bit quantities to hold - * the translation table for the red channel, or NULL. - * \param green A pointer to a 256 element array of 16-bit quantities to hold - * the translation table for the green channel, or NULL. - * \param blue A pointer to a 256 element array of 16-bit quantities to hold - * the translation table for the blue channel, or NULL. - * - * \return 0 on success, or -1 if gamma ramps are unsupported. - * - * \sa SDL_SetWindowGammaRamp() + * Get the gamma ramp for a given window's display. + * + * Despite the name and signature, this method retrieves the gamma ramp of the + * entire display, not an individual window. A window is considered to be + * owned by the display that contains the window's center pixel. (The index of + * this display can be retrieved using SDL_GetWindowDisplayIndex().) + * + * \param window the window used to select the display whose gamma ramp will + * be queried + * \param red a 256 element array of 16-bit quantities filled in with the + * translation table for the red channel, or NULL + * \param green a 256 element array of 16-bit quantities filled in with the + * translation table for the green channel, or NULL + * \param blue a 256 element array of 16-bit quantities filled in with the + * translation table for the blue channel, or NULL + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_SetWindowGammaRamp */ extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red, @@ -777,32 +1609,148 @@ extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * blue); /** - * \brief Destroy a window. + * Possible return values from the SDL_HitTest callback. + * + * \sa SDL_HitTest + */ +typedef enum +{ + SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */ + SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */ + SDL_HITTEST_RESIZE_TOPLEFT, + SDL_HITTEST_RESIZE_TOP, + SDL_HITTEST_RESIZE_TOPRIGHT, + SDL_HITTEST_RESIZE_RIGHT, + SDL_HITTEST_RESIZE_BOTTOMRIGHT, + SDL_HITTEST_RESIZE_BOTTOM, + SDL_HITTEST_RESIZE_BOTTOMLEFT, + SDL_HITTEST_RESIZE_LEFT +} SDL_HitTestResult; + +/** + * Callback used for hit-testing. + * + * \param win the SDL_Window where hit-testing was set on + * \param area an SDL_Point which should be hit-tested + * \param data what was passed as `callback_data` to SDL_SetWindowHitTest() + * \return an SDL_HitTestResult value. + * + * \sa SDL_SetWindowHitTest + */ +typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win, + const SDL_Point *area, + void *data); + +/** + * Provide a callback that decides if a window region has special properties. + * + * Normally windows are dragged and resized by decorations provided by the + * system window manager (a title bar, borders, etc), but for some apps, it + * makes sense to drag them from somewhere else inside the window itself; for + * example, one might have a borderless window that wants to be draggable from + * any part, or simulate its own title bar, etc. + * + * This function lets the app provide a callback that designates pieces of a + * given window as special. This callback is run during event processing if we + * need to tell the OS to treat a region of the window specially; the use of + * this callback is known as "hit testing." + * + * Mouse input may not be delivered to your application if it is within a + * special area; the OS will often apply that input to moving the window or + * resizing the window and not deliver it to the application. + * + * Specifying NULL for a callback disables hit-testing. Hit-testing is + * disabled by default. + * + * Platforms that don't support this functionality will return -1 + * unconditionally, even if you're attempting to disable hit-testing. + * + * Your callback may fire at any time, and its firing does not indicate any + * specific behavior (for example, on Windows, this certainly might fire when + * the OS is deciding whether to drag your window, but it fires for lots of + * other reasons, too, some unrelated to anything you probably care about _and + * when the mouse isn't actually at the location it is testing_). Since this + * can fire at any time, you should try to keep your callback efficient, + * devoid of allocations, etc. + * + * \param window the window to set hit-testing on + * \param callback the function to call when doing a hit-test + * \param callback_data an app-defined void pointer passed to **callback** + * \returns 0 on success or -1 on error (including unsupported); call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.4. + */ +extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window * window, + SDL_HitTest callback, + void *callback_data); + +/** + * Request a window to demand attention from the user. + * + * \param window the window to be flashed + * \param operation the flash operation + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.16. + */ +extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window * window, SDL_FlashOperation operation); + +/** + * Destroy a window. + * + * If `window` is NULL, this function will return immediately after setting + * the SDL error message to "Invalid window". See SDL_GetError(). + * + * \param window the window to destroy + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_CreateWindow + * \sa SDL_CreateWindowFrom */ extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window * window); /** - * \brief Returns whether the screensaver is currently enabled (default on). - * - * \sa SDL_EnableScreenSaver() - * \sa SDL_DisableScreenSaver() + * Check whether the screensaver is currently enabled. + * + * The screensaver is disabled by default since SDL 2.0.2. Before SDL 2.0.2 + * the screensaver was enabled by default. + * + * The default can also be changed using `SDL_HINT_VIDEO_ALLOW_SCREENSAVER`. + * + * \returns SDL_TRUE if the screensaver is enabled, SDL_FALSE if it is + * disabled. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DisableScreenSaver + * \sa SDL_EnableScreenSaver */ extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenSaverEnabled(void); /** - * \brief Allow the screen to be blanked by a screensaver - * - * \sa SDL_IsScreenSaverEnabled() - * \sa SDL_DisableScreenSaver() + * Allow the screen to be blanked by a screen saver. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_DisableScreenSaver + * \sa SDL_IsScreenSaverEnabled */ extern DECLSPEC void SDLCALL SDL_EnableScreenSaver(void); /** - * \brief Prevent the screen from being blanked by a screensaver - * - * \sa SDL_IsScreenSaverEnabled() - * \sa SDL_EnableScreenSaver() + * Prevent the screen from being blanked by a screen saver. + * + * If you disable the screensaver, it is automatically re-enabled when SDL + * quits. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_EnableScreenSaver + * \sa SDL_IsScreenSaverEnabled */ extern DECLSPEC void SDLCALL SDL_DisableScreenSaver(void); @@ -810,125 +1758,331 @@ extern DECLSPEC void SDLCALL SDL_DisableScreenSaver(void); /** * \name OpenGL support functions */ -/*@{*/ +/* @{ */ /** - * \brief Dynamically load an OpenGL library. - * - * \param path The platform dependent OpenGL library name, or NULL to open the - * default OpenGL library. - * - * \return 0 on success, or -1 if the library couldn't be loaded. - * - * This should be done after initializing the video driver, but before - * creating any OpenGL windows. If no OpenGL library is loaded, the default - * library will be loaded upon creation of the first OpenGL window. - * - * \note If you do this, you need to retrieve all of the GL functions used in - * your program from the dynamic library using SDL_GL_GetProcAddress(). - * - * \sa SDL_GL_GetProcAddress() - * \sa SDL_GL_UnloadLibrary() + * Dynamically load an OpenGL library. + * + * This should be done after initializing the video driver, but before + * creating any OpenGL windows. If no OpenGL library is loaded, the default + * library will be loaded upon creation of the first OpenGL window. + * + * If you do this, you need to retrieve all of the GL functions used in your + * program from the dynamic library using SDL_GL_GetProcAddress(). + * + * \param path the platform dependent OpenGL library name, or NULL to open the + * default OpenGL library + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_GetProcAddress + * \sa SDL_GL_UnloadLibrary */ extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); /** - * \brief Get the address of an OpenGL function. + * Get an OpenGL function by name. + * + * If the GL library is loaded at runtime with SDL_GL_LoadLibrary(), then all + * GL functions must be retrieved this way. Usually this is used to retrieve + * function pointers to OpenGL extensions. + * + * There are some quirks to looking up OpenGL functions that require some + * extra care from the application. If you code carefully, you can handle + * these quirks without any platform-specific code, though: + * + * - On Windows, function pointers are specific to the current GL context; + * this means you need to have created a GL context and made it current + * before calling SDL_GL_GetProcAddress(). If you recreate your context or + * create a second context, you should assume that any existing function + * pointers aren't valid to use with it. This is (currently) a + * Windows-specific limitation, and in practice lots of drivers don't suffer + * this limitation, but it is still the way the wgl API is documented to + * work and you should expect crashes if you don't respect it. Store a copy + * of the function pointers that comes and goes with context lifespan. + * - On X11, function pointers returned by this function are valid for any + * context, and can even be looked up before a context is created at all. + * This means that, for at least some common OpenGL implementations, if you + * look up a function that doesn't exist, you'll get a non-NULL result that + * is _NOT_ safe to call. You must always make sure the function is actually + * available for a given GL context before calling it, by checking for the + * existence of the appropriate extension with SDL_GL_ExtensionSupported(), + * or verifying that the version of OpenGL you're using offers the function + * as core functionality. + * - Some OpenGL drivers, on all platforms, *will* return NULL if a function + * isn't supported, but you can't count on this behavior. Check for + * extensions you use, and if you get a NULL anyway, act as if that + * extension wasn't available. This is probably a bug in the driver, but you + * can code defensively for this scenario anyhow. + * - Just because you're on Linux/Unix, don't assume you'll be using X11. + * Next-gen display servers are waiting to replace it, and may or may not + * make the same promises about function pointers. + * - OpenGL function pointers must be declared `APIENTRY` as in the example + * code. This will ensure the proper calling convention is followed on + * platforms where this matters (Win32) thereby avoiding stack corruption. + * + * \param proc the name of an OpenGL function + * \returns a pointer to the named OpenGL function. The returned pointer + * should be cast to the appropriate function signature. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_ExtensionSupported + * \sa SDL_GL_LoadLibrary + * \sa SDL_GL_UnloadLibrary */ extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc); /** - * \brief Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary(). - * - * \sa SDL_GL_LoadLibrary() + * Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary(). + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_LoadLibrary */ extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void); /** - * \brief Return true if an OpenGL extension is supported for the current - * context. + * Check if an OpenGL extension is supported for the current context. + * + * This function operates on the current GL context; you must have created a + * context and it must be current before calling this function. Do not assume + * that all contexts you create will have the same set of extensions + * available, or that recreating an existing context will offer the same + * extensions again. + * + * While it's probably not a massive overhead, this function is not an O(1) + * operation. Check the extensions you care about after creating the GL + * context and save that information somewhere instead of calling the function + * every time you need to know. + * + * \param extension the name of the extension to check + * \returns SDL_TRUE if the extension is supported, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char *extension); /** - * \brief Set an OpenGL window attribute before window creation. + * Reset all previously set OpenGL context attributes to their default values. + * + * \since This function is available since SDL 2.0.2. + * + * \sa SDL_GL_GetAttribute + * \sa SDL_GL_SetAttribute + */ +extern DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void); + +/** + * Set an OpenGL window attribute before window creation. + * + * This function sets the OpenGL attribute `attr` to `value`. The requested + * attributes should be set before creating an OpenGL window. You should use + * SDL_GL_GetAttribute() to check the values after creating the OpenGL + * context, since the values obtained can differ from the requested ones. + * + * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to set + * \param value the desired value for the attribute + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_GetAttribute + * \sa SDL_GL_ResetAttributes */ extern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value); /** - * \brief Get the actual value for an attribute from the current context. + * Get the actual value for an attribute from the current context. + * + * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to get + * \param value a pointer filled in with the current value of `attr` + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_ResetAttributes + * \sa SDL_GL_SetAttribute */ extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value); /** - * \brief Create an OpenGL context for use with an OpenGL window, and make it - * current. - * - * \sa SDL_GL_DeleteContext() + * Create an OpenGL context for an OpenGL window, and make it current. + * + * Windows users new to OpenGL should note that, for historical reasons, GL + * functions added after OpenGL version 1.1 are not available by default. + * Those functions must be loaded at run-time, either with an OpenGL + * extension-handling library or with SDL_GL_GetProcAddress() and its related + * functions. + * + * SDL_GLContext is an alias for `void *`. It's opaque to the application. + * + * \param window the window to associate with the context + * \returns the OpenGL context associated with `window` or NULL on error; call + * SDL_GetError() for more details. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_DeleteContext + * \sa SDL_GL_MakeCurrent */ extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window * window); /** - * \brief Set up an OpenGL context for rendering into an OpenGL window. - * - * \note The context must have been created with a compatible window. + * Set up an OpenGL context for rendering into an OpenGL window. + * + * The context must have been created with a compatible window. + * + * \param window the window to associate with the context + * \param context the OpenGL context to associate with the window + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_CreateContext */ extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext context); /** - * \brief Set the swap interval for the current OpenGL context. - * - * \param interval 0 for immediate updates, 1 for updates synchronized with the - * vertical retrace. If the system supports it, you may - * specify -1 to allow late swaps to happen immediately - * instead of waiting for the next retrace. - * - * \return 0 on success, or -1 if setting the swap interval is not supported. - * - * \sa SDL_GL_GetSwapInterval() + * Get the currently active OpenGL window. + * + * \returns the currently active OpenGL window on success or NULL on failure; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + */ +extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void); + +/** + * Get the currently active OpenGL context. + * + * \returns the currently active OpenGL context or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_MakeCurrent + */ +extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void); + +/** + * Get the size of a window's underlying drawable in pixels. + * + * This returns info useful for calling glViewport(). + * + * This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI + * drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a + * platform with high-DPI support (Apple calls this "Retina"), and not + * disabled by the `SDL_HINT_VIDEO_HIGHDPI_DISABLED` hint. + * + * \param window the window from which the drawable size should be queried + * \param w a pointer to variable for storing the width in pixels, may be NULL + * \param h a pointer to variable for storing the height in pixels, may be + * NULL + * + * \since This function is available since SDL 2.0.1. + * + * \sa SDL_CreateWindow + * \sa SDL_GetWindowSize + */ +extern DECLSPEC void SDLCALL SDL_GL_GetDrawableSize(SDL_Window * window, int *w, + int *h); + +/** + * Set the swap interval for the current OpenGL context. + * + * Some systems allow specifying -1 for the interval, to enable adaptive + * vsync. Adaptive vsync works the same as vsync, but if you've already missed + * the vertical retrace for a given frame, it swaps buffers immediately, which + * might be less jarring for the user during occasional framerate drops. If an + * application requests adaptive vsync and the system does not support it, + * this function will fail and return -1. In such a case, you should probably + * retry the call with 1 for the interval. + * + * Adaptive vsync is implemented for some glX drivers with + * GLX_EXT_swap_control_tear: + * + * https://www.opengl.org/registry/specs/EXT/glx_swap_control_tear.txt + * + * and for some Windows drivers with WGL_EXT_swap_control_tear: + * + * https://www.opengl.org/registry/specs/EXT/wgl_swap_control_tear.txt + * + * Read more on the Khronos wiki: + * https://www.khronos.org/opengl/wiki/Swap_Interval#Adaptive_Vsync + * + * \param interval 0 for immediate updates, 1 for updates synchronized with + * the vertical retrace, -1 for adaptive vsync + * \returns 0 on success or -1 if setting the swap interval is not supported; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_GetSwapInterval */ extern DECLSPEC int SDLCALL SDL_GL_SetSwapInterval(int interval); /** - * \brief Get the swap interval for the current OpenGL context. - * - * \return 0 if there is no vertical retrace synchronization, 1 if the buffer + * Get the swap interval for the current OpenGL context. + * + * If the system can't determine the swap interval, or there isn't a valid + * current context, this function will return 0 as a safe default. + * + * \returns 0 if there is no vertical retrace synchronization, 1 if the buffer * swap is synchronized with the vertical retrace, and -1 if late - * swaps happen immediately instead of waiting for the next retrace. - * If the system can't determine the swap interval, or there isn't a - * valid current context, this will return 0 as a safe default. - * - * \sa SDL_GL_SetSwapInterval() + * swaps happen immediately instead of waiting for the next retrace; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_SetSwapInterval */ extern DECLSPEC int SDLCALL SDL_GL_GetSwapInterval(void); /** - * \brief Swap the OpenGL buffers for a window, if double-buffering is - * supported. + * Update a window with OpenGL rendering. + * + * This is used with double-buffered OpenGL contexts, which are the default. + * + * On macOS, make sure you bind 0 to the draw framebuffer before swapping the + * window, otherwise nothing will happen. If you aren't using + * glBindFramebuffer(), this is the default and you won't have to do anything + * extra. + * + * \param window the window to change + * + * \since This function is available since SDL 2.0.0. */ extern DECLSPEC void SDLCALL SDL_GL_SwapWindow(SDL_Window * window); /** - * \brief Delete an OpenGL context. - * - * \sa SDL_GL_CreateContext() + * Delete an OpenGL context. + * + * \param context the OpenGL context to be deleted + * + * \since This function is available since SDL 2.0.0. + * + * \sa SDL_GL_CreateContext */ extern DECLSPEC void SDLCALL SDL_GL_DeleteContext(SDL_GLContext context); -/*@}*//*OpenGL support functions*/ +/* @} *//* OpenGL support functions */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_video_h */ +#endif /* SDL_video_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/external/SDL2/SDL_vulkan.h b/external/SDL2/SDL_vulkan.h new file mode 100644 index 0000000..ab86a0b --- /dev/null +++ b/external/SDL2/SDL_vulkan.h @@ -0,0 +1,215 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2017, Mark Callow + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_vulkan.h + * + * Header file for functions to creating Vulkan surfaces on SDL windows. + */ + +#ifndef SDL_vulkan_h_ +#define SDL_vulkan_h_ + +#include "SDL_video.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Avoid including vulkan.h, don't define VkInstance if it's already included */ +#ifdef VULKAN_H_ +#define NO_SDL_VULKAN_TYPEDEFS +#endif +#ifndef NO_SDL_VULKAN_TYPEDEFS +#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; + +#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; +#else +#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; +#endif + +VK_DEFINE_HANDLE(VkInstance) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) + +#endif /* !NO_SDL_VULKAN_TYPEDEFS */ + +typedef VkInstance SDL_vulkanInstance; +typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */ + +/** + * \name Vulkan support functions + * + * \note SDL_Vulkan_GetInstanceExtensions & SDL_Vulkan_CreateSurface API + * is compatable with Tizen's implementation of Vulkan in SDL. + */ +/* @{ */ + +/** + * Dynamically load the Vulkan loader library. + * + * This should be called after initializing the video driver, but before + * creating any Vulkan windows. If no Vulkan loader library is loaded, the + * default library will be loaded upon creation of the first Vulkan window. + * + * It is fairly common for Vulkan applications to link with libvulkan instead + * of explicitly loading it at run time. This will work with SDL provided the + * application links to a dynamic library and both it and SDL use the same + * search path. + * + * If you specify a non-NULL `path`, an application should retrieve all of the + * Vulkan functions it uses from the dynamic library using + * SDL_Vulkan_GetVkGetInstanceProcAddr unless you can guarantee `path` points + * to the same vulkan loader library the application linked to. + * + * On Apple devices, if `path` is NULL, SDL will attempt to find the + * `vkGetInstanceProcAddr` address within all the Mach-O images of the current + * process. This is because it is fairly common for Vulkan applications to + * link with libvulkan (and historically MoltenVK was provided as a static + * library). If it is not found, on macOS, SDL will attempt to load + * `vulkan.framework/vulkan`, `libvulkan.1.dylib`, + * `MoltenVK.framework/MoltenVK`, and `libMoltenVK.dylib`, in that order. On + * iOS, SDL will attempt to load `libMoltenVK.dylib`. Applications using a + * dynamic framework or .dylib must ensure it is included in its application + * bundle. + * + * On non-Apple devices, application linking with a static libvulkan is not + * supported. Either do not link to the Vulkan loader or link to a dynamic + * library version. + * + * \param path The platform dependent Vulkan loader library name or NULL + * \returns 0 on success or -1 if the library couldn't be loaded; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 2.0.6. + * + * \sa SDL_Vulkan_GetVkInstanceProcAddr + * \sa SDL_Vulkan_UnloadLibrary + */ +extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path); + +/** + * Get the address of the `vkGetInstanceProcAddr` function. + * + * This should be called after either calling SDL_Vulkan_LoadLibrary() or + * creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag. + * + * \returns the function pointer for `vkGetInstanceProcAddr` or NULL on error. + * + * \since This function is available since SDL 2.0.6. + */ +extern DECLSPEC void *SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void); + +/** + * Unload the Vulkan library previously loaded by SDL_Vulkan_LoadLibrary() + * + * \since This function is available since SDL 2.0.6. + * + * \sa SDL_Vulkan_LoadLibrary + */ +extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); + +/** + * Get the names of the Vulkan instance extensions needed to create a surface + * with SDL_Vulkan_CreateSurface. + * + * If `pNames` is NULL, then the number of required Vulkan instance extensions + * is returned in `pCount`. Otherwise, `pCount` must point to a variable set + * to the number of elements in the `pNames` array, and on return the variable + * is overwritten with the number of names actually written to `pNames`. If + * `pCount` is less than the number of required extensions, at most `pCount` + * structures will be written. If `pCount` is smaller than the number of + * required extensions, SDL_FALSE will be returned instead of SDL_TRUE, to + * indicate that not all the required extensions were returned. + * + * The `window` parameter is currently needed to be valid as of SDL 2.0.8, + * however, this parameter will likely be removed in future releases + * + * \param window A window for which the required Vulkan instance extensions + * should be retrieved (will be deprecated in a future release) + * \param pCount A pointer to an unsigned int corresponding to the number of + * extensions to be returned + * \param pNames NULL or a pointer to an array to be filled with required + * Vulkan instance extensions + * \returns SDL_TRUE on success, SDL_FALSE on error. + * + * \since This function is available since SDL 2.0.6. + * + * \sa SDL_Vulkan_CreateSurface + */ +extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_GetInstanceExtensions(SDL_Window *window, + unsigned int *pCount, + const char **pNames); + +/** + * Create a Vulkan rendering surface for a window. + * + * The `window` must have been created with the `SDL_WINDOW_VULKAN` flag and + * `instance` must have been created with extensions returned by + * SDL_Vulkan_GetInstanceExtensions() enabled. + * + * \param window The window to which to attach the Vulkan surface + * \param instance The Vulkan instance handle + * \param surface A pointer to a VkSurfaceKHR handle to output the newly + * created surface + * \returns SDL_TRUE on success, SDL_FALSE on error. + * + * \since This function is available since SDL 2.0.6. + * + * \sa SDL_Vulkan_GetInstanceExtensions + * \sa SDL_Vulkan_GetDrawableSize + */ +extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window, + VkInstance instance, + VkSurfaceKHR* surface); + +/** + * Get the size of the window's underlying drawable dimensions in pixels. + * + * This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI + * drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a + * platform with high-DPI support (Apple calls this "Retina"), and not + * disabled by the `SDL_HINT_VIDEO_HIGHDPI_DISABLED` hint. + * + * \param window an SDL_Window for which the size is to be queried + * \param w Pointer to the variable to write the width to or NULL + * \param h Pointer to the variable to write the height to or NULL + * + * \since This function is available since SDL 2.0.6. + * + * \sa SDL_GetWindowSize + * \sa SDL_CreateWindow + * \sa SDL_Vulkan_CreateSurface + */ +extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window * window, + int *w, int *h); + +/* @} *//* Vulkan support functions */ + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_vulkan_h_ */ diff --git a/external/SDL2/begin_code.h b/external/SDL2/begin_code.h index 4e613f9..63f064b 100644 --- a/external/SDL2/begin_code.h +++ b/external/SDL2/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -33,27 +33,39 @@ #endif #define _begin_code_h +#ifndef SDL_DEPRECATED +# if (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ +# define SDL_DEPRECATED __attribute__((deprecated)) +# else +# define SDL_DEPRECATED +# endif +#endif + +#ifndef SDL_UNUSED +# ifdef __GNUC__ +# define SDL_UNUSED __attribute__((unused)) +# else +# define SDL_UNUSED +# endif +#endif + /* Some compilers use a special export keyword */ #ifndef DECLSPEC -# if defined(__BEOS__) || defined(__HAIKU__) -# if defined(__GNUC__) -# define DECLSPEC __declspec(dllexport) +# if defined(__WIN32__) || defined(__WINRT__) || defined(__CYGWIN__) +# ifdef DLL_EXPORT +# define DECLSPEC __declspec(dllexport) # else -# define DECLSPEC __declspec(export) +# define DECLSPEC # endif -# elif defined(__WIN32__) -# ifdef __BORLANDC__ +# elif defined(__OS2__) # ifdef BUILD_SDL -# define DECLSPEC +# define DECLSPEC __declspec(dllexport) # else -# define DECLSPEC __declspec(dllimport) +# define DECLSPEC # endif -# else -# define DECLSPEC __declspec(dllexport) -# endif # else # if defined(__GNUC__) && __GNUC__ >= 4 -# define DECLSPEC __attribute__ ((visibility("default"))) +# define DECLSPEC __attribute__ ((visibility("default"))) # else # define DECLSPEC # endif @@ -62,8 +74,13 @@ /* By default SDL uses the C calling convention */ #ifndef SDLCALL -#if defined(__WIN32__) && !defined(__GNUC__) +#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__) #define SDLCALL __cdecl +#elif defined(__OS2__) || defined(__EMX__) +#define SDLCALL _System +# if defined (__GNUC__) && !defined(_System) +# define _System /* for old EMX/GCC compat. */ +# endif #else #define SDLCALL #endif @@ -84,6 +101,9 @@ #ifdef _MSC_VER #pragma warning(disable: 4103) #endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpragma-pack" +#endif #ifdef __BORLANDC__ #pragma nopackwarning #endif @@ -95,48 +115,44 @@ #endif #endif /* Compiler needs structure packing set */ -/* Set up compiler-specific options for inlining functions */ -#ifndef SDL_INLINE_OKAY -#ifdef __GNUC__ -#define SDL_INLINE_OKAY -#else -/* Add any special compiler-specific cases here */ -#if defined(_MSC_VER) || defined(__BORLANDC__) || \ - defined(__DMC__) || defined(__SC__) || \ - defined(__WATCOMC__) || defined(__LCC__) || \ - defined(__DECC) +#ifndef SDL_INLINE +#if defined(__GNUC__) +#define SDL_INLINE __inline__ +#elif defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__DMC__) || defined(__SC__) || \ + defined(__WATCOMC__) || defined(__LCC__) || \ + defined(__DECC) || defined(__CC_ARM) +#define SDL_INLINE __inline #ifndef __inline__ -#define __inline__ __inline +#define __inline__ __inline #endif -#define SDL_INLINE_OKAY #else -#if !defined(__MRC__) && !defined(_SGI_SOURCE) +#define SDL_INLINE inline #ifndef __inline__ #define __inline__ inline #endif -#define SDL_INLINE_OKAY -#endif /* Not a funky compiler */ -#endif /* Visual C++ */ -#endif /* GNU C */ -#endif /* SDL_INLINE_OKAY */ - -/* If inlining isn't supported, remove "__inline__", turning static - inlined functions into static functions (resulting in code bloat - in all files which include the offending header files) -*/ -#ifndef SDL_INLINE_OKAY -#define __inline__ #endif +#endif /* SDL_INLINE not defined */ #ifndef SDL_FORCE_INLINE #if defined(_MSC_VER) #define SDL_FORCE_INLINE __forceinline #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) -#define SDL_FORCE_INLINE __attribute__((always_inline)) static inline +#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__ #else -#define SDL_FORCE_INLINE static __inline__ +#define SDL_FORCE_INLINE static SDL_INLINE #endif +#endif /* SDL_FORCE_INLINE not defined */ + +#ifndef SDL_NORETURN +#if defined(__GNUC__) +#define SDL_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define SDL_NORETURN __declspec(noreturn) +#else +#define SDL_NORETURN #endif +#endif /* SDL_NORETURN not defined */ /* Apparently this is needed by several Windows compilers */ #if !defined(__MACH__) @@ -148,3 +164,24 @@ #endif #endif /* NULL */ #endif /* ! Mac OS X - breaks precompiled headers */ + +#ifndef SDL_FALLTHROUGH +#if (defined(__cplusplus) && __cplusplus >= 201703L) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L) +#define SDL_FALLTHROUGH [[fallthrough]] +#else +#if defined(__has_attribute) +#define _HAS_FALLTHROUGH __has_attribute(__fallthrough__) +#else +#define _HAS_FALLTHROUGH 0 +#endif /* __has_attribute */ +#if _HAS_FALLTHROUGH && \ + ((defined(__GNUC__) && __GNUC__ >= 7) || \ + (defined(__clang_major__) && __clang_major__ >= 10)) +#define SDL_FALLTHROUGH __attribute__((__fallthrough__)) +#else +#define SDL_FALLTHROUGH do {} while (0) /* fallthrough */ +#endif /* _HAS_FALLTHROUGH */ +#undef _HAS_FALLTHROUGH +#endif /* C++17 or C2x */ +#endif /* SDL_FALLTHROUGH not defined */ diff --git a/external/SDL2/close_code.h b/external/SDL2/close_code.h index 4100603..dc73432 100644 --- a/external/SDL2/close_code.h +++ b/external/SDL2/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2013 Sam Lantinga + Copyright (C) 1997-2022 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,15 +21,18 @@ /** * \file close_code.h - * + * * This file reverses the effects of begin_code.h and should be included * after you finish any function and structure declarations in your headers */ +#ifndef _begin_code_h +#error close_code.h included without matching begin_code.h +#endif #undef _begin_code_h /* Reset structure packing at previous byte alignment */ -#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__BORLANDC__) +#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) #ifdef __BORLANDC__ #pragma nopackwarning #endif diff --git a/game_shared/bot/bot_manager.h b/game_shared/bot/bot_manager.h index 26fa1ea..2b45d75 100644 --- a/game_shared/bot/bot_manager.h +++ b/game_shared/bot/bot_manager.h @@ -14,19 +14,12 @@ #include "extdll.h" #include "util.h" +#undef min +#undef max #include #include "GameEvent.h" // Game event enum used by career mode, tutor system, and bots -#ifndef _WIN32 -// DAL undefs max and min -#ifndef max -#define max(a,b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif -#endif - +#include "minmax.h" class CNavArea; diff --git a/game_shared/bot/bot_profile.cpp b/game_shared/bot/bot_profile.cpp index 84e59aa..5b24803 100644 --- a/game_shared/bot/bot_profile.cpp +++ b/game_shared/bot/bot_profile.cpp @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // @@ -364,7 +364,8 @@ void BotProfileManager::Init( const char *filename, unsigned int *checksum ) // found attribute name - keep it char attributeName[64]; - strcpy( attributeName, token ); + strncpy( attributeName, token, sizeof( attributeName ) - 1 ); + attributeName[ sizeof( attributeName ) - 1 ] = '\0'; // eat '=' dataFile = SharedParse( dataFile ); diff --git a/game_shared/bot/nav_area.h b/game_shared/bot/nav_area.h index 4b79518..158b8c9 100644 --- a/game_shared/bot/nav_area.h +++ b/game_shared/bot/nav_area.h @@ -5,6 +5,8 @@ #ifndef _NAV_AREA_H_ #define _NAV_AREA_H_ +#undef min +#undef max #include #include "nav.h" #include "steam_util.h" diff --git a/game_shared/bot/nav_file.cpp b/game_shared/bot/nav_file.cpp index b18bc25..67971d4 100644 --- a/game_shared/bot/nav_file.cpp +++ b/game_shared/bot/nav_file.cpp @@ -139,7 +139,7 @@ public: } /// load the directory - void Load( SteamFile *file ) + bool Load( SteamFile *file ) { // read number of entries EntryType count; @@ -153,10 +153,19 @@ public: for( int i=0; iRead( &len, sizeof(unsigned short) ); + if ( len >= sizeof( placeName ) ) + { + assert( false && "PlaceDirectory::Load: Invalid placeName size" ); + return false; + } + file->Read( placeName, len ); + placeName[ sizeof( placeName ) - 1 ] = '\0'; AddPlace( TheBotPhrases->NameToID( placeName ) ); } + + return true; } private: @@ -1013,7 +1022,11 @@ NavErrorType LoadNavigationMap( void ) // load Place directory if (version >= 5) { - placeDirectory.Load( &navFile ); + if ( !placeDirectory.Load( &navFile ) ) + { + CONSOLE_ECHO( "ERROR: Invalid navigation file '%s'.\n", filename ); + return NAV_INVALID_FILE; + } } // get number of areas diff --git a/game_shared/shared_util.cpp b/game_shared/shared_util.cpp index eb810d0..6226e25 100644 --- a/game_shared/shared_util.cpp +++ b/game_shared/shared_util.cpp @@ -203,7 +203,7 @@ skipwhite: if (c == s_shared_quote) { data++; - while (1) + while (len < sizeof( s_shared_token ) - 1) { c = *data++; if (c==s_shared_quote || !c) @@ -217,24 +217,31 @@ skipwhite: } // parse single characters - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c == ',' ) + if (len < sizeof( s_shared_token ) - 1) { - s_shared_token[len] = c; - len++; - s_shared_token[len] = 0; - return data+1; + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c == ',' ) + { + s_shared_token[len] = c; + len++; + s_shared_token[len] = 0; + return data+1; + } } // parse a regular word - do + while (len < sizeof( s_shared_token ) - 1) { s_shared_token[len] = c; data++; len++; c = *data; - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c == ',' ) + + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c == ',' ) break; - } while (c>32); + + if (c <= 32) + break; + } s_shared_token[len] = 0; return data; diff --git a/lib/public/SDL2.lib b/lib/public/SDL2.lib index cc89dba06d8c2b222473d6f6e38f7754a30c9529..3bdbc5e79acfaab36412b77331cc6d58af0a27c3 100644 GIT binary patch literal 178186 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 asYtA$aqk;s)smOzX2PmH&QR3R|NjAG1e03; literal 108368 zcmeIbeVpAzbw54>h=>S?h&+iA5do2hWD_DHl1CCq!m^tOL?pS{y~$qK-Mid-HwlP{ zh>D1ah=_=Yh_tnqQfn!tmQrdhMN1J;5fKp)5fKp)@uB#8pLskp^Z5*W_p|%`bI#0ro-QuaNJ&UenNnLJ~D@)wJ*`A&Fjgl%~CR5t8U-H)z`XTs(t5 zva6;~Y$YVoC%>-g$|r;*y68qtAKhL^MJ@aVT{71YFfIXI@wBE-0iS4xJ2k!H9wCW# z{j#Q4?kyzIn)5VmLi&mJT(4>Tb|H!OI7ic_9>_s^Jf-Q_XN4qs-*cKaA}*p9;wRd5 zp{9YWge2PVB~62fk7&cung(~qGpKcprdO;(IzeY3-9)=QuIW_#C8~8at-C@L+U&d=hw13h}e&H2tb21kp2J()8oUg&=zP9!2u}L7}LQ zv=G&{)wJ#);DgrRrbs+=l~DAPqlF;)*`AsnxmXC0JOX)Ev?u<8PC{CVKD3LbHAolH z-iBUzA?k&=vR#`tGQqZSa@qens-7 zj|w93=lc}Nt(OQzFGcx+#Pd&U`tu;bndtCa6p0^iL3`aIN$y3p;LE?#n6v@>~5D(~sC~Klolp#nwe!ih6@fY-q)r#b&PQv&F`WV_CQQyOw z-mqRsqJvOBMEgIdsc#eHpkt2Hbl|f>5*={8rUQ4wGw6+|6QTo-)U^N32oHJ#%8BT( zO`6^WJfcId)b#qRg(TYld`*YkE~KJf`~|%cxI~9-uj$Z35DxUFQB4Q$Bc!5>@t5d% zO$T0tbb$^U*7SOmE77G_X!_Wl$Uo>(#6|S+tu*y7Lw^CyLwi$%bj}0Kf85Y^_)D}! z(@{tx(c4bbbkwbQ2EFxQO>cQnNTRphr|FnmP>!It2u%yVCM3~YkWQkvqOB4gy|W>d z_0dG5dG-}O@CMdJkWDUgQ9!!7xe5lhBo0Z>iQ*phESg` z0d0@|Of-hFBiar+M7yC461{4Prro}aXV7+!86sWKC+^VnF_at8#m8v6;v&44L4D96 z+8$*`^iupL+65SjP`|ruCB%cV8#1qdelJ7?QCc5BSO=qme zdlP-=!G{&eot_kmR^5Ys4(eT@NZfm>Ad+J(MdFwD2qJmHd4?XtU(n0v7(!ZKeigAf8xLE`6MQ6%Rgy+m(6Sdq9F zbxri-QHta{QGP_HY^UkuyM-h=WlYmM<_bx43fe8vJFe06VWget!W%VxXbax6pbzh^ z=|d0U8T8?EHC?y_dZ4#oX6SkR1)X%Ori)R=L?69Z)0HzYF9ThK@+A8Bs3FKd4*LAf zhWhXq^qx~ReR3V)0N;6edGZ{Tksdu z*<|QZ`~{6%plPcIg(T{1qiK&FFfRqQkw>E4575-U6wjdDuhcYr1LjR2d5NYKU&8wx z^nR2J(Fwb1I`$&WZ$aOZN1L8yakKIqxd$)re^giH& z#E-Yv^s@^v|3q1xewU`xE*FyM^dUn6e?g}mrs>>kge2PQi<)*qxhg^(?1Z%a6zL`U z$xVvnp7-KA0kqfAnl|q)B+&(PHJy4c-v8%fjKKH~k~^Xfh+ch?rfq;rwBrm-+n$Pf z3g|@$N3;XphYTEB4A&JhqQqva1Nwg2-MDKc1)9Zjuv>9be^t!V(?TdOKdhLyx&Uso$qLVjh z>irtVThNI!H4U}!eF%EpW18MSAMFnG>aS~>f%+jj>kv&d?#DCe&8Tyb_&M4W(PJ2| ziJm@R)34E{h<>}brl)Qbg6KEvH2t~+OZ_ZT|z63jC}=k{nC@56T@Xb#GX=*>rJI%j8;1JOB}&i*FmrJ#46WoTRc1+Q~XtBx2NBV%ie1f<(v+f<)7JiM?uJX~w7tdEQh*E;n!4^*aMLx(}* zkg=3PEo;^WLw*2QD5h}7);lZ4M^-k+2Zk2bH#G*rbQVcXC>DgL4Gt%a?|royU-#3mf)E*;&_Yb zvc4tmj3J*i`_Ue?-h$?Ev$ecA$P->9HR;KOLh=)7h&69`Y^YX><)tB(=leF~vAi_I znm>%{1XeIA`HV4fh{gm(a7;|$mNf@XFDUSUO?sCv$EFOSnu?YkBv23 zoqA9`B?=T48RXKaQbQ5xyC$dMxPBt?X@h84b7KR2t-o0p7-he2%RVFIBKgQ)tEyn?iOiPuIXCE8v>+6b#ty0BH-tU3ca&I<}x3mw^eV~M+=I>2}pM#W@W8r(fc5lkoK|5*3NH?4i*e%vBYSv8eLzi zAIT`hf>s^Vz5eEg&gNRHuFEWZ{gr9>&;^Opft-MJSB(t<$+3K$Mgr2+=|E4)j%Tsl zhjeW}t!O3+^{IImt80nZw#_fq_7c+8g-~9mUgEV)`7CZVNBYNG8)^eVnu1~tbSMVX zetfjPj1!SZT!ZG)+&ph|uqd1cEKs5FOGg`c6Rz(+v)!qW@WO}$RyS7Bz3s&Dl2{@E z#j>W>rnq@Tjzw|`!iD;oBp6p$WB%A^22)MWHClc6t|(CR>_`vaBkRKsqlR!Di4~eK zz4)}+&};=|1#QnJy}mlVhUc~0^;RcJZXzOm^a7{6q&7M@9HypFY|`Vx>4+}&GlM( z;+IBf`J{=mLB-A+A8a&BKTATX3B{Nkfy&xP=Dsl&jJH~NodhCZ&b46_=7G%RgZE_^&dPa6%L}rml4m8P-CG-P*IA-@`K7WjM6s?e zXR7~_XcG~|>XZ|y#q7B}V$LNkmD+gtWK7ao z-q@lzJRZ+;vBV>^3Zt2%bHZ4CG>L{W10B7}!vUS96_Nge<|tMNbXVcZA)hqok2i(~ z75swLE4gYUAYBZdOE7<4)94KKwi?Y=qZ3Rp3&kuPkKO3HzD@CRIl75vsoc;EpB{sr zq~`sGOIny3Ay%y16{W2}=);r;@Dihqba|fdp@=?^7;QE98~sN38G#Uq)P!1IZ?|h3 z>#KQrK;5%_T22`6jE#2|kB<(-uST7sSZ+e1oMK6kmjby78KudN85=Q|SdWevi5=I3 zURYm09xUb|m4;_D;`Jja_;n*Ztf{qv35#Qy@QYflaM2A4hG#SupxM%rK$KL^HhQMG zBQ?j>TD8IX%X`=MtqHX}m$YcLIMw1@(n9lD(7S3ub3Ew>p3U@X14DJ1hQ|vVCYn%8 z;g;0eeG6CiFW@QlJfkshxYJl&ABc1u*Jv$Yeo~~NI7T{a;fio!7AS^iH2V7&Md204 zOJ}BHu)KU$DhJEUdk#+(h{rSvAbJc28vlaf#@PC1t))IQd0eTC;-o?^3z5o9DoR73 zydoKe&>tTCL$$H`p#J>e=_-;^sHN?)5V3@`kvko=3dG}&C8Uj<@yO#f%tEmVm-JF7 zvtFu3_C$wsO==Szq?5&yh?%UnULRYu3De2oox-_@$h(i zCQj{jfC9O5JMn^@qvN2L`jt8&JRHoxK@H`v6HcdK>R0C8T_+sybA55`? zVw^WPsI=GAIs-#I)<{6Q3+uzhx{-i%HM&v{3N+-CW?y|{1E1NgR5zBWcwG(f#QF-* zWzdT)KNTNWVoZw3l`z*~OwyrNSX`E|gtV0^P3?oXC+DghnAJZH8?LU{r?}wkq9Mi7 zu6OFAn|K_SL(+|j)N)9QPrN0yF}yni0L~>XtrCANajw^*scX1pp!F=@Yc9o>SFlK_ z6%Cv8mN)S|w6v}HJcE&dbdPIdg{CoZdXai6^QoY8(IS)8;V?esp@t8Ql3KK3gI?A3 zvn?Ht%Zfr^MdVEEy{3RZpi}YT)qYwU#<0B}BAK@(oSwR5X@S?(St#7^(P0t=A9h83 zvzDf5Vj{1v7edQ|gi;@>Z+x^Y2orhz{!VkOEC84J5N7ePEKnr&;b-r$IT#7 z@L@4>99s+bg>`v5L7+Qtywe=Oa2^ijE(90*aBAHktsBGkdaFjqX!Rl0bONtSC5Ugb zRM!c-ZXcEohwGWPl_2AcgqFn^l<=|;TINI0h>_}QZm310 zh8n7h)tT6bQ)?EfzG0JIV*m>QYnxFjIM-?Mc$9*ECu-dRT4hNz)*7~pV=Z=aqG3vh zw|vsXXk!P^_)Wt2q-h`NZL+ut1A^!!P%IBZrX!mRWJQtwl3F+=WcpeZ>CdkXhdW{{ zfRV)^#yg$nXpnav#!7i83=H$OGzx<_QKXN=@(QyEP*;*jn^Ib$u0^rFN@ZCHBaFh# z>vZV5G_Vn1$?{?zZs}+nRyqUqr3;I|xRi&A=N}eE^SNfyhpZ~=MV6)CI7R8O5*{<3 z!TEvS#>J&P6zWGWjY|gz>icDE+j1EquZwGq0m~2^P3d6)@HPhIVH%^#!_TC8v{EbnD z&vg`Xy>op1OtqA`xH*vQL`JeGM6xD<615?W%!I(&Uy-tBlO8@)Ji})oVEYuPL399b z{>U^^ry-P@P_T_t>Lf%ugNCCl=R#=|Dru-b2y3ODNhp~xUhMN!ppJ9~vE$i?^o8Ve z?X^cRWorg&^_D}38(Q^X!mgi5g1wI@oaK-d=1;NMu}E(BH_@#|!Wm{PA#J2vebf{+ zJ}%(8#VrZnn_-*ltHXE%Hqa`XqA*1Y1}6{|EL<1JDWqOyR|b_ZHE4$$O$9<9Mw^0#UTdEod|;JnP-vyRvKguH z5vNRpLeHZf)(f-WPPpb9@<|irWAs$33(}X$CoF$jEE*l4RUK>g?6VOG5^R`8#=={1v*uZi z`2`x9XEl~Bn$we}gLqbBeu0MOk;WPrF4V)UI+l~inN=D-x9Ty@E@QHI!VH^ui0O3V zESq=&ojB7b9-C_uBrF)lBrMZf8qp~U-L4eZYb_7$Zgo(_^g38iXm<(~y@a#}>WyGY zOg}40v%P`WBo2e&nI!GTXduzgB#DlRsYl{B+JlXap^>g*X?c4rGJ0;b4U6QRCXU{O ztNf0o<-;^o@#J=JluEHkPL}RiVyH*^xB;8=M(QK&dN7n(j*$+8rwt%g93vfRZVINO z5NnnV9lir7G;v7U?zC`5if6!bNV<8T9Z4<6N~464*riN8gwt5Zve;300(arZI~(RY zh95x#wu>jkQNf61ta$PKz5de(_dYjs#W7zBH1l^r6DXvCTKKhv?Fv|~%&M-_0kSJcRcvKuC zMgNVYisPi?shC(!9kpi6 z3Y0elvY~fug{{u!I+o9gwuyHF(#1@M?7!6)PVmtf2}qY_(=M=&HDIea)yX(~_7y1W zuXQdf3PE22Jd1HCEvJyKNNqv+bR{B%r1M*pvPhC@r{9XEkW6e=P9cqH2NZ&O4cG=@ zupj;eLNj9uX1P{tehaQ2@Ma07R;0)TR+r4o3XJ|pI}maGpuCNu9;@wwRhSjdrFh8o z#0l$9i%zw2uGK2GLaz;aK50^8Es8PZs~o8IwtT!3T7KyS8aC;f!cP=KzE0)9>4_Tk zGZvdUD3z#%e47&&l(kRQO<9aO!Tt4-+SpJt^gfb^Sbhovm^?8Vg}`G_|2{FX#AqWk z6o9u4XgV&7Gg8r^jC^%%cs!WYBM!qe8okZ1T|+^$NWO9i6+9Sja(f(M+f3<0~VU8PN%BCxyK(AndQ)~L20lWe=tLUgofso=?4M-vK^l~m~_0{RCjmDs0f*P<% z4?D<-lINNHzz}G4W3XO+W-yeRP>jh_iUJEHMjOl8bY?IR1*Kf15T~!v9z#{f&Cn&^ ziA}hLno&?ufh5$PkCPvRF@({#GM_FZpyl*943ZT}L!5X89_7Z=^_zis_4etoa|=X4 zxfLlGBvYj2VT%-OSXz>7he-->)%IwlV8ZHM2?LuLiy>1*3KSMyA`r!8R4gw-jYGzu zS{{UCtI$z<)@cglLCA3EbWp?&^k`aDqH9H={%~z$+^Te17HbJ7qu1yx(ngWi5H;L)q)@uv93#m*LA`1!oq>El5}`s5Wi;!ZP!$& zi!ez4d^jkpw?gYUmk2Kma0*U;X$&n0beA_q8zbW*r9lFD7_zn{ACk*ep0IPM(-Bk% zNDoxMOm05Uy~C&83z}DU@q&$F^$ggQ~Lwq!xq-k*<$i z2}l=b%?9w1IZ9_9TZ=|(>xaW;UM#1OTA79BsVWds7`y-op(Id|ROLs1>MU!lZ`E4i zBruW~ZRE4J)f~XArWMzU-XY{d6GngJ6k|j(6JpU89M~cE8--T!aCuXtV8Wt0VVTux ztj8x5FE@k=MLtJm`p7I38GSvO#n&gk(1LFX07NnqVtMU!GDn~pS(Kna;?v*1xi+Tu z7B_`o(mD&F)aN4PvmsbjOenQj07^#zf?)!qi+Mf{N)_ijlBp23^Q>7OpKf-2#fnHD zwk$2>p>F9Y&UW*1iY27Iv`rpzlz1wxI`9CM*UfIy&hwYNM4P_WeIqR}!6 zfz4~(_po59EYD2S=w z9X)`hkRd>rMLlq&&A(eKO)6epOE6~ zpOoT>E2X&cA}O~2s1z;G+)EG!^z;=7|0yZ%+(C+aULnPoca>uAS4wf-8Y!;dB*pqY zrMP`uigWgmq6g1U;qSA@O7YzLptlkFEh!cv%vA$Yd}#yp2BkO}e|N^;V<20HIPW|| zipO^Wohn7ACdC!&q<92>`_@Zw2*Rygi!^{vu1oPG!aeshAzHr@;!DrqR*N4CanHj- z44#j8Am0|@4np|b5cVo~V?O#PLhK3siyslC*r~v{JptfiW$&d0T1N6-6zE5P2hp9 zeX$g$LifUDQj9K_V(d66cE|4|1#RHHXjOPa-U%Wz!%kcYl@E1aF z=0cQPLyG;Sx+q25HA{-#!=)I)-^UJ4_m^T5o{u{Q?dd?Y zwF9Ks4S&D#Mk$WO@0}t4CUiF;FAu*-iYpJ5;_BBUUhr=}1bGD=2i@%IU>Y=pw{544fW>x#Ci^9pE2=zgvA=ie;#m{pTT0(Bt!^*bcM>)O(Z^r@akr5q}SU zE7JKEv;#cff;0;J{@Mb>iN9Atw)4?QH|QMDN#NiAJ0WiS1KPmv(I)>W#6`aqV&hd%T)>i@cJ zP(G-u>)(xbc!3nF&p`P?{^U;R|ETj7y=W8nqW=N&o?l|TIRRLpIWI@Np!3j1ohZ>tC8P>-wrwAI_gOwj=@;9-6?2?C!@XN@7#Bw zZ1MLR{C(`h7@ICc9efCF6u%$B-*fSI33!(wj^{zQo`g1nJl^|Jv^|VvD=tEvqb~0S z-TZmqf8&W4(;tSPYb@=mONigIh_l4Sw&i2Qb?xzunQ#@b^mmy_a#&DGV zMaP2Phi8l<*P<+M{*e#|VC>uX18B!T6yh?_!bgSJ@duD&9C`?Uw-BLT&srqKj-UtL zi!wvF8=$uz;@b|-`y$TmF%DdS@$;_JrMUbwj1~ARK!@S?HRnq4#l4W$osb96L+I}} zVZ6O}PmJ;4@4gxJh&FWYsYoB%#HBl;FT5II(Z*)r_o>@L_9F0hz6vM4&?{Tv+;L7gt-x6 zo<2v44JV^-qTS9s5%0Dk)E(sW-;ehm(lRsy?EvxIkH0s(8Dl5f<~@%IaX!5FU;Aqz z_C`Ow?J4w+-w4rz=ZEm#AOldwGGPhIpk#r;61WPil1*S z#OK9d$bIFW@=bD;SS?NxYsA~d>7pT;;+WC`ZM)^8NAyaz}ZQ z+)Z90&y(+y3&kho$HiO4PV#86NPJE{Esqtyk=Kc9d&@)Qd*yF&XVLfNgYvubK6$TvKz>`^FTW>$Ab%*265o-( z5Wg3H5YLFG#m~g=#B<^|;^*R7@tAmA{8Bt2ek-07Pl;cPesQW;E8Zd2i4TbPi?eW( z&zEIOo+AEEeo?+$-YEY@{;m9y{G_;6w8S>@&thx&NAV}|zhZm&Qu$7CvbaIMN^B># z7k@4PQeG`TD_m+V!8M$`AvDN{CoKi@}K0*^1tQ($bXbylm9MnlDEm*<(=}M<&Wfl zi`&FMi+>Y;FaAz^Roo)}QQR!PA#M`i6kir!6aOUc5dS6a6#pr175^@77hf0uD*i+K zi?~o+ATAYGiO+~P$PbARiVus6#7D%%;-lgb`3t#JED;CDH_Bg$pUS)CW#Y&3N8-og z0db$WU;IEkEPf(>DjpHv7e5sLARZLo7WazpitmZ#HYpX@-M|_#plFcVwpHjyiFb~-ztxmUzdl=S#q{KOwN=&@=&>rxL#Z@ z4-<355n{fWDdvg8#VpYy7Kqv64dRXBK=EcVR~#b_5(kL=#ED|1_%Hb)alY7Ad|F;1 zuauvXpOk&#Ok5CihTK_xN_VlTO$e5E`@94uZh#^q+&mQ6V(e-y-M81#)MxgBX<~ z^2PEP`Es#~m?vK$b`{&ozZL%@?iP26Z;6F+ksOex$d`$e<%{Gpd7M06E|oiCmbIOH zrMN-tCg#gwxf2G+b@C*6s$41i<%x2+TqA38t$e#&CF}Auxj_!ejj|zE%VXtYIVj&L z-y!?tdf6*akSiqK$^X~W|F5V2Ur+!4eNW$7?*d|dS{({Cp1Nq6Al!&g&d(@@Go@4k z=)4jg!B7w0ZE^6ZJQRBlnbq(B#(svgXvNzpk-uNR`l1|?dS}%IzDUbX3B_LGVlSa; z|Jb-&rPTW8$bV{)0ak3h<;`KrY_P}*kE4Zlc`5-DHc(UA$|y>ifMOwC9YN%5vgKmW ziAG|UG%=GsA7!7qe1@z)JP%eq*0hN+hq$Lg#!o!!GnsOnp5}`dna9a;%Bva{t*N=~ zI3_iQES_T*@?uWl<~iS6&&hf-Voz+hvTo1M=$7nvrJHP6 z3@(hcU|*`>HVYI)(Y|8fRRynujGqlPKI(eMsyuVX5;vJps>{u|`%!rg0+U$zGb$CS zo^2e{6e@M?v!OT^=Bg;kf%f6>f+=|cClviE7ijI796OzIw-K2-G9o~DA3tGcylr60 zM=)b7m6p&8`7===P?z>{277OUznMQ}$DHb~6PyQ>69yvu$ogAZC zrQVW@4g)afzBa-F!!s+QtH;#o56dXHh#(XhBecNW%WQlHrieb2dzB*(80{0|JELhL zjw}L;;0%w|eBc`wFscXZ!Q7Rrce)M*W;T;VWcX=BMvz97Ga|QO z+Q!~K`O8FIm9f_Dc<}A7uLUyUipDiPU*)^pMp+BIwI#~PuyohqFQiBm6u1t=%u-!M zRKtlSEM9)r-$am*0<*RxY+!*AgifqBTq4SCcfEyZ5S6zXad8AQU&m$EvW~}%h_s7S zHhI$w^BrM5*AliC7{9dR?ixogLj0lES}$VNq@(fO#5~uX$6p@`eKPhc43@?)gRBYd zxa5gdxvcZC_^F9jre~`3a5fgol=~Xpg1vxj5q-3Yv)ja5@(X*D^|2X;waQ~`!YwN7 zVh_bM2lD=WeMI;;&`yCF%lg|5S!s8r(8X>-GAk+4_A5~Ii{0g> zg~nTpw{HE;cSv0fw2EM_k)f2+b8=<46@+IlN!6a=v>MhshqC8@!o_VJ0Cq7Pza|AvY$M>x7s7u!SgG*MnvgUruDAfyAF^Gdw?o zM9}DV9{UW7Iip>6J@xuEPh=rH3eoLChi)Y&~4ToARTite#d?{VM zP??f{4z$>HEQHNwPJw$iCG*#GsK@Ajl;~m;_5Kc8rr%efU(q11T?Sz(*Z2q`gwS6V z_ebQV%gOVQdgRAi6a%MRLvK={UnuY4sZV*8B5zeTThCkPKVl=IPc40Iu#VV1hZh0Ujj{0+u$E^UhX3|c?!|cg?!MVX)xTDK zaN-4ub}gDmX?cMn1`CV`{_=01BS=)o<57U;FYorM!9~S7Ra8l;bp~h{4@%G=NzlM6 zLQC#a*9nQPKh?}OMy#S$w}OL9G^4=iR`{}ruOXx7P*ImsaB>?D@mcZk+_&EsgQ_}1 zY_BS!#3T1E>F$D7BM4n`K(kpK3yGW?W!cyy{J1xpYwrCA=x@GYbtz+1j^<;94;1kej0n> zs)G*@XThi|PdTPs+~m{uS%f#EY?2VePZMGU;i?5iq*g7$7cAIjIlG>I{6c0w)? z_*DiMMY3M%B=JE9Cy15~Jl~yibF6~HsmbDjQ%)8SoFrT#aBOooTaZP+Y~a+`0zvG^ zb>atM6bO#M=n^)qkUNZ13ekBb%}Wjvh3*WDIRKkcM&2p)wiTbXYI6ZLlVA)!mC)=U zX0kH~W~*AqG(Vj$J=ZQ^>CA`0)z$5RfW4@khZ-C4nD!aOXM53U6ZPolB{XERZ)o@E zoWD>Rt8tZWbeFi`4ekRst`+SR!#oBa8~t=dNh9BpenMiTfhR{hC2`&jaV8rFw*Ljs5hC*zVOI@k9T+ z^SlWd)3eONtLkZaAV{&&c1B@wG^W5hL= zOmi;0l$bYB5!b$sm@M?@6$-3bS;(dFotHpjViu?~L$ic$KUWfgd#RO4(q^L1KdKp< zopZCm#yYLgrI?wa$J*va9kaP%TDgqY3WG9I3D6&EwCxv%WTsY$XowrECDO!fEzt;! z*J7!gSCk0UqUU&PL*(jLm$sfdrMa=wvN%r74@}#NRpR1{%-nn+W9-Hm7=oK;YLmBw zoz$t>cPgqFBPy&JBP%F8BS}jDQ~QkfhXUg`pZLf`jtSyR#raygSF_6yyrL`*GnYV- z8PG94GovfwhLK>FllDL|jY~T%aSMiaVuvF;aS8?nVk?6?pQ_mGE|AzkqR2BuWP%rj zTl7NSF0f3)Oyq*F5M}*wgjRGx(7-@1kOXFWfdn5~WhsFu1I7*af*2$7y+}69jR=`6 zFstLHd}TUjYp6_I+_XchF3<7!s!;tOF3==lnACF`&o{} zg}`JdR*0@QLKnn4H!({LLK#47oLD5&E1*S^r1iN~+(0{6%MB!YMK@p>W5t4~jRZ?F zB{z%}hf!5obeWa2E{N}ON4fb$PwLqS-( z=K>c(tpagq2pLDs48#h;>UQRgBICfU8ODK`6{Ite41zNSOj4|wWT@g7=L;&;n@om* zyy0ZPS6j3(2OG5^D_!$1mlsvEt&3o5Ad13n9+(Y+LMhc{fzK%&z1>A92pN7lp>5fT zdtqeO^fHP_v(YM*0cIey-HzU@=s8jGacMz~S#gnweZv)uG-hV&_b0+c>CZ2=OHm~D zdliAye4>;@ZKP#U8*y3G&V(~WRP2I6D0G?3jXJ|>s8$`bF#;_JNv*8J|0(8Y)*!SXVC)7F9YJH2#1`!G6vP+o z^%Th2HezAf`W>Nyz_A}Pm)L^uIVUT3$7+p9J(9KsNj@Jm+kB5(+rc=L<`?=f)ZvjL zqhro_#4#lEP8}|8|At$4W~XsH^p@NbI!!iVoUth{`&i}-QR8^yiLVYwTxxzr-v*(E zF-Ik1T8k9W#O11t>^^0LzAr_1tj+7z+o_J zUJ-JwX)xzH1K|Q@y4yv&eaRjGF$?A*#4cFihcz9qR6KekVxESL#*{eVCEIuij(!u{ z@&;ib_XbCSB>w0@WX{kyP&C}YK_`?GqvIeDy$iYNaV*Rx8i7j^joG_4Mh@cBCdr)T z43i6(_|l3zbz384uk1{fISV%_zrf|lr7qnYl@xiOM2n0 zyD;_Q2G<;BW20TTvlkd&^8m`ink)}^d(o>c+7LTYZjPNv=GZac8eo@8f`;u^n2dpT zQGDsu&_0+p{45G(Ea762-3d(-Xe9*+#Gs4;)EjZfkwUHpsWehZyoq%j%$aq^0;=rP zT0-XBz9u50%kI|ARad`4^ZPx z2`Hz==0S*}-2#L%+xIG^K}R8(U*Rs;<%dFFZb4ef?P_x25@n#FQo#G0lco#G5M|a} zy|fI~1TI<_^?{4CY=WlOyV6`Ucbma@3x_4fhH9vXD3`faTqGy6ic8YSq&=u}{ekH( z`6&`I^Y#L9ysipF9Vy%NiL#^R+~B<+-ogb^7kRuu>IB*Zz97DmB~ll#WQo+ti8=aRsn-V3~0J>#{`Ec^mv zCiY&LOfCKK(2!s7)u$~p*)}9^Ra%&Q`Du2+x1SaieEmhn_$*ba<$aKVRGdsln0Y>r zH!{-qBDLcYuVg7^JXdyh`aDUF>5TV%)Fexd`w9&Cc@P|+4-G?^Q9sjbH9B>D&@f?! z6I^EIA8E$ZV`lOnX@(PIWt8tV^dW%oIapxScX@M#@D^};IKXS@BLeIhvtoTvfb)X) zq&_s@#ro&~d)5aC7z0LcydpOmvwE*#jub=;d$1s8H`Vcim@e6g%j^^uQeoKFLr`QQ?52jy?pT^Z|&7 zMW;JLma_MEOY?|H9f=5Z{K1Hb9aa&-79>?2l?cK?FG_?uHWBEk!xJ%QI0-gh#EN<9 zP=$}n9j)LjIN}Hm4a_kMuVW8ea8A_jgM$}dj~&18Om_$)Vuck%TBxA+(CG_(_G0Cd zRV$8PyKvshd4iaS3=R(;Iz#_EeAb-VhaYx$&&;`oVg4Lu{`SnBX@0HSewo}_biVP< z6LB#CJj|k^Xw9j;&PdxC!ae=@f;nW6&pF{bH?SmK9O!xYjev0eo%+z8{a^u6H@ zrt9|6Gp87bN^L8L!_L4tDEnigEzxz}C`Wq%Y3l&VE>Tzn(S5FLqmQt51J*VH77lbc z82e+wIqE4cyWN5EB8OrR`c=TO!(NmdD!FYF96C^Fb25pNn_ZlzJ%IJ%5Q{#Vs~}~1 z({>?}J^1LdWq(Y#rZOe?k`POOWLL>ord4e3u-y4fn-zyR;XGwy1LJVrTKB7M4zT-?BGcY?bcp`2>+~S)6d>sXw9|vM zvqy4=awm^8`|#q?;x(wRm#0W(KX>wYxi|1G4lg)7?7-}g3HPr|%XkIHGUt(P{F4}S zOIkg>>v!cyYTsw_IJ50%R`ed(2RN^caqRk=gR?&-Tz;7`cQ=LxqkD7bheen~31-G9 zx}S_bPuAk}En%4rO9y6uOgLX}E^hNQZ{Iz_vWvJDqx+oAE@_3Y1KJ+NXy!m`1UzfQt?F|vG_J1`!SOHDKR4=lps9y}bZ{W0NM%*<#HDnhL~u9f7H)|B38@j^!AN=7wW|2&vs z;cUy~F*0wxH+c+fuo!nJlSe8U!)R6HkO(Py!FK(Xn438t8ewVkH*D2RI%m1}`C$=S z!Rx2%-1U@Q~1B+8-0mVeSn#+v5$;eNDzd)k3%iI$^BL_%X*}Depg%$H;sO9N{p?fKZZNY>cal~wmGq9?OX_vRRaTg>nZ{H8fj`(vUtn41|M%P?`k!aG2-AYHeY-0WgW zh{nCUO&+i09Z4$_OGCWChnoZJx{c=MqQ@~rI;UxGiJcy_;~5%vY&UtdTw7Vj&|q#o z6>TL`cgsVxsj9oo%zgz&+*}*0JhLx(-_Xv}2@ETA6Ih|{GI+fK9@&RiZ<(`8-VC&w zbfUv6b7xo~pCz-^eSzCojH?gsJ4pLu!Xs!Vr~So<%p-tB>wXS9r{rtq0OWLKF|HoO zwI@dhY=2BRznQnxs&ZU%Vql@%kBMT=DZxAhd0m~wWS$Bpk6tnoy%FeZO3}FsO9$Qc z`(#eZT>DMHKIw(9jSq;)qvzHz-(HTcU2Qs8`(whjT`~?IhCHAA0;p3`-<$Ks5se3y3YaCWiM}=l9cFrvdwLM-9MSs`t=NWgd*>U95slm3$>%cnO|>z> z)b4+$2W==utDLvlnfYpip(SpLT?XxsiH>=>HMP?s#OC;D$GyhfkEuX9og-Oi$~G%q zBjr|xh9e~J6~MuDJu91?c~^}Dc!|$v2Wo#zMQM(5OzTG40(4)RncOuwQtFv{S}?~_ zOn%ONS}@N@F}W|)Nn_@AQ(7S=x#XTSPOgQv8BT$h@5y79%r9t7qr)+^Z&%|u+`)C- z3v=&<@f1(_lARv3O(|N%_iRteT!MD@HZwHspJaM+wT0s_pC=X2GP@FIGBo8!#lhGg z6CNo`R%FN?;4Fq>yuw$ksodQ5T`3xz25BGkHdoz$IrNmwZOPvB>=3bP-ZDM<-60b5 zl|T8M<=*4x6yR0fLoa#LsWW#B&w1%_S+hST+$KxbG{{cs+yH634S$sb;}urRayAw3 zjj^I4>^5Jy)_)$uB1g>rBZOtH>rp?4_`V`Ub3ua5S@-=dhj@O7$mS)L@|gK5cz=j! zeYEL|99$;tkBPR=Tpm9VA_jLuSe&UX)ejaRYOnRvRjL<+h7PSP?CgzpFVKJ31CF<#e6DOdWofBkHqF&OfNd>HZy?TjjqdMf46*9i;s+;X2IZ z@pCDn^SNqqCXvSs;l37EeLlCk`4=3kF>rd7FTUIg@n3Qrc43+=x9)pD4(+dEG;;}C1+>g6;1?O1z1Xb+ zQf58%uQ?KK1!^v=y8oIRE5F3hv;`)+fX-#m{+NoE|2GMu^1W;!+Aswx zO^KJEk`)$OJ^uR?u~l2|8m9X((cIa4*cB4bL(YZ|89}}(1-0b0>61=cL zyT!`w65WzwRrgSkdH?-$f~S4V+dNI8<}zREUro@=#hnh${+MvRm8=)j4%oj~G<}6q zRXh32ciycbQh2?n&5~=J6U|%hUHh*gVtixiv|!#AV!|3fxCC|5n7I-A-$G1%uj=HH zN=8rGdA>bF3O^9KAEz_D;NK&py1o8&^7+cVU%wWinfn4Kjg=d{{v*NCEu_jfP|k+` z>t%TM;@e5*GH0XkpCM{hOW({|_#G({Ey$&&`rWtB%xLys#i;tu-^rI~Nj}M6$ek%7 zt`T-nUFR-0qI@I7(pM8ZDEnigV{{Jbn<0|E?brgi+)WfI*YEy2L}C{xJGidPFo$aVz-G-7TR{p|!%-I_fuSocO)<|6J%W99n7cT%jl;=1m8xpMq& zh-dE$pM2gjs{!AOu+)7;)pJ*ZNVcK(c|>!qxyxAhrI?xReV^gjtI{WrlxrXNGoZ6>v&M5c078K#apCc@}ZPBUNTx{2{{$Zl1RwU5|@7i;)Kz8eL}Z zK)P>znO6QIhSIliW&eUII2rqwhZs(O|Dq}=8T*$XhbS{Wj4i#1wu7Dw%EKYbtO_WZ zn)ykH(sQ_nnbH>UNQA=*t!tc|uY#X)oB?=G8pUqDvUTp))0ryy%Z#s&I$Uh3#LgzV z&f%<*6|7fa9Qv6>QWwqH7T5iJF!#=VjAQhVukTmxQGL-_)Csrq%=h}wJr-Prwd(`8 z4|SlzDYo1y_2Y$DaOAnHF$<*j@55g>%r>?b;K6znz9@%>xlv2^c$vBU6CSTW z>;SkWv%-pTu3Uc^W72)ZE$w!&(syl1KcJH#PclqqYEq>ZOGe`vK>L+PBZCNaMeV$S z4h+~l;8gaCr!1ab`>48_Tk;Md>)T()SX1KfB)2d8bc{GPo=!5es^1hLR`PL@+rxaO z0BwG4czE({CAUBH+ak1zK0R`4@y{0E>8mzE7Yp6?hg^yNt^l(dTFxKOb0ug~;jJWB zvcE6E)jmTe-+FSp`+q3FTvB5%;O^f}nX%@NG1}76b_XZy>U?9md&H7&0y@e1rv$OB z_s4v3c8!;__y6A*ujO~ffTs6*L z-n+Jv=hxiqWm}H45OeujYh`_8jIIcqrdoS3M_fEUiisyT{^+^~z` zuHHcq}RJ^Ym=2WzY z@N$NY-|+-kxr7!E!RPZ;lvjd!ME)XS_U>>6VBwi->;S(S4@ zxwYL_GPH^(w@PM*WZ|g{^R)Kr7N zdb`eB?(2FFhDh7S!^3Ig=yqhvwf;Rry#FVyf3FZT&0yChnww$l&Cqb#VLg0qRT;5L zR_(}h{;L_%np&&E>SyjfypKoOTyM=EZm^H%u3JXtOW`#M4o)o&SFz8??F`PaXzOI~7cMQ5z{^(gJr+bf&QW_!`-I6L^?eLK&*Q(os$w=_l?XI0-9%6)C^ z=g`OqeoD|XbAi`;v@OwudP>W1{}>0W8zYrgr*ivVZ*XW$xb<0@EEILyn{%V!0Tv4@ z8hSyBeLQwwh9#|^tPKxjNOl>e5?01a;vkDf>k3iB=(hB7Us`WWa4LUkWoA+bTQp@o z8D*>My2|Yqz9~hDGuAa;t`#2Q@apw3weM4X5vH7aDw5Hka2hC|8*Q zWZL6l4i)P(k$F(J?J-x5hdZ3{k?Q4`n{CYWNbRAjIV!0y8Z~BF9A(Fwe2jP93Uf9M zJsyisp1Q`!jqS5J##GoeWZwL9ELPtd+A_kPf4j51UTL0@c^4lMqAl*N(w8!$;M@qO zF$=xwzFUuUIJHJQnVxlxl&Pb)IHWpOrxzVQr%D}VaE=ObW>vAX z%2{2$HN=_IGfnw9n&T{+zH)n8h%;^Fc1(yJ;@W;JdU$!Zk5_8Sw*F@%=10U zK(jS?Y`xtXZ?Qq4>mHODQx|xwjg9t{+$xzF85Vl9k>;lQ%Ekyc*y=i88KgxXiJX5e z7_QeU_&dtYQ5Hu?&9O@Bo0+-8u_@A`EmhiJrd=!vu@<&!o2y#$W!7Mp7NfE0YqxD9 z_my*8il#2r^+nk=TFIC}mJ-L8ps~z#KO@W3+_DreH2v%vEmxMyi_uu-x-HAxYRrld zZ3^!7&E@TcVzdf*%dJrNhG^KLS=QW0+gqWVfUavVSDq&(m}>3QcZ9Cda%=v53EJvL zeKVbg^MGBqmdty!Kg8>8VP~VtO&+-whLs^!ALgTKIg~Y)?#r^|tAT8kR)u)jLYe;7 zvO2+>&epOfL95?FYY;qgJ<&D)|Z} zi}F)BQkXeEfOem^%ue50hgcu!ZMLh7)0q-n$52+b&RkQgwpvwEf@ITCV@RuO!{h9u zYD&v(J;MpJ(`|pwy}bt_6#ATMjJ2wrmFC4IV+Q%$ zXmUKiC1#-gYqHzY%+0ID7-rv8`qVF33!;6$GXl*2SN`o=g{YPN+hp?N$-oMsQrn^MFn@X(z5?%$juR_>3vZ;mY~Uf;4s75aW=b?;1u<&Ln1 z6P4~~VI?zI`UW^F!o$YEG`G-qrHIqqLeEYSr@4i`n{3xgK#2!!sV7vC&g+ zRa$2#+4!%`UaPTjs51)t<;nMpTpv6)L9FO8y5#$j*23PKVrh@j6}>m-=4|IB zn2X18eonatn0$%m-c9dI5U1Ox^7$!ZHJ{3vwc7V5SW5@^VXUc~uYDlFntrd!A51Z) z#;bD4>dg%FiwhD=tl?DkaGcqB`cQ(`Pc9^Ucj)>}m>Xd(OwnMT>%qEhF}bhK4<}ev z{Tt_YlrM5<@GY_+`e^UI3^O(M5sqXIv&?T+*;CGaCtb|Z`WragS)UTjTv>jUV^;Pc zl>4T>#33~|bl_T`-WeF0p4Rv=ht#RHI&RkK!MblFnUVQYkJcP30PDJ+mCSBwefHxP zYh`kgOZRyy`FbWR%*z~3>&#`%fzzX7p50@W%)Q9N-6t&8s!<#-4nGaLF1t*gF84UY zIICU#jB&{-3!Pp4B*&_L_BZnmyP^OoHr?*J6f-&dREQTfjINO~{p!jPsrm`v4A!SZ zti+|DPQqRN8@Q**ELr1exb9hf8p`k)7Sp~(xKq^dp$H%?>aY`cK%lp z4mY@-N}Ml7INacRDslcgzzGf2rxNE&5zcg#+uuYumC7yCs&5EzxS@KtrIz#d@wXPG zww}HAx<)AZJ|(ZLH#!7(GpjJ-^pxx{?Fx*);~4B<$5iIy%O0b-p+Y`#r@j83VKgdW zx_b9DlIe%HIE>+Dv%*=8T+8}rhXEhf6E_ zEJ_2*}0CAlp`YIjC3b6D-c#>PtD92u0`JxY75Ho%&7w>6aOIsfiZI?Y;@y2-TZuUU-Y;Q*xTe3Yz& zkcYDWa2QQi?Oh{e<}6=#2tg*gA1h0&4(J@>e_D)@s_)_4NOp%qsgDedRJkQ7hw@(> zrP|rKOfR{Uq0rGo--NrZ`&?eW!BAjg??Jk*{oI`5n-*oPx!FT>osUdU{BMhJ1`I}7 zHoC^h)W}^Hqg9U@an~rBp7K8yrHv`;`buw=49eXOrRqCBSMT3)C=Hg8Zc8gS%HP8f zs>~&Gmcrk57^7o&`F5({?_j_3gV3rPCUy;VzG9 z8;ifkk%rhLd`e60K8`YNdHFs=862`)_N^LB&kM|%$8BID(*QJ(e0Y3_mcypdgl!q8fYk+snu2C{|^J9)u zXP=c*+W#MBDEI*LQ;Ex^Gd@KpS^*39D`1^2C0Ldnefe_>IuKgvJy zyUt0bzdYeEqL2LU>pqi{UwV{kImx_Xo^%+U4RbM!4G&a$FK2f3er1t1wUa4x*L9O= d%THOH%>(V}o6Gz+^wKJLdu6chvj5fxNK%>A!bk6nB3+WYLD zOyYOFB)^&I-nDAgs#U92ty;Be)st^&4_7yC+k5kV|9>+_X6I*S4$U8%^?#q1zs^t3 zA3DlEKYy>|T=`mO*U{hj-{#L1H$27p)}L?j;Qs^}c*vuF(fN=3bJe|Hb^f#dx%zW& zbuRaxJ#T)k^S|q#Yrgb$=TiUdeb2h{tv_}iTz6O5`PQFr@!(rBurnEW*jt|GJXnAB zz2eo*gYjqTMeEMD{>1a(hWuYT{~7;0;z#Pv{~>=C4lFM%O}h&-3k!wLxYiks+Gjeo z_LiF;wl_QOxij0{S=T+0$~99bn(cn4XMoJPcRbsjFQ%M@h3U*n;Y4Yalt!{L{Z$(toZPqJ=TrQJx1B@kzLWoT~KzEdw!L7yVh15z2 z#63z?xh%KV9k);SI{v}&%6(&R)GG;EqpI1y&!pUi>6DvGxgml?dmez5svwY$v|yo) zz95W`NKrT&LE3B#MY9${W~1AmwKO{y(d=AIvvZba=c1dPvot#&YL@3%YIWQ_*B*Dm zCzBCgGX{)jG*wJ60vLtN>6=5bPs6N6Keq#t)L|wMU~msVE;umQtXUbO}&N z-Q&ZBc~YX{Mn5yy+-&#P!reu4)LrWBsI^6^@O~&qXwCUKmo+3b$cZu3=jLE|(JcxE zSuFC5onG#=H}iwx7%F14((Rnz!p{PN_2P`Jt|%#`+oMjYKkf|I+p8Vc)Iyg+_1JKl zx;EWjJzE$Kw)<;>NA?<010TsOZFN?Qo!*wz@bS<=x)c^EtEALiSAV2FH@VNDPqopR zkp~&os1Ge`(Ib(dUSkOX1qoU=&sQ_GRHm9QxC`^+3uFELP%&Lj=QH)XyV>3vEzIbG zquEL^Q>r(bZfgV{V)gKfs)bBB4WX3F0Jx%-fMca}qh76`sMzkUFC43O*S+;24Skxa zmm%#9UYclZS~NHdri`lfRc<70c*Jjymq^jw9GgB}Y!{zPqU?>(j|4NvyxWz`ZT&<>32DrH>2H=}+ zsnp13)1Y=GS1*+6xmF=n%bh6YPt-F@t(Dy3QmIj&p7!{U#krWv=CWu(O|Eo7(_3|G z)l|BeY1F*lXSY{9d!pvnin)5GT(7uBFLZq@<%MRwl*#A3`nADY2Xi*Rrl4l#GL3So zUdoXrkxEVL@9CV|Xg2e?D$E)x*`&W(^w$>sRinRvN)`<0ry>2N?V6c%&COIw)pV*- zVGJcI9?@U?(;EGBf&N;dzuNRykN)b?Ut9`G8I-@^m$Ie~=0~nS4R?Ai#r+pJc|!4UDNEt4q08Uh{eu%;a(|%)WFJe*!#SqRQOu zyXYrIy>N(rTsV+r-s9go|IS}M%8Y^0+{!iFLZwp8)(T~ANA;M|GIjhDBhjr0?7mj4 zRLL>&4Nt!2meR$112dRtWL7N9F}bt!H;*p2dCvQIhJIv0Vv-n!#f9Z+RRHQfp@~KY z268oBeZbl%K!UTiayH+Du?XUL44I@$momX~-HkG|Ob%)Tdf)-+M$W$4oSY-uMcL(r zjHfQ+R$QMkUr4s@`s)N&-$1F*u3`=L7umbvgAu!nWIZwV4#~P)O7`bzB(zv`4b{R#u&vlN*;HA#z8di%nu=*%4J$5hR+HrQVh(85cv<5?NxwS`ppQ z#Q038P-WE-#aM6KR#HXwKH7OK@Xsck5DIz+{hqaVS8dUR>`T152dZ6^(m@W6n3avWV*xKq{6lU~NXFTrqu{laOTs7L)rdCSQ(x^GmCP zVJAIk57(l}7F1+5+T&7xYkS-rjJo6QpdVcUO%~ZDklE4k9{8w}c2Msko@j!NSVj8_bp*pz3xqpe>1BF(NE zwoDQ5#8jp~*Ms}6Kb9R_0X>7E>|rV;Fy`SIwUrmK`=DWf%K`$?M5CSIsMKE{M6{`- zN5Es;RPRU86^g_#R7h`kduvPJRcA7+5aMjF=eZXmc?&uG9t|sm5xpvnkN~Usih!27>@^=>GrS)25yWe^Fr5L z9&GKP8j(DKxKvj4Wu@KguCdP!PH^{5IU_K1z5+rSc7s9Q#RMX7=_s0DKC_R{0GB#1 z8b1r^5a$*`LHWFNVuHg_c3w_v0prc_lu`o4PFu}zQ^jF^6aHd%t%C_ZL8GYIoeY{b z7_8R_+_NU52VDavT%riCbd|=aL6hht%ZR38BCxN6T2d$Ld7?W3r&&IW+iU9R2cn4; zi=DrvK9)9!?Oidd60ps~DeUmzFvddXKAZ80rIGbGQB3~6NXcVPl=>r_D_IuDJLJ+J z0MeaxtkBjaM6^3f_4R_qrbra&Shj@nERBr8UFnXxI2DQ}mc_U<%3XlFx!>;fE|LMW z+8%e5)Eo0Aty@@xn|-he4`d`0BwkM#CQ_oP*AfB6wew04qr{a0wn<~F6KVB$T~`t~ zc`)Pvp6re{y8Y#08=8NFvlwqm$7wtqS(J*!R-LSfN(aj?OtTnn7mM10k$iQ=xZ58MUhBRiQU+tXh z^k8oG&qTGPR8ON{8*Gm{O*%q>JSOMd9Vh3xW(Gc6^PsxXU+zYl5@h!gg-x8h42GN4 z_Qe5MzJo@&^7atjvaLA5Qg5xH!#FBk#5vMARoP$6q9n>OKW*y5z>pfpFIq6Hc47xY zAx0X4BnLp3(4G>jF5sJOvKyntS$Nj~Xy}4|zcY-fA;o`bqq{zqhWn`6Syvj^V<)fd z%ugTeA{$m#Ge80l&Kr6)h7uaeqZUQ0@y#&kjQe|wA|lt=|F=g?AbAhxm5_~hr?0i zt;lSRM%R@RJZ@uYk6ikAP)}^FwZ}U!vjn`iTqZ)V`w+L1C~bOT#MaYHG-j~^w;Eft z{~s-3yNkdfJ}Pgu$SCNwM&q^aptVJ=jrG<*z`5=*cfM7@f%q9^%InRd>&}sXLVb7X z*jz&i7mE)-d?KJ0f&paY0OJrnlpYQOK%BsKcO45CHXn?mfG;>P6kk$KD~@KA4m+^n z=GNDz&HwOy)EC{;XSVrTF_X(wQZ8}3SPB}7J5{Xs{$D*mx2s>SM zR59IjGlhD&l5WtE8_q?rVQ$H>(`T_WN2-NFq1I@m0YisXnLPcwL4WBWqnQlO)k^hz zs!^arV)JZ~4_B7y8=sT#p&%bi@oALzE0;3x!hw91;Q7qWqa&MhOSMw1kuQnkA@6|f z(wh)C6hCINHAD~9GNlv_voBXK0!>tMZY`Iq=Sr0SCa6oLiY!_p>JeX-m|1PRMk*oYK1YU(iI z5+hREFFr6pOtAqe+pt9yW5~&}T$u4A!35D!#RejMigd(+ULGVJ@ne!-DFzv9P_C4z zr-~JKX-q;mMDXs~XnN*|TCb+D&ev1re2zl1sPhQOm^0XhJ%N1A zhTQkjhkVY4+>{?5@_9dUeGY1VmgsevzXAT7>2=yeG2ATGIG`~x@GRwx3S8=$0fJ2t zuTFkZKM+Ld4xDva0)S08Ne;_f=thC;9PNtH6oYz!z7{NIxbFmt$eo)X4mKAH6g%mY z?GgxYrsW|+vyJ^q0DyYNE*UB#m)seSn)N|>{Sy0h9OkVd%)SdJjlVTQCR}y!SxjJh ztG<#^BjQT`NoLT)(P9|qiYQQE;vC8cCrKn168v&2enH@2BX`RHC(1td5W#W}4kwF! z++{hbMBdNAJKQ3Uw@fWb2S4O7r$cB%c|y667bK!CYrJ4h`H||0y|B>3bg;P{Bwu;V zRyQzuw0t-dA zkUBY^VNj#>#m;zp*k8W5g$o4iK+6u>=gDFwg(>hY4|4r+cYM)GG$~NhkK&k0XdbyQ zuu}mo0LLCp-_nTb@VtTIV8v4Hc6F?RK5`vl(%T@l!cw3z;voW7`6d-~37*0tj zOL^gqdCHM6mPUv_+}mXw?jSnB0z!yu#1NRhTrT(i>A?kQB(p2jgz$JKAh-owuM05L zxD$f=bs^kx9?B9Er#C~VXS2B4Rw~uWJ(9_557YF~N-LM{#X_UbP*?3ZfSMU_gBN>42M##P^i~j5y?P~`4CL4md#aiO&O7IP_3GW z6`svxa9^R+ka*Z>A3&6LE2(n5SgF;;pb#Q9IH;RCcz+tUdNy0E*Bb~UHW^rLpYC{f zImn`~q;l0lvF@H(zpyZ~ij#}ZaABs4Ubed42BF~AOT~J&)~E(r&34w?+dUn)K8?7b zQm$F5m#P&D#?jgBUe6l~1ZZbU&1|*aX!wEIR%s!)3x^^t`1Cc4s&2N1I|+64-bb&m z0uJqr3b|afj7yktEsV~a74onMYxQhg3w^Hw?i*Ap&0MC~EE<5ZcS7p8 zr&-A7Fpe1O;aX>y9`Xr|BE0T4^UYc<1t%q9T*3l{T~;xl$~TKmDh~)sAv|Y%D~&Ao zXbbGb#AeDA8=lj~&L})%LyJ_HhT!HVj6`j2LQVS$Ou9wETvTJSAY5ZUTtg}k1c!3- zW*sh4k&9Nd*Umb6`}-`&K*)>vO3tztU$BP!7Hld=UzhI-HF?QxKUO&pweguar| zQ(^L;%!Rd^?VR2|QyrWU#%VhHY>+^^78Mg2u1ZQ??T~Q1%!`45GPOMsXx(jCyTXwE zQ|L%I+Hf#CDXcEsFp(#ACTbDlbyF^fe50FMQ%j7m5JW3$PayV{dP~X7Otk^ET*qB3 zRugje_@IF+=!@Vk`G6v(h!4gm=#~;G(3TP@w!RXZ-1-1mvV=1#Al?=*aU6lN-PTMtDgH(?3$AvZ-#Y>fi)=z~_G7L^1bvy2TL$9*OB?qT8dZnrL%rV3S5ml_SkI(g+RS>N>*Z1-UC89!7i@2C>CcBsm2xgqfTcpv-gU)8bm=ylY1bXeG)mc8u~u@iMdot>)$Jp&m2&B7k?y$m>H4)QI9kFL#%80KW>+-J zj4C?TtQKq8MydjxqgbrU(ECOul`7N=X?bmSO&CFeJE~c?n6H$wW!RG-Dciwf(B&g# zT3Iv^n0$?Ny@o4f8COVNYPi{1OP>+G5#4CfMIZ7o8gO}&1vJ~)5`jY@(6U>hyQcM0 zIcSl{uJ}!nDlE2arj{?I+!qYsEdtQOp+lO$s$0z>uS2cgU^dCwq3Ei*^CQbLN@I#b$W-s^6?+9=kl*(S@?Y385T1Qfa&W1%yAJ94AY zFo1*|EuDWB#jX)*g&z0>d$UCXt3y;6UOnq(H`kwQZ&{(0d~cd zBFB-G2FV9jl2#Naq_seEbKKcP%(!A5tSSfG5|JFNV@$)aWD5l_EBEyr&0A)Ai)MEZ0*5T!6`~ahs?q+?0j084k#_ zu|-aA6FOSLlro42$c(`cYn>G%uW&(5$b2l5!V)d$S!}txlPbrIsfR=unI=1_#~9C6 z9bRua>rdk>M7rMTRA2>Bi0p}xiikssqejQ{#z*<^y}>u3Bh$AS%)}A^@3%<|Bvc8F zaJUQKc;rdAUu)a(d6}{zEp2^mN4gKE9Cle zsh#t!?~{;V?`iM?!W7yVNM!*)e_w5|>@b}P0D=U)SvA^{R{xOKrv0b_<2R z`YAY^_GKetn@c3l!O4`ko(O~`U5U@iMB*L^E0VNeTPPTBvOhLeC`x1deQIb`fWGL}@G)@TIH znOlhYawgTxAVUph$vM;3b>?gNbRpM3cD6M$$;zP;(lgXc`GzZmMH!=q;Ll89Ta|LR zDEpj7b2y!<*2}ee)7|2WHbz0ViI@rOD^9mL3|wJ4T&<)tg={`6O@6Ni65kZjXY8v6 zTc@F#R1NHPYV}$zpI5nayb@Gt*0UMxMTR}x!_@^xv#A;~S!6P9R}F;1b`*|gxHe%) zBe-^$ZI3;k9Id3Psd}?iaVeXVZ%1>q4p(@ik}bPhCKSSB>2x8D5YV)XEzl4Lnz%8l z%di8W%q>;-G+zfayLBv|%{OXIWWqRy+jOfWYF@o!wOlBrnt69b0j!&JCqm<_)(ho& z9V17hO)}gfU8#yeM%JLk2MHEwhzIQ6QsfX2AxRdk%j7YQZ4hqYX)ujO}{5>=v`-GO~4) zIgFR5E~1O%fC>+@M?u+bR?F#PrJQ%A|9+)2ytuT9W8*yjP`H2xTyd-Ad>-zvY+yI3 zRf2yz35R$wRmtWH$PKc!L#3J)R0)J=)&BGIW~EN!bUAyLl`qk=~hmlv{r`e9=wpV5}WFCy7N`H zS;Wo}G0TQZ@@PWB!*U^uvj{Pv`{uqLThc5hX$D?HC3`$7=H?hlpc>^8d^8?mhM?e# zxlm|eYfN#<&{Hkio6{vWO&%Z`WUyd@3JUx)qvn>=IEl&D%LZS34Im`Dl&e%TvbvwE zNFtRkmr77f*!bg+iJ9k}FyRCvjsB-TGaz5eW=m25;$F|{Sy*KrKp~&4Rx?F$OG~dXt z7LW?gJ>X{%BG*&JYOS23G)~YE(00qAZoq$&X%@;wM6_wu#Ist{(R3T-Mk7bbG&RKO zUK zcFfM0pG_0X{O+@|%mRNO%o0Vpa)Jma5$8aSv8D_RR)fkcS4+8yNffz*E{qWpfn1LM zcD;B-KTiZzUa85LP?^b{P@#`Sp;AAeLd5}QS;}dtuu4M^*2=aJkmg;m#J4F37Ltzi zaaRJQu@0)-O1h_p6)nJKZLCMKA#YwuINyX)-z@x{4QwD3sFj}u9%V%mmuc7~ z88C`mPNBeVG%pVkiA_LLsBsD28nu84|2Xa5{Rv#cpel=v?uIG*ylDILuG3)zyZw>J zC^&NkIG@+)49mv(fM1_5aL6-ds~4guR7+|OO`Fa_OpT8C>pfo*e3kKQIH#Ax&cY%(X}* z2L+!i=`c^g`?3p#$5^MxiJ3&D5v#WjKvdq2Fd~&2BoWYLG!YO|pNht6NW~x+F+jvD zT_5l>kRmvw)6z&huIIUn3$8W*KN34k%mU-9K>2WZl3V6KqH$NG0w8y3qhB11&vq^< zKbf4Um=V0fgpXbV9f>%52_D#ldlymBm)Aq9Jmy(s>JFTp zZj0%Pa~O8UnY6%dj*Kt}$VLwW1c8m>I#)oTxxXUP2_TU=K+3(kS~3ZaXdpHKC2>4+ zu078Ro-c16oyGLt_uSVn%p?^h3&nz~GIMqXec;X=vmpR$&n6xeA-NlK1 zd?GyH7TR`(FsEp61Fck_45yb~JZ{6Kvob65UNUZy*^zAC^DQD7WNXv4$YJ z3UY4LaM+~2&KGKUgrJ!(yUWNP;eD<)Qss0Oc^<|?q##w$hjWc)0}+;pP&=`-jF$j( zK^`Xo#YQFXE;kAVTu@R4M+&7(F`sR?OWUV;c~AvM8_hb-k_stx9^ti8b@Rm>vOuKy zyeyrmrk0knxuuLoiU_Z2wwS`R4{$7I(o4BTyk>w59t{H`TdBjxjtc>sW(?Trk#`VN zbF0-tsa&Y$8B3;^suyxTF4ScmAOk-+JiY87OWOZwNxa{nLg6RX(T_8kl3T8& zQ`u@$;NnE}+XTsZ>-jHESHcce_P5rk)ceN30xc2Djp)4ls#i1lii;L-jVvMO~e$if`FHSI0dy2Y5q>L*61Ye#AI{z{n_!nT!t{2j@5Ea3%-pdu=S=nGyh@R2D!oQ9*`S1et!ew@nt zX@Q*gLoyTiy1fbOhf&hN9vkh~NHBid4-;@Y_^RrSe=xJFod{#UYEo?OSk(msv)qnM z8ur={Hf!)y^Xyx*C<2+z-WDpCS=)rEIvG=>;pSsp+?-K1pw1MwCiAL@e_$I-XG9uB z&U?d2*2OD=;zoqlYD!T-PvV+QR2APGlg|gL-0cdj&3k<$5+k{>b^3SXJcXy`5qp_2 zq33Ie)WGR|+4bECm~SA?2cZTHcZ+TuDHCbFS#DJ8NQUJi?VT3|bEsY}XApRvao3Sc z&O6#aoGT*!sF}*UYm~g*D>#x*;bK7w0R_;mS+RA|jU26Kb4?^+VN*&LdQ~Y{rP4sQ zHoR{W*l$%FYzOh48+2DYr;%&VJj6$T^R;>v_Gcy#Fyf7`Kg1-BWBY6_ zhbW^=u!Rwc#A$jF0P#g=#tV%?EBS0GTLd4CH05f5aS5V8BZE)^V?(J*!SQmgTFr|K zC~|0;rhwF3yaj|{3VKFK4J_R!*BnGLH9Y!R!^2xL*rL>5>s-*qb+>@fs8pfB7O-rA z`)`0$(y2x@$B$;IHu!M>1wz&qZreATGQ{ftu&)o=BQ1N35pi0vyq55YVosB$V&u*rw_P+-zhYWqDj9a}z4h z#Z`u-5YbPYD#zJkG`PJP7HqtoV&!_^a4`xu23k6_;7O#+!Q=&s0;VGXGHU_4B(4#~ z!(yjkCJ&~dJi2>EZz9mf!Fu=@*EUvFbe7-MHP%)A0!Sp?)Jbv0H{b2`Ja$D>ueJ&F z#0U9TOIc*66RJ;WrpUJRZDM_*!tL>$yU0r7>=E4yxN9{I#ky#U(Z|UzP!Jk zpG+dONSvjQJtm424TkRRL}=9oSpy*^-BqDNmhdtzU6G0INhL+MZC2#u>8w@Z!1rxl zggR4a0&yJoq(?w2Er#IoNbV~|FV61wlF$Nq-fQfBheEMn~|1(@ffF*u6o)EVsA)47+e-5Wu+E^L+mRxZCFv+uv>#QjUrQWjn7u$37W5RdWq&jg<433 zKnBarhJ$6c)+G$m7pQPb!Vr*e0i;Y~ld#z!4`f(j*X@jn9sc9AX+Cai89Sz+7(}vkI$^BU3{g{iA7|E zGRb4pQLbU8Z%?zvrN}lfS_KwuceJtCc_D%n#zH}PidlD5$AnN0Ic+-#_7l2@$PQ$1 zJDc(n=9qmz?>!*$OL#WKHI9*GP-_~DrOqWjFSblAY? zrWHN_se2k0Y!VEO8gUIKt2r>SOF5Rkn^iGq$Vj#jJ1QaM}4Rio~?Zm-++9&b1XS6YS-Rz1XO zX*-5XgYbHilZF~)6G@dJI5(ZfRmvKc(N!w#AisysgfcX;fM8|MGz!&J9&4|aQjIcC zxlk&p3bM#)lt?Qw9OHR;+<*!g0q`@XVT0g~Q@~)*9r0Jd6|;O1NADn*6vAq|ziM31 z#BHf+E?dp#kn;v@p7@b+-md?3gLvZ1--}hLx$*CJV@%a8n=H2z4S%p>CjDL z#S0$j$Q9R`&IPdcPO-}6%rN$H6)?`s6j?RmI)wEIWJpT=q>P;wJ6E}v7*qH zi2Z1uoDTMd#yg~sNaSMYh&ZrkzEGItaBO=rF`nNtIZFh7EKvzV0iyb*a;o@@FD*JO zbi%^`fbHREFvK;e&JaeGogx+9sVy*_5XG2cktUd#!bHB^7|$J^N@lG@3pLk@PJm+X z8B0Ic44PP)ThhW(@ukA1)KairyEoin_Og>Fmu zgYRzM@BeS+$n5;g%%S;Xv;ObX^4GbehmRiSpP#??ddG2o+jj?l<&IEdEQ$d=Dhk9`<(R`O*wy=zrm^h$RnKBUgnSK(j!Lah@&1*b$`iAKVG6}}P-VG?|~4tRIroA_V#MNmVuD0-c5&u!2^iU0|cu)cm8qsQ>qXHll*0U(lmUuHZI=1dDGZgQ`@(ieAw-g~x<{ z2+J?EN)!nwL5HA^=92fnm|NcO=1&g+$7t43{~yXag8D9I7~v*;M!J+{3PBNv=#S7T z^e^#&W)X2rj38;My>hImH=_TfX#}P8Z>7>R%d5`kz|cjeZJEO}dcUy^b{%^@`ddIBH*wyTU;=y{|;8xB3Y@RF`z!mFRV( znN6?jN2&V6z>W z=M;-NnA)+y7RPa4s<2C?D5>)>j*!F`HsX*78I0XJdi-5Lb``_vSoAv=ePuAf{Szi0 z)^7d#>zGgEh!Qknc?}6}&hR9&9Wcs0HQnL;?&&*5DTYm7L zUQrB|*|vRn&dZIlHi!7D0Jl075f z&?xb}UFdzc%ZgD>LGF zm1EzjXk19RZ-HXheH^qsu25Aog+bF}W)9IGeK|q&SCSg?#>+`Rfgyewv&B#DEGwrc znwp@{BOCq_pUC=)Oo7!UL2=auaUNX{NR6vF$&5MJP86+jMBbUeKjEZcs?p#y(%;1y zD0RpacK_Sz@(l6G>cTGS|45DyB1aJlT{gW<^Cyid(|Er;%xPALzG8B5wRerT0Bl zYi85=Y%%YOMMxcLN8J%R6!q50&eH@(-8S0!9q|MYtz1G<;&iT5tYoWYSDMgzY-1j6 ziMuEjd6PXR{c+SIFh?#WFLJh0%#`Ylrc1Y~R=Y+@)(Ihy(J#(iVy@*&dd=`?wU9xk zU8G$V3xtt!H6~Cb{(4$W*5{+~fuAwy2jcTZ$Hc9~<&uth$}u+2G_KwuHWf)5$W&`( z%~asW;&M=z(#Vcb0kezk-ul9^YIj{akn`fAY^WQQMi>_4KDyY zoptfZDkXhSyUObIcCUJE0@&qzzw19dTJC`juTTH~;o|X*Qs(dEN!!FvukGmd+npxu z-_fgX>9X5EI-zV;B0 z*P<&oCrbGf^~_QW38I$pOu+QCmx|yL-;B7#x0f-L#auR*h4hmC-$Hyb)R$Vm;-iEo zJyQ{X$tXSp!Gu&>lit9X@QPzxeuMk9OEFi^lHDp0_k(Zjzq5Rvf*!wBezytr9P6M))$2+~n zCXvXeVnG`5&RHsxN8X;LF}A-a#<=Z1J)=`5PA7biCsU}GD{1UPNdPGvpe2vbJkQF6 zYqrFY%kZubaNrTBLM{hWByb)k1wHtBJQ|*v%QVWVdI=YuDd&yu{iQz=bObu1P{YG& zjF2WGA>N?BbONc%^O8_H=Qf(nd=4*Xb6Z|Ype<_6%U{U_oCApSTGLYBWA*q5;=+u?iQ$1Jytp{TnTx{AE*(>Rt@>QvrWuO zY6267%@*~qTpYwly|I{qv{y@|bQPJ+ZMAp}P$)#LoIRH1!Y7bcjK) zhO7DU1cTNBrDlj%pePs`YBcY?$l|YKk2CYb*k@A!#u5{M`!;RI%(n7<1a01?HSHzxyVfS&(S91uJ+{ z%`EZeneQu&o*C{QD)hyQhDy!pWflhKmRS}zv3zh!{fW3yvq*)0${QX2qRpr`LJctM zT^Xa?A6@K8rFo;p01wVwvq(si5aBSr{=iMIAzS_^6RU5=n+2X|8iA=k088MiS*{Ms zebWR_nsv@MaeN|UK@CDT+h_bqeN1FJyw&*VyU}BOw`(K=Ac}`}HDy#JDfKD`vq`zo8OWDm7#XB$=8FSMzjb zsLW89mNGSGl`8ionV~{YK9%YWV=?t-sMJ)Vp+cV~4V5NRr`B4YP7M`%iZxsm)UI|2 zpNh4En0ht@5mdGzfH;jC23A8T)NZIepnEOlkqS5nYt_O*AfGA@7Ml7vSQb>up>m66 zj({N!hb7vkqeBRMiaJ#4%?3kThoLMgI|QT@jfGBCB$RikW=MmFAha3}miTmeu+Xm1 zgHS%L9xSx0_ApdHzlQ)UN?yVwOuatigNq)IL^&({SK|aBvo>Y#`{>j0crZNCK2#w$ zHlXTLNRiufX^L6m394UhqfS^`&-z}rR_$4Ivv|6E;(k(LkVij*p)nn2GeHH6FLu2v z3oPnZmV~wJZ0ORaqGhs9jY>nRcY@LyR2XCSi4r76U(Q<8a71Vl_cDL{Z1D~PN!LIcPg#seKD2UtPwTq=c>2;m91Gc)@+=jnzivHPA$!b ztWDW6OJ(39rYM@TDTFzjLhya`DTKKlDFi?VO+0HZJu&&kHdxY%ySQ<79MFUn!kk4R z%w;SJVUFLAOsEh9aL_cH3n>JAu`2{wU{MINB&-nTA{0WRw1XZuP1|bDt`O++1WRfz zMj^~u6oNHTv2|}V7p)Lfk*N@3(jCv)6hiD0n!&}yE{MJt4P|J;`sERpv)>=g6Lk{JXByr%)YkA_iTepGt`eQ7rK zi5H*f@tI64xP5id^-Oi*(PVA|y{|r%;(boE@$-XwYQ=U#8~xEjD(@0orB-#qvr)WO zLP{x6zoZg4izImZK9;3r_yFr`8D-ewc zP2+v_ZK=G^o{4JgrHo>WQt?XF7ReBBt!ji~@nH3CNPn^$5W3i|9l&0*f0AR7upWg; zAqCwE+Oh>=0^<|Yu8zCskm|&rryc%%on76muEa+rnwM$hgCO2Osl5at6j^0FSpWPY z2+A`ORjwW=@xyr2E?l3dpKp%IZc)}6ubC(?@w9pX&YYG4TkE7qv*`f_Cn>VJSeR*t z3NTcN4_p&=q0xPQ@L$8~^#3Ku#3aAu>kdKNJh89aAz`*sI!%Zsc~3T3a;9tz8n zV|7be-(VfCUPyF&*(aBx|wBHvO$FRLLLx8m;*Z@+fT{TfF!#JwE;AMmL8 zVCN~}AGqhx1!laPqH-o##t%$hNS&M)pgiCLc(F6y9`@-q7gxOMhgTD&okF&FVCtw< z&;#R{$R5_(TlCx|Ug%WE?(|AbDiv8SsO-}#HM|0l#ch)&hP#y4 zH>C=enePOHi@4fGV{rdo=Y+NuZ{dlTTkO)KW&)m906bPFwIhOx#+nmOIEV^G5*t*| zrjXK~x-xHnO-OnPl9lCTtn6*r`Qs46y2|!?-bOF719&B3rLf(tc25u6!;88Cz1u3g zmVsiVgX!*F*yb1x7O{&_Ivza0lLz$BBh61Nk&!JbmT4=(^tFOf!IY1ZjM6BNrKwL( zO-G^@wlYX5jqvWk7_fLpatjAR(Nz>Rm<{|ENF;73B1wr@yaMOEf^aUWb)RD{c{TGKDS0iQV>Nj-pBrgHwfgqv>CUjRP9u>(i3!xc24LW0 zKF(-fb0MoGo-O`m%zH7WBd+9mfEGE9gVyTQb>qPN@)-x|$zmK-K<;8dt%4Qi7iuH3lrOWughO*-@e2^^I|X8Y~d9V-3qk}%rU!~ zs1_nOCV{pv7qvS_{7mh^D)lxx^!yW#97vPf4dMRr_8$B~6zj1F7z=xn)QRf&#JVxv z*L91X_L{|!g*_DYw%A=Gztevs@@Et~BDKxejD?r90}v_hWJShR@dXt0S~r;~=k zQ+g8zP7Su!d@w0@UdbRok~Y;+;QWIgA&=^iH`LZj7RS3Wz_D+%mqto=Po51zHH{Qk zBK0m-XVu4vu=3D91h0pI79euYOn?aBIoTa=bo>YY`Z>~OWT#Gc)qwZk#Dk!pa1C)k|?ip^H5GwO`^JEW1+ zJ)fXoLOnWhyo73#4udRWqF1V&HK&%N9oB01*t3zW7S61hI>8Lv>Iuy)_8baSG9UuB znHI5R3OeRQoZM*yj@5${8D8P0SO{UTP7Io-SQgr57>|2vx0#E}sCvCI0GKagL5c$K zg8s-oim{ZGiO5eZC}#Yw9f_WAyk6U3XlPB(q8%zG+|*xTN3WOTY_>bvSnRxTyE7WQ zrVE>vE_9irY#M#qS2MFL2R!t^H_-yB5_~1;A5ln~-QZ4Ei(*r|wa$W*x zpAV00u$D1?G&%`ug~uadMN&#aS|+zf@f&N(-VirTVk%WT=Q=&aKK0MUXduZt%*?Z? zvGz(^#!HLf6LQQ~Zi(}Yp| zB8icn2g67uE=vtZb6$))ge5QuFr^^y@IYf;B3%JDy$sX+tYr%?WkVLT2AAF>e&$ix zppE`=H}W{0yH5`pXlW1GSrETn_@X^ZV#b&gbUq&w!rO%OKmR1H=`MHXbSk`)#qkt@=tv6|xou?wy2K!L*5tv7(VAbc5btXz7c2 z{ths4vnPB=smw}%7>DzQaU;DYY=;GbJOfoiDTCV&=vQpghhafzg(Jl!yJ`^VnL`2k zXc^9&Lo77~W@ARgn5|qhJflE6A@N*frj<=~^x(7PvNtNnp^e(+^8B0OYdC~{uuU(~ zA{2UJJ>`?pZ6=J%5oV8t_$s8T*`|0rWkcHgQ)hxf*Zv)5(5ws zYT=cuP|Kdcx`Y#^1upm&b;gm#7(Dw4+)x0 zUR+wz5Ro)0NQ22@IpeJtNBBq9mDJK+cG9Tews?0{XyPSg$)i(=Xq{I{VQZgSkueCJ zwQ6@HS3tSE$-x_AbU9$X-|n?24xz!kZJ^SVr#7}E(EtnBjM~3OSGWcD<-?kn>eP8;Tib~I;=eb zL#Jut0-FM(p%P7sV>8D3O`K2OvHX zPzx7%r9NaFqW4lY5&!~ww!7<4vCx5xqku1Xb548##Hf{N_j;${MavAfak*!h>aX!F zAK1t=@_v1Z5Z;gurEwcnh^T$rRE~(Gfs<;e3a!2F# zDN+Pu9J8G7A~Np$!PTv;gM-sAa3<8iBjRC~#{H_?+8mu3CC1QZrzWz7oarQ~6Sip+ z*Yfs4iL3B_OIXlJ>Wsn4O}O)tz?zyf3B0_+@A(IlR9Y3_Nole>R}wYE2ZWo0@mexy z>^Xcy?Y&tEyOeZ2CxYLnrw<=Kynp|pLq`wIGwk#CR(CBpH-6#$>o0np&acRtPXL^| z5A8C(3ksc6$4?&{IL>!&iBDJIAI2AG_gZ{k1x#PUU7_Ft{oM!pz6UTr{6c~6YW(B1 z>-FOq`2JDA>>dg@kZbKn7Wi%i%=$>cMd3@K_~!ugw-PQ2p98|L1+%X`C-6<-9~*sy z?_GfTCkYpa?-A!6=Mfj<@x2PgzX_PiT>|c5_{TPGUqydE4VXWDu??R$ZU<5PlJ9by zpT{5i?;-eO8#ki+FC+}X(SNpfzk=_73AjJ{ZU%9p_)PNgn3p)t6Y+=s1G!dwe}L~# z1O7C|Dx!->2Ak)>`Mh;6n$wFKOZn}lyHRKhVNfM`0oSex4&25 zy8-_&eWMHTW3 z#|B68`{o~1n8d#}II!7yX9#Yedoa-MLjm_oAvo|a07v8Tz65YIo*zm8NAu&)62OuC z{zU?~#{up$k#Gm3wu8O^+!t_zs&mT=TBZ`?e%$K(4i0Ok)QoTiV*!w>fEFcK;MnP_bY(;n1qX?@2>#! zkAAoieI(D{1kBza#t-<9F@4r{VsBaGJGMIcf=kcU+DPJos)l$ou;_(|>nZ@PS(sH)c zXqA>4t&^o}uC>(6WlH%{ZgJ_>=^HIoYD<~cN^bGinPbz|^3rl{F}2)SY-Mxl6NOea zx00(`F)hL~1z)I4Omk~3+sa<-w>P`1iyfp{8+FilHkVJGs4iDa>EkzUj?S%a4ab46 zwWSsGA@H$L&DK-3+|rHvX|nu1{yY^-x#;YgB8Fs-pIYmjJ9TEzTN@2mPi^#OP8IO; z5`N|&oo5b3`_CNp`n)xqJ>}ano|>>PBzrQjlRWO+GPP^J16$(;=LyblZ$lf(e{0>< z;b1gaAMbza;?wq%S9h~}7b05r!;Qby?RAFE!<_?Dt=75KR(p)Q_otD^Z3LZqU}~e& z+v*I>uUFw~d)&iHeqf4yTUZMZOu-%OJR1MDitSM=m94f$=i6JYH9nVyTpXA}ci|=; zG4Oae!~FUV5c{3Z)l&!dfnocA;`s4ax_hPtuOfWR{pD1~C@H)(E#tottFo?z{gL|5;IufCawdp7SKejD+FYBfvb09N&$jC#7Phd_|=#dN2Q z_Py$l14vm`&xu&5CIu*$n&;*nRk#bd1BHh%6c3$xJ=dhhwTD~#!MXM)NUMwfuXXwe z#cZ`t(_pelP@xt4`fsI)CjGsuaYYKDNS2^0w^gjC5yB$yJyr%U09 z1T+PRB$j${g<5`mREnNF4KRj2V$oRd4ce+NhT5>T9R$@X;TaY}gTS6*m`(ugR}Vxt ziM+`O6TdMAO5MePNf3XAns&f5U70a%R>|{uANr%#Gb~=2p6NRNkw#4Ci zA1#XC3s#nRH3Gu&@I>ICD6kI<43O3jYG6HWL^?KFibEA8eWd%SmR)=zYJp5rW6}CZ z*V6(eb<(VC&OZGE)g+0kWA+iX)&YSDmAWTu0i`~HLZ2WpH;9W9Nc2?#jmMHP(Gx0f zwAHw|R=Ltl@v2H@9+d-d!_Mk~ST(^PW39=C5hjXkM$M9|5YTIuclQ@DLQ7ggo% z*cPaY-gT(;`YDO4fHWns&fVY3o}s{m)U+A<7B+WC9Gts9k+cq4Qkv_KmAtjVHZo*+ z99FBleUS)28~vDy$L`~??)z?AH*_05Cac*xzbkPaP^W6`y8Ft1i?3($SxtgncmLtP zC$5FolEHLt5M?+T@~#HtRt)#HZSE2Bwu(b)wXP}5aiaWGGFdRfShb2ok>LX+i{}}1GAFUalQ}pGM==Gx!ix(x>=Il#An_v4R{~Xg zNd>yKiRfo0$Al)0NYKg$U_uW&>*N!*fnOP*gOG0xs5@3#OY93Jn5#oDOvXt?2l+QiQg+|{yFdB(m$J09 z^7WP001slpT?)5-cf{lfpx5kjgl1zPga>YRoZ~=2vraCJtvvZ{$bUM9BfAB8AyE^9iJVY3Cp~haZdSJY5;=~O+P%=-BsX-okM|h7WicnQICp=K z?0r1>a5dY|sE#Bf#^^|Uq!pz!@Fy@~3I5yGh;HIJO7lEA5eIamqB2oTgL>c2DsQ$& zXB}di5D0ig64kHc@BxP}Na-O)pV1TyG|3p3+rp5SGovE=0^P)tQ9!7@ffcQ)d4{GENvX>=sG? ze6pIlS#N&Q0pNXCCt{+m%`!wXO_leu+ws2po|KFP>qM&ta7jCE(qKf)wuZ)r8G`>} zmA5A&(Nm73gt~go-Hb1O+8GE#^R5!0>??6|FN~<8))yWCWkgAvWr7hkt4%az(kUY< z-|mel@_p-K3upK+a~5$Wpmz}~WA_|X5bv?bnGgxTEC5l3kkB(x1pN2-^UkLt#sYng zbWblWFP7?sR;ixN-QisC?BUaU^n~1uSl0JU{R!Akp(n6W5Ia(;FXfh{1+gEcANG}M zxaHJhA-Bx<5L4msVL9;4pvF^Y94CY4{zS5xTckUDvAepljQEV>$Cr_e01s}$j6~@9 zZO$W6<=cURkG|#cIWRp5pZ}+??b4ELJ=dsL??iOQo~geCK&Da4m#VpRYAMIxK8|mQ zKv_x^a;@TtEFv(1ov5FvrE`lo)88}o1jN!AZ#0RUhiLtADElK{>v=G+Sxw!Eic={3 zEVqnLVD54rE@lCrsg`o}$h6HgB0(c2$hkK^hAXR$MTA5-lQ^EKygM=k!01Yo{RU4U9 zRn!xLLd?0--;#3d@`zErQXPHIEh4CCsnn=55uX?66sCNGCCo2F%~F$vtdY;d!@FmS zou(t(p)y+?MGePu0+C zhx+r09aPXQeJ3h@)K-z5;zm!1q>m&3)R<{*((-1;eq}M8XvHASCxglGg&-e;qxpay z;+5n}n8n6ARU-GtdV7`TB`sC&AVrb_D&+XFw$y&1d?dkq7YXKIK@7A&(!b9aS>`ctU4n!@@;Ti?3v=l1j~efJ)u#0AJFPt zkIuK@%P*K;#7K`Y5@eBlhfRWawCr_$9 zJHyK;2^lS;hv#L*gA*%G^XmNDfHP!^?p9J(1z;hSzsOjEj7bfL?Tfw@a%NV`kFvf} z*(~?#Mo=cLz#?C+<*y|C^6QESp&(1pgk4(Q=)k!|qvJvb6fmCDT*1=Yxxmt0nbsxB z#6*kg?EB@pSxQw`ZR&?<& zux})+wuBJV&X97@uVE{&XX6!k9_CGf|xkb`MJkvR;L=0%s0;rk0Xb+aBv$ z&p@q**=i~FV{>x`W(zvh-eT=^#iR64_^zWnDWH06M4^?x^iplMv)F38D}N8u1T5(%#kM$9+Bbv51WKBahbgWXEVHbt?GP$`nv9 z1e&_AlAsDIq((MAu+i2?iowSKR#lG;SLN3^IBcD)Yv>eOKyzU@%VZK+s&PEBXKEoq zh3tT5A2!2#rmhUb3%2?gPYa2uZ}PaAjwtdyQ!jvim%1a{9^Rr)O6VBpHty+lp57n` z3G7Y({WpnKh5YXt)3_~pKn>sLl?a9LG<^K0z(*L@#cXpp*g}L1BLCaHC613J9q|jE zq;Y+VXt0%lN~BoWI(}>NIygU}z<20Lk-C@bzd3n*PR+(?qbaE|l+7)m`KOZC$AW9t zz7@59Y)7>zMYg=ovc?;$AKFoM8mTp$P3)PvXGis@Sy7id{IVU_l{vw=<(DL{&Fnt8 z(Sd4TV_WFr4(n=GkrEm0uyU4<=1tN!cZk8PyOz8zl-Ou6%w0eZ3DNE6?YJ&k(x^; z;G<=cY4k;UJ)|@1(x!iu;g=G`jQYOG_0=MkN9wH&k+y`@^>-()3JKx&2b=|Ta(i+; z`F06+Q!TcCal3iabpOWDfbBlZJlP} zJCL?UNp78J)Nk@+%G|7sdDK7S;pPlV?1Db($q9di%bv4i)2@)k;v0clI}r3EjysLf#LxQC8o=ul#%QOe|&mK)8b+fU@GnIenhQy#8Pz^d>z!OcW$ z_%!5N9G=!GcmpncKGXT*eeyFd25rdT5~lU9eDF}Mq7Drx-7jKP9E&1vA;N)Am(GZN zk3u)O{4}n!uC}pskecsms_31w*7guC&~?1~$}v%V#;^xY60R2rj+Ez%JP3J(yM=>- zerq@$cV%P}Z&^<3MsP@h`!kd#i?TBgkxz1P;UWcf!No!odbesUa7Bt~{jBO?fD*dt zdK*LBt{ckZsXh;TtGl_?WAE`dB5>$^kchqJUeR45gQMp4Au>63DOv;MXjCdbmwh&W ztB?ht>CA&~cW?)mbO)*(ypt$BuxP`xh1ar4r89h!UnbYj8`U_tRN(jhvctq7B0qa~??QoJ%9@fvOq85*fyzh+z zDl$f{ir}M&sbaBzk*crJlFTq)|1P3S)FZxa!t?C95CW#_@6_j(kD1fV%j-3#{d@qc zX+QhLh=%p>69qyn|2YCw?73;&D0ootTm|=yR3suf{AP8rbWEr#^C|$18TpS9%}9|Z zeN$B(rZM7SV7d5uL`^Nhq$=9Jy5uCqh3NCGUZ;O%yup(5O$A{{4$p8deWxnLrCN$7 z(qqZo{*WqdW#M3J=+E|%&ze=pHzO$2+=ea`%>If`K&9sD^&l@K;B*+WH$vci z(}fNP4l1=q+!|xojN9_W#VdDdl_(LjMBF!tMls$*!rw%Inzzwd`+h{T1!)arNJVRH zdvg;379fa~#^)lC2>~SW`fZKnL?5XU)>>QbA@UVsd&ox7*CG%wPalT*>eQN!sJTf# zc#b@Fz7ADhhS|d=2OEVqL4au?^~X(wEU??y%$>yuCOwIknoFI%+{UNmXxgC=PuLpQ zf|MU;iD-|Rl1E8O{7brp5;|^wG9l{r>AZlflP^GU40AwhO)@k-3NJoFGL}m?u-S*- z{}8|HG`%b}FD5&qd4eoWiV=a&i&vyKg85z^5I|wJ}ij*1G3pXX^y*J24WVwDfJE z>;Rz(m-`M*jyfa?`@uyzy*bJj*iR6})PuwG-MLvFpdmHYL|_T^=&vw(B--FROmd2u zcsVhSEHmWkhRD;W*U_guj2LkeMN{e~qjww!QS9Q(aJag0(TjV~F+!c;kVlnHfu>Yv zd{GqPQ=r*tW)sN-^=9TUA5ER-0g!wnkNvag!~Kh+xQ!R5e+46u2z4w}53{2Mr)8Tr zPN$h@^2T|+^Ra&R2wQ!xhcwVYEpH45=XsMuW)@3=fBJfI;2pL(bY@@JL4Qc&sHrIa zy^ZbJIwpfm{{g!jIW*`bBQ)}QzNDGjRKtxb!47uTBL(&8f zM_>4yl>!N_!d}Ce&C<9JPdr+HA7=^|a_Ep}sKM6&V9Zkn7(G2V#q31?Nc8E*8Iql^ zbNRLu9bSugO7bML&LghAg$fh`H00l?Ll8VJCnCud_LGJ^gBn zgF@0qkiCJ8=PvxaZ`XHx?T&Z<+-sk<_NS#sPHpT@|GIL2{V%K!bE zw;`b>f8YDBzxm$GOMmU_AO8GfUikS0bmPr$M)YU)N^1A$Gd}SbU;Nw$U;pOSTRymN{`WuX zIIrgK@4NRKzjNDn<-YQT@@J2I@+04XYWWy{|E=bcXJwwd_nTK7`s8g7`JFeOcbunV z4EF8%_(xv-qK`Mr-?(<|YsU{f{o{X)L}vW`T~GSLe}8iQCGUH~k$dlc)GI&yCyw(K z{yuy{<*MxCU-v7|`c@{>z6>KlHi(dUoVEALj3m z_}CjtpMCV-RQFtX+c)3-XX7H0vmsmLzFluU{cAt*@-M&T&dM`ivAno>H03xy%HN;( zqigSf=~r+6zHi=AcqgUxd8vMs~Y>yFT#n_gxsj^2Pu58~=6T3)vHIJm5G-`TH9# zT>q-se&?;rzYP4x`1>2?ulTc@p7=|( zkN*4Te*Z7u`fI=MIGgN8?JFjis^2tYDzwy@} zc-e?Bs`r^Cq`iI^B@*7j1{qo)Y_KB}RZVUW9)p^1-_sss$(?0$? z&&l2Tf?r%gB0v8Aw^#qxbAJ8t_g?t=|NNO>yYiOrzX#*X-~avI*SVj6`#-+x)VKZm za}VzN<-0zMb*yXORS#zn}VmbMr^v^v+Z7JKXu*FMsy^uXdc9k>zmTuIK#27x(gH`@Qy3r7z>?Ua{c4o`J$w|o1S#@l!xzulS7k5l0`};s*vfiEYR`x`7 zwA(Kc^ccqG^r@|0dra1SG~dK2z-WI3*TYWDOrI)A9?VQ1oIW@^dw6!{;Pk0&MAx2T zo91#LT1E0I3fBdfR}rK?O4J{{S4#vBM}c%H zUk>iE`E@xEkzt7U2F_d#T-X$J2bTkpl8y719U~*85n1oXbop|s5pDcE7&>be{p)p4 zKNw9RBwyq-C3oB99CSD#Hlp!e&Y|(Tpa&_s;p8gPklxEUvoNgD#9dCVut$-c9FrF? zvAnFq;X&J>;e$h;H)@K~=ysD2+UVlw6uEz*aa~RxU)UaZdz3wMGLLE9IYq(3A_6y> zz8&=SvT1xJ>cUh4ZIk;0CwqGntj6Coe#zE-W`a0gP1Fbp<_s)3cpNEaKbmQmb5N-} z^5%U4KKRot2ds-Ej9jHxwxfHNTpZLOp6A7T@(2>Go>9Y*5z%B^P6oGoX9mOWcw_Uy zSl>i8#i*7pfxDz46A7=Mzv=Dqc+ih#@Fh?J^XHO=nvWwc2PKp~Wv~iN2bQPzALyLk z+J7tl>2B?(-{yrNg!C5Ed58AYm7zl{Cyr{IHl9R6JEd`AAX*EtIx($o0c zK>oBB`AP6#kMqb!zGeSA|JzS|&+YlQzvGjG!>``=A%Ml{on-mmVP^O=)4{E^)6PHq z{fT?N^n&{~(15dcFa6!TeTDy>``zZNa$jA06Mehq?_aU~l@~ZK*u`-7ZSVO!eU-o7 z^Wopi{Tu!Md+;hb4i_=pJs%cePUweS!7m%PpoMFK^X3P^**rv z1rEb%l3t+bz2^h>)V{j*3iv=A=g#Nd^V#SAFZSL$KB_AHAHN|GVz3ZE#U2m~ijagz zi3sT=kY*B!ijI?HAdzGy&P*tZ8Wmku?0t9bWpynpww1N4D0Z=~YwzV_UvWj(hJ4@e z=bU@*+`0EohTYHa_xt1by)WkG@Z9%#&U2pAp3@&0h!n+1ir|uk$qtO0h>KVIj1$)+ zxSqgogmEa|6NFX^7tig_G7f|5Dfx;aAfr%d7-TUp00tim@qR&E5xid#7jLUMOI)Ym z%~9DA28M~SM}@Ad=@KqC!8Hi35ym>w@Ec+L9q%df6$6>ZA>w)uE+*9o8L62rw1IeY z{5H!Ng7??*m1AZ>aWO|?fEOzt?1xucarB4Z_+(HlvAi|vi6 zxj*ZG_C@Rm7!A4q!v9xk8vjt=8}XL|mMciWvj+~#kTk&GV*GzE{GEfp7zFPN;_u%0 zdo2E z!iD+zN&H42ryE!oO&8KpyGr2VoW=-j$2E*y;L0*)!IdMlC-By6Af2wzG5etzl67)5 ziLrdgQ_p;chgentH{drjsR}Ut@Gl3})zg<$;){zVo8=$8rM@iw?55^-w-$Z|Y)qO~nL2Ul!a`bk_bA?!m@I82U^8*e^r-;F zd{9K?;Ws`fAblu5|IgnT{P>vP@5c85`hQHnFYs$lNkNxqx!%9DQ6@E+%SDa(% zLOZv7V2l$WsCNj zMN?_|DgJM)&RYH4u?DQkE$6L3M%vQ5?do$ZlP=LoT*j8hI1)M=!5hXi_^Gm+g}_I! zb~Uoa#VD~LR^VqorP`6L|0XB&)THmp30()yGm;XTJedH8;&*3?gw|U&d6-IyMmjlB zCnJ%k=awL`(583Bv7p+kZDvExIBjcTaq+H&G-FF1L^An?p&Ee2Yc!)8*cnof#Lqud z7=6Q%Gr~~a5>qrK*!G~1H7N|94KJE$c?xwyY$|vqJ|t8qjT**3)aOS0n7U@#q4w>g zj%VX9E1Wv~#o9Gqf!en}{x;z6MEnJxKBmKA_)Af?;HNSvT`H5(m1C^YUxyfXYgdl3 z&Z033E8IsG?Nf`!c2@CYtE_ORTeRO=w2Lj;?=0FHi*~m~^DYR>{?mdm7>xhFE(mx1 zKU5Ghho)Z;6n1M0!cPB9L11vsf zeFr~@z!*(9jT%AY@`_OPP=$OHf{bryZ1xv-P|fTIXQ8e%`}bquI#p<}?v2yLRS4H; zaZQ0sjqS{UYcHWSTVIhxvNB?X^rw}NPSExdTrXUQ;5WiJ9&h#aWVjTUm2k1@9AON^ zJK4NE8#GB|{N=+|Z8VUK0nL+Z@vBYjLnrjYXNKbT;)D_z=QVrYb4n{4OXno*Y$_=% znSX@Ql*lcqNB$pi9FwnQrT$BkT3E(!G=BWcMWyOFMFt3pi$&(*Vn?vj#_ofn=GhS* zZ?%5UBWV|*Df$6_+4?1Fk(yRdK3YH1B)S6OvwzBNGx$rZ$bfYJbhxo??h9yA)e{T! za5LC25aT8dql?YW`O^6P3$#3ouHttS8f9b%q_le2tE5zq;ir0s%#*5jNLP+=CcdyB z4l&NrE{q=H|MY={r`nZcaEwRM$}CzKF2ygZT{*^$a52{nF>cYW9OD7Fm?wuA>$EG! zco{Cm?=|g$ju56QZilZ=?uGs0>V?6Z&gsmlEIlKPJiJxkYah6F1SE?+Y2Ei){qTCP z0zgA1@k#DqQ8Ck!GL`8Et*mjXm8tr4rjlGQnMz!epY}(Zc;=@}m*r#&lZU)R6PliN z9#M8ra^h1S76K~8O#GG%mG~Ecrut8Gss0mPIZ`AP?R@-S(O%H5A;!xVZ7p2Jdh%A) zjh7ag2#HU!7Fk(UCTY?1GYH>UG}L2i(Jq>z#d7RLj@4uHM=E`-8kT4n=9w(sRiHQYQDu44SMuro?c zfMiJ{_ZI$VH*^*FpZSz&hpBTmboeKYB5CBt$NbLjo0>{d4I#U4B}wT=p5!qdzZEI0 zR_tz%bmNfic1c3tLDucTOm)i1lu0qv>XWr;2B~^*W=FjpjmU2BDHo9r@VJE39NRrm zg2{H}98(AQtaA=!)>Y83gwC5O6}xLnX7r#(QYlk&_Y&q9v(#4WLHhqUKv4ep&c2&+vg^(?@ym|GwSu7rO3a^$s&htkrV-rT#1Mm-&>#q^jFSm$Fvr$}#TH zUxyg?XjhK$utj^!qJ3h~zOZN<6H@#*MWgujTD0XBjTWrJ(SlVtTCj>n3s%u+!73Up zSVd!F%ArtL2U`%ZF?!I2yWqdR55G|}Y{0XSRSbg@E?JiUWRK)$wp_{I_|yCaxa5S(j$Xgmk88h+j}&gSG7~# z;-bcy#6>+(4_U@KyyuAPQM~7h>q)#ZYJ#sD@IG8zFW?Ou3AC5-#+V6Qui;J2Wf^bb zeU!M~!~1A)eS~*FT%Y27jJUqUJ1DM=c(;mc6W;CO`T_5dxPHNVp}1IGFA^6!Y#ria zhmDpt@*iA_#l_m3se^hPu5NL00Yg|^oCAr7D-W(7agBlNIB~Jndr(|#^`hd+hpSgy zMR3K%#RURO#WfACCE_Z9i}6GLgNw1sGOFSFMqIUU{YzYpaD6W>^jM64i)%hyjB}Q; z0IucYItDJblgNK~pCGgjxb72I7hEgE)dSaw;)=s{lDL+^b+Witz||+NKDbU1*GjlP z5Z5ZWP8HW#aGfTu^Wa)3u8ZLMP+XV6#Z=5PE{E%5aa|49|A^~)xM)LU88^Xoy0~tI zi|L8{2iF3v3D;TT+5i`aG_s5r;5tWK zFT=%N2J##= zT#azuDXtc{{vxjVaM4CY{)6joaUBEKUE*qo>mhMVxYkajk^w8F8(GYlFDXg6mmvod?%*;<^Z~=f!myTrY_0a=2a;*VS;n zB(Ce>`n$Mpg6m~*-3r$~#I**lSHyKUT(632EnKX#vWy4ddR<)W;Ce$`kHYn)xSoXT zZEm6~u0N1XHu!fk>jzo8|>ZBwjj+!mRIKWEOD8r@iR*2Ce5Fhl*q^39k@Z-19`C%nWg{l z@uyKf55$*dab?355Enf!7S~X?mWm4wvH$tk>@$?`Kl)LEkHr6M!87$YFZ^8LO8ns# zf5I72$KbB;a7L0c^P!vz9KMBYzErdbR?%VvRkY~Qjuz5e9xpLlEiprmfGDP83zs<- zEu5UbRS!Iy_5PzT-ucY1JB~c^FQ51BzUvR~v|qH(t2@>XI<#!;{qakPX6hDjOCNR|K^*$fBdrQx?e8c@AD4_ z-F?*e-_?|!|Naf(!M7DR-towB@72zEc*dt^Z>}4A;wxWv%v@IX#e46UAMo}!8-~w0 z?A0fK-?Cl9h~iH^xu@c~=8xX2KlYgAr-@n;Ugx!!tPMVU@Sne#wsz4wj~;i)N2^O7 zIAYXCM!0CmRH@=&3$T#~BDV}}Fy;m$TPI!LM$3LHc`j}4wM;!NA{NGc4 ztX}lwpN_d=b$0fJN1y%Pr#bJ;eCp1V*8bgCvGW<%Key*zuivpCd!O&RM!xpcfWrBU z`}VrHdxu58&Uh;G{Ks$Dc}elgkM4SGV&=BnjUQC=@0PO$OfS!!lCvszWYaba{`~82 z)-C!qtL3MxJBn}o?I#0%bIH#~&)RR`-9z85TK~`cN3PuR$Po`5_B2KU4p{O25gDI{ z#yxgi;fgi8KK#z~o~4^7EPUm+n-1Gh`|ID{uRQ$H@jGs69yQ>Kq7hd;xYs93SIucW z^S1ZHj}<-Kz444Qk2=&;MF|Fydd7FQKhirWgM%NLM#;hu_S)pA1e6|5KGh-az`0co1F4}f- zOq4lCFck@WwsG;HB$*kdeB)Q#{XJ|GcyRDxRe_El*yqBcA(mPE?x5^1We|$ zy)o1h+(&mAtxt1b%7 zX{WETW~R2}nd74T)HMfuT1DYP<&DIrgoafW`8i}Dv25t3MTxp7x4S4`yC@^r06M}d za8Uv-%5Pkhn_QH~U6c=8l)-FT9ifkNQ5s#8RW8c?F3Ni@N;aElM_7BiC>1WsVi)CH z7v&)r&Qz?4t0(0VkgyT$FqokMfwcdbf*mn~Ui}H!f*A6sG9h~=dQEFV2ZWm>>i*l!n@~n&Um5aia?oN4%U6dnTl#^VP zt6Y?4T$G<(lmmB74!zw)Ip0OO%SCzFMd2aJ&Uo?ENGGMjMG3nom$@j9x+w3vD8qM8 z4y)2d>2*;qby1#nQ8v0L`DT6J_OPVsoqWqvK z+gX&oMj7&qv?!IDvW-P)*A(`oIx_}jsGh6xXTDEMz^JazZ7#|SF3KhsW!KRrM^hUI zyC^lFu$jv>@-RX&KDJDbzNJ4Fv&;8WLC`4w4X+mAF z!#*e3zKXRkVw}GCAu}TrZ$8IOKlL%&SG)GbKTco!fs&aqh+gna`u4UG+t+gKix{V` z{Xxm(l^F6YocGWtwy*QFFJeqzW1<9(#V<312ArvH+x4*aMGSl~i;am&o<2Z)G4C{=`yvLu60|Wve6hA-yiWQ{9EHWyW=Q)Y z#u-+=_%gNe)AqAg+P+TIzKC)9VojQv!Fm~i=*JA}eC>-Er>{a#Y;9EE_rZsDST|^2 z#5m(MQGAWYoAFw)>w}AIUr%da#5lt$5?^M#J{){*Lize!`y$5a>tON4vTT+XJFF~b zTRg-#eN6(zj@L26f4SfGHCp>3#u=~4;>%30`lDChX#1L>eG%gfYl`?X<8|WTeadWK z^RzEwoW7=tFAmU{sbsqrYhT1TeHDu@GxyG1@;V5n|C6;ZVw~|hM0}0Ho9Xq{^IOnf zn!c{nzKC&#HBEe(@w(Eud4uii5$%f@r>{fB7fU3=QjZzd+u9c~iuQx15T__ZSgGho zQFeAv5@&O!1DBbhbgR7NsgeJ-j>Rz?#?EI3ewi5@)ptI7gX@eLg(ZiVHkQt>!7(Z` zW=zC?=Ij3j0=#fMpl+WJbcBMulgdd9w&H%&B-+AAgjaXqc9!lQ9(*3{Z0qhZX7C2# zhA0l$m&x&j9cB6y7YgCpN>)(PSXM#7uy;$(sypV^u>q|Ho6Y!{yGBZqKf<^EZ0#)Z z!{GWd92VS(i}YNG`GI=MP!sb51nL<|O>7=cCF=~gL~%J%H0I`0Q(dh%>6-`L0g+83 zE>6_yaRX{__>FZXdPzwg!cb zn%V7O<6J-e>8KjFk!e0A@LCjP&&O zc!Z`)1eTNaG+|AF3o*a6v^qaOpW0=SYN291N`>Sh$XT{X?htabnXBk#!Kg|HhbqjE zAC~cGhB^X%44ptosO~&;3pkrmM2J4$XEPj>Sh=j!7HsA45=lWgcvQsR^+%& zmN+-8TFa6OR84`X@kkVnkedgxQH}nlsv~OC8|#2-wvD_8R^k1!md<;SL4kv9ixn|xscWkgSrwvE9KV2 zY?7axW>Hi*4A+CXMQ}nI&}O=VR}kKLSrv&&weFdPn2a?sbzi!^Ki!8_O{}3OcwDca zFi@FVW$N-SMFP6=`OMlFIe9MsxCytn zE0oGsY6!Q$hFR=VfK+-gHPj8J?$3>7i4ByrgfvWWp~7?|BBd5wSg#XS zE6ThIek;7_o9Ep=bi^bism7@zzqm;?;pV|8soKuFDwQmu0IWe+g1dstefT(PH*bto zSh#f?CnC52R_A~hZbNO9ttQ4L;OK$KT^=qks`6lsoeE`F?4qlha8GZ41_)Tf7AuPc zqwVRyYhwL#HtWK)_$u&Wy`kuG>#iwh?CW?i$NYIkmDcx~3cC{Vu#79|!R!!tQ~>y{ zQX3~};|h_|o}RAdsxE>ucqm!SDS(NW@L^*6mO=tmDRe?By~?6D*Gi8PnT(Va&{tZ! zC6&TrhA+?*MOY+eb?orqU3R^(o`u#0MOG+B6_K9M8r*`j$CK=4FTQEQ7<`)XLioP5 z3?-1_$|OZz5Cx}=*6lg2i&X8qJN2BrlY7F+p-aH!IAeB^m!?$zTlA#Yyn8;x|C1*|l@RiT-O$%(0kWm8HJS#i_JIPJ z5-wUt#L|FQn~7w@n^Vg}15Hbmwjb4}uCNSmEtqLT`)Q5dRK~QmWe!E9CulMEFlfyM9#ik=hukU%-qx)<#3!?srvem;W_lvt0VEnq2<1?gi@zcN{b_7 zGJYAzYiy<|vVr#EU(+*WST3d5h!$z<#W_G4sI0w) zu)bbgU4;PEdxr@Q9EmdP8Rkqe@Tt-Nf&<5|9p3#zS82{}x7p74MOB+VP))*sxMLSy ziX+xoXG<*Yv2BOf=2Fxflx0S~gML_PrG19FjIaml3#q0V1r8j77Bd@~ZsED2uCw19 z^^z|nFi+K8W`pErLmADlb)DhPZfLIE8&=*G!N7X5m||YYCp2`yF7NMZM6VpVAQWv_ z*xVKkg~HxQM3`WyD_udU$k3+uL0H`mW`NW@d=VCpx=^@R<#)5f_YsIPYt^NV4=xi` zr;XSATO!TNW3Y~vr|VHtCM_`3>YM&bCsjBhtV8YR^-jD5Kyy6O;|;QoYI1)@nPFK# z*+ML-eisCli_lfI1jYLSSq*8VZXczPlm(;xC#D+kXbyEPgsk3~UggA!NQykK2Nuje zgd^{;p7a`u&|QfXel)@wywLwwy$X*oJn%kP)jVN5NcDZJ&PRGorPa{m94;SH$#`^I zT|gw7bJ(m=^?7yo!-ZG1y+;~R!Rn)#shwHL{oN{Aen1IDBv8f4H<7eZoD;&_RdQ|0 zkj2*U=w`TsHqBhs={LLkEK znpjB22kPyia5YF}joG_+OFDtGI%uF2JsLN}<|c};dvd4&)Cfqj1Rj%i2;)EV2rDlQ zkE)I|2PPnxN2|;ptghrtU_zbgjJMf&hV9iE?20ThyAUzcuyI6LIJ&E4m2 z^P@nFkF+m)ft`}H=e(rEv{g(qqQr$ju$C#>A1W|Uxl!P{sw%3hbbTwLyXpyvfcs?6l9GuuQs#DsmNsJcqlB_4wv8o?^|NPIR+g8R zIM2|5A`~LOyuPu%thBnk#3I#~l+~5ZuC1z_S(13rj`e+VS!GT2?26i1CFbOx$qc4) zRc(EF#jMiuk{M&lD_ke?SUd{rsw(QrYG&1yL>61bqUu@IrH!@ql^|l?$l_XCQeH8; zad!Fa67wLR83l7{W)!g6Ql|fmBAn$T9-4~0wKgNrl+W4JBsG+jOkprh6I~w^z0ikV zP+Br0zqF*X)ZMTsk2b*3B&v^;#6dQta1gZw9yFV|=RkrTi05ZBFwc)V&=lY7z}1k7 zUaw~d>L8neIfyzC51P%~>!2Dt46mq_;$5*oFp6HSc4N3F zw9J@raDHCmQ!u%(sG#8BqNz@DUO|5Tq)C(V@(QL-o?K8sAIId>W*m_*`t$V*7cUrK zJfT-4Cmv?P#hBmWH-@Wl6Q7)+j)OM%>DIe&1PRvNKK8i+a#?7JF|w{MqE>%+Z1y1L~j}O87?`%KfY&y-{HV~tZ{z%c^U#bI3vS24kz{S@ymbQSn#gK z2oNu?{E`he9{~6HK*i55zN6tke~`kY;@1vH6L5dYQdmFvri00t!5Ky?eti7&cMLu( z0p=Cn5P@eneqQ-+80Z(}C=79YyyBY&$RB}we2Bts1DqGXHk6(H;;`0n(&fQtz{L(icJT_~LFvQDCK5k+-2!(DR9#D?Q zFMWA(<%huBzK6o)0qe!@Q7HE7Ju{5E#wZ-OWq75>JkWRCFT?1?oGhF zHCEwrf%D?G6!bF=$S^kJ$Hy;yuLi#f2WA-0AEa=8@n!iv+dkV!czVgl@_Qa|mrYRo z{L+{7cQi(r;pN580Gp42`#8UUeg_sPOe%h?mJ5L!U)VptxW=U7$LxLraOX};&950u z{sGMXMGEJazU%P09hfnb6wa@`r2hV>F{$KZd~XBpPm@#2M}A*xOe%h?mcIw?rzxrV zaa&c%RE0^!uMd#r!2MXPuzvA98%$2Xz0ujz6prA_uVH}GeAFF&M*>%**sRkm55p?^ z=f`}y3vfGDDXgFVXonoBF(MpZUh?sv);8cyo~iixwX5X!y2hm9M?36&;C`%5&2M`! zX|7S2RQy?~oI5o}nBnEc47$q#Ac>LO#>+yL7FnLESoL{}W5In90COe>TtiQbE z+aL1n3ru}b;r#4Q>Z_k9NdI!2GZf z<0kz0`0=YodfW-jPn`@U!`Or$^Re^rP_OjTGK|mg7fc$L~_$o;kmNe*0XYF#YkH0$kUHsrfNqJ`T*Q8b`EOe#ys& z_kqd1Sn=~qk2UZ=517H1*x`EdWBn2YX4LN#Za?_*%Fnc`Z~VQ&z$uRxzmEX96}a;* zS6ILLr2rg;UC}?kk&v$(xFfGpSigRJ7x?XRb^rXjP+y%6+&9-L>?rv2iZ9!bLvDaQ zi60-n^L*O#I$$E9W71po3@p$IPfEjwb!uhoyW00{<0_NJg6|Mnt zc%=u&m)72!VSI-lAIj?$-zV{T_}UEP&A-~=dhy#I{%h{T_%42Y`1azr5+6f{G&M$qh#^*`Eyz-*L`N=mF{JLIJ7&ztel8^Sr3gGVkyTbbA z=X1be`%vw+#|O@;Hz zf4p6&2AG51Q8+*Qnf&&97xp-Qd{XiI2$&~7NX?J+=_4Oz7*FHJhi|X+7=aHj1M?{x z57U;!Kwbpy@Xr+1uYKDS{NB`< zRPrqYn;(HY?u*p?IKJ^MFxz~oaD02kcMU!a2WI_O3g?$!SiTDWsW7SJs|BP8xW2Cy z)~|d}zBho`sBuJl$;bNTCt#-kOY!q7zk~7lWnkX?R^ga`y!dTGL=N1PVeIvT!ui?b zjPLnBDh!E4FIt`3isjxZMEb z!tE7~=_dS=#+8{)V|N%}6yV2)QhJ5Ua()Of4MP>qPtPUrf3e2EDUTPwo51fMz@0cu z@$)O^H0$>pKEPNzLgD<{!H=N7&w+W41}L71_}O}~`;E+38+KI~;`n&U$9~WAz&){> z!urLR_3U=L4={$~$Hz~9T<)+3Fu8lA=0~~b0duCt5$z=()o~>-ckZS5S>-a}h*o%& zalz_5h2j6@8IbQd1eG+l=Z(Ov&{+B?8Jb^`cvvcNEAcxIm=U8CPgS1+m$dGN`6~J8 z8(Ok1@sLt}C+-sPx>EDA!cF3bZoKQ+s&zaGhoh1a)9p?jrpZ|1n}quaAJ+nR`Dhhi znNOl#l5j1+y)tHialk$br|dd6j(YwDnEmw)DXKnj<9-2~OMtmxtm4P61Uw62a?}h0Dj9>8M<0l{Ed+dw>#^3Pc;}>7{|IRB>7y;tt z6%Xd4>(anco;7LUSa08-29ERlkEVfReg94xINE2Qr-9=*d}e9?dZArBIt?84QkVvg zdOkD_9LK|ErGaBPYDojfdi#hpaExyt4IJBxNE$figT6FyzX$HOE?kMLoU?rFUDkiP zEdZ{;g>&<(2kw?MaCyM}=)$?nZv}9>lqbvQ4z~-qqtd`J9#5r#+a0)lXe=f?Ugezi zcxf8A5x`aY;?%Ll42rnJf$P>-N+97T9L-DI9{8OC%#|9)b{aU{9@+eu|84?itrMs7 zfsJE+egv2&`oU2zF9P$G##!=7`(g8AJTfW=7(3#}$HFDWV{d#L3rwxXrHaQ~U=})Y zu6VHC?g8d>jbps*bhG7SJnjYN?;2;xmlO};J^?1PDs?Yz-&eqF zGc!ql9=JV#nVJT!4w%klTvB|gmlJ{coyMg~kL!TB%ZYQvm+A2!FpulwZI(K503I33CvQBv*M8?-)P`g z19O{`-#TSK+w}|U-Fty~!ijUqNBiYPVBXO<_UF9nE6Fdw44tL)V#$|Oj))rr%#<{6 zwZI&c1}+ZFs$^V}Uf9pO9GK@dE>*g{4$NmxoJ%jXJHG{HTYb+W?J_UDFx{$wY1cSE zy%4tyn2VBeN%7#g*-gMau5qd2@d7aKIdQIdus!-5m@OKYsy!;G9e}k#N$Hy;AIonL zm=iQEm3*fIbFmZWl8<)hRluy#INCE_dSTfzs6beN%;^_O9I-w%%bJ_KgxhSc)a0(T%VOVhxu2Ikd%aMQr= z3t;wZOdT$9hXAuQ4cuyAp6CZhy}Sub=3%MBrCxRhW_CX~@(Td-n`B(V@%w-nFQDW2 z2aVzX{sb@Avxc~eWExuv3}AyCuY5SUj}Q5k4%tSqmo zs;O*hJ~V%{hnKqM^1$56rb7#+=6imxX{l@~ZE0uQ;5mWPAgoo)Io4g_9NSyeixwxzbFtax;HY)M;BG@eAQYo3cZBoP~G zE9y(@Dw{{=v2yqZzlkW-D-F4@!>A};&>mW{U{R#2Jr-?S(9u<}U?$wnaJTYs(SxF) zu23)*Iw;l^ULac#7c9bw|Jaus~|8`E+#@;FU199^PEdbzPc{jKY4i$-FRh4H-oo5tof^gubC z$K$-qymH)Sj&rY~#xP?{ZXmFvEf9?3#JJYpcqoSM*O=UnP*+bVnn=w8H5l*0;NF;A zi2{b(#^lE0?brqa9ysD5P+CzNh%Ln#r|qG5u(Qj^!3V@V5b22tI36ufx}*KGw=p>P z&-+4=#^OL_a~u)W2g*UL#$bD(HncE~5pxB?T(>8vsdG_B+}IDOF*G)YLY(5_Kw0Oa zK(MPT(iY_5s&WTJtOMy`0rLz`V6Y1(>UZOeC0q}sIPR^1I08D*i_;PVF&v9z9H74r z?E49iC#x8^bmBBvV}D?;g=_gA zIQ1cqWMLi)BW4$PTZE{C?Na})Hzmd5BL$ebRug&`+qBry9z1*XBYrMc*=|Tt3H^wjt$Oz zlNN>Y*B%Pvh}b}|l_@CsfFHHW^~W9*Lw?;0Uf;33%8BZMcw{M#)(spVibf=U1ZeLj zAP^4WT8mg*%0NQc0VqKdv$(he#Yu%GIVd4wo}d5@S&A9^I8~5@#IXW6o+`c^7ic*& zl>|Gkw=)zE)CcP&oBIbGliMdynFyAp*&Ev#3$#Xhu^+kJV1Duig_Z@|;*#RNkj_xs z!3R$jt@&e^?x@(9F?~VZJV-o}8pHTOX4Wmfd}2MJHXJR(6W>xK6Doq`VN~3K))0;# z4oR-?W*JBEjY*}KkgXEZM`fT`e0f($G9OEo&bJAu_Rd9}@t9~k6`&wrGK@E*JGd;M z`1A`4E$hJn`6v!ll|MHVmYQE@IA8)(@k@Y#AFC1XfTO|o&Sh3@j#U@B;;n9}t1WA4 znAcp{WTmiKt+EiJ_Rs|}A^V!e%NMA!u$g0gVNx|Aiyo-6mM<_ddoe#VjswgV$swhR z=U8A8YAeYS3%epgGcF00idWdlP^-ci=OJh^*seD6(?B~b56aB~k*J77{t0Qo=CmKE zt|ihy>LPwn|2z{@f~|i-rS8&lVj-pdlALOZF;nSAjzsDBhkLuxbhib%V6DYt(r%&E z(xsZs)sj&x_OOWNggfQ3CbKo(S$`aq_>qldQWTRyXzK_@5dzelq!C@W_`-EPYRW%Y zIxWAOFG+o zgI#GvdtzZyv`wy=EIbKZXQHRp9Ezf#NqfnF2PQ#E!;x?T%v4~WuR?U-T7j%3$Tlm9 zEjvVLSaskm`9uv)Ms)?l7^+ceuuXbFA`MJ-*~#oWg31hISlc9jgfSiIl7ryI03jwP z2}5P@v_IVPs{|gB1Ym_kdyzRnb&D3GyCPjct@fIVx?pTEt}wMhJAg?NNbLHykU-fs zlOMB$hEWE6*dlHlLKmPdBnh|$)4c=xbRw1`w&qtHB)F(H(%QOQwCP`Hma+&WWgb?r z{$@b5$N4Ubs1K5j@TBIX9v&xVB)njrtsds zsQ#tglE=!>x_KZH&x-YM09w9 zj8oH7qMfPj+-By763={Xg=l-#%ABGl9lmw`Ago!zjP&#=hB*qV4#q5{S!sa5+cY}8 zli1|#=vSLw`cj5KFIJz}G#&R%+Y3Z9`^P0{95IYWOQmud#u{pH&?FmUGe;YJr^(n^ zQiWm3p3v(S%bbPT=zB9=Kaj+%Sr7IUzdh268$Rq5FzqPsMl1;p?q)o4Q*(Euf$7H> z=oJks3`ZiErMW00Z9kCC^p(+<`AceliF!5*Nk-qZzozXAp_zHhThlDXc~<0fhBxz; zx4ON&ARG?vnx=d&&X%shtzycGr}<}nslX6+-2TQEin+%-rJO-IlFRhyom_5@R>7e( z(l*dQEN!eQ#{_{XDeEvwV*D`0}z)5X05Bnhw!| z`6a$TcZfyh9o@mj7%{eC96|pMum=X1oaV$kyAt@Y z>iQi3pJti>_>c!@3jNX?-aE;9*ie|*uN?UXpIG`55<>8qE1=ZIJ}2gJ?epK zj^O^mM3$_`+5!H+1FR34O%Q-Ka1jJB2ANXY0whJ4#?HNfjuj?Dly@uu1BaSC1fXK?gxwCFd3>5fnc<)!$wh42Lg4sg<`?)3?*b1GRlBt6+4-XlnxqkJ*CZv zMz>kJR*PuJQb@Wmu7>8Mr&+g|9b?u43deK_g;kDD0Ry|nNLQEKc4WaAs^Dw_P zvJ5vUM3;8PLhxq>G^{^=&5`i(#^!oywi(dy{yfZ#L>6_SoMOr$D9tZ@+4ZZR0vd6} z1ttSyVt~`jfPMoCg*iT~u6VQLlVPi*)NrVJrt(&{oOAq1;|b{Fc+Hj;z!p=pr8I^Y zLpZMltqLvthT3t_bb$^reDU7J2=7P&S_Nyx-@xsf|cny^+QvQ^#^uKutrue|<4L!@})pkcN1 z@S+C7bZ)T)qpi*Xsu*VZgBUSo8N&JoJ-yE|$$XQB=TNvUy1a)T%}_a-*{{diNTi3Y ze_8Lsg`sH78gS(BVZWZMf|%?!%}W;XetlrUPH;J7G>v8|vtLgY82O!tH4m0mHn7jY zdKDyktGlMsO}cKZd6`u+Ocb+KB3BVw0~5^U4&h8}eWX5!I>E{k zzCfF)>BSuMa3zk-8@DXsz;Dyg=bVqH5Q)5%7fy{aj;^#bc|-duhUPdW$ALYWn@Ce^ za~#^0$R=x;XZnJ`mJZxh({7l(c~=UXJ}^HJ!8i|Z{3we?7NhAxZHc07b@vRv#;6f2 zYV|50U0a%Jl_f37F(N)tg_TQsI$!cZ->>ed3vf<&aX7LxEEE4vjP4T(NNF(h6FS+XmpC&}3Yr^q~g%;4O;jn>|iY%a4Q=x%XoGz9qG3XS6 zYJJkYAW~)=y`$6^j~ZowT?g1x$VXNMZ(86=N2X~LuvI`azSq31$C##hJe>v)&M7&4 zS7_hQq~TjCA6)}Gxs+-y8`9unb^~;F)z?-UC7Q*vThBsgP4Oe!lv zeAl8imeyC+%2EkJa1iyP-cGCyGgnMhHPp8lKd345jDWNElJiIE@{&-00T2i=LP1FJXacGQoE$eSYa6 zh!w+5A_JfdZHZrNxsX9tTm1~nO{(6+&ydgTt+0DU7FZA%XseWQNGQ4r{gB8~SRD{Y z4F4~=W3F$DV#00~ts}~Q*qq9y!vl?6Us&JJf`yeeEj3tac|>J}RKCjJuPOaiHZ?Ug z*)!C65Tv)2(}anO4%vccqmO1_ctdG}7hCZ{JD69Yxm;kV^+p4xiQ*zgm{pET&Y{Q+ zm{3Oh-4a0xaIs?@Zn?I~2uJ-??@q@2+~&D8I*v~XiyBS+u`v~+NA*EDc}-VEXVgka z4@g~5nWN^EouoBQrz9?+SX;DH%xmY+vJ)zK!W??;a|_f0V^%VSWJ-)ucnOSLEWLwq z+`FQNb(vXU21EnAu?eFhSig$K2-#%Oa!F)D&6PwZw5NMv086FOH%>&emqN6;rYaE~ z4K3tiS}%BJk{o2-6JZ*8%A%*cEU|mK+f&Fg$i=)p;3LaH5M57BIGB6LVkQF$O*PiM zVX?g`DY|yIvpbThH(V8562a|hA@(=0@;M}VhS`zTt@E=9HS%hgH9wu~;zB%H@!zU%lw2AHS7)QKRxp%qp1NP5B~L?jrKnPEmm&w}@(gk~&(4a7P+u@K+v zEAE_@2CP7pXG+ZMvt{c%cXJI0m8KduET2!ye?8W3W8HVRnfk(JW&)e^6jvb&!Cj1I zS&R%=A?c)Jvsxq^2nWMSLeVN_+%o%6xAmpPi-{3xmvwqz2K`he$kTW7*6=W=Mid`2 zf%SZmch0b8jFQTh>3K*hh1j00>>&lyEEZcbQ%G-nMsws@ESSQ~+8KQV)bv`vQSd2W zW@OToCm}K@U}kT2MtYh^C}Hg0Q2wIyd|JWU<&)D}TL!14M9a72A?9g%&XGMTTej?# zo(P@=tu~35o=og7F?>o}gT;-_KSwOmik^RwV=iG-x9Jmpsf(SR>6%^TZg!Gn8&j1% zH=~f*zDNR?gZTp?RY?{bP~>t9MfSE=VKAb+qc^;m160xuo0FK0>_EgiLISa;47qbj zAbQV^b1M!J!JT3G56t ziUg~a6C@0N7tLv)GV=QP#QH>Yt}o^y1TZAPPnt#D$52GFw! z^u#fY%JGwfM$od-{q2g9WWh2X6JU}D4qnU4uLbX#l_{lu>ZSJ zDpaMxm9xl`*|`tqd-<{X?h4G|PQK>CSS)MJ&c!}gqZg8MEj5lR%g*iE4cnQ^xy*oy zVCrEYGduStjJQ@=gH;%p(Nm<(k-c$1?y1$*udcA=H9NNjLvU(R*q)!o6@-a`p>oO2 zJ*fckM5P(WCd*_m;O1p-YiEj4Ax^yOW_Sj?>9B2m;y z*}26yXQzg`HAih?f$G`^R5r4#;ccPR;44IJ0xJ5f7!Agk>WfbvL6dn&q&HqafF` zBVxnge-VzTD=%N(hQ^bd2T&a6T)_%cxe=v08(E73KDT^5{e))ubW>#T20+%_yvTIY!(dh{Py&nghh*$Lt{q znv?`sHUb38{V<)k6E^G@7h|_HwlT&cXg@=x=JtNfjb`T#NgG~V98sqRgaRSVqi5%C zvlU)tR3>Chhqu9A-du+aV6{O3cJ9aN(U!Oh{s;W${)>yX9E|xEWU{354zSre`LKiH z;@%jBWNi`3;PvPK$g5@r?HvFfKX~zo%S0$DH#@w^zLY?<&Z07%{H+J zBe2=IU!oqFJF~Y_pI>5`3y@(qe7>EHS}F9(b%0jehK*Ki%Fi$CCyb(r(lS1cIIEUb z79L`gR(9^y(%NE}3g&zyY6UBC+7Wz{u9X*s+zEx4jf`U=R}5oF%+mJPen7>=(|W_~ zQ?(z&GI~%qtcI@XQZaJns#3UGT7=2#?A&)yv%Ad#t`v#JEX#oH|3xsG(a=>jRjPK5 zb^d3l)s<)4I8r)bRtSs50Hb6v1`k45#Ecm$T92H&>37}+qmU;ll%UaM(G*YH@IMobxF`Ctsg&Dpt6=+dlgNw>Y`V@6IFGei0Uu%n&b0k*g`d5|3E-(Y;W zon0VIVP)q&W||B&;hx^OGQBFL`HW-5V0P|P{@;s>D|p^QuuJ(u&ZkxQL@E!71|ION zaUMow(ZQ9%6B9FTO(I3rT5Ro^yPslSl}XhW%!;T^!G%_UVutbj9m2_*+r_P|;!;^G z>Cf&jm?{aAhamyXOZI9r8vIz*jOx#KVS#keSi7==CdLl6e4IxK)XT6W6;4DPR01Se zz!hk-5HR~o$1;OUk4O@Z_42+B5;~jgFI7u>F5OfScznMC=ZjVN2yhAYFArT(6U)+e zFQ;^pC8$TqEsO{xDkcI z>ZxNEYf-2yvJ8{>*}3z*z7!Wre07Pf!qjM>A>7>28*j%NCDT~VhwlP!-`XR>z#zmT z#0RJB1bZYGps1UYR4b*j(6XM=^37FiN7x5X#5T8egfMBxO05LRWP;Ja%|!<>v<$Pg zV1sO~zf@G0)>qV4n&T53Z)@lYg)1-;5?M4|Qs_k#UX89%>@mp))kLL%9DoZU^w-LE z6iJvmO5Rcgw5!iYPsLSrhTHXe71a?kW`afT*09j4+#Fn*Lvc(RW#{H>4I>u^c4nX3 z(L1We#g3S}(sDBH&eST>5i0<<1<6!Tr9gU)nQ-+@cJACXyud?g%u5eq95kfM!Jz;t z(7U?5>ZKLvGPl5zK!w3-yV8yGC?(aA_~OuVskUdN;h`c@j+Hx$#X87zUDR()Y}`*$-qL`{#0Jp8Sf7E)O4e6QB?^0;m0P_Rlz7sSAD<-w_z!( zb%M=8{7Nb>#dw_#k|7#ob(WJ>T#V5W4F2fGj>8<^BqKN~S&BUwY}VNf&$XrT8)%iF z-cDvzPB?40vS1X;BC>PWr9z-hO~5g-P4??5U=^LQZY;x?)vPLV$u@WO>#HHm zimX1g6wwZepWD*#(*omD%?h;}heEpR)9@p+T9VCBd6e^*2n@otWAZ6G_lm9Z4o@r+ z7p37Tu}DyhC#T~F`+KC^&z(7^Msj>^vM(l-BZb)Za$ZMgKV~moJ+e;PVt-MYoP$~4 zClN7@R9%6o7%u08g0S^Tjvr%8*Vv7a`1h!*q%#RmEd4SNbaVQCFmTA@V9?^!2A4;A z{?TovXZW3rgBU24cH)Ax_6F3~sh(`8%byBt*$dR;vEvt5Ru&)+KVOsRG$ zpsTmaAA?nXX)T_<)qc5*krK0NI5~aaqV9PeAw-yaOE6Hom3}Q%(Y}anrRNISJDwS%)0fzt;w{Cm{J6i&e67XQt!JRgzda zmZalTX-5f3bAM7go>*MP9Gj318hctoFiL5_?4J&Pc4t?Yia)zUqtfvLYsc2uZt3_C zjg<#`;=R#OZ3MfYXpW9Z$EO~ekeQ6@Ty?SD48ysBkhJbsx*(YDD33%jJ*S6*hx8w6 zQ>X_MddjRg*v&AAgKS;R%3-$op_+W0JR6tc#K-Ia=gKENhQ%?=2HTftv_7~*7Ld!} z(2;hxs0vHhRfBPM649fPY0!PdxxuJxTZ)+`0LLI#_V3?pq_EyK)-ex;QDmu9*C(a# z6*)v!xfnALWN-ie8p5*EP@<`N3}*GiOc_as0d_X>IOh!R~({M!-$$TJ_Im5P3Lm#?oYD@74%MGH5^??52ArFSW~IMYbyA z()8o%L2x*9v)xB91t~5j5-a1;&wzb{Lc_{*->nEm6f2WsyQSqzcU42uYh$JOhL=>P zd=4G62pwP-(8SRmHAS4*&7{gu{YcUJ$WFl8U@Ok0W*1|MT^NN}T-+kP77luevGsG3 zFVDnLX1%NIacb$ibo{ICx0(G}Pkxz>H#1MLWB8PZhxT^Ns7V!hx9e+Vd88{Mr$q2H z-t634U5HZaC~$VQE_QtveL0dQdGt%Qe6mvHL3@;dX(F@dlFL5x_~5ByL{<&Gu>bsC z+P)Gx-fXeoNZX?>Z%m9A)AQ6A#E_xXn$M)?p&SdAtlm8{%VTN!>y2C9IMTk{)0?Gd zM;dXW=k~-QM0IS0EQ2`7O~+swhiYWowG8(x^TOz}C#tZ*2c-@52Xj=utB_(el?5Jc zBy-Arb{pBKn@7&Xb=ux)Fv^7ad(|;xKdyO{Rf#5yOR(~vN7PnY zjT)$6fAHIc=&>s)rRSX_BI?VAInB7#0n<>GGHv+^rXzIit}Fp`A24ph;bX35=)sK% zdclp1;$Okp3r<|%-~&B*aUV%~W|Lp)f>CVnkvi&1_Y|V8^`Oa}!M+`1=W`pd&#<|r zp|Kg;T58LyrOMkE*P*M`!q@}67}I&w`}=616tSLLE6_6&CV$7=oshB6utV=4ky)4z z9eCJC$`6y6CoPK~*>IvyYsZ==9?nf2?}SLn_g36y(1zk6>g=?nYQh9mpf`%$D+{BM zZrRNw88I7k2jVa37%shtSX5qR@(y5aRX7lh$2;}XQpu;SRv=hIhLeP`vP!Mk3iL!H z%a(KLDP|tnm<%)nOFG6_Wc}ETVUi>~Nq@Q^4zmK{MpK)6ptHNDOJ+@e_Tga-o~cs^ zC00CDIYFa|2Pw0e%rIq5631d?o)jm8BVU=!lF(e{B}d*$1e&b~U~SD3GX}k3IkH{` z9Vb}`6kq$k1?Z1c_MbU2PU3k?GE4rAj}S{K1s6iH_4*JwSfb6X&pMr$GkLgHcJ8~5 z5X?-#q0GsqKW4CydE$j6>qq7%EHOp8U{NWz!DIa(=Wern^r$vYNwz=1^l!0co)Nu% z?Gq)&NRG9Ya<;9Dfyni>Ne(!a$rFLIbGNrN?bHKQ&4H;ed;+$TpAx8S`EMVn8mMJh z-1et*Zf^REnR^Ji{;<&ctS28#6=G&VcA1GHzx4@5XKB_qwPu8wMv@GYFMjm#Y2{#! z5eFT9Id_PQBbElR3Y{BrnR7Oqh=iOYC0xGVWq!rw1Kc!ZrKM>5Df4Rp1GI8FE|$xi zCmMjYkA#-CQ5Py@Z**i(U2}DHA-^z#)9TLg$#9P1!nS$5S*=l9aSVUqFlcHqGsCJ9 zHDk#UTl$kxr8hjg4d>DvMsfgA4m~+is&Q8-WCM!KpEyTj4+J^d>l7u`5$6Azx zGNTtZ)6j_flNGF5+ADO6l)mob=v+&aMdosVD zbwve}WYO8a=K2Gy9++-E*2sa77$r1 z?YmT(J)GS*XU`=ajx`#3mStN2PDh<1odGceb^$zjbGWq0$d}2hoz&e*p|%Lly^{|0 z0jM*|?M3(6B64-CrppjPAqq{p>!o#LVJ;R@jRqH2$YKNnmV>}#dxDz)bX?}ZvU&6W!9)yO`EwwPu)`Ph^ zJBh(i1oA8bwH6pjLzDxGjL~r$zF4hl6h4XM@J%*8&-x>`z`uuw{L#4}^8a_(4c*Nkl+ zA#2Sr_RPo%cp3-G5LgRN&WWn=EOVIz7olE@+Q*$ywN-6(Q>IIaV60H?5^jEi-dRJf zLz>7Y1gwBjSKvftvC%cm*mbRFQR0{)rt$}oqF4K?!v8QvDJ1V=#aN)cBh;rl4 zU!jIG(XXjaT>o=iFYk2Xrxgbxf^E3#r;MxR&2>c5`)SC7-jGnu%h4uxt2m;uK+DjL z?c(uJpab0k-pt0V!K3Oc%W?LED(N^$8+yeArRtHgp*a?UyY`F7IwMKGZ>)C2UeqTN ziV}n?*DjgI0g5;}$&-pvE&>~f`9@|OefAGaejJJ0gQtPAW~*Fs zBWw1M9%5zY*fN1%u+T~xA&xg>=O<7+2SW(grIk(ldxrxBs|=% zdi?D0jP-|ehbx!4X;pF)36Ej&t|iQAU$H%2aaL~4x}vLWsINU-tbh*y;M!U24=F2c zt`wvH9Oy&kY4)Y`kKp*N1E zTb7CSfXx_YbT=!;KZHd<`xUJ;#&(&DPeuKSHFRbr zRb%c=lMPAVqT(@?!Lzie$u?>0Sb)WfV}wz0(GGwK$m(Gg8%A1ts#PNCVv>0JAIVWs z%P_P)HC!}2r-rK(W70!7AfXylOE^2x*N(PzEVnnNSm>h2_s}v6*=)c>FH(g51 z%VyMYL~XEJRr;a_D3XawE3jH}Nn$yh z4S+^y&^MGxP2kM(a zrJr;;QbMg|$N8`vg}o+$fR$Nst^?-Qkn#9-v-dX(h8~r=4i9)XI+vr2u-?LHhmoZ+ zu|flZdC*R5EB`USuuLVLj->`VopxgVoVqexUPm7_sA!b@2`liKK=)X!KN>u>H;!kx zCf60J9;Yfr?JqeRh$>u8$_^yL;!Ma2G)XD9vJ@2wZd!lIQ!qsW6Z^&4g|n>}G(E;5 z)D-9f!%9bK=IA-?qJOd@>*{LJgy4o`+9g!5T6->a?ET0EIG9dv^b;clteDokf>tTS zP7ho^D;fM_X$cX3+|t@oC5-+GMv`~yBDDN2yArJXM2>=AeKDn?Ng&P;_mSn>K;9=HKlw9P(tAP`60ZtafzoWjqQj!+f0 zwX{g9I1E~q{Vg;&KZVv+_6YM%SoR7T#}}wIYpV?NaDCH|fX4FZcdmzy-mISx{hU{sZP@-DNYaqqK%P|o^NatLdOC$RIXoVFZV)ku`< z`e*{5l1zntm?4@i?oU1sACoe{We#YL61_2`M_aun>!s2|GEOu*=2XM8*_- z5h4koPHrtQx99LMajoSZ$Q)Ka-qtYaVarfs%B%nhu}kX6`lGQI5<#xWdeB|0m# zolr5!$qzM_K~BSpvz&H?R$g6MJ{zM_EvP%2W&O_-v-UxuMKE4RT$m;n1fu;voHc}4 zSJu3MvaTpRGY=091(r47CNvqzRf0anUsnojN_7^hZ746TRhdX#Y)*w;T!3gP!%&tl zv#wyAdc!ygNmlq<10S4;X86?{e!+>)OWB-~sO(L#1!O!*Isi0@O^cZNqYyauv%aOW zsjjBExu&6B{FWz;7OBny{06i&&3tyNqnGQ|@4;9MP8@2N67#7lF=kAw8pN2SkXB90 z9?CyxFtP%Iamnu9TlW8pixpj`$lAm&mFkmNWt{3^yzC6nSkoxOk_}Z=(zNg^hx)Zu zNNusTt*ESPpnPSe<+IheFk{>qY3*GoectW)U$4_RMAG}L8kH%bmpRB_@l{@5uv&sR zwLye8&*K;#=KL#sz-o!4tZ0{+;){K7WGYxa=0k0S-PVR`qon=(yWdx=iNNJI7~;gj zYV+EKO-Qh1+wcS?+<2Pt)ivF_=baLoT|Z&^u)Qwd3B*Z4fB2f8ADw<;<;KrveLVH; z=YNK7PZs(^jgt>4KPqSQfP>$jKIqYFmm0>4LVx4=^G zYiP#0y3;=EUHkTm*&}|sui)lCRN%B+q2IID=g*9)Kl$OSCSTLH(^=2G3_e0HIQ`!G z3;!{7>AsWSdHF97?s)}H+8#hYCtkkaS(jhD_MNpqTyx0pZV!ED7!!rQ=$)cN2QJ+3 zV9m9cJ$iG?Ur^Pz2|c>U?5v92FTVHaA2t`hdc;O3=sCsb%GVzpS{fgI&Qq=19re@V z7|tfiB>xewUsdz*&Y#t0FS}*)pWljC8^-xUzjueZw=Zt{=j-qP?Uqln-n*v~*X0O3 ztMqS^2CsYhz^SXs-hAxgPyYlZ3?!cwtJmBfzPP9~@JY{(um5SEV{itN&cu-={ou&L z7fx$0o%-O0&4#g3=$l@dc+m|b4ynGr<(CPo-pJYynpv=mi_q34S&s? zcE)PM__xr1oOj>N|Nb%h@!A*8+JDa77ylONm`(l#8G9aCF(iEQ*Y!_+KKBn7-hxBg zgnq-7k*5#sS+?iRx7|Eq@7p(DU>MH|{j--g+!?C=HNP>iJg>Fnq-i)Q4`pL$#sxW> z=kNM@*4rD-xb6Abg*V@TI!)-AqpsLxuUp4%-}G7TH8r0eJi{=~6?*o>*Y3RP=+@VN z*mCKJ-do>VhSSQ0eq-@n$7C)3wBnk|iGQ!1SY2lrLvqN!IQr&8OXr{8_0g68Gw`)P z-HBRssnBbmTJX|_3;uq`cGq`SA5gsw%ET=~zpy=U-JHud7H;^>9=rYJ?qC0C7+(wh zs%6`sU0B>OaqZ(Ho7X=z6O&p~hmik>XV%}kVElF0Y<_?9No61HbR){V(1%>Q>*r7Q zp7iOLMaO3jTye-O!+2WgXCC<8T4S$=Z>T)Ja{cS?KefRyw%e9`PP%u;UH*7v-nF^W zSBh2~bbJXqk3#=w=r)1LSD$>(EnftOzQ2CSXygZ>KUUPb`@3IV^4AwWxM0_>ZXXVL zz8Cs!hwr)VLyzowZB=mTJ#DeqU``yk9r>TV-MCxk9DhJj;eZ!Uzvh4wHyFlsLLYg` zw1)l4FWKvl!xt|){^)Z~HH=q<{>a6X4;ys;o=@B}<;8_B?o#m^+*7kX`HVmH>d1$C zy?^cpU);U9{JF~4(Pa|)z|(G>TDZ@+(A1mXo_fyBJ7GZoM4{K7dT#!Ety-&8r{4+vpIi1UyZ+F3LbnWD({%ka4Huyv z+kxROc-)xq+I4p=cz9Civ44KN{yf9DLg-%|c-VItpFOwTvXu{?FzTusVGX=1^wQ8C z+pI2pY3v)19$9(lv3Jfz{eU)UXvS4V1Kv7d&%5hh`}LEjKe+j?Pa8(7(BFFZ>#LU? ze9A>Pv`+c+`a|C?GmLYD{_8atmwfu?Z|_;K%l*5R-F3^GhViq|zgn={tf$AE+J5|? z#b?wNpL8G21%%ZxG-K$vsQ`+y40m=t=6hwEVvbMsk;`Jwpgs( z&hpGN`!@r3VFc<`jpttd`?ekb`srPl{p6LbUkzSymQuZ8mzfgXHsJJDk4C$UPH%tF z6MuMNy;7%XJn#Aw+dXk#eqH|3r*_QP{mP4wpBnG=Ro1`uEbDpwKOWrrv)`Pwu!T}D zXnexAmq&`9-n#kD9ammb`O~tMIO-1yWM)d+_rALRt{?i8RnI!T!+BRf5BYPl#?Sa- zPsSZ*zxnXlbFQ5;|Fm}=MEDy2*_0da+<4>%_Z&4+P5bS2Ip3mQYkbe|&;258-ygF6 z`e~%1_|(0S!{2Ir{A<^|I&eW`(LGQ8Y3<^EzkgDx(b;_Oqmw>-qx9*@p*yyhZol>y z`5!B_R^w%TZrru_#NB6n`_ZdsUEbxobCjyn_}t+yyqVGYt=tyx7j3@i!Pm+l{tsg~ zc{@J-`yYx=3g3IjMa!N||3#%z!!=(2!i?LebepvKr{6#P{O*DeP_Mb+Co^SkDD$+R z*Y>{V;WWi0Kk(jFtA=LWbpFP^3qEew^>@>h`n$&WT-f2!DR+L}>!{~5 zOQ!s42-+%V? zZ`I*S3XNwK4eNI1{WWK{dF80%diU;ifl}y1!Tn21W`=tdT=uW<{;%&U9CGh0rH<41 zrAr20e*d`hc6g2=aMIsdQIc%hkezb|5FyLD&3 zxBvd1N1*&^ymjjM?8|0eu;uA4Lta1P?H5s=FVpz8{wE!?;@IOxES*2{jXjmO&R6Ow zjj#Fg@dwWNcIwh&zDxb>wI}}b3mkE%@xq@Cxa65W_a3!*?%exEWbb+x>h|G$?`0?K z-S$Rq#m38LblrT#hODENifTNqs8`+1xA!Xi*{GxMoO9c^XQTdV{J6io`H#11){j_q z)BGEZW4RN>*e&>Nd1N32=9q;dg-VX!yP0xv+)q z+u_}ZgJ=A&!gCkH^PEkNO3}@B{JI-{An+rN8|tSyhQAklPva&HZh9HMH~7BB4YE#s ziQmJ0@F#y{5qf_`%T|^zsamzTsI+`=(FE|bz*p*vD~hT(CMkb8uT(X#RE-;1gngpC zbRviIFI74H)(k)Xs3I91s>+#+Q`n0J4=S2evADc?NeS42g9Z*6a{Q3N0|ymV<48b+ zwxn$3p$LexT0CQL^&t;Y2gvobxYh?TZ9bj2lt8b)#rE#1BE8-UyI&H2q%131xip+J zr>qM1S>?Vq{i%*_nyT<)KVz9DIpmCOO)J6`F~^ zF8QipOE4A~l_r(CxI=Q)prXq1;xLybCFMn`FqeN6<1{3UW6JHUN%?h?FG;yxhT)G` zCBWIXC9Aoed(2+0Y}- z2as+ihk4!Vp?Ezf8dhQb!=VVv7IO${6J+x_>MgeC;A9cD7|r{Nm&38OWJ!6BFGP*c zZ#Nx~UQt#QAC8XF>_*lK4P0DVnZze~6JnLVBpB6yZPW2Et#^EC=)Iiqm!L`{Uou7D z9z+b{4lPQ`f3iuLOxcJJ%ZaC?;t`*cW-r$vNz1iWP>71dNyWlj6e`@^*44aA`+)tI zhF6qV$;PCc^3uvJEv~|bCoCvR>f7RTH*WbmXN3}fq@`DU zY`n9&haw_Yp03abzaK>M=;Bm`$-T*&4cJ|?iemD>eM*zbyUC=SCusc+Wll2x>;|&ti)?(glG(4MlGU3& zvDTmpyI@OnIwknhmjjCLFk@tV*+sb+SW>un8JcvwZ)0@;MdsC`<89N`%7ZtCc zrK_+5e#wE?Yz)tsg|-L$$}(;iOUhS#?KC4NO%ClGL{j5RlB{ChbX&o$o`|=kK4mda z!$`_yd@H(wH^Sgxw^fxqA?QqfBTQ1kcq1DVQ1F_dswbav2hjL21 zZ&L2PFDbM8DUJ`vohx-kh01gJ`c<3pR+&%zzN7hl{^fG?MXT6U_IvK4jHNg9iDTH4p@gYa8>cF z60RQh#v|^vjMSlc?T|qS^IjM0VP4+{lW+(LDUL)PJmk;^<)S(G`2R%Uc-=7lE%AwZ zkjWy&A})cGEf(&(t#22zxKehI5tDDULF@8*kRio?;vtP>e5G`fgAPR!ClNf}D0w{ikQ6<6qmwW0d+-uz zKHU3;9J&v*VgFC6xzQE|BchJ6F0@&0(#KFaqGwy2-vQ?BXA9_Mu)*Pa+TuKZb9;f*I`+|3A zGjzDE{r?j=(m-X9)QZd4gZ!9gf_5JgtD$nwat4;KrK>4fXJB1hG1kvjVU1r(9zWDsq=qJ(f8FQkaN2i9iW9_0+o2I30D#+OQY`8;hS}lRXdaP?y zs^;mmP3h5X3+6wSfz2~meT-o|Xnr+hjw=6FN-y)>6%ts<7#YqwaAs@F;qxAwe6 zv4yskbXtUv3)BRxtc)3k$uPLak?RP>toLoV#BNl#{6~&4YNJMHRdnMXns8}Z74}w* z(I-%e_tyFut6g=_*a(9iOQZE>t`xNl+q?A5_U+a9EG7VRM@$O7J3ouDk2%MQ*J174 zz5#3LVY*`jsd%>^%c#&h?Yk=O7>=3PE7Ya!u`4QFN4>p7y@LwscZT8KMUEgtBIt?2 zh^$-_>Ptw)wrYWSPS*}wsOec)ZmaT)8xp23*K%T6s9qOJEQ0?iqTEju;o8^rpvWq9 z5$Lg?HK2U?!zjV6)EdJD)%k`CsNXs4F^6$gD18Lg^A7veVT>1T1L|iS*smS7#bHl745fbt%6@G@#-{51wbRPC7w9Zt6tR3&SBH2AK4CFN zTyY-@pLAAlI*t#wY2@Nu7ITR@t3AASF+FYU-f$7NNH3e24w9CVSJ+!$;a<4`FE*h1bhSsaNoO z6~EW;W5gLVzN<5S44$=~>0)X<>neP*S}elP8m2#&e>2qC1{|YQWHR`%pffqedCsJW~}jvtBwom+9Tvw;H&W_s2^;- zhAEBeqnI!7q#H1=eGTlrO;8FPP4Ja@hRHDc;>V@$Vj{j4XXMCrK13Jwgl$l&E9wjz z8|bkGI#vp~tUj0;EWp2`)6+t&(!GV6Yv@C1sopXuagx8DGI;6LcuOftt1Q%~M_=pG zR*lHAZPC|YJmqeXCs3vVn+e7>*Wg#8-0=A-P^Qg)nR4_ySB}U@IU*O(8zBVy1KbPt zjNyXn1&2+-o5bBz!v*xFRKZFewjCU{`|$J5MNDEv!bXwSB1y=JVUeI=GJTHUf8#ga zm*v(E1^C&lhuTEqcflja;{l!Ff$W5`&EM?XaFxnIMloaP*((58{c~c@^tW6J+0E~U zQ*F@x=<53}z*c(S3Avyuf-Sj#`l;c9>UxL0;jnicHY@t(oViaTc(q-Z$=a&W_Hnv2 zZ6B8bRBanKMd|7ph*i&;ZD}>1rBv^(om{?~ZbqCJKL3d5xN=nDHZfP5&MV(Ou9Ef( z7nm^5sH4!42CpMHY4D)3nFenlIH~Akz)3Slktf)4aPfJ*0f;sFP4)rQF9s+Ez2?JS zF)_doUhK65-y@fRP6OR^7W?cgwLQN_%2XNBeTJ`0F-}ZYHrm|9BPP;VBZ-pL7_7@z z!nRWc3QL8~JXMb44`Tv_`-4(XLi?4I;cYLyVui9Tlr!EhhEm4|#|I~f7)tfJ*J3Dj zycI*1`b)W_ivC)Z^6n5vtW|$T3cQXVMw(>nJ$Ns|MJyfi>DQP(hBCEisOmEB`OF_SGizh*{XI`g!{xsE$}ky5PyDzO zQA`3=*MC?h(ywZ9aXAjqYBc?*kA6BhK|?{McT5(0r+htoi~cHQKLb@Jay1gORO`Q! z5J@&74A|3%Fdqi$e4xTlPMTzL0rj@S{$jX*+T*a#9M&+uauVd%|(&4>{86HzAnGWNq&(FsJD!5P`zikfcl5SK6M!Ki}eb1 zO!Vh)aCw@)cJWQphO+%lT)T2%OJj>2YgfQLQv!9SC5*NA*RCzFo9W9fhRHB;@LT2N z)B1RYDv4}KsBQ&ZE#hminKj8;M0KwbRg7u%9!k7)kjP1{kPE0fV;j_aUj=)`VJxkJ z{cp;Z#}TXPP2|cO$Yn9>J;x*^ktORB3ATgH66y-f5(ez8DbOAe!51KJBv;5uu8<3; zEygyeo;F-S?R40y4nwZYnlm^0-D6ty)w+M}>d^KHx;$^6z#^`;O=w*8-9y!Px>0=> zQuUqSSA7?jZ=XPgL^pIMRJ3>f@S?e{z1zNU!5QnE|Npul@G}iu?uunC* z2%D@3En%#EN>6In%q!83Z$X`z=PP-P6XS3xelNvJUSn!-5=AhflANKX0tFUdrqnw0 z>SIbW)$&kkYOrN`i`1^cCBcI9)~SK?wxNC*p;iMLXw!K~XwwrLXwws$)TSp|E!s={ z&A+51qtE8QCz^kjS*ua&k7!=2K9>GrtX2)RR~wI3&G#IyTcSq{Ct5JEfa1wFF7b`M=)-k(x8 zWJ?_@s6V}X0`nSwdcO?IX}ci%hgN9T?m zCUMu=&K3>ba`s$2Q_*XNcFV+`kMxU=ARR7Z#@N60% z4zgc^H)rEUD5Y*kF^vtWZ2)4;Xv47l(69mF+ytNbJ03q8YtIIxm3d+VGECdX?Ad^% zdm0dE#M)T@Y(QFi8jwryy~VyV$T%?$Bk>#CtorY}+hF8K97kQgcGlw35}XxpR@`er zkg%5))GY~zTliLmQ~okhOdkc1qADdI*Vb^fo-XX1p#3hoKxZ?8*Q<9xnNRP6vVI(mk|skf87VHi?3?`UVZpz7eTehwSpu;_YD`9<@V z)bFg>m(uR$#${@Ie52R+W$Jyfoa!sj)(_L`Z%BMG31sTH;)+?Nn78K2YJI^=(~VfL zL0PfkgEnl$nD0`AaYiGmmdp1+9&d~<UQ?AU;WMvTf$T9 zV~DolPSI((XebMZV;w}zmX-@PrC@p%D;>mD?bQ7Q&!;TwO`ep2}@g1l0QbN^p^>S z$uPqBwStN#Cee@-F6q(7ITx<1D${pDHQCIz)(vYX1Swg476wi;kRxb%5vdf+7B?on z?1G4xyS2`p{c`%YD<2pI#vb3WqH>;wztXe29{4m3?*rV{xz^X+X`GY6lypoxYb4e5 zQ^V35vg;?{Y7LUyES$j8TJ*MpS$sdEq$5OtZ#KYb5b8la|4cw4!P;OeCu;+rdzhH; zgj+t_iec?X8T7|BX4fC4yiK#fnfD!11%$@b1eL-tL+173Z zod9|zD2BIH6tn~sD-0rxIB}-e5vZKfRVF80WpV-ags}~(rwkWRI~?}1!@h9XHxBE9 zk}BbKH(Wq*m|HLobIUtY@HK+*z*xbkhzWL>!+JQZx5EZI>^O%_aaf_lY*&8hH_-{9 zja$~uh;~Cf)y8kuq>b8pe&^C{cqk>J|J1)y^K=MyEk~_RJ3qVh28+imqphM-Ge(5& z4+jxm0fP8#&5rtoH9yubXm{-v-C^fSj<@lR={Uz7QyNIkbj+$`(kmQxZSIT1$}8TMrrVoFR#=E1f3JIi)|L8XQZitA0XyTu zs1~w9>s0Nfjgunwi>wr3jAC-33|Bd<(SAEIEbX_Y@^-p;pj|K{I4Qkl>ZJ5QC>7IR zR@RgmkE{SRXEX@Ny9R`(+ofg&k4LY+TUW12#^d}#-G+K0p6VBBjq{IXrHI#x2LXmM zI$0~y#EKi2gV`A~dgQAZHb08->53l}Ii|cB8MBHUQ#Y2jBeEcQwD|+tA&Q{Mp66H( z$g9aQ|GCJDIWWMuE?3g?LF=U@49bRHQ-Yx|70_qclAQ;>S7odB?ei3#f}7cA3LAJM4Cc zMb=JH;f&~{ypNeAbu2m0z%n*3l}p^1c9t>JulPLx+`q)i`e_ThPmx(-5-EP=E2~QM z(IK8&FMRDhJIw8EIB4=(qc3Iq4bxGW{Kd~XMV>Y>py4elj58Z6Z&7*JD1W~LrSkuK zP=3>6MhW}^?nMbCCrTi>fF9Nm>=$q^*jI)Ns(lXAS%uR7eVIWv0Dym={;t&iC``r5K zQ1m+tVMM3*qsktNULu{ZiS;{2j1N_}LSv0#jogKaRPsT10}Y!H8m~&ulG{(CG5fQj zJG4}^5tV!nVw3M{BpD`EG788aU1><5lA|<)OQ%*XOD6x3)kYKVg*q!uR*E{SteiJ- zHl>Qk9G_E$vbVxHwx4ZVQf8pP?#su*0vX((?q@+4W*}54O+*MW975)GEOYGa(Uc!8 zjg3~q@ND&Ao6>iq-HJ6ndGulo)74)pyFiU)1feiSSg*T+=7M$yW%}oUGBWS#Qn|)( zqUI6{=+kt`1=XX*HlUX@3ihnS{^9(7>ab48eQ|e$;R0%%!!B~z6%M=FVLx}+tqyy{ zVSjL#?!qp)1@BZt|F~)Veyqq^o)Vork;Oe6oeV*To~Z7|wu+`=_^xms7V+0?`LSkS zt9F;n#fQzATc5j;-lGq)Zqz<@KdSHCXhDAc&cbNHJoH~D52zi7E^J24W4~t2u78lL zlnbHFwtIL>p&2urJm6zwi>j^J02k;a2O`5&xaIPk!ac2)=ae$|+VSt0#a+?KIkh#n z1A;2OZTt@^npLPRuilRkFs>M#x_{`OcGD00%4sG_8|%Z%A}6cxnfhC!uWuTEWAuxq zw=j2?ZW_P&vKC`EY^naP_JSMxzc&4{2`Llsv@iPH){k3!`HSdtHSec>d3){D8z)_L z*_f2tNhz@WMu#JxyD4Qe!?|=!+Q)bEwKXCokOa}a8^39{fs4s&PrWg^qyKA{(fg(O zfqDe-W$pMImk%t|QAOZLqDk9umUa9aVqr&L?7!ox%hGGlf&anU|MG!uIuB`<3eU@r zH3_;Cp>2FQd}Q>w+OtzGOButD>%XIROiE$x*c6lMNI!`xUcOu{Z#g5HS6IJuc}{dM z(sQm$?csQ;dAc)`dX7Z4kwivOS*}=U21F<4>kQL>^tUzYd{Ax8UX+97EeoSr^;hph z)#gqW?^vOlS@`@p@0 zEJ;^yg3Hrw^_SqD(za9#g&PI#j~e3;pKu$%y@_A8y2)X;J8rA9<(ffpw-4M{{f=&k zhrE}a%O`ZKM&qx$Bg9Y_fw&V`0y)^7`+Z z1JJaGRb)pXg~>VaVc6@nUcB`g^PFBlfP{MF)Nw3$XV(ww)k#9q2qIJMi=HX=+1mTRvs1g7CxVDo?k{z^LdeZ=7rUK zzQ;WO67`VJ(5toi777uc=j+VI1`*>wQ)f2%6~_M&=Gpq6Zl13+@!4peIX1xXt}@T3 z$80Pj9dWv4Ja!dBzh!jo~e8B`EJl3KpzL)5Bdz~ zzd&CAMFos-ZA=Tq;~h{;`b2htVqZ^$l`{a^9%&Q;M+9vR1a_^8spo^1ymS+B`#|W7f>4< zcB#XzaTwQ5(MLc}WQ*TB9QKfN_lU!ucGxoxd(~lYIP4>b?RMB#4%_FjG_*GI-VDP9 zRJOx9J1o~>{Tw#TVZ$9Z#bJdGLyuujv^oQ;*JKVK(}=e zZMCpA?S5?ZP17R}GM0^LDKnOx3yuXQUC*)0sP@UgWK?^+vqjvr;<5zP8ZJ_!p&bns z7ZeEnOl&$q7;DcZq_Xxv)Dw=L(^&h*AgNjy#pQG06bz$%iV5Gzcg(_%gQa5h__euX z7wb<(Qk)3h|$sI#>961Fmk*zL4otM)!P3a+>Jq
b5r|c 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%0A@4pP|4VTYCqbY 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 literal 507268 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%0Ab!m$1s8Wv|`-mt=UH(_n0ney!QFFIl6vm1s{ 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

_}>} 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

SGmuigLOL_Y0i^;BYdm57GThhQgBx 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 z zibey3FEa=e6SgMVRuL^)(=lg80_eIyFexq}agO1*oeivQ(XKJiImNFZ9`2sKtL~nC zWO?_Vf+9T`jNp-kfDU}3;vGObO>@wgIluKDueB9 zf(Xl{u$aVlhnXtc>~IpyAx{blcBkrd%sQj=HzXpi9g^Wyot#cb7zFGvRYajK5FA}X zDq-9>@(_&2PZt<|T&bweAYC^L1cJu~6zr-x!-fK{g{#FLe@aF`>?`EB7Kt<=q0y~i zNFh3Tw6@M5@xo6GT|AJ0#1zi{91x5G>pr4cL~y0zA>!W{n&2`;7Spnw3uAc_P1f;= z7$I;S( z1&LYic411K(Jay3<{NX%PmYBH)mHP#dIf7DVx#sChr5?JKtDmWL=AQ`(O-LrZdgMY zhnybUWjlku%Rw-(WmDwMin)tx^LvykmF=}e5TdCJWu-#m@EjL)37W9n zn`E>j=Z9SxRv}Y)0i9riv?OFGXbR9uq#_CN!LHOHRSNO~fn_3umP_e zrQ0cuGPWF(JrY1nwKbjA$l!%WLK|1e8d?C8dqIcOVV9Wj%V`TK0+AI{C}%{Ic#Qt; z#UmnjdEcEQyUFC_BCD%`URgG9*IZpU&k#9?q+VF2W0n;P)4eyFThFzCwSfY#kYEbI z907@R+G10H<$zyNj2;JC5~C4&|Fso4hr~YkHQ;5P!6F+m=b#cQs!5xSQCQHR<(J4Y zSmGq)`+Weaf{2-Jpza_>1|pvG`OC(zSLn$|4TX~dt7Ne)!ZjwKI%U3vL2Umv&Uv^S zAQY}wQ^Z{TeD_Fmz$!OuSPtQH_}>rHcduX1nztX`y_vnfyLof`bb$$Mdv`-&WCq<` zR!k8ZNH-n`o{X{a=q0|vp)q>IdLKSRo_%g*Y{Q7q%%_V5Wb5>F&s&7WB5BO2H-p)0 z0)segrWK+ZE?-dWC{;qgzI!3833{-Y*$Pp!WCGEX9$-~k^U2LU~t%j&5S;}#|wBhG}Gmb za$3^eMlcIU6C{XLN4Yl+z&<3Mnhh(_FqCOqD;FjfZpr#33Oy7=fa?XBCmA<9uygSsM#tP{Nl!_wc0jupP!i^!X zO)~O_f)m?G4R9W=mnAMKg0~pv-k>fbj$x?4)UC^=m5_i>ef@~L1*~Kil)^&`>j-D=!Ds2@!J!mN8%ocDA zwonv`^`fTWp))c#yin&lnO^*+w1FEPY53Vk_TyaaV3Rt73foR9C78Rr2&D)hfXN;e zxPiA7$qtHmykcAlgBTHdkX7U#Gh1y!@+NX zBTStHc2)#Rk*f%A9W0XvWLEDUHdY>5oz*!k;Giz#Tp_(3Yy8o8-B7whs4+5$V4&W9 z3r2-3k_D2s#r+#%%Ud%-Y$BY`aO_F3%?=bqs>l?)3K!?7EX87H91SQf=FMsj;fmcp zOt@CdxRwO=Jp}j&Qz>3nGpSTSAiRVK8x+?>1Y>S+ug5gUsSj@m#iiJhO*OQzyh14N zRF2t+IYsFTr3i0?ZTGx6eRZ58C~Ya;7>+Bl*?!iW&jv z9o(f*Cln*oi50}iSRSU!Bjg{tS=d%)Ev|Gyu+Wr7&Ka*j}n1jKm* z)sBZ7R&Hw~BOrGEviTU~&7gLNK$LnSVuwZ8u$k~0(O)(4-4L@V;^y6*hT;nL+y$aL zt;5Ee*R;hQ0dvH(S^jFPxL8b=3ktkp8NjoxL&vX>tU1L-#p){8id`GSLKY5g8j#uF zE`g!`8rEZE%G$v$R{a_LHi)%E;2IRDix()nhG%0AgKI%~3@RRPZq+W4Sc%wII^{(M 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 z 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�c-45gJD&z#&#I&A%pEP*fR!u(O|C{ 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

B9zLp|lGv&&M%>q0wKo|pBDR*fLhWV!W-aUK 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 diff --git a/lib/public/steam_api.lib b/lib/public/steam_api.lib new file mode 100644 index 0000000000000000000000000000000000000000..b413162c64bff9ce87e2597afd15a719d278ab27 GIT binary patch literal 370310 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 UZiY3|<7J8ms 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/__pycache__/type_checking.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/__pycache__/type_checking.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c5d6f0434e16d4939a77a67e5d8a56251657a1e GIT binary patch literal 15728 zcmb7LX>c6Jb)K0$uvlD65CShz8bOpuP|%9BNF6jq2?RhAA_zbPNJ>jW%K>^8SYi*b zXBNj~>5Ec)QkL!bNJQDB?ZmMY$BuLPKH@lb9LKQ}TS+EPRVw+#R4V1F{7994<$G_A zJqYTMgx;B+?$@thzkcs~uUm&ZI+6`pL_aAMfp#93I6HA!xKtMv3gq+<&+|n zj3QK_71W}Z(Nubl6e5`j|3))05f!mQyx5Xy!MCW07ZSzROlvWjNfz5OZN>IXd$A+a zQS8ig7P~TC#Z)F$+>qH&?9Ox-H)b|+pO!*T@wUuu{G2HC7B^)!6*p%#^LuMyOL1#v zYjIm<8^0$Dw->i(wioZn+)=zUb7xV{=*7D-cNP0GeZ{*ocXOMz!j9rSnR`^lyjMgn ztC^jm-P|QQ4k~8sLjQ}Z>;vzeh26#bGWT)&uEId^{>=USoC5uHCXK$a3lErgqugWe z-9m4Bf@i#?&AlR$i*HdfZxI_rx7c`96FuU#=c1VhMX%T-HsgJZ*oyakVjJFX$NP41 z2j2IKJB7~gcZoi{KZN$Z;%u-Jbko_P#kAM(DM2h2mc$Yo9J zn^(;J=0oCPe1BX#0_i*o>1-7T(BifnzKgeBiDaG-2l3@G{&I-Nq}oC8IBK6bsEA*Q zL2($|4qc6iVKMStEOQt&o5T@te^eX;w?kr7Jjt^=F2?XaEKZn_3nLg|Tuk8Gq+I9TiW5gJ+np48HLygXUS5 z$T{%%q?kdAXSqd|=bkiMbDB4EaUL{|3j-}?xy2l}*lzA^XfY-PTA17-=gSXN%r^5L zb9*jclk~hI=C8yuC&U8U=OLF1Vo?+zgQ6&59^;rt8C>%ET-NYQ^MO3ggSqHsEf>iv z=8!pV9urG>Rb0f1Ob7`|7ATP}*`QPr%b+v~N-G|n`q9lvv5H<#i8b_cnBNs>!angE zERQN?ds1A&x3}@PxBGM1j(K?VX*WA^i8|R#iFcs&JGu3{{MH9T*<2RSG2Q1e=Ct@t zw0yVUl2!>a&YWWDzlUqz8|uwzaR0uWsJ)+QeE{-1Bd&nf3*762kWR3wFNzOgMV}TQ z#@CPV*Wbcdj3hoPJ|;en**(MGKEdC9JN!nyGW_Lt_{;lPi-^Co%->5~d)4QtGn^l3 z$2svbM*AdMOk9`|pAy%usF`QM|8>aqg!r`iAj;2(&o02ah~EY8S$z9F(1&jG&N+|w z&oSjq=H>>A4J~HHAE3n_V)eh6nFF0a;#OT|%G|)(*KKYzH-+o< zrBHrCd>Q@z82!Eit@#sZ&7X=tgVva!@#j7bkHV&0%(nriAj#*%U!dn#nWwM$JZzVm_Kz#J50mL3|r+zr$_6%R2Bq@t2Tno~_6Cx&E)h zu~-l5#{$nk2s8)Je{CKTKP1WG`A6P5iir3dp8JolL{a;ZV3k zZE4KerkI$$V9wc=+i}z^nbJVbSl$AG(b8O@BFy2u#J9s`dtod;D-D@9@jA6&NNPtF zYj`Eb=7QJAlZJGYBdg|I#WrROCb-{l$};5<)37VjoLHhs^lNT%*jzHfOlfY-?H(=J zrYsqSS{+)n9$&$1MoYP}yJ4tYvW+}AoQ8a;s=vjJ9>L_@1eGVs!gM=M7;_6~Gqh07 z&zWvZ0TapR*4*|5!^$oh_CnS&m)us5gX89!+cQ#H&dYMCXqN2Lm>aQcf!{7jhuN8w z<#}loo%ZQ8jeB;yTry|e1pUxEnzoGP(bOp5F){tjvsQWKG@+PjsUN>J*#_DgD2g^Ie%UPPD~6?GDtbA` z-@Ho8w9{?`d^%lCOo68uYo_eOpdmZNRt$d|iJg1#P*vWeEVeL0(yl4C`X1%7dR=`9 zT3=OOQeKWu0S|(?=(y8WgwpD>;K1X;(FSxUKA=O_b&M9hP|la!xK)-=%YIev0CD`> zg`dwWuRb+=;G8g*&&`($!jg0677BaMSz<9uS{<$`stXjT=l;@0sbtuj49%^t>>x8I2^)CUyKXX-I7GO2LqYHMUl{N@2~PDHMWrKqo~U?~l4kk3}S!nTq z4yBzTlMpS!&NXU51YJp2Sqm;;FIGWYVDk&Dsw~E35BVA!weV%p#i-mtYhP6a;*LwI z4ehWsJ3`pOIwV@ql4~w&h;VY~rJ`42QL}_-_1>_5p+Bp8L~>Y}*>y>)s#R@^BHFOu zFNpT4COS4@kBd&P-rMaLFPxzsT@5`_=yA2K$A*R;SGh-bLywK<@zc5h<0|j(rJiUX0<}Af_Mwaan4%}wocVk@Le z=5?EKF9aTLBC@aN^CinB9if#vf2-{@y^yzb{AcL!xC^G#%R;~e!{cME?Va?&f`Kuh z06+#t3ENQ`YhOlJRp?!Q8H!b<%y@9S%R zoMCD!;L79?EOV}my-fQV9KtlvMuWXB*s{ z$Ah|AFv(I`5^JG2`*T1nc8y6ra4|;RIF>&UN!O#^N_~&lI0;(>-OW|NCGh(wT&Tg& z3An9p5p=n-D(|QN2K0GyUlHa8%V5pH07gAc*VK7<4Vv`lO(D!@ib<8lu-L z2zCR&F>MY{EoxffJk+Fpxj{<# zX4AeYTff(9=KW#xvK~R9v_xUv6ZmUaqgq1kMA?q#PA!S@cD26jMC}f=#GfXQqpx#c z9r}75&oCo<(Ia%NwA8f7>=KUQ0WKkFE0+Pf*r2H}XfXIN7BFL5l#(X2OGwCxD1iqN z6Wa4I=>#G!X=LFIn0t3YWK)#OgBa3i8K>^H@6eS$NATBtE8i}g$_*S)7lM|>ToSiQ%RqRGjPsV|y#LL==hkCpRSwx)WF@j0D z0ZaxH2yfwS8_NfA#kHk1eb;QoW}CgVCiC+PcE65z(Sp4!H*YHg>-lP*!5{B%W#4)uFFCL{1^vFamTBmSJ=TWC_U4 zX6Ms~-k~y+y(f>tOZ9a;5d5%JsBo&P%&V8YcYhCFQcKf$fU(tag6=a%E@^8$RqYxj z$F=L)Iqg#9QuK^cx;+ZGvY3?5s!)HVnIl#0B~3(M2E2P(sYb8Gu4AiIBlLSvxwsnu z>WQj)Eq=wrdzeH=bPdmlP)(m*(}4&8M06`ZUrIY0&Ek^1hGu^E zl2J6Bo~B9$HlYYf)5(yrJ)jK-P3oj*hN6Q;3xFsb@L|cAGsC?<*R%)a2~c=Hkt4d; z_4fw6ST)04r%QpMaCYQN;43fml?4R)JP3LHptnvl(fboMYd~SZobAS}r9$3zlK_Vm zb41FrL=~La61KK&!km`1nm%9k2ld&3?MBB5dv6}eg8LEAniVTYW7)wabP{p%UWT`k$MU$1S z6HRDgUqm~r8$}=*5Ir$q(u-1W%JR+3xNRp#o;o#pa%31(+=R$ml=MPs zsYZkPqTTT5)ZpQU-+t@%rq-(6VkhXJ&-%d4Eqve5G0wPaolK#(S^FTvaBF#%SAop{!Xp=t39(?W z1AbE80l5ZkQA37;^MsyjW0V)GGZwF^eNMWMf@cam?Uiy6%JHhg;nX`J1etx0^}#E! zK^eiAcxE%g6-^eTHOodDnZa+OrI(=rP^W*LyRv3!c|BJV_Hp_L3k5$=4?@x~05WP3 z47k2YB<$pFXOYbG1fUm^M|!2v)oC?L`5M@Xz1`1g4xY?!&3y=Mos9%;5P~D4A4Jr; z(|^+hC?ae^m%I?`Pid<+rS964+M9g$o0!lq>LyeREo+huQ)T8nWmInB(~qHBYa(=` zG!-_kp5Hl(A>=tK$X0maM2oD@GhtA0Y?%B>uX|Lq(*6epqE5zF{Ykg9-z@cD#_GAQN?k98_fd2uwBc ziyx+;dNi8Uy*pdxvzR(4@hfyTL7cbu*DH!&h<);Pl_o z(#zGyQmVW}{US&>ySHVJR0@TgPI~U~kA%+d+KE;>2lSmdZlI$sdNh{!seeXp10A?( zT3xp-kF%m|(XW~MEE;S zY2`8c?nR4s+;c|cC>q+q(936SIJ2M@8l@~IWC3miCYzuhG%H+qGAzVU6FkR|AlzuP zJdp+Fig!<=CbGHuH4*d8)d1Pr5Ex}w@;JKlgtHDr?{BGXXcnrsm1&tIL1W(DSajY- z@1TlzQqjnQyXBTc{uf$%7&4N?4o#|e;IEzcuzVN3g(9I{NfThukiY}U|1yDHWGPf` ziyvmAX>iY8gcJTh^!0Y3Dlg;Njet4GuZHD@YVhfeK&1d44bax}(a?+=9~nPQs0>(i zDTg!E^(R6Y*qexK=VJv@1Z~{ehof5RRp%j=3OJ$Fsgk22S~lI#t;(!GZg>tUl{L(N z3+Um8l7~%ez}PqnDayRphUV*Rt)FV+87YpCM<$PqjuArTSzwP@kQ3P<53263@64bv z5Ley#_<&x2K0X7`N_0oYho^{cJEQ};S(=vR+;dBUEZHMyLZjz#g>6mQ9ABiDSYKcF|ATMy^~L&>3u6DJ18357djfee`CTc$V~S|J}AoJG}j zz*L=w{XjB2RVQVuOQGDVCxW1eG*)CE#1U#9nYR#klOJXiwqD-kNsc@3<+$?>;BjO_ zE~{Ryq#8xa5c!a5G6FS(xBI1 zEw8H|smow#lF*IYmXqb8?;GEVjC^~O)oK!xLEhFbB^TG^W za%c?dEMC~R!Q`=xV{1qJ$PZFMI0m8f3;1#4$mb!K=tfQ4j<_Xj?zY$9;ZEYUF^nb? zNRUN-gvLlU^Y6s=rr(m@1OL_-g}UuXEY6t(q;ZJloT*p-I;E*kPP`#)3WGxEG;P3* z6Q@T`o*YH+Ix#stIx$Y0kiu?H7S_#L7lN2;n2%@gf}n(Q=9ksQh&W2YeTnjM zaNURi<#S$4C|Zb)NK~VsJ&D*0aiU04-Ni{i?rIx%C~-hHVl3Tx05-T_=Yi04I}g-^ zoys|0T>!P^=a7-}PU<+PV2ZS>I9n!IDLms%ffSD6IN6YP?rZ*pfh^7^({UY=%C$^b z+G+6{J9pJc`HaEz)14axWb=HHz==OGIzD-7+VK}bcP1(8?9HLi`-Zb2P@h|%@Xk-X zrS)NC-`2_%y=YQ6_r&Db;OO}H;E9nZyu-044i8R^@cZLX`L|*DBn5g%unECAB+uo< z2o~ zih6my*MTIQUV{iXun4`Z-t^#65@ctP<@4WLe8JWv4B)oDWC<0*>d^(0c7gDY(=-vB z@ox=|e9!0T9>RG&pW{0$*t@ScRXPy#rW&c?BL=cws)0mF4t$vUYX?pT=H$r@z?#&*4CObTGWDwibZTCnTg%xAX zVsa0s_c)JWVP|m-5mp!%&gur_+Y$9$02>S#Z4x^o+B6(g5@-`xnGR9h?%Fe=AIrk^ zEVnCUV{q)u;4@Qh_s#U&+nO3>Y1Kz+%k2wfBXo$acp?Yt!E@a0bO!2$(14g3E!N!% zWj8xIJ~Va;UKS)rhNdS@j*d*ZUA}w+EQ54*lmY@b?!|DtX8{h}7C$a_<6cw@_{0X1 zR>KQ+-ifCGf#VJqF}VFE1`&w(_einuKJp$J9|9}1>>C7K#iq~gaB}tc5-hWjyPp;SiAcV83)gG8o$vmv&nV`O+dsz6~3Ya4N@_g!SwO;|2iHYr`A(TQTfLR*29IN9taR zW+qiLa*eUNZ{RkdeGsreiRWe$N2h6D2uvJK)3&W+;({YI&>;Uyzij5xk5O5<9rKJipJV)??BV0=OKN2jLe-C00PC)@6Ab<-o+_+Qe z&=#0Lwd2U-#BJQ=yBPQ3BEt3ExT8gvh`nQdi!X5ds<;*;(|vpxoMsXyvW1pz1Ff8u z6>HeWz>|f-nj59Nvu+}rrJbG4O41nlEfiSp@6hvoR5ax|dOQtSDAR5XPO!d6dPGS~ zI-~0at|BxgzmIn}S!?e+^M)1SO|3jFbceUl$0qztf>o}_IhdMLw;Ymfp$C5Ia|i2c z)=gk0IW=+WY|QC_~5d4*b@9y~cpM`di@I$%R_xqjK?3+`-M zAB0QOYL?VZO`aT?8aa7-Bs)3Cy6i^jMy}gtEtD&8P&p%Ca9b#H0N}krK*(*u9pJ@g z=O5ah9yFmNQ3N{5b=6AMr-e2L{+})_&RXR{1-FYS4#2^iR<_(IJ>v`<=YY6re@g@K zN?-tjnUI9s1X8zeH#G z3W~tPu)II&lgyW8-d^M8@JjT%?;&`nm{p;x{hy##E$|()Wy^Gs3TLMnY6kvqfa#Gb zLh4if>U962+mg+S@?19SCbQXGh5nBR><-%4@@GUTj(vkYD2J(rXnWU+W9-HyZ#l|C z@V=9jM3i)oL=xbaZB)=sksVYJx|LlhT--vz7HAX6yb>6-c3j4{3*vjSL+h9Y5-B@TQ+7FNvrU-dM82bv5xQ?SjJ zy<1*yr*FHdc#w+YR7_AoH+cAZ10U}58IIdJJ~%xJ-Nzv|WlG$(vBB}9rv{I5%`xh5 zkqSwLO$D8pc!wX9Q~^kV!XhKj`CCrMdimw&soA@!crO+2r{W3~ln{|0qk?0=m+9$~ zRD6nx&rtDM6mBv=-{9=dm}w}rJ|`eP2Jk&)wbh{_mot7qSUTd6FzC1QBUn?EDd)n zsl*MKXsU;PsU7|6(cv#VBK4|`;??(Roy?oprzdg;-V%O0g!Yl%@M|j4j+>m_T8e5Q vhk9D6NHiP)d_+ literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/compiler.py b/devtools/meson/mesonbuild/interpreter/compiler.py new file mode 100644 index 0000000..52737c4 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/compiler.py @@ -0,0 +1,805 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2012-2021 The Meson development team +# Copyright © 2021 Intel Corporation +from __future__ import annotations + +import collections +import enum +import functools +import os +import itertools +import typing as T + +from .. import build +from .. import coredata +from .. import dependencies +from .. import mesonlib +from .. import mlog +from ..compilers import SUFFIX_TO_LANG +from ..compilers.compilers import CompileCheckMode +from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs, + FeatureNew, disablerIfNotFound, + InterpreterException) +from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args +from ..mesonlib import OptionKey +from .interpreterobjects import (extract_required_kwarg, extract_search_dirs) +from .type_checking import REQUIRED_KW, in_set_validator, NoneType + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + from ..compilers import Compiler, RunResult + from ..interpreterbase import TYPE_var, TYPE_kwargs + from .kwargs import ExtractRequired, ExtractSearchDirs + from .interpreter.interpreter import SourceOutputs + + from typing_extensions import TypedDict, Literal + + class GetSupportedArgumentKw(TypedDict): + + checked: Literal['warn', 'require', 'off'] + + class AlignmentKw(TypedDict): + + prefix: str + args: T.List[str] + dependencies: T.List[dependencies.Dependency] + + class CompileKW(TypedDict): + + name: str + no_builtin_args: bool + include_directories: T.List[build.IncludeDirs] + args: T.List[str] + dependencies: T.List[dependencies.Dependency] + + class CommonKW(TypedDict): + + prefix: str + no_builtin_args: bool + include_directories: T.List[build.IncludeDirs] + args: T.List[str] + dependencies: T.List[dependencies.Dependency] + + class ComputeIntKW(CommonKW): + + guess: T.Optional[int] + high: T.Optional[int] + low: T.Optional[int] + + class HeaderKW(CommonKW, ExtractRequired): + pass + + class FindLibraryKW(ExtractRequired, ExtractSearchDirs): + + disabler: bool + has_headers: T.List[str] + static: bool + + # This list must be all of the `HeaderKW` values with `header_` + # prepended to the key + header_args: T.List[str] + header_dependencies: T.List[dependencies.Dependency] + header_include_directories: T.List[build.IncludeDirs] + header_no_builtin_args: bool + header_prefix: str + header_required: T.Union[bool, coredata.UserFeatureOption] + + class PreprocessKW(TypedDict): + output: str + compile_args: T.List[str] + include_directories: T.List[build.IncludeDirs] + dependencies: T.List[dependencies.Dependency] + + +class _TestMode(enum.Enum): + + """Whether we're doing a compiler or linker check.""" + + COMPILER = 0 + LINKER = 1 + + +class TryRunResultHolder(ObjectHolder['RunResult']): + def __init__(self, res: 'RunResult', interpreter: 'Interpreter'): + super().__init__(res, interpreter) + self.methods.update({'returncode': self.returncode_method, + 'compiled': self.compiled_method, + 'stdout': self.stdout_method, + 'stderr': self.stderr_method, + }) + + @noPosargs + @noKwargs + def returncode_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> int: + return self.held_object.returncode + + @noPosargs + @noKwargs + def compiled_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + return self.held_object.compiled + + @noPosargs + @noKwargs + def stdout_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.held_object.stdout + + @noPosargs + @noKwargs + def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.held_object.stderr + + +_ARGS_KW: KwargInfo[T.List[str]] = KwargInfo( + 'args', + ContainerTypeInfo(list, str), + listify=True, + default=[], +) +_DEPENDENCIES_KW: KwargInfo[T.List['dependencies.Dependency']] = KwargInfo( + 'dependencies', + ContainerTypeInfo(list, dependencies.Dependency), + listify=True, + default=[], +) +_INCLUDE_DIRS_KW: KwargInfo[T.List[build.IncludeDirs]] = KwargInfo( + 'include_directories', + ContainerTypeInfo(list, build.IncludeDirs), + default=[], + listify=True, +) +_PREFIX_KW: KwargInfo[str] = KwargInfo( + 'prefix', + (str, ContainerTypeInfo(list, str)), + default='', + since_values={list: '1.0.0'}, + convertor=lambda x: '\n'.join(x) if isinstance(x, list) else x) + +_NO_BUILTIN_ARGS_KW = KwargInfo('no_builtin_args', bool, default=False) +_NAME_KW = KwargInfo('name', str, default='') + +# Many of the compiler methods take this kwarg signature exactly, this allows +# simplifying the `typed_kwargs` calls +_COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _PREFIX_KW, _NO_BUILTIN_ARGS_KW] + +# Common methods of compiles, links, runs, and similar +_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW] + +_HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS] + +class CompilerHolder(ObjectHolder['Compiler']): + preprocess_uid: T.Dict[str, itertools.count] = collections.defaultdict(itertools.count) + + def __init__(self, compiler: 'Compiler', interpreter: 'Interpreter'): + super().__init__(compiler, interpreter) + self.environment = self.env + self.methods.update({'compiles': self.compiles_method, + 'links': self.links_method, + 'get_id': self.get_id_method, + 'get_linker_id': self.get_linker_id_method, + 'compute_int': self.compute_int_method, + 'sizeof': self.sizeof_method, + 'get_define': self.get_define_method, + 'check_header': self.check_header_method, + 'has_header': self.has_header_method, + 'has_header_symbol': self.has_header_symbol_method, + 'run': self.run_method, + 'has_function': self.has_function_method, + 'has_member': self.has_member_method, + 'has_members': self.has_members_method, + 'has_type': self.has_type_method, + 'alignment': self.alignment_method, + 'version': self.version_method, + 'cmd_array': self.cmd_array_method, + 'find_library': self.find_library_method, + 'has_argument': self.has_argument_method, + 'has_function_attribute': self.has_func_attribute_method, + 'get_supported_function_attributes': self.get_supported_function_attributes_method, + 'has_multi_arguments': self.has_multi_arguments_method, + 'get_supported_arguments': self.get_supported_arguments_method, + 'first_supported_argument': self.first_supported_argument_method, + 'has_link_argument': self.has_link_argument_method, + 'has_multi_link_arguments': self.has_multi_link_arguments_method, + 'get_supported_link_arguments': self.get_supported_link_arguments_method, + 'first_supported_link_argument': self.first_supported_link_argument_method, + 'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method, + 'get_argument_syntax': self.get_argument_syntax_method, + 'preprocess': self.preprocess_method, + }) + + @property + def compiler(self) -> 'Compiler': + return self.held_object + + def _dep_msg(self, deps: T.List['dependencies.Dependency'], compile_only: bool, endl: str) -> str: + msg_single = 'with dependency {}' + msg_many = 'with dependencies {}' + names = [] + for d in deps: + if isinstance(d, dependencies.InternalDependency): + FeatureNew.single_use('compiler method "dependencies" kwarg with internal dep', '0.57.0', self.subproject, + location=self.current_node) + continue + if isinstance(d, dependencies.ExternalLibrary): + if compile_only: + continue + name = '-l' + d.name + else: + name = d.name + names.append(name) + if not names: + return endl + tpl = msg_many if len(names) > 1 else msg_single + if endl is None: + endl = '' + return tpl.format(', '.join(names)) + endl + + @noPosargs + @noKwargs + def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.compiler.version + + @noPosargs + @noKwargs + def cmd_array_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]: + return self.compiler.exelist + + def _determine_args(self, nobuiltins: bool, + incdirs: T.List[build.IncludeDirs], + extra_args: T.List[str], + mode: CompileCheckMode = CompileCheckMode.LINK) -> T.List[str]: + args: T.List[str] = [] + for i in incdirs: + for idir in i.to_string_list(self.environment.get_source_dir()): + args.extend(self.compiler.get_include_args(idir, False)) + if not nobuiltins: + opts = self.environment.coredata.options + args += self.compiler.get_option_compile_args(opts) + if mode is CompileCheckMode.LINK: + args.extend(self.compiler.get_option_link_args(opts)) + args.extend(extra_args) + return args + + def _determine_dependencies(self, deps: T.List['dependencies.Dependency'], compile_only: bool = False, endl: str = ':') -> T.Tuple[T.List['dependencies.Dependency'], str]: + deps = dependencies.get_leaf_external_dependencies(deps) + return deps, self._dep_msg(deps, compile_only, endl) + + @typed_pos_args('compiler.alignment', str) + @typed_kwargs( + 'compiler.alignment', + _PREFIX_KW, + _ARGS_KW, + _DEPENDENCIES_KW, + ) + def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int: + typename = args[0] + deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross) + result, cached = self.compiler.alignment(typename, kwargs['prefix'], self.environment, + extra_args=kwargs['args'], + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Checking for alignment of', + mlog.bold(typename, True), msg, mlog.bold(str(result)), cached_msg) + return result + + @typed_pos_args('compiler.run', (str, mesonlib.File)) + @typed_kwargs('compiler.run', *_COMPILES_KWS) + def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult': + code = args[0] + if isinstance(code, mesonlib.File): + self.interpreter.add_build_def_file(code) + code = mesonlib.File.from_absolute_file( + code.rel_to_builddir(self.environment.source_dir)) + testname = kwargs['name'] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False, endl=None) + result = self.compiler.run(code, self.environment, extra_args=extra_args, + dependencies=deps) + if testname: + if not result.compiled: + h = mlog.red('DID NOT COMPILE') + elif result.returncode == 0: + h = mlog.green('YES') + else: + h = mlog.red(f'NO ({result.returncode})') + mlog.log('Checking if', mlog.bold(testname, True), msg, 'runs:', h) + return result + + @noPosargs + @noKwargs + def get_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.compiler.get_id() + + @noPosargs + @noKwargs + @FeatureNew('compiler.get_linker_id', '0.53.0') + def get_linker_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.compiler.get_linker_id() + + @noPosargs + @noKwargs + def symbols_have_underscore_prefix_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + ''' + Check if the compiler prefixes _ (underscore) to global C symbols + See: https://en.wikipedia.org/wiki/Name_mangling#C + ''' + return self.compiler.symbols_have_underscore_prefix(self.environment) + + @typed_pos_args('compiler.has_member', str, str) + @typed_kwargs('compiler.has_member', *_COMMON_KWS) + def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool: + typename, membername = args + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'], + self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if had: + hadtxt = mlog.green('YES') + else: + hadtxt = mlog.red('NO') + mlog.log('Checking whether type', mlog.bold(typename, True), + 'has member', mlog.bold(membername, True), msg, hadtxt, cached_msg) + return had + + @typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1) + @typed_kwargs('compiler.has_members', *_COMMON_KWS) + def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'CommonKW') -> bool: + typename, membernames = args + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'], + self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if had: + hadtxt = mlog.green('YES') + else: + hadtxt = mlog.red('NO') + members = mlog.bold(', '.join([f'"{m}"' for m in membernames])) + mlog.log('Checking whether type', mlog.bold(typename, True), + 'has members', members, msg, hadtxt, cached_msg) + return had + + @typed_pos_args('compiler.has_function', str) + @typed_kwargs('compiler.has_function', *_COMMON_KWS) + def has_function_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: + funcname = args[0] + extra_args = self._determine_args(kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) + had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if had: + hadtxt = mlog.green('YES') + else: + hadtxt = mlog.red('NO') + mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt, cached_msg) + return had + + @typed_pos_args('compiler.has_type', str) + @typed_kwargs('compiler.has_type', *_COMMON_KWS) + def has_type_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: + typename = args[0] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment, + extra_args=extra_args, dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if had: + hadtxt = mlog.green('YES') + else: + hadtxt = mlog.red('NO') + mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt, cached_msg) + return had + + @FeatureNew('compiler.compute_int', '0.40.0') + @typed_pos_args('compiler.compute_int', str) + @typed_kwargs( + 'compiler.compute_int', + KwargInfo('low', (int, NoneType)), + KwargInfo('high', (int, NoneType)), + KwargInfo('guess', (int, NoneType)), + *_COMMON_KWS, + ) + def compute_int_method(self, args: T.Tuple[str], kwargs: 'ComputeIntKW') -> int: + expression = args[0] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross) + res = self.compiler.compute_int(expression, kwargs['low'], kwargs['high'], + kwargs['guess'], kwargs['prefix'], + self.environment, extra_args=extra_args, + dependencies=deps) + mlog.log('Computing int of', mlog.bold(expression, True), msg, res) + return res + + @typed_pos_args('compiler.sizeof', str) + @typed_kwargs('compiler.sizeof', *_COMMON_KWS) + def sizeof_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> int: + element = args[0] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross) + esize, cached = self.compiler.sizeof(element, kwargs['prefix'], self.environment, + extra_args=extra_args, dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Checking for size of', + mlog.bold(element, True), msg, mlog.bold(str(esize)), cached_msg) + return esize + + @FeatureNew('compiler.get_define', '0.40.0') + @typed_pos_args('compiler.get_define', str) + @typed_kwargs('compiler.get_define', *_COMMON_KWS) + def get_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> str: + element = args[0] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + value, cached = self.compiler.get_define(element, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Fetching value of define', mlog.bold(element, True), msg, value, cached_msg) + return value + + @typed_pos_args('compiler.compiles', (str, mesonlib.File)) + @typed_kwargs('compiler.compiles', *_COMPILES_KWS) + def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool: + code = args[0] + if isinstance(code, mesonlib.File): + if code.is_built: + FeatureNew.single_use('compiler.compiles with file created at setup time', '1.2.0', self.subproject, + 'It was broken and either errored or returned false.', self.current_node) + self.interpreter.add_build_def_file(code) + code = mesonlib.File.from_absolute_file( + code.absolute_path(self.environment.source_dir, self.environment.build_dir)) + testname = kwargs['name'] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None) + result, cached = self.compiler.compiles(code, self.environment, + extra_args=extra_args, + dependencies=deps) + if testname: + if result: + h = mlog.green('YES') + else: + h = mlog.red('NO') + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h, cached_msg) + return result + + @typed_pos_args('compiler.links', (str, mesonlib.File)) + @typed_kwargs('compiler.links', *_COMPILES_KWS) + def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool: + code = args[0] + compiler = None + if isinstance(code, mesonlib.File): + if code.is_built: + FeatureNew.single_use('compiler.links with file created at setup time', '1.2.0', self.subproject, + 'It was broken and either errored or returned false.', self.current_node) + self.interpreter.add_build_def_file(code) + code = mesonlib.File.from_absolute_file( + code.absolute_path(self.environment.source_dir, self.environment.build_dir)) + suffix = code.suffix + if suffix not in self.compiler.file_suffixes: + for_machine = self.compiler.for_machine + clist = self.interpreter.coredata.compilers[for_machine] + if suffix not in SUFFIX_TO_LANG: + # just pass it to the compiler driver + mlog.warning(f'Unknown suffix for test file {code}') + elif SUFFIX_TO_LANG[suffix] not in clist: + mlog.warning(f'Passed {SUFFIX_TO_LANG[suffix]} source to links method, not specified for {for_machine.get_lower_case_name()} machine.') + else: + compiler = clist[SUFFIX_TO_LANG[suffix]] + + testname = kwargs['name'] + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) + result, cached = self.compiler.links(code, self.environment, + compiler=compiler, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if testname: + if result: + h = mlog.green('YES') + else: + h = mlog.red('NO') + mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached_msg) + return result + + @FeatureNew('compiler.check_header', '0.47.0') + @typed_pos_args('compiler.check_header', str) + @typed_kwargs('compiler.check_header', *_HEADER_KWS) + def check_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool: + hname = args[0] + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Check usable header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + haz, cached = self.compiler.check_header(hname, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if required and not haz: + raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not usable') + elif haz: + h = mlog.green('YES') + else: + h = mlog.red('NO') + mlog.log('Check usable header', mlog.bold(hname, True), msg, h, cached_msg) + return haz + + def _has_header_impl(self, hname: str, kwargs: 'HeaderKW') -> bool: + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Has header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + haz, cached = self.compiler.has_header(hname, kwargs['prefix'], self.environment, + extra_args=extra_args, dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + if required and not haz: + raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not found') + elif haz: + h = mlog.green('YES') + else: + h = mlog.red('NO') + mlog.log('Has header', mlog.bold(hname, True), msg, h, cached_msg) + return haz + + @typed_pos_args('compiler.has_header', str) + @typed_kwargs('compiler.has_header', *_HEADER_KWS) + def has_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool: + return self._has_header_impl(args[0], kwargs) + + @typed_pos_args('compiler.has_header_symbol', str, str) + @typed_kwargs('compiler.has_header_symbol', *_HEADER_KWS) + def has_header_symbol_method(self, args: T.Tuple[str, str], kwargs: 'HeaderKW') -> bool: + hname, symbol = args + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Header', mlog.bold(hname, True), 'has symbol', mlog.bold(symbol, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False + extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + deps, msg = self._determine_dependencies(kwargs['dependencies']) + haz, cached = self.compiler.has_header_symbol(hname, symbol, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + if required and not haz: + raise InterpreterException(f'{self.compiler.get_display_language()} symbol {symbol} not found in header {hname}') + elif haz: + h = mlog.green('YES') + else: + h = mlog.red('NO') + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log('Header', mlog.bold(hname, True), 'has symbol', mlog.bold(symbol, True), msg, h, cached_msg) + return haz + + def notfound_library(self, libname: str) -> 'dependencies.ExternalLibrary': + lib = dependencies.ExternalLibrary(libname, None, + self.environment, + self.compiler.language, + silent=True) + return lib + + @disablerIfNotFound + @typed_pos_args('compiler.find_library', str) + @typed_kwargs( + 'compiler.find_library', + KwargInfo('required', (bool, coredata.UserFeatureOption), default=True), + KwargInfo('has_headers', ContainerTypeInfo(list, str), listify=True, default=[], since='0.50.0'), + KwargInfo('static', (bool, NoneType), since='0.51.0'), + KwargInfo('disabler', bool, default=False, since='0.49.0'), + KwargInfo('dirs', ContainerTypeInfo(list, str), listify=True, default=[]), + *(k.evolve(name=f'header_{k.name}') for k in _HEADER_KWS) + ) + def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'dependencies.ExternalLibrary': + # TODO add dependencies support? + libname = args[0] + + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) + if disabled: + mlog.log('Library', mlog.bold(libname), 'skipped: feature', mlog.bold(feature), 'disabled') + return self.notfound_library(libname) + + # This could be done with a comprehension, but that confuses the type + # checker, and having it check this seems valuable + has_header_kwargs: 'HeaderKW' = { + 'required': required, + 'args': kwargs['header_args'], + 'dependencies': kwargs['header_dependencies'], + 'include_directories': kwargs['header_include_directories'], + 'prefix': kwargs['header_prefix'], + 'no_builtin_args': kwargs['header_no_builtin_args'], + } + for h in kwargs['has_headers']: + if not self._has_header_impl(h, has_header_kwargs): + return self.notfound_library(libname) + + search_dirs = extract_search_dirs(kwargs) + + prefer_static = self.environment.coredata.get_option(OptionKey('prefer_static')) + if kwargs['static'] is True: + libtype = mesonlib.LibType.STATIC + elif kwargs['static'] is False: + libtype = mesonlib.LibType.SHARED + elif prefer_static: + libtype = mesonlib.LibType.PREFER_STATIC + else: + libtype = mesonlib.LibType.PREFER_SHARED + linkargs = self.compiler.find_library(libname, self.environment, search_dirs, libtype) + if required and not linkargs: + if libtype == mesonlib.LibType.PREFER_SHARED: + libtype_s = 'shared or static' + else: + libtype_s = libtype.name.lower() + raise InterpreterException('{} {} library {!r} not found' + .format(self.compiler.get_display_language(), + libtype_s, libname)) + lib = dependencies.ExternalLibrary(libname, linkargs, self.environment, + self.compiler.language) + return lib + + def _has_argument_impl(self, arguments: T.Union[str, T.List[str]], + mode: _TestMode = _TestMode.COMPILER) -> bool: + """Shared implementation for methods checking compiler and linker arguments.""" + # This simplifies the callers + if isinstance(arguments, str): + arguments = [arguments] + test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments + result, cached = test(arguments, self.environment) + cached_msg = mlog.blue('(cached)') if cached else '' + mlog.log( + 'Compiler for', + self.compiler.get_display_language(), + 'supports{}'.format(' link' if mode is _TestMode.LINKER else ''), + 'arguments {}:'.format(' '.join(arguments)), + mlog.green('YES') if result else mlog.red('NO'), + cached_msg) + return result + + @noKwargs + @typed_pos_args('compiler.has_argument', str) + def has_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: + return self._has_argument_impl([args[0]]) + + @noKwargs + @typed_pos_args('compiler.has_multi_arguments', varargs=str) + @FeatureNew('compiler.has_multi_arguments', '0.37.0') + def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool: + return self._has_argument_impl(args[0]) + + @FeatureNew('compiler.get_supported_arguments', '0.43.0') + @typed_pos_args('compiler.get_supported_arguments', varargs=str) + @typed_kwargs( + 'compiler.get_supported_arguments', + KwargInfo('checked', str, default='off', since='0.59.0', + validator=in_set_validator({'warn', 'require', 'off'})), + ) + def get_supported_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'GetSupportedArgumentKw') -> T.List[str]: + supported_args: T.List[str] = [] + checked = kwargs['checked'] + + for arg in args[0]: + if not self._has_argument_impl([arg]): + msg = f'Compiler for {self.compiler.get_display_language()} does not support "{arg}"' + if checked == 'warn': + mlog.warning(msg) + elif checked == 'require': + raise mesonlib.MesonException(msg) + else: + supported_args.append(arg) + return supported_args + + @noKwargs + @typed_pos_args('compiler.first_supported_argument', varargs=str) + def first_supported_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]: + for arg in args[0]: + if self._has_argument_impl([arg]): + mlog.log('First supported argument:', mlog.bold(arg)) + return [arg] + mlog.log('First supported argument:', mlog.red('None')) + return [] + + @FeatureNew('compiler.has_link_argument', '0.46.0') + @noKwargs + @typed_pos_args('compiler.has_link_argument', str) + def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: + return self._has_argument_impl([args[0]], mode=_TestMode.LINKER) + + @FeatureNew('compiler.has_multi_link_argument', '0.46.0') + @noKwargs + @typed_pos_args('compiler.has_multi_link_argument', varargs=str) + def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool: + return self._has_argument_impl(args[0], mode=_TestMode.LINKER) + + @FeatureNew('compiler.get_supported_link_arguments', '0.46.0') + @noKwargs + @typed_pos_args('compiler.get_supported_link_arguments', varargs=str) + def get_supported_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]: + supported_args: T.List[str] = [] + for arg in args[0]: + if self._has_argument_impl([arg], mode=_TestMode.LINKER): + supported_args.append(arg) + return supported_args + + @FeatureNew('compiler.first_supported_link_argument_method', '0.46.0') + @noKwargs + @typed_pos_args('compiler.first_supported_link_argument', varargs=str) + def first_supported_link_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]: + for arg in args[0]: + if self._has_argument_impl([arg], mode=_TestMode.LINKER): + mlog.log('First supported link argument:', mlog.bold(arg)) + return [arg] + mlog.log('First supported link argument:', mlog.red('None')) + return [] + + def _has_function_attribute_impl(self, attr: str) -> bool: + """Common helper for function attribute testing.""" + result, cached = self.compiler.has_func_attribute(attr, self.environment) + cached_msg = mlog.blue('(cached)') if cached else '' + h = mlog.green('YES') if result else mlog.red('NO') + mlog.log(f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:', h, cached_msg) + return result + + @FeatureNew('compiler.has_function_attribute', '0.48.0') + @noKwargs + @typed_pos_args('compiler.has_function_attribute', str) + def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: + return self._has_function_attribute_impl(args[0]) + + @FeatureNew('compiler.get_supported_function_attributes', '0.48.0') + @noKwargs + @typed_pos_args('compiler.get_supported_function_attributes', varargs=str) + def get_supported_function_attributes_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]: + return [a for a in args[0] if self._has_function_attribute_impl(a)] + + @FeatureNew('compiler.get_argument_syntax_method', '0.49.0') + @noPosargs + @noKwargs + def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.compiler.get_argument_syntax() + + @FeatureNew('compiler.preprocess', '0.64.0') + @typed_pos_args('compiler.preprocess', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), min_varargs=1) + @typed_kwargs( + 'compiler.preprocess', + KwargInfo('output', str, default='@PLAINNAME@.i'), + KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]), + _INCLUDE_DIRS_KW, + _DEPENDENCIES_KW.evolve(since='1.1.0'), + ) + def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]: + compiler = self.compiler.get_preprocessor() + sources: 'SourceOutputs' = self.interpreter.source_strings_to_files(args[0]) + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in sources): + FeatureNew.single_use('compiler.preprocess with generated sources', '1.1.0', self.subproject, + location=self.current_node) + + tg_counter = next(self.preprocess_uid[self.interpreter.subdir]) + if tg_counter > 0: + FeatureNew.single_use('compiler.preprocess used multiple times', '1.1.0', self.subproject, + location=self.current_node) + tg_name = f'preprocessor_{tg_counter}' + tg = build.CompileTarget( + tg_name, + self.interpreter.subdir, + self.subproject, + self.environment, + sources, + kwargs['output'], + compiler, + self.interpreter.backend, + kwargs['compile_args'], + kwargs['include_directories'], + kwargs['dependencies']) + self.interpreter.add_target(tg.name, tg) + # Expose this target as list of its outputs, so user can pass them to + # other targets, list outputs, etc. + private_dir = os.path.relpath(self.interpreter.backend.get_target_private_dir(tg), self.interpreter.subdir) + return [build.CustomTargetIndex(tg, os.path.join(private_dir, o)) for o in tg.outputs] diff --git a/devtools/meson/mesonbuild/interpreter/dependencyfallbacks.py b/devtools/meson/mesonbuild/interpreter/dependencyfallbacks.py new file mode 100644 index 0000000..7ef1527 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/dependencyfallbacks.py @@ -0,0 +1,374 @@ +from __future__ import annotations + +from .interpreterobjects import extract_required_kwarg +from .. import mlog +from .. import dependencies +from .. import build +from ..wrap import WrapMode +from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many, listify +from ..dependencies import Dependency, DependencyException, NotFoundDependency +from ..interpreterbase import (MesonInterpreterObject, FeatureNew, + InterpreterException, InvalidArguments) + +import typing as T +if T.TYPE_CHECKING: + from .interpreter import Interpreter + from ..interpreterbase import TYPE_nkwargs, TYPE_nvar + from .interpreterobjects import SubprojectHolder + + +class DependencyFallbacksHolder(MesonInterpreterObject): + def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None, + default_options: T.Optional[T.Dict[OptionKey, str]] = None) -> None: + super().__init__(subproject=interpreter.subproject) + self.interpreter = interpreter + self.subproject = interpreter.subproject + self.coredata = interpreter.coredata + self.build = interpreter.build + self.environment = interpreter.environment + self.wrap_resolver = interpreter.environment.wrap_resolver + self.allow_fallback = allow_fallback + self.subproject_name: T.Optional[str] = None + self.subproject_varname: T.Optional[str] = None + self.subproject_kwargs = {'default_options': default_options or {}} + self.names: T.List[str] = [] + self.forcefallback: bool = False + self.nofallback: bool = False + for name in names: + if not name: + raise InterpreterException('dependency_fallbacks empty name \'\' is not allowed') + if '<' in name or '>' in name or '=' in name: + raise InvalidArguments('Characters <, > and = are forbidden in dependency names. To specify' + 'version\n requirements use the \'version\' keyword argument instead.') + if name in self.names: + raise InterpreterException(f'dependency_fallbacks name {name!r} is duplicated') + self.names.append(name) + self._display_name = self.names[0] if self.names else '(anonymous)' + + def set_fallback(self, fbinfo: T.Optional[T.Union[T.List[str], str]]) -> None: + # Legacy: This converts dependency()'s fallback kwargs. + if fbinfo is None: + return + if self.allow_fallback is not None: + raise InvalidArguments('"fallback" and "allow_fallback" arguments are mutually exclusive') + fbinfo = stringlistify(fbinfo) + if len(fbinfo) == 0: + # dependency('foo', fallback: []) is the same as dependency('foo', allow_fallback: false) + self.allow_fallback = False + return + if len(fbinfo) == 1: + FeatureNew.single_use('Fallback without variable name', '0.53.0', self.subproject) + subp_name, varname = fbinfo[0], None + elif len(fbinfo) == 2: + subp_name, varname = fbinfo + else: + raise InterpreterException('Fallback info must have one or two items.') + self._subproject_impl(subp_name, varname) + + def _subproject_impl(self, subp_name: str, varname: str) -> None: + assert self.subproject_name is None + self.subproject_name = subp_name + self.subproject_varname = varname + + def _do_dependency_cache(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: + name = func_args[0] + cached_dep = self._get_cached_dep(name, kwargs) + if cached_dep: + self._verify_fallback_consistency(cached_dep) + return cached_dep + + def _do_dependency(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: + # Note that there is no df.dependency() method, this is called for names + # given as positional arguments to dependency_fallbacks(name1, ...). + # We use kwargs from the dependency() function, for things like version, + # module, etc. + name = func_args[0] + self._handle_featurenew_dependencies(name) + dep = dependencies.find_external_dependency(name, self.environment, kwargs) + if dep.found(): + for_machine = self.interpreter.machine_from_native_kwarg(kwargs) + identifier = dependencies.get_dep_identifier(name, kwargs) + self.coredata.deps[for_machine].put(identifier, dep) + return dep + return None + + def _do_existing_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: + subp_name = func_args[0] + varname = self.subproject_varname + if subp_name and self._get_subproject(subp_name): + return self._get_subproject_dep(subp_name, varname, kwargs) + return None + + def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: + if self.forcefallback: + mlog.log('Looking for a fallback subproject for the dependency', + mlog.bold(self._display_name), 'because:\nUse of fallback dependencies is forced.') + elif self.nofallback: + mlog.log('Not looking for a fallback subproject for the dependency', + mlog.bold(self._display_name), 'because:\nUse of fallback dependencies is disabled.') + return None + else: + mlog.log('Looking for a fallback subproject for the dependency', + mlog.bold(self._display_name)) + + # dependency('foo', static: true) should implicitly add + # default_options: ['default_library=static'] + static = kwargs.get('static') + default_options = func_kwargs.get('default_options', {}) + if static is not None and 'default_library' not in default_options: + default_library = 'static' if static else 'shared' + mlog.log(f'Building fallback subproject with default_library={default_library}') + default_options[OptionKey('default_library')] = default_library + func_kwargs['default_options'] = default_options + + # Configure the subproject + subp_name = self.subproject_name + varname = self.subproject_varname + func_kwargs.setdefault('version', []) + if 'default_options' in kwargs and isinstance(kwargs['default_options'], str): + func_kwargs['default_options'] = listify(kwargs['default_options']) + self.interpreter.do_subproject(subp_name, 'meson', func_kwargs) + return self._get_subproject_dep(subp_name, varname, kwargs) + + def _get_subproject(self, subp_name: str) -> T.Optional[SubprojectHolder]: + sub = self.interpreter.subprojects.get(subp_name) + if sub and sub.found(): + return sub + return None + + def _get_subproject_dep(self, subp_name: str, varname: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: + # Verify the subproject is found + subproject = self._get_subproject(subp_name) + if not subproject: + mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject', + mlog.bold(subp_name), 'found:', mlog.red('NO'), + mlog.blue('(subproject failed to configure)')) + return None + + # The subproject has been configured. If for any reason the dependency + # cannot be found in this subproject we have to return not-found object + # instead of None, because we don't want to continue the lookup on the + # system. + + # Check if the subproject overridden at least one of the names we got. + cached_dep = None + for name in self.names: + cached_dep = self._get_cached_dep(name, kwargs) + if cached_dep: + break + + # If we have cached_dep we did all the checks and logging already in + # self._get_cached_dep(). + if cached_dep: + self._verify_fallback_consistency(cached_dep) + return cached_dep + + # Legacy: Use the variable name if provided instead of relying on the + # subproject to override one of our dependency names + if not varname: + # If no variable name is specified, check if the wrap file has one. + # If the wrap file has a variable name, better use it because the + # subproject most probably is not using meson.override_dependency(). + for name in self.names: + varname = self.wrap_resolver.get_varname(subp_name, name) + if varname: + break + if not varname: + mlog.warning(f'Subproject {subp_name!r} did not override {self._display_name!r} dependency and no variable name specified') + mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject', + mlog.bold(subproject.subdir), 'found:', mlog.red('NO')) + return self._notfound_dependency() + + var_dep = self._get_subproject_variable(subproject, varname) or self._notfound_dependency() + if not var_dep.found(): + mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject', + mlog.bold(subproject.subdir), 'found:', mlog.red('NO')) + return var_dep + + wanted = stringlistify(kwargs.get('version', [])) + found = var_dep.get_version() + if not self._check_version(wanted, found): + mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject', + mlog.bold(subproject.subdir), 'found:', mlog.red('NO'), + 'found', mlog.normal_cyan(found), 'but need:', + mlog.bold(', '.join([f"'{e}'" for e in wanted]))) + return self._notfound_dependency() + + mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject', + mlog.bold(subproject.subdir), 'found:', mlog.green('YES'), + mlog.normal_cyan(found) if found else None) + return var_dep + + def _get_cached_dep(self, name: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: + # Unlike other methods, this one returns not-found dependency instead + # of None in the case the dependency is cached as not-found, or if cached + # version does not match. In that case we don't want to continue with + # other candidates. + for_machine = self.interpreter.machine_from_native_kwarg(kwargs) + identifier = dependencies.get_dep_identifier(name, kwargs) + wanted_vers = stringlistify(kwargs.get('version', [])) + + override = self.build.dependency_overrides[for_machine].get(identifier) + if override: + info = [mlog.blue('(overridden)' if override.explicit else '(cached)')] + cached_dep = override.dep + # We don't implicitly override not-found dependencies, but user could + # have explicitly called meson.override_dependency() with a not-found + # dep. + if not cached_dep.found(): + mlog.log('Dependency', mlog.bold(self._display_name), + 'found:', mlog.red('NO'), *info) + return cached_dep + elif self.forcefallback and self.subproject_name: + cached_dep = None + else: + info = [mlog.blue('(cached)')] + cached_dep = self.coredata.deps[for_machine].get(identifier) + + if cached_dep: + found_vers = cached_dep.get_version() + if not self._check_version(wanted_vers, found_vers): + if not override: + # We cached this dependency on disk from a previous run, + # but it could got updated on the system in the meantime. + return None + mlog.log('Dependency', mlog.bold(name), + 'found:', mlog.red('NO'), + 'found', mlog.normal_cyan(found_vers), 'but need:', + mlog.bold(', '.join([f"'{e}'" for e in wanted_vers])), + *info) + return self._notfound_dependency() + if found_vers: + info = [mlog.normal_cyan(found_vers), *info] + mlog.log('Dependency', mlog.bold(self._display_name), + 'found:', mlog.green('YES'), *info) + return cached_dep + return None + + def _get_subproject_variable(self, subproject: SubprojectHolder, varname: str) -> T.Optional[Dependency]: + try: + var_dep = subproject.get_variable_method([varname], {}) + except InvalidArguments: + var_dep = None + if not isinstance(var_dep, Dependency): + mlog.warning(f'Variable {varname!r} in the subproject {subproject.subdir!r} is', + 'not found' if var_dep is None else 'not a dependency object') + return None + return var_dep + + def _verify_fallback_consistency(self, cached_dep: Dependency) -> None: + subp_name = self.subproject_name + varname = self.subproject_varname + subproject = self._get_subproject(subp_name) + if subproject and varname: + var_dep = self._get_subproject_variable(subproject, varname) + if var_dep and cached_dep.found() and var_dep != cached_dep: + mlog.warning(f'Inconsistency: Subproject has overridden the dependency with another variable than {varname!r}') + + def _handle_featurenew_dependencies(self, name: str) -> None: + 'Do a feature check on dependencies used by this subproject' + if name == 'mpi': + FeatureNew.single_use('MPI Dependency', '0.42.0', self.subproject) + elif name == 'pcap': + FeatureNew.single_use('Pcap Dependency', '0.42.0', self.subproject) + elif name == 'vulkan': + FeatureNew.single_use('Vulkan Dependency', '0.42.0', self.subproject) + elif name == 'libwmf': + FeatureNew.single_use('LibWMF Dependency', '0.44.0', self.subproject) + elif name == 'openmp': + FeatureNew.single_use('OpenMP Dependency', '0.46.0', self.subproject) + + def _notfound_dependency(self) -> NotFoundDependency: + return NotFoundDependency(self.names[0] if self.names else '', self.environment) + + @staticmethod + def _check_version(wanted: T.List[str], found: str) -> bool: + if not wanted: + return True + return not (found == 'undefined' or not version_compare_many(found, wanted)[0]) + + def _get_candidates(self) -> T.List[T.Tuple[T.Callable[[TYPE_nkwargs, TYPE_nvar, TYPE_nkwargs], T.Optional[Dependency]], TYPE_nvar, TYPE_nkwargs]]: + candidates = [] + # 1. check if any of the names is cached already. + for name in self.names: + candidates.append((self._do_dependency_cache, [name], {})) + # 2. check if the subproject fallback has already been configured. + if self.subproject_name: + candidates.append((self._do_existing_subproject, [self.subproject_name], self.subproject_kwargs)) + # 3. check external dependency if we are not forced to use subproject + if not self.forcefallback or not self.subproject_name: + for name in self.names: + candidates.append((self._do_dependency, [name], {})) + # 4. configure the subproject + if self.subproject_name: + candidates.append((self._do_subproject, [self.subproject_name], self.subproject_kwargs)) + return candidates + + def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> Dependency: + mods = extract_as_list(kwargs, 'modules') + if mods: + self._display_name += ' (modules: {})'.format(', '.join(str(i) for i in mods)) + + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) + if disabled: + mlog.log('Dependency', mlog.bold(self._display_name), 'skipped: feature', mlog.bold(feature), 'disabled') + return self._notfound_dependency() + + # Check if usage of the subproject fallback is forced + wrap_mode = self.coredata.get_option(OptionKey('wrap_mode')) + assert isinstance(wrap_mode, WrapMode), 'for mypy' + force_fallback_for = self.coredata.get_option(OptionKey('force_fallback_for')) + assert isinstance(force_fallback_for, list), 'for mypy' + self.nofallback = wrap_mode == WrapMode.nofallback + self.forcefallback = (force_fallback or + wrap_mode == WrapMode.forcefallback or + any(name in force_fallback_for for name in self.names) or + self.subproject_name in force_fallback_for) + + # Add an implicit subproject fallback if none has been set explicitly, + # unless implicit fallback is not allowed. + # Legacy: self.allow_fallback can be None when that kwarg is not defined + # in dependency('name'). In that case we don't want to use implicit + # fallback when required is false because user will typically fallback + # manually using cc.find_library() for example. + if not self.subproject_name and self.allow_fallback is not False: + for name in self.names: + subp_name, varname = self.wrap_resolver.find_dep_provider(name) + if subp_name: + self.forcefallback |= subp_name in force_fallback_for + if self.forcefallback or self.allow_fallback is True or required or self._get_subproject(subp_name): + self._subproject_impl(subp_name, varname) + break + + candidates = self._get_candidates() + + # writing just "dependency('')" is an error, because it can only fail + if not candidates and required: + raise InvalidArguments('Dependency is required but has no candidates.') + + # Try all candidates, only the last one is really required. + last = len(candidates) - 1 + for i, item in enumerate(candidates): + func, func_args, func_kwargs = item + func_kwargs['required'] = required and (i == last) + kwargs['required'] = required and (i == last) + dep = func(kwargs, func_args, func_kwargs) + if dep and dep.found(): + # Override this dependency to have consistent results in subsequent + # dependency lookups. + for name in self.names: + for_machine = self.interpreter.machine_from_native_kwarg(kwargs) + identifier = dependencies.get_dep_identifier(name, kwargs) + if identifier not in self.build.dependency_overrides[for_machine]: + self.build.dependency_overrides[for_machine][identifier] = \ + build.DependencyOverride(dep, self.interpreter.current_node, explicit=False) + return dep + elif required and (dep or i == last): + # This was the last candidate or the dependency has been cached + # as not-found, or cached dependency version does not match, + # otherwise func() would have returned None instead. + raise DependencyException(f'Dependency {self._display_name!r} is required but not found.') + elif dep: + # Same as above, but the dependency is not required. + return dep + return self._notfound_dependency() diff --git a/devtools/meson/mesonbuild/interpreter/interpreter.py b/devtools/meson/mesonbuild/interpreter/interpreter.py new file mode 100644 index 0000000..19b60d0 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/interpreter.py @@ -0,0 +1,3408 @@ +# Copyright 2012-2021 The Meson development team +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mparser +from .. import environment +from .. import coredata +from .. import dependencies +from .. import mlog +from .. import build +from .. import optinterpreter +from .. import compilers +from .. import envconfig +from ..wrap import wrap, WrapMode +from .. import mesonlib +from ..mesonlib import (MesonBugException, MesonException, HoldableObject, + FileMode, MachineChoice, OptionKey, listify, + extract_as_list, has_path_sep, PerMachine) +from ..programs import ExternalProgram, NonExistingExternalProgram +from ..dependencies import Dependency +from ..depfile import DepFile +from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args +from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, noArgsFlattening, noSecondLevelHolderResolving, unholder_return +from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest +from ..interpreterbase import Disabler, disablerIfNotFound +from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs, FeatureDeprecatedKwargs +from ..interpreterbase import ObjectHolder, ContextManagerObject +from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule +from ..backend.backends import ExecutableSerialisation +from ..optinterpreter import optname_regex + +from . import interpreterobjects as OBJ +from . import compiler as compilerOBJ +from .mesonmain import MesonMain +from .dependencyfallbacks import DependencyFallbacksHolder +from .interpreterobjects import ( + SubprojectHolder, + Test, + RunProcess, + extract_required_kwarg, + extract_search_dirs, + NullSubprojectInterpreter, +) +from .type_checking import ( + COMMAND_KW, + CT_BUILD_ALWAYS, + CT_BUILD_ALWAYS_STALE, + CT_BUILD_BY_DEFAULT, + CT_INPUT_KW, + CT_INSTALL_DIR_KW, + MULTI_OUTPUT_KW, + OUTPUT_KW, + DEFAULT_OPTIONS, + DEPENDENCIES_KW, + DEPENDS_KW, + DEPEND_FILES_KW, + DEPFILE_KW, + DISABLER_KW, + D_MODULE_VERSIONS_KW, + ENV_KW, + ENV_METHOD_KW, + ENV_SEPARATOR_KW, + INCLUDE_DIRECTORIES, + INSTALL_KW, + INSTALL_DIR_KW, + INSTALL_MODE_KW, + LINK_WITH_KW, + LINK_WHOLE_KW, + CT_INSTALL_TAG_KW, + INSTALL_TAG_KW, + LANGUAGE_KW, + NATIVE_KW, + OVERRIDE_OPTIONS_KW, + PRESERVE_PATH_KW, + REQUIRED_KW, + SOURCES_KW, + VARIABLES_KW, + TEST_KWS, + NoneType, + in_set_validator, + env_convertor_with_method +) +from . import primitives as P_OBJ + +from pathlib import Path +from enum import Enum +import os +import shutil +import uuid +import re +import stat +import collections +import typing as T +import textwrap +import importlib +import copy + +if T.TYPE_CHECKING: + import argparse + + from typing_extensions import Literal + + from . import kwargs as kwtypes + from ..backend.backends import Backend + from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs + from ..programs import OverrideProgram + + # Input source types passed to Targets + SourceInputs = T.Union[mesonlib.File, build.GeneratedList, build.BuildTarget, build.BothLibraries, + build.CustomTargetIndex, build.CustomTarget, build.GeneratedList, + build.ExtractedObjects, str] + # Input source types passed to the build.Target classes + SourceOutputs = T.Union[mesonlib.File, build.GeneratedList, + build.BuildTarget, build.CustomTargetIndex, build.CustomTarget, + build.ExtractedObjects, build.GeneratedList, build.StructuredSources] + + BuildTargetSource = T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources] + + +def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) -> T.Optional[str]: + if isinstance(value, list): + if len(value) != 1: + return 'when passed as array must have a length of 1' + elif not isinstance(value[0], mesonlib.File): + return 'when passed as array must contain a File' + return None + + +def stringifyUserArguments(args: T.List[T.Any], quote: bool = False) -> str: + if isinstance(args, list): + return '[%s]' % ', '.join([stringifyUserArguments(x, True) for x in args]) + elif isinstance(args, dict): + return '{%s}' % ', '.join(['{} : {}'.format(stringifyUserArguments(k, True), stringifyUserArguments(v, True)) for k, v in args.items()]) + elif isinstance(args, bool): + return 'true' if args else 'false' + elif isinstance(args, int): + return str(args) + elif isinstance(args, str): + return f"'{args}'" if quote else args + raise InvalidArguments('Function accepts only strings, integers, bools, lists, dictionaries and lists thereof.') + +class Summary: + def __init__(self, project_name: str, project_version: str): + self.project_name = project_name + self.project_version = project_version + self.sections = collections.defaultdict(dict) + self.max_key_len = 0 + + def add_section(self, section: str, values: T.Dict[str, T.Any], bool_yn: bool, + list_sep: T.Optional[str], subproject: str) -> None: + for k, v in values.items(): + if k in self.sections[section]: + raise InterpreterException(f'Summary section {section!r} already have key {k!r}') + formatted_values = [] + for i in listify(v): + if isinstance(i, bool) and bool_yn: + formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) + elif isinstance(i, (str, int, bool)): + formatted_values.append(str(i)) + elif isinstance(i, (ExternalProgram, Dependency)): + FeatureNew.single_use('dependency or external program in summary', '0.57.0', subproject) + formatted_values.append(i.summary_value()) + elif isinstance(i, Disabler): + FeatureNew.single_use('disabler in summary', '0.64.0', subproject) + formatted_values.append(mlog.red('NO')) + elif isinstance(i, coredata.UserOption): + FeatureNew.single_use('feature option in summary', '0.58.0', subproject) + formatted_values.append(i.printable_value()) + else: + m = 'Summary value in section {!r}, key {!r}, must be string, integer, boolean, dependency, disabler, or external program' + raise InterpreterException(m.format(section, k)) + self.sections[section][k] = (formatted_values, list_sep) + self.max_key_len = max(self.max_key_len, len(k)) + + def dump(self): + mlog.log(self.project_name, mlog.normal_cyan(self.project_version)) + for section, values in self.sections.items(): + mlog.log('') # newline + if section: + mlog.log(' ', mlog.bold(section)) + for k, v in values.items(): + v, list_sep = v + padding = self.max_key_len - len(k) + end = ' ' if v else '' + mlog.log(' ' * 3, k + ' ' * padding + ':', end=end) + indent = self.max_key_len + 6 + self.dump_value(v, list_sep, indent) + mlog.log('') # newline + + def dump_value(self, arr, list_sep, indent): + lines_sep = '\n' + ' ' * indent + if list_sep is None: + mlog.log(*arr, sep=lines_sep) + return + max_len = shutil.get_terminal_size().columns + line = [] + line_len = indent + lines_sep = list_sep.rstrip() + lines_sep + for v in arr: + v_len = len(v) + len(list_sep) + if line and line_len + v_len > max_len: + mlog.log(*line, sep=list_sep, end=lines_sep) + line_len = indent + line = [] + line.append(v) + line_len += v_len + mlog.log(*line, sep=list_sep) + +known_library_kwargs = ( + build.known_shlib_kwargs | + build.known_stlib_kwargs +) + +known_build_target_kwargs = ( + known_library_kwargs | + build.known_exe_kwargs | + build.known_jar_kwargs | + {'target_type'} +) + +class InterpreterRuleRelaxation(Enum): + ''' Defines specific relaxations of the Meson rules. + + This is intended to be used for automatically converted + projects (CMake subprojects, build system mixing) that + generate a Meson AST via introspection, etc. + ''' + + ALLOW_BUILD_DIR_FILE_REFERENCES = 1 + +permitted_dependency_kwargs = { + 'allow_fallback', + 'cmake_args', + 'cmake_module_path', + 'cmake_package_version', + 'components', + 'default_options', + 'fallback', + 'include_type', + 'language', + 'main', + 'method', + 'modules', + 'native', + 'not_found_message', + 'optional_modules', + 'private_headers', + 'required', + 'static', + 'version', +} + +implicit_check_false_warning = """You should add the boolean check kwarg to the run_command call. + It currently defaults to false, + but it will default to true in future releases of meson. + See also: https://github.com/mesonbuild/meson/issues/9300""" +class Interpreter(InterpreterBase, HoldableObject): + + def __init__( + self, + _build: build.Build, + backend: T.Optional[Backend] = None, + subproject: str = '', + subdir: str = '', + subproject_dir: str = 'subprojects', + default_project_options: T.Optional[T.Dict[OptionKey, str]] = None, + mock: bool = False, + ast: T.Optional[mparser.CodeBlockNode] = None, + is_translated: bool = False, + relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None, + user_defined_options: T.Optional['argparse.Namespace'] = None, + ) -> None: + super().__init__(_build.environment.get_source_dir(), subdir, subproject) + self.active_projectname = '' + self.build = _build + self.environment = self.build.environment + self.coredata = self.environment.get_coredata() + self.backend = backend + self.summary: T.Dict[str, 'Summary'] = {} + self.modules: T.Dict[str, NewExtensionModule] = {} + # Subproject directory is usually the name of the subproject, but can + # be different for dependencies provided by wrap files. + self.subproject_directory_name = subdir.split(os.path.sep)[-1] + self.subproject_dir = subproject_dir + self.relaxations = relaxations or set() + if not mock and ast is None: + self.load_root_meson_file() + self.sanity_check_ast() + elif ast is not None: + self.ast = ast + self.sanity_check_ast() + self.builtin.update({'meson': MesonMain(self.build, self)}) + self.generators: T.List[build.Generator] = [] + self.processed_buildfiles = set() # type: T.Set[str] + self.project_args_frozen = False + self.global_args_frozen = False # implies self.project_args_frozen + self.subprojects: T.Dict[str, SubprojectHolder] = {} + self.subproject_stack: T.List[str] = [] + self.configure_file_outputs: T.Dict[str, int] = {} + # Passed from the outside, only used in subprojects. + if default_project_options: + self.default_project_options = default_project_options.copy() + else: + self.default_project_options = {} + self.project_default_options: T.Dict[OptionKey, str] = {} + self.build_func_dict() + self.build_holder_map() + self.user_defined_options = user_defined_options + self.compilers: PerMachine[T.Dict[str, 'compilers.Compiler']] = PerMachine({}, {}) + + # build_def_files needs to be defined before parse_project is called + # + # For non-meson subprojects, we'll be using the ast. Even if it does + # exist we don't want to add a dependency on it, it's autogenerated + # from the actual build files, and is just for reference. + self.build_def_files: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() + build_filename = os.path.join(self.subdir, environment.build_filename) + if not is_translated: + self.build_def_files.add(build_filename) + if not mock: + self.parse_project() + self._redetect_machines() + + def __getnewargs_ex__(self) -> T.Tuple[T.Tuple[object], T.Dict[str, object]]: + raise MesonBugException('This class is unpicklable') + + def _redetect_machines(self) -> None: + # Re-initialize machine descriptions. We can do a better job now because we + # have the compilers needed to gain more knowledge, so wipe out old + # inference and start over. + machines = self.build.environment.machines.miss_defaulting() + machines.build = environment.detect_machine_info(self.coredata.compilers.build) + self.build.environment.machines = machines.default_missing() + assert self.build.environment.machines.build.cpu is not None + assert self.build.environment.machines.host.cpu is not None + assert self.build.environment.machines.target.cpu is not None + + self.builtin['build_machine'] = \ + OBJ.MachineHolder(self.build.environment.machines.build, self) + self.builtin['host_machine'] = \ + OBJ.MachineHolder(self.build.environment.machines.host, self) + self.builtin['target_machine'] = \ + OBJ.MachineHolder(self.build.environment.machines.target, self) + + def build_func_dict(self) -> None: + self.funcs.update({'add_global_arguments': self.func_add_global_arguments, + 'add_global_link_arguments': self.func_add_global_link_arguments, + 'add_languages': self.func_add_languages, + 'add_project_arguments': self.func_add_project_arguments, + 'add_project_dependencies': self.func_add_project_dependencies, + 'add_project_link_arguments': self.func_add_project_link_arguments, + 'add_test_setup': self.func_add_test_setup, + 'alias_target': self.func_alias_target, + 'assert': self.func_assert, + 'benchmark': self.func_benchmark, + 'both_libraries': self.func_both_lib, + 'build_target': self.func_build_target, + 'configuration_data': self.func_configuration_data, + 'configure_file': self.func_configure_file, + 'custom_target': self.func_custom_target, + 'debug': self.func_debug, + 'declare_dependency': self.func_declare_dependency, + 'dependency': self.func_dependency, + 'disabler': self.func_disabler, + 'environment': self.func_environment, + 'error': self.func_error, + 'executable': self.func_executable, + 'files': self.func_files, + 'find_library': self.func_find_library, + 'find_program': self.func_find_program, + 'generator': self.func_generator, + 'get_option': self.func_get_option, + 'get_variable': self.func_get_variable, + 'gettext': self.func_gettext, + 'import': self.func_import, + 'include_directories': self.func_include_directories, + 'install_data': self.func_install_data, + 'install_emptydir': self.func_install_emptydir, + 'install_headers': self.func_install_headers, + 'install_man': self.func_install_man, + 'install_subdir': self.func_install_subdir, + 'install_symlink': self.func_install_symlink, + 'is_disabler': self.func_is_disabler, + 'is_variable': self.func_is_variable, + 'jar': self.func_jar, + 'join_paths': self.func_join_paths, + 'library': self.func_library, + 'message': self.func_message, + 'option': self.func_option, + 'project': self.func_project, + 'range': self.func_range, + 'run_command': self.func_run_command, + 'run_target': self.func_run_target, + 'set_variable': self.func_set_variable, + 'structured_sources': self.func_structured_sources, + 'subdir': self.func_subdir, + 'shared_library': self.func_shared_lib, + 'shared_module': self.func_shared_module, + 'static_library': self.func_static_lib, + 'subdir_done': self.func_subdir_done, + 'subproject': self.func_subproject, + 'summary': self.func_summary, + 'test': self.func_test, + 'unset_variable': self.func_unset_variable, + 'vcs_tag': self.func_vcs_tag, + 'warning': self.func_warning, + }) + if 'MESON_UNIT_TEST' in os.environ: + self.funcs.update({'exception': self.func_exception}) + if 'MESON_RUNNING_IN_PROJECT_TESTS' in os.environ: + self.funcs.update({'expect_error': self.func_expect_error}) + + def build_holder_map(self) -> None: + ''' + Build a mapping of `HoldableObject` types to their corresponding + `ObjectHolder`s. This mapping is used in `InterpreterBase` to automatically + holderify all returned values from methods and functions. + ''' + self.holder_map.update({ + # Primitives + list: P_OBJ.ArrayHolder, + dict: P_OBJ.DictHolder, + int: P_OBJ.IntegerHolder, + bool: P_OBJ.BooleanHolder, + str: P_OBJ.StringHolder, + P_OBJ.MesonVersionString: P_OBJ.MesonVersionStringHolder, + P_OBJ.DependencyVariableString: P_OBJ.DependencyVariableStringHolder, + P_OBJ.OptionString: P_OBJ.OptionStringHolder, + + # Meson types + mesonlib.File: OBJ.FileHolder, + build.SharedLibrary: OBJ.SharedLibraryHolder, + build.StaticLibrary: OBJ.StaticLibraryHolder, + build.BothLibraries: OBJ.BothLibrariesHolder, + build.SharedModule: OBJ.SharedModuleHolder, + build.Executable: OBJ.ExecutableHolder, + build.Jar: OBJ.JarHolder, + build.CustomTarget: OBJ.CustomTargetHolder, + build.CustomTargetIndex: OBJ.CustomTargetIndexHolder, + build.Generator: OBJ.GeneratorHolder, + build.GeneratedList: OBJ.GeneratedListHolder, + build.ExtractedObjects: OBJ.GeneratedObjectsHolder, + build.RunTarget: OBJ.RunTargetHolder, + build.AliasTarget: OBJ.AliasTargetHolder, + build.Headers: OBJ.HeadersHolder, + build.Man: OBJ.ManHolder, + build.EmptyDir: OBJ.EmptyDirHolder, + build.Data: OBJ.DataHolder, + build.SymlinkData: OBJ.SymlinkDataHolder, + build.InstallDir: OBJ.InstallDirHolder, + build.IncludeDirs: OBJ.IncludeDirsHolder, + build.EnvironmentVariables: OBJ.EnvironmentVariablesHolder, + build.StructuredSources: OBJ.StructuredSourcesHolder, + compilers.RunResult: compilerOBJ.TryRunResultHolder, + dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder, + coredata.UserFeatureOption: OBJ.FeatureOptionHolder, + envconfig.MachineInfo: OBJ.MachineHolder, + build.ConfigurationData: OBJ.ConfigurationDataHolder, + }) + + ''' + Build a mapping of `HoldableObject` base classes to their + corresponding `ObjectHolder`s. The difference to `self.holder_map` + is that the keys here define an upper bound instead of requiring an + exact match. + + The mappings defined here are only used when there was no direct hit + found in `self.holder_map`. + ''' + self.bound_holder_map.update({ + dependencies.Dependency: OBJ.DependencyHolder, + ExternalProgram: OBJ.ExternalProgramHolder, + compilers.Compiler: compilerOBJ.CompilerHolder, + ModuleObject: OBJ.ModuleObjectHolder, + MutableModuleObject: OBJ.MutableModuleObjectHolder, + }) + + def append_holder_map(self, held_type: T.Type[mesonlib.HoldableObject], holder_type: T.Type[ObjectHolder]) -> None: + ''' + Adds one additional mapping to the `holder_map`. + + The intended use for this function is in the `initialize` method of + modules to register custom object holders. + ''' + self.holder_map.update({ + held_type: holder_type + }) + + def process_new_values(self, invalues: T.List[T.Union[TYPE_var, ExecutableSerialisation]]) -> None: + invalues = listify(invalues) + for v in invalues: + if isinstance(v, ObjectHolder): + raise InterpreterException('Modules must not return ObjectHolders') + if isinstance(v, (build.BuildTarget, build.CustomTarget, build.RunTarget)): + self.add_target(v.name, v) + elif isinstance(v, list): + self.process_new_values(v) + elif isinstance(v, ExecutableSerialisation): + v.subproject = self.subproject + self.build.install_scripts.append(v) + elif isinstance(v, build.Data): + self.build.data.append(v) + elif isinstance(v, build.SymlinkData): + self.build.symlinks.append(v) + elif isinstance(v, dependencies.InternalDependency): + # FIXME: This is special cased and not ideal: + # The first source is our new VapiTarget, the rest are deps + self.process_new_values(v.sources[0]) + elif isinstance(v, build.InstallDir): + self.build.install_dirs.append(v) + elif isinstance(v, Test): + self.build.tests.append(v) + elif isinstance(v, (int, str, bool, Disabler, ObjectHolder, build.GeneratedList, + ExternalProgram, build.ConfigurationData)): + pass + else: + raise InterpreterException(f'Module returned a value of unknown type {v!r}.') + + def handle_meson_version(self, pv: str, location: mparser.BaseNode) -> None: + if not mesonlib.version_compare(coredata.stable_version, pv): + raise InterpreterException.from_node(f'Meson version is {coredata.version} but project requires {pv}', node=location) + mesonlib.project_meson_versions[self.subproject] = pv + + def handle_meson_version_from_ast(self) -> None: + if not self.ast.lines: + return + project = self.ast.lines[0] + # first line is always project() + if not isinstance(project, mparser.FunctionNode): + return + for kw, val in project.args.kwargs.items(): + assert isinstance(kw, mparser.IdNode), 'for mypy' + if kw.value == 'meson_version': + # mypy does not understand "and isinstance" + if isinstance(val, mparser.StringNode): + self.handle_meson_version(val.value, val) + + def get_build_def_files(self) -> mesonlib.OrderedSet[str]: + return self.build_def_files + + def add_build_def_file(self, f: mesonlib.FileOrString) -> None: + # Use relative path for files within source directory, and absolute path + # for system files. Skip files within build directory. Also skip not regular + # files (e.g. /dev/stdout) Normalize the path to avoid duplicates, this + # is especially important to convert '/' to '\' on Windows. + if isinstance(f, mesonlib.File): + if f.is_built: + return + f = os.path.normpath(f.relative_name()) + elif os.path.isfile(f) and not f.startswith('/dev'): + srcdir = Path(self.environment.get_source_dir()) + builddir = Path(self.environment.get_build_dir()) + try: + f_ = Path(f).resolve() + except OSError: + f_ = Path(f) + s = f_.stat() + if (hasattr(s, 'st_file_attributes') and + s.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT != 0 and + s.st_reparse_tag == stat.IO_REPARSE_TAG_APPEXECLINK): + # This is a Windows Store link which we can't + # resolve, so just do our best otherwise. + f_ = f_.parent.resolve() / f_.name + else: + raise + if builddir in f_.parents: + return + if srcdir in f_.parents: + f_ = f_.relative_to(srcdir) + f = str(f_) + else: + return + if f not in self.build_def_files: + self.build_def_files.add(f) + + def get_variables(self) -> T.Dict[str, InterpreterObject]: + return self.variables + + def check_stdlibs(self) -> None: + machine_choices = [MachineChoice.HOST] + if self.coredata.is_cross_build(): + machine_choices.append(MachineChoice.BUILD) + for for_machine in machine_choices: + props = self.build.environment.properties[for_machine] + for l in self.coredata.compilers[for_machine].keys(): + try: + di = mesonlib.stringlistify(props.get_stdlib(l)) + except KeyError: + continue + if len(di) == 1: + FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject, location=self.current_node) + kwargs = {'native': for_machine is MachineChoice.BUILD, + } + name = l + '_stdlib' + df = DependencyFallbacksHolder(self, [name]) + df.set_fallback(di) + dep = df.lookup(kwargs, force_fallback=True) + self.build.stdlibs[for_machine][l] = dep + + @typed_pos_args('import', str) + @typed_kwargs( + 'import', + REQUIRED_KW.evolve(since='0.59.0'), + DISABLER_KW.evolve(since='0.59.0'), + ) + @disablerIfNotFound + def func_import(self, node: mparser.BaseNode, args: T.Tuple[str], + kwargs: 'kwtypes.FuncImportModule') -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]: + modname = args[0] + disabled, required, _ = extract_required_kwarg(kwargs, self.subproject) + if disabled: + return NotFoundExtensionModule(modname) + + expect_unstable = False + # Some tests use "unstable_" instead of "unstable-", and that happens to work because + # of implementation details + if modname.startswith(('unstable-', 'unstable_')): + if modname.startswith('unstable_'): + mlog.deprecation(f'Importing unstable modules as "{modname}" instead of "{modname.replace("_", "-", 1)}"', + location=node) + real_modname = modname[len('unstable') + 1:] # + 1 to handle the - or _ + expect_unstable = True + else: + real_modname = modname + + if real_modname in self.modules: + return self.modules[real_modname] + try: + module = importlib.import_module(f'mesonbuild.modules.{real_modname}') + except ImportError: + if required: + raise InvalidArguments(f'Module "{modname}" does not exist') + ext_module = NotFoundExtensionModule(real_modname) + else: + ext_module = module.initialize(self) + assert isinstance(ext_module, (ExtensionModule, NewExtensionModule)) + self.build.modules.append(real_modname) + if ext_module.INFO.added: + FeatureNew.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.added, self.subproject, location=node) + if ext_module.INFO.deprecated: + FeatureDeprecated.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.deprecated, self.subproject, location=node) + if expect_unstable and not ext_module.INFO.unstable and ext_module.INFO.stabilized is None: + raise InvalidArguments(f'Module {ext_module.INFO.name} has never been unstable, remove "unstable-" prefix.') + if ext_module.INFO.stabilized is not None: + if expect_unstable: + FeatureDeprecated.single_use( + f'module {ext_module.INFO.name} has been stabilized', + ext_module.INFO.stabilized, self.subproject, + 'drop "unstable-" prefix from the module name', + location=node) + else: + FeatureNew.single_use( + f'module {ext_module.INFO.name} as stable module', + ext_module.INFO.stabilized, self.subproject, + f'Consider either adding "unstable-" to the module name, or updating the meson required version to ">= {ext_module.INFO.stabilized}"', + location=node) + elif ext_module.INFO.unstable: + if not expect_unstable: + if required: + raise InvalidArguments(f'Module "{ext_module.INFO.name}" has not been stabilized, and must be imported as unstable-{ext_module.INFO.name}') + ext_module = NotFoundExtensionModule(real_modname) + else: + mlog.warning(f'Module {ext_module.INFO.name} has no backwards or forwards compatibility and might not exist in future releases.', location=node, fatal=False) + + self.modules[real_modname] = ext_module + return ext_module + + @typed_pos_args('files', varargs=str) + @noKwargs + def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[mesonlib.File]: + return self.source_strings_to_files(args[0]) + + @noPosargs + @typed_kwargs( + 'declare_dependency', + KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]), + INCLUDE_DIRECTORIES.evolve(name='d_import_dirs', since='0.62.0'), + D_MODULE_VERSIONS_KW.evolve(since='0.62.0'), + KwargInfo('link_args', ContainerTypeInfo(list, str), listify=True, default=[]), + DEPENDENCIES_KW, + INCLUDE_DIRECTORIES, + LINK_WITH_KW, + LINK_WHOLE_KW.evolve(since='0.46.0'), + SOURCES_KW, + KwargInfo('extra_files', ContainerTypeInfo(list, (mesonlib.File, str)), listify=True, default=[], since='1.2.0'), + VARIABLES_KW.evolve(since='0.54.0', since_values={list: '0.56.0'}), + KwargInfo('version', (str, NoneType)), + KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'), + ) + def func_declare_dependency(self, node, args, kwargs): + deps = kwargs['dependencies'] + incs = self.extract_incdirs(kwargs) + libs = kwargs['link_with'] + libs_whole = kwargs['link_whole'] + objects = kwargs['objects'] + sources = self.source_strings_to_files(kwargs['sources']) + extra_files = self.source_strings_to_files(kwargs['extra_files']) + compile_args = kwargs['compile_args'] + link_args = kwargs['link_args'] + variables = kwargs['variables'] + version = kwargs['version'] + if version is None: + version = self.project_version + d_module_versions = kwargs['d_module_versions'] + d_import_dirs = self.extract_incdirs(kwargs, 'd_import_dirs') + srcdir = Path(self.environment.source_dir) + # convert variables which refer to an -uninstalled.pc style datadir + for k, v in variables.items(): + try: + p = Path(v) + except ValueError: + continue + else: + if not self.is_subproject() and srcdir / self.subproject_dir in p.parents: + continue + if p.is_absolute() and p.is_dir() and srcdir / self.root_subdir in [p] + list(Path(os.path.abspath(p)).parents): + variables[k] = P_OBJ.DependencyVariableString(v) + for d in deps: + if not isinstance(d, dependencies.Dependency): + raise InterpreterException('Invalid dependency') + + dep = dependencies.InternalDependency(version, incs, compile_args, + link_args, libs, libs_whole, sources, extra_files, + deps, variables, d_module_versions, d_import_dirs, + objects) + return dep + + @typed_pos_args('assert', bool, optargs=[str]) + @noKwargs + def func_assert(self, node: mparser.FunctionNode, args: T.Tuple[bool, T.Optional[str]], + kwargs: 'TYPE_kwargs') -> None: + value, message = args + if message is None: + FeatureNew.single_use('assert function without message argument', '0.53.0', self.subproject, location=node) + + if not value: + if message is None: + from ..ast import AstPrinter + printer = AstPrinter() + node.args.arguments[0].accept(printer) + message = printer.result + raise InterpreterException('Assert failed: ' + message) + + def validate_arguments(self, args, argcount, arg_types): + if argcount is not None: + if argcount != len(args): + raise InvalidArguments(f'Expected {argcount} arguments, got {len(args)}.') + for actual, wanted in zip(args, arg_types): + if wanted is not None: + if not isinstance(actual, wanted): + raise InvalidArguments('Incorrect argument type.') + + # Executables aren't actually accepted, but we allow them here to allow for + # better error messages when overridden + @typed_pos_args( + 'run_command', + (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str), + varargs=(build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str)) + @typed_kwargs( + 'run_command', + KwargInfo('check', (bool, NoneType), since='0.47.0'), + KwargInfo('capture', bool, default=True, since='0.47.0'), + ENV_KW.evolve(since='0.50.0'), + ) + def func_run_command(self, node: mparser.BaseNode, + args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str], + T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]], + kwargs: 'kwtypes.RunCommand') -> RunProcess: + return self.run_command_impl(node, args, kwargs) + + def run_command_impl(self, + node: mparser.BaseNode, + args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str], + T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]], + kwargs: 'kwtypes.RunCommand', + in_builddir: bool = False) -> RunProcess: + cmd, cargs = args + capture = kwargs['capture'] + env = kwargs['env'] + srcdir = self.environment.get_source_dir() + builddir = self.environment.get_build_dir() + + check = kwargs['check'] + if check is None: + mlog.warning(implicit_check_false_warning, once=True) + check = False + + overridden_msg = ('Program {!r} was overridden with the compiled ' + 'executable {!r} and therefore cannot be used during ' + 'configuration') + expanded_args: T.List[str] = [] + if isinstance(cmd, build.Executable): + for name, exe in self.build.find_overrides.items(): + if cmd == exe: + progname = name + break + else: + raise InterpreterException(f'Program {cmd.description()!r} is a compiled executable and therefore cannot be used during configuration') + raise InterpreterException(overridden_msg.format(progname, cmd.description())) + if isinstance(cmd, ExternalProgram): + if not cmd.found(): + raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable') + elif isinstance(cmd, compilers.Compiler): + exelist = cmd.get_exelist() + cmd = exelist[0] + prog = ExternalProgram(cmd, silent=True) + if not prog.found(): + raise InterpreterException(f'Program {cmd!r} not found or not executable') + cmd = prog + expanded_args = exelist[1:] + else: + if isinstance(cmd, mesonlib.File): + cmd = cmd.absolute_path(srcdir, builddir) + # Prefer scripts in the current source directory + search_dir = os.path.join(srcdir, self.subdir) + prog = ExternalProgram(cmd, silent=True, search_dir=search_dir) + if not prog.found(): + raise InterpreterException(f'Program or command {cmd!r} not found or not executable') + cmd = prog + for a in cargs: + if isinstance(a, str): + expanded_args.append(a) + elif isinstance(a, mesonlib.File): + expanded_args.append(a.absolute_path(srcdir, builddir)) + elif isinstance(a, ExternalProgram): + expanded_args.append(a.get_path()) + elif isinstance(a, compilers.Compiler): + FeatureNew.single_use('Compiler object as a variadic argument to `run_command`', '0.61.0', self.subproject, location=node) + prog = ExternalProgram(a.exelist[0], silent=True) + if not prog.found(): + raise InterpreterException(f'Program {cmd!r} not found or not executable') + expanded_args.append(prog.get_path()) + else: + raise InterpreterException(overridden_msg.format(a.name, cmd.description())) + + # If any file that was used as an argument to the command + # changes, we must re-run the configuration step. + self.add_build_def_file(cmd.get_path()) + for a in expanded_args: + if not os.path.isabs(a): + a = os.path.join(builddir if in_builddir else srcdir, self.subdir, a) + self.add_build_def_file(a) + + return RunProcess(cmd, expanded_args, env, srcdir, builddir, self.subdir, + self.environment.get_build_command() + ['introspect'], + in_builddir=in_builddir, check=check, capture=capture) + + def func_gettext(self, nodes, args, kwargs): + raise InterpreterException('Gettext() function has been moved to module i18n. Import it and use i18n.gettext() instead') + + def func_option(self, nodes, args, kwargs): + raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.') + + @typed_pos_args('subproject', str) + @typed_kwargs( + 'subproject', + REQUIRED_KW, + DEFAULT_OPTIONS.evolve(since='0.38.0'), + KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs: kwtypes.Subproject) -> SubprojectHolder: + kw: kwtypes.DoSubproject = { + 'required': kwargs['required'], + 'default_options': kwargs['default_options'], + 'version': kwargs['version'], + 'options': None, + 'cmake_options': [], + } + return self.do_subproject(args[0], 'meson', kw) + + def disabled_subproject(self, subp_name: str, disabled_feature: T.Optional[str] = None, + exception: T.Optional[Exception] = None) -> SubprojectHolder: + sub = SubprojectHolder(NullSubprojectInterpreter(), os.path.join(self.subproject_dir, subp_name), + disabled_feature=disabled_feature, exception=exception) + self.subprojects[subp_name] = sub + return sub + + def do_subproject(self, subp_name: str, method: Literal['meson', 'cmake'], kwargs: kwtypes.DoSubproject) -> SubprojectHolder: + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) + if disabled: + mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled') + return self.disabled_subproject(subp_name, disabled_feature=feature) + + default_options = {k.evolve(subproject=subp_name): v for k, v in kwargs['default_options'].items()} + + if subp_name == '': + raise InterpreterException('Subproject name must not be empty.') + if subp_name[0] == '.': + raise InterpreterException('Subproject name must not start with a period.') + if '..' in subp_name: + raise InterpreterException('Subproject name must not contain a ".." path segment.') + if os.path.isabs(subp_name): + raise InterpreterException('Subproject name must not be an absolute path.') + if has_path_sep(subp_name): + mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.', + location=self.current_node) + if subp_name in self.subproject_stack: + fullstack = self.subproject_stack + [subp_name] + incpath = ' => '.join(fullstack) + raise InvalidCode(f'Recursive include of subprojects: {incpath}.') + if subp_name in self.subprojects: + subproject = self.subprojects[subp_name] + if required and not subproject.found(): + raise InterpreterException(f'Subproject "{subproject.subdir}" required but not found.') + if kwargs['version']: + pv = self.build.subprojects[subp_name] + wanted = kwargs['version'] + if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]: + raise InterpreterException(f'Subproject {subp_name} version is {pv} but {wanted} required.') + return subproject + + r = self.environment.wrap_resolver + try: + subdir = r.resolve(subp_name, method) + except wrap.WrapException as e: + if not required: + mlog.log(e) + mlog.log('Subproject ', mlog.bold(subp_name), 'is buildable:', mlog.red('NO'), '(disabling)') + return self.disabled_subproject(subp_name, exception=e) + raise e + + subdir_abs = os.path.join(self.environment.get_source_dir(), subdir) + os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) + self.global_args_frozen = True + + stack = ':'.join(self.subproject_stack + [subp_name]) + m = ['\nExecuting subproject', mlog.bold(stack)] + if method != 'meson': + m += ['method', mlog.bold(method)] + mlog.log(*m, '\n', nested=False) + + try: + if method == 'meson': + return self._do_subproject_meson(subp_name, subdir, default_options, kwargs) + elif method == 'cmake': + return self._do_subproject_cmake(subp_name, subdir, subdir_abs, default_options, kwargs) + else: + raise mesonlib.MesonBugException(f'The method {method} is invalid for the subproject {subp_name}') + # Invalid code is always an error + except InvalidCode: + raise + except Exception as e: + if not required: + with mlog.nested(subp_name): + # Suppress the 'ERROR:' prefix because this exception is not + # fatal and VS CI treat any logs with "ERROR:" as fatal. + mlog.exception(e, prefix=mlog.yellow('Exception:')) + mlog.log('\nSubproject', mlog.bold(subdir), 'is buildable:', mlog.red('NO'), '(disabling)') + return self.disabled_subproject(subp_name, exception=e) + raise e + + def _do_subproject_meson(self, subp_name: str, subdir: str, + default_options: T.Dict[OptionKey, str], + kwargs: kwtypes.DoSubproject, + ast: T.Optional[mparser.CodeBlockNode] = None, + build_def_files: T.Optional[T.List[str]] = None, + is_translated: bool = False, + relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None) -> SubprojectHolder: + with mlog.nested(subp_name): + new_build = self.build.copy() + subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir, + default_options, ast=ast, is_translated=is_translated, + relaxations=relaxations, + user_defined_options=self.user_defined_options) + # Those lists are shared by all interpreters. That means that + # even if the subproject fails, any modification that the subproject + # made to those lists will affect the parent project. + subi.subprojects = self.subprojects + subi.modules = self.modules + subi.holder_map = self.holder_map + subi.bound_holder_map = self.bound_holder_map + subi.summary = self.summary + + subi.subproject_stack = self.subproject_stack + [subp_name] + current_active = self.active_projectname + with mlog.nested_warnings(): + subi.run() + subi_warnings = mlog.get_warning_count() + mlog.log('Subproject', mlog.bold(subp_name), 'finished.') + + mlog.log() + + if kwargs['version']: + pv = subi.project_version + wanted = kwargs['version'] + if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]: + raise InterpreterException(f'Subproject {subp_name} version is {pv} but {wanted} required.') + self.active_projectname = current_active + self.subprojects.update(subi.subprojects) + self.subprojects[subp_name] = SubprojectHolder(subi, subdir, warnings=subi_warnings, + callstack=self.subproject_stack) + # Duplicates are possible when subproject uses files from project root + if build_def_files: + self.build_def_files.update(build_def_files) + # We always need the subi.build_def_files, to propagate sub-sub-projects + self.build_def_files.update(subi.build_def_files) + self.build.merge(subi.build) + self.build.subprojects[subp_name] = subi.project_version + return self.subprojects[subp_name] + + def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, + default_options: T.Dict[OptionKey, str], + kwargs: kwtypes.DoSubproject) -> SubprojectHolder: + from ..cmake import CMakeInterpreter + with mlog.nested(subp_name): + new_build = self.build.copy() + prefix = self.coredata.options[OptionKey('prefix')].value + + from ..modules.cmake import CMakeSubprojectOptions + options = kwargs['options'] or CMakeSubprojectOptions() + cmake_options = kwargs['cmake_options'] + options.cmake_options + cm_int = CMakeInterpreter(new_build, Path(subdir), Path(subdir_abs), Path(prefix), new_build.environment, self.backend) + cm_int.initialise(cmake_options) + cm_int.analyse() + + # Generate a meson ast and execute it with the normal do_subproject_meson + ast = cm_int.pretend_to_be_meson(options.target_options) + + mlog.log() + with mlog.nested('cmake-ast'): + mlog.log('Processing generated meson AST') + + # Debug print the generated meson file + from ..ast import AstIndentationGenerator, AstPrinter + printer = AstPrinter(update_ast_line_nos=True) + ast.accept(AstIndentationGenerator()) + ast.accept(printer) + printer.post_process() + meson_filename = os.path.join(self.build.environment.get_build_dir(), subdir, 'meson.build') + with open(meson_filename, "w", encoding='utf-8') as f: + f.write(printer.result) + + mlog.log('Build file:', meson_filename) + mlog.cmd_ci_include(meson_filename) + mlog.log() + + result = self._do_subproject_meson( + subp_name, subdir, default_options, + kwargs, ast, + [str(f) for f in cm_int.bs_files], + is_translated=True, + relaxations={ + InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES, + } + ) + result.cm_interpreter = cm_int + + mlog.log() + return result + + def get_option_internal(self, optname: str) -> coredata.UserOption: + key = OptionKey.from_string(optname).evolve(subproject=self.subproject) + + if not key.is_project(): + for opts in [self.coredata.options, compilers.base_options]: + v = opts.get(key) + if v is None or v.yielding: + v = opts.get(key.as_root()) + if v is not None: + assert isinstance(v, coredata.UserOption), 'for mypy' + return v + + try: + opt = self.coredata.options[key] + if opt.yielding and key.subproject and key.as_root() in self.coredata.options: + popt = self.coredata.options[key.as_root()] + if type(opt) is type(popt): + opt = popt + else: + # Get class name, then option type as a string + opt_type = opt.__class__.__name__[4:][:-6].lower() + popt_type = popt.__class__.__name__[4:][:-6].lower() + # This is not a hard error to avoid dependency hell, the workaround + # when this happens is to simply set the subproject's option directly. + mlog.warning('Option {0!r} of type {1!r} in subproject {2!r} cannot yield ' + 'to parent option of type {3!r}, ignoring parent value. ' + 'Use -D{2}:{0}=value to set the value for this option manually' + '.'.format(optname, opt_type, self.subproject, popt_type), + location=self.current_node) + return opt + except KeyError: + pass + + raise InterpreterException(f'Tried to access unknown option {optname!r}.') + + @typed_pos_args('get_option', str) + @noKwargs + def func_get_option(self, nodes: mparser.BaseNode, args: T.Tuple[str], + kwargs: 'TYPE_kwargs') -> T.Union[coredata.UserOption, 'TYPE_var']: + optname = args[0] + if ':' in optname: + raise InterpreterException('Having a colon in option name is forbidden, ' + 'projects are not allowed to directly access ' + 'options of other subprojects.') + + if optname_regex.search(optname.split('.', maxsplit=1)[-1]) is not None: + raise InterpreterException(f'Invalid option name {optname!r}') + + opt = self.get_option_internal(optname) + if isinstance(opt, coredata.UserFeatureOption): + opt.name = optname + return opt + elif isinstance(opt, coredata.UserOption): + if isinstance(opt.value, str): + return P_OBJ.OptionString(opt.value, f'{{{optname}}}') + return opt.value + return opt + + @typed_pos_args('configuration_data', optargs=[dict]) + @noKwargs + def func_configuration_data(self, node: mparser.BaseNode, args: T.Tuple[T.Optional[T.Dict[str, T.Any]]], + kwargs: 'TYPE_kwargs') -> build.ConfigurationData: + initial_values = args[0] + if initial_values is not None: + FeatureNew.single_use('configuration_data dictionary', '0.49.0', self.subproject, location=node) + for k, v in initial_values.items(): + if not isinstance(v, (str, int, bool)): + raise InvalidArguments( + f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"') + return build.ConfigurationData(initial_values) + + def set_backend(self) -> None: + # The backend is already set when parsing subprojects + if self.backend is not None: + return + from ..backend import backends + + if OptionKey('genvslite') in self.user_defined_options.cmd_line_options.keys(): + # Use of the '--genvslite vsxxxx' option ultimately overrides any '--backend xxx' + # option the user may specify. + backend_name = self.coredata.get_option(OptionKey('genvslite')) + self.backend = backends.get_genvslite_backend(backend_name, self.build, self) + else: + backend_name = self.coredata.get_option(OptionKey('backend')) + self.backend = backends.get_backend_from_name(backend_name, self.build, self) + + if self.backend is None: + raise InterpreterException(f'Unknown backend "{backend_name}".') + if backend_name != self.backend.name: + if self.backend.name.startswith('vs'): + mlog.log('Auto detected Visual Studio backend:', mlog.bold(self.backend.name)) + if not self.environment.first_invocation: + raise MesonBugException(f'Backend changed from {backend_name} to {self.backend.name}') + self.coredata.set_option(OptionKey('backend'), self.backend.name, first_invocation=True) + + # Only init backend options on first invocation otherwise it would + # override values previously set from command line. + if self.environment.first_invocation: + self.coredata.init_backend_options(backend_name) + + options = {k: v for k, v in self.environment.options.items() if k.is_backend()} + self.coredata.set_options(options) + + @typed_pos_args('project', str, varargs=str) + @typed_kwargs( + 'project', + DEFAULT_OPTIONS, + KwargInfo('meson_version', (str, NoneType)), + KwargInfo( + 'version', + (str, mesonlib.File, NoneType, list), + default='undefined', + validator=_project_version_validator, + convertor=lambda x: x[0] if isinstance(x, list) else x, + ), + KwargInfo('license', (ContainerTypeInfo(list, str), NoneType), default=None, listify=True), + KwargInfo('license_files', ContainerTypeInfo(list, str), default=[], listify=True, since='1.1.0'), + KwargInfo('subproject_dir', str, default='subprojects'), + ) + def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str]], kwargs: 'kwtypes.Project') -> None: + proj_name, proj_langs = args + if ':' in proj_name: + raise InvalidArguments(f"Project name {proj_name!r} must not contain ':'") + + # This needs to be evaluated as early as possible, as meson uses this + # for things like deprecation testing. + if kwargs['meson_version']: + self.handle_meson_version(kwargs['meson_version'], node) + + # Load "meson.options" before "meson_options.txt", and produce a warning if + # it is being used with an old version. I have added check that if both + # exist the warning isn't raised + option_file = os.path.join(self.source_root, self.subdir, 'meson.options') + old_option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') + + if os.path.exists(option_file): + if os.path.exists(old_option_file): + if os.path.samefile(option_file, old_option_file): + mlog.debug("Not warning about meson.options with version minimum < 1.1 because meson_options.txt also exists") + else: + raise MesonException("meson.options and meson_options.txt both exist, but are not the same file.") + else: + FeatureNew.single_use('meson.options file', '1.1', self.subproject, 'Use meson_options.txt instead') + else: + option_file = old_option_file + if os.path.exists(option_file): + oi = optinterpreter.OptionInterpreter(self.subproject) + oi.process(option_file) + self.coredata.update_project_options(oi.options) + self.add_build_def_file(option_file) + + if self.subproject: + self.project_default_options = {k.evolve(subproject=self.subproject): v + for k, v in kwargs['default_options'].items()} + else: + self.project_default_options = kwargs['default_options'] + + # Do not set default_options on reconfigure otherwise it would override + # values previously set from command line. That means that changing + # default_options in a project will trigger a reconfigure but won't + # have any effect. + # + # If this is the first invocation we always need to initialize + # builtins, if this is a subproject that is new in a re-invocation we + # need to initialize builtins for that + if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.coredata.initialized_subprojects): + default_options = self.project_default_options.copy() + default_options.update(self.default_project_options) + self.coredata.init_builtins(self.subproject) + self.coredata.initialized_subprojects.add(self.subproject) + else: + default_options = {} + self.coredata.set_default_options(default_options, self.subproject, self.environment) + + if not self.is_subproject(): + self.build.project_name = proj_name + self.active_projectname = proj_name + + version = kwargs['version'] + if isinstance(version, mesonlib.File): + FeatureNew.single_use('version from file', '0.57.0', self.subproject, location=node) + self.add_build_def_file(version) + ifname = version.absolute_path(self.environment.source_dir, + self.environment.build_dir) + try: + ver_data = Path(ifname).read_text(encoding='utf-8').split('\n') + except FileNotFoundError: + raise InterpreterException('Version file not found.') + if len(ver_data) == 2 and ver_data[1] == '': + ver_data = ver_data[0:1] + if len(ver_data) != 1: + raise InterpreterException('Version file must contain exactly one line of text.') + self.project_version = ver_data[0] + else: + self.project_version = version + + if self.build.project_version is None: + self.build.project_version = self.project_version + + if kwargs['license'] is None: + proj_license = ['unknown'] + if kwargs['license_files']: + raise InvalidArguments('Project `license` name must be specified when `license_files` is set') + else: + proj_license = kwargs['license'] + proj_license_files = [] + for i in self.source_strings_to_files(kwargs['license_files']): + ifname = i.absolute_path(self.environment.source_dir, + self.environment.build_dir) + proj_license_files.append((ifname, i)) + self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license, + proj_license_files, self.subproject) + if self.subproject in self.build.projects: + raise InvalidCode('Second call to project().') + + # spdirname is the subproject_dir for this project, relative to self.subdir. + # self.subproject_dir is the subproject_dir for the main project, relative to top source dir. + spdirname = kwargs['subproject_dir'] + if not isinstance(spdirname, str): + raise InterpreterException('Subproject_dir must be a string') + if os.path.isabs(spdirname): + raise InterpreterException('Subproject_dir must not be an absolute path.') + if spdirname.startswith('.'): + raise InterpreterException('Subproject_dir must not begin with a period.') + if '..' in spdirname: + raise InterpreterException('Subproject_dir must not contain a ".." segment.') + if not self.is_subproject(): + self.subproject_dir = spdirname + self.build.subproject_dir = self.subproject_dir + + # Load wrap files from this (sub)project. + wrap_mode = self.coredata.get_option(OptionKey('wrap_mode')) + if not self.is_subproject() or wrap_mode != WrapMode.nopromote: + subdir = os.path.join(self.subdir, spdirname) + r = wrap.Resolver(self.environment.get_source_dir(), subdir, self.subproject, wrap_mode) + if self.is_subproject(): + self.environment.wrap_resolver.merge_wraps(r) + else: + self.environment.wrap_resolver = r + + self.build.projects[self.subproject] = proj_name + mlog.log('Project name:', mlog.bold(proj_name)) + mlog.log('Project version:', mlog.bold(self.project_version)) + + if not self.is_subproject(): + # We have to activate VS before adding languages and before calling + # self.set_backend() otherwise it wouldn't be able to detect which + # vs backend version we need. But after setting default_options in case + # the project sets vs backend by default. + backend = self.coredata.get_option(OptionKey('backend')) + vsenv = self.coredata.get_option(OptionKey('vsenv')) + force_vsenv = vsenv or backend.startswith('vs') + mesonlib.setup_vsenv(force_vsenv) + + self.add_languages(proj_langs, True, MachineChoice.HOST) + self.add_languages(proj_langs, False, MachineChoice.BUILD) + + self.set_backend() + if not self.is_subproject(): + self.check_stdlibs() + + @typed_kwargs('add_languages', KwargInfo('native', (bool, NoneType), since='0.54.0'), REQUIRED_KW) + @typed_pos_args('add_languages', varargs=str) + def func_add_languages(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddLanguages') -> bool: + langs = args[0] + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) + native = kwargs['native'] + + if disabled: + for lang in sorted(langs, key=compilers.sort_clink): + mlog.log('Compiler for language', mlog.bold(lang), 'skipped: feature', mlog.bold(feature), 'disabled') + return False + if native is not None: + return self.add_languages(langs, required, self.machine_from_native_kwarg(kwargs)) + else: + # absent 'native' means 'both' for backwards compatibility + tv = FeatureNew.get_target_version(self.subproject) + if FeatureNew.check_version(tv, '0.54.0'): + mlog.warning('add_languages is missing native:, assuming languages are wanted for both host and build.', + location=node) + + success = self.add_languages(langs, False, MachineChoice.BUILD) + success &= self.add_languages(langs, required, MachineChoice.HOST) + return success + + @noArgsFlattening + @noKwargs + def func_message(self, node: mparser.BaseNode, args, kwargs): + if len(args) > 1: + FeatureNew.single_use('message with more than one argument', '0.54.0', self.subproject, location=node) + args_str = [stringifyUserArguments(i) for i in args] + self.message_impl(args_str) + + def message_impl(self, args): + mlog.log(mlog.bold('Message:'), *args) + + @noArgsFlattening + @FeatureNew('summary', '0.53.0') + @typed_pos_args('summary', (str, dict), optargs=[object]) + @typed_kwargs( + 'summary', + KwargInfo('section', str, default=''), + KwargInfo('bool_yn', bool, default=False), + KwargInfo('list_sep', (str, NoneType), since='0.54.0') + ) + def func_summary(self, node: mparser.BaseNode, args: T.Tuple[T.Union[str, T.Dict[str, T.Any]], T.Optional[T.Any]], + kwargs: 'kwtypes.Summary') -> None: + if args[1] is None: + if not isinstance(args[0], dict): + raise InterpreterException('Summary first argument must be dictionary.') + values = args[0] + else: + if not isinstance(args[0], str): + raise InterpreterException('Summary first argument must be string.') + values = {args[0]: args[1]} + self.summary_impl(kwargs['section'], values, kwargs) + + def summary_impl(self, section: str, values, kwargs: 'kwtypes.Summary') -> None: + if self.subproject not in self.summary: + self.summary[self.subproject] = Summary(self.active_projectname, self.project_version) + self.summary[self.subproject].add_section( + section, values, kwargs['bool_yn'], kwargs['list_sep'], self.subproject) + + def _print_summary(self) -> None: + # Add automatic 'Subprojects' section in main project. + all_subprojects = collections.OrderedDict() + for name, subp in sorted(self.subprojects.items()): + value = [subp.found()] + if subp.disabled_feature: + value += [f'Feature {subp.disabled_feature!r} disabled'] + elif subp.exception: + value += [str(subp.exception)] + elif subp.warnings > 0: + value += [f'{subp.warnings} warnings'] + if subp.callstack: + stack = ' => '.join(subp.callstack) + value += [f'(from {stack})'] + all_subprojects[name] = value + if all_subprojects: + self.summary_impl('Subprojects', all_subprojects, + {'bool_yn': True, + 'list_sep': ' ', + }) + # Add automatic section with all user defined options + if self.user_defined_options: + values = collections.OrderedDict() + if self.user_defined_options.cross_file: + values['Cross files'] = self.user_defined_options.cross_file + if self.user_defined_options.native_file: + values['Native files'] = self.user_defined_options.native_file + sorted_options = sorted(self.user_defined_options.cmd_line_options.items()) + values.update({str(k): v for k, v in sorted_options}) + if values: + self.summary_impl('User defined options', values, {'bool_yn': False, 'list_sep': None}) + # Print all summaries, main project last. + mlog.log('') # newline + main_summary = self.summary.pop('', None) + for subp_name, summary in sorted(self.summary.items()): + if self.subprojects[subp_name].found(): + summary.dump() + if main_summary: + main_summary.dump() + + @noArgsFlattening + @FeatureNew('warning', '0.44.0') + @noKwargs + def func_warning(self, node, args, kwargs): + if len(args) > 1: + FeatureNew.single_use('warning with more than one argument', '0.54.0', self.subproject, location=node) + args_str = [stringifyUserArguments(i) for i in args] + mlog.warning(*args_str, location=node) + + @noArgsFlattening + @noKwargs + def func_error(self, node, args, kwargs): + if len(args) > 1: + FeatureNew.single_use('error with more than one argument', '0.58.0', self.subproject, location=node) + args_str = [stringifyUserArguments(i) for i in args] + raise InterpreterException('Problem encountered: ' + ' '.join(args_str)) + + @noArgsFlattening + @FeatureNew('debug', '0.63.0') + @noKwargs + def func_debug(self, node, args, kwargs): + args_str = [stringifyUserArguments(i) for i in args] + mlog.debug('Debug:', *args_str) + + @noKwargs + @noPosargs + def func_exception(self, node, args, kwargs): + raise RuntimeError('unit test traceback :)') + + @noKwargs + @typed_pos_args('expect_error', str) + def func_expect_error(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: TYPE_kwargs) -> ContextManagerObject: + class ExpectErrorObject(ContextManagerObject): + def __init__(self, msg: str, subproject: str) -> None: + super().__init__(subproject) + self.msg = msg + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_val is None: + raise InterpreterException('Expecting an error but code block succeeded') + if isinstance(exc_val, mesonlib.MesonException): + msg = str(exc_val) + if msg != self.msg: + raise InterpreterException(f'Expecting error {self.msg!r} but got {msg!r}') + return True + return ExpectErrorObject(args[0], self.subproject) + + def add_languages(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> bool: + success = self.add_languages_for(args, required, for_machine) + if not self.coredata.is_cross_build(): + self.coredata.copy_build_options_from_regular_ones() + self._redetect_machines() + return success + + def should_skip_sanity_check(self, for_machine: MachineChoice) -> bool: + should = self.environment.properties.host.get('skip_sanity_check', False) + if not isinstance(should, bool): + raise InterpreterException('Option skip_sanity_check must be a boolean.') + if for_machine != MachineChoice.HOST and not should: + return False + if not self.environment.is_cross_build() and not should: + return False + return should + + def add_languages_for(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> bool: + args = [a.lower() for a in args] + langs = set(self.compilers[for_machine].keys()) + langs.update(args) + # We'd really like to add cython's default language here, but it can't + # actually be done because the cython compiler hasn't been initialized, + # so we can't actually get the option yet. Because we can't know what + # compiler to add by default, and we don't want to add unnecessary + # compilers we don't add anything for cython here, and instead do it + # When the first cython target using a particular language is used. + if 'vala' in langs and 'c' not in langs: + FeatureNew.single_use('Adding Vala language without C', '0.59.0', self.subproject, location=self.current_node) + args.append('c') + if 'nasm' in langs: + FeatureNew.single_use('Adding NASM language', '0.64.0', self.subproject, location=self.current_node) + + success = True + for lang in sorted(args, key=compilers.sort_clink): + if lang in self.compilers[for_machine]: + continue + machine_name = for_machine.get_lower_case_name() + comp = self.coredata.compilers[for_machine].get(lang) + if not comp: + try: + skip_sanity_check = self.should_skip_sanity_check(for_machine) + if skip_sanity_check: + mlog.log('Cross compiler sanity tests disabled via the cross file.', once=True) + comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check) + if comp is None: + raise InvalidArguments(f'Tried to use unknown language "{lang}".') + except mesonlib.MesonException: + if not required: + mlog.log('Compiler for language', + mlog.bold(lang), 'for the', machine_name, + 'machine not found.') + success = False + continue + else: + raise + + # Add per-subproject compiler options. They inherit value from main project. + if self.subproject: + options = {} + for k in comp.get_options(): + v = copy.copy(self.coredata.options[k]) + k = k.evolve(subproject=self.subproject) + options[k] = v + self.coredata.add_compiler_options(options, lang, for_machine, self.environment) + + if for_machine == MachineChoice.HOST or self.environment.is_cross_build(): + logger_fun = mlog.log + else: + logger_fun = mlog.debug + logger_fun(comp.get_display_language(), 'compiler for the', machine_name, 'machine:', + mlog.bold(' '.join(comp.get_exelist())), comp.get_version_string()) + if comp.linker is not None: + logger_fun(comp.get_display_language(), 'linker for the', machine_name, 'machine:', + mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version) + self.build.ensure_static_linker(comp) + self.compilers[for_machine][lang] = comp + + return success + + def program_from_file_for(self, for_machine: MachineChoice, prognames: T.List[mesonlib.FileOrString] + ) -> T.Optional[ExternalProgram]: + for p in prognames: + if isinstance(p, mesonlib.File): + continue # Always points to a local (i.e. self generated) file. + if not isinstance(p, str): + raise InterpreterException('Executable name must be a string') + prog = ExternalProgram.from_bin_list(self.environment, for_machine, p) + # if the machine file specified something, it may be a regular + # not-found program but we still want to return that + if not isinstance(prog, NonExistingExternalProgram): + return prog + return None + + def program_from_system(self, args: T.List[mesonlib.FileOrString], search_dirs: T.List[str], + extra_info: T.List[mlog.TV_Loggable]) -> T.Optional[ExternalProgram]: + # Search for scripts relative to current subdir. + # Do not cache found programs because find_program('foobar') + # might give different results when run from different source dirs. + source_dir = os.path.join(self.environment.get_source_dir(), self.subdir) + for exename in args: + if isinstance(exename, mesonlib.File): + if exename.is_built: + search_dir = os.path.join(self.environment.get_build_dir(), + exename.subdir) + else: + search_dir = os.path.join(self.environment.get_source_dir(), + exename.subdir) + exename = exename.fname + extra_search_dirs = [] + elif isinstance(exename, str): + search_dir = source_dir + extra_search_dirs = search_dirs + else: + raise InvalidArguments(f'find_program only accepts strings and files, not {exename!r}') + extprog = ExternalProgram(exename, search_dir=search_dir, + extra_search_dirs=extra_search_dirs, + silent=True) + if extprog.found(): + extra_info.append(f"({' '.join(extprog.get_command())})") + return extprog + return None + + def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString], + extra_info: T.List['mlog.TV_Loggable'] + ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.Executable]]: + for name in command_names: + if not isinstance(name, str): + continue + if name in self.build.find_overrides: + exe = self.build.find_overrides[name] + extra_info.append(mlog.blue('(overridden)')) + return exe + return None + + def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString]) -> None: + for name in command_names: + if isinstance(name, str): + self.build.searched_programs.add(name) + + def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None: + if name in self.build.searched_programs: + raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.') + if name in self.build.find_overrides: + raise InterpreterException(f'Tried to override executable "{name}" which has already been overridden.') + self.build.find_overrides[name] = exe + + def notfound_program(self, args: T.List[mesonlib.FileOrString]) -> ExternalProgram: + return NonExistingExternalProgram(' '.join( + [a if isinstance(a, str) else a.absolute_path(self.environment.source_dir, self.environment.build_dir) + for a in args])) + + # TODO update modules to always pass `for_machine`. It is bad-form to assume + # the host machine. + def find_program_impl(self, args: T.List[mesonlib.FileOrString], + for_machine: MachineChoice = MachineChoice.HOST, + required: bool = True, silent: bool = True, + wanted: T.Union[str, T.List[str]] = '', + search_dirs: T.Optional[T.List[str]] = None, + version_func: T.Optional[T.Callable[[T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']], str]] = None + ) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']: + args = mesonlib.listify(args) + + extra_info: T.List[mlog.TV_Loggable] = [] + progobj = self.program_lookup(args, for_machine, required, search_dirs, extra_info) + if progobj is None: + progobj = self.notfound_program(args) + + if isinstance(progobj, ExternalProgram) and not progobj.found(): + if not silent: + mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO')) + if required: + m = 'Program {!r} not found or not executable' + raise InterpreterException(m.format(progobj.get_name())) + return progobj + + if wanted: + if version_func: + version = version_func(progobj) + elif isinstance(progobj, build.Executable): + if progobj.subproject: + interp = self.subprojects[progobj.subproject].held_object + else: + interp = self + assert isinstance(interp, Interpreter) + version = interp.project_version + else: + version = progobj.get_version(self) + is_found, not_found, _ = mesonlib.version_compare_many(version, wanted) + if not is_found: + mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.red('NO'), + 'found', mlog.normal_cyan(version), 'but need:', + mlog.bold(', '.join([f"'{e}'" for e in not_found])), *extra_info) + if required: + m = 'Invalid version of program, need {!r} {!r} found {!r}.' + raise InterpreterException(m.format(progobj.name, not_found, version)) + return self.notfound_program(args) + extra_info.insert(0, mlog.normal_cyan(version)) + + # Only store successful lookups + self.store_name_lookups(args) + if not silent: + mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.green('YES'), *extra_info) + if isinstance(progobj, build.Executable): + progobj.was_returned_by_find_program = True + return progobj + + def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice, + required: bool, search_dirs: T.List[str], extra_info: T.List[mlog.TV_Loggable] + ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: + progobj = self.program_from_overrides(args, extra_info) + if progobj: + return progobj + + if args[0] == 'meson': + # Override find_program('meson') to return what we were invoked with + return ExternalProgram('meson', self.environment.get_build_command(), silent=True) + + fallback = None + wrap_mode = self.coredata.get_option(OptionKey('wrap_mode')) + if wrap_mode != WrapMode.nofallback and self.environment.wrap_resolver: + fallback = self.environment.wrap_resolver.find_program_provider(args) + if fallback and wrap_mode == WrapMode.forcefallback: + return self.find_program_fallback(fallback, args, required, extra_info) + + progobj = self.program_from_file_for(for_machine, args) + if progobj is None: + progobj = self.program_from_system(args, search_dirs, extra_info) + if progobj is None and args[0].endswith('python3'): + prog = ExternalProgram('python3', mesonlib.python_command, silent=True) + progobj = prog if prog.found() else None + if progobj is None and fallback and required: + progobj = self.find_program_fallback(fallback, args, required, extra_info) + + return progobj + + def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString], + required: bool, extra_info: T.List[mlog.TV_Loggable] + ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: + mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', + mlog.bold(' '.join(args))) + sp_kwargs: kwtypes.DoSubproject = { + 'required': required, + 'default_options': {}, + 'version': [], + 'cmake_options': [], + 'options': None, + } + self.do_subproject(fallback, 'meson', sp_kwargs) + return self.program_from_overrides(args, extra_info) + + @typed_pos_args('find_program', varargs=(str, mesonlib.File), min_varargs=1) + @typed_kwargs( + 'find_program', + DISABLER_KW.evolve(since='0.49.0'), + NATIVE_KW, + REQUIRED_KW, + KwargInfo('dirs', ContainerTypeInfo(list, str), default=[], listify=True, since='0.53.0'), + KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True, since='0.52.0'), + ) + @disablerIfNotFound + def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonlib.FileOrString]], + kwargs: 'kwtypes.FindProgram', + ) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']: + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) + if disabled: + mlog.log('Program', mlog.bold(' '.join(args[0])), 'skipped: feature', mlog.bold(feature), 'disabled') + return self.notfound_program(args[0]) + + search_dirs = extract_search_dirs(kwargs) + return self.find_program_impl(args[0], kwargs['native'], required=required, + silent=False, wanted=kwargs['version'], + search_dirs=search_dirs) + + def func_find_library(self, node, args, kwargs): + raise InvalidCode('find_library() is removed, use meson.get_compiler(\'name\').find_library() instead.\n' + 'Look here for documentation: http://mesonbuild.com/Reference-manual.html#compiler-object\n' + 'Look here for example: http://mesonbuild.com/howtox.html#add-math-library-lm-portably\n' + ) + + # When adding kwargs, please check if they make sense in dependencies.get_dep_identifier() + @FeatureNewKwargs('dependency', '0.57.0', ['cmake_package_version']) + @FeatureNewKwargs('dependency', '0.56.0', ['allow_fallback']) + @FeatureNewKwargs('dependency', '0.54.0', ['components']) + @FeatureNewKwargs('dependency', '0.52.0', ['include_type']) + @FeatureNewKwargs('dependency', '0.50.0', ['not_found_message', 'cmake_module_path', 'cmake_args']) + @FeatureNewKwargs('dependency', '0.49.0', ['disabler']) + @FeatureNewKwargs('dependency', '0.40.0', ['method']) + @disablerIfNotFound + @permittedKwargs(permitted_dependency_kwargs) + @typed_pos_args('dependency', varargs=str, min_varargs=1) + @typed_kwargs('dependency', DEFAULT_OPTIONS.evolve(since='0.38.0'), allow_unknown=True) + def func_dependency(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs) -> Dependency: + # Replace '' by empty list of names + names = [n for n in args[0] if n] + if len(names) > 1: + FeatureNew('dependency with more than one name', '0.60.0').use(self.subproject) + allow_fallback = kwargs.get('allow_fallback') + if allow_fallback is not None and not isinstance(allow_fallback, bool): + raise InvalidArguments('"allow_fallback" argument must be boolean') + fallback = kwargs.get('fallback') + default_options = kwargs.get('default_options') + df = DependencyFallbacksHolder(self, names, allow_fallback, default_options) + df.set_fallback(fallback) + not_found_message = kwargs.get('not_found_message', '') + if not isinstance(not_found_message, str): + raise InvalidArguments('The not_found_message must be a string.') + try: + d = df.lookup(kwargs) + except Exception: + if not_found_message: + self.message_impl([not_found_message]) + raise + assert isinstance(d, Dependency) + if not d.found() and not_found_message: + self.message_impl([not_found_message]) + # Ensure the correct include type + if 'include_type' in kwargs: + wanted = kwargs['include_type'] + if not isinstance(wanted, str): + raise InvalidArguments('The `include_type` kwarg must be a string') + actual = d.get_include_type() + if wanted != actual: + mlog.debug(f'Current include type of {args[0]} is {actual}. Converting to requested {wanted}') + d = d.generate_system_dependency(wanted) + if d.feature_since is not None: + version, extra_msg = d.feature_since + FeatureNew.single_use(f'dep {d.name!r} custom lookup', version, self.subproject, extra_msg, node) + for f in d.featurechecks: + f.use(self.subproject, node) + return d + + @FeatureNew('disabler', '0.44.0') + @noKwargs + @noPosargs + def func_disabler(self, node, args, kwargs): + return Disabler() + + @FeatureNewKwargs('executable', '0.42.0', ['implib']) + @FeatureNewKwargs('executable', '0.56.0', ['win_subsystem']) + @FeatureDeprecatedKwargs('executable', '0.56.0', ['gui_app'], extra_message="Use 'win_subsystem' instead.") + @permittedKwargs(build.known_exe_kwargs) + @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('executable', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_executable(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.Executable: + return self.build_target(node, args, kwargs, build.Executable) + + @permittedKwargs(build.known_stlib_kwargs) + @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('static_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_static_lib(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.StaticLibrary: + return self.build_target(node, args, kwargs, build.StaticLibrary) + + @permittedKwargs(build.known_shlib_kwargs) + @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('shared_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_shared_lib(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.SharedLibrary: + holder = self.build_target(node, args, kwargs, build.SharedLibrary) + holder.shared_library_only = True + return holder + + @permittedKwargs(known_library_kwargs) + @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('both_libraries', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_both_lib(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.BothLibraries: + return self.build_both_libraries(node, args, kwargs) + + @FeatureNew('shared_module', '0.37.0') + @permittedKwargs(build.known_shmod_kwargs) + @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('shared_module', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_shared_module(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.SharedModule: + return self.build_target(node, args, kwargs, build.SharedModule) + + @permittedKwargs(known_library_kwargs) + @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_library(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> build.Executable: + return self.build_library(node, args, kwargs) + + @permittedKwargs(build.known_jar_kwargs) + @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('jar', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_jar(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], + kwargs) -> build.Jar: + return self.build_target(node, args, kwargs, build.Jar) + + @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) + @permittedKwargs(known_build_target_kwargs) + @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('build_target', OVERRIDE_OPTIONS_KW, allow_unknown=True) + def func_build_target(self, node: mparser.BaseNode, + args: T.Tuple[str, T.List[BuildTargetSource]], + kwargs) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, + build.SharedModule, build.BothLibraries, build.Jar]: + if 'target_type' not in kwargs: + raise InterpreterException('Missing target_type keyword argument') + target_type = kwargs.pop('target_type') + if target_type == 'executable': + return self.build_target(node, args, kwargs, build.Executable) + elif target_type == 'shared_library': + return self.build_target(node, args, kwargs, build.SharedLibrary) + elif target_type == 'shared_module': + FeatureNew.single_use( + 'build_target(target_type: \'shared_module\')', + '0.51.0', self.subproject, location=node) + return self.build_target(node, args, kwargs, build.SharedModule) + elif target_type == 'static_library': + return self.build_target(node, args, kwargs, build.StaticLibrary) + elif target_type == 'both_libraries': + return self.build_both_libraries(node, args, kwargs) + elif target_type == 'library': + return self.build_library(node, args, kwargs) + elif target_type == 'jar': + return self.build_target(node, args, kwargs, build.Jar) + else: + raise InterpreterException('Unknown target_type.') + + @noPosargs + @typed_kwargs( + 'vcs_tag', + CT_INPUT_KW.evolve(required=True), + MULTI_OUTPUT_KW, + # Cannot use the COMMAND_KW because command is allowed to be empty + KwargInfo( + 'command', + ContainerTypeInfo(list, (str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, ExternalProgram, mesonlib.File)), + listify=True, + default=[], + ), + KwargInfo('fallback', (str, NoneType)), + KwargInfo('replace_string', str, default='@VCS_TAG@'), + ) + def func_vcs_tag(self, node: mparser.BaseNode, args: T.List['TYPE_var'], kwargs: 'kwtypes.VcsTag') -> build.CustomTarget: + if kwargs['fallback'] is None: + FeatureNew.single_use('Optional fallback in vcs_tag', '0.41.0', self.subproject, location=node) + fallback = kwargs['fallback'] or self.project_version + replace_string = kwargs['replace_string'] + regex_selector = '(.*)' # default regex selector for custom command: use complete output + vcs_cmd = kwargs['command'] + source_dir = os.path.normpath(os.path.join(self.environment.get_source_dir(), self.subdir)) + if vcs_cmd: + if isinstance(vcs_cmd[0], (str, mesonlib.File)): + if isinstance(vcs_cmd[0], mesonlib.File): + FeatureNew.single_use('vcs_tag with file as the first argument', '0.62.0', self.subproject, location=node) + maincmd = self.find_program_impl(vcs_cmd[0], required=False) + if maincmd.found(): + vcs_cmd[0] = maincmd + else: + FeatureNew.single_use('vcs_tag with custom_tgt, external_program, or exe as the first argument', '0.63.0', self.subproject, location=node) + else: + vcs = mesonlib.detect_vcs(source_dir) + if vcs: + mlog.log('Found {} repository at {}'.format(vcs['name'], vcs['wc_dir'])) + vcs_cmd = vcs['get_rev'].split() + regex_selector = vcs['rev_regex'] + else: + vcs_cmd = [' '] # executing this cmd will fail in vcstagger.py and force to use the fallback string + # vcstagger.py parameters: infile, outfile, fallback, source_dir, replace_string, regex_selector, command... + + self._validate_custom_target_outputs(len(kwargs['input']) > 1, kwargs['output'], "vcs_tag") + + cmd = self.environment.get_build_command() + \ + ['--internal', + 'vcstagger', + '@INPUT0@', + '@OUTPUT0@', + fallback, + source_dir, + replace_string, + regex_selector] + vcs_cmd + + tg = build.CustomTarget( + kwargs['output'][0], + self.subdir, + self.subproject, + self.environment, + cmd, + self.source_strings_to_files(kwargs['input']), + kwargs['output'], + build_by_default=True, + build_always_stale=True, + ) + self.add_target(tg.name, tg) + return tg + + @FeatureNew('subdir_done', '0.46.0') + @noPosargs + @noKwargs + def func_subdir_done(self, node: mparser.BaseNode, args: TYPE_var, kwargs: TYPE_kwargs) -> T.NoReturn: + raise SubdirDoneRequest() + + @staticmethod + def _validate_custom_target_outputs(has_multi_in: bool, outputs: T.Iterable[str], name: str) -> None: + """Checks for additional invalid values in a custom_target output. + + This cannot be done with typed_kwargs because it requires the number of + inputs. + """ + for out in outputs: + if has_multi_in and ('@PLAINNAME@' in out or '@BASENAME@' in out): + raise InvalidArguments(f'{name}: output cannot contain "@PLAINNAME@" or "@BASENAME@" ' + 'when there is more than one input (we can\'t know which to use)') + + @typed_pos_args('custom_target', optargs=[str]) + @typed_kwargs( + 'custom_target', + COMMAND_KW, + CT_BUILD_ALWAYS, + CT_BUILD_ALWAYS_STALE, + CT_BUILD_BY_DEFAULT, + CT_INPUT_KW, + CT_INSTALL_DIR_KW, + CT_INSTALL_TAG_KW, + MULTI_OUTPUT_KW, + DEPENDS_KW, + DEPEND_FILES_KW, + DEPFILE_KW, + ENV_KW.evolve(since='0.57.0'), + INSTALL_KW, + INSTALL_MODE_KW.evolve(since='0.47.0'), + KwargInfo('feed', bool, default=False, since='0.59.0'), + KwargInfo('capture', bool, default=False), + KwargInfo('console', bool, default=False, since='0.48.0'), + ) + def func_custom_target(self, node: mparser.FunctionNode, args: T.Tuple[str], + kwargs: 'kwtypes.CustomTarget') -> build.CustomTarget: + if kwargs['depfile'] and ('@BASENAME@' in kwargs['depfile'] or '@PLAINNAME@' in kwargs['depfile']): + FeatureNew.single_use('substitutions in custom_target depfile', '0.47.0', self.subproject, location=node) + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) + + # Don't mutate the kwargs + + build_by_default = kwargs['build_by_default'] + build_always_stale = kwargs['build_always_stale'] + # Remap build_always to build_by_default and build_always_stale + if kwargs['build_always'] is not None and kwargs['build_always_stale'] is not None: + raise InterpreterException('CustomTarget: "build_always" and "build_always_stale" are mutually exclusive') + + if build_by_default is None and kwargs['install']: + build_by_default = True + + elif kwargs['build_always'] is not None: + if build_by_default is None: + build_by_default = kwargs['build_always'] + build_always_stale = kwargs['build_by_default'] + + # These are nullable so that we can know whether they're explicitly + # set or not. If they haven't been overwritten, set them to their true + # default + if build_by_default is None: + build_by_default = False + if build_always_stale is None: + build_always_stale = False + + name = args[0] + if name is None: + # name will default to first output, but we cannot do that yet because + # they could need substitutions (e.g. @BASENAME@) first. CustomTarget() + # will take care of setting a proper default but name must be an empty + # string in the meantime. + FeatureNew.single_use('custom_target() with no name argument', '0.60.0', self.subproject, location=node) + name = '' + inputs = self.source_strings_to_files(kwargs['input'], strict=False) + command = kwargs['command'] + if command and isinstance(command[0], str): + command[0] = self.find_program_impl([command[0]]) + + if len(inputs) > 1 and kwargs['feed']: + raise InvalidArguments('custom_target: "feed" keyword argument can only be used with a single input') + if len(kwargs['output']) > 1 and kwargs['capture']: + raise InvalidArguments('custom_target: "capture" keyword argument can only be used with a single output') + if kwargs['capture'] and kwargs['console']: + raise InvalidArguments('custom_target: "capture" and "console" keyword arguments are mutually exclusive') + for c in command: + if kwargs['capture'] and isinstance(c, str) and '@OUTPUT@' in c: + raise InvalidArguments('custom_target: "capture" keyword argument cannot be used with "@OUTPUT@"') + if kwargs['feed'] and isinstance(c, str) and '@INPUT@' in c: + raise InvalidArguments('custom_target: "feed" keyword argument cannot be used with "@INPUT@"') + if kwargs['install'] and not kwargs['install_dir']: + raise InvalidArguments('custom_target: "install_dir" keyword argument must be set when "install" is true.') + if len(kwargs['install_dir']) > 1: + FeatureNew.single_use('multiple install_dir for custom_target', '0.40.0', self.subproject, location=node) + if len(kwargs['install_tag']) not in {0, 1, len(kwargs['output'])}: + raise InvalidArguments('custom_target: install_tag argument must have 0 or 1 outputs, ' + 'or the same number of elements as the output keyword argument. ' + f'(there are {len(kwargs["install_tag"])} install_tags, ' + f'and {len(kwargs["output"])} outputs)') + + for t in kwargs['output']: + self.validate_forbidden_targets(t) + self._validate_custom_target_outputs(len(inputs) > 1, kwargs['output'], "custom_target") + + tg = build.CustomTarget( + name, + self.subdir, + self.subproject, + self.environment, + command, + inputs, + kwargs['output'], + build_always_stale=build_always_stale, + build_by_default=build_by_default, + capture=kwargs['capture'], + console=kwargs['console'], + depend_files=kwargs['depend_files'], + depfile=kwargs['depfile'], + extra_depends=kwargs['depends'], + env=kwargs['env'], + feed=kwargs['feed'], + install=kwargs['install'], + install_dir=kwargs['install_dir'], + install_mode=install_mode, + install_tag=kwargs['install_tag'], + backend=self.backend) + self.add_target(tg.name, tg) + return tg + + @typed_pos_args('run_target', str) + @typed_kwargs( + 'run_target', + COMMAND_KW, + DEPENDS_KW, + ENV_KW.evolve(since='0.57.0'), + ) + def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str], + kwargs: 'kwtypes.RunTarget') -> build.RunTarget: + all_args = kwargs['command'].copy() + + for i in listify(all_args): + if isinstance(i, ExternalProgram) and not i.found(): + raise InterpreterException(f'Tried to use non-existing executable {i.name!r}') + if isinstance(all_args[0], str): + all_args[0] = self.find_program_impl([all_args[0]]) + name = args[0] + tg = build.RunTarget(name, all_args, kwargs['depends'], self.subdir, self.subproject, self.environment, + kwargs['env']) + self.add_target(name, tg) + return tg + + @FeatureNew('alias_target', '0.52.0') + @typed_pos_args('alias_target', str, varargs=build.Target, min_varargs=1) + @noKwargs + def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[build.Target]], + kwargs: 'TYPE_kwargs') -> build.AliasTarget: + name, deps = args + tg = build.AliasTarget(name, deps, self.subdir, self.subproject, self.environment) + self.add_target(name, tg) + return tg + + @typed_pos_args('generator', (build.Executable, ExternalProgram)) + @typed_kwargs( + 'generator', + KwargInfo('arguments', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True), + KwargInfo('output', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True), + DEPFILE_KW, + DEPENDS_KW, + KwargInfo('capture', bool, default=False, since='0.43.0'), + ) + def func_generator(self, node: mparser.FunctionNode, + args: T.Tuple[T.Union[build.Executable, ExternalProgram]], + kwargs: 'kwtypes.FuncGenerator') -> build.Generator: + for rule in kwargs['output']: + if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule: + raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.') + if has_path_sep(rule): + raise InvalidArguments('"output" must not contain a directory separator.') + if len(kwargs['output']) > 1: + for o in kwargs['output']: + if '@OUTPUT@' in o: + raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.') + + gen = build.Generator(args[0], **kwargs) + self.generators.append(gen) + return gen + + @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File)) + @typed_kwargs('benchmark', *TEST_KWS) + def func_benchmark(self, node: mparser.BaseNode, + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + kwargs: 'kwtypes.FuncBenchmark') -> None: + self.add_test(node, args, kwargs, False) + + @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File)) + @typed_kwargs('test', *TEST_KWS, KwargInfo('is_parallel', bool, default=True)) + def func_test(self, node: mparser.BaseNode, + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + kwargs: 'kwtypes.FuncTest') -> None: + self.add_test(node, args, kwargs, True) + + def unpack_env_kwarg(self, kwargs: T.Union[build.EnvironmentVariables, T.Dict[str, 'TYPE_var'], T.List['TYPE_var'], str]) -> build.EnvironmentVariables: + envlist = kwargs.get('env') + if envlist is None: + return build.EnvironmentVariables() + msg = ENV_KW.validator(envlist) + if msg: + raise InvalidArguments(f'"env": {msg}') + return ENV_KW.convertor(envlist) + + def make_test(self, node: mparser.BaseNode, + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + kwargs: 'kwtypes.BaseTest') -> Test: + name = args[0] + if ':' in name: + mlog.deprecation(f'":" is not allowed in test name "{name}", it has been replaced with "_"', + location=node) + name = name.replace(':', '_') + exe = args[1] + if isinstance(exe, ExternalProgram): + if not exe.found(): + raise InvalidArguments('Tried to use not-found external program as test exe') + elif isinstance(exe, mesonlib.File): + exe = self.find_program_impl([exe]) + + env = self.unpack_env_kwarg(kwargs) + + if kwargs['timeout'] <= 0: + FeatureNew.single_use('test() timeout <= 0', '0.57.0', self.subproject, location=node) + + prj = self.subproject if self.is_subproject() else self.build.project_name + + suite: T.List[str] = [] + for s in kwargs['suite']: + if s: + s = ':' + s + suite.append(prj.replace(' ', '_').replace(':', '_') + s) + + return Test(name, + prj, + suite, + exe, + kwargs['depends'], + kwargs.get('is_parallel', False), + kwargs['args'], + env, + kwargs['should_fail'], + kwargs['timeout'], + kwargs['workdir'], + kwargs['protocol'], + kwargs['priority'], + kwargs['verbose']) + + def add_test(self, node: mparser.BaseNode, args: T.List, kwargs: T.Dict[str, T.Any], is_base_test: bool): + t = self.make_test(node, args, kwargs) + if is_base_test: + self.build.tests.append(t) + mlog.debug('Adding test', mlog.bold(t.name, True)) + else: + self.build.benchmarks.append(t) + mlog.debug('Adding benchmark', mlog.bold(t.name, True)) + + @typed_pos_args('install_headers', varargs=(str, mesonlib.File)) + @typed_kwargs( + 'install_headers', + PRESERVE_PATH_KW, + KwargInfo('subdir', (str, NoneType)), + INSTALL_MODE_KW.evolve(since='0.47.0'), + INSTALL_DIR_KW, + ) + def func_install_headers(self, node: mparser.BaseNode, + args: T.Tuple[T.List['mesonlib.FileOrString']], + kwargs: 'kwtypes.FuncInstallHeaders') -> build.Headers: + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) + source_files = self.source_strings_to_files(args[0]) + install_subdir = kwargs['subdir'] + if install_subdir is not None: + if kwargs['install_dir'] is not None: + raise InterpreterException('install_headers: cannot specify both "install_dir" and "subdir". Use only "install_dir".') + if os.path.isabs(install_subdir): + mlog.deprecation('Subdir keyword must not be an absolute path. This will be a hard error in the next release.') + else: + install_subdir = '' + + dirs = collections.defaultdict(list) + ret_headers = [] + if kwargs['preserve_path']: + for file in source_files: + dirname = os.path.dirname(file.fname) + dirs[dirname].append(file) + else: + dirs[''].extend(source_files) + + for childdir in dirs: + h = build.Headers(dirs[childdir], os.path.join(install_subdir, childdir), kwargs['install_dir'], + install_mode, self.subproject) + ret_headers.append(h) + self.build.headers.append(h) + + return ret_headers + + @typed_pos_args('install_man', varargs=(str, mesonlib.File)) + @typed_kwargs( + 'install_man', + KwargInfo('locale', (str, NoneType), since='0.58.0'), + INSTALL_MODE_KW.evolve(since='0.47.0'), + INSTALL_DIR_KW, + ) + def func_install_man(self, node: mparser.BaseNode, + args: T.Tuple[T.List['mesonlib.FileOrString']], + kwargs: 'kwtypes.FuncInstallMan') -> build.Man: + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) + # We just need to narrow this, because the input is limited to files and + # Strings as inputs, so only Files will be returned + sources = self.source_strings_to_files(args[0]) + for s in sources: + try: + num = int(s.rsplit('.', 1)[-1]) + except (IndexError, ValueError): + num = 0 + if not 1 <= num <= 9: + raise InvalidArguments('Man file must have a file extension of a number between 1 and 9') + + m = build.Man(sources, kwargs['install_dir'], install_mode, + self.subproject, kwargs['locale']) + self.build.man.append(m) + + return m + + @FeatureNew('install_emptydir', '0.60.0') + @typed_kwargs( + 'install_emptydir', + INSTALL_MODE_KW, + KwargInfo('install_tag', (str, NoneType), since='0.62.0') + ) + def func_install_emptydir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs) -> None: + d = build.EmptyDir(args[0], kwargs['install_mode'], self.subproject, kwargs['install_tag']) + self.build.emptydir.append(d) + + return d + + @FeatureNew('install_symlink', '0.61.0') + @typed_pos_args('symlink_name', str) + @typed_kwargs( + 'install_symlink', + KwargInfo('pointing_to', str, required=True), + KwargInfo('install_dir', str, required=True), + INSTALL_TAG_KW, + ) + def func_install_symlink(self, node: mparser.BaseNode, + args: T.Tuple[T.List[str]], + kwargs) -> build.SymlinkData: + name = args[0] # Validation while creating the SymlinkData object + target = kwargs['pointing_to'] + l = build.SymlinkData(target, name, kwargs['install_dir'], + self.subproject, kwargs['install_tag']) + self.build.symlinks.append(l) + return l + + @FeatureNew('structured_sources', '0.62.0') + @typed_pos_args('structured_sources', object, optargs=[dict]) + @noKwargs + @noArgsFlattening + def func_structured_sources( + self, node: mparser.BaseNode, + args: T.Tuple[object, T.Optional[T.Dict[str, object]]], + kwargs: 'TYPE_kwargs') -> build.StructuredSources: + valid_types = (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList) + sources: T.Dict[str, T.List[T.Union[mesonlib.File, 'build.GeneratedTypes']]] = collections.defaultdict(list) + + for arg in mesonlib.listify(args[0]): + if not isinstance(arg, valid_types): + raise InvalidArguments(f'structured_sources: type "{type(arg)}" is not valid') + if isinstance(arg, str): + arg = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, arg) + sources[''].append(arg) + if args[1]: + if '' in args[1]: + raise InvalidArguments('structured_sources: keys to dictionary argument may not be an empty string.') + for k, v in args[1].items(): + for arg in mesonlib.listify(v): + if not isinstance(arg, valid_types): + raise InvalidArguments(f'structured_sources: type "{type(arg)}" is not valid') + if isinstance(arg, str): + arg = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, arg) + sources[k].append(arg) + return build.StructuredSources(sources) + + @typed_pos_args('subdir', str) + @typed_kwargs( + 'subdir', + KwargInfo( + 'if_found', + ContainerTypeInfo(list, object), + validator=lambda a: 'Objects must have a found() method' if not all(hasattr(x, 'found') for x in a) else None, + since='0.44.0', + default=[], + listify=True, + ), + ) + def func_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtypes.Subdir') -> None: + mesonlib.check_direntry_issues(args) + if '..' in args[0]: + raise InvalidArguments('Subdir contains ..') + if self.subdir == '' and args[0] == self.subproject_dir: + raise InvalidArguments('Must not go into subprojects dir with subdir(), use subproject() instead.') + if self.subdir == '' and args[0].startswith('meson-'): + raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().') + if args[0] == '': + raise InvalidArguments("The argument given to subdir() is the empty string ''. This is prohibited.") + for i in kwargs['if_found']: + if not i.found(): + return + + prev_subdir = self.subdir + subdir = os.path.join(prev_subdir, args[0]) + if os.path.isabs(subdir): + raise InvalidArguments('Subdir argument must be a relative path.') + absdir = os.path.join(self.environment.get_source_dir(), subdir) + symlinkless_dir = os.path.realpath(absdir) + build_file = os.path.join(symlinkless_dir, 'meson.build') + if build_file in self.processed_buildfiles: + raise InvalidArguments(f'Tried to enter directory "{subdir}", which has already been visited.') + self.processed_buildfiles.add(build_file) + self.subdir = subdir + os.makedirs(os.path.join(self.environment.build_dir, subdir), exist_ok=True) + buildfilename = os.path.join(self.subdir, environment.build_filename) + self.build_def_files.add(buildfilename) + absname = os.path.join(self.environment.get_source_dir(), buildfilename) + if not os.path.isfile(absname): + self.subdir = prev_subdir + raise InterpreterException(f"Nonexistent build file '{buildfilename!s}'") + with open(absname, encoding='utf-8') as f: + code = f.read() + assert isinstance(code, str) + try: + codeblock = mparser.Parser(code, absname).parse() + except mesonlib.MesonException as me: + me.file = absname + raise me + try: + self.evaluate_codeblock(codeblock) + except SubdirDoneRequest: + pass + self.subdir = prev_subdir + + def _get_kwarg_install_mode(self, kwargs: T.Dict[str, T.Any]) -> T.Optional[FileMode]: + if kwargs.get('install_mode', None) is None: + return None + if isinstance(kwargs['install_mode'], FileMode): + return kwargs['install_mode'] + install_mode: T.List[str] = [] + mode = mesonlib.typeslistify(kwargs.get('install_mode', []), (str, int)) + for m in mode: + # We skip any arguments that are set to `false` + if m is False: + m = None + install_mode.append(m) + if len(install_mode) > 3: + raise InvalidArguments('Keyword argument install_mode takes at ' + 'most 3 arguments.') + if len(install_mode) > 0 and install_mode[0] is not None and \ + not isinstance(install_mode[0], str): + raise InvalidArguments('Keyword argument install_mode requires the ' + 'permissions arg to be a string or false') + return FileMode(*install_mode) + + # This is either ignored on basically any OS nowadays, or silently gets + # ignored (Solaris) or triggers an "illegal operation" error (FreeBSD). + # It was likely added "because it exists", but should never be used. In + # theory it is useful for directories, but we never apply modes to + # directories other than in install_emptydir. + def _warn_kwarg_install_mode_sticky(self, mode: FileMode) -> None: + if mode.perms > 0 and mode.perms & stat.S_ISVTX: + mlog.deprecation('install_mode with the sticky bit on a file does not do anything and will ' + 'be ignored since Meson 0.64.0', location=self.current_node) + perms = stat.filemode(mode.perms - stat.S_ISVTX)[1:] + return FileMode(perms, mode.owner, mode.group) + else: + return mode + + @typed_pos_args('install_data', varargs=(str, mesonlib.File)) + @typed_kwargs( + 'install_data', + KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File)), listify=True, default=[]), + KwargInfo('rename', ContainerTypeInfo(list, str), default=[], listify=True, since='0.46.0'), + INSTALL_MODE_KW.evolve(since='0.38.0'), + INSTALL_TAG_KW.evolve(since='0.60.0'), + INSTALL_DIR_KW, + PRESERVE_PATH_KW.evolve(since='0.64.0'), + ) + def func_install_data(self, node: mparser.BaseNode, + args: T.Tuple[T.List['mesonlib.FileOrString']], + kwargs: 'kwtypes.FuncInstallData') -> build.Data: + sources = self.source_strings_to_files(args[0] + kwargs['sources']) + rename = kwargs['rename'] or None + if rename: + if len(rename) != len(sources): + raise InvalidArguments( + '"rename" and "sources" argument lists must be the same length if "rename" is given. ' + f'Rename has {len(rename)} elements and sources has {len(sources)}.') + + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) + return self.install_data_impl(sources, kwargs['install_dir'], install_mode, + rename, kwargs['install_tag'], + preserve_path=kwargs['preserve_path']) + + def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: T.Optional[str], + install_mode: FileMode, rename: T.Optional[str], + tag: T.Optional[str], + install_dir_name: T.Optional[str] = None, + install_data_type: T.Optional[str] = None, + preserve_path: bool = False) -> build.Data: + + """Just the implementation with no validation.""" + idir = install_dir or '' + idir_name = install_dir_name or idir or '{datadir}' + if isinstance(idir_name, P_OBJ.OptionString): + idir_name = idir_name.optname + dirs = collections.defaultdict(list) + ret_data = [] + if preserve_path: + for file in sources: + dirname = os.path.dirname(file.fname) + dirs[dirname].append(file) + else: + dirs[''].extend(sources) + + for childdir, files in dirs.items(): + d = build.Data(files, os.path.join(idir, childdir), os.path.join(idir_name, childdir), + install_mode, self.subproject, rename, tag, install_data_type) + ret_data.append(d) + + self.build.data.extend(ret_data) + return ret_data + + @typed_pos_args('install_subdir', str) + @typed_kwargs( + 'install_subdir', + KwargInfo('install_dir', str, required=True), + KwargInfo('strip_directory', bool, default=False), + KwargInfo('exclude_files', ContainerTypeInfo(list, str), + default=[], listify=True, since='0.42.0', + validator=lambda x: 'cannot be absolute' if any(os.path.isabs(d) for d in x) else None), + KwargInfo('exclude_directories', ContainerTypeInfo(list, str), + default=[], listify=True, since='0.42.0', + validator=lambda x: 'cannot be absolute' if any(os.path.isabs(d) for d in x) else None), + INSTALL_MODE_KW.evolve(since='0.38.0'), + INSTALL_TAG_KW.evolve(since='0.60.0'), + ) + def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], + kwargs: 'kwtypes.FuncInstallSubdir') -> build.InstallDir: + exclude = (set(kwargs['exclude_files']), set(kwargs['exclude_directories'])) + + srcdir = os.path.join(self.environment.source_dir, self.subdir, args[0]) + if not os.path.isdir(srcdir) or not any(os.listdir(srcdir)): + FeatureNew.single_use('install_subdir with empty directory', '0.47.0', self.subproject, location=node) + FeatureDeprecated.single_use('install_subdir with empty directory', '0.60.0', self.subproject, + 'It worked by accident and is buggy. Use install_emptydir instead.', node) + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) + + idir_name = kwargs['install_dir'] + if isinstance(idir_name, P_OBJ.OptionString): + idir_name = idir_name.optname + + idir = build.InstallDir( + self.subdir, + args[0], + kwargs['install_dir'], + idir_name, + install_mode, + exclude, + kwargs['strip_directory'], + self.subproject, + install_tag=kwargs['install_tag']) + self.build.install_dirs.append(idir) + return idir + + @noPosargs + @typed_kwargs( + 'configure_file', + DEPFILE_KW.evolve(since='0.52.0'), + INSTALL_MODE_KW.evolve(since='0.47.0,'), + INSTALL_TAG_KW.evolve(since='0.60.0'), + KwargInfo('capture', bool, default=False, since='0.41.0'), + KwargInfo( + 'command', + (ContainerTypeInfo(list, (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str), allow_empty=False), NoneType), + listify=True, + ), + KwargInfo( + 'configuration', + (ContainerTypeInfo(dict, (str, int, bool)), build.ConfigurationData, NoneType), + ), + KwargInfo( + 'copy', bool, default=False, since='0.47.0', + deprecated='0.64.0', deprecated_message='Use fs.copyfile instead', + ), + KwargInfo('encoding', str, default='utf-8', since='0.47.0'), + KwargInfo('format', str, default='meson', since='0.46.0', + validator=in_set_validator({'meson', 'cmake', 'cmake@'})), + KwargInfo( + 'input', + ContainerTypeInfo(list, (mesonlib.File, str)), + listify=True, + default=[], + ), + # Cannot use shared implementation until None backwards compat is dropped + KwargInfo('install', (bool, NoneType), since='0.50.0'), + KwargInfo('install_dir', (str, bool), default='', + validator=lambda x: 'must be `false` if boolean' if x is True else None), + OUTPUT_KW, + KwargInfo('output_format', str, default='c', since='0.47.0', + validator=in_set_validator({'c', 'nasm'})), + ) + def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], + kwargs: kwtypes.ConfigureFile): + actions = sorted(x for x in ['configuration', 'command', 'copy'] + if kwargs[x] not in [None, False]) + num_actions = len(actions) + if num_actions == 0: + raise InterpreterException('Must specify an action with one of these ' + 'keyword arguments: \'configuration\', ' + '\'command\', or \'copy\'.') + elif num_actions == 2: + raise InterpreterException('Must not specify both {!r} and {!r} ' + 'keyword arguments since they are ' + 'mutually exclusive.'.format(*actions)) + elif num_actions == 3: + raise InterpreterException('Must specify one of {!r}, {!r}, and ' + '{!r} keyword arguments since they are ' + 'mutually exclusive.'.format(*actions)) + + if kwargs['capture'] and not kwargs['command']: + raise InvalidArguments('configure_file: "capture" keyword requires "command" keyword.') + + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) + + fmt = kwargs['format'] + output_format = kwargs['output_format'] + depfile = kwargs['depfile'] + + # Validate input + inputs = self.source_strings_to_files(kwargs['input']) + inputs_abs = [] + for f in inputs: + if isinstance(f, mesonlib.File): + inputs_abs.append(f.absolute_path(self.environment.source_dir, + self.environment.build_dir)) + self.add_build_def_file(f) + else: + raise InterpreterException('Inputs can only be strings or file objects') + + # Validate output + output = kwargs['output'] + if inputs_abs: + values = mesonlib.get_filenames_templates_dict(inputs_abs, None) + outputs = mesonlib.substitute_values([output], values) + output = outputs[0] + if depfile: + depfile = mesonlib.substitute_values([depfile], values)[0] + ofile_rpath = os.path.join(self.subdir, output) + if ofile_rpath in self.configure_file_outputs: + mesonbuildfile = os.path.join(self.subdir, 'meson.build') + current_call = f"{mesonbuildfile}:{self.current_lineno}" + first_call = "{}:{}".format(mesonbuildfile, self.configure_file_outputs[ofile_rpath]) + mlog.warning('Output file', mlog.bold(ofile_rpath, True), 'for configure_file() at', current_call, 'overwrites configure_file() output at', first_call) + else: + self.configure_file_outputs[ofile_rpath] = self.current_lineno + (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output)) + ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname) + + # Perform the appropriate action + if kwargs['configuration'] is not None: + conf = kwargs['configuration'] + if isinstance(conf, dict): + FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject, location=node) + for k, v in conf.items(): + if not isinstance(v, (str, int, bool)): + raise InvalidArguments( + f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"') + conf = build.ConfigurationData(conf) + mlog.log('Configuring', mlog.bold(output), 'using configuration') + if len(inputs) > 1: + raise InterpreterException('At most one input file can given in configuration mode') + if inputs: + os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True) + file_encoding = kwargs['encoding'] + missing_variables, confdata_useless = \ + mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf, + fmt, file_encoding, self.subproject) + if missing_variables: + var_list = ", ".join(repr(m) for m in sorted(missing_variables)) + mlog.warning( + f"The variable(s) {var_list} in the input file '{inputs[0]}' are not " + "present in the given configuration data.", location=node) + if confdata_useless: + ifbase = os.path.basename(inputs_abs[0]) + tv = FeatureNew.get_target_version(self.subproject) + if FeatureNew.check_version(tv, '0.47.0'): + mlog.warning('Got an empty configuration_data() object and found no ' + f'substitutions in the input file {ifbase!r}. If you want to ' + 'copy a file to the build dir, use the \'copy:\' keyword ' + 'argument added in 0.47.0', location=node) + else: + mesonlib.dump_conf_header(ofile_abs, conf, output_format) + conf.used = True + elif kwargs['command'] is not None: + if len(inputs) > 1: + FeatureNew.single_use('multiple inputs in configure_file()', '0.52.0', self.subproject, location=node) + # We use absolute paths for input and output here because the cwd + # that the command is run from is 'unspecified', so it could change. + # Currently it's builddir/subdir for in_builddir else srcdir/subdir. + values = mesonlib.get_filenames_templates_dict(inputs_abs, [ofile_abs]) + if depfile: + depfile = os.path.join(self.environment.get_scratch_dir(), depfile) + values['@DEPFILE@'] = depfile + # Substitute @INPUT@, @OUTPUT@, etc here. + _cmd = mesonlib.substitute_values(kwargs['command'], values) + mlog.log('Configuring', mlog.bold(output), 'with command') + cmd, *args = _cmd + res = self.run_command_impl(node, (cmd, args), + {'capture': True, 'check': True, 'env': build.EnvironmentVariables()}, + True) + if kwargs['capture']: + dst_tmp = ofile_abs + '~' + file_encoding = kwargs['encoding'] + with open(dst_tmp, 'w', encoding=file_encoding) as f: + f.writelines(res.stdout) + if inputs_abs: + shutil.copymode(inputs_abs[0], dst_tmp) + mesonlib.replace_if_different(ofile_abs, dst_tmp) + if depfile: + mlog.log('Reading depfile:', mlog.bold(depfile)) + with open(depfile, encoding='utf-8') as f: + df = DepFile(f.readlines()) + deps = df.get_all_dependencies(ofile_fname) + for dep in deps: + self.add_build_def_file(dep) + + elif kwargs['copy']: + if len(inputs_abs) != 1: + raise InterpreterException('Exactly one input file must be given in copy mode') + os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True) + shutil.copy2(inputs_abs[0], ofile_abs) + + # Install file if requested, we check for the empty string + # for backwards compatibility. That was the behaviour before + # 0.45.0 so preserve it. + idir = kwargs['install_dir'] + if idir is False: + idir = '' + FeatureDeprecated.single_use('configure_file install_dir: false', '0.50.0', + self.subproject, 'Use the `install:` kwarg instead', location=node) + install = kwargs['install'] if kwargs['install'] is not None else idir != '' + if install: + if not idir: + raise InterpreterException( + '"install_dir" must be specified when "install" in a configure_file is true') + idir_name = idir + if isinstance(idir_name, P_OBJ.OptionString): + idir_name = idir_name.optname + cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname) + install_tag = kwargs['install_tag'] + self.build.data.append(build.Data([cfile], idir, idir_name, install_mode, self.subproject, + install_tag=install_tag, data_type='configure')) + return mesonlib.File.from_built_file(self.subdir, output) + + def extract_incdirs(self, kwargs, key: str = 'include_directories'): + prospectives = extract_as_list(kwargs, key) + if key == 'include_directories': + for i in prospectives: + if isinstance(i, str): + FeatureNew.single_use('include_directories kwarg of type string', '0.50.0', self.subproject, + f'Use include_directories({i!r}) instead', location=self.current_node) + break + + result = [] + for p in prospectives: + if isinstance(p, build.IncludeDirs): + result.append(p) + elif isinstance(p, str): + result.append(self.build_incdir_object([p])) + else: + raise InterpreterException('Include directory objects can only be created from strings or include directories.') + return result + + @typed_pos_args('include_directories', varargs=str) + @typed_kwargs('include_directories', KwargInfo('is_system', bool, default=False)) + def func_include_directories(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], + kwargs: 'kwtypes.FuncIncludeDirectories') -> build.IncludeDirs: + return self.build_incdir_object(args[0], kwargs['is_system']) + + def build_incdir_object(self, incdir_strings: T.List[str], is_system: bool = False) -> build.IncludeDirs: + if not isinstance(is_system, bool): + raise InvalidArguments('Is_system must be boolean.') + src_root = self.environment.get_source_dir() + build_root = self.environment.get_build_dir() + absbase_src = os.path.join(src_root, self.subdir) + absbase_build = os.path.join(build_root, self.subdir) + + for a in incdir_strings: + if a.startswith(src_root): + raise InvalidArguments(textwrap.dedent('''\ + Tried to form an absolute path to a dir in the source tree. + You should not do that but use relative paths instead, for + directories that are part of your project. + + To get include path to any directory relative to the current dir do + + incdir = include_directories(dirname) + + After this incdir will contain both the current source dir as well as the + corresponding build dir. It can then be used in any subdirectory and + Meson will take care of all the busywork to make paths work. + + Dirname can even be '.' to mark the current directory. Though you should + remember that the current source and build directories are always + put in the include directories by default so you only need to do + include_directories('.') if you intend to use the result in a + different subdirectory. + + Note that this error message can also be triggered by + external dependencies being installed within your source + tree - it's not recommended to do this. + ''')) + else: + try: + self.validate_within_subproject(self.subdir, a) + except InterpreterException: + mlog.warning('include_directories sandbox violation!', location=self.current_node) + print(textwrap.dedent(f'''\ + The project is trying to access the directory {a!r} which belongs to a different + subproject. This is a problem as it hardcodes the relative paths of these two projects. + This makes it impossible to compile the project in any other directory layout and also + prevents the subproject from changing its own directory layout. + + Instead of poking directly at the internals the subproject should be executed and + it should set a variable that the caller can then use. Something like: + + # In subproject + some_dep = declare_dependency(include_directories: include_directories('include')) + + # In subproject wrap file + [provide] + some = some_dep + + # In parent project + some_dep = dependency('some') + executable(..., dependencies: [some_dep]) + + This warning will become a hard error in a future Meson release. + ''')) + absdir_src = os.path.join(absbase_src, a) + absdir_build = os.path.join(absbase_build, a) + if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build): + raise InvalidArguments(f'Include dir {a} does not exist.') + i = build.IncludeDirs(self.subdir, incdir_strings, is_system) + return i + + @typed_pos_args('add_test_setup', str) + @typed_kwargs( + 'add_test_setup', + KwargInfo('exe_wrapper', ContainerTypeInfo(list, (str, ExternalProgram)), listify=True, default=[]), + KwargInfo('gdb', bool, default=False), + KwargInfo('timeout_multiplier', int, default=1), + KwargInfo('exclude_suites', ContainerTypeInfo(list, str), listify=True, default=[], since='0.57.0'), + KwargInfo('is_default', bool, default=False, since='0.49.0'), + ENV_KW, + ) + def func_add_test_setup(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtypes.AddTestSetup') -> None: + setup_name = args[0] + if re.fullmatch('([_a-zA-Z][_0-9a-zA-Z]*:)?[_a-zA-Z][_0-9a-zA-Z]*', setup_name) is None: + raise InterpreterException('Setup name may only contain alphanumeric characters.') + if ":" not in setup_name: + setup_name = f'{(self.subproject if self.subproject else self.build.project_name)}:{setup_name}' + + exe_wrapper: T.List[str] = [] + for i in kwargs['exe_wrapper']: + if isinstance(i, str): + exe_wrapper.append(i) + else: + if not i.found(): + raise InterpreterException('Tried to use non-found executable.') + exe_wrapper += i.get_command() + + timeout_multiplier = kwargs['timeout_multiplier'] + if timeout_multiplier <= 0: + FeatureNew('add_test_setup() timeout_multiplier <= 0', '0.57.0').use(self.subproject) + + if kwargs['is_default']: + if self.build.test_setup_default_name is not None: + raise InterpreterException(f'{self.build.test_setup_default_name!r} is already set as default. ' + 'is_default can be set to true only once') + self.build.test_setup_default_name = setup_name + self.build.test_setups[setup_name] = build.TestSetup(exe_wrapper, kwargs['gdb'], timeout_multiplier, kwargs['env'], + kwargs['exclude_suites']) + + @typed_pos_args('add_global_arguments', varargs=str) + @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW) + def func_add_global_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + self._add_global_arguments(node, self.build.global_args[kwargs['native']], args[0], kwargs) + + @typed_pos_args('add_global_link_arguments', varargs=str) + @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW) + def func_add_global_link_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + self._add_global_arguments(node, self.build.global_link_args[kwargs['native']], args[0], kwargs) + + @typed_pos_args('add_project_arguments', varargs=str) + @typed_kwargs('add_project_arguments', NATIVE_KW, LANGUAGE_KW) + def func_add_project_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + self._add_project_arguments(node, self.build.projects_args[kwargs['native']], args[0], kwargs) + + @typed_pos_args('add_project_link_arguments', varargs=str) + @typed_kwargs('add_global_arguments', NATIVE_KW, LANGUAGE_KW) + def func_add_project_link_arguments(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + self._add_project_arguments(node, self.build.projects_link_args[kwargs['native']], args[0], kwargs) + + @FeatureNew('add_project_dependencies', '0.63.0') + @typed_pos_args('add_project_dependencies', varargs=dependencies.Dependency) + @typed_kwargs('add_project_dependencies', NATIVE_KW, LANGUAGE_KW) + def func_add_project_dependencies(self, node: mparser.FunctionNode, args: T.Tuple[T.List[dependencies.Dependency]], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + for_machine = kwargs['native'] + for lang in kwargs['language']: + if lang not in self.compilers[for_machine]: + raise InvalidCode(f'add_project_dependencies() called before add_language() for language "{lang}"') + + for d in dependencies.get_leaf_external_dependencies(args[0]): + compile_args = list(d.get_compile_args()) + system_incdir = d.get_include_type() == 'system' + for i in d.get_include_dirs(): + for lang in kwargs['language']: + comp = self.coredata.compilers[for_machine][lang] + for idir in i.to_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()): + compile_args.extend(comp.get_include_args(idir, system_incdir)) + + self._add_project_arguments(node, self.build.projects_args[for_machine], compile_args, kwargs) + self._add_project_arguments(node, self.build.projects_link_args[for_machine], d.get_link_args(), kwargs) + + def _warn_about_builtin_args(self, args: T.List[str]) -> None: + # -Wpedantic is deliberately not included, since some people want to use it but not use -Wextra + # see e.g. + # https://github.com/mesonbuild/meson/issues/3275#issuecomment-641354956 + # https://github.com/mesonbuild/meson/issues/3742 + warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra') + optargs = ('-O0', '-O2', '-O3', '-Os', '-Oz', '/O1', '/O2', '/Os') + for arg in args: + if arg in warnargs: + mlog.warning(f'Consider using the built-in warning_level option instead of using "{arg}".', + location=self.current_node) + elif arg in optargs: + mlog.warning(f'Consider using the built-in optimization level instead of using "{arg}".', + location=self.current_node) + elif arg == '-Werror': + mlog.warning(f'Consider using the built-in werror option instead of using "{arg}".', + location=self.current_node) + elif arg == '-g': + mlog.warning(f'Consider using the built-in debug option instead of using "{arg}".', + location=self.current_node) + elif arg.startswith('-fsanitize'): + mlog.warning(f'Consider using the built-in option for sanitizers instead of using "{arg}".', + location=self.current_node) + elif arg.startswith('-std=') or arg.startswith('/std:'): + mlog.warning(f'Consider using the built-in option for language standard version instead of using "{arg}".', + location=self.current_node) + + def _add_global_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]], + args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + if self.is_subproject(): + msg = f'Function \'{node.func_name}\' cannot be used in subprojects because ' \ + 'there is no way to make that reliable.\nPlease only call ' \ + 'this if is_subproject() returns false. Alternatively, ' \ + 'define a variable that\ncontains your language-specific ' \ + 'arguments and add it to the appropriate *_args kwarg ' \ + 'in each target.' + raise InvalidCode(msg) + frozen = self.project_args_frozen or self.global_args_frozen + self._add_arguments(node, argsdict, frozen, args, kwargs) + + def _add_project_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.Dict[str, T.List[str]]], + args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + if self.subproject not in argsdict: + argsdict[self.subproject] = {} + self._add_arguments(node, argsdict[self.subproject], + self.project_args_frozen, args, kwargs) + + def _add_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]], + args_frozen: bool, args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: + if args_frozen: + msg = f'Tried to use \'{node.func_name}\' after a build target has been declared.\n' \ + 'This is not permitted. Please declare all arguments before your targets.' + raise InvalidCode(msg) + + self._warn_about_builtin_args(args) + + for lang in kwargs['language']: + argsdict[lang] = argsdict.get(lang, []) + args + + @noArgsFlattening + @typed_pos_args('environment', optargs=[(str, list, dict)]) + @typed_kwargs('environment', ENV_METHOD_KW, ENV_SEPARATOR_KW.evolve(since='0.62.0')) + def func_environment(self, node: mparser.FunctionNode, args: T.Tuple[T.Union[None, str, T.List['TYPE_var'], T.Dict[str, 'TYPE_var']]], + kwargs: 'TYPE_kwargs') -> build.EnvironmentVariables: + init = args[0] + if init is not None: + FeatureNew.single_use('environment positional arguments', '0.52.0', self.subproject, location=node) + msg = ENV_KW.validator(init) + if msg: + raise InvalidArguments(f'"environment": {msg}') + if isinstance(init, dict) and any(i for i in init.values() if isinstance(i, list)): + FeatureNew.single_use('List of string in dictionary value', '0.62.0', self.subproject, location=node) + return env_convertor_with_method(init, kwargs['method'], kwargs['separator']) + return build.EnvironmentVariables() + + @typed_pos_args('join_paths', varargs=str, min_varargs=1) + @noKwargs + def func_join_paths(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> str: + parts = args[0] + other = os.path.join('', *parts[1:]).replace('\\', '/') + ret = os.path.join(*parts).replace('\\', '/') + if isinstance(parts[0], P_OBJ.DependencyVariableString) and '..' not in other: + return P_OBJ.DependencyVariableString(ret) + elif isinstance(parts[0], P_OBJ.OptionString): + name = os.path.join(parts[0].optname, other) + return P_OBJ.OptionString(ret, name) + else: + return ret + + def run(self) -> None: + super().run() + mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets)))) + FeatureNew.report(self.subproject) + FeatureDeprecated.report(self.subproject) + FeatureBroken.report(self.subproject) + if not self.is_subproject(): + self.print_extra_warnings() + self._print_summary() + + def print_extra_warnings(self) -> None: + # TODO cross compilation + for c in self.coredata.compilers.host.values(): + if c.get_id() == 'clang': + self.check_clang_asan_lundef() + break + + def check_clang_asan_lundef(self) -> None: + if OptionKey('b_lundef') not in self.coredata.options: + return + if OptionKey('b_sanitize') not in self.coredata.options: + return + if (self.coredata.options[OptionKey('b_lundef')].value and + self.coredata.options[OptionKey('b_sanitize')].value != 'none'): + value = self.coredata.options[OptionKey('b_sanitize')].value + mlog.warning(textwrap.dedent(f'''\ + Trying to use {value} sanitizer on Clang with b_lundef. + This will probably not work. + Try setting b_lundef to false instead.'''), + location=self.current_node) # noqa: E128 + + # Check that the indicated file is within the same subproject + # as we currently are. This is to stop people doing + # nasty things like: + # + # f = files('../../master_src/file.c') + # + # Note that this is validated only when the file + # object is generated. The result can be used in a different + # subproject than it is defined in (due to e.g. a + # declare_dependency). + def validate_within_subproject(self, subdir, fname): + srcdir = Path(self.environment.source_dir) + builddir = Path(self.environment.build_dir) + if isinstance(fname, P_OBJ.DependencyVariableString): + def validate_installable_file(fpath: Path) -> bool: + installablefiles: T.Set[Path] = set() + for d in self.build.data: + for s in d.sources: + installablefiles.add(Path(s.absolute_path(srcdir, builddir))) + installabledirs = [str(Path(srcdir, s.source_subdir)) for s in self.build.install_dirs] + if fpath in installablefiles: + return True + for d in installabledirs: + if str(fpath).startswith(d): + return True + return False + + norm = Path(fname) + # variables built from a dep.get_variable are allowed to refer to + # subproject files, as long as they are scheduled to be installed. + if validate_installable_file(norm): + return + norm = Path(os.path.abspath(Path(srcdir, subdir, fname))) + if os.path.isdir(norm): + inputtype = 'directory' + else: + inputtype = 'file' + if InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES in self.relaxations and builddir in norm.parents: + return + if srcdir not in norm.parents: + # Grabbing files outside the source tree is ok. + # This is for vendor stuff like: + # + # /opt/vendorsdk/src/file_with_license_restrictions.c + return + project_root = Path(srcdir, self.root_subdir) + subproject_dir = project_root / self.subproject_dir + if norm == project_root: + return + if project_root not in norm.parents: + raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {norm.name} outside current (sub)project.') + if subproject_dir == norm or subproject_dir in norm.parents: + raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {norm.name} from a nested subproject.') + + @T.overload + def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], strict: bool = True) -> T.List['mesonlib.File']: ... + + @T.overload + def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], strict: bool = False) -> T.List['mesonlib.FileOrString']: ... # noqa: F811 + + @T.overload + def source_strings_to_files(self, sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]) -> T.List[T.Union[mesonlib.File, build.GeneratedTypes]]: ... # noqa: F811 + + @T.overload + def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: ... # noqa: F811 + + def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: # noqa: F811 + """Lower inputs to a list of Targets and Files, replacing any strings. + + :param sources: A raw (Meson DSL) list of inputs (targets, files, and + strings) + :raises InterpreterException: if any of the inputs are of an invalid type + :return: A list of Targets and Files + """ + mesonlib.check_direntry_issues(sources) + if not isinstance(sources, list): + sources = [sources] + results: T.List['SourceOutputs'] = [] + for s in sources: + if isinstance(s, str): + if not strict and s.startswith(self.environment.get_build_dir()): + results.append(s) + mlog.warning(f'Source item {s!r} cannot be converted to File object, because it is a generated file. ' + 'This will become a hard error in the future.', location=self.current_node) + else: + self.validate_within_subproject(self.subdir, s) + results.append(mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s)) + elif isinstance(s, mesonlib.File): + results.append(s) + elif isinstance(s, (build.GeneratedList, build.BuildTarget, + build.CustomTargetIndex, build.CustomTarget, + build.ExtractedObjects, build.StructuredSources)): + results.append(s) + else: + raise InterpreterException(f'Source item is {s!r} instead of ' + 'string or File-type object') + return results + + @staticmethod + def validate_forbidden_targets(name: str) -> None: + if name.startswith('meson-internal__'): + raise InvalidArguments("Target names starting with 'meson-internal__' are reserved " + "for Meson's internal use. Please rename.") + if name.startswith('meson-') and '.' not in name: + raise InvalidArguments("Target names starting with 'meson-' and without a file extension " + "are reserved for Meson's internal use. Please rename.") + if name in coredata.FORBIDDEN_TARGET_NAMES: + raise InvalidArguments(f"Target name '{name}' is reserved for Meson's " + "internal use. Please rename.") + + def add_target(self, name: str, tobj: build.Target) -> None: + if self.backend.name == 'none': + raise InterpreterException('Install-only backend cannot generate target rules, try using `--backend=ninja`.') + if name == '': + raise InterpreterException('Target name must not be empty.') + if name.strip() == '': + raise InterpreterException('Target name must not consist only of whitespace.') + if has_path_sep(name): + pathseg = os.path.join(self.subdir, os.path.split(name)[0]) + if os.path.exists(os.path.join(self.source_root, pathseg)): + raise InvalidArguments(textwrap.dedent(f'''\ + Target "{name}" has a path segment pointing to directory "{pathseg}". This is an error. + To define a target that builds in that directory you must define it + in the meson.build file in that directory. + ''')) + self.validate_forbidden_targets(name) + # To permit an executable and a shared library to have the + # same name, such as "foo.exe" and "libfoo.a". + idname = tobj.get_id() + if idname in self.build.targets: + raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.') + + if isinstance(tobj, build.BuildTarget): + self.add_languages(tobj.missing_languages, True, tobj.for_machine) + tobj.process_compilers_late() + self.add_stdlib_info(tobj) + + self.build.targets[idname] = tobj + if idname not in self.coredata.target_guids: + self.coredata.target_guids[idname] = str(uuid.uuid4()).upper() + + @FeatureNew('both_libraries', '0.46.0') + def build_both_libraries(self, node, args, kwargs): + shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary) + static_lib = self.build_target(node, args, kwargs, build.StaticLibrary) + + if self.backend.name == 'xcode': + # Xcode is a bit special in that you can't (at least for the moment) + # form a library only from object file inputs. The simple but inefficient + # solution is to use the sources directly. This will lead to them being + # built twice. This is unfortunate and slow, but at least it works. + # Feel free to submit patches to get this fixed if it is an + # issue for you. + reuse_object_files = False + else: + reuse_object_files = static_lib.pic + + if reuse_object_files: + # Replace sources with objects from the shared library to avoid + # building them twice. We post-process the static library instead of + # removing sources from args because sources could also come from + # any InternalDependency, see BuildTarget.add_deps(). + static_lib.objects.append(build.ExtractedObjects(shared_lib, shared_lib.sources, shared_lib.generated, [])) + static_lib.sources = [] + static_lib.generated = [] + # Compilers with no corresponding sources confuses the backend. + # Keep only compilers used for linking + static_lib.compilers = {k: v for k, v in static_lib.compilers.items() if k in compilers.clink_langs} + + return build.BothLibraries(shared_lib, static_lib) + + def build_library(self, node, args, kwargs): + default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject)) + if default_library == 'shared': + return self.build_target(node, args, kwargs, build.SharedLibrary) + elif default_library == 'static': + return self.build_target(node, args, kwargs, build.StaticLibrary) + elif default_library == 'both': + return self.build_both_libraries(node, args, kwargs) + else: + raise InterpreterException(f'Unknown default_library value: {default_library}.') + + def build_target(self, node: mparser.BaseNode, args, kwargs, targetclass): + @FeatureNewKwargs('build target', '1.2.0', ['rust_dependency_map']) + @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories']) + @FeatureNewKwargs('build target', '0.41.0', ['rust_args']) + @FeatureNewKwargs('build target', '0.38.0', ['build_by_default']) + @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) + def build_target_decorator_caller(self, node, args, kwargs): + return True + + build_target_decorator_caller(self, node, args, kwargs) + + name, sources = args + for_machine = self.machine_from_native_kwarg(kwargs) + if 'sources' in kwargs: + sources += listify(kwargs['sources']) + if any(isinstance(s, build.BuildTarget) for s in sources): + FeatureBroken.single_use('passing references to built targets as a source file', '1.1.0', self.subproject, + 'Consider using `link_with` or `link_whole` if you meant to link, or dropping them as otherwise they are ignored.', + node) + if any(isinstance(s, build.ExtractedObjects) for s in sources): + FeatureBroken.single_use('passing object files as sources', '1.1.0', self.subproject, + 'Pass these to the `objects` keyword instead, they are ignored when passed as sources.', + node) + # Go ahead and drop these here, since they're only allowed through for + # backwards compatibility anyway + sources = [s for s in sources + if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))] + sources = self.source_strings_to_files(sources) + objs = extract_as_list(kwargs, 'objects') + kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') + kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs) + if 'extra_files' in kwargs: + ef = extract_as_list(kwargs, 'extra_files') + kwargs['extra_files'] = self.source_strings_to_files(ef) + self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources) + if targetclass not in {build.Executable, build.SharedLibrary, build.SharedModule, build.StaticLibrary, build.Jar}: + mlog.debug('Unknown target type:', str(targetclass)) + raise RuntimeError('Unreachable code') + self.kwarg_strings_to_includedirs(kwargs) + + # Filter out kwargs from other target types. For example 'soversion' + # passed to library() when default_library == 'static'. + kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs} + + srcs: T.List['SourceInputs'] = [] + struct: T.Optional[build.StructuredSources] = build.StructuredSources() + for s in sources: + if isinstance(s, build.StructuredSources): + struct = struct + s + else: + srcs.append(s) + + if not struct: + struct = None + else: + # Validate that we won't end up with two outputs with the same name. + # i.e, don't allow: + # [structured_sources('foo/bar.rs'), structured_sources('bar/bar.rs')] + for v in struct.sources.values(): + outputs: T.Set[str] = set() + for f in v: + o: T.List[str] + if isinstance(f, str): + o = [os.path.basename(f)] + elif isinstance(f, mesonlib.File): + o = [f.fname] + else: + o = f.get_outputs() + conflicts = outputs.intersection(o) + if conflicts: + raise InvalidArguments.from_node( + f"Conflicting sources in structured sources: {', '.join(sorted(conflicts))}", + node=node) + outputs.update(o) + + kwargs['include_directories'] = self.extract_incdirs(kwargs) + target = targetclass(name, self.subdir, self.subproject, for_machine, srcs, struct, objs, + self.environment, self.compilers[for_machine], kwargs) + + self.add_target(name, target) + self.project_args_frozen = True + return target + + def kwarg_strings_to_includedirs(self, kwargs): + if 'd_import_dirs' in kwargs: + items = mesonlib.extract_as_list(kwargs, 'd_import_dirs') + cleaned_items = [] + for i in items: + if isinstance(i, str): + # BW compatibility. This was permitted so we must support it + # for a few releases so people can transition to "correct" + # path declarations. + if os.path.normpath(i).startswith(self.environment.get_source_dir()): + mlog.warning('''Building a path to the source dir is not supported. Use a relative path instead. +This will become a hard error in the future.''', location=self.current_node) + i = os.path.relpath(i, os.path.join(self.environment.get_source_dir(), self.subdir)) + i = self.build_incdir_object([i]) + cleaned_items.append(i) + kwargs['d_import_dirs'] = cleaned_items + + def add_stdlib_info(self, target): + for l in target.compilers.keys(): + dep = self.build.stdlibs[target.for_machine].get(l, None) + if dep: + target.add_deps(dep) + + def check_sources_exist(self, subdir, sources): + for s in sources: + if not isinstance(s, str): + continue # This means a generated source and they always exist. + fname = os.path.join(subdir, s) + if not os.path.isfile(fname): + raise InterpreterException(f'Tried to add non-existing source file {s}.') + + # Only permit object extraction from the same subproject + def validate_extraction(self, buildtarget: mesonlib.HoldableObject) -> None: + if self.subproject != buildtarget.subproject: + raise InterpreterException('Tried to extract objects from a different subproject.') + + def is_subproject(self) -> bool: + return self.subproject != '' + + @typed_pos_args('set_variable', str, object) + @noKwargs + @noArgsFlattening + @noSecondLevelHolderResolving + def func_set_variable(self, node: mparser.BaseNode, args: T.Tuple[str, object], kwargs: 'TYPE_kwargs') -> None: + varname, value = args + self.set_variable(varname, value, holderify=True) + + @typed_pos_args('get_variable', (str, Disabler), optargs=[object]) + @noKwargs + @noArgsFlattening + @unholder_return + def func_get_variable(self, node: mparser.BaseNode, args: T.Tuple[T.Union[str, Disabler], T.Optional[object]], + kwargs: 'TYPE_kwargs') -> 'TYPE_var': + varname, fallback = args + if isinstance(varname, Disabler): + return varname + + try: + return self.variables[varname] + except KeyError: + if fallback is not None: + return self._holderify(fallback) + raise InterpreterException(f'Tried to get unknown variable "{varname}".') + + @typed_pos_args('is_variable', str) + @noKwargs + def func_is_variable(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: + return args[0] in self.variables + + @FeatureNew('unset_variable', '0.60.0') + @typed_pos_args('unset_variable', str) + @noKwargs + def func_unset_variable(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> None: + varname = args[0] + try: + del self.variables[varname] + except KeyError: + raise InterpreterException(f'Tried to unset unknown variable "{varname}".') + + @staticmethod + def machine_from_native_kwarg(kwargs: T.Dict[str, T.Any]) -> MachineChoice: + native = kwargs.get('native', False) + if not isinstance(native, bool): + raise InvalidArguments('Argument to "native" must be a boolean.') + return MachineChoice.BUILD if native else MachineChoice.HOST + + @FeatureNew('is_disabler', '0.52.0') + @typed_pos_args('is_disabler', object) + @noKwargs + def func_is_disabler(self, node: mparser.BaseNode, args: T.Tuple[object], kwargs: 'TYPE_kwargs') -> bool: + return isinstance(args[0], Disabler) + + @noKwargs + @FeatureNew('range', '0.58.0') + @typed_pos_args('range', int, optargs=[int, int]) + def func_range(self, node, args: T.Tuple[int, T.Optional[int], T.Optional[int]], kwargs: T.Dict[str, T.Any]) -> P_OBJ.RangeHolder: + start, stop, step = args + # Just like Python's range, we allow range(stop), range(start, stop), or + # range(start, stop, step) + if stop is None: + stop = start + start = 0 + if step is None: + step = 1 + # This is more strict than Python's range() + if start < 0: + raise InterpreterException('start cannot be negative') + if stop < start: + raise InterpreterException('stop cannot be less than start') + if step < 1: + raise InterpreterException('step must be >=1') + return P_OBJ.RangeHolder(start, stop, step, subproject=self.subproject) diff --git a/devtools/meson/mesonbuild/interpreter/interpreterobjects.py b/devtools/meson/mesonbuild/interpreter/interpreterobjects.py new file mode 100644 index 0000000..fac3b0e --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/interpreterobjects.py @@ -0,0 +1,1054 @@ +from __future__ import annotations +import os +import shlex +import subprocess +import copy +import textwrap + +from pathlib import Path, PurePath + +from .. import mesonlib +from .. import coredata +from .. import build +from .. import mlog + +from ..modules import ModuleReturnValue, ModuleObject, ModuleState, ExtensionModule +from ..backend.backends import TestProtocol +from ..interpreterbase import ( + ContainerTypeInfo, KwargInfo, MesonOperator, + MesonInterpreterObject, ObjectHolder, MutableInterpreterObject, + FeatureNew, FeatureDeprecated, + typed_pos_args, typed_kwargs, typed_operator, + noArgsFlattening, noPosargs, noKwargs, unholder_return, + flatten, resolve_second_level_holders, InterpreterException, InvalidArguments, InvalidCode) +from ..interpreter.type_checking import NoneType, ENV_SEPARATOR_KW +from ..dependencies import Dependency, ExternalLibrary, InternalDependency +from ..programs import ExternalProgram +from ..mesonlib import HoldableObject, OptionKey, listify, Popen_safe + +import typing as T + +if T.TYPE_CHECKING: + from . import kwargs + from ..cmake.interpreter import CMakeInterpreter + from ..envconfig import MachineInfo + from ..interpreterbase import FeatureCheckBase, InterpreterObject, SubProject, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs + from .interpreter import Interpreter + + from typing_extensions import TypedDict + + class EnvironmentSeparatorKW(TypedDict): + + separator: str + +_ERROR_MSG_KW: KwargInfo[T.Optional[str]] = KwargInfo('error_message', (str, NoneType)) + + +def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired', + subproject: 'SubProject', + feature_check: T.Optional[FeatureCheckBase] = None, + default: bool = True) -> T.Tuple[bool, bool, T.Optional[str]]: + val = kwargs.get('required', default) + disabled = False + required = False + feature: T.Optional[str] = None + if isinstance(val, coredata.UserFeatureOption): + if not feature_check: + feature_check = FeatureNew('User option "feature"', '0.47.0') + feature_check.use(subproject) + feature = val.name + if val.is_disabled(): + disabled = True + elif val.is_enabled(): + required = True + elif isinstance(val, bool): + required = val + else: + raise InterpreterException('required keyword argument must be boolean or a feature option') + + # Keep boolean value in kwargs to simplify other places where this kwarg is + # checked. + # TODO: this should be removed, and those callers should learn about FeatureOptions + kwargs['required'] = required + + return disabled, required, feature + +def extract_search_dirs(kwargs: 'kwargs.ExtractSearchDirs') -> T.List[str]: + search_dirs_str = mesonlib.stringlistify(kwargs.get('dirs', [])) + search_dirs = [Path(d).expanduser() for d in search_dirs_str] + for d in search_dirs: + if mesonlib.is_windows() and d.root.startswith('\\'): + # a Unix-path starting with `/` that is not absolute on Windows. + # discard without failing for end-user ease of cross-platform directory arrays + continue + if not d.is_absolute(): + raise InvalidCode(f'Search directory {d} is not an absolute path.') + return [str(s) for s in search_dirs] + +class FeatureOptionHolder(ObjectHolder[coredata.UserFeatureOption]): + def __init__(self, option: coredata.UserFeatureOption, interpreter: 'Interpreter'): + super().__init__(option, interpreter) + if option and option.is_auto(): + # TODO: we need to cast here because options is not a TypedDict + auto = T.cast('coredata.UserFeatureOption', self.env.coredata.options[OptionKey('auto_features')]) + self.held_object = copy.copy(auto) + self.held_object.name = option.name + self.methods.update({'enabled': self.enabled_method, + 'disabled': self.disabled_method, + 'allowed': self.allowed_method, + 'auto': self.auto_method, + 'require': self.require_method, + 'disable_auto_if': self.disable_auto_if_method, + 'enable_auto_if': self.enable_auto_if_method, + 'disable_if': self.disable_if_method, + 'enable_if': self.enable_if_method, + }) + + @property + def value(self) -> str: + return 'disabled' if not self.held_object else self.held_object.value + + def as_disabled(self) -> coredata.UserFeatureOption: + disabled = copy.deepcopy(self.held_object) + disabled.value = 'disabled' + return disabled + + def as_enabled(self) -> coredata.UserFeatureOption: + enabled = copy.deepcopy(self.held_object) + enabled.value = 'enabled' + return enabled + + @noPosargs + @noKwargs + def enabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.value == 'enabled' + + @noPosargs + @noKwargs + def disabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.value == 'disabled' + + @noPosargs + @noKwargs + @FeatureNew('feature_option.allowed()', '0.59.0') + def allowed_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.value != 'disabled' + + @noPosargs + @noKwargs + def auto_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.value == 'auto' + + def _disable_if(self, condition: bool, message: T.Optional[str]) -> coredata.UserFeatureOption: + if not condition: + return copy.deepcopy(self.held_object) + + if self.value == 'enabled': + err_msg = f'Feature {self.held_object.name} cannot be enabled' + if message: + err_msg += f': {message}' + raise InterpreterException(err_msg) + return self.as_disabled() + + @FeatureNew('feature_option.require()', '0.59.0') + @typed_pos_args('feature_option.require', bool) + @typed_kwargs( + 'feature_option.require', + _ERROR_MSG_KW, + ) + def require_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption: + return self._disable_if(not args[0], kwargs['error_message']) + + @FeatureNew('feature_option.disable_if()', '1.1.0') + @typed_pos_args('feature_option.disable_if', bool) + @typed_kwargs( + 'feature_option.disable_if', + _ERROR_MSG_KW, + ) + def disable_if_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption: + return self._disable_if(args[0], kwargs['error_message']) + + @FeatureNew('feature_option.enable_if()', '1.1.0') + @typed_pos_args('feature_option.enable_if', bool) + @typed_kwargs( + 'feature_option.enable_if', + _ERROR_MSG_KW, + ) + def enable_if_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption: + if not args[0]: + return copy.deepcopy(self.held_object) + + if self.value == 'disabled': + err_msg = f'Feature {self.held_object.name} cannot be disabled' + if kwargs['error_message']: + err_msg += f': {kwargs["error_message"]}' + raise InterpreterException(err_msg) + return self.as_enabled() + + @FeatureNew('feature_option.disable_auto_if()', '0.59.0') + @noKwargs + @typed_pos_args('feature_option.disable_auto_if', bool) + def disable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption: + return copy.deepcopy(self.held_object) if self.value != 'auto' or not args[0] else self.as_disabled() + + @FeatureNew('feature_option.enable_auto_if()', '1.1.0') + @noKwargs + @typed_pos_args('feature_option.enable_auto_if', bool) + def enable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption: + return self.as_enabled() if self.value == 'auto' and args[0] else copy.deepcopy(self.held_object) + + +class RunProcess(MesonInterpreterObject): + + def __init__(self, + cmd: ExternalProgram, + args: T.List[str], + env: build.EnvironmentVariables, + source_dir: str, + build_dir: str, + subdir: str, + mesonintrospect: T.List[str], + in_builddir: bool = False, + check: bool = False, + capture: bool = True) -> None: + super().__init__() + if not isinstance(cmd, ExternalProgram): + raise AssertionError('BUG: RunProcess must be passed an ExternalProgram') + self.capture = capture + self.returncode, self.stdout, self.stderr = self.run_command(cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check) + self.methods.update({'returncode': self.returncode_method, + 'stdout': self.stdout_method, + 'stderr': self.stderr_method, + }) + + def run_command(self, + cmd: ExternalProgram, + args: T.List[str], + env: build.EnvironmentVariables, + source_dir: str, + build_dir: str, + subdir: str, + mesonintrospect: T.List[str], + in_builddir: bool, + check: bool = False) -> T.Tuple[int, str, str]: + command_array = cmd.get_command() + args + menv = {'MESON_SOURCE_ROOT': source_dir, + 'MESON_BUILD_ROOT': build_dir, + 'MESON_SUBDIR': subdir, + 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]), + } + if in_builddir: + cwd = os.path.join(build_dir, subdir) + else: + cwd = os.path.join(source_dir, subdir) + child_env = os.environ.copy() + child_env.update(menv) + child_env = env.get_env(child_env) + stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL + mlog.debug('Running command:', mesonlib.join_args(command_array)) + try: + p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd) + if self.capture: + mlog.debug('--- stdout ---') + mlog.debug(o) + else: + o = '' + mlog.debug('--- stdout disabled ---') + mlog.debug('--- stderr ---') + mlog.debug(e) + mlog.debug('') + + if check and p.returncode != 0: + raise InterpreterException('Command `{}` failed with status {}.'.format(mesonlib.join_args(command_array), p.returncode)) + + return p.returncode, o, e + except FileNotFoundError: + raise InterpreterException('Could not execute command `%s`.' % mesonlib.join_args(command_array)) + + @noPosargs + @noKwargs + def returncode_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: + return self.returncode + + @noPosargs + @noKwargs + def stdout_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.stdout + + @noPosargs + @noKwargs + def stderr_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.stderr + +class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], MutableInterpreterObject): + + def __init__(self, obj: build.EnvironmentVariables, interpreter: 'Interpreter'): + super().__init__(obj, interpreter) + self.methods.update({'set': self.set_method, + 'append': self.append_method, + 'prepend': self.prepend_method, + }) + + def __repr__(self) -> str: + repr_str = "<{0}: {1}>" + return repr_str.format(self.__class__.__name__, self.held_object.envvars) + + def __deepcopy__(self, memo: T.Dict[str, object]) -> 'EnvironmentVariablesHolder': + # Avoid trying to copy the interpreter + return EnvironmentVariablesHolder(copy.deepcopy(self.held_object), self.interpreter) + + def warn_if_has_name(self, name: str) -> None: + # Multiple append/prepend operations was not supported until 0.58.0. + if self.held_object.has_name(name): + m = f'Overriding previous value of environment variable {name!r} with a new one' + FeatureNew(m, '0.58.0').use(self.subproject, self.current_node) + + @typed_pos_args('environment.set', str, varargs=str, min_varargs=1) + @typed_kwargs('environment.set', ENV_SEPARATOR_KW) + def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: + name, values = args + self.held_object.set(name, values, kwargs['separator']) + + @typed_pos_args('environment.append', str, varargs=str, min_varargs=1) + @typed_kwargs('environment.append', ENV_SEPARATOR_KW) + def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: + name, values = args + self.warn_if_has_name(name) + self.held_object.append(name, values, kwargs['separator']) + + @typed_pos_args('environment.prepend', str, varargs=str, min_varargs=1) + @typed_kwargs('environment.prepend', ENV_SEPARATOR_KW) + def prepend_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: + name, values = args + self.warn_if_has_name(name) + self.held_object.prepend(name, values, kwargs['separator']) + + +_CONF_DATA_SET_KWS: KwargInfo[T.Optional[str]] = KwargInfo('description', (str, NoneType)) + + +class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInterpreterObject): + + def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'): + super().__init__(obj, interpreter) + self.methods.update({'set': self.set_method, + 'set10': self.set10_method, + 'set_quoted': self.set_quoted_method, + 'has': self.has_method, + 'get': self.get_method, + 'keys': self.keys_method, + 'get_unquoted': self.get_unquoted_method, + 'merge_from': self.merge_from_method, + }) + + def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder': + return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter) + + def is_used(self) -> bool: + return self.held_object.used + + def __check_used(self) -> None: + if self.is_used(): + raise InterpreterException("Can not set values on configuration object that has been used.") + + @typed_pos_args('configuration_data.set', str, (str, int, bool)) + @typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS) + def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None: + self.__check_used() + self.held_object.values[args[0]] = (args[1], kwargs['description']) + + @typed_pos_args('configuration_data.set_quoted', str, str) + @typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS) + def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None: + self.__check_used() + escaped_val = '\\"'.join(args[1].split('"')) + self.held_object.values[args[0]] = (f'"{escaped_val}"', kwargs['description']) + + @typed_pos_args('configuration_data.set10', str, (int, bool)) + @typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS) + def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None: + self.__check_used() + # bool is a subclass of int, so we need to check for bool explicitly. + # We already have typed_pos_args checking that this is either a bool or + # an int. + if not isinstance(args[1], bool): + mlog.deprecation('configuration_data.set10 with number. the `set10` ' + 'method should only be used with booleans', + location=self.interpreter.current_node) + if args[1] < 0: + mlog.warning('Passing a number that is less than 0 may not have the intended result, ' + 'as meson will treat all non-zero values as true.', + location=self.interpreter.current_node) + self.held_object.values[args[0]] = (int(args[1]), kwargs['description']) + + @typed_pos_args('configuration_data.has', (str, int, bool)) + @noKwargs + def has_method(self, args: T.Tuple[T.Union[str, int, bool]], kwargs: TYPE_kwargs) -> bool: + return args[0] in self.held_object.values + + @FeatureNew('configuration_data.get()', '0.38.0') + @typed_pos_args('configuration_data.get', str, optargs=[(str, int, bool)]) + @noKwargs + def get_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]], + kwargs: TYPE_kwargs) -> T.Union[str, int, bool]: + name = args[0] + if name in self.held_object: + return self.held_object.get(name)[0] + elif args[1] is not None: + return args[1] + raise InterpreterException(f'Entry {name} not in configuration data.') + + @FeatureNew('configuration_data.get_unquoted()', '0.44.0') + @typed_pos_args('configuration_data.get_unquoted', str, optargs=[(str, int, bool)]) + @noKwargs + def get_unquoted_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]], + kwargs: TYPE_kwargs) -> T.Union[str, int, bool]: + name = args[0] + if name in self.held_object: + val = self.held_object.get(name)[0] + elif args[1] is not None: + val = args[1] + else: + raise InterpreterException(f'Entry {name} not in configuration data.') + if isinstance(val, str) and val[0] == '"' and val[-1] == '"': + return val[1:-1] + return val + + def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]: + return self.held_object.values[name] + + @FeatureNew('configuration_data.keys()', '0.57.0') + @noPosargs + @noKwargs + def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: + return sorted(self.keys()) + + def keys(self) -> T.List[str]: + return list(self.held_object.values.keys()) + + @typed_pos_args('configuration_data.merge_from', build.ConfigurationData) + @noKwargs + def merge_from_method(self, args: T.Tuple[build.ConfigurationData], kwargs: TYPE_kwargs) -> None: + from_object = args[0] + self.held_object.values.update(from_object.values) + + +_PARTIAL_DEP_KWARGS = [ + KwargInfo('compile_args', bool, default=False), + KwargInfo('link_args', bool, default=False), + KwargInfo('links', bool, default=False), + KwargInfo('includes', bool, default=False), + KwargInfo('sources', bool, default=False), +] + +class DependencyHolder(ObjectHolder[Dependency]): + def __init__(self, dep: Dependency, interpreter: 'Interpreter'): + super().__init__(dep, interpreter) + self.methods.update({'found': self.found_method, + 'type_name': self.type_name_method, + 'version': self.version_method, + 'name': self.name_method, + 'get_pkgconfig_variable': self.pkgconfig_method, + 'get_configtool_variable': self.configtool_method, + 'get_variable': self.variable_method, + 'partial_dependency': self.partial_dependency_method, + 'include_type': self.include_type_method, + 'as_system': self.as_system_method, + 'as_link_whole': self.as_link_whole_method, + }) + + def found(self) -> bool: + return self.found_method([], {}) + + @noPosargs + @noKwargs + def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.type_name + + @noPosargs + @noKwargs + def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + if self.held_object.type_name == 'internal': + return True + return self.held_object.found() + + @noPosargs + @noKwargs + def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.get_version() + + @noPosargs + @noKwargs + def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.get_name() + + @FeatureDeprecated('dependency.get_pkgconfig_variable', '0.56.0', + 'use dependency.get_variable(pkgconfig : ...) instead') + @typed_pos_args('dependency.get_pkgconfig_variable', str) + @typed_kwargs( + 'dependency.get_pkgconfig_variable', + KwargInfo('default', (str, NoneType)), + KwargInfo( + 'define_variable', + ContainerTypeInfo(list, str, pairs=True), + default=[], + listify=True, + validator=lambda x: 'must be of length 2 or empty' if len(x) not in {0, 2} else None, + ), + ) + def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConfigVar') -> str: + return self.held_object.get_pkgconfig_variable(args[0], **kwargs) + + @FeatureNew('dependency.get_configtool_variable', '0.44.0') + @FeatureDeprecated('dependency.get_configtool_variable', '0.56.0', + 'use dependency.get_variable(configtool : ...) instead') + @noKwargs + @typed_pos_args('dependency.get_config_tool_variable', str) + def configtool_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> str: + return self.held_object.get_configtool_variable(args[0]) + + @FeatureNew('dependency.partial_dependency', '0.46.0') + @noPosargs + @typed_kwargs('dependency.partial_dependency', *_PARTIAL_DEP_KWARGS) + def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency: + pdep = self.held_object.get_partial_dependency(**kwargs) + return pdep + + @FeatureNew('dependency.get_variable', '0.51.0') + @typed_pos_args('dependency.get_variable', optargs=[str]) + @typed_kwargs( + 'dependency.get_variable', + KwargInfo('cmake', (str, NoneType)), + KwargInfo('pkgconfig', (str, NoneType)), + KwargInfo('configtool', (str, NoneType)), + KwargInfo('internal', (str, NoneType), since='0.54.0'), + KwargInfo('default_value', (str, NoneType)), + KwargInfo('pkgconfig_define', ContainerTypeInfo(list, str, pairs=True), default=[], listify=True), + ) + def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> str: + default_varname = args[0] + if default_varname is not None: + FeatureNew('Positional argument to dependency.get_variable()', '0.58.0').use(self.subproject, self.current_node) + return self.held_object.get_variable( + cmake=kwargs['cmake'] or default_varname, + pkgconfig=kwargs['pkgconfig'] or default_varname, + configtool=kwargs['configtool'] or default_varname, + internal=kwargs['internal'] or default_varname, + default_value=kwargs['default_value'], + pkgconfig_define=kwargs['pkgconfig_define'], + ) + + @FeatureNew('dependency.include_type', '0.52.0') + @noPosargs + @noKwargs + def include_type_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.get_include_type() + + @FeatureNew('dependency.as_system', '0.52.0') + @noKwargs + @typed_pos_args('dependency.as_system', optargs=[str]) + def as_system_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> Dependency: + return self.held_object.generate_system_dependency(args[0] or 'system') + + @FeatureNew('dependency.as_link_whole', '0.56.0') + @noKwargs + @noPosargs + def as_link_whole_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> Dependency: + if not isinstance(self.held_object, InternalDependency): + raise InterpreterException('as_link_whole method is only supported on declare_dependency() objects') + new_dep = self.held_object.generate_link_whole_dependency() + return new_dep + +class ExternalProgramHolder(ObjectHolder[ExternalProgram]): + def __init__(self, ep: ExternalProgram, interpreter: 'Interpreter') -> None: + super().__init__(ep, interpreter) + self.methods.update({'found': self.found_method, + 'path': self.path_method, + 'version': self.version_method, + 'full_path': self.full_path_method}) + + @noPosargs + @noKwargs + def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.found() + + @noPosargs + @noKwargs + @FeatureDeprecated('ExternalProgram.path', '0.55.0', + 'use ExternalProgram.full_path() instead') + def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self._full_path() + + @noPosargs + @noKwargs + @FeatureNew('ExternalProgram.full_path', '0.55.0') + def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self._full_path() + + def _full_path(self) -> str: + if not self.found(): + raise InterpreterException('Unable to get the path of a not-found external program') + path = self.held_object.get_path() + assert path is not None + return path + + @noPosargs + @noKwargs + @FeatureNew('ExternalProgram.version', '0.62.0') + def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + if not self.found(): + raise InterpreterException('Unable to get the version of a not-found external program') + try: + return self.held_object.get_version(self.interpreter) + except mesonlib.MesonException: + return 'unknown' + + def found(self) -> bool: + return self.held_object.found() + +class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]): + def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'): + super().__init__(el, interpreter) + self.methods.update({'found': self.found_method, + 'type_name': self.type_name_method, + 'partial_dependency': self.partial_dependency_method, + }) + + @noPosargs + @noKwargs + def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.type_name + + @noPosargs + @noKwargs + def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.held_object.found() + + @FeatureNew('dependency.partial_dependency', '0.46.0') + @noPosargs + @typed_kwargs('dependency.partial_dependency', *_PARTIAL_DEP_KWARGS) + def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency: + pdep = self.held_object.get_partial_dependency(**kwargs) + return pdep + +# A machine that's statically known from the cross file +class MachineHolder(ObjectHolder['MachineInfo']): + def __init__(self, machine_info: 'MachineInfo', interpreter: 'Interpreter'): + super().__init__(machine_info, interpreter) + self.methods.update({'system': self.system_method, + 'cpu': self.cpu_method, + 'cpu_family': self.cpu_family_method, + 'endian': self.endian_method, + 'kernel': self.kernel_method, + 'subsystem': self.subsystem_method, + }) + + @noPosargs + @noKwargs + def cpu_family_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.cpu_family + + @noPosargs + @noKwargs + def cpu_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.cpu + + @noPosargs + @noKwargs + def system_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.system + + @noPosargs + @noKwargs + def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.endian + + @noPosargs + @noKwargs + def kernel_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + if self.held_object.kernel is not None: + return self.held_object.kernel + raise InterpreterException('Kernel not defined or could not be autodetected.') + + @noPosargs + @noKwargs + def subsystem_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + if self.held_object.subsystem is not None: + return self.held_object.subsystem + raise InterpreterException('Subsystem not defined or could not be autodetected.') + + +class IncludeDirsHolder(ObjectHolder[build.IncludeDirs]): + pass + +class FileHolder(ObjectHolder[mesonlib.File]): + pass + +class HeadersHolder(ObjectHolder[build.Headers]): + pass + +class DataHolder(ObjectHolder[build.Data]): + pass + +class SymlinkDataHolder(ObjectHolder[build.SymlinkData]): + pass + +class InstallDirHolder(ObjectHolder[build.InstallDir]): + pass + +class ManHolder(ObjectHolder[build.Man]): + pass + +class EmptyDirHolder(ObjectHolder[build.EmptyDir]): + pass + +class GeneratedObjectsHolder(ObjectHolder[build.ExtractedObjects]): + pass + +class Test(MesonInterpreterObject): + def __init__(self, name: str, project: str, suite: T.List[str], + exe: T.Union[ExternalProgram, build.Executable, build.CustomTarget], + depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]], + is_parallel: bool, + cmd_args: T.List[T.Union[str, mesonlib.File, build.Target]], + env: build.EnvironmentVariables, + should_fail: bool, timeout: int, workdir: T.Optional[str], protocol: str, + priority: int, verbose: bool): + super().__init__() + self.name = name + self.suite = listify(suite) + self.project_name = project + self.exe = exe + self.depends = depends + self.is_parallel = is_parallel + self.cmd_args = cmd_args + self.env = env + self.should_fail = should_fail + self.timeout = timeout + self.workdir = workdir + self.protocol = TestProtocol.from_str(protocol) + self.priority = priority + self.verbose = verbose + + def get_exe(self) -> T.Union[ExternalProgram, build.Executable, build.CustomTarget]: + return self.exe + + def get_name(self) -> str: + return self.name + +class NullSubprojectInterpreter(HoldableObject): + pass + +# TODO: This should really be an `ObjectHolder`, but the additional stuff in this +# class prevents this. Thus, this class should be split into a pure +# `ObjectHolder` and a class specifically for storing in `Interpreter`. +class SubprojectHolder(MesonInterpreterObject): + + def __init__(self, subinterpreter: T.Union['Interpreter', NullSubprojectInterpreter], + subdir: str, + warnings: int = 0, + disabled_feature: T.Optional[str] = None, + exception: T.Optional[Exception] = None, + callstack: T.Optional[T.List[str]] = None) -> None: + super().__init__() + self.held_object = subinterpreter + self.warnings = warnings + self.disabled_feature = disabled_feature + self.exception = exception + self.subdir = PurePath(subdir).as_posix() + self.cm_interpreter: T.Optional[CMakeInterpreter] = None + self.callstack = callstack + self.methods.update({'get_variable': self.get_variable_method, + 'found': self.found_method, + }) + + @noPosargs + @noKwargs + def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.found() + + def found(self) -> bool: + return not isinstance(self.held_object, NullSubprojectInterpreter) + + @noKwargs + @noArgsFlattening + @unholder_return + def get_variable_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[TYPE_var, InterpreterObject]: + if len(args) < 1 or len(args) > 2: + raise InterpreterException('Get_variable takes one or two arguments.') + if isinstance(self.held_object, NullSubprojectInterpreter): # == not self.found() + raise InterpreterException(f'Subproject "{self.subdir}" disabled can\'t get_variable on it.') + varname = args[0] + if not isinstance(varname, str): + raise InterpreterException('Get_variable first argument must be a string.') + try: + return self.held_object.variables[varname] + except KeyError: + pass + + if len(args) == 2: + return self.held_object._holderify(args[1]) + + raise InvalidArguments(f'Requested variable "{varname}" not found.') + +class ModuleObjectHolder(ObjectHolder[ModuleObject]): + def method_call(self, method_name: str, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> TYPE_var: + modobj = self.held_object + method = modobj.methods.get(method_name) + if not method: + raise InvalidCode(f'Unknown method {method_name!r} in object.') + if not getattr(method, 'no-args-flattening', False): + args = flatten(args) + if not getattr(method, 'no-second-level-holder-flattening', False): + args, kwargs = resolve_second_level_holders(args, kwargs) + state = ModuleState(self.interpreter) + # Many modules do for example self.interpreter.find_program_impl(), + # so we have to ensure they use the current interpreter and not the one + # that first imported that module, otherwise it will use outdated + # overrides. + if isinstance(modobj, ExtensionModule): + modobj.interpreter = self.interpreter + ret = method(state, args, kwargs) + if isinstance(ret, ModuleReturnValue): + self.interpreter.process_new_values(ret.new_objects) + ret = ret.return_value + return ret + +class MutableModuleObjectHolder(ModuleObjectHolder, MutableInterpreterObject): + def __deepcopy__(self, memo: T.Dict[int, T.Any]) -> 'MutableModuleObjectHolder': + # Deepcopy only held object, not interpreter + modobj = copy.deepcopy(self.held_object, memo) + return MutableModuleObjectHolder(modobj, self.interpreter) + + +_BuildTarget = T.TypeVar('_BuildTarget', bound=T.Union[build.BuildTarget, build.BothLibraries]) + +class BuildTargetHolder(ObjectHolder[_BuildTarget]): + def __init__(self, target: _BuildTarget, interp: 'Interpreter'): + super().__init__(target, interp) + self.methods.update({'extract_objects': self.extract_objects_method, + 'extract_all_objects': self.extract_all_objects_method, + 'name': self.name_method, + 'get_id': self.get_id_method, + 'outdir': self.outdir_method, + 'full_path': self.full_path_method, + 'path': self.path_method, + 'found': self.found_method, + 'private_dir_include': self.private_dir_include_method, + }) + + def __repr__(self) -> str: + r = '<{} {}: {}>' + h = self.held_object + assert isinstance(h, build.BuildTarget) + return r.format(self.__class__.__name__, h.get_id(), h.filename) + + @property + def _target_object(self) -> build.BuildTarget: + if isinstance(self.held_object, build.BothLibraries): + return self.held_object.get_default_object() + assert isinstance(self.held_object, build.BuildTarget) + return self.held_object + + def is_cross(self) -> bool: + return not self._target_object.environment.machines.matches_build_machine(self._target_object.for_machine) + + @noPosargs + @noKwargs + def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + if not (isinstance(self.held_object, build.Executable) and self.held_object.was_returned_by_find_program): + FeatureNew.single_use('BuildTarget.found', '0.59.0', subproject=self.held_object.subproject) + return True + + @noPosargs + @noKwargs + def private_dir_include_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.IncludeDirs: + return build.IncludeDirs('', [], False, [self.interpreter.backend.get_target_private_dir(self._target_object)]) + + @noPosargs + @noKwargs + def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.interpreter.backend.get_target_filename_abs(self._target_object) + + @noPosargs + @noKwargs + @FeatureDeprecated('BuildTarget.path', '0.55.0', 'Use BuildTarget.full_path instead') + def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.interpreter.backend.get_target_filename_abs(self._target_object) + + @noPosargs + @noKwargs + def outdir_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.interpreter.backend.get_target_dir(self._target_object) + + @noKwargs + @typed_pos_args('extract_objects', varargs=(mesonlib.File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) + def extract_objects_method(self, args: T.Tuple[T.List[T.Union[mesonlib.FileOrString, 'build.GeneratedTypes']]], kwargs: TYPE_nkwargs) -> build.ExtractedObjects: + return self._target_object.extract_objects(args[0]) + + @noPosargs + @typed_kwargs( + 'extract_all_objects', + KwargInfo( + 'recursive', bool, default=False, since='0.46.0', + not_set_warning=textwrap.dedent('''\ + extract_all_objects called without setting recursive + keyword argument. Meson currently defaults to + non-recursive to maintain backward compatibility but + the default will be changed in the future. + ''') + ) + ) + def extract_all_objects_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.BuildTargeMethodExtractAllObjects') -> build.ExtractedObjects: + return self._target_object.extract_all_objects(kwargs['recursive']) + + @noPosargs + @noKwargs + @FeatureDeprecated('BuildTarget.get_id', '1.2.0', + 'This was never formally documented and does not seem to have a real world use. ' + + 'See https://github.com/mesonbuild/meson/pull/6061') + def get_id_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self._target_object.get_id() + + @FeatureNew('name', '0.54.0') + @noPosargs + @noKwargs + def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self._target_object.name + +class ExecutableHolder(BuildTargetHolder[build.Executable]): + pass + +class StaticLibraryHolder(BuildTargetHolder[build.StaticLibrary]): + pass + +class SharedLibraryHolder(BuildTargetHolder[build.SharedLibrary]): + pass + +class BothLibrariesHolder(BuildTargetHolder[build.BothLibraries]): + def __init__(self, libs: build.BothLibraries, interp: 'Interpreter'): + # FIXME: This build target always represents the shared library, but + # that should be configurable. + super().__init__(libs, interp) + self.methods.update({'get_shared_lib': self.get_shared_lib_method, + 'get_static_lib': self.get_static_lib_method, + }) + + def __repr__(self) -> str: + r = '<{} {}: {}, {}: {}>' + h1 = self.held_object.shared + h2 = self.held_object.static + return r.format(self.__class__.__name__, h1.get_id(), h1.filename, h2.get_id(), h2.filename) + + @noPosargs + @noKwargs + def get_shared_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.SharedLibrary: + return self.held_object.shared + + @noPosargs + @noKwargs + def get_static_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.StaticLibrary: + return self.held_object.static + +class SharedModuleHolder(BuildTargetHolder[build.SharedModule]): + pass + +class JarHolder(BuildTargetHolder[build.Jar]): + pass + +class CustomTargetIndexHolder(ObjectHolder[build.CustomTargetIndex]): + def __init__(self, target: build.CustomTargetIndex, interp: 'Interpreter'): + super().__init__(target, interp) + self.methods.update({'full_path': self.full_path_method, + }) + + @FeatureNew('custom_target[i].full_path', '0.54.0') + @noPosargs + @noKwargs + def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + assert self.interpreter.backend is not None + return self.interpreter.backend.get_target_filename_abs(self.held_object) + +class CustomTargetHolder(ObjectHolder[build.CustomTarget]): + def __init__(self, target: 'build.CustomTarget', interp: 'Interpreter'): + super().__init__(target, interp) + self.methods.update({'full_path': self.full_path_method, + 'to_list': self.to_list_method, + }) + + self.operators.update({ + MesonOperator.INDEX: self.op_index, + }) + + def __repr__(self) -> str: + r = '<{} {}: {}>' + h = self.held_object + return r.format(self.__class__.__name__, h.get_id(), h.command) + + @noPosargs + @noKwargs + def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.interpreter.backend.get_target_filename_abs(self.held_object) + + @FeatureNew('custom_target.to_list', '0.54.0') + @noPosargs + @noKwargs + def to_list_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[build.CustomTargetIndex]: + result = [] + for i in self.held_object: + result.append(i) + return result + + @noKwargs + @typed_operator(MesonOperator.INDEX, int) + def op_index(self, other: int) -> build.CustomTargetIndex: + try: + return self.held_object[other] + except IndexError: + raise InvalidArguments(f'Index {other} out of bounds of custom target {self.held_object.name} output of size {len(self.held_object)}.') + +class RunTargetHolder(ObjectHolder[build.RunTarget]): + pass + +class AliasTargetHolder(ObjectHolder[build.AliasTarget]): + pass + +class GeneratedListHolder(ObjectHolder[build.GeneratedList]): + pass + +class GeneratorHolder(ObjectHolder[build.Generator]): + def __init__(self, gen: build.Generator, interpreter: 'Interpreter'): + super().__init__(gen, interpreter) + self.methods.update({'process': self.process_method}) + + @typed_pos_args('generator.process', min_varargs=1, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) + @typed_kwargs( + 'generator.process', + KwargInfo('preserve_path_from', (str, NoneType), since='0.45.0'), + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), + ) + def process_method(self, + args: T.Tuple[T.List[T.Union[str, mesonlib.File, 'build.GeneratedTypes']]], + kwargs: 'kwargs.GeneratorProcess') -> build.GeneratedList: + preserve_path_from = kwargs['preserve_path_from'] + if preserve_path_from is not None: + preserve_path_from = os.path.normpath(preserve_path_from) + if not os.path.isabs(preserve_path_from): + # This is a bit of a hack. Fix properly before merging. + raise InvalidArguments('Preserve_path_from must be an absolute path for now. Sorry.') + + if any(isinstance(a, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for a in args[0]): + FeatureNew.single_use( + 'Calling generator.process with CustomTarget or Index of CustomTarget.', + '0.57.0', self.interpreter.subproject) + + gl = self.held_object.process_files(args[0], self.interpreter, + preserve_path_from, extra_args=kwargs['extra_args']) + + return gl + + +class StructuredSourcesHolder(ObjectHolder[build.StructuredSources]): + + def __init__(self, sources: build.StructuredSources, interp: 'Interpreter'): + super().__init__(sources, interp) diff --git a/devtools/meson/mesonbuild/interpreter/kwargs.py b/devtools/meson/mesonbuild/interpreter/kwargs.py new file mode 100644 index 0000000..cf476ce --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/kwargs.py @@ -0,0 +1,310 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 The Meson Developers +# Copyright © 2021 Intel Corporation +from __future__ import annotations + +"""Keyword Argument type annotations.""" + +import typing as T + +from typing_extensions import TypedDict, Literal, Protocol + +from .. import build +from .. import coredata +from ..compilers import Compiler +from ..mesonlib import MachineChoice, File, FileMode, FileOrString, OptionKey +from ..modules.cmake import CMakeSubprojectOptions +from ..programs import ExternalProgram + + +class FuncAddProjectArgs(TypedDict): + + """Keyword Arguments for the add_*_arguments family of arguments. + + including `add_global_arguments`, `add_project_arguments`, and their + link variants + + Because of the use of a convertor function, we get the native keyword as + a MachineChoice instance already. + """ + + native: MachineChoice + language: T.List[str] + + +class BaseTest(TypedDict): + + """Shared base for the Rust module.""" + + args: T.List[T.Union[str, File, build.Target]] + should_fail: bool + timeout: int + workdir: T.Optional[str] + depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]] + priority: int + env: build.EnvironmentVariables + suite: T.List[str] + + +class FuncBenchmark(BaseTest): + + """Keyword Arguments shared between `test` and `benchmark`.""" + + protocol: Literal['exitcode', 'tap', 'gtest', 'rust'] + + +class FuncTest(FuncBenchmark): + + """Keyword Arguments for `test` + + `test` only adds the `is_parallel` argument over benchmark, so inheritance + is helpful here. + """ + + is_parallel: bool + + +class ExtractRequired(TypedDict): + + """Keyword Arguments consumed by the `extract_required_kwargs` function. + + Any function that uses the `required` keyword argument which accepts either + a boolean or a feature option should inherit it's arguments from this class. + """ + + required: T.Union[bool, coredata.UserFeatureOption] + + +class ExtractSearchDirs(TypedDict): + + """Keyword arguments consumed by the `extract_search_dirs` function. + + See the not in `ExtractRequired` + """ + + dirs: T.List[str] + + +class FuncGenerator(TypedDict): + + """Keyword rguments for the generator function.""" + + arguments: T.List[str] + output: T.List[str] + depfile: T.Optional[str] + capture: bool + depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] + + +class GeneratorProcess(TypedDict): + + """Keyword Arguments for generator.process.""" + + preserve_path_from: T.Optional[str] + extra_args: T.List[str] + +class DependencyMethodPartialDependency(TypedDict): + + """ Keyword Arguments for the dep.partial_dependency methods """ + + compile_args: bool + link_args: bool + links: bool + includes: bool + sources: bool + +class BuildTargeMethodExtractAllObjects(TypedDict): + recursive: bool + +class FuncInstallSubdir(TypedDict): + + install_dir: str + strip_directory: bool + exclude_files: T.List[str] + exclude_directories: T.List[str] + install_mode: FileMode + + +class FuncInstallData(TypedDict): + + install_dir: str + sources: T.List[FileOrString] + rename: T.List[str] + install_mode: FileMode + + +class FuncInstallHeaders(TypedDict): + + install_dir: T.Optional[str] + install_mode: FileMode + subdir: T.Optional[str] + + +class FuncInstallMan(TypedDict): + + install_dir: T.Optional[str] + install_mode: FileMode + locale: T.Optional[str] + + +class FuncImportModule(ExtractRequired): + + disabler: bool + + +class FuncIncludeDirectories(TypedDict): + + is_system: bool + +class FuncAddLanguages(ExtractRequired): + + native: T.Optional[bool] + +class RunTarget(TypedDict): + + command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, ExternalProgram, File]] + depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] + env: build.EnvironmentVariables + + +class CustomTarget(TypedDict): + + build_always: bool + build_always_stale: T.Optional[bool] + build_by_default: T.Optional[bool] + capture: bool + command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, + build.CustomTargetIndex, ExternalProgram, File]] + console: bool + depend_files: T.List[FileOrString] + depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] + depfile: T.Optional[str] + env: build.EnvironmentVariables + feed: bool + input: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, + build.ExtractedObjects, build.GeneratedList, ExternalProgram, File]] + install: bool + install_dir: T.List[T.Union[str, T.Literal[False]]] + install_mode: FileMode + install_tag: T.List[T.Optional[str]] + output: T.List[str] + +class AddTestSetup(TypedDict): + + exe_wrapper: T.List[T.Union[str, ExternalProgram]] + gdb: bool + timeout_multiplier: int + is_default: bool + exclude_suites: T.List[str] + env: build.EnvironmentVariables + + +class Project(TypedDict): + + version: T.Optional[FileOrString] + meson_version: T.Optional[str] + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] + license: T.List[str] + subproject_dir: str + + +class _FoundProto(Protocol): + + """Protocol for subdir arguments. + + This allows us to define any object that has a found(self) -> bool method + """ + + def found(self) -> bool: ... + + +class Subdir(TypedDict): + + if_found: T.List[_FoundProto] + + +class Summary(TypedDict): + + section: str + bool_yn: bool + list_sep: T.Optional[str] + + +class FindProgram(ExtractRequired, ExtractSearchDirs): + + native: MachineChoice + version: T.List[str] + + +class RunCommand(TypedDict): + + check: bool + capture: T.Optional[bool] + env: build.EnvironmentVariables + + +class FeatureOptionRequire(TypedDict): + + error_message: T.Optional[str] + + +class DependencyPkgConfigVar(TypedDict): + + default: T.Optional[str] + define_variable: T.List[str] + + +class DependencyGetVariable(TypedDict): + + cmake: T.Optional[str] + pkgconfig: T.Optional[str] + configtool: T.Optional[str] + internal: T.Optional[str] + default_value: T.Optional[str] + pkgconfig_define: T.List[str] + + +class ConfigurationDataSet(TypedDict): + + description: T.Optional[str] + +class VcsTag(TypedDict): + + command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, + build.CustomTargetIndex, ExternalProgram, File]] + fallback: T.Optional[str] + input: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, + build.ExtractedObjects, build.GeneratedList, ExternalProgram, File]] + output: T.List[str] + replace_string: str + + +class ConfigureFile(TypedDict): + + output: str + capture: bool + format: T.Literal['meson', 'cmake', 'cmake@'] + output_format: T.Literal['c', 'nasm'] + depfile: T.Optional[str] + install: T.Optional[bool] + install_dir: T.Union[str, T.Literal[False]] + install_mode: FileMode + install_tag: T.Optional[str] + encoding: str + command: T.Optional[T.List[T.Union[build.Executable, ExternalProgram, Compiler, File, str]]] + input: T.List[FileOrString] + configuration: T.Optional[T.Union[T.Dict[str, T.Union[str, int, bool]], build.ConfigurationData]] + + +class Subproject(ExtractRequired): + + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] + version: T.List[str] + + +class DoSubproject(ExtractRequired): + + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] + version: T.List[str] + cmake_options: T.List[str] + options: T.Optional[CMakeSubprojectOptions] diff --git a/devtools/meson/mesonbuild/interpreter/mesonmain.py b/devtools/meson/mesonbuild/interpreter/mesonmain.py new file mode 100644 index 0000000..73df5ed --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/mesonmain.py @@ -0,0 +1,477 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2012-2021 The Meson development team +# Copyright © 2021 Intel Corporation +from __future__ import annotations + +import os +import typing as T + +from .. import mesonlib +from .. import dependencies +from .. import build +from .. import mlog, coredata + +from ..mesonlib import MachineChoice, OptionKey +from ..programs import OverrideProgram, ExternalProgram +from ..interpreter.type_checking import ENV_KW, ENV_METHOD_KW, ENV_SEPARATOR_KW, env_convertor_with_method +from ..interpreterbase import (MesonInterpreterObject, FeatureNew, FeatureDeprecated, + typed_pos_args, noArgsFlattening, noPosargs, noKwargs, + typed_kwargs, KwargInfo, InterpreterException) +from .primitives import MesonVersionString +from .type_checking import NATIVE_KW, NoneType + +if T.TYPE_CHECKING: + from typing_extensions import Literal + from ..backend.backends import ExecutableSerialisation + from ..compilers import Compiler + from ..interpreterbase import TYPE_kwargs, TYPE_var + from .interpreter import Interpreter + + from typing_extensions import TypedDict + + class FuncOverrideDependency(TypedDict): + + native: mesonlib.MachineChoice + static: T.Optional[bool] + + class AddInstallScriptKW(TypedDict): + + skip_if_destdir: bool + install_tag: str + dry_run: bool + + class NativeKW(TypedDict): + + native: mesonlib.MachineChoice + + class AddDevenvKW(TypedDict): + method: Literal['set', 'prepend', 'append'] + separator: str + + +class MesonMain(MesonInterpreterObject): + def __init__(self, build: 'build.Build', interpreter: 'Interpreter'): + super().__init__(subproject=interpreter.subproject) + self.build = build + self.interpreter = interpreter + self.methods.update({'add_devenv': self.add_devenv_method, + 'add_dist_script': self.add_dist_script_method, + 'add_install_script': self.add_install_script_method, + 'add_postconf_script': self.add_postconf_script_method, + 'backend': self.backend_method, + 'build_options': self.build_options_method, + 'build_root': self.build_root_method, + 'can_run_host_binaries': self.can_run_host_binaries_method, + 'current_source_dir': self.current_source_dir_method, + 'current_build_dir': self.current_build_dir_method, + 'get_compiler': self.get_compiler_method, + 'get_cross_property': self.get_cross_property_method, + 'get_external_property': self.get_external_property_method, + 'global_build_root': self.global_build_root_method, + 'global_source_root': self.global_source_root_method, + 'has_exe_wrapper': self.has_exe_wrapper_method, + 'has_external_property': self.has_external_property_method, + 'install_dependency_manifest': self.install_dependency_manifest_method, + 'is_cross_build': self.is_cross_build_method, + 'is_subproject': self.is_subproject_method, + 'is_unity': self.is_unity_method, + 'override_dependency': self.override_dependency_method, + 'override_find_program': self.override_find_program_method, + 'project_build_root': self.project_build_root_method, + 'project_license': self.project_license_method, + 'project_license_files': self.project_license_files_method, + 'project_name': self.project_name_method, + 'project_source_root': self.project_source_root_method, + 'project_version': self.project_version_method, + 'source_root': self.source_root_method, + 'version': self.version_method, + }) + + def _find_source_script( + self, name: str, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram], + args: T.List[str]) -> 'ExecutableSerialisation': + largs: T.List[T.Union[str, build.Executable, ExternalProgram]] = [] + + if isinstance(prog, (build.Executable, ExternalProgram)): + FeatureNew.single_use(f'Passing executable/found program object to script parameter of {name}', + '0.55.0', self.subproject, location=self.current_node) + largs.append(prog) + else: + if isinstance(prog, mesonlib.File): + FeatureNew.single_use(f'Passing file object to script parameter of {name}', + '0.57.0', self.subproject, location=self.current_node) + found = self.interpreter.find_program_impl([prog]) + largs.append(found) + + largs.extend(args) + es = self.interpreter.backend.get_executable_serialisation(largs, verbose=True) + es.subproject = self.interpreter.subproject + return es + + def _process_script_args( + self, name: str, args: T.Sequence[T.Union[ + str, mesonlib.File, build.BuildTarget, build.CustomTarget, + build.CustomTargetIndex, + ExternalProgram, + ]]) -> T.List[str]: + script_args = [] # T.List[str] + new = False + for a in args: + if isinstance(a, str): + script_args.append(a) + elif isinstance(a, mesonlib.File): + new = True + script_args.append(a.rel_to_builddir(self.interpreter.environment.source_dir)) + elif isinstance(a, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)): + new = True + script_args.extend([os.path.join(a.get_subdir(), o) for o in a.get_outputs()]) + + # This feels really hacky, but I'm not sure how else to fix + # this without completely rewriting install script handling. + # This is complicated by the fact that the install target + # depends on all. + if isinstance(a, build.CustomTargetIndex): + a.target.build_by_default = True + else: + a.build_by_default = True + else: + script_args.extend(a.command) + new = True + + if new: + FeatureNew.single_use( + f'Calling "{name}" with File, CustomTarget, Index of CustomTarget, ' + 'Executable, or ExternalProgram', + '0.55.0', self.interpreter.subproject, location=self.current_node) + return script_args + + @typed_pos_args( + 'meson.add_install_script', + (str, mesonlib.File, build.Executable, ExternalProgram), + varargs=(str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, ExternalProgram) + ) + @typed_kwargs( + 'meson.add_install_script', + KwargInfo('skip_if_destdir', bool, default=False, since='0.57.0'), + KwargInfo('install_tag', (str, NoneType), since='0.60.0'), + KwargInfo('dry_run', bool, default=False, since='1.1.0'), + ) + def add_install_script_method( + self, + args: T.Tuple[T.Union[str, mesonlib.File, build.Executable, ExternalProgram], + T.List[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, ExternalProgram]]], + kwargs: 'AddInstallScriptKW') -> None: + script_args = self._process_script_args('add_install_script', args[1]) + script = self._find_source_script('add_install_script', args[0], script_args) + script.skip_if_destdir = kwargs['skip_if_destdir'] + script.tag = kwargs['install_tag'] + script.dry_run = kwargs['dry_run'] + self.build.install_scripts.append(script) + + @typed_pos_args( + 'meson.add_postconf_script', + (str, mesonlib.File, ExternalProgram), + varargs=(str, mesonlib.File, ExternalProgram) + ) + @noKwargs + def add_postconf_script_method( + self, + args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram], + T.List[T.Union[str, mesonlib.File, ExternalProgram]]], + kwargs: 'TYPE_kwargs') -> None: + script_args = self._process_script_args('add_postconf_script', args[1]) + script = self._find_source_script('add_postconf_script', args[0], script_args) + self.build.postconf_scripts.append(script) + + @typed_pos_args( + 'meson.add_dist_script', + (str, mesonlib.File, ExternalProgram), + varargs=(str, mesonlib.File, ExternalProgram) + ) + @noKwargs + def add_dist_script_method( + self, + args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram], + T.List[T.Union[str, mesonlib.File, ExternalProgram]]], + kwargs: 'TYPE_kwargs') -> None: + if args[1]: + FeatureNew.single_use('Calling "add_dist_script" with multiple arguments', + '0.49.0', self.interpreter.subproject, location=self.current_node) + if self.interpreter.subproject != '': + FeatureNew.single_use('Calling "add_dist_script" in a subproject', + '0.58.0', self.interpreter.subproject, location=self.current_node) + script_args = self._process_script_args('add_dist_script', args[1]) + script = self._find_source_script('add_dist_script', args[0], script_args) + self.build.dist_scripts.append(script) + + @noPosargs + @noKwargs + def current_source_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + src = self.interpreter.environment.source_dir + sub = self.interpreter.subdir + if sub == '': + return src + return os.path.join(src, sub) + + @noPosargs + @noKwargs + def current_build_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + src = self.interpreter.environment.build_dir + sub = self.interpreter.subdir + if sub == '': + return src + return os.path.join(src, sub) + + @noPosargs + @noKwargs + def backend_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.interpreter.backend.name + + @noPosargs + @noKwargs + @FeatureDeprecated('meson.source_root', '0.56.0', 'use meson.project_source_root() or meson.global_source_root() instead.') + def source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.interpreter.environment.source_dir + + @noPosargs + @noKwargs + @FeatureDeprecated('meson.build_root', '0.56.0', 'use meson.project_build_root() or meson.global_build_root() instead.') + def build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.interpreter.environment.build_dir + + @noPosargs + @noKwargs + @FeatureNew('meson.project_source_root', '0.56.0') + def project_source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + src = self.interpreter.environment.source_dir + sub = self.interpreter.root_subdir + if sub == '': + return src + return os.path.join(src, sub) + + @noPosargs + @noKwargs + @FeatureNew('meson.project_build_root', '0.56.0') + def project_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + src = self.interpreter.environment.build_dir + sub = self.interpreter.root_subdir + if sub == '': + return src + return os.path.join(src, sub) + + @noPosargs + @noKwargs + @FeatureNew('meson.global_source_root', '0.58.0') + def global_source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.interpreter.environment.source_dir + + @noPosargs + @noKwargs + @FeatureNew('meson.global_build_root', '0.58.0') + def global_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.interpreter.environment.build_dir + + @noPosargs + @noKwargs + @FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.') + def has_exe_wrapper_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + return self._can_run_host_binaries_impl() + + @noPosargs + @noKwargs + @FeatureNew('meson.can_run_host_binaries', '0.55.0') + def can_run_host_binaries_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + return self._can_run_host_binaries_impl() + + def _can_run_host_binaries_impl(self) -> bool: + return not ( + self.build.environment.is_cross_build() and + self.build.environment.need_exe_wrapper() and + self.build.environment.exe_wrapper is None + ) + + @noPosargs + @noKwargs + def is_cross_build_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + return self.build.environment.is_cross_build() + + @typed_pos_args('meson.get_compiler', str) + @typed_kwargs('meson.get_compiler', NATIVE_KW) + def get_compiler_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> 'Compiler': + cname = args[0] + for_machine = kwargs['native'] + clist = self.interpreter.coredata.compilers[for_machine] + try: + return clist[cname] + except KeyError: + raise InterpreterException(f'Tried to access compiler for language "{cname}", not specified for {for_machine.get_lower_case_name()} machine.') + + @noPosargs + @noKwargs + def is_unity_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + optval = self.interpreter.environment.coredata.get_option(OptionKey('unity')) + return optval == 'on' or (optval == 'subprojects' and self.interpreter.is_subproject()) + + @noPosargs + @noKwargs + def is_subproject_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + return self.interpreter.is_subproject() + + @typed_pos_args('meson.install_dependency_manifest', str) + @noKwargs + def install_dependency_manifest_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> None: + self.build.dep_manifest_name = args[0] + + @FeatureNew('meson.override_find_program', '0.46.0') + @typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable)) + @noKwargs + def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable]], kwargs: 'TYPE_kwargs') -> None: + name, exe = args + if isinstance(exe, mesonlib.File): + abspath = exe.absolute_path(self.interpreter.environment.source_dir, + self.interpreter.environment.build_dir) + if not os.path.exists(abspath): + raise InterpreterException(f'Tried to override {name} with a file that does not exist.') + exe = OverrideProgram(name, [abspath]) + self.interpreter.add_find_program_override(name, exe) + + @typed_kwargs( + 'meson.override_dependency', + NATIVE_KW, + KwargInfo('static', (bool, NoneType), since='0.60.0'), + ) + @typed_pos_args('meson.override_dependency', str, dependencies.Dependency) + @FeatureNew('meson.override_dependency', '0.54.0') + def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency], kwargs: 'FuncOverrideDependency') -> None: + name, dep = args + if not name: + raise InterpreterException('First argument must be a string and cannot be empty') + + optkey = OptionKey('default_library', subproject=self.interpreter.subproject) + default_library = self.interpreter.coredata.get_option(optkey) + assert isinstance(default_library, str), 'for mypy' + static = kwargs['static'] + if static is None: + # We don't know if dep represents a static or shared library, could + # be a mix of both. We assume it is following default_library + # value. + self._override_dependency_impl(name, dep, kwargs, static=None) + if default_library == 'static': + self._override_dependency_impl(name, dep, kwargs, static=True) + elif default_library == 'shared': + self._override_dependency_impl(name, dep, kwargs, static=False) + else: + self._override_dependency_impl(name, dep, kwargs, static=True) + self._override_dependency_impl(name, dep, kwargs, static=False) + else: + # dependency('foo') without specifying static kwarg should find this + # override regardless of the static value here. But do not raise error + # if it has already been overridden, which would happen when overriding + # static and shared separately: + # meson.override_dependency('foo', shared_dep, static: false) + # meson.override_dependency('foo', static_dep, static: true) + # In that case dependency('foo') would return the first override. + self._override_dependency_impl(name, dep, kwargs, static=None, permissive=True) + self._override_dependency_impl(name, dep, kwargs, static=static) + + def _override_dependency_impl(self, name: str, dep: dependencies.Dependency, kwargs: 'FuncOverrideDependency', + static: T.Optional[bool], permissive: bool = False) -> None: + # We need the cast here as get_dep_identifier works on such a dict, + # which FuncOverrideDependency is, but mypy can't figure that out + nkwargs = T.cast('T.Dict[str, T.Any]', kwargs.copy()) + if static is None: + del nkwargs['static'] + else: + nkwargs['static'] = static + identifier = dependencies.get_dep_identifier(name, nkwargs) + for_machine = kwargs['native'] + override = self.build.dependency_overrides[for_machine].get(identifier) + if override: + if permissive: + return + m = 'Tried to override dependency {!r} which has already been resolved or overridden at {}' + location = mlog.get_error_location_string(override.node.filename, override.node.lineno) + raise InterpreterException(m.format(name, location)) + self.build.dependency_overrides[for_machine][identifier] = \ + build.DependencyOverride(dep, self.interpreter.current_node) + + @noPosargs + @noKwargs + def project_version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.build.dep_manifest[self.interpreter.active_projectname].version + + @FeatureNew('meson.project_license()', '0.45.0') + @noPosargs + @noKwargs + def project_license_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]: + return self.build.dep_manifest[self.interpreter.active_projectname].license + + @FeatureNew('meson.project_license_files()', '1.1.0') + @noPosargs + @noKwargs + def project_license_files_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[mesonlib.File]: + return [l[1] for l in self.build.dep_manifest[self.interpreter.active_projectname].license_files] + + @noPosargs + @noKwargs + def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> MesonVersionString: + return MesonVersionString(self.interpreter.coredata.version) + + @noPosargs + @noKwargs + def project_name_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.interpreter.active_projectname + + def __get_external_property_impl(self, propname: str, fallback: T.Optional[object], machine: MachineChoice) -> object: + """Shared implementation for get_cross_property and get_external_property.""" + try: + return self.interpreter.environment.properties[machine][propname] + except KeyError: + if fallback is not None: + return fallback + raise InterpreterException(f'Unknown property for {machine.get_lower_case_name()} machine: {propname}') + + @noArgsFlattening + @FeatureDeprecated('meson.get_cross_property', '0.58.0', 'Use meson.get_external_property() instead') + @typed_pos_args('meson.get_cross_property', str, optargs=[object]) + @noKwargs + def get_cross_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: 'TYPE_kwargs') -> object: + propname, fallback = args + return self.__get_external_property_impl(propname, fallback, MachineChoice.HOST) + + @noArgsFlattening + @FeatureNew('meson.get_external_property', '0.54.0') + @typed_pos_args('meson.get_external_property', str, optargs=[object]) + @typed_kwargs('meson.get_external_property', NATIVE_KW) + def get_external_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: 'NativeKW') -> object: + propname, fallback = args + return self.__get_external_property_impl(propname, fallback, kwargs['native']) + + @FeatureNew('meson.has_external_property', '0.58.0') + @typed_pos_args('meson.has_external_property', str) + @typed_kwargs('meson.has_external_property', NATIVE_KW) + def has_external_property_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> bool: + prop_name = args[0] + return prop_name in self.interpreter.environment.properties[kwargs['native']] + + @FeatureNew('add_devenv', '0.58.0') + @typed_kwargs('environment', ENV_METHOD_KW, ENV_SEPARATOR_KW.evolve(since='0.62.0')) + @typed_pos_args('add_devenv', (str, list, dict, build.EnvironmentVariables)) + def add_devenv_method(self, args: T.Tuple[T.Union[str, list, dict, build.EnvironmentVariables]], + kwargs: 'AddDevenvKW') -> None: + env = args[0] + msg = ENV_KW.validator(env) + if msg: + raise build.InvalidArguments(f'"add_devenv": {msg}') + converted = env_convertor_with_method(env, kwargs['method'], kwargs['separator']) + assert isinstance(converted, build.EnvironmentVariables) + self.build.devenv.append(converted) + + @noPosargs + @noKwargs + @FeatureNew('meson.build_options', '1.1.0') + def build_options_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + options = self.interpreter.user_defined_options + if options is None: + return '' + return coredata.format_cmd_line_options(options) diff --git a/devtools/meson/mesonbuild/interpreter/primitives/__init__.py b/devtools/meson/mesonbuild/interpreter/primitives/__init__.py new file mode 100644 index 0000000..aebef41 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/__init__.py @@ -0,0 +1,29 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 + +__all__ = [ + 'ArrayHolder', + 'BooleanHolder', + 'DictHolder', + 'IntegerHolder', + 'RangeHolder', + 'StringHolder', + 'MesonVersionString', + 'MesonVersionStringHolder', + 'DependencyVariableString', + 'DependencyVariableStringHolder', + 'OptionString', + 'OptionStringHolder', +] + +from .array import ArrayHolder +from .boolean import BooleanHolder +from .dict import DictHolder +from .integer import IntegerHolder +from .range import RangeHolder +from .string import ( + StringHolder, + MesonVersionString, MesonVersionStringHolder, + DependencyVariableString, DependencyVariableStringHolder, + OptionString, OptionStringHolder, +) diff --git a/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e069275bf8d1baf436a3223da0ce3bac49a2757 GIT binary patch literal 741 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/boolean.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/boolean.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..45261164b589af59f8a9b24b77d420bac1595fa2 GIT binary patch literal 2645 zcma)8Pj3@P6rb5$uh;h4aRQ`JB)U{>!Tn>E9xD_T2m%CkXi1T}I9hEy<7AWlV`j&J zSmx5CqL+Sy9N^gR&|AO7TzleHsW(o2Z`O8Vidxp%x6f~8-oE#HZ+^4a>-8#u>-WF@ z=pU2``4j(4uM#NVkS57fP#9q}CJFT^CCp%EY$T>{CYEm{CBKx|zMYi)a^m<7j1y+X z6~D@>J2mkTW|v|&srz-k(uS1{zmY8X3zXa2r#MUt3smwe0synIVVjwukmZ6;WAMf7`_Cld*THDoLdKlOA zvb6#TNl-ZPDI>nYDB{DcBl9`wQ&wX3q3fHN=MiNURy_pFc!}Gr##~lsjU$sSu;!t4 zKo6*2h7pG?@(QnP8EolSgPnp|Wj*UOJ2RP8eNHUm*8rzwRllBPF%Q!T8rCNK9n~+L z$mNo9UCtVN`4_b#tRdq z1$T+jBjY9X1L*b(QxZx3}G1)aHSpC1xi|_2yd}p5@PJOoOs+13511o0= zk18izZf7i4_He*L$yL2*gP^dh=Byj0mPP1|y(o->Y(fROKn7FR^|iHo%IvJIEBoem zKU}-_Ks3-^1xrvETBguAHZh__5YQ@>An3(mo(BPdtw%M$=V26;dqiK<$>L%rM;t5yzqe$rKG$ zD)!*4p?n9|;ep^+^g>kMfJPt-e}SOrj~vsbF8zo)badgr!D+cjM7XztKvjbv$=EPP z-3@}r!!RyJ1X6*xgaW>th(M;+eJ$`L5}%;J091X#Bt0I-L2w)+>=oR*1##n{i*1nO zrgZ3XqhT8KtYuJvBdsNjqd$bR8sZRGW3_PNINA(zE|5Vq{N7J z)inj&xP9}+-8-FIn(zc7Bx)!yfP#VW&Bx&u8gd^Ta|I+Tx`T0nYj{=1unm_sjeh_E CYI_C% literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/dict.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/dict.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2d2dd893546558e2c7bc14a9f498928ce21cf9d GIT binary patch literal 3530 zcmb7H&2QX96rZuZUhntjvrQ;86xwQ`T3QJSQA*X)hBmZpi?Wr#-Nlf;QXma#W9 ztDHzgxp3t|klG6p{{uJvi#c%N)Eg2vPP{kX4<`aryzXU%llp?M9nyoXP8NLzZ>|9{lW{|h@fn{4k!7c!+u@TEc7(I+)Mb^XUCa^yC-6Y|m7j6tc z>qfDoR#@#X9xggNu8{SmaL4sM1|ReS9wsr0xfFsBUBRKnp<2AHj#)!Zh7V#*5bNKd z1fVBPC#-8uF~x(@cJ^9eo)mcujhF#qPE#?G?~IB!osB?hr)z=juP@wPX#Qh%o1 z#L?q85tkN*Sg!Od7cChVR=HN9MJ=C9rR|B1YrYF``At@@n0s8}MT?0;Oz%fRg@_>^Y zaVkkwePxa~wE-uea=hH&l)5@)0?wQCDDoHqRIFA*xAU8B>}>O0X+RT8eS;@!6m-A` zdkx+xbQ6qP*nsSj?=dWB3!Q6|`{2(i1Yk&?Kx4$*U;ml>wS4<(hw+`x282c|);gR1 zl}^mI9i)MuM3EnN0*sHeUF~^3>tt~5bcGjqiMPY!4g-5NySvi5=DWcvbFW_jY5s(l z^v{ni+jJZ+^b*HuUh|_h*N?9Qk*+^Ur|qFm;uLJ!pyG7e%|R#Tv3UiXGss2aRcKD! zQy<`T@}6&P!mJ@YTU=cVDEjVYOndyvSaH3VJe1DcF?0bV8QU#fF0-c-oMjNQAfJx&A0M#=?Y?r19|nqh)EJ^`*J^*`u5Hmu0c_pzRE3 zZK)-72xDm?69$E0ZjEJbsdantb7@6ga0p~> z<+Cu0mX6WzgjT6Z4fvIHQ=8N$DgI6yChbrCgX;-|9d?_B?udh6Fx|pHGJs$dAlF*r zBGAgchUY6+8~K|oGcWG??yeKM0e=@3#~6=<_D^Mw&aRO)e_L)x$}8 zU7tI#*XQqLj-JmPeQa6(T)U}CAXK}@?PeRlKbB@!jtGaTQ-M+iB7xkpMW1QU$v(mZ z8Ag`|o}l7K=70>K!li~f22?>wf~n_fM%3x!qT+%h0w54d08DSG0K>yIsrx(}#_l)~ zjICoJG#_Tpt7Xo^xjxtr64xLM`sEBHD*{V~G*%%GqMoXlgHy4SsHL4 z=2ni>zmb6dgrgZpBH`@i_vzPg zlLGh6rDl17w&@%9`0he~e!+_u;10Rqg$v0hUqB5|Jh9tsXbK%sfz`uI^{*y;6Bc~} zud2z!s6vJ+Q;YUzGEj}PYeSQ{2#yn}TcM@!!G5GU?g;l4bg8_U2c6*d@&nwtQ+-kt z5P^o?`k%UJX}I2i1CD#*JHTth8)L2~T9MX|rqog9p2Z@A8PIWL(Q$%^^&l@fvg|lt z_FO-m5ty~b6>Kn33QSqzeQYdj;I9Tzxmg8(DBuuXO`yX{GrhwI#6jTASk)iVL<+@} zl|iLgj>m;3f&G z2(*SY;r{_%_-R|#G8ds$H|7FOC34sxTB(dmF{KGAk*bK^t-MH9RM_6SyLju~QtOT? qc>>eNAn~BDq=29}V~tV@)qvYp3iWkNMKSJN)-3IE&D6@Yto;qm>K};! literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/integer.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/integer.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e03004dbcd0abf7670d50c18deb532c0f8305090 GIT binary patch literal 3984 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/string.cpython-37.pyc b/devtools/meson/mesonbuild/interpreter/primitives/__pycache__/string.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bd139f59adb11f023dd72ae2c6b3651c33be8d2 GIT binary patch literal 10008 zcmbVSO>i4WcAh`{5Cp-0iu$7<>KAJXqJP)+Y8`1UO5$3kv?k@XVQQy9^pFGzVBnsC zWKF2u#8hJMVGlWOtu`f9s#3`zhg@<>F3BZT$sxB?O>Rl$;2cs(r78!X^1atHAO@mD zI$(8A|4sMn*YADry&nE(Xeg)Q_t*dRcWZxoO4I(0D)BFc!WC^q^ZpkFp$WaAHT8XG| zH%BTX&C$xJt~sgAG5K@6k#3APCn^*Cb_Q=xRwkQMl__1jp^2;*c&v#5XTUjhSlclx z(`d_yL9`7zhfqI^dR`2nKIBZJegyS`7)E`V`;VeNB1Tak<^E%+kBM>A$GQJF>JwrT z^-1oZ5yp~Mn)-&gQPRV~YOCe?Rln}Gyv1)!)i`|Lksey?n%itwrBfOR^S4(wotl5s zZ3st(LmxVx+q&I$WYu?Nn7i&&{f=}Nod;pTf7o_}?Z$m0E%&Ni_pUdpzVEc^t@SY5 zazA)bMO!$~a__hv7o*qOu4i+7WTADx+NcY>+i5y2-y>QVTD~LO(m`G_!tC;=cjoQ; zRT&O)X^SVV(Z=Fmh6_0Ae=;=9(JH#oaJ;%O=t!TKUukQ)NQw00JPunInI}3QhgGqh zl#>=YC$nRSL1MosJTb+v7lf6YZN1f z#aVG~$H1P>IvG%9iu2u(CGoxPY-2pzD^6xz7Z*U+#qOGAaVeT_oX5;1#wglf6|Y5O zCV0))#T&fl>&~Pzxo+@`Z+6#xOMJh(?i9usc!zKE4&M>)Ml&7i_NX;}ATCEe(|tWZ z6z@enhx>YdM_h?|j-V$kuJ)bFkHq^?|54`{&Vl}};k@U?b!x912mfw}o7l^Yb7Hf| zZ_}8CCx-a3_#k@sB=^oblQ^rlquyKML!RLjW>^%rqZv*|GYs(zcf?Pk8O~tTN8M34 zDa@op_Gq0Yu^f#$_myU8mGe;IyJ3FGmr$ulD^1Ur!O*!LEjbrji*Cy)nW5>fZia*P zT?Go$(4&rQ)kx>*N6&G7LSM#oP4l%K?Ww-4ZyV1HUHe+wG@hEsEu<7u8YzR6MH)cL zAq^tsk%o{8NW(}YNTWz&LVq&+3^0rG_*2uL*qrpISOcMrkF#qAS`I}mR<~t3Y5@pG zV-80x>2AxBs3p^FIU2QOyDi6}mI2jL&qS0QXG&&3(+R9!#PcMcvv{7u^E94k>K2U^ z8aSR?EDeX*n%nZL^_CarJijV^??K()2(wO0s8V{(mCdRjTAOaY6=tNE2?l1rU7(6o~8w1B-{&6V}Fhtk4P z)o@DuqbCp!=ZCW+%Llr(ZS4@ztS=IDZa58qGGjQZ`WMJ7&uOgvx%TbdYwxZI=l;q% zu-%ijm5s)$E1uZ0sf>2tbsOGFlK@}ktDSm7tn`S|N?X>Ob-#Y!@mAD6%I$|?_Hv`z zTou*#-UL1WgQNxLmU_gsY-6W&-?qz_8*Z)I@ZLi~y|LfEw#bChzT`4g>%UEozpz{*3oT&rTdHKL|>Ia_lhw+@H zvrvf+WIfEr!VzYgj=$jwFHCpZqUt;0aIAi|>Ip}8wJ>fPj+HTP7*aYJR|iQo<4PgY z(72vw4UKD~yZRb8!xyClb`n4bU1-K)2j!rbERWjiWoZhSORnBrQPrnOL|PI#2{R>_pC zj}vsdlgI!$1GZgjR6WnOp|sq~idsVN2_%oCOVbN_TDM;Emp9YKm^r4$f74c4&+=a| zxhKM4u_;WPfB=Hb_X#cuNCgS2vB=zG0Ex+CFzF&nm=|@3L-nEEsy3aQc+n%&)%4(S zV%^?R0ZB_amf0Y`Twd<98_s8Fy(dTTa%imrVPT>zc6`&yja3AbO{O0`iB2Y%7`hF7 zC)+Ia!`d_CTcp9*0PU(|Ff@eL8V)Hwh1=+mcPLA4NnSwP2S{osW^gRAlbG&E_<{m$ zW>?=5&O?_#+EtRk=ZKTj7_%>J7cq!vj%k}o(6&oPOdYd2R{j4!ZHEs+TN#7y_RyB( zTTDbu89W79Ru}{|$RKE;!wwF`(y&~o;d1Y9Y2HMNbTDv|ut!L#S_8VVo>k}33Oh?5>cLVe?F zZ3prxzvr96*w%l85c;+Coc*(1i05rq-p~X@_RRX~`kH4zXXt1D%4rn?W$x2G`+LdAmM=YK{P3V7Qk> zMv#-&NA%!QLckI>W7kWeiK7{U%$4&i;+4{sQZ~%hJ@|xvwN-QEBIZ<3oMJC7OjqH; zwM1x0Cp2L&l<`g}4D9M=XkuOkZG0$l5-$>%$P_AM_x>J zq_JI}Gf2H!eyuzgj6@O_$I$nJ!Kej1+m$~89y($M9&#*|UO$VR5QQ{y1|9n<^XnMY zKvK$V1%1lgr7%{REC?x+oen1Yw1g;3lK7pV=jcJGox>p6rPd6l6D;m=AA&)mGnR++ zT=~tn!QRoBWOQCA62V=SCYF*)GfT-V^+F{S+W?}Ie`_jLl*Bb2$9#E&@*d5P7xwG1q zE?u65`C3OxTxP*RLL^7AizK&a-xGZUgT6%aXm^^K)u;MB4p3Zg$C@+5^v5wJ5&Gs^ zkjc^>hYBFQccIvG%G9uX%F6Ua9KD9M6}N=8H6SNcxrIB5M<&XUTW-Ig%B?I}f=#jl zWM1@bbKCj@jCo$Ne~NiufQJZ>5nzWVptE1fDXRP>lH!RqtH4bsbXf_sb=j z>x8fn_Or0Og~G#JOz;vcns037Po;|3^HojVsNxr zJU-?$Q1pm!&z0hh`{S8UBSXnhgZc&*$ zgg#XdGYEAl{`?E{Dc%~vM1t&SKyc`iLTs=V2;9YLkHPvKfVH6(ATn!vZh*WiIIs*| zv;h!~izY*UPIR#p7|LnegHSn-L4S!93&41SNVSQ?vI7{*0CWX~hdGF2g60lg8{QFFHkDbPp6+i$QvU;__l}GWMBQUC5nB-gCqgD%At080zq(BQ)Zd zcF{-@B4f{|@Yw4>lHNWIV?c zbv06=3og1tuQ&ZP$ zN(0DZ@^zCWZ-50}UZ)a?guF=^orL@`WyFkdD7x~gIgN&G@2WO}n_D#K3}vIpD2VVr zK?e7xRDg+_v38T8&yE9cDXY&S=ai<}S>)3hB(%n9#+tISnB`c8@~qCQ)UZJJ zM^Pt#2`1L=ejdbO8{rs#;`~^B2vx$g2n*n2r0h_3pR&`*j5iaY?eCFT6tOJT6U&kp z$ID(oAzs!o9ZTp=3g3Jl0B}QI5x#bcEbk- zLldOXkDgsLr*K1=8&XCau{@sS>mhDW7$A!;_`*@YNlqxf6xfj=;m;HYH%$MC1wC3` zGxLbXU$obLlNp(*#ZspKeEJlJ#Cp#&`(1SW0}?Nug`i1lNu1itgk}1gL*c#Csy+O; zD(ltNhVz|7hGL$7rsWM}5E-f`7H6K&9S{jzEHY$Th51C?=vX2}pRxJlAboa7hchoC zN(l@@NpN<#e7A+rg~GcF#TUJCZ%@NXvZ4|QE20vAF?^;!VvDtvmeboXp^zJ6M_sW7 zM!5{>JCD%{J!q@3XVpMCH1SjCl)SbK@wm<|Www|QU z451lr1#Kj(2v5e0mVxG{k_xzR z^_13wiC!AvFNFWBQ_R1xbR!f^Dxm zK9-~_3)}t=Orxy79vtnXt9RTYqVyz+hr_nr^KUTV3hhh=5REjJO!OWS0_gz6E8QiS&sQwgUAoB6hGV@Oi1d|~U?^3ZdnBQ`z2o=R zRtv9FGKr|ODD-M8TwccZO^cjfTq>tXY#8GqH0d6F?K;9NI=pZAk*A0@QeXKC%1DS} zh1%sCY2AM#btMQlu7`UGPik%dG0CrJYMSI_s{1wi|C1J>z0%=GYAKx{KWnW+|D}ZU zCD~Kaor@B_x<72w*LQt6%(D4v)K}SZg~N#4<9|6?t$L13(VJwzm3x(?68T@sMPt7! zPgS~+4u|-5_5GXk?|-ncc!O=EBx#q!lu;ncN6C%}y9sP{82u$d4s)03-%Aehg;M1& literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreter/primitives/array.py b/devtools/meson/mesonbuild/interpreter/primitives/array.py new file mode 100644 index 0000000..eeea112 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/array.py @@ -0,0 +1,108 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 +from __future__ import annotations + +import typing as T + +from ...interpreterbase import ( + ObjectHolder, + IterableObject, + MesonOperator, + typed_operator, + noKwargs, + noPosargs, + noArgsFlattening, + typed_pos_args, + FeatureNew, + + TYPE_var, + + InvalidArguments, +) +from ...mparser import PlusAssignmentNode + +if T.TYPE_CHECKING: + # Object holders need the actual interpreter + from ...interpreter import Interpreter + from ...interpreterbase import TYPE_kwargs + +class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject): + def __init__(self, obj: T.List[TYPE_var], interpreter: 'Interpreter') -> None: + super().__init__(obj, interpreter) + self.methods.update({ + 'contains': self.contains_method, + 'length': self.length_method, + 'get': self.get_method, + }) + + self.trivial_operators.update({ + MesonOperator.EQUALS: (list, lambda x: self.held_object == x), + MesonOperator.NOT_EQUALS: (list, lambda x: self.held_object != x), + MesonOperator.IN: (object, lambda x: x in self.held_object), + MesonOperator.NOT_IN: (object, lambda x: x not in self.held_object), + }) + + # Use actual methods for functions that require additional checks + self.operators.update({ + MesonOperator.PLUS: self.op_plus, + MesonOperator.INDEX: self.op_index, + }) + + def display_name(self) -> str: + return 'array' + + def iter_tuple_size(self) -> None: + return None + + def iter_self(self) -> T.Iterator[TYPE_var]: + return iter(self.held_object) + + def size(self) -> int: + return len(self.held_object) + + @noArgsFlattening + @noKwargs + @typed_pos_args('array.contains', object) + def contains_method(self, args: T.Tuple[object], kwargs: TYPE_kwargs) -> bool: + def check_contains(el: T.List[TYPE_var]) -> bool: + for element in el: + if isinstance(element, list): + found = check_contains(element) + if found: + return True + if element == args[0]: + return True + return False + return check_contains(self.held_object) + + @noKwargs + @noPosargs + def length_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: + return len(self.held_object) + + @noArgsFlattening + @noKwargs + @typed_pos_args('array.get', int, optargs=[object]) + def get_method(self, args: T.Tuple[int, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var: + index = args[0] + if index < -len(self.held_object) or index >= len(self.held_object): + if args[1] is None: + raise InvalidArguments(f'Array index {index} is out of bounds for array of size {len(self.held_object)}.') + return args[1] + return self.held_object[index] + + @typed_operator(MesonOperator.PLUS, object) + def op_plus(self, other: TYPE_var) -> T.List[TYPE_var]: + if not isinstance(other, list): + if not isinstance(self.current_node, PlusAssignmentNode): + FeatureNew.single_use('list.', '0.60.0', self.subproject, 'The right hand operand was not a list.', + location=self.current_node) + other = [other] + return self.held_object + other + + @typed_operator(MesonOperator.INDEX, int) + def op_index(self, other: int) -> TYPE_var: + try: + return self.held_object[other] + except IndexError: + raise InvalidArguments(f'Index {other} out of bounds of array of size {len(self.held_object)}.') diff --git a/devtools/meson/mesonbuild/interpreter/primitives/boolean.py b/devtools/meson/mesonbuild/interpreter/primitives/boolean.py new file mode 100644 index 0000000..4b49caf --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/boolean.py @@ -0,0 +1,52 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 +from __future__ import annotations + +from ...interpreterbase import ( + ObjectHolder, + MesonOperator, + typed_pos_args, + noKwargs, + noPosargs, + + InvalidArguments +) + +import typing as T + +if T.TYPE_CHECKING: + # Object holders need the actual interpreter + from ...interpreter import Interpreter + from ...interpreterbase import TYPE_var, TYPE_kwargs + +class BooleanHolder(ObjectHolder[bool]): + def __init__(self, obj: bool, interpreter: 'Interpreter') -> None: + super().__init__(obj, interpreter) + self.methods.update({ + 'to_int': self.to_int_method, + 'to_string': self.to_string_method, + }) + + self.trivial_operators.update({ + MesonOperator.BOOL: (None, lambda x: self.held_object), + MesonOperator.NOT: (None, lambda x: not self.held_object), + MesonOperator.EQUALS: (bool, lambda x: self.held_object == x), + MesonOperator.NOT_EQUALS: (bool, lambda x: self.held_object != x), + }) + + def display_name(self) -> str: + return 'bool' + + @noKwargs + @noPosargs + def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: + return 1 if self.held_object else 0 + + @noKwargs + @typed_pos_args('bool.to_string', optargs=[str, str]) + def to_string_method(self, args: T.Tuple[T.Optional[str], T.Optional[str]], kwargs: TYPE_kwargs) -> str: + true_str = args[0] or 'true' + false_str = args[1] or 'false' + if any(x is not None for x in args) and not all(x is not None for x in args): + raise InvalidArguments('bool.to_string() must have either no arguments or exactly two string arguments that signify what values to return for true and false.') + return true_str if self.held_object else false_str diff --git a/devtools/meson/mesonbuild/interpreter/primitives/dict.py b/devtools/meson/mesonbuild/interpreter/primitives/dict.py new file mode 100644 index 0000000..ac7c99b --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/dict.py @@ -0,0 +1,88 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 +from __future__ import annotations + +import typing as T + +from ...interpreterbase import ( + ObjectHolder, + IterableObject, + MesonOperator, + typed_operator, + noKwargs, + noPosargs, + noArgsFlattening, + typed_pos_args, + + TYPE_var, + + InvalidArguments, +) + +if T.TYPE_CHECKING: + # Object holders need the actual interpreter + from ...interpreter import Interpreter + from ...interpreterbase import TYPE_kwargs + +class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject): + def __init__(self, obj: T.Dict[str, TYPE_var], interpreter: 'Interpreter') -> None: + super().__init__(obj, interpreter) + self.methods.update({ + 'has_key': self.has_key_method, + 'keys': self.keys_method, + 'get': self.get_method, + }) + + self.trivial_operators.update({ + # Arithmetic + MesonOperator.PLUS: (dict, lambda x: {**self.held_object, **x}), + + # Comparison + MesonOperator.EQUALS: (dict, lambda x: self.held_object == x), + MesonOperator.NOT_EQUALS: (dict, lambda x: self.held_object != x), + MesonOperator.IN: (str, lambda x: x in self.held_object), + MesonOperator.NOT_IN: (str, lambda x: x not in self.held_object), + }) + + # Use actual methods for functions that require additional checks + self.operators.update({ + MesonOperator.INDEX: self.op_index, + }) + + def display_name(self) -> str: + return 'dict' + + def iter_tuple_size(self) -> int: + return 2 + + def iter_self(self) -> T.Iterator[T.Tuple[str, TYPE_var]]: + return iter(self.held_object.items()) + + def size(self) -> int: + return len(self.held_object) + + @noKwargs + @typed_pos_args('dict.has_key', str) + def has_key_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: + return args[0] in self.held_object + + @noKwargs + @noPosargs + def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: + return sorted(self.held_object) + + @noArgsFlattening + @noKwargs + @typed_pos_args('dict.get', str, optargs=[object]) + def get_method(self, args: T.Tuple[str, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var: + if args[0] in self.held_object: + return self.held_object[args[0]] + if args[1] is not None: + return args[1] + raise InvalidArguments(f'Key {args[0]!r} is not in the dictionary.') + + @typed_operator(MesonOperator.INDEX, str) + def op_index(self, other: str) -> TYPE_var: + if other not in self.held_object: + raise InvalidArguments(f'Key {other} is not in the dictionary.') + return self.held_object[other] diff --git a/devtools/meson/mesonbuild/interpreter/primitives/integer.py b/devtools/meson/mesonbuild/interpreter/primitives/integer.py new file mode 100644 index 0000000..b7f3532 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/integer.py @@ -0,0 +1,83 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 +from __future__ import annotations + +from ...interpreterbase import ( + FeatureBroken, InvalidArguments, MesonOperator, ObjectHolder, + noKwargs, noPosargs, typed_operator, +) + +import typing as T + +if T.TYPE_CHECKING: + # Object holders need the actual interpreter + from ...interpreter import Interpreter + from ...interpreterbase import TYPE_var, TYPE_kwargs + +class IntegerHolder(ObjectHolder[int]): + def __init__(self, obj: int, interpreter: 'Interpreter') -> None: + super().__init__(obj, interpreter) + self.methods.update({ + 'is_even': self.is_even_method, + 'is_odd': self.is_odd_method, + 'to_string': self.to_string_method, + }) + + self.trivial_operators.update({ + # Arithmetic + MesonOperator.UMINUS: (None, lambda x: -self.held_object), + MesonOperator.PLUS: (int, lambda x: self.held_object + x), + MesonOperator.MINUS: (int, lambda x: self.held_object - x), + MesonOperator.TIMES: (int, lambda x: self.held_object * x), + + # Comparison + MesonOperator.EQUALS: (int, lambda x: self.held_object == x), + MesonOperator.NOT_EQUALS: (int, lambda x: self.held_object != x), + MesonOperator.GREATER: (int, lambda x: self.held_object > x), + MesonOperator.LESS: (int, lambda x: self.held_object < x), + MesonOperator.GREATER_EQUALS: (int, lambda x: self.held_object >= x), + MesonOperator.LESS_EQUALS: (int, lambda x: self.held_object <= x), + }) + + # Use actual methods for functions that require additional checks + self.operators.update({ + MesonOperator.DIV: self.op_div, + MesonOperator.MOD: self.op_mod, + }) + + def display_name(self) -> str: + return 'int' + + def operator_call(self, operator: MesonOperator, other: TYPE_var) -> TYPE_var: + if isinstance(other, bool): + FeatureBroken.single_use('int operations with non-int', '1.2.0', self.subproject, + 'It is not commutative and only worked because of leaky Python abstractions.', + location=self.current_node) + return super().operator_call(operator, other) + + @noKwargs + @noPosargs + def is_even_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.held_object % 2 == 0 + + @noKwargs + @noPosargs + def is_odd_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: + return self.held_object % 2 != 0 + + @noKwargs + @noPosargs + def to_string_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return str(self.held_object) + + @typed_operator(MesonOperator.DIV, int) + def op_div(self, other: int) -> int: + if other == 0: + raise InvalidArguments('Tried to divide by 0') + return self.held_object // other + + @typed_operator(MesonOperator.MOD, int) + def op_mod(self, other: int) -> int: + if other == 0: + raise InvalidArguments('Tried to divide by 0') + return self.held_object % other diff --git a/devtools/meson/mesonbuild/interpreter/primitives/range.py b/devtools/meson/mesonbuild/interpreter/primitives/range.py new file mode 100644 index 0000000..5eb5e03 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/range.py @@ -0,0 +1,38 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 +from __future__ import annotations + +import typing as T + +from ...interpreterbase import ( + MesonInterpreterObject, + IterableObject, + MesonOperator, + InvalidArguments, +) + +if T.TYPE_CHECKING: + from ...interpreterbase import SubProject + +class RangeHolder(MesonInterpreterObject, IterableObject): + def __init__(self, start: int, stop: int, step: int, *, subproject: 'SubProject') -> None: + super().__init__(subproject=subproject) + self.range = range(start, stop, step) + self.operators.update({ + MesonOperator.INDEX: self.op_index, + }) + + def op_index(self, other: int) -> int: + try: + return self.range[other] + except IndexError: + raise InvalidArguments(f'Index {other} out of bounds of range.') + + def iter_tuple_size(self) -> None: + return None + + def iter_self(self) -> T.Iterator[int]: + return iter(self.range) + + def size(self) -> int: + return len(self.range) diff --git a/devtools/meson/mesonbuild/interpreter/primitives/string.py b/devtools/meson/mesonbuild/interpreter/primitives/string.py new file mode 100644 index 0000000..b825128 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/primitives/string.py @@ -0,0 +1,244 @@ +# Copyright 2021 The Meson development team +# SPDX-license-identifier: Apache-2.0 +from __future__ import annotations + +import re +import os + +import typing as T + +from ...mesonlib import version_compare +from ...interpreterbase import ( + ObjectHolder, + MesonOperator, + FeatureNew, + typed_operator, + noArgsFlattening, + noKwargs, + noPosargs, + typed_pos_args, + + InvalidArguments, +) + + +if T.TYPE_CHECKING: + # Object holders need the actual interpreter + from ...interpreter import Interpreter + from ...interpreterbase import TYPE_var, TYPE_kwargs + +class StringHolder(ObjectHolder[str]): + def __init__(self, obj: str, interpreter: 'Interpreter') -> None: + super().__init__(obj, interpreter) + self.methods.update({ + 'contains': self.contains_method, + 'startswith': self.startswith_method, + 'endswith': self.endswith_method, + 'format': self.format_method, + 'join': self.join_method, + 'replace': self.replace_method, + 'split': self.split_method, + 'splitlines': self.splitlines_method, + 'strip': self.strip_method, + 'substring': self.substring_method, + 'to_int': self.to_int_method, + 'to_lower': self.to_lower_method, + 'to_upper': self.to_upper_method, + 'underscorify': self.underscorify_method, + 'version_compare': self.version_compare_method, + }) + + self.trivial_operators.update({ + # Arithmetic + MesonOperator.PLUS: (str, lambda x: self.held_object + x), + + # Comparison + MesonOperator.EQUALS: (str, lambda x: self.held_object == x), + MesonOperator.NOT_EQUALS: (str, lambda x: self.held_object != x), + MesonOperator.GREATER: (str, lambda x: self.held_object > x), + MesonOperator.LESS: (str, lambda x: self.held_object < x), + MesonOperator.GREATER_EQUALS: (str, lambda x: self.held_object >= x), + MesonOperator.LESS_EQUALS: (str, lambda x: self.held_object <= x), + }) + + # Use actual methods for functions that require additional checks + self.operators.update({ + MesonOperator.DIV: self.op_div, + MesonOperator.INDEX: self.op_index, + MesonOperator.IN: self.op_in, + MesonOperator.NOT_IN: self.op_notin, + }) + + def display_name(self) -> str: + return 'str' + + @noKwargs + @typed_pos_args('str.contains', str) + def contains_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: + return self.held_object.find(args[0]) >= 0 + + @noKwargs + @typed_pos_args('str.startswith', str) + def startswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: + return self.held_object.startswith(args[0]) + + @noKwargs + @typed_pos_args('str.endswith', str) + def endswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: + return self.held_object.endswith(args[0]) + + @noArgsFlattening + @noKwargs + @typed_pos_args('str.format', varargs=object) + def format_method(self, args: T.Tuple[T.List[object]], kwargs: TYPE_kwargs) -> str: + arg_strings: T.List[str] = [] + for arg in args[0]: + if isinstance(arg, bool): # Python boolean is upper case. + arg = str(arg).lower() + arg_strings.append(str(arg)) + + def arg_replace(match: T.Match[str]) -> str: + idx = int(match.group(1)) + if idx >= len(arg_strings): + raise InvalidArguments(f'Format placeholder @{idx}@ out of range.') + return arg_strings[idx] + + return re.sub(r'@(\d+)@', arg_replace, self.held_object) + + @noKwargs + @noPosargs + @FeatureNew('str.splitlines', '1.2.0') + def splitlines_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: + return self.held_object.splitlines() + + @noKwargs + @typed_pos_args('str.join', varargs=str) + def join_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> str: + return self.held_object.join(args[0]) + + @noKwargs + @FeatureNew('str.replace', '0.58.0') + @typed_pos_args('str.replace', str, str) + def replace_method(self, args: T.Tuple[str, str], kwargs: TYPE_kwargs) -> str: + return self.held_object.replace(args[0], args[1]) + + @noKwargs + @typed_pos_args('str.split', optargs=[str]) + def split_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> T.List[str]: + return self.held_object.split(args[0]) + + @noKwargs + @typed_pos_args('str.strip', optargs=[str]) + def strip_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> str: + if args[0]: + FeatureNew.single_use('str.strip with a positional argument', '0.43.0', self.subproject, location=self.current_node) + return self.held_object.strip(args[0]) + + @noKwargs + @FeatureNew('str.substring', '0.56.0') + @typed_pos_args('str.substring', optargs=[int, int]) + def substring_method(self, args: T.Tuple[T.Optional[int], T.Optional[int]], kwargs: TYPE_kwargs) -> str: + start = args[0] if args[0] is not None else 0 + end = args[1] if args[1] is not None else len(self.held_object) + return self.held_object[start:end] + + @noKwargs + @noPosargs + def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: + try: + return int(self.held_object) + except ValueError: + raise InvalidArguments(f'String {self.held_object!r} cannot be converted to int') + + @noKwargs + @noPosargs + def to_lower_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.lower() + + @noKwargs + @noPosargs + def to_upper_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.upper() + + @noKwargs + @noPosargs + def underscorify_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return re.sub(r'[^a-zA-Z0-9]', '_', self.held_object) + + @noKwargs + @typed_pos_args('str.version_compare', str) + def version_compare_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: + return version_compare(self.held_object, args[0]) + + @staticmethod + def _op_div(this: str, other: str) -> str: + return os.path.join(this, other).replace('\\', '/') + + @FeatureNew('/ with string arguments', '0.49.0') + @typed_operator(MesonOperator.DIV, str) + def op_div(self, other: str) -> str: + return self._op_div(self.held_object, other) + + @typed_operator(MesonOperator.INDEX, int) + def op_index(self, other: int) -> str: + try: + return self.held_object[other] + except IndexError: + raise InvalidArguments(f'Index {other} out of bounds of string of size {len(self.held_object)}.') + + @FeatureNew('"in" string operator', '1.0.0') + @typed_operator(MesonOperator.IN, str) + def op_in(self, other: str) -> bool: + return other in self.held_object + + @FeatureNew('"not in" string operator', '1.0.0') + @typed_operator(MesonOperator.NOT_IN, str) + def op_notin(self, other: str) -> bool: + return other not in self.held_object + + +class MesonVersionString(str): + pass + +class MesonVersionStringHolder(StringHolder): + @noKwargs + @typed_pos_args('str.version_compare', str) + def version_compare_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: + self.interpreter.tmp_meson_version = args[0] + return version_compare(self.held_object, args[0]) + +# These special subclasses of string exist to cover the case where a dependency +# exports a string variable interchangeable with a system dependency. This +# matters because a dependency can only have string-type get_variable() return +# values. If at any time dependencies start supporting additional variable +# types, this class could be deprecated. +class DependencyVariableString(str): + pass + +class DependencyVariableStringHolder(StringHolder): + def op_div(self, other: str) -> T.Union[str, DependencyVariableString]: + ret = super().op_div(other) + if '..' in other: + return ret + return DependencyVariableString(ret) + + +class OptionString(str): + optname: str + + def __new__(cls, value: str, name: str) -> 'OptionString': + obj = str.__new__(cls, value) + obj.optname = name + return obj + + def __getnewargs__(self) -> T.Tuple[str, str]: # type: ignore # because the entire point of this is to diverge + return (str(self), self.optname) + + +class OptionStringHolder(StringHolder): + held_object: OptionString + + def op_div(self, other: str) -> T.Union[str, OptionString]: + ret = super().op_div(other) + name = self._op_div(self.held_object.optname, other) + return OptionString(ret, name) diff --git a/devtools/meson/mesonbuild/interpreter/type_checking.py b/devtools/meson/mesonbuild/interpreter/type_checking.py new file mode 100644 index 0000000..8b57d06 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreter/type_checking.py @@ -0,0 +1,481 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation + +"""Helpers for strict type checking.""" + +from __future__ import annotations +import os +import typing as T + +from .. import compilers +from ..build import (CustomTarget, BuildTarget, + CustomTargetIndex, ExtractedObjects, GeneratedList, IncludeDirs, + BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable) +from ..coredata import UserFeatureOption +from ..dependencies import Dependency, InternalDependency +from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo +from ..mesonlib import (File, FileMode, MachineChoice, listify, has_path_sep, + OptionKey, EnvironmentVariables) +from ..programs import ExternalProgram + +# Helper definition for type checks that are `Optional[T]` +NoneType: T.Type[None] = type(None) + +if T.TYPE_CHECKING: + from typing_extensions import Literal + + from ..interpreterbase import TYPE_var + from ..mesonlib import EnvInitValueType + + _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] + + +def in_set_validator(choices: T.Set[str]) -> T.Callable[[str], T.Optional[str]]: + """Check that the choice given was one of the given set.""" + + def inner(check: str) -> T.Optional[str]: + if check not in choices: + return f"must be one of {', '.join(sorted(choices))}, not {check}" + return None + + return inner + + +def _language_validator(l: T.List[str]) -> T.Optional[str]: + """Validate language keyword argument. + + Particularly for functions like `add_compiler()`, and `add_*_args()` + """ + diff = {a.lower() for a in l}.difference(compilers.all_languages) + if diff: + return f'unknown languages: {", ".join(diff)}' + return None + + +def _install_mode_validator(mode: T.List[T.Union[str, bool, int]]) -> T.Optional[str]: + """Validate the `install_mode` keyword argument. + + This is a rather odd thing, it's a scalar, or an array of 3 values in the form: + [(str | False), (str | int | False) = False, (str | int | False) = False] + where the second and third components are not required and default to False. + """ + if not mode: + return None + if True in mode: + return 'components can only be permission strings, numbers, or False' + if len(mode) > 3: + return 'may have at most 3 elements' + + perms = mode[0] + if not isinstance(perms, (str, bool)): + return 'first component must be a permissions string or False' + + if isinstance(perms, str): + if not len(perms) == 9: + return ('permissions string must be exactly 9 characters in the form rwxr-xr-x,' + f' got {len(perms)}') + for i in [0, 3, 6]: + if perms[i] not in {'-', 'r'}: + return f'permissions character {i+1} must be "-" or "r", not {perms[i]}' + for i in [1, 4, 7]: + if perms[i] not in {'-', 'w'}: + return f'permissions character {i+1} must be "-" or "w", not {perms[i]}' + for i in [2, 5]: + if perms[i] not in {'-', 'x', 's', 'S'}: + return f'permissions character {i+1} must be "-", "s", "S", or "x", not {perms[i]}' + if perms[8] not in {'-', 'x', 't', 'T'}: + return f'permission character 9 must be "-", "t", "T", or "x", not {perms[8]}' + + if len(mode) >= 2 and not isinstance(mode[1], (int, str, bool)): + return 'second component can only be a string, number, or False' + if len(mode) >= 3 and not isinstance(mode[2], (int, str, bool)): + return 'third component can only be a string, number, or False' + + return None + + +def _install_mode_convertor(mode: T.Optional[T.List[T.Union[str, bool, int]]]) -> FileMode: + """Convert the DSL form of the `install_mode` keyword argument to `FileMode`""" + + if not mode: + return FileMode() + + # This has already been validated by the validator. False denotes "use + # default". mypy is totally incapable of understanding it, because + # generators clobber types via homogeneous return. But also we *must* + # convert the first element different from the rest + m1 = mode[0] if isinstance(mode[0], str) else None + rest = (m if isinstance(m, (str, int)) else None for m in mode[1:]) + + return FileMode(m1, *rest) + + +def _lower_strlist(input: T.List[str]) -> T.List[str]: + """Lower a list of strings. + + mypy (but not pyright) gets confused about using a lambda as the convertor function + """ + return [i.lower() for i in input] + + +def variables_validator(contents: T.Union[str, T.List[str], T.Dict[str, str]]) -> T.Optional[str]: + if isinstance(contents, str): + contents = [contents] + if isinstance(contents, dict): + variables = contents + else: + variables = {} + for v in contents: + try: + key, val = v.split('=', 1) + except ValueError: + return f'variable {v!r} must have a value separated by equals sign.' + variables[key.strip()] = val.strip() + for k, v in variables.items(): + if not k: + return 'empty variable name' + if not v: + return 'empty variable value' + if any(c.isspace() for c in k): + return f'invalid whitespace in variable name {k!r}' + return None + + +def variables_convertor(contents: T.Union[str, T.List[str], T.Dict[str, str]]) -> T.Dict[str, str]: + if isinstance(contents, str): + contents = [contents] + if isinstance(contents, dict): + return contents + variables = {} + for v in contents: + key, val = v.split('=', 1) + variables[key.strip()] = val.strip() + return variables + + +NATIVE_KW = KwargInfo( + 'native', bool, + default=False, + convertor=lambda n: MachineChoice.BUILD if n else MachineChoice.HOST) + +LANGUAGE_KW = KwargInfo( + 'language', ContainerTypeInfo(list, str, allow_empty=False), + listify=True, + required=True, + validator=_language_validator, + convertor=_lower_strlist) + +INSTALL_MODE_KW: KwargInfo[T.List[T.Union[str, bool, int]]] = KwargInfo( + 'install_mode', + ContainerTypeInfo(list, (str, bool, int)), + listify=True, + default=[], + validator=_install_mode_validator, + convertor=_install_mode_convertor, +) + +REQUIRED_KW: KwargInfo[T.Union[bool, UserFeatureOption]] = KwargInfo( + 'required', + (bool, UserFeatureOption), + default=True, + # TODO: extract_required_kwarg could be converted to a convertor +) + +DISABLER_KW: KwargInfo[bool] = KwargInfo('disabler', bool, default=False) + +def _env_validator(value: T.Union[EnvironmentVariables, T.List['TYPE_var'], T.Dict[str, 'TYPE_var'], str, None], + only_dict_str: bool = True) -> T.Optional[str]: + def _splitter(v: str) -> T.Optional[str]: + split = v.split('=', 1) + if len(split) == 1: + return f'"{v}" is not two string values separated by an "="' + return None + + if isinstance(value, str): + v = _splitter(value) + if v is not None: + return v + elif isinstance(value, list): + for i in listify(value): + if not isinstance(i, str): + return f"All array elements must be a string, not {i!r}" + v = _splitter(i) + if v is not None: + return v + elif isinstance(value, dict): + # We don't need to spilt here, just do the type checking + for k, dv in value.items(): + if only_dict_str: + if any(i for i in listify(dv) if not isinstance(i, str)): + return f"Dictionary element {k} must be a string or list of strings not {dv!r}" + elif isinstance(dv, list): + if any(not isinstance(i, str) for i in dv): + return f"Dictionary element {k} must be a string, bool, integer or list of strings, not {dv!r}" + elif not isinstance(dv, (str, bool, int)): + return f"Dictionary element {k} must be a string, bool, integer or list of strings, not {dv!r}" + # We know that otherwise we have an EnvironmentVariables object or None, and + # we're okay at this point + return None + +def _options_validator(value: T.Union[EnvironmentVariables, T.List['TYPE_var'], T.Dict[str, 'TYPE_var'], str, None]) -> T.Optional[str]: + # Reusing the env validator is a little overkill, but nicer than duplicating the code + return _env_validator(value, only_dict_str=False) + +def split_equal_string(input: str) -> T.Tuple[str, str]: + """Split a string in the form `x=y` + + This assumes that the string has already been validated to split properly. + """ + a, b = input.split('=', 1) + return (a, b) + +# Split _env_convertor() and env_convertor_with_method() to make mypy happy. +# It does not want extra arguments in KwargInfo convertor callable. +def env_convertor_with_method(value: _FullEnvInitValueType, + init_method: Literal['set', 'prepend', 'append'] = 'set', + separator: str = os.pathsep) -> EnvironmentVariables: + if isinstance(value, str): + return EnvironmentVariables(dict([split_equal_string(value)]), init_method, separator) + elif isinstance(value, list): + return EnvironmentVariables(dict(split_equal_string(v) for v in listify(value)), init_method, separator) + elif isinstance(value, dict): + return EnvironmentVariables(value, init_method, separator) + elif value is None: + return EnvironmentVariables() + return value + +def _env_convertor(value: _FullEnvInitValueType) -> EnvironmentVariables: + return env_convertor_with_method(value) + +ENV_KW: KwargInfo[T.Union[EnvironmentVariables, T.List, T.Dict, str, None]] = KwargInfo( + 'env', + (EnvironmentVariables, list, dict, str, NoneType), + validator=_env_validator, + convertor=_env_convertor, +) + +DEPFILE_KW: KwargInfo[T.Optional[str]] = KwargInfo( + 'depfile', + (str, type(None)), + validator=lambda x: 'Depfile must be a plain filename with a subdirectory' if has_path_sep(x) else None +) + +# TODO: CustomTargetIndex should be supported here as well +DEPENDS_KW: KwargInfo[T.List[T.Union[BuildTarget, CustomTarget]]] = KwargInfo( + 'depends', + ContainerTypeInfo(list, (BuildTarget, CustomTarget)), + listify=True, + default=[], +) + +DEPEND_FILES_KW: KwargInfo[T.List[T.Union[str, File]]] = KwargInfo( + 'depend_files', + ContainerTypeInfo(list, (File, str)), + listify=True, + default=[], +) + +COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File]]] = KwargInfo( + 'command', + # TODO: should accept CustomTargetIndex as well? + ContainerTypeInfo(list, (str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File), allow_empty=False), + required=True, + listify=True, + default=[], +) + +def _override_options_convertor(raw: T.Union[str, T.List[str], T.Dict[str, T.Union[str, int, bool, T.List[str]]]]) -> T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]]: + if isinstance(raw, str): + raw = [raw] + if isinstance(raw, list): + output: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] = {} + for each in raw: + k, v = split_equal_string(each) + output[OptionKey.from_string(k)] = v + return output + return {OptionKey.from_string(k): v for k, v in raw.items()} + + +OVERRIDE_OPTIONS_KW: KwargInfo[T.Union[str, T.Dict[str, T.Union[str, int, bool, T.List[str]]], T.List[str]]] = KwargInfo( + 'override_options', + (str, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, (str, int, bool, list))), + default={}, + validator=_options_validator, + convertor=_override_options_convertor, + since_values={dict: '1.2.0'}, +) + + +def _output_validator(outputs: T.List[str]) -> T.Optional[str]: + output_set = set(outputs) + if len(output_set) != len(outputs): + seen = set() + for el in outputs: + if el in seen: + return f"contains {el!r} multiple times, but no duplicates are allowed." + seen.add(el) + for i in outputs: + if i == '': + return 'Output must not be empty.' + elif i.strip() == '': + return 'Output must not consist only of whitespace.' + elif has_path_sep(i): + return f'Output {i!r} must not contain a path segment.' + elif '@INPUT' in i: + return f'output {i!r} contains "@INPUT", which is invalid. Did you mean "@PLAINNAME@" or "@BASENAME@?' + + return None + +MULTI_OUTPUT_KW: KwargInfo[T.List[str]] = KwargInfo( + 'output', + ContainerTypeInfo(list, str, allow_empty=False), + listify=True, + required=True, + default=[], + validator=_output_validator, +) + +OUTPUT_KW: KwargInfo[str] = KwargInfo( + 'output', + str, + required=True, + validator=lambda x: _output_validator([x]) +) + +CT_INPUT_KW: KwargInfo[T.List[T.Union[str, File, ExternalProgram, BuildTarget, CustomTarget, CustomTargetIndex, ExtractedObjects, GeneratedList]]] = KwargInfo( + 'input', + ContainerTypeInfo(list, (str, File, ExternalProgram, BuildTarget, CustomTarget, CustomTargetIndex, ExtractedObjects, GeneratedList)), + listify=True, + default=[], +) + +CT_INSTALL_TAG_KW: KwargInfo[T.List[T.Union[str, bool]]] = KwargInfo( + 'install_tag', + ContainerTypeInfo(list, (str, bool)), + listify=True, + default=[], + since='0.60.0', + convertor=lambda x: [y if isinstance(y, str) else None for y in x], +) + +INSTALL_TAG_KW: KwargInfo[T.Optional[str]] = KwargInfo('install_tag', (str, NoneType)) + +INSTALL_KW = KwargInfo('install', bool, default=False) + +CT_INSTALL_DIR_KW: KwargInfo[T.List[T.Union[str, Literal[False]]]] = KwargInfo( + 'install_dir', + ContainerTypeInfo(list, (str, bool)), + listify=True, + default=[], + validator=lambda x: 'must be `false` if boolean' if True in x else None, +) + +CT_BUILD_BY_DEFAULT: KwargInfo[T.Optional[bool]] = KwargInfo('build_by_default', (bool, type(None)), since='0.40.0') + +CT_BUILD_ALWAYS: KwargInfo[T.Optional[bool]] = KwargInfo( + 'build_always', (bool, NoneType), + deprecated='0.47.0', + deprecated_message='combine build_by_default and build_always_stale instead.', +) + +CT_BUILD_ALWAYS_STALE: KwargInfo[T.Optional[bool]] = KwargInfo( + 'build_always_stale', (bool, NoneType), + since='0.47.0', +) + +INSTALL_DIR_KW: KwargInfo[T.Optional[str]] = KwargInfo('install_dir', (str, NoneType)) + +INCLUDE_DIRECTORIES: KwargInfo[T.List[T.Union[str, IncludeDirs]]] = KwargInfo( + 'include_directories', + ContainerTypeInfo(list, (str, IncludeDirs)), + listify=True, + default=[], +) + +DEFAULT_OPTIONS = OVERRIDE_OPTIONS_KW.evolve(name='default_options') + +ENV_METHOD_KW = KwargInfo('method', str, default='set', since='0.62.0', + validator=in_set_validator({'set', 'prepend', 'append'})) + +ENV_SEPARATOR_KW = KwargInfo('separator', str, default=os.pathsep) + +DEPENDENCIES_KW: KwargInfo[T.List[Dependency]] = KwargInfo( + 'dependencies', + # InternalDependency is a subclass of Dependency, but we want to + # print it in error messages + ContainerTypeInfo(list, (Dependency, InternalDependency)), + listify=True, + default=[], +) + +D_MODULE_VERSIONS_KW: KwargInfo[T.List[T.Union[str, int]]] = KwargInfo( + 'd_module_versions', + ContainerTypeInfo(list, (str, int)), + listify=True, + default=[], +) + +_link_with_error = '''can only be self-built targets, external dependencies (including libraries) must go in "dependencies".''' + +# Allow Dependency for the better error message? But then in other cases it will list this as one of the allowed types! +LINK_WITH_KW: KwargInfo[T.List[T.Union[BothLibraries, SharedLibrary, StaticLibrary, CustomTarget, CustomTargetIndex, Jar, Executable]]] = KwargInfo( + 'link_with', + ContainerTypeInfo(list, (BothLibraries, SharedLibrary, StaticLibrary, CustomTarget, CustomTargetIndex, Jar, Executable, Dependency)), + listify=True, + default=[], + validator=lambda x: _link_with_error if any(isinstance(i, Dependency) for i in x) else None, +) + +def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex, Dependency]]) -> T.Optional[str]: + for l in values: + if isinstance(l, (CustomTarget, CustomTargetIndex)) and l.links_dynamically(): + return f'{type(l).__name__} returning a shared library is not allowed' + if isinstance(l, Dependency): + return _link_with_error + return None + +LINK_WHOLE_KW: KwargInfo[T.List[T.Union[BothLibraries, StaticLibrary, CustomTarget, CustomTargetIndex]]] = KwargInfo( + 'link_whole', + ContainerTypeInfo(list, (BothLibraries, StaticLibrary, CustomTarget, CustomTargetIndex, Dependency)), + listify=True, + default=[], + validator=link_whole_validator, +) + +SOURCES_KW: KwargInfo[T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList]]] = KwargInfo( + 'sources', + ContainerTypeInfo(list, (str, File, CustomTarget, CustomTargetIndex, GeneratedList)), + listify=True, + default=[], +) + +VARIABLES_KW: KwargInfo[T.Dict[str, str]] = KwargInfo( + 'variables', + # str is listified by validator/convertor, cannot use listify=True here because + # that would listify dict too. + (str, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str)), # type: ignore + validator=variables_validator, + convertor=variables_convertor, + default={}, +) + +PRESERVE_PATH_KW: KwargInfo[bool] = KwargInfo('preserve_path', bool, default=False, since='0.63.0') + +TEST_KWS: T.List[KwargInfo] = [ + KwargInfo('args', ContainerTypeInfo(list, (str, File, BuildTarget, CustomTarget, CustomTargetIndex)), + listify=True, default=[]), + KwargInfo('should_fail', bool, default=False), + KwargInfo('timeout', int, default=30), + KwargInfo('workdir', (str, NoneType), default=None, + validator=lambda x: 'must be an absolute path' if not os.path.isabs(x) else None), + KwargInfo('protocol', str, + default='exitcode', + validator=in_set_validator({'exitcode', 'tap', 'gtest', 'rust'}), + since_values={'gtest': '0.55.0', 'rust': '0.57.0'}), + KwargInfo('priority', int, default=0, since='0.52.0'), + # TODO: env needs reworks of the way the environment variable holder itself works probably + ENV_KW, + DEPENDS_KW.evolve(since='0.46.0'), + KwargInfo('suite', ContainerTypeInfo(list, str), listify=True, default=['']), # yes, a list of empty string + KwargInfo('verbose', bool, default=False, since='0.62.0'), +] diff --git a/devtools/meson/mesonbuild/interpreterbase/__init__.py b/devtools/meson/mesonbuild/interpreterbase/__init__.py new file mode 100644 index 0000000..f0c2002 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/__init__.py @@ -0,0 +1,139 @@ +# Copyright 2013-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +__all__ = [ + 'InterpreterObject', + 'MesonInterpreterObject', + 'ObjectHolder', + 'IterableObject', + 'MutableInterpreterObject', + 'ContextManagerObject', + + 'MesonOperator', + + 'Disabler', + 'is_disabled', + + 'InterpreterException', + 'InvalidCode', + 'InvalidArguments', + 'SubdirDoneRequest', + 'ContinueRequest', + 'BreakRequest', + + 'default_resolve_key', + 'flatten', + 'resolve_second_level_holders', + + 'noPosargs', + 'noKwargs', + 'stringArgs', + 'noArgsFlattening', + 'noSecondLevelHolderResolving', + 'unholder_return', + 'disablerIfNotFound', + 'permittedKwargs', + 'typed_operator', + 'unary_operator', + 'typed_pos_args', + 'ContainerTypeInfo', + 'KwargInfo', + 'typed_kwargs', + 'FeatureCheckBase', + 'FeatureNew', + 'FeatureDeprecated', + 'FeatureBroken', + 'FeatureNewKwargs', + 'FeatureDeprecatedKwargs', + + 'InterpreterBase', + + 'SubProject', + + 'TV_fw_var', + 'TV_fw_args', + 'TV_fw_kwargs', + 'TV_func', + 'TYPE_elementary', + 'TYPE_var', + 'TYPE_nvar', + 'TYPE_kwargs', + 'TYPE_nkwargs', + 'TYPE_key_resolver', + 'TYPE_HoldableTypes', + + 'HoldableTypes', +] + +from .baseobjects import ( + InterpreterObject, + MesonInterpreterObject, + ObjectHolder, + IterableObject, + MutableInterpreterObject, + ContextManagerObject, + + TV_fw_var, + TV_fw_args, + TV_fw_kwargs, + TV_func, + TYPE_elementary, + TYPE_var, + TYPE_nvar, + TYPE_kwargs, + TYPE_nkwargs, + TYPE_key_resolver, + TYPE_HoldableTypes, + + SubProject, + + HoldableTypes, +) + +from .decorators import ( + noPosargs, + noKwargs, + stringArgs, + noArgsFlattening, + noSecondLevelHolderResolving, + unholder_return, + disablerIfNotFound, + permittedKwargs, + typed_pos_args, + ContainerTypeInfo, + KwargInfo, + typed_operator, + unary_operator, + typed_kwargs, + FeatureCheckBase, + FeatureNew, + FeatureDeprecated, + FeatureBroken, + FeatureNewKwargs, + FeatureDeprecatedKwargs, +) + +from .exceptions import ( + InterpreterException, + InvalidCode, + InvalidArguments, + SubdirDoneRequest, + ContinueRequest, + BreakRequest, +) + +from .disabler import Disabler, is_disabled +from .helpers import default_resolve_key, flatten, resolve_second_level_holders +from .interpreterbase import InterpreterBase +from .operator import MesonOperator diff --git a/devtools/meson/mesonbuild/interpreterbase/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/interpreterbase/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a17883124006473425a8bc3961a22a5a28d38e2 GIT binary patch literal 2133 zcmchXS#R4$5P&85(0y5oPx(F--$xD~En3G3YP3m=#3z}`M4hxCI@2vEn11)@||K8hV zB7q4^VhRUv5QlIW)0n|5<}i;1EMf`ESivfeU=8bd4@Yqf$8iEDaS9tajWallb2yI+ zxQI)*j4QZ`YuLp5xQ-jRiCeghJGhH`xPN^B2|U0Dc9K$%q5&A7K^UYV7@}bqrZl7} z0~yLfmU57zJmjeW1u8<3N>HLQl&Jz0szQ}UV1#N=qdL@+ob#c5k49mX#$b%bVVovl zf+k^-reKO1(4c9UrWu%_S(v3cn4@`^rv+G`MOdUISfXWErWIJBRam7pSfeI1!@Q5| z`?L=0v;iBm37fP9TeJ<^v;#Y#|FOMGd$33QupjD&_5nSB2lNmg(j#~j+K%kUbO?u` zd~6@lF&u08NlNMI1H$ zJn&ilJg)x4)pNY{pPP<({ce_GILphPPU5>#WzH;*!==hwo`I2qs{TQ`r*GS$=Uc9$ z^5@R2Xos|*;pyb? z2US@Yjx4=AjAtzQcRhiI+b?J-a7=mkfgbsLu4jZRta3$6%MtQY2cA0}S7pOgp;(CC z?nYlzc_vJ~67l3lw7aLKCsZ!Byby0xHI~nWZlkuTm!yiZ=~TL1UBG_4emh?6*k>`Z zqx`{!M>FZoypV3#nc2(ljm{h6)|4t2iQ%UdA~{}cnzg`btMcWK7f%gg3+@VC3zZ2C z9Gwj%-9)@n^9+51CuEUPVw5$SDVbq8%kqG%uv}$~upuc|qam$_ z7tIruHVo6Y4FmF5x`*8Gw(5CznNgcZrMvzx@Jy^eO*g+@6w zyanX}cn5C0g|D1?b=^&pQn_G(${Ykr|kG_&LpJo9`MsBP3X3m6dB`6UK+ZDQFhjz zSNS)q{5!>D@M*;6x*dpijz7E^gr|`Z7DNfJ4mI<5R@%^9A^1pltdD*HV6>|Ny#Pj` zB~o~02%@=}q0E&b?Ah-F@c05FP|gyq@T>*A`L(ga=a@gL zvbx~6RPF!xS+yVJXxzwQ*ER~(dd~NAz9oa2`6f*14RS@ zOvrxEE8RpUT&jqVn9vxOZCyRAqeN3{I@?f5=&S=Fav>U^6neEqTbnK2ed&ZDhqPf> zkIMl|4+|fjZ%EvR=l9#aCqv3khZ9&6DMrI-`gkbmNvL_yt2|HTFw>h>)3``dI!yj; zV;o5~3=2N3_N_lZD_ei1dr(2@G6=i4i*2A5+=p-{mu;QB{NFQlsFq^>Rv~e^)wHuW1rr!@{qYc6WcU`|{xMMYXh5@d|-! dWzRYwNliS%G45gycMThR#vk{kDj@&> literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreterbase/__pycache__/baseobjects.cpython-37.pyc b/devtools/meson/mesonbuild/interpreterbase/__pycache__/baseobjects.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a075b32a374aaac03dcdb401c05d2c1940412ac GIT binary patch literal 7658 zcmbVR+ix7#d7m>gJ3D*jlArauT_*Dm#%V`I1;v60O~4MRhdXbCz6k zc7{DOONE1VA4;R?i~9#OQegpoXn+EJC{Un95d`ReF;4{w6!2StzWJ%Y@66tKi7%bS zoH^$^x9^U=&@1xu~yTfAL^RMHO_pk$6AbOT<3|D!po}inhiJ{!D8| zeQT{*e2e~E?^NrQ>MQy4z0*bqQpI2DEw`3c?^#~uGrY!U zKQmhA-qZLTKlQ1`Pl-iwZb>^ZTIaFC1+gL=aZy|nukiVfwWPH!1Ny4!F}7b5mpl5B z2Iv()u3{|B7{jTrRR`=WKaKJ`d;#Tm3ChoWrnj!C(b@Xhn%`X_th060xK0i$Tvy|+ ziwa-t7-%sJDBN+o9OvtaSJzUwr&G{kzWG*k~qa*!M(o?$YuU2Ag_uy#c7OrhZi1c_1C^2 zeyX#y- zajm6uMl$wXC+YgsY#H3bP3F_`=sc^Q@5@&dr$E7;paTxm1 zdXKI+D>wRGpRac(cd_9`Vx5XmU3b*j-A`@TZ3A)Fy^MYS7q6C_o<31y)W23YX>j26 zgzKh7*X@P8?^C_(x_{pH{H#Zw9pO8{TrLyrG>TX7Ms#wUsdhR$MXDhag6y=QSYx&nWo-z#tot#XlU{Lrxs{v^8%nnUIIl; zw933fdh5AKnhUTT^i~zWQ_l@P&rbtlp=I+0eg=?5z63}fkY#=rtCBpMEqmO)z*o>N za0bdc(g8Ze&&8;}v76zYEH)bt6{CCp<13T%TzQh3YhfVjx+J>DGbq}`E%eg;S$Gxa zyo*X#8)$A;GF8_(L5u<0y%d|A9Wb&#nwm&<9%GfdGuha!fY&yilfsq??$`6 zx37faA;u}z)>v}kI4aXalUlR!VK<5&kJQAIw4|y#&pf#q$vN86OiLLd)at28J*hPu zp$wUZ^T)|LBoWP19A7t5dn6;7{#K+SgF+9Hj95*P>c3GLlj413h{k z=eadpB|l!pp3LV3wPNu_VYp6dNu#wNWq8_Psow)nn^-D?#|2(ii~+V7VpSRLP@Q6r znKen`mdrP|gwqc^x$lf_$$6UOo)U?ZGtM(Fa(2Ba65N5!Jb?p}94+uPsba=ZIjN}^ z9Uh9vfi7{pHn|SNxzU(+65YA_C96vkmL#8<8rpI^FY52^hB8(gKTS%L4I1^LtYele zqeye`h5ACiL4Yx{rNwU44Wif!+Ct{3>nat*k##fU!&?L(gP!W)?osxG9?X0qWs5zG zisn&hV7elkXV=&=Yk&!hV8dkPI1?V4ofMmmweT0p*{B=YmSD-)Rod(jHxgHlxseVN zYccyAj?S2tI(P%-gLn&kN8Dz<$iD<+DE7Ivul%YJlPu)^vOKoy0pGj{wwYcCw^9Z4F zp~?^_&+Nyzv7?kc?Z#U&eCE>0T`}@v1B_HYp2jRQxpJI>C(cUE4Y+i$ifT7SIWqn9 z(3fXajw54isbq#@S1q!Kw||j;;)RqQCt%7F3M8ifJR0t9CeS-Q+d& z@8OMzjWx3d229Q#M}2JB4|%rV4mo3p+{JH<+;yPz7h~j@LheM#nD#G<$}-3cm?u}L zXi%X<`7NsbhzhzEb#_U6Owm_ekMd+4bdWWPswix>uv9hXXXYw%cFk@BGJZ(qDMz%1 z%ES?c+ey?guFMt=jc4RUTVdZPzIWhyb@w0w z9U1nZy1?=9(~lf8&AToS+pc@!VF-x>yhFGA+Z-TWe9(_6d^^S!$qnaTzt`J$+CJ1d zse+y-cczuPGU$-bUbeysXv_P+>O_>^MaN%FP?pqA7mp#)gwOD?Cl8&7_)?>YYXhGN zNhq@8=5yoMT8Hr*w>~X{NO^7}HYo5Se0YEh*B4;&~6-CY5Ooa7Dff82knUL{3ZHNw}7|s|I@Mp)X0ILD+wcN({1X zvw^-1h5Z?P_}JJsqucP$SZu-A--fZ*W0-2F?*ggsn0z+#MNXM^iU^8u4K%j|gI?N( z5qB%flglAQQJ#F#Xc9k>5_LBEo41^aUMDARWSvLO+0$h1DG2PvG=mH=T)3xSvZwWG znuBe{*_E`BvPxMqttf|g_5J&+KmB0sJ^40)E2DG(Q7%fWci;&~$^zUcjXh;@=*jQfvAeK=_sVY$(>VXmXPF(?h$0Ah)7p=O0GAx;FiNZ zM|S8%9wdijq~Cs=6rMOFE0Oa!F`nFVzGUx=IDujmN$l_kVoL~NGL zvk~>e5rscx*T{%xhKy83S{X_}TTsepqFjMQlSV3ucptUT@J8et!n~EMX3eVQB*EKw z#}BC_W#4Y0GEt^v-;gL{!$g^hWDB*RAeG`Qs8*J8v3MDmRY|KKAY(8|1Sap^MV4x4 zJUVdf5MGTvdZlC9UO?urOVh|94EKa2jpI2OF1+@ZpHGBcH4fo6SjlHAfM6oJVJ zia}zMT#B?_fVA*)m90*^%%fH&Eb1l*P7stL7K!`2zMxGVwQGhDR93^uCcq#gkK=SZ zP8g6|>X4s{8OkLlRhgv)1#cvmX|k&pbk!D0i}tWSX*DwP*o9OHDVU62Uy+=cIkMV6 zVN%9NI`R{TuDfw$XmYdJP$Q6~ecWt(6yQALT*Wn~*=W+Cryz|+U3dvJP zkfi=KWH^*=n0Tqm5Beq1yhX)26%!3SaZCRc9sh_ovQgN~)T?IIkOU>$hfIa1tX~^| z@iX>^$SzMrILmY^Z-}zp@P?E}V?tQ1bpCMiJ=3E}c{+WW`83nXOMSQ{eTg@e8$*e% zp&J83L{7{w5eYdZgkah}#7F6~QK+KeLv=MdJ6Z96!#mQH=TE|MY{Tohqj#))lRu%o z)S6Tr(usctz`u^xNAjB5^&e3hywgWoA8Bw&CzG#HL6@2q$I)MurKZS`q>Lfo&QY4b*hn}(ew<62K=ai5u-$p*Bf%j;j=_5;-n!JnuW(t&+e@6eI zq$VXVQ=4@38vQ9$%(_&D(!585%NZogR;D)nHA31wHSPra@**ugqx`=~$fNujY(oFj z;QuBmzel6WS$nw7tZMCueV9h|N0UtRYvLK5CQCp&m?JMyK_P*plx#YuCLQuDl^34o z-xC3%r?#?dN=y`0Ck&9)mT3|DcJ^<_J9Nzv-A!39BkH8Mv&L+lQiNsQVr8SO*YtT~ hfi19QeObS%##E8FnbXU9b**MpjT%~2eQ{;3@_!!UG06Y` literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreterbase/__pycache__/decorators.cpython-37.pyc b/devtools/meson/mesonbuild/interpreterbase/__pycache__/decorators.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7de750fe316eee8d871adf9b39c678ba68588935 GIT binary patch literal 34205 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 QG{ao#GKc0_ey))I6SX5&iU0rr literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/interpreterbase/__pycache__/interpreterbase.cpython-37.pyc b/devtools/meson/mesonbuild/interpreterbase/__pycache__/interpreterbase.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4b03bdd4785c1a422da7c448ab94b8bc80b9465 GIT binary patch literal 22747 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 TYPE_var: + if isinstance(obj, ObjectHolder): + assert isinstance(obj.held_object, HoldableTypes) + return obj.held_object + elif isinstance(obj, MesonInterpreterObject): + return obj + elif isinstance(obj, HoldableObject): + raise MesonBugException(f'Argument {obj} of type {type(obj).__name__} is not held by an ObjectHolder.') + elif isinstance(obj, InterpreterObject): + raise InvalidArguments(f'Argument {obj} of type {type(obj).__name__} cannot be passed to a method or function') + raise MesonBugException(f'Unknown object {obj} of type {type(obj).__name__} in the parameters.') diff --git a/devtools/meson/mesonbuild/interpreterbase/baseobjects.py b/devtools/meson/mesonbuild/interpreterbase/baseobjects.py new file mode 100644 index 0000000..4966978 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/baseobjects.py @@ -0,0 +1,187 @@ +# Copyright 2013-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mparser +from .exceptions import InvalidCode, InvalidArguments +from .helpers import flatten, resolve_second_level_holders +from .operator import MesonOperator +from ..mesonlib import HoldableObject, MesonBugException +import textwrap + +import typing as T +from abc import ABCMeta +from contextlib import AbstractContextManager + +if T.TYPE_CHECKING: + from typing_extensions import Protocol + + # Object holders need the actual interpreter + from ..interpreter import Interpreter + + __T = T.TypeVar('__T', bound='TYPE_var', contravariant=True) + + class OperatorCall(Protocol[__T]): + def __call__(self, other: __T) -> 'TYPE_var': ... + +TV_fw_var = T.Union[str, int, bool, list, dict, 'InterpreterObject'] +TV_fw_args = T.List[T.Union[mparser.BaseNode, TV_fw_var]] +TV_fw_kwargs = T.Dict[str, T.Union[mparser.BaseNode, TV_fw_var]] + +TV_func = T.TypeVar('TV_func', bound=T.Callable[..., T.Any]) + +TYPE_elementary = T.Union[str, int, bool, T.List[T.Any], T.Dict[str, T.Any]] +TYPE_var = T.Union[TYPE_elementary, HoldableObject, 'MesonInterpreterObject'] +TYPE_nvar = T.Union[TYPE_var, mparser.BaseNode] +TYPE_kwargs = T.Dict[str, TYPE_var] +TYPE_nkwargs = T.Dict[str, TYPE_nvar] +TYPE_key_resolver = T.Callable[[mparser.BaseNode], str] + +SubProject = T.NewType('SubProject', str) + +class InterpreterObject: + def __init__(self, *, subproject: T.Optional['SubProject'] = None) -> None: + self.methods: T.Dict[ + str, + T.Callable[[T.List[TYPE_var], TYPE_kwargs], TYPE_var] + ] = {} + self.operators: T.Dict[MesonOperator, 'OperatorCall'] = {} + self.trivial_operators: T.Dict[ + MesonOperator, + T.Tuple[ + T.Union[T.Type, T.Tuple[T.Type, ...]], + 'OperatorCall' + ] + ] = {} + # Current node set during a method call. This can be used as location + # when printing a warning message during a method call. + self.current_node: mparser.BaseNode = None + self.subproject = subproject or SubProject('') + + # Some default operators supported by all objects + self.operators.update({ + MesonOperator.EQUALS: self.op_equals, + MesonOperator.NOT_EQUALS: self.op_not_equals, + }) + + # The type of the object that can be printed to the user + def display_name(self) -> str: + return type(self).__name__ + + def method_call( + self, + method_name: str, + args: T.List[TYPE_var], + kwargs: TYPE_kwargs + ) -> TYPE_var: + if method_name in self.methods: + method = self.methods[method_name] + if not getattr(method, 'no-args-flattening', False): + args = flatten(args) + if not getattr(method, 'no-second-level-holder-flattening', False): + args, kwargs = resolve_second_level_holders(args, kwargs) + return method(args, kwargs) + raise InvalidCode(f'Unknown method "{method_name}" in object {self} of type {type(self).__name__}.') + + def operator_call(self, operator: MesonOperator, other: TYPE_var) -> TYPE_var: + if operator in self.trivial_operators: + op = self.trivial_operators[operator] + if op[0] is None and other is not None: + raise MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}') + if op[0] is not None and not isinstance(other, op[0]): + raise InvalidArguments(f'The `{operator.value}` operator of {self.display_name()} does not accept objects of type {type(other).__name__} ({other})') + return op[1](other) + if operator in self.operators: + return self.operators[operator](other) + raise InvalidCode(f'Object {self} of type {self.display_name()} does not support the `{operator.value}` operator.') + + # Default comparison operator support + def _throw_comp_exception(self, other: TYPE_var, opt_type: str) -> T.NoReturn: + raise InvalidArguments(textwrap.dedent( + f''' + Trying to compare values of different types ({self.display_name()}, {type(other).__name__}) using {opt_type}. + This was deprecated and undefined behavior previously and is as of 0.60.0 a hard error. + ''' + )) + + def op_equals(self, other: TYPE_var) -> bool: + # We use `type(...) == type(...)` here to enforce an *exact* match for comparison. We + # don't want comparisons to be possible where `isinstance(derived_obj, type(base_obj))` + # would pass because this comparison must never be true: `derived_obj == base_obj` + if type(self) is not type(other): + self._throw_comp_exception(other, '==') + return self == other + + def op_not_equals(self, other: TYPE_var) -> bool: + if type(self) is not type(other): + self._throw_comp_exception(other, '!=') + return self != other + +class MesonInterpreterObject(InterpreterObject): + ''' All non-elementary objects and non-object-holders should be derived from this ''' + +class MutableInterpreterObject: + ''' Dummy class to mark the object type as mutable ''' + +HoldableTypes = (HoldableObject, int, bool, str, list, dict) +TYPE_HoldableTypes = T.Union[TYPE_elementary, HoldableObject] +InterpreterObjectTypeVar = T.TypeVar('InterpreterObjectTypeVar', bound=TYPE_HoldableTypes) + +class ObjectHolder(InterpreterObject, T.Generic[InterpreterObjectTypeVar]): + def __init__(self, obj: InterpreterObjectTypeVar, interpreter: 'Interpreter') -> None: + super().__init__(subproject=interpreter.subproject) + # This causes some type checkers to assume that obj is a base + # HoldableObject, not the specialized type, so only do this assert in + # non-type checking situations + if not T.TYPE_CHECKING: + assert isinstance(obj, HoldableTypes), f'This is a bug: Trying to hold object of type `{type(obj).__name__}` that is not in `{HoldableTypes}`' + self.held_object = obj + self.interpreter = interpreter + self.env = self.interpreter.environment + + # Hide the object holder abstraction from the user + def display_name(self) -> str: + return type(self.held_object).__name__ + + # Override default comparison operators for the held object + def op_equals(self, other: TYPE_var) -> bool: + # See the comment from InterpreterObject why we are using `type()` here. + if type(self.held_object) is not type(other): + self._throw_comp_exception(other, '==') + return self.held_object == other + + def op_not_equals(self, other: TYPE_var) -> bool: + if type(self.held_object) is not type(other): + self._throw_comp_exception(other, '!=') + return self.held_object != other + + def __repr__(self) -> str: + return f'<[{type(self).__name__}] holds [{type(self.held_object).__name__}]: {self.held_object!r}>' + +class IterableObject(metaclass=ABCMeta): + '''Base class for all objects that can be iterated over in a foreach loop''' + + def iter_tuple_size(self) -> T.Optional[int]: + '''Return the size of the tuple for each iteration. Returns None if only a single value is returned.''' + raise MesonBugException(f'iter_tuple_size not implemented for {self.__class__.__name__}') + + def iter_self(self) -> T.Iterator[T.Union[TYPE_var, T.Tuple[TYPE_var, ...]]]: + raise MesonBugException(f'iter not implemented for {self.__class__.__name__}') + + def size(self) -> int: + raise MesonBugException(f'size not implemented for {self.__class__.__name__}') + +class ContextManagerObject(MesonInterpreterObject, AbstractContextManager): + def __init__(self, subproject: 'SubProject') -> None: + super().__init__(subproject=subproject) diff --git a/devtools/meson/mesonbuild/interpreterbase/decorators.py b/devtools/meson/mesonbuild/interpreterbase/decorators.py new file mode 100644 index 0000000..64e02c2 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/decorators.py @@ -0,0 +1,833 @@ +# Copyright 2013-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mesonlib, mlog +from .disabler import Disabler +from .exceptions import InterpreterException, InvalidArguments +from ._unholder import _unholder + +from dataclasses import dataclass +from functools import wraps +import abc +import itertools +import copy +import typing as T + +if T.TYPE_CHECKING: + from typing_extensions import Protocol + + from .. import mparser + from .baseobjects import InterpreterObject, TV_func, TYPE_var, TYPE_kwargs + from .interpreterbase import SubProject + from .operator import MesonOperator + + _TV_IntegerObject = T.TypeVar('_TV_IntegerObject', bound=InterpreterObject, contravariant=True) + _TV_ARG1 = T.TypeVar('_TV_ARG1', bound=TYPE_var, contravariant=True) + + class FN_Operator(Protocol[_TV_IntegerObject, _TV_ARG1]): + def __call__(s, self: _TV_IntegerObject, other: _TV_ARG1) -> TYPE_var: ... + _TV_FN_Operator = T.TypeVar('_TV_FN_Operator', bound=FN_Operator) + +def get_callee_args(wrapped_args: T.Sequence[T.Any]) -> T.Tuple['mparser.BaseNode', T.List['TYPE_var'], 'TYPE_kwargs', 'SubProject']: + # First argument could be InterpreterBase, InterpreterObject or ModuleObject. + # In the case of a ModuleObject it is the 2nd argument (ModuleState) that + # contains the needed information. + s = wrapped_args[0] + if not hasattr(s, 'current_node'): + s = wrapped_args[1] + node = s.current_node + subproject = s.subproject + args = kwargs = None + if len(wrapped_args) >= 3: + args = wrapped_args[-2] + kwargs = wrapped_args[-1] + return node, args, kwargs, subproject + +def noPosargs(f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + args = get_callee_args(wrapped_args)[1] + if args: + raise InvalidArguments('Function does not take positional arguments.') + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapped) + +def noKwargs(f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + kwargs = get_callee_args(wrapped_args)[2] + if kwargs: + raise InvalidArguments('Function does not take keyword arguments.') + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapped) + +def stringArgs(f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + args = get_callee_args(wrapped_args)[1] + if not isinstance(args, list): + mlog.debug('Not a list:', str(args)) + raise InvalidArguments('Argument not a list.') + if not all(isinstance(s, str) for s in args): + mlog.debug('Element not a string:', str(args)) + raise InvalidArguments('Arguments must be strings.') + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapped) + +def noArgsFlattening(f: TV_func) -> TV_func: + setattr(f, 'no-args-flattening', True) # noqa: B010 + return f + +def noSecondLevelHolderResolving(f: TV_func) -> TV_func: + setattr(f, 'no-second-level-holder-flattening', True) # noqa: B010 + return f + +def unholder_return(f: TV_func) -> T.Callable[..., TYPE_var]: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + res = f(*wrapped_args, **wrapped_kwargs) + return _unholder(res) + return T.cast('T.Callable[..., TYPE_var]', wrapped) + +def disablerIfNotFound(f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + kwargs = get_callee_args(wrapped_args)[2] + disabler = kwargs.pop('disabler', False) + ret = f(*wrapped_args, **wrapped_kwargs) + if disabler and not ret.found(): + return Disabler() + return ret + return T.cast('TV_func', wrapped) + +@dataclass(repr=False, eq=False) +class permittedKwargs: + permitted: T.Set[str] + + def __call__(self, f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + kwargs = get_callee_args(wrapped_args)[2] + unknowns = set(kwargs).difference(self.permitted) + if unknowns: + ustr = ', '.join([f'"{u}"' for u in sorted(unknowns)]) + raise InvalidArguments(f'Got unknown keyword arguments {ustr}') + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapped) + +def typed_operator(operator: MesonOperator, + types: T.Union[T.Type, T.Tuple[T.Type, ...]]) -> T.Callable[['_TV_FN_Operator'], '_TV_FN_Operator']: + """Decorator that does type checking for operator calls. + + The principle here is similar to typed_pos_args, however much simpler + since only one other object ever is passed + """ + def inner(f: '_TV_FN_Operator') -> '_TV_FN_Operator': + @wraps(f) + def wrapper(self: 'InterpreterObject', other: TYPE_var) -> TYPE_var: + if not isinstance(other, types): + raise InvalidArguments(f'The `{operator.value}` of {self.display_name()} does not accept objects of type {type(other).__name__} ({other})') + return f(self, other) + return T.cast('_TV_FN_Operator', wrapper) + return inner + +def unary_operator(operator: MesonOperator) -> T.Callable[['_TV_FN_Operator'], '_TV_FN_Operator']: + """Decorator that does type checking for unary operator calls. + + This decorator is for unary operators that do not take any other objects. + It should be impossible for a user to accidentally break this. Triggering + this check always indicates a bug in the Meson interpreter. + """ + def inner(f: '_TV_FN_Operator') -> '_TV_FN_Operator': + @wraps(f) + def wrapper(self: 'InterpreterObject', other: TYPE_var) -> TYPE_var: + if other is not None: + raise mesonlib.MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}') + return f(self, other) + return T.cast('_TV_FN_Operator', wrapper) + return inner + + +def typed_pos_args(name: str, *types: T.Union[T.Type, T.Tuple[T.Type, ...]], + varargs: T.Optional[T.Union[T.Type, T.Tuple[T.Type, ...]]] = None, + optargs: T.Optional[T.List[T.Union[T.Type, T.Tuple[T.Type, ...]]]] = None, + min_varargs: int = 0, max_varargs: int = 0) -> T.Callable[..., T.Any]: + """Decorator that types type checking of positional arguments. + + This supports two different models of optional arguments, the first is the + variadic argument model. Variadic arguments are a possibly bounded, + possibly unbounded number of arguments of the same type (unions are + supported). The second is the standard default value model, in this case + a number of optional arguments may be provided, but they are still + ordered, and they may have different types. + + This function does not support mixing variadic and default arguments. + + :name: The name of the decorated function (as displayed in error messages) + :varargs: They type(s) of any variadic arguments the function takes. If + None the function takes no variadic args + :min_varargs: the minimum number of variadic arguments taken + :max_varargs: the maximum number of variadic arguments taken. 0 means unlimited + :optargs: The types of any optional arguments parameters taken. If None + then no optional parameters are taken. + + Some examples of usage blow: + >>> @typed_pos_args('mod.func', str, (str, int)) + ... def func(self, state: ModuleState, args: T.Tuple[str, T.Union[str, int]], kwargs: T.Dict[str, T.Any]) -> T.Any: + ... pass + + >>> @typed_pos_args('method', str, varargs=str) + ... def method(self, node: BaseNode, args: T.Tuple[str, T.List[str]], kwargs: T.Dict[str, T.Any]) -> T.Any: + ... pass + + >>> @typed_pos_args('method', varargs=str, min_varargs=1) + ... def method(self, node: BaseNode, args: T.Tuple[T.List[str]], kwargs: T.Dict[str, T.Any]) -> T.Any: + ... pass + + >>> @typed_pos_args('method', str, optargs=[(str, int), str]) + ... def method(self, node: BaseNode, args: T.Tuple[str, T.Optional[T.Union[str, int]], T.Optional[str]], kwargs: T.Dict[str, T.Any]) -> T.Any: + ... pass + + When should you chose `typed_pos_args('name', varargs=str, + min_varargs=1)` vs `typed_pos_args('name', str, varargs=str)`? + + The answer has to do with the semantics of the function, if all of the + inputs are the same type (such as with `files()`) then the former is + correct, all of the arguments are string names of files. If the first + argument is something else the it should be separated. + """ + def inner(f: TV_func) -> TV_func: + + @wraps(f) + def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + args = get_callee_args(wrapped_args)[1] + + # These are implementation programming errors, end users should never see them. + assert isinstance(args, list), args + assert max_varargs >= 0, 'max_varags cannot be negative' + assert min_varargs >= 0, 'min_varags cannot be negative' + assert optargs is None or varargs is None, \ + 'varargs and optargs not supported together as this would be ambiguous' + + num_args = len(args) + num_types = len(types) + a_types = types + + if varargs: + min_args = num_types + min_varargs + max_args = num_types + max_varargs + if max_varargs == 0 and num_args < min_args: + raise InvalidArguments(f'{name} takes at least {min_args} arguments, but got {num_args}.') + elif max_varargs != 0 and (num_args < min_args or num_args > max_args): + raise InvalidArguments(f'{name} takes between {min_args} and {max_args} arguments, but got {num_args}.') + elif optargs: + if num_args < num_types: + raise InvalidArguments(f'{name} takes at least {num_types} arguments, but got {num_args}.') + elif num_args > num_types + len(optargs): + raise InvalidArguments(f'{name} takes at most {num_types + len(optargs)} arguments, but got {num_args}.') + # Add the number of positional arguments required + if num_args > num_types: + diff = num_args - num_types + a_types = tuple(list(types) + list(optargs[:diff])) + elif num_args != num_types: + raise InvalidArguments(f'{name} takes exactly {num_types} arguments, but got {num_args}.') + + for i, (arg, type_) in enumerate(itertools.zip_longest(args, a_types, fillvalue=varargs), start=1): + if not isinstance(arg, type_): + if isinstance(type_, tuple): + shouldbe = 'one of: {}'.format(", ".join(f'"{t.__name__}"' for t in type_)) + else: + shouldbe = f'"{type_.__name__}"' + raise InvalidArguments(f'{name} argument {i} was of type "{type(arg).__name__}" but should have been {shouldbe}') + + # Ensure that we're actually passing a tuple. + # Depending on what kind of function we're calling the length of + # wrapped_args can vary. + nargs = list(wrapped_args) + i = nargs.index(args) + if varargs: + # if we have varargs we need to split them into a separate + # tuple, as python's typing doesn't understand tuples with + # fixed elements and variadic elements, only one or the other. + # so in that case we need T.Tuple[int, str, float, T.Tuple[str, ...]] + pos = args[:len(types)] + var = list(args[len(types):]) + pos.append(var) + nargs[i] = tuple(pos) + elif optargs: + if num_args < num_types + len(optargs): + diff = num_types + len(optargs) - num_args + nargs[i] = tuple(list(args) + [None] * diff) + else: + nargs[i] = args + else: + nargs[i] = tuple(args) + return f(*nargs, **wrapped_kwargs) + + return T.cast('TV_func', wrapper) + return inner + + +class ContainerTypeInfo: + + """Container information for keyword arguments. + + For keyword arguments that are containers (list or dict), this class encodes + that information. + + :param container: the type of container + :param contains: the types the container holds + :param pairs: if the container is supposed to be of even length. + This is mainly used for interfaces that predate the addition of dictionaries, and use + `[key, value, key2, value2]` format. + :param allow_empty: Whether this container is allowed to be empty + There are some cases where containers not only must be passed, but must + not be empty, and other cases where an empty container is allowed. + """ + + def __init__(self, container: T.Type, contains: T.Union[T.Type, T.Tuple[T.Type, ...]], *, + pairs: bool = False, allow_empty: bool = True): + self.container = container + self.contains = contains + self.pairs = pairs + self.allow_empty = allow_empty + + def check(self, value: T.Any) -> bool: + """Check that a value is valid. + + :param value: A value to check + :return: True if it is valid, False otherwise + """ + if not isinstance(value, self.container): + return False + iter_ = iter(value.values()) if isinstance(value, dict) else iter(value) + if any(not isinstance(i, self.contains) for i in iter_): + return False + if self.pairs and len(value) % 2 != 0: + return False + if not value and not self.allow_empty: + return False + return True + + def check_any(self, value: T.Any) -> bool: + """Check a value should emit new/deprecated feature. + + :param value: A value to check + :return: True if any of the items in value matches, False otherwise + """ + if not isinstance(value, self.container): + return False + iter_ = iter(value.values()) if isinstance(value, dict) else iter(value) + return any(isinstance(i, self.contains) for i in iter_) + + def description(self) -> str: + """Human readable description of this container type. + + :return: string to be printed + """ + container = 'dict' if self.container is dict else 'array' + if isinstance(self.contains, tuple): + contains = ' | '.join([t.__name__ for t in self.contains]) + else: + contains = self.contains.__name__ + s = f'{container}[{contains}]' + if self.pairs: + s += ' that has even size' + if not self.allow_empty: + s += ' that cannot be empty' + return s + +_T = T.TypeVar('_T') + +class _NULL_T: + """Special null type for evolution, this is an implementation detail.""" + + +_NULL = _NULL_T() + +class KwargInfo(T.Generic[_T]): + + """A description of a keyword argument to a meson function + + This is used to describe a value to the :func:typed_kwargs function. + + :param name: the name of the parameter + :param types: A type or tuple of types that are allowed, or a :class:ContainerType + :param required: Whether this is a required keyword argument. defaults to False + :param listify: If true, then the argument will be listified before being + checked. This is useful for cases where the Meson DSL allows a scalar or + a container, but internally we only want to work with containers + :param default: A default value to use if this isn't set. defaults to None, + this may be safely set to a mutable type, as long as that type does not + itself contain mutable types, typed_kwargs will copy the default + :param since: Meson version in which this argument has been added. defaults to None + :param since_message: An extra message to pass to FeatureNew when since is triggered + :param deprecated: Meson version in which this argument has been deprecated. defaults to None + :param deprecated_message: An extra message to pass to FeatureDeprecated + when since is triggered + :param validator: A callable that does additional validation. This is mainly + intended for cases where a string is expected, but only a few specific + values are accepted. Must return None if the input is valid, or a + message if the input is invalid + :param convertor: A callable that converts the raw input value into a + different type. This is intended for cases such as the meson DSL using a + string, but the implementation using an Enum. This should not do + validation, just conversion. + :param deprecated_values: a dictionary mapping a value to the version of + meson it was deprecated in. The Value may be any valid value for this + argument. + :param since_values: a dictionary mapping a value to the version of meson it was + added in. + :param not_set_warning: A warning message that is logged if the kwarg is not + set by the user. + """ + def __init__(self, name: str, + types: T.Union[T.Type[_T], T.Tuple[T.Union[T.Type[_T], ContainerTypeInfo], ...], ContainerTypeInfo], + *, required: bool = False, listify: bool = False, + default: T.Optional[_T] = None, + since: T.Optional[str] = None, + since_message: T.Optional[str] = None, + since_values: T.Optional[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]]] = None, + deprecated: T.Optional[str] = None, + deprecated_message: T.Optional[str] = None, + deprecated_values: T.Optional[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]]] = None, + validator: T.Optional[T.Callable[[T.Any], T.Optional[str]]] = None, + convertor: T.Optional[T.Callable[[_T], object]] = None, + not_set_warning: T.Optional[str] = None): + self.name = name + self.types = types + self.required = required + self.listify = listify + self.default = default + self.since = since + self.since_message = since_message + self.since_values = since_values + self.deprecated = deprecated + self.deprecated_message = deprecated_message + self.deprecated_values = deprecated_values + self.validator = validator + self.convertor = convertor + self.not_set_warning = not_set_warning + + def evolve(self, *, + name: T.Union[str, _NULL_T] = _NULL, + required: T.Union[bool, _NULL_T] = _NULL, + listify: T.Union[bool, _NULL_T] = _NULL, + default: T.Union[_T, None, _NULL_T] = _NULL, + since: T.Union[str, None, _NULL_T] = _NULL, + since_message: T.Union[str, None, _NULL_T] = _NULL, + since_values: T.Union[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, + deprecated: T.Union[str, None, _NULL_T] = _NULL, + deprecated_message: T.Union[str, None, _NULL_T] = _NULL, + deprecated_values: T.Union[T.Dict[T.Union[_T, ContainerTypeInfo, type], T.Union[str, T.Tuple[str, str]]], None, _NULL_T] = _NULL, + validator: T.Union[T.Callable[[_T], T.Optional[str]], None, _NULL_T] = _NULL, + convertor: T.Union[T.Callable[[_T], TYPE_var], None, _NULL_T] = _NULL) -> 'KwargInfo': + """Create a shallow copy of this KwargInfo, with modifications. + + This allows us to create a new copy of a KwargInfo with modifications. + This allows us to use a shared kwarg that implements complex logic, but + has slight differences in usage, such as being added to different + functions in different versions of Meson. + + The use the _NULL special value here allows us to pass None, which has + meaning in many of these cases. _NULL itself is never stored, always + being replaced by either the copy in self, or the provided new version. + """ + return type(self)( + name if not isinstance(name, _NULL_T) else self.name, + self.types, + listify=listify if not isinstance(listify, _NULL_T) else self.listify, + required=required if not isinstance(required, _NULL_T) else self.required, + default=default if not isinstance(default, _NULL_T) else self.default, + since=since if not isinstance(since, _NULL_T) else self.since, + since_message=since_message if not isinstance(since_message, _NULL_T) else self.since_message, + since_values=since_values if not isinstance(since_values, _NULL_T) else self.since_values, + deprecated=deprecated if not isinstance(deprecated, _NULL_T) else self.deprecated, + deprecated_message=deprecated_message if not isinstance(deprecated_message, _NULL_T) else self.deprecated_message, + deprecated_values=deprecated_values if not isinstance(deprecated_values, _NULL_T) else self.deprecated_values, + validator=validator if not isinstance(validator, _NULL_T) else self.validator, + convertor=convertor if not isinstance(convertor, _NULL_T) else self.convertor, + ) + + +def typed_kwargs(name: str, *types: KwargInfo, allow_unknown: bool = False) -> T.Callable[..., T.Any]: + """Decorator for type checking keyword arguments. + + Used to wrap a meson DSL implementation function, where it checks various + things about keyword arguments, including the type, and various other + information. For non-required values it sets the value to a default, which + means the value will always be provided. + + If type is a :class:ContainerTypeInfo, then the default value will be + passed as an argument to the container initializer, making a shallow copy + + :param name: the name of the function, including the object it's attached to + (if applicable) + :param *types: KwargInfo entries for each keyword argument. + """ + def inner(f: TV_func) -> TV_func: + + def types_description(types_tuple: T.Tuple[T.Union[T.Type, ContainerTypeInfo], ...]) -> str: + candidates = [] + for t in types_tuple: + if isinstance(t, ContainerTypeInfo): + candidates.append(t.description()) + else: + candidates.append(t.__name__) + shouldbe = 'one of: ' if len(candidates) > 1 else '' + shouldbe += ', '.join(candidates) + return shouldbe + + def raw_description(t: object) -> str: + """describe a raw type (ie, one that is not a ContainerTypeInfo).""" + if isinstance(t, list): + if t: + return f"array[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t)))}]" + return 'array[]' + elif isinstance(t, dict): + if t: + return f"dict[{' | '.join(sorted(mesonlib.OrderedSet(type(v).__name__ for v in t.values())))}]" + return 'dict[]' + return type(t).__name__ + + def check_value_type(types_tuple: T.Tuple[T.Union[T.Type, ContainerTypeInfo], ...], + value: T.Any) -> bool: + for t in types_tuple: + if isinstance(t, ContainerTypeInfo): + if t.check(value): + return True + elif isinstance(value, t): + return True + return False + + @wraps(f) + def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + + def emit_feature_change(values: T.Dict[_T, T.Union[str, T.Tuple[str, str]]], feature: T.Union[T.Type['FeatureDeprecated'], T.Type['FeatureNew']]) -> None: + for n, version in values.items(): + if isinstance(version, tuple): + version, msg = version + else: + msg = None + + warning: T.Optional[str] = None + if isinstance(n, ContainerTypeInfo): + if n.check_any(value): + warning = f'of type {n.description()}' + elif isinstance(n, type): + if isinstance(value, n): + warning = f'of type {n.__name__}' + elif isinstance(value, list): + if n in value: + warning = f'value "{n}" in list' + elif isinstance(value, dict): + if n in value.keys(): + warning = f'value "{n}" in dict keys' + elif n == value: + warning = f'value "{n}"' + if warning: + feature.single_use(f'"{name}" keyword argument "{info.name}" {warning}', version, subproject, msg, location=node) + + node, _, _kwargs, subproject = get_callee_args(wrapped_args) + # Cast here, as the convertor function may place something other than a TYPE_var in the kwargs + kwargs = T.cast('T.Dict[str, object]', _kwargs) + + if not allow_unknown: + all_names = {t.name for t in types} + unknowns = set(kwargs).difference(all_names) + if unknowns: + ustr = ', '.join([f'"{u}"' for u in sorted(unknowns)]) + raise InvalidArguments(f'{name} got unknown keyword arguments {ustr}') + + for info in types: + types_tuple = info.types if isinstance(info.types, tuple) else (info.types,) + value = kwargs.get(info.name) + if value is not None: + if info.since: + feature_name = info.name + ' arg in ' + name + FeatureNew.single_use(feature_name, info.since, subproject, info.since_message, location=node) + if info.deprecated: + feature_name = info.name + ' arg in ' + name + FeatureDeprecated.single_use(feature_name, info.deprecated, subproject, info.deprecated_message, location=node) + if info.listify: + kwargs[info.name] = value = mesonlib.listify(value) + if not check_value_type(types_tuple, value): + shouldbe = types_description(types_tuple) + raise InvalidArguments(f'{name} keyword argument {info.name!r} was of type {raw_description(value)} but should have been {shouldbe}') + + if info.validator is not None: + msg = info.validator(value) + if msg is not None: + raise InvalidArguments(f'{name} keyword argument "{info.name}" {msg}') + + if info.deprecated_values is not None: + emit_feature_change(info.deprecated_values, FeatureDeprecated) + + if info.since_values is not None: + emit_feature_change(info.since_values, FeatureNew) + + elif info.required: + raise InvalidArguments(f'{name} is missing required keyword argument "{info.name}"') + else: + # set the value to the default, this ensuring all kwargs are present + # This both simplifies the typing checking and the usage + assert check_value_type(types_tuple, info.default), f'In function {name} default value of {info.name} is not a valid type, got {type(info.default)} expected {types_description(types_tuple)}' + # Create a shallow copy of the container. This allows mutable + # types to be used safely as default values + kwargs[info.name] = copy.copy(info.default) + if info.not_set_warning: + mlog.warning(info.not_set_warning) + + if info.convertor: + kwargs[info.name] = info.convertor(kwargs[info.name]) + + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapper) + return inner + + +# This cannot be a dataclass due to https://github.com/python/mypy/issues/5374 +class FeatureCheckBase(metaclass=abc.ABCMeta): + "Base class for feature version checks" + + feature_registry: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[T.Tuple[str, T.Optional['mparser.BaseNode']]]]]] + emit_notice = False + unconditional = False + + def __init__(self, feature_name: str, feature_version: str, extra_message: str = ''): + self.feature_name = feature_name # type: str + self.feature_version = feature_version # type: str + self.extra_message = extra_message # type: str + + @staticmethod + def get_target_version(subproject: str) -> str: + # Don't do any checks if project() has not been parsed yet + if subproject not in mesonlib.project_meson_versions: + return '' + return mesonlib.project_meson_versions[subproject] + + @staticmethod + @abc.abstractmethod + def check_version(target_version: str, feature_version: str) -> bool: + pass + + def use(self, subproject: 'SubProject', location: T.Optional['mparser.BaseNode'] = None) -> None: + tv = self.get_target_version(subproject) + # No target version + if tv == '' and not self.unconditional: + return + # Target version is new enough, don't warn + if self.check_version(tv, self.feature_version) and not self.emit_notice: + return + # Feature is too new for target version or we want to emit notices, register it + if subproject not in self.feature_registry: + self.feature_registry[subproject] = {self.feature_version: set()} + register = self.feature_registry[subproject] + if self.feature_version not in register: + register[self.feature_version] = set() + + feature_key = (self.feature_name, location) + if feature_key in register[self.feature_version]: + # Don't warn about the same feature multiple times + # FIXME: This is needed to prevent duplicate warnings, but also + # means we won't warn about a feature used in multiple places. + return + register[self.feature_version].add(feature_key) + # Target version is new enough, don't warn even if it is registered for notice + if self.check_version(tv, self.feature_version): + return + self.log_usage_warning(tv, location) + + @classmethod + def report(cls, subproject: str) -> None: + if subproject not in cls.feature_registry: + return + warning_str = cls.get_warning_str_prefix(cls.get_target_version(subproject)) + notice_str = cls.get_notice_str_prefix(cls.get_target_version(subproject)) + fv = cls.feature_registry[subproject] + tv = cls.get_target_version(subproject) + for version in sorted(fv.keys()): + message = ', '.join(sorted({f"'{i[0]}'" for i in fv[version]})) + if cls.check_version(tv, version): + notice_str += '\n * {}: {{{}}}'.format(version, message) + else: + warning_str += '\n * {}: {{{}}}'.format(version, message) + if '\n' in notice_str: + mlog.notice(notice_str, fatal=False) + if '\n' in warning_str: + mlog.warning(warning_str) + + def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None: + raise InterpreterException('log_usage_warning not implemented') + + @staticmethod + def get_warning_str_prefix(tv: str) -> str: + raise InterpreterException('get_warning_str_prefix not implemented') + + @staticmethod + def get_notice_str_prefix(tv: str) -> str: + raise InterpreterException('get_notice_str_prefix not implemented') + + def __call__(self, f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + node, _, _, subproject = get_callee_args(wrapped_args) + if subproject is None: + raise AssertionError(f'{wrapped_args!r}') + self.use(subproject, node) + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapped) + + @classmethod + def single_use(cls, feature_name: str, version: str, subproject: 'SubProject', + extra_message: str = '', location: T.Optional['mparser.BaseNode'] = None) -> None: + """Oneline version that instantiates and calls use().""" + cls(feature_name, version, extra_message).use(subproject, location) + + +class FeatureNew(FeatureCheckBase): + """Checks for new features""" + + # Class variable, shared across all instances + # + # Format: {subproject: {feature_version: set(feature_names)}} + feature_registry = {} + + @staticmethod + def check_version(target_version: str, feature_version: str) -> bool: + return mesonlib.version_compare_condition_with_min(target_version, feature_version) + + @staticmethod + def get_warning_str_prefix(tv: str) -> str: + return f'Project specifies a minimum meson_version \'{tv}\' but uses features which were added in newer versions:' + + @staticmethod + def get_notice_str_prefix(tv: str) -> str: + return '' + + def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None: + args = [ + 'Project targets', f"'{tv}'", + 'but uses feature introduced in', + f"'{self.feature_version}':", + f'{self.feature_name}.', + ] + if self.extra_message: + args.append(self.extra_message) + mlog.warning(*args, location=location) + +class FeatureDeprecated(FeatureCheckBase): + """Checks for deprecated features""" + + # Class variable, shared across all instances + # + # Format: {subproject: {feature_version: set(feature_names)}} + feature_registry = {} + emit_notice = True + + @staticmethod + def check_version(target_version: str, feature_version: str) -> bool: + # For deprecation checks we need to return the inverse of FeatureNew checks + return not mesonlib.version_compare_condition_with_min(target_version, feature_version) + + @staticmethod + def get_warning_str_prefix(tv: str) -> str: + return 'Deprecated features used:' + + @staticmethod + def get_notice_str_prefix(tv: str) -> str: + return 'Future-deprecated features used:' + + def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None: + args = [ + 'Project targets', f"'{tv}'", + 'but uses feature deprecated since', + f"'{self.feature_version}':", + f'{self.feature_name}.', + ] + if self.extra_message: + args.append(self.extra_message) + mlog.warning(*args, location=location) + + +class FeatureBroken(FeatureCheckBase): + """Checks for broken features""" + + # Class variable, shared across all instances + # + # Format: {subproject: {feature_version: set(feature_names)}} + feature_registry = {} + unconditional = True + + @staticmethod + def check_version(target_version: str, feature_version: str) -> bool: + # always warn for broken stuff + return False + + @staticmethod + def get_warning_str_prefix(tv: str) -> str: + return 'Broken features used:' + + @staticmethod + def get_notice_str_prefix(tv: str) -> str: + return '' + + def log_usage_warning(self, tv: str, location: T.Optional['mparser.BaseNode']) -> None: + args = [ + 'Project uses feature that was always broken,', + 'and is now deprecated since', + f"'{self.feature_version}':", + f'{self.feature_name}.', + ] + if self.extra_message: + args.append(self.extra_message) + mlog.deprecation(*args, location=location) + + +# This cannot be a dataclass due to https://github.com/python/mypy/issues/5374 +class FeatureCheckKwargsBase(metaclass=abc.ABCMeta): + + @property + @abc.abstractmethod + def feature_check_class(self) -> T.Type[FeatureCheckBase]: + pass + + def __init__(self, feature_name: str, feature_version: str, + kwargs: T.List[str], extra_message: T.Optional[str] = None): + self.feature_name = feature_name + self.feature_version = feature_version + self.kwargs = kwargs + self.extra_message = extra_message + + def __call__(self, f: TV_func) -> TV_func: + @wraps(f) + def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: + node, _, kwargs, subproject = get_callee_args(wrapped_args) + if subproject is None: + raise AssertionError(f'{wrapped_args!r}') + for arg in self.kwargs: + if arg not in kwargs: + continue + name = arg + ' arg in ' + self.feature_name + self.feature_check_class.single_use( + name, self.feature_version, subproject, self.extra_message, node) + return f(*wrapped_args, **wrapped_kwargs) + return T.cast('TV_func', wrapped) + +class FeatureNewKwargs(FeatureCheckKwargsBase): + feature_check_class = FeatureNew + +class FeatureDeprecatedKwargs(FeatureCheckKwargsBase): + feature_check_class = FeatureDeprecated diff --git a/devtools/meson/mesonbuild/interpreterbase/disabler.py b/devtools/meson/mesonbuild/interpreterbase/disabler.py new file mode 100644 index 0000000..182bb62 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/disabler.py @@ -0,0 +1,45 @@ +# Copyright 2013-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import typing as T + +from .baseobjects import MesonInterpreterObject + +if T.TYPE_CHECKING: + from .baseobjects import TYPE_var, TYPE_kwargs + +class Disabler(MesonInterpreterObject): + def method_call(self, method_name: str, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> TYPE_var: + if method_name == 'found': + return False + return Disabler() + +def _is_arg_disabled(arg: T.Any) -> bool: + if isinstance(arg, Disabler): + return True + if isinstance(arg, list): + for i in arg: + if _is_arg_disabled(i): + return True + return False + +def is_disabled(args: T.Sequence[T.Any], kwargs: T.Dict[str, T.Any]) -> bool: + for i in args: + if _is_arg_disabled(i): + return True + for i in kwargs.values(): + if _is_arg_disabled(i): + return True + return False diff --git a/devtools/meson/mesonbuild/interpreterbase/exceptions.py b/devtools/meson/mesonbuild/interpreterbase/exceptions.py new file mode 100644 index 0000000..cdbe0fb --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/exceptions.py @@ -0,0 +1,33 @@ +# Copyright 2013-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ..mesonlib import MesonException + +class InterpreterException(MesonException): + pass + +class InvalidCode(InterpreterException): + pass + +class InvalidArguments(InterpreterException): + pass + +class SubdirDoneRequest(BaseException): + pass + +class ContinueRequest(BaseException): + pass + +class BreakRequest(BaseException): + pass diff --git a/devtools/meson/mesonbuild/interpreterbase/helpers.py b/devtools/meson/mesonbuild/interpreterbase/helpers.py new file mode 100644 index 0000000..2196b4e --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/helpers.py @@ -0,0 +1,56 @@ +# Copyright 2013-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mesonlib, mparser +from .exceptions import InterpreterException + +import collections.abc +import typing as T + +if T.TYPE_CHECKING: + from .baseobjects import TYPE_var, TYPE_kwargs + +def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var']: + if isinstance(args, mparser.StringNode): + assert isinstance(args.value, str) + return [args.value] + if not isinstance(args, collections.abc.Sequence): + return [args] + result: T.List['TYPE_var'] = [] + for a in args: + if isinstance(a, list): + rest = flatten(a) + result = result + rest + elif isinstance(a, mparser.StringNode): + result.append(a.value) + else: + result.append(a) + return result + +def resolve_second_level_holders(args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.Tuple[T.List['TYPE_var'], 'TYPE_kwargs']: + def resolver(arg: 'TYPE_var') -> 'TYPE_var': + if isinstance(arg, list): + return [resolver(x) for x in arg] + if isinstance(arg, dict): + return {k: resolver(v) for k, v in arg.items()} + if isinstance(arg, mesonlib.SecondLevelHolder): + return arg.get_default_object() + return arg + return [resolver(x) for x in args], {k: resolver(v) for k, v in kwargs.items()} + +def default_resolve_key(key: mparser.BaseNode) -> str: + if not isinstance(key, mparser.IdNode): + raise InterpreterException('Invalid kwargs format.') + return key.value diff --git a/devtools/meson/mesonbuild/interpreterbase/interpreterbase.py b/devtools/meson/mesonbuild/interpreterbase/interpreterbase.py new file mode 100644 index 0000000..5f854d0 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/interpreterbase.py @@ -0,0 +1,666 @@ +# Copyright 2016-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. +from __future__ import annotations + +from .. import environment, mparser, mesonlib + +from .baseobjects import ( + InterpreterObject, + MesonInterpreterObject, + MutableInterpreterObject, + InterpreterObjectTypeVar, + ObjectHolder, + IterableObject, + ContextManagerObject, + + HoldableTypes, +) + +from .exceptions import ( + BreakRequest, + ContinueRequest, + InterpreterException, + InvalidArguments, + InvalidCode, + MesonException, + SubdirDoneRequest, +) + +from .decorators import FeatureNew +from .disabler import Disabler, is_disabled +from .helpers import default_resolve_key, flatten, resolve_second_level_holders +from .operator import MesonOperator +from ._unholder import _unholder + +import os, copy, re, pathlib +import typing as T +import textwrap + +if T.TYPE_CHECKING: + from .baseobjects import SubProject, TYPE_kwargs, TYPE_var + from ..interpreter import Interpreter + + HolderMapType = T.Dict[ + T.Union[ + T.Type[mesonlib.HoldableObject], + T.Type[int], + T.Type[bool], + T.Type[str], + T.Type[list], + T.Type[dict], + ], + # For some reason, this has to be a callable and can't just be ObjectHolder[InterpreterObjectTypeVar] + T.Callable[[InterpreterObjectTypeVar, 'Interpreter'], ObjectHolder[InterpreterObjectTypeVar]] + ] + + FunctionType = T.Dict[ + str, + T.Callable[[mparser.BaseNode, T.List[TYPE_var], T.Dict[str, TYPE_var]], TYPE_var] + ] + + +class InvalidCodeOnVoid(InvalidCode): + + def __init__(self, op_type: str) -> None: + super().__init__(f'Cannot perform {op_type!r} operation on void statement.') + + +class InterpreterBase: + def __init__(self, source_root: str, subdir: str, subproject: 'SubProject'): + self.source_root = source_root + self.funcs: FunctionType = {} + self.builtin: T.Dict[str, InterpreterObject] = {} + # Holder maps store a mapping from an HoldableObject to a class ObjectHolder + self.holder_map: HolderMapType = {} + self.bound_holder_map: HolderMapType = {} + self.subdir = subdir + self.root_subdir = subdir + self.subproject = subproject + self.variables: T.Dict[str, InterpreterObject] = {} + self.argument_depth = 0 + self.current_lineno = -1 + # Current node set during a function call. This can be used as location + # when printing a warning message during a method call. + self.current_node = None # type: mparser.BaseNode + # This is set to `version_string` when this statement is evaluated: + # meson.version().compare_version(version_string) + # If it was part of a if-clause, it is used to temporally override the + # current meson version target within that if-block. + self.tmp_meson_version = None # type: T.Optional[str] + + def handle_meson_version_from_ast(self, strict: bool = True) -> None: + # do nothing in an AST interpreter + return + + def load_root_meson_file(self) -> None: + mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename) + if not os.path.isfile(mesonfile): + raise InvalidArguments(f'Missing Meson file in {mesonfile}') + with open(mesonfile, encoding='utf-8') as mf: + code = mf.read() + if code.isspace(): + raise InvalidCode('Builder file is empty.') + assert isinstance(code, str) + try: + self.ast = mparser.Parser(code, mesonfile).parse() + self.handle_meson_version_from_ast() + except mparser.ParseException as me: + me.file = mesonfile + # try to detect parser errors from new syntax added by future + # meson versions, and just tell the user to update meson + self.ast = me.ast + self.handle_meson_version_from_ast() + raise me + + def parse_project(self) -> None: + """ + Parses project() and initializes languages, compilers etc. Do this + early because we need this before we parse the rest of the AST. + """ + self.evaluate_codeblock(self.ast, end=1) + + def sanity_check_ast(self) -> None: + if not isinstance(self.ast, mparser.CodeBlockNode): + raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.') + if not self.ast.lines: + raise InvalidCode('No statements in code.') + first = self.ast.lines[0] + if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': + p = pathlib.Path(self.source_root).resolve() + found = p + for parent in p.parents: + if (parent / 'meson.build').is_file(): + with open(parent / 'meson.build', encoding='utf-8') as f: + if f.readline().startswith('project('): + found = parent + break + else: + break + + error = 'first statement must be a call to project()' + if found != p: + raise InvalidCode(f'Not the project root: {error}\n\nDid you mean to run meson from the directory: "{found}"?') + else: + raise InvalidCode(f'Invalid source tree: {error}') + + def run(self) -> None: + # Evaluate everything after the first line, which is project() because + # we already parsed that in self.parse_project() + try: + self.evaluate_codeblock(self.ast, start=1) + except SubdirDoneRequest: + pass + + def evaluate_codeblock(self, node: mparser.CodeBlockNode, start: int = 0, end: T.Optional[int] = None) -> None: + if node is None: + return + if not isinstance(node, mparser.CodeBlockNode): + e = InvalidCode('Tried to execute a non-codeblock. Possibly a bug in the parser.') + e.lineno = node.lineno + e.colno = node.colno + raise e + statements = node.lines[start:end] + i = 0 + while i < len(statements): + cur = statements[i] + try: + self.current_lineno = cur.lineno + self.evaluate_statement(cur) + except Exception as e: + if getattr(e, 'lineno', None) is None: + # We are doing the equivalent to setattr here and mypy does not like it + # NOTE: self.current_node is continually updated during processing + e.lineno = self.current_node.lineno # type: ignore + e.colno = self.current_node.colno # type: ignore + e.file = os.path.join(self.source_root, self.subdir, environment.build_filename) # type: ignore + raise e + i += 1 # In THE FUTURE jump over blocks and stuff. + + def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObject]: + self.current_node = cur + if isinstance(cur, mparser.FunctionNode): + return self.function_call(cur) + elif isinstance(cur, mparser.AssignmentNode): + self.assignment(cur) + elif isinstance(cur, mparser.MethodNode): + return self.method_call(cur) + elif isinstance(cur, mparser.StringNode): + return self._holderify(cur.value) + elif isinstance(cur, mparser.BooleanNode): + return self._holderify(cur.value) + elif isinstance(cur, mparser.IfClauseNode): + return self.evaluate_if(cur) + elif isinstance(cur, mparser.IdNode): + return self.get_variable(cur.value) + elif isinstance(cur, mparser.ComparisonNode): + return self.evaluate_comparison(cur) + elif isinstance(cur, mparser.ArrayNode): + return self.evaluate_arraystatement(cur) + elif isinstance(cur, mparser.DictNode): + return self.evaluate_dictstatement(cur) + elif isinstance(cur, mparser.NumberNode): + return self._holderify(cur.value) + elif isinstance(cur, mparser.AndNode): + return self.evaluate_andstatement(cur) + elif isinstance(cur, mparser.OrNode): + return self.evaluate_orstatement(cur) + elif isinstance(cur, mparser.NotNode): + return self.evaluate_notstatement(cur) + elif isinstance(cur, mparser.UMinusNode): + return self.evaluate_uminusstatement(cur) + elif isinstance(cur, mparser.ArithmeticNode): + return self.evaluate_arithmeticstatement(cur) + elif isinstance(cur, mparser.ForeachClauseNode): + self.evaluate_foreach(cur) + elif isinstance(cur, mparser.PlusAssignmentNode): + self.evaluate_plusassign(cur) + elif isinstance(cur, mparser.IndexNode): + return self.evaluate_indexing(cur) + elif isinstance(cur, mparser.TernaryNode): + return self.evaluate_ternary(cur) + elif isinstance(cur, mparser.FormatStringNode): + if isinstance(cur, mparser.MultilineFormatStringNode): + return self.evaluate_multiline_fstring(cur) + else: + return self.evaluate_fstring(cur) + elif isinstance(cur, mparser.ContinueNode): + raise ContinueRequest() + elif isinstance(cur, mparser.BreakNode): + raise BreakRequest() + elif isinstance(cur, mparser.TestCaseClauseNode): + return self.evaluate_testcase(cur) + else: + raise InvalidCode("Unknown statement.") + return None + + def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> InterpreterObject: + (arguments, kwargs) = self.reduce_arguments(cur.args) + if len(kwargs) > 0: + raise InvalidCode('Keyword arguments are invalid in array construction.') + return self._holderify([_unholder(x) for x in arguments]) + + @FeatureNew('dict', '0.47.0') + def evaluate_dictstatement(self, cur: mparser.DictNode) -> InterpreterObject: + def resolve_key(key: mparser.BaseNode) -> str: + if not isinstance(key, mparser.StringNode): + FeatureNew.single_use('Dictionary entry using non literal key', '0.53.0', self.subproject) + key_holder = self.evaluate_statement(key) + if key_holder is None: + raise InvalidArguments('Key cannot be void.') + str_key = _unholder(key_holder) + if not isinstance(str_key, str): + raise InvalidArguments('Key must be a string') + return str_key + arguments, kwargs = self.reduce_arguments(cur.args, key_resolver=resolve_key, duplicate_key_error='Duplicate dictionary key: {}') + assert not arguments + return self._holderify({k: _unholder(v) for k, v in kwargs.items()}) + + def evaluate_notstatement(self, cur: mparser.NotNode) -> InterpreterObject: + v = self.evaluate_statement(cur.value) + if v is None: + raise InvalidCodeOnVoid('not') + if isinstance(v, Disabler): + return v + return self._holderify(v.operator_call(MesonOperator.NOT, None)) + + def evaluate_if(self, node: mparser.IfClauseNode) -> T.Optional[Disabler]: + assert isinstance(node, mparser.IfClauseNode) + for i in node.ifs: + # Reset self.tmp_meson_version to know if it gets set during this + # statement evaluation. + self.tmp_meson_version = None + result = self.evaluate_statement(i.condition) + if result is None: + raise InvalidCodeOnVoid('if') + if isinstance(result, Disabler): + return result + if not isinstance(result, InterpreterObject): + raise mesonlib.MesonBugException(f'Argument to if ({result}) is not an InterpreterObject but {type(result).__name__}.') + res = result.operator_call(MesonOperator.BOOL, None) + if not isinstance(res, bool): + raise InvalidCode(f'If clause {result!r} does not evaluate to true or false.') + if res: + prev_meson_version = mesonlib.project_meson_versions[self.subproject] + if self.tmp_meson_version: + mesonlib.project_meson_versions[self.subproject] = self.tmp_meson_version + try: + self.evaluate_codeblock(i.block) + finally: + mesonlib.project_meson_versions[self.subproject] = prev_meson_version + return None + if not isinstance(node.elseblock, mparser.EmptyNode): + self.evaluate_codeblock(node.elseblock) + return None + + def evaluate_testcase(self, node: mparser.TestCaseClauseNode) -> T.Optional[Disabler]: + result = self.evaluate_statement(node.condition) + if isinstance(result, Disabler): + return result + if not isinstance(result, ContextManagerObject): + raise InvalidCode(f'testcase clause {result!r} does not evaluate to a context manager.') + with result: + self.evaluate_codeblock(node.block) + return None + + def evaluate_comparison(self, node: mparser.ComparisonNode) -> InterpreterObject: + val1 = self.evaluate_statement(node.left) + if val1 is None: + raise MesonException('Cannot compare a void statement on the left-hand side') + if isinstance(val1, Disabler): + return val1 + val2 = self.evaluate_statement(node.right) + if val2 is None: + raise MesonException('Cannot compare a void statement on the right-hand side') + if isinstance(val2, Disabler): + return val2 + + # New code based on InterpreterObjects + operator = { + 'in': MesonOperator.IN, + 'notin': MesonOperator.NOT_IN, + '==': MesonOperator.EQUALS, + '!=': MesonOperator.NOT_EQUALS, + '>': MesonOperator.GREATER, + '<': MesonOperator.LESS, + '>=': MesonOperator.GREATER_EQUALS, + '<=': MesonOperator.LESS_EQUALS, + }[node.ctype] + + # Check if the arguments should be reversed for simplicity (this essentially converts `in` to `contains`) + if operator in (MesonOperator.IN, MesonOperator.NOT_IN): + val1, val2 = val2, val1 + + val1.current_node = node + return self._holderify(val1.operator_call(operator, _unholder(val2))) + + def evaluate_andstatement(self, cur: mparser.AndNode) -> InterpreterObject: + l = self.evaluate_statement(cur.left) + if l is None: + raise MesonException('Cannot compare a void statement on the left-hand side') + if isinstance(l, Disabler): + return l + l_bool = l.operator_call(MesonOperator.BOOL, None) + if not l_bool: + return self._holderify(l_bool) + r = self.evaluate_statement(cur.right) + if r is None: + raise MesonException('Cannot compare a void statement on the right-hand side') + if isinstance(r, Disabler): + return r + return self._holderify(r.operator_call(MesonOperator.BOOL, None)) + + def evaluate_orstatement(self, cur: mparser.OrNode) -> InterpreterObject: + l = self.evaluate_statement(cur.left) + if l is None: + raise MesonException('Cannot compare a void statement on the left-hand side') + if isinstance(l, Disabler): + return l + l_bool = l.operator_call(MesonOperator.BOOL, None) + if l_bool: + return self._holderify(l_bool) + r = self.evaluate_statement(cur.right) + if r is None: + raise MesonException('Cannot compare a void statement on the right-hand side') + if isinstance(r, Disabler): + return r + return self._holderify(r.operator_call(MesonOperator.BOOL, None)) + + def evaluate_uminusstatement(self, cur: mparser.UMinusNode) -> InterpreterObject: + v = self.evaluate_statement(cur.value) + if v is None: + raise InvalidCodeOnVoid('unary minus') + if isinstance(v, Disabler): + return v + v.current_node = cur + return self._holderify(v.operator_call(MesonOperator.UMINUS, None)) + + def evaluate_arithmeticstatement(self, cur: mparser.ArithmeticNode) -> InterpreterObject: + l = self.evaluate_statement(cur.left) + if isinstance(l, Disabler): + return l + r = self.evaluate_statement(cur.right) + if isinstance(r, Disabler): + return r + if l is None or r is None: + raise InvalidCodeOnVoid(cur.operation) + + mapping: T.Dict[str, MesonOperator] = { + 'add': MesonOperator.PLUS, + 'sub': MesonOperator.MINUS, + 'mul': MesonOperator.TIMES, + 'div': MesonOperator.DIV, + 'mod': MesonOperator.MOD, + } + l.current_node = cur + res = l.operator_call(mapping[cur.operation], _unholder(r)) + return self._holderify(res) + + def evaluate_ternary(self, node: mparser.TernaryNode) -> T.Optional[InterpreterObject]: + assert isinstance(node, mparser.TernaryNode) + result = self.evaluate_statement(node.condition) + if result is None: + raise MesonException('Cannot use a void statement as condition for ternary operator.') + if isinstance(result, Disabler): + return result + result.current_node = node + result_bool = result.operator_call(MesonOperator.BOOL, None) + if result_bool: + return self.evaluate_statement(node.trueblock) + else: + return self.evaluate_statement(node.falseblock) + + @FeatureNew('multiline format strings', '0.63.0') + def evaluate_multiline_fstring(self, node: mparser.MultilineFormatStringNode) -> InterpreterObject: + return self.evaluate_fstring(node) + + @FeatureNew('format strings', '0.58.0') + def evaluate_fstring(self, node: mparser.FormatStringNode) -> InterpreterObject: + assert isinstance(node, mparser.FormatStringNode) + + def replace(match: T.Match[str]) -> str: + var = str(match.group(1)) + try: + val = _unholder(self.variables[var]) + if not isinstance(val, (str, int, float, bool)): + raise InvalidCode(f'Identifier "{var}" does not name a formattable variable ' + + '(has to be an integer, a string, a floating point number or a boolean).') + + return str(val) + except KeyError: + raise InvalidCode(f'Identifier "{var}" does not name a variable.') + + res = re.sub(r'@([_a-zA-Z][_0-9a-zA-Z]*)@', replace, node.value) + return self._holderify(res) + + def evaluate_foreach(self, node: mparser.ForeachClauseNode) -> None: + assert isinstance(node, mparser.ForeachClauseNode) + items = self.evaluate_statement(node.items) + if not isinstance(items, IterableObject): + raise InvalidArguments('Items of foreach loop do not support iterating') + + tsize = items.iter_tuple_size() + if len(node.varnames) != (tsize or 1): + raise InvalidArguments(f'Foreach expects exactly {tsize or 1} variables for iterating over objects of type {items.display_name()}') + + for i in items.iter_self(): + if tsize is None: + if isinstance(i, tuple): + raise mesonlib.MesonBugException(f'Iteration of {items} returned a tuple even though iter_tuple_size() is None') + self.set_variable(node.varnames[0], self._holderify(i)) + else: + if not isinstance(i, tuple): + raise mesonlib.MesonBugException(f'Iteration of {items} did not return a tuple even though iter_tuple_size() is {tsize}') + if len(i) != tsize: + raise mesonlib.MesonBugException(f'Iteration of {items} did not return a tuple even though iter_tuple_size() is {tsize}') + for j in range(tsize): + self.set_variable(node.varnames[j], self._holderify(i[j])) + try: + self.evaluate_codeblock(node.block) + except ContinueRequest: + continue + except BreakRequest: + break + + def evaluate_plusassign(self, node: mparser.PlusAssignmentNode) -> None: + assert isinstance(node, mparser.PlusAssignmentNode) + varname = node.var_name + addition = self.evaluate_statement(node.value) + if addition is None: + raise InvalidCodeOnVoid('plus assign') + + # Remember that all variables are immutable. We must always create a + # full new variable and then assign it. + old_variable = self.get_variable(varname) + old_variable.current_node = node + new_value = self._holderify(old_variable.operator_call(MesonOperator.PLUS, _unholder(addition))) + self.set_variable(varname, new_value) + + def evaluate_indexing(self, node: mparser.IndexNode) -> InterpreterObject: + assert isinstance(node, mparser.IndexNode) + iobject = self.evaluate_statement(node.iobject) + if iobject is None: + raise InterpreterException('Tried to evaluate indexing on void.') + if isinstance(iobject, Disabler): + return iobject + index_holder = self.evaluate_statement(node.index) + if index_holder is None: + raise InvalidArguments('Cannot use void statement as index.') + index = _unholder(index_holder) + + iobject.current_node = node + return self._holderify(iobject.operator_call(MesonOperator.INDEX, index)) + + def function_call(self, node: mparser.FunctionNode) -> T.Optional[InterpreterObject]: + func_name = node.func_name + (h_posargs, h_kwargs) = self.reduce_arguments(node.args) + (posargs, kwargs) = self._unholder_args(h_posargs, h_kwargs) + if is_disabled(posargs, kwargs) and func_name not in {'get_variable', 'set_variable', 'unset_variable', 'is_disabler'}: + return Disabler() + if func_name in self.funcs: + func = self.funcs[func_name] + func_args = posargs + if not getattr(func, 'no-args-flattening', False): + func_args = flatten(posargs) + if not getattr(func, 'no-second-level-holder-flattening', False): + func_args, kwargs = resolve_second_level_holders(func_args, kwargs) + self.current_node = node + res = func(node, func_args, kwargs) + return self._holderify(res) if res is not None else None + else: + self.unknown_function_called(func_name) + return None + + def method_call(self, node: mparser.MethodNode) -> T.Optional[InterpreterObject]: + invocable = node.source_object + obj: T.Optional[InterpreterObject] + if isinstance(invocable, mparser.IdNode): + object_display_name = f'variable "{invocable.value}"' + obj = self.get_variable(invocable.value) + else: + object_display_name = invocable.__class__.__name__ + obj = self.evaluate_statement(invocable) + method_name = node.name + (h_args, h_kwargs) = self.reduce_arguments(node.args) + (args, kwargs) = self._unholder_args(h_args, h_kwargs) + if is_disabled(args, kwargs): + return Disabler() + if not isinstance(obj, InterpreterObject): + raise InvalidArguments(f'{object_display_name} is not callable.') + # TODO: InterpreterBase **really** shouldn't be in charge of checking this + if method_name == 'extract_objects': + if isinstance(obj, ObjectHolder): + self.validate_extraction(obj.held_object) + elif not isinstance(obj, Disabler): + raise InvalidArguments(f'Invalid operation "extract_objects" on {object_display_name} of type {type(obj).__name__}') + obj.current_node = self.current_node = node + res = obj.method_call(method_name, args, kwargs) + return self._holderify(res) if res is not None else None + + def _holderify(self, res: T.Union[TYPE_var, InterpreterObject]) -> InterpreterObject: + if isinstance(res, HoldableTypes): + # Always check for an exact match first. + cls = self.holder_map.get(type(res), None) + if cls is not None: + # Casts to Interpreter are required here since an assertion would + # not work for the `ast` module. + return cls(res, T.cast('Interpreter', self)) + # Try the boundary types next. + for typ, cls in self.bound_holder_map.items(): + if isinstance(res, typ): + return cls(res, T.cast('Interpreter', self)) + raise mesonlib.MesonBugException(f'Object {res} of type {type(res).__name__} is neither in self.holder_map nor self.bound_holder_map.') + elif isinstance(res, ObjectHolder): + raise mesonlib.MesonBugException(f'Returned object {res} of type {type(res).__name__} is an object holder.') + elif isinstance(res, MesonInterpreterObject): + return res + raise mesonlib.MesonBugException(f'Unknown returned object {res} of type {type(res).__name__} in the parameters.') + + def _unholder_args(self, + args: T.List[InterpreterObject], + kwargs: T.Dict[str, InterpreterObject]) -> T.Tuple[T.List[TYPE_var], TYPE_kwargs]: + return [_unholder(x) for x in args], {k: _unholder(v) for k, v in kwargs.items()} + + def unknown_function_called(self, func_name: str) -> None: + raise InvalidCode(f'Unknown function "{func_name}".') + + def reduce_arguments( + self, + args: mparser.ArgumentNode, + key_resolver: T.Callable[[mparser.BaseNode], str] = default_resolve_key, + duplicate_key_error: T.Optional[str] = None, + ) -> T.Tuple[ + T.List[InterpreterObject], + T.Dict[str, InterpreterObject] + ]: + assert isinstance(args, mparser.ArgumentNode) + if args.incorrect_order(): + raise InvalidArguments('All keyword arguments must be after positional arguments.') + self.argument_depth += 1 + reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments] + if any(x is None for x in reduced_pos): + raise InvalidArguments('At least one value in the arguments is void.') + reduced_kw: T.Dict[str, InterpreterObject] = {} + for key, val in args.kwargs.items(): + reduced_key = key_resolver(key) + assert isinstance(val, mparser.BaseNode) + reduced_val = self.evaluate_statement(val) + if reduced_val is None: + raise InvalidArguments(f'Value of key {reduced_key} is void.') + self.current_node = key + if duplicate_key_error and reduced_key in reduced_kw: + raise InvalidArguments(duplicate_key_error.format(reduced_key)) + reduced_kw[reduced_key] = reduced_val + self.argument_depth -= 1 + final_kw = self.expand_default_kwargs(reduced_kw) + return reduced_pos, final_kw + + def expand_default_kwargs(self, kwargs: T.Dict[str, T.Optional[InterpreterObject]]) -> T.Dict[str, T.Optional[InterpreterObject]]: + if 'kwargs' not in kwargs: + return kwargs + to_expand = _unholder(kwargs.pop('kwargs')) + if not isinstance(to_expand, dict): + raise InterpreterException('Value of "kwargs" must be dictionary.') + if 'kwargs' in to_expand: + raise InterpreterException('Kwargs argument must not contain a "kwargs" entry. Points for thinking meta, though. :P') + for k, v in to_expand.items(): + if k in kwargs: + raise InterpreterException(f'Entry "{k}" defined both as a keyword argument and in a "kwarg" entry.') + kwargs[k] = self._holderify(v) + return kwargs + + def assignment(self, node: mparser.AssignmentNode) -> None: + assert isinstance(node, mparser.AssignmentNode) + if self.argument_depth != 0: + raise InvalidArguments(textwrap.dedent('''\ + Tried to assign values inside an argument list. + To specify a keyword argument, use : instead of =. + ''')) + var_name = node.var_name + if not isinstance(var_name, str): + raise InvalidArguments('Tried to assign value to a non-variable.') + value = self.evaluate_statement(node.value) + # For mutable objects we need to make a copy on assignment + if isinstance(value, MutableInterpreterObject): + value = copy.deepcopy(value) + self.set_variable(var_name, value) + + def set_variable(self, varname: str, variable: T.Union[TYPE_var, InterpreterObject], *, holderify: bool = False) -> None: + if variable is None: + raise InvalidCode('Can not assign void to variable.') + if holderify: + variable = self._holderify(variable) + else: + # Ensure that we are always storing ObjectHolders + if not isinstance(variable, InterpreterObject): + raise mesonlib.MesonBugException(f'set_variable in InterpreterBase called with a non InterpreterObject {variable} of type {type(variable).__name__}') + if not isinstance(varname, str): + raise InvalidCode('First argument to set_variable must be a string.') + if re.match('[_a-zA-Z][_0-9a-zA-Z]*$', varname) is None: + raise InvalidCode('Invalid variable name: ' + varname) + if varname in self.builtin: + raise InvalidCode(f'Tried to overwrite internal variable "{varname}"') + self.variables[varname] = variable + + def get_variable(self, varname: str) -> InterpreterObject: + if varname in self.builtin: + return self.builtin[varname] + if varname in self.variables: + return self.variables[varname] + raise InvalidCode(f'Unknown variable "{varname}".') + + def validate_extraction(self, buildtarget: mesonlib.HoldableObject) -> None: + raise InterpreterException('validate_extraction is not implemented in this context (please file a bug)') diff --git a/devtools/meson/mesonbuild/interpreterbase/operator.py b/devtools/meson/mesonbuild/interpreterbase/operator.py new file mode 100644 index 0000000..5dec8d0 --- /dev/null +++ b/devtools/meson/mesonbuild/interpreterbase/operator.py @@ -0,0 +1,32 @@ +# SPDX-license-identifier: Apache-2.0 + +from enum import Enum + +class MesonOperator(Enum): + # Arithmetic + PLUS = '+' + MINUS = '-' + TIMES = '*' + DIV = '/' + MOD = '%' + + UMINUS = 'uminus' + + # Logic + NOT = 'not' + + # Should return the boolsche interpretation of the value (`'' == false` for instance) + BOOL = 'bool()' + + # Comparison + EQUALS = '==' + NOT_EQUALS = '!=' + GREATER = '>' + LESS = '<' + GREATER_EQUALS = '>=' + LESS_EQUALS = '<=' + + # Container + IN = 'in' + NOT_IN = 'not in' + INDEX = '[]' diff --git a/devtools/meson/mesonbuild/linkers/__init__.py b/devtools/meson/mesonbuild/linkers/__init__.py new file mode 100644 index 0000000..7c35694 --- /dev/null +++ b/devtools/meson/mesonbuild/linkers/__init__.py @@ -0,0 +1,32 @@ +# Copyright 2012-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from .base import ArLikeLinker, RSPFileSyntax +from .detect import ( + defaults, + guess_win_linker, + guess_nix_linker, +) + +__all__ = [ + # base.py + 'ArLikeLinker', + 'RSPFileSyntax', + + # detect.py + 'defaults', + 'guess_win_linker', + 'guess_nix_linker', +] diff --git a/devtools/meson/mesonbuild/linkers/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/linkers/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94255139fe4587cc433f6c16bf2b09a62e1b7bc0 GIT binary patch literal 375 zcmZ9I&q@O^5XO`2pRUq{J@^uP5xjU15fu>+MWnqgfw1kQH8k0kWLMiq@KJmRZ@xvY zp1gVX)FOx>ffPooq#8jsBjw%)#m6P{;|n`cYdKNPT3Vk^XLr|1%h|T+>P;E> z4CJ!zb?1Ds>ZNnyNi{+b=AF{0%}%ilZ(58?Y#b1R+7xkHWxjNw>ANi`);Ov6m>m%-9Ey9d?*S6YmBVF4JocBrtA7VN#glbeL b#Nor%XQ!rxUdyurkGnCVpa&VFEW)PW8nt5U literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/linkers/__pycache__/base.cpython-37.pyc b/devtools/meson/mesonbuild/linkers/__pycache__/base.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c6e32ccab31f5a9292f0baaa9edc12cd5610b6c8 GIT binary patch literal 1452 zcmZuxOK;pZ5GF;fR^EqSX9CPBE2hHOKnKX zs29CCKf{OSnE%jQ{{^o(pU5gP&p{DH(40(ZOeyMK?!{g;v)GsZK|}Wi6Mh~{n{ks8=^ccdL^MS3nuq|b zr4x2S;}-auA_QM};>B&@?T~2cJ;sZuYbQz-HnCZu%<#Q;=G;(6nJ&~+Dw`tkeBgRT zt_O-FF%<*|(U?j9uf`h^2WNA$3c_6X$?Jk>7)nF-adGHrgHb} zME25RIs=#PnQ}HOv^D)<6uOXel}sh)uEqJZ5M_>fhx1oulAoind% zMeP5!^K{_Y=3wxa=q`}0#D5PSd_NNMXf!TzVRSm0QHJk+DnY=&yF>g=xg{)03u|*7t+eNkSZV6s#I-*a*?VrBujXLol@b8#%n+J zMF2L`=ah*h(E?9Hw88G2dZH_q!4AYqg{H(XKL%CIPoBQ`tqn*D8 z2Y{jmTG~>pltO46IO8|KzCvPx!XDo6VU-p5!8bDBzsQqb28_F&CW_Z*=SiB%ndREd zzJn!$eL&d!)@2U;&%)>3+n1W@_Po8@-^z^r-B|rHVvb35m9ufv-D0>yO{AFExTVr?ufM>L+K`sEIw>J!lU&4m+u z0(A^{MxF~S#FDlqSREerzN=fnsvJhP=Lp_W^pImPHO%fN(K2)+D851QEsBenm4H8(LFWhvEDb@&s3LMWe zHFk8@b$4HEZ}7pd8-vG>hMTSpEp+}^X>4v6lq!2wO6PCDgHY!IV}6c|3xBAel^<6D RVUS-3t~0Qr9kxtc;r|nRR+In$ literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/linkers/__pycache__/detect.cpython-37.pyc b/devtools/meson/mesonbuild/linkers/__pycache__/detect.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ede51bb9b6289d876f7adef6c5a2d05e05e4a092 GIT binary patch literal 6015 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 T`q1#uG5l>AdU$a6VEq3BSd(V< literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/linkers/base.py b/devtools/meson/mesonbuild/linkers/base.py new file mode 100644 index 0000000..a656bb4 --- /dev/null +++ b/devtools/meson/mesonbuild/linkers/base.py @@ -0,0 +1,50 @@ +# Copyright 2012-2023 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# https://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Core public classes for linkers. +from __future__ import annotations + +import enum +import typing as T + +if T.TYPE_CHECKING: + from ..environment import Environment + + +@enum.unique +class RSPFileSyntax(enum.Enum): + + """Which RSP file syntax the compiler supports.""" + + MSVC = enum.auto() + GCC = enum.auto() + + +class ArLikeLinker: + # POSIX requires supporting the dash, GNU permits omitting it + std_args = ['-csr'] + + def can_linker_accept_rsp(self) -> bool: + # armar / AIX can't accept arguments using the @rsp syntax + # in fact, only the 'ar' id can + return False + + def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: + return self.std_args + + def get_output_args(self, target: str) -> T.List[str]: + return [target] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC diff --git a/devtools/meson/mesonbuild/linkers/detect.py b/devtools/meson/mesonbuild/linkers/detect.py new file mode 100644 index 0000000..e09a28e --- /dev/null +++ b/devtools/meson/mesonbuild/linkers/detect.py @@ -0,0 +1,234 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +from .. import mlog +from ..mesonlib import ( + EnvironmentException, + Popen_safe, Popen_safe_logged, join_args, search_version +) + +import re +import shlex +import typing as T + +if T.TYPE_CHECKING: + from .linkers import DynamicLinker, GnuDynamicLinker + from ..environment import Environment + from ..compilers import Compiler + from ..mesonlib import MachineChoice + +defaults: T.Dict[str, T.List[str]] = {} +defaults['static_linker'] = ['ar', 'gar'] +defaults['vs_static_linker'] = ['lib'] +defaults['clang_cl_static_linker'] = ['llvm-lib'] +defaults['cuda_static_linker'] = ['nvlink'] +defaults['gcc_static_linker'] = ['gcc-ar'] +defaults['clang_static_linker'] = ['llvm-ar'] + +def __failed_to_detect_linker(compiler: T.List[str], args: T.List[str], stdout: str, stderr: str) -> 'T.NoReturn': + msg = 'Unable to detect linker for compiler `{}`\nstdout: {}\nstderr: {}'.format( + join_args(compiler + args), stdout, stderr) + raise EnvironmentException(msg) + + +def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Type['Compiler'], + comp_version: str, for_machine: MachineChoice, *, + use_linker_prefix: bool = True, invoked_directly: bool = True, + extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker': + from . import linkers + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + + # Explicitly pass logo here so that we can get the version of link.exe + if not use_linker_prefix or comp_class.LINKER_PREFIX is None: + check_args = ['/logo', '--version'] + elif isinstance(comp_class.LINKER_PREFIX, str): + check_args = [comp_class.LINKER_PREFIX + '/logo', comp_class.LINKER_PREFIX + '--version'] + elif isinstance(comp_class.LINKER_PREFIX, list): + check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version'] + + check_args += env.coredata.get_external_link_args(for_machine, comp_class.language) + + override = [] # type: T.List[str] + value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld') + if value is not None: + override = comp_class.use_linker_args(value[0], comp_version) + check_args += override + + if extra_args is not None: + check_args.extend(extra_args) + + p, o, _ = Popen_safe(compiler + check_args) + if 'LLD' in o.split('\n', maxsplit=1)[0]: + if '(compatible with GNU linkers)' in o: + return linkers.LLVMDynamicLinker( + compiler, for_machine, comp_class.LINKER_PREFIX, + override, version=search_version(o)) + elif not invoked_directly: + return linkers.ClangClDynamicLinker( + for_machine, override, exelist=compiler, prefix=comp_class.LINKER_PREFIX, + version=search_version(o), direct=False, machine=None) + + if value is not None and invoked_directly: + compiler = value + # We've already handled the non-direct case above + + p, o, e = Popen_safe(compiler + check_args) + if 'LLD' in o.split('\n', maxsplit=1)[0]: + return linkers.ClangClDynamicLinker( + for_machine, [], + prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [], + exelist=compiler, version=search_version(o), direct=invoked_directly) + elif 'OPTLINK' in o: + # Optlink's stdout *may* begin with a \r character. + return linkers.OptlinkDynamicLinker(compiler, for_machine, version=search_version(o)) + elif o.startswith('Microsoft') or e.startswith('Microsoft'): + out = o or e + match = re.search(r'.*(X86|X64|ARM|ARM64).*', out) + if match: + target = str(match.group(1)) + else: + target = 'x86' + + return linkers.MSVCDynamicLinker( + for_machine, [], machine=target, exelist=compiler, + prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [], + version=search_version(out), direct=invoked_directly) + elif 'GNU coreutils' in o: + import shutil + fullpath = shutil.which(compiler[0]) + raise EnvironmentException( + f"Found GNU link.exe instead of MSVC link.exe in {fullpath}.\n" + "This link.exe is not a linker.\n" + "You may need to reorder entries to your %PATH% variable to resolve this.") + __failed_to_detect_linker(compiler, check_args, o, e) + +def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Type['Compiler'], + comp_version: str, for_machine: MachineChoice, *, + extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker': + """Helper for guessing what linker to use on Unix-Like OSes. + + :compiler: Invocation to use to get linker + :comp_class: The Compiler Type (uninstantiated) + :comp_version: The compiler version string + :for_machine: which machine this linker targets + :extra_args: Any additional arguments required (such as a source file) + """ + from . import linkers + env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) + extra_args = extra_args or [] + + ldflags = env.coredata.get_external_link_args(for_machine, comp_class.language) + extra_args += comp_class._unix_args_to_native(ldflags, env.machines[for_machine]) + + if isinstance(comp_class.LINKER_PREFIX, str): + check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args + else: + check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args + + override = [] # type: T.List[str] + value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld') + if value is not None: + override = comp_class.use_linker_args(value[0], comp_version) + check_args += override + + mlog.debug('-----') + p, o, e = Popen_safe_logged(compiler + check_args, msg='Detecting linker via') + + v = search_version(o + e) + linker: DynamicLinker + if 'LLD' in o.split('\n', maxsplit=1)[0]: + if isinstance(comp_class.LINKER_PREFIX, str): + cmd = compiler + override + [comp_class.LINKER_PREFIX + '-v'] + extra_args + else: + cmd = compiler + override + comp_class.LINKER_PREFIX + ['-v'] + extra_args + _, newo, newerr = Popen_safe_logged(cmd, msg='Detecting LLD linker via') + + lld_cls: T.Type[DynamicLinker] + if 'ld64.lld' in newerr: + lld_cls = linkers.LLVMLD64DynamicLinker + else: + lld_cls = linkers.LLVMDynamicLinker + + linker = lld_cls( + compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + elif 'Snapdragon' in e and 'LLVM' in e: + linker = linkers.QualcommLLVMDynamicLinker( + compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + elif e.startswith('lld-link: '): + # The LLD MinGW frontend didn't respond to --version before version 9.0.0, + # and produced an error message about failing to link (when no object + # files were specified), instead of printing the version number. + # Let's try to extract the linker invocation command to grab the version. + + _, o, e = Popen_safe(compiler + check_args + ['-v']) + + try: + linker_cmd = re.match(r'.*\n(.*?)\nlld-link: ', e, re.DOTALL).group(1) + linker_cmd = shlex.split(linker_cmd)[0] + except (AttributeError, IndexError, ValueError): + pass + else: + _, o, e = Popen_safe([linker_cmd, '--version']) + v = search_version(o) + + linker = linkers.LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + # first might be apple clang, second is for real gcc, the third is icc + elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e: + if isinstance(comp_class.LINKER_PREFIX, str): + cmd = compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args + else: + cmd = compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args + _, newo, newerr = Popen_safe_logged(cmd, msg='Detecting Apple linker via') + + for line in newerr.split('\n'): + if 'PROJECT:ld' in line or 'PROJECT:dyld' in line: + v = line.split('-')[1] + break + else: + __failed_to_detect_linker(compiler, check_args, o, e) + linker = linkers.AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + elif 'GNU' in o or 'GNU' in e: + gnu_cls: T.Type[GnuDynamicLinker] + # this is always the only thing on stdout, except for swift + # which may or may not redirect the linker stdout to stderr + if o.startswith('GNU gold') or e.startswith('GNU gold'): + gnu_cls = linkers.GnuGoldDynamicLinker + elif o.startswith('mold') or e.startswith('mold'): + gnu_cls = linkers.MoldDynamicLinker + else: + gnu_cls = linkers.GnuBFDDynamicLinker + linker = gnu_cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + elif 'Solaris' in e or 'Solaris' in o: + for line in (o+e).split('\n'): + if 'ld: Software Generation Utilities' in line: + v = line.split(':')[2].lstrip() + break + else: + v = 'unknown version' + linker = linkers.SolarisDynamicLinker( + compiler, for_machine, comp_class.LINKER_PREFIX, override, + version=v) + elif 'ld: 0706-012 The -- flag is not recognized' in e: + if isinstance(comp_class.LINKER_PREFIX, str): + _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-V'] + extra_args) + else: + _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-V'] + extra_args) + linker = linkers.AIXDynamicLinker( + compiler, for_machine, comp_class.LINKER_PREFIX, override, + version=search_version(e)) + else: + __failed_to_detect_linker(compiler, check_args, o, e) + return linker diff --git a/devtools/meson/mesonbuild/linkers/linkers.py b/devtools/meson/mesonbuild/linkers/linkers.py new file mode 100644 index 0000000..8f4d431 --- /dev/null +++ b/devtools/meson/mesonbuild/linkers/linkers.py @@ -0,0 +1,1621 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import abc +import os +import typing as T +import re + +from .base import ArLikeLinker, RSPFileSyntax +from .. import mesonlib +from ..mesonlib import EnvironmentException, MesonException +from ..arglist import CompilerArgs + +if T.TYPE_CHECKING: + from ..coredata import KeyedOptionDictType + from ..environment import Environment + from ..mesonlib import MachineChoice + + +class StaticLinker: + + id: str + + def __init__(self, exelist: T.List[str]): + self.exelist = exelist + + def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs: + return CompilerArgs(self, args) + + def can_linker_accept_rsp(self) -> bool: + """ + Determines whether the linker can accept arguments using the @rsp syntax. + """ + return mesonlib.is_windows() + + def get_base_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + """Like compilers.get_base_link_args, but for the static linker.""" + return [] + + def get_exelist(self) -> T.List[str]: + return self.exelist.copy() + + def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: + return [] + + def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + return [] + + def get_output_args(self, target: str) -> T.List[str]: + return [] + + def get_coverage_link_args(self) -> T.List[str]: + return [] + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return ([], set()) + + def thread_link_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def openmp_flags(self) -> T.List[str]: + return [] + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + @classmethod + def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]: + return args[:] + + @classmethod + def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: + return args[:] + + def get_link_debugfile_name(self, targetfile: str) -> str: + return None + + def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: + # Static libraries do not have PDB files + return [] + + def get_always_args(self) -> T.List[str]: + return [] + + def get_linker_always_args(self) -> T.List[str]: + return [] + + def rsp_file_syntax(self) -> RSPFileSyntax: + """The format of the RSP file that this compiler supports. + + If `self.can_linker_accept_rsp()` returns True, then this needs to + be implemented + """ + assert not self.can_linker_accept_rsp(), f'{self.id} linker accepts RSP, but doesn\' provide a supported format, this is a bug' + raise EnvironmentException(f'{self.id} does not implement rsp format, this shouldn\'t be called') + + +class VisualStudioLikeLinker: + always_args = ['/NOLOGO'] + + def __init__(self, machine: str): + self.machine = machine + + def get_always_args(self) -> T.List[str]: + return self.always_args.copy() + + def get_linker_always_args(self) -> T.List[str]: + return self.always_args.copy() + + def get_output_args(self, target: str) -> T.List[str]: + args = [] # type: T.List[str] + if self.machine: + args += ['/MACHINE:' + self.machine] + args += ['/OUT:' + target] + return args + + @classmethod + def unix_args_to_native(cls, args: T.List[str]) -> T.List[str]: + from ..compilers.c import VisualStudioCCompiler + return VisualStudioCCompiler.unix_args_to_native(args) + + @classmethod + def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: + from ..compilers.c import VisualStudioCCompiler + return VisualStudioCCompiler.native_args_to_unix(args) + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.MSVC + + +class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker): + + """Microsoft's lib static linker.""" + + id = 'lib' + + def __init__(self, exelist: T.List[str], machine: str): + StaticLinker.__init__(self, exelist) + VisualStudioLikeLinker.__init__(self, machine) + + +class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker): + + """Intel's xilib static linker.""" + + id = 'xilib' + + def __init__(self, exelist: T.List[str], machine: str): + StaticLinker.__init__(self, exelist) + VisualStudioLikeLinker.__init__(self, machine) + + +class ArLinker(ArLikeLinker, StaticLinker): + id = 'ar' + + def __init__(self, for_machine: mesonlib.MachineChoice, exelist: T.List[str]): + super().__init__(exelist) + stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[1] + # Enable deterministic builds if they are available. + stdargs = 'csr' + thinargs = '' + if '[D]' in stdo: + stdargs += 'D' + if '[T]' in stdo: + thinargs = 'T' + self.std_args = [stdargs] + self.std_thin_args = [stdargs + thinargs] + self.can_rsp = '@<' in stdo + self.for_machine = for_machine + + def can_linker_accept_rsp(self) -> bool: + return self.can_rsp + + def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: + # Thin archives are a GNU extension not supported by the system linkers + # on Mac OS X, Solaris, or illumos, so don't build them on those OSes. + # OS X ld rejects with: "file built for unknown-unsupported file format" + # illumos/Solaris ld rejects with: "unknown file type" + if is_thin and not env.machines[self.for_machine].is_darwin() \ + and not env.machines[self.for_machine].is_sunos(): + return self.std_thin_args + else: + return self.std_args + + +class AppleArLinker(ArLinker): + + # mostly this is used to determine that we need to call ranlib + + id = 'applear' + + +class ArmarLinker(ArLikeLinker, StaticLinker): + id = 'armar' + + +class DLinker(StaticLinker): + def __init__(self, exelist: T.List[str], arch: str, *, rsp_syntax: RSPFileSyntax = RSPFileSyntax.GCC): + super().__init__(exelist) + self.id = exelist[0] + self.arch = arch + self.__rsp_syntax = rsp_syntax + + def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: + return ['-lib'] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-of=' + target] + + def get_linker_always_args(self) -> T.List[str]: + if mesonlib.is_windows(): + if self.arch == 'x86_64': + return ['-m64'] + elif self.arch == 'x86_mscoff' and self.id == 'dmd': + return ['-m32mscoff'] + return ['-m32'] + return [] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return self.__rsp_syntax + + +class CcrxLinker(StaticLinker): + + def __init__(self, exelist: T.List[str]): + super().__init__(exelist) + self.id = 'rlink' + + def can_linker_accept_rsp(self) -> bool: + return False + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-output={target}'] + + def get_linker_always_args(self) -> T.List[str]: + return ['-nologo', '-form=library'] + + +class Xc16Linker(StaticLinker): + + def __init__(self, exelist: T.List[str]): + super().__init__(exelist) + self.id = 'xc16-ar' + + def can_linker_accept_rsp(self) -> bool: + return False + + def get_output_args(self, target: str) -> T.List[str]: + return [f'{target}'] + + def get_linker_always_args(self) -> T.List[str]: + return ['rcs'] + +class CompCertLinker(StaticLinker): + + def __init__(self, exelist: T.List[str]): + super().__init__(exelist) + self.id = 'ccomp' + + def can_linker_accept_rsp(self) -> bool: + return False + + def get_output_args(self, target: str) -> T.List[str]: + return [f'-o{target}'] + + +class TILinker(StaticLinker): + + def __init__(self, exelist: T.List[str]): + super().__init__(exelist) + self.id = 'ti-ar' + + def can_linker_accept_rsp(self) -> bool: + return False + + def get_output_args(self, target: str) -> T.List[str]: + return [f'{target}'] + + def get_linker_always_args(self) -> T.List[str]: + return ['-r'] + + +class C2000Linker(TILinker): + # Required for backwards compat with projects created before ti-cgt support existed + id = 'ar2000' + + +class AIXArLinker(ArLikeLinker, StaticLinker): + id = 'aixar' + std_args = ['-csr', '-Xany'] + + +class MetrowerksStaticLinker(StaticLinker): + + def can_linker_accept_rsp(self) -> bool: + return True + + def get_linker_always_args(self) -> T.List[str]: + return ['-library'] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC + + +class MetrowerksStaticLinkerARM(MetrowerksStaticLinker): + id = 'mwldarm' + + +class MetrowerksStaticLinkerEmbeddedPowerPC(MetrowerksStaticLinker): + id = 'mwldeppc' + +def prepare_rpaths(raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]: + # The rpaths we write must be relative if they point to the build dir, + # because otherwise they have different length depending on the build + # directory. This breaks reproducible builds. + internal_format_rpaths = [evaluate_rpath(p, build_dir, from_dir) for p in raw_rpaths] + ordered_rpaths = order_rpaths(internal_format_rpaths) + return ordered_rpaths + + +def order_rpaths(rpath_list: T.List[str]) -> T.List[str]: + # We want rpaths that point inside our build dir to always override + # those pointing to other places in the file system. This is so built + # binaries prefer our libraries to the ones that may lie somewhere + # in the file system, such as /lib/x86_64-linux-gnu. + # + # The correct thing to do here would be C++'s std::stable_partition. + # Python standard library does not have it, so replicate it with + # sort, which is guaranteed to be stable. + return sorted(rpath_list, key=os.path.isabs) + + +def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str: + if p == from_dir: + return '' # relpath errors out in this case + elif os.path.isabs(p): + return p # These can be outside of build dir. + else: + return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) + +class DynamicLinker(metaclass=abc.ABCMeta): + + """Base class for dynamic linkers.""" + + _BUILDTYPE_ARGS = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + + @abc.abstractproperty + def id(self) -> str: + pass + + def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: + args = [arg] if isinstance(arg, str) else arg + if self.prefix_arg is None: + return args + elif isinstance(self.prefix_arg, str): + return [self.prefix_arg + arg for arg in args] + ret = [] + for arg in args: + ret += self.prefix_arg + [arg] + return ret + + def __init__(self, exelist: T.List[str], + for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], + always_args: T.List[str], *, version: str = 'unknown version'): + self.exelist = exelist + self.for_machine = for_machine + self.version = version + self.prefix_arg = prefix_arg + self.always_args = always_args + self.machine = None # type: T.Optional[str] + + def __repr__(self) -> str: + return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist)) + + def get_id(self) -> str: + return self.id + + def get_version_string(self) -> str: + return f'({self.id} {self.version})' + + def get_exelist(self) -> T.List[str]: + return self.exelist.copy() + + def get_accepts_rsp(self) -> bool: + # rsp files are only used when building on Windows because we want to + # avoid issues with quoting and max argument length + return mesonlib.is_windows() + + def rsp_file_syntax(self) -> RSPFileSyntax: + """The format of the RSP file that this compiler supports. + + If `self.can_linker_accept_rsp()` returns True, then this needs to + be implemented + """ + return RSPFileSyntax.GCC + + def get_always_args(self) -> T.List[str]: + return self.always_args.copy() + + def get_lib_prefix(self) -> str: + return '' + + # XXX: is use_ldflags a compiler or a linker attribute? + + def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + raise EnvironmentException(f'Language {self.id} does not support has_multi_link_arguments.') + + def get_debugfile_name(self, targetfile: str) -> str: + '''Name of debug file written out (see below)''' + return None + + def get_debugfile_args(self, targetfile: str) -> T.List[str]: + """Some compilers (MSVC) write debug into a separate file. + + This method takes the target object path and returns a list of + commands to append to the linker invocation to control where that + file is written. + """ + return [] + + def get_std_shared_lib_args(self) -> T.List[str]: + return [] + + def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return self.get_std_shared_lib_args() + + def get_pie_args(self) -> T.List[str]: + # TODO: this really needs to take a boolean and return the args to + # disable pie, otherwise it only acts to enable pie if pie *isn't* the + # default. + raise EnvironmentException(f'Linker {self.id} does not support position-independent executable') + + def get_lto_args(self) -> T.List[str]: + return [] + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return [] + + def sanitizer_args(self, value: str) -> T.List[str]: + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # We can override these in children by just overriding the + # _BUILDTYPE_ARGS value. + return self._BUILDTYPE_ARGS[buildtype] + + def get_asneeded_args(self) -> T.List[str]: + return [] + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + raise EnvironmentException( + f'Linker {self.id} does not support link_whole') + + def get_allow_undefined_args(self) -> T.List[str]: + raise EnvironmentException( + f'Linker {self.id} does not support allow undefined') + + @abc.abstractmethod + def get_output_args(self, outname: str) -> T.List[str]: + pass + + def get_coverage_args(self) -> T.List[str]: + raise EnvironmentException(f"Linker {self.id} doesn't implement coverage data generation.") + + @abc.abstractmethod + def get_search_args(self, dirname: str) -> T.List[str]: + pass + + def export_dynamic_args(self, env: 'Environment') -> T.List[str]: + return [] + + def import_library_args(self, implibname: str) -> T.List[str]: + """The name of the outputted import library. + + This implementation is used only on Windows by compilers that use GNU ld + """ + return [] + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def no_undefined_args(self) -> T.List[str]: + """Arguments to error if there are any undefined symbols at link time. + + This is the inverse of get_allow_undefined_args(). + + TODO: A future cleanup might merge this and + get_allow_undefined_args() into a single method taking a + boolean + """ + return [] + + def fatal_warnings(self) -> T.List[str]: + """Arguments to make all warnings errors.""" + return [] + + def headerpad_args(self) -> T.List[str]: + # Only used by the Apple linker + return [] + + def get_gui_app_args(self, value: bool) -> T.List[str]: + # Only used by VisualStudioLikeLinkers + return [] + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + # Only used if supported by the dynamic linker and + # only when targeting Windows + return [] + + def bitcode_args(self) -> T.List[str]: + raise MesonException('This linker does not support bitcode bundles') + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return ([], set()) + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + def get_archive_name(self, filename: str) -> str: + #Only used by AIX. + return str() + + def get_command_to_archive_shlib(self) -> T.List[str]: + #Only used by AIX. + return [] + + +class PosixDynamicLinkerMixin: + + """Mixin class for POSIX-ish linkers. + + This is obviously a pretty small subset of the linker interface, but + enough dynamic linkers that meson supports are POSIX-like but not + GNU-like that it makes sense to split this out. + """ + + def get_output_args(self, outname: str) -> T.List[str]: + return ['-o', outname] + + def get_std_shared_lib_args(self) -> T.List[str]: + return ['-shared'] + + def get_search_args(self, dirname: str) -> T.List[str]: + return ['-L' + dirname] + + +class GnuLikeDynamicLinkerMixin: + + """Mixin class for dynamic linkers that provides gnu-like interface. + + This acts as a base for the GNU linkers (bfd and gold), LLVM's lld, and + other linkers like GNU-ld. + """ + + if T.TYPE_CHECKING: + for_machine = MachineChoice.HOST + def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... + + _BUILDTYPE_ARGS = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': ['-O1'], + 'minsize': [], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + + _SUBSYSTEMS = { + "native": "1", + "windows": "windows", + "console": "console", + "posix": "7", + "efi_application": "10", + "efi_boot_service_driver": "11", + "efi_runtime_driver": "12", + "efi_rom": "13", + "boot_application": "16", + } # type: T.Dict[str, str] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # We can override these in children by just overriding the + # _BUILDTYPE_ARGS value. + return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) + + def get_pie_args(self) -> T.List[str]: + return ['-pie'] + + def get_asneeded_args(self) -> T.List[str]: + return self._apply_prefix('--as-needed') + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + if not args: + return args + return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive') + + def get_allow_undefined_args(self) -> T.List[str]: + return self._apply_prefix('--allow-shlib-undefined') + + def get_lto_args(self) -> T.List[str]: + return ['-flto'] + + def sanitizer_args(self, value: str) -> T.List[str]: + if value == 'none': + return [] + return ['-fsanitize=' + value] + + def get_coverage_args(self) -> T.List[str]: + return ['--coverage'] + + def export_dynamic_args(self, env: 'Environment') -> T.List[str]: + m = env.machines[self.for_machine] + if m.is_windows() or m.is_cygwin(): + return self._apply_prefix('--export-all-symbols') + return self._apply_prefix('-export-dynamic') + + def import_library_args(self, implibname: str) -> T.List[str]: + return self._apply_prefix('--out-implib=' + implibname) + + def thread_flags(self, env: 'Environment') -> T.List[str]: + if env.machines[self.for_machine].is_haiku(): + return [] + return ['-pthread'] + + def no_undefined_args(self) -> T.List[str]: + return self._apply_prefix('--no-undefined') + + def fatal_warnings(self) -> T.List[str]: + return self._apply_prefix('--fatal-warnings') + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + m = env.machines[self.for_machine] + if m.is_windows() or m.is_cygwin(): + # For PE/COFF the soname argument has no effect + return [] + sostr = '' if soversion is None else '.' + soversion + return self._apply_prefix(f'-soname,{prefix}{shlib_name}.{suffix}{sostr}') + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + m = env.machines[self.for_machine] + if m.is_windows() or m.is_cygwin(): + return ([], set()) + if not rpath_paths and not install_rpath and not build_rpath: + return ([], set()) + args = [] + origin_placeholder = '$ORIGIN' + processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) + # Need to deduplicate rpaths, as macOS's install_name_tool + # is *very* allergic to duplicate -delete_rpath arguments + # when calling depfixer on installation. + all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) + rpath_dirs_to_remove = set() + for p in all_paths: + rpath_dirs_to_remove.add(p.encode('utf8')) + # Build_rpath is used as-is (it is usually absolute). + if build_rpath != '': + all_paths.add(build_rpath) + for p in build_rpath.split(':'): + rpath_dirs_to_remove.add(p.encode('utf8')) + + # TODO: should this actually be "for (dragonfly|open)bsd"? + if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd(): + # This argument instructs the compiler to record the value of + # ORIGIN in the .dynamic section of the elf. On Linux this is done + # by default, but is not on dragonfly/openbsd for some reason. Without this + # $ORIGIN in the runtime path will be undefined and any binaries + # linked against local libraries will fail to resolve them. + args.extend(self._apply_prefix('-z,origin')) + + # In order to avoid relinking for RPATH removal, the binary needs to contain just + # enough space in the ELF header to hold the final installation RPATH. + paths = ':'.join(all_paths) + if len(paths) < len(install_rpath): + padding = 'X' * (len(install_rpath) - len(paths)) + if not paths: + paths = padding + else: + paths = paths + ':' + padding + args.extend(self._apply_prefix('-rpath,' + paths)) + + # TODO: should this actually be "for solaris/sunos"? + if mesonlib.is_sunos(): + return (args, rpath_dirs_to_remove) + + # Rpaths to use while linking must be absolute. These are not + # written to the binary. Needed only with GNU ld: + # https://sourceware.org/bugzilla/show_bug.cgi?id=16936 + # Not needed on Windows or other platforms that don't use RPATH + # https://github.com/mesonbuild/meson/issues/1897 + # + # In addition, this linker option tends to be quite long and some + # compilers have trouble dealing with it. That's why we will include + # one option per folder, like this: + # + # -Wl,-rpath-link,/path/to/folder1 -Wl,-rpath,/path/to/folder2 ... + # + # ...instead of just one single looooong option, like this: + # + # -Wl,-rpath-link,/path/to/folder1:/path/to/folder2:... + for p in rpath_paths: + args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p))) + + return (args, rpath_dirs_to_remove) + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + # MinGW only directly supports a couple of the possible + # PE application types. The raw integer works as an argument + # as well, and is always accepted, so we manually map the + # other types here. List of all types: + # https://github.com/wine-mirror/wine/blob/3ded60bd1654dc689d24a23305f4a93acce3a6f2/include/winnt.h#L2492-L2507 + versionsuffix = None + if ',' in value: + value, versionsuffix = value.split(',', 1) + newvalue = self._SUBSYSTEMS.get(value) + if newvalue is not None: + if versionsuffix is not None: + newvalue += f':{versionsuffix}' + args = [f'--subsystem,{newvalue}'] + else: + raise mesonlib.MesonBugException(f'win_subsystem: {value!r} not handled in MinGW linker. This should not be possible.') + + return self._apply_prefix(args) + + +class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): + + """Apple's ld implementation.""" + + id = 'ld64' + + def get_asneeded_args(self) -> T.List[str]: + return self._apply_prefix('-dead_strip_dylibs') + + def get_allow_undefined_args(self) -> T.List[str]: + return self._apply_prefix('-undefined,dynamic_lookup') + + def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup') + + def get_pie_args(self) -> T.List[str]: + return [] + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + result = [] # type: T.List[str] + for a in args: + result.extend(self._apply_prefix('-force_load')) + result.append(a) + return result + + def get_coverage_args(self) -> T.List[str]: + return ['--coverage'] + + def sanitizer_args(self, value: str) -> T.List[str]: + if value == 'none': + return [] + return ['-fsanitize=' + value] + + def no_undefined_args(self) -> T.List[str]: + return self._apply_prefix('-undefined,error') + + def headerpad_args(self) -> T.List[str]: + return self._apply_prefix('-headerpad_max_install_names') + + def bitcode_args(self) -> T.List[str]: + return self._apply_prefix('-bitcode_bundle') + + def fatal_warnings(self) -> T.List[str]: + return self._apply_prefix('-fatal_warnings') + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + install_name = ['@rpath/', prefix, shlib_name] + if soversion is not None: + install_name.append('.' + soversion) + install_name.append('.dylib') + args = ['-install_name', ''.join(install_name)] + if darwin_versions: + args.extend(['-compatibility_version', darwin_versions[0], + '-current_version', darwin_versions[1]]) + return args + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + if not rpath_paths and not install_rpath and not build_rpath: + return ([], set()) + args = [] + # @loader_path is the equivalent of $ORIGIN on macOS + # https://stackoverflow.com/q/26280738 + origin_placeholder = '@loader_path' + processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) + all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) + if build_rpath != '': + all_paths.add(build_rpath) + for rp in all_paths: + args.extend(self._apply_prefix('-rpath,' + rp)) + + return (args, set()) + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return ["-Wl,-cache_path_lto," + path] + + +class LLVMLD64DynamicLinker(AppleDynamicLinker): + + id = 'ld64.lld' + + +class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): + + """Representation of GNU ld.bfd and ld.gold.""" + + def get_accepts_rsp(self) -> bool: + return True + + +class GnuGoldDynamicLinker(GnuDynamicLinker): + + id = 'ld.gold' + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return ['-Wl,-plugin-opt,cache-dir=' + path] + + +class GnuBFDDynamicLinker(GnuDynamicLinker): + + id = 'ld.bfd' + + +class MoldDynamicLinker(GnuDynamicLinker): + + id = 'ld.mold' + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return ['-Wl,--thinlto-cache-dir=' + path] + + +class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): + + """Representation of LLVM's ld.lld linker. + + This is only the gnu-like linker, not the apple like or link.exe like + linkers. + """ + + id = 'ld.lld' + + def __init__(self, exelist: T.List[str], + for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], + always_args: T.List[str], *, version: str = 'unknown version'): + super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) + + # Some targets don't seem to support this argument (windows, wasm, ...) + _, _, e = mesonlib.Popen_safe(self.exelist + always_args + self._apply_prefix('--allow-shlib-undefined')) + # Versions < 9 do not have a quoted argument + self.has_allow_shlib_undefined = ('unknown argument: --allow-shlib-undefined' not in e) and ("unknown argument: '--allow-shlib-undefined'" not in e) + + def get_allow_undefined_args(self) -> T.List[str]: + if self.has_allow_shlib_undefined: + return self._apply_prefix('--allow-shlib-undefined') + return [] + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return ['-Wl,--thinlto-cache-dir=' + path] + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + # lld does not support a numeric subsystem value + version = None + if ',' in value: + value, version = value.split(',', 1) + if value in self._SUBSYSTEMS: + if version is not None: + value += f':{version}' + return self._apply_prefix([f'--subsystem,{value}']) + else: + raise mesonlib.MesonBugException(f'win_subsystem: {value} not handled in lld linker. This should not be possible.') + + +class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): + + """Emscripten's wasm-ld.""" + + id = 'ld.wasm' + + def get_allow_undefined_args(self) -> T.List[str]: + return ['-sERROR_ON_UNDEFINED_SYMBOLS=0'] + + def no_undefined_args(self) -> T.List[str]: + return ['-sERROR_ON_UNDEFINED_SYMBOLS=1'] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + raise MesonException(f'{self.id} does not support shared libraries.') + + def get_asneeded_args(self) -> T.List[str]: + return [] + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return ([], set()) + + +class CcrxDynamicLinker(DynamicLinker): + + """Linker for Renesas CCrx compiler.""" + + id = 'rlink' + + def __init__(self, for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(['rlink.exe'], for_machine, '', [], + version=version) + + def get_accepts_rsp(self) -> bool: + return False + + def get_lib_prefix(self) -> str: + return '-lib=' + + def get_std_shared_lib_args(self) -> T.List[str]: + return [] + + def get_output_args(self, outputname: str) -> T.List[str]: + return [f'-output={outputname}'] + + def get_search_args(self, dirname: str) -> 'T.NoReturn': + raise OSError('rlink.exe does not have a search dir argument') + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + +class Xc16DynamicLinker(DynamicLinker): + + """Linker for Microchip XC16 compiler.""" + + id = 'xc16-gcc' + + def __init__(self, for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(['xc16-gcc'], for_machine, '', [], + version=version) + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + if not args: + return args + return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group') + + def get_accepts_rsp(self) -> bool: + return False + + def get_lib_prefix(self) -> str: + return '' + + def get_std_shared_lib_args(self) -> T.List[str]: + return [] + + def get_output_args(self, outputname: str) -> T.List[str]: + return [f'-o{outputname}'] + + def get_search_args(self, dirname: str) -> 'T.NoReturn': + raise OSError('xc16-gcc does not have a search dir argument') + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return ([], set()) + +class CompCertDynamicLinker(DynamicLinker): + + """Linker for CompCert C compiler.""" + + id = 'ccomp' + + def __init__(self, for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(['ccomp'], for_machine, '', [], + version=version) + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + if not args: + return args + return self._apply_prefix('-Wl,--whole-archive') + args + self._apply_prefix('-Wl,--no-whole-archive') + + def get_accepts_rsp(self) -> bool: + return False + + def get_lib_prefix(self) -> str: + return '' + + def get_std_shared_lib_args(self) -> T.List[str]: + return [] + + def get_output_args(self, outputname: str) -> T.List[str]: + return [f'-o{outputname}'] + + def get_search_args(self, dirname: str) -> T.List[str]: + return [f'-L{dirname}'] + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + raise MesonException(f'{self.id} does not support shared libraries.') + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return ([], set()) + +class TIDynamicLinker(DynamicLinker): + + """Linker for Texas Instruments compiler family.""" + + id = 'ti' + + def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(exelist, for_machine, '', [], + version=version) + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + if not args: + return args + return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group') + + def get_accepts_rsp(self) -> bool: + return False + + def get_lib_prefix(self) -> str: + return '-l=' + + def get_std_shared_lib_args(self) -> T.List[str]: + return [] + + def get_output_args(self, outputname: str) -> T.List[str]: + return ['-z', f'--output_file={outputname}'] + + def get_search_args(self, dirname: str) -> 'T.NoReturn': + raise OSError('TI compilers do not have a search dir argument') + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_always_args(self) -> T.List[str]: + return [] + + +class C2000DynamicLinker(TIDynamicLinker): + # Required for backwards compat with projects created before ti-cgt support existed + id = 'cl2000' + + +class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): + + """Linker for the ARM compiler.""" + + id = 'armlink' + + def __init__(self, for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(['armlink'], for_machine, '', [], + version=version) + + def get_accepts_rsp(self) -> bool: + return False + + def get_std_shared_lib_args(self) -> 'T.NoReturn': + raise MesonException('The Arm Linkers do not support shared libraries') + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + +class ArmClangDynamicLinker(ArmDynamicLinker): + + """Linker used with ARM's clang fork. + + The interface is similar enough to the old ARM ld that it inherits and + extends a few things as needed. + """ + + def export_dynamic_args(self, env: 'Environment') -> T.List[str]: + return ['--export_dynamic'] + + def import_library_args(self, implibname: str) -> T.List[str]: + return ['--symdefs=' + implibname] + +class QualcommLLVMDynamicLinker(LLVMDynamicLinker): + + """ARM Linker from Snapdragon LLVM ARM Compiler.""" + + id = 'ld.qcld' + + +class NAGDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): + + """NAG Fortran linker, ld via gcc indirection. + + Using nagfor -Wl,foo passes option foo to a backend gcc invocation. + (This linking gathers the correct objects needed from the nagfor runtime + system.) + To pass gcc -Wl,foo options (i.e., to ld) one must apply indirection + again: nagfor -Wl,-Wl,,foo + """ + + id = 'nag' + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + if not rpath_paths and not install_rpath and not build_rpath: + return ([], set()) + args = [] + origin_placeholder = '$ORIGIN' + processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) + all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) + if build_rpath != '': + all_paths.add(build_rpath) + for rp in all_paths: + args.extend(self._apply_prefix('-Wl,-Wl,,-rpath,,' + rp)) + + return (args, set()) + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_std_shared_lib_args(self) -> T.List[str]: + from ..compilers.fortran import NAGFortranCompiler + return NAGFortranCompiler.get_nagfor_quiet(self.version) + ['-Wl,-shared'] + + +class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): + + """PGI linker.""" + + id = 'pgi' + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + def get_std_shared_lib_args(self) -> T.List[str]: + # PGI -shared is Linux only. + if mesonlib.is_windows(): + return ['-Bdynamic', '-Mmakedll'] + elif mesonlib.is_linux(): + return ['-shared'] + return [] + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + if not env.machines[self.for_machine].is_windows(): + return (['-R' + os.path.join(build_dir, p) for p in rpath_paths], set()) + return ([], set()) + +NvidiaHPC_DynamicLinker = PGIDynamicLinker + + +class PGIStaticLinker(StaticLinker): + def __init__(self, exelist: T.List[str]): + super().__init__(exelist) + self.id = 'ar' + self.std_args = ['-r'] + + def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: + return self.std_args + + def get_output_args(self, target: str) -> T.List[str]: + return [target] + +NvidiaHPC_StaticLinker = PGIStaticLinker + + +class VisualStudioLikeLinkerMixin: + + """Mixin class for dynamic linkers that act like Microsoft's link.exe.""" + + if T.TYPE_CHECKING: + for_machine = MachineChoice.HOST + def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... + + _BUILDTYPE_ARGS = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + # The otherwise implicit REF and ICF linker optimisations are disabled by + # /DEBUG. REF implies ICF. + 'release': ['/OPT:REF'], + 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], + 'custom': [], + } # type: T.Dict[str, T.List[str]] + + def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, + prefix_arg: T.Union[str, T.List[str]], always_args: T.List[str], *, + version: str = 'unknown version', direct: bool = True, machine: str = 'x86'): + # There's no way I can find to make mypy understand what's going on here + super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) # type: ignore + self.machine = machine + self.direct = direct + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) + + def invoked_by_compiler(self) -> bool: + return not self.direct + + def get_output_args(self, outputname: str) -> T.List[str]: + return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname]) + + def get_always_args(self) -> T.List[str]: + parent = super().get_always_args() # type: ignore + return self._apply_prefix('/nologo') + T.cast('T.List[str]', parent) + + def get_search_args(self, dirname: str) -> T.List[str]: + return self._apply_prefix('/LIBPATH:' + dirname) + + def get_std_shared_lib_args(self) -> T.List[str]: + return self._apply_prefix('/DLL') + + def get_debugfile_name(self, targetfile: str) -> str: + basename = targetfile.rsplit('.', maxsplit=1)[0] + return basename + '.pdb' + + def get_debugfile_args(self, targetfile: str) -> T.List[str]: + return self._apply_prefix(['/DEBUG', '/PDB:' + self.get_debugfile_name(targetfile)]) + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + # Only since VS2015 + args = mesonlib.listify(args) + l = [] # T.List[str] + for a in args: + l.extend(self._apply_prefix('/WHOLEARCHIVE:' + a)) + return l + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + def import_library_args(self, implibname: str) -> T.List[str]: + """The command to generate the import library.""" + return self._apply_prefix(['/IMPLIB:' + implibname]) + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.MSVC + + +class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): + + """Microsoft's Link.exe.""" + + id = 'link' + + def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *, + exelist: T.Optional[T.List[str]] = None, + prefix: T.Union[str, T.List[str]] = '', + machine: str = 'x86', version: str = 'unknown version', + direct: bool = True): + super().__init__(exelist or ['link.exe'], for_machine, + prefix, always_args, machine=machine, version=version, direct=direct) + + def get_always_args(self) -> T.List[str]: + return self._apply_prefix(['/nologo', '/release']) + super().get_always_args() + + def get_gui_app_args(self, value: bool) -> T.List[str]: + return self.get_win_subsystem_args("windows" if value else "console") + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) + + +class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): + + """Clang's lld-link.exe.""" + + id = 'lld-link' + + def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *, + exelist: T.Optional[T.List[str]] = None, + prefix: T.Union[str, T.List[str]] = '', + machine: str = 'x86', version: str = 'unknown version', + direct: bool = True): + super().__init__(exelist or ['lld-link.exe'], for_machine, + prefix, always_args, machine=machine, version=version, direct=direct) + + def get_output_args(self, outputname: str) -> T.List[str]: + # If we're being driven indirectly by clang just skip /MACHINE + # as clang's target triple will handle the machine selection + if self.machine is None: + return self._apply_prefix([f"/OUT:{outputname}"]) + + return super().get_output_args(outputname) + + def get_gui_app_args(self, value: bool) -> T.List[str]: + return self.get_win_subsystem_args("windows" if value else "console") + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return ["/lldltocache:" + path] + + +class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): + + """Intel's Xilink.exe.""" + + id = 'xilink' + + def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *, + exelist: T.Optional[T.List[str]] = None, + prefix: T.Union[str, T.List[str]] = '', + machine: str = 'x86', version: str = 'unknown version', + direct: bool = True): + super().__init__(['xilink.exe'], for_machine, '', always_args, version=version) + + def get_gui_app_args(self, value: bool) -> T.List[str]: + return self.get_win_subsystem_args("windows" if value else "console") + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) + + +class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): + + """Sys-V derived linker used on Solaris and OpenSolaris.""" + + id = 'ld.solaris' + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + if not args: + return args + return self._apply_prefix('--whole-archive') + args + self._apply_prefix('--no-whole-archive') + + def get_pie_args(self) -> T.List[str]: + # Available in Solaris 11.2 and later + pc, stdo, stde = mesonlib.Popen_safe(self.exelist + self._apply_prefix('-zhelp')) + for line in (stdo + stde).split('\n'): + if '-z type' in line: + if 'pie' in line: + return ['-z', 'type=pie'] + break + return [] + + def get_asneeded_args(self) -> T.List[str]: + return self._apply_prefix(['-z', 'ignore']) + + def no_undefined_args(self) -> T.List[str]: + return ['-z', 'defs'] + + def get_allow_undefined_args(self) -> T.List[str]: + return ['-z', 'nodefs'] + + def fatal_warnings(self) -> T.List[str]: + return ['-z', 'fatal-warnings'] + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + if not rpath_paths and not install_rpath and not build_rpath: + return ([], set()) + processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) + all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths]) + rpath_dirs_to_remove = set() + for p in all_paths: + rpath_dirs_to_remove.add(p.encode('utf8')) + if build_rpath != '': + all_paths.add(build_rpath) + for p in build_rpath.split(':'): + rpath_dirs_to_remove.add(p.encode('utf8')) + + # In order to avoid relinking for RPATH removal, the binary needs to contain just + # enough space in the ELF header to hold the final installation RPATH. + paths = ':'.join(all_paths) + if len(paths) < len(install_rpath): + padding = 'X' * (len(install_rpath) - len(paths)) + if not paths: + paths = padding + else: + paths = paths + ':' + padding + return (self._apply_prefix(f'-rpath,{paths}'), rpath_dirs_to_remove) + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + sostr = '' if soversion is None else '.' + soversion + return self._apply_prefix(f'-soname,{prefix}{shlib_name}.{suffix}{sostr}') + + +class AIXDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): + + """Sys-V derived linker used on AIX""" + + id = 'ld.aix' + + def get_always_args(self) -> T.List[str]: + return self._apply_prefix(['-bnoipath', '-bbigtoc']) + super().get_always_args() + + def no_undefined_args(self) -> T.List[str]: + return self._apply_prefix(['-bernotok']) + + def get_allow_undefined_args(self) -> T.List[str]: + return self._apply_prefix(['-berok']) + + def get_archive_name(self, filename: str) -> str: + # In AIX we allow the shared library name to have the lt_version and so_version. + # But the archive name must just be .a . + # For Example shared object can have the name libgio.so.0.7200.1 but the archive + # must have the name libgio.a having libgio.a (libgio.so.0.7200.1) in the + # archive. This regular expression is to do the same. + filename = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', filename.replace('.so', '.a')) + return filename + + def get_command_to_archive_shlib(self) -> T.List[str]: + # Archive shared library object and remove the shared library object, + # since it already exists in the archive. + command = ['ar', '-q', '-v', '$out', '$in', '&&', 'rm', '-f', '$in'] + return command + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + # AIX's linker always links the whole archive: "The ld command + # processes all input files in the same manner, whether they are + # archives or not." + return args + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + all_paths = mesonlib.OrderedSet() # type: mesonlib.OrderedSet[str] + # install_rpath first, followed by other paths, and the system path last + if install_rpath != '': + all_paths.add(install_rpath) + if build_rpath != '': + all_paths.add(build_rpath) + for p in rpath_paths: + all_paths.add(os.path.join(build_dir, p)) + # We should consider allowing the $LIBPATH environment variable + # to override sys_path. + sys_path = env.get_compiler_system_lib_dirs(self.for_machine) + if len(sys_path) == 0: + # get_compiler_system_lib_dirs doesn't support our compiler. + # Use the default system library path + all_paths.update(['/usr/lib', '/lib']) + else: + # Include the compiler's default library paths, but filter out paths that don't exist + for p in sys_path: + if os.path.isdir(p): + all_paths.add(p) + return (self._apply_prefix('-blibpath:' + ':'.join(all_paths)), set()) + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return ['-pthread'] + + +class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): + + """Digital Mars dynamic linker for windows.""" + + id = 'optlink' + + def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + # Use optlink instead of link so we don't interfere with other link.exe + # implementations. + super().__init__(exelist, for_machine, '', [], version=version) + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_debugfile_args(self, targetfile: str) -> T.List[str]: + # Optlink does not generate pdb files. + return [] + + def get_always_args(self) -> T.List[str]: + return [] + + +class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker): + """Cuda linker (nvlink)""" + + id = 'nvlink' + + @staticmethod + def parse_version() -> str: + version_cmd = ['nvlink', '--version'] + try: + _, out, _ = mesonlib.Popen_safe(version_cmd) + except OSError: + return 'unknown version' + # Output example: + # nvlink: NVIDIA (R) Cuda linker + # Copyright (c) 2005-2018 NVIDIA Corporation + # Built on Sun_Sep_30_21:09:22_CDT_2018 + # Cuda compilation tools, release 10.0, V10.0.166 + # we need the most verbose version output. Luckily starting with V + return out.strip().rsplit('V', maxsplit=1)[-1] + + def get_accepts_rsp(self) -> bool: + # nvcc does not support response files + return False + + def get_lib_prefix(self) -> str: + # nvcc doesn't recognize Meson's default .a extension for static libraries on + # Windows and passes it to cl as an object file, resulting in 'warning D9024 : + # unrecognized source file type 'xxx.a', object file assumed'. + # + # nvcc's --library= option doesn't help: it takes the library name without the + # extension and assumes that the extension on Windows is .lib; prefixing the + # library with -Xlinker= seems to work. + # + # On Linux, we have to use rely on -Xlinker= too, since nvcc/nvlink chokes on + # versioned shared libraries: + # + # nvcc fatal : Don't know what to do with 'subprojects/foo/libbar.so.0.1.2' + # + from ..compilers.cuda import CudaCompiler + return CudaCompiler.LINKER_PREFIX + + def fatal_warnings(self) -> T.List[str]: + return ['--warning-as-error'] + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + +class MetrowerksLinker(DynamicLinker): + + def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(exelist, for_machine, '', [], + version=version) + + def fatal_warnings(self) -> T.List[str]: + return ['-w', 'error'] + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_accepts_rsp(self) -> bool: + return True + + def get_lib_prefix(self) -> str: + return "" + + def get_linker_always_args(self) -> T.List[str]: + return [] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def get_search_args(self, dirname: str) -> T.List[str]: + return self._apply_prefix('-L' + dirname) + + def invoked_by_compiler(self) -> bool: + return False + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC + + +class MetrowerksLinkerARM(MetrowerksLinker): + id = 'mwldarm' + + +class MetrowerksLinkerEmbeddedPowerPC(MetrowerksLinker): + id = 'mwldeppc' diff --git a/devtools/meson/mesonbuild/mcompile.py b/devtools/meson/mesonbuild/mcompile.py new file mode 100644 index 0000000..4e46702 --- /dev/null +++ b/devtools/meson/mesonbuild/mcompile.py @@ -0,0 +1,359 @@ +# Copyright 2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Entrypoint script for backend agnostic compile.""" + +import os +import json +import re +import sys +import shutil +import typing as T +from collections import defaultdict +from pathlib import Path + +from . import mlog +from . import mesonlib +from .mesonlib import MesonException, RealPathAction, join_args, setup_vsenv +from mesonbuild.environment import detect_ninja +from mesonbuild.coredata import UserArrayOption +from mesonbuild import build + +if T.TYPE_CHECKING: + import argparse + +def array_arg(value: str) -> T.List[str]: + return UserArrayOption(None, value, allow_dups=True, user_input=True).value + +def validate_builddir(builddir: Path) -> None: + if not (builddir / 'meson-private' / 'coredata.dat').is_file(): + raise MesonException(f'Current directory is not a meson build directory: `{builddir}`.\n' + 'Please specify a valid build dir or change the working directory to it.\n' + 'It is also possible that the build directory was generated with an old\n' + 'meson version. Please regenerate it in this case.') + +def parse_introspect_data(builddir: Path) -> T.Dict[str, T.List[dict]]: + """ + Converts a List of name-to-dict to a dict of name-to-dicts (since names are not unique) + """ + path_to_intro = builddir / 'meson-info' / 'intro-targets.json' + if not path_to_intro.exists(): + raise MesonException(f'`{path_to_intro.name}` is missing! Directory is not configured yet?') + with path_to_intro.open(encoding='utf-8') as f: + schema = json.load(f) + + parsed_data = defaultdict(list) # type: T.Dict[str, T.List[dict]] + for target in schema: + parsed_data[target['name']] += [target] + return parsed_data + +class ParsedTargetName: + full_name = '' + name = '' + type = '' + path = '' + + def __init__(self, target: str): + self.full_name = target + split = target.rsplit(':', 1) + if len(split) > 1: + self.type = split[1] + if not self._is_valid_type(self.type): + raise MesonException(f'Can\'t invoke target `{target}`: unknown target type: `{self.type}`') + + split = split[0].rsplit('/', 1) + if len(split) > 1: + self.path = split[0] + self.name = split[1] + else: + self.name = split[0] + + @staticmethod + def _is_valid_type(type: str) -> bool: + # Amend docs in Commands.md when editing this list + allowed_types = { + 'executable', + 'static_library', + 'shared_library', + 'shared_module', + 'custom', + 'alias', + 'run', + 'jar', + } + return type in allowed_types + +def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introspect_data: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]: + if target.name not in introspect_data: + raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found') + + intro_targets = introspect_data[target.name] + found_targets = [] # type: T.List[T.Dict[str, T.Any]] + + resolved_bdir = builddir.resolve() + + if not target.type and not target.path: + found_targets = intro_targets + else: + for intro_target in intro_targets: + if ((target.type and target.type != intro_target['type'].replace(' ', '_')) or + (target.path and intro_target['filename'] != 'no_name' and + Path(target.path) != Path(intro_target['filename'][0]).relative_to(resolved_bdir).parent)): + continue + found_targets += [intro_target] + + if not found_targets: + raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found') + elif len(found_targets) > 1: + suggestions: T.List[str] = [] + for i in found_targets: + p = Path(i['filename'][0]).relative_to(resolved_bdir).parent / i['name'] + t = i['type'].replace(' ', '_') + suggestions.append(f'- ./{p}:{t}') + suggestions_str = '\n'.join(suggestions) + raise MesonException(f'Can\'t invoke target `{target.full_name}`: ambiguous name.' + f'Add target type and/or path:\n{suggestions_str}') + + return found_targets[0] + +def generate_target_names_ninja(target: ParsedTargetName, builddir: Path, introspect_data: dict) -> T.List[str]: + intro_target = get_target_from_intro_data(target, builddir, introspect_data) + + if intro_target['type'] in {'alias', 'run'}: + return [target.name] + else: + return [str(Path(out_file).relative_to(builddir.resolve())) for out_file in intro_target['filename']] + +def get_parsed_args_ninja(options: 'argparse.Namespace', builddir: Path) -> T.Tuple[T.List[str], T.Optional[T.Dict[str, str]]]: + runner = detect_ninja() + if runner is None: + raise MesonException('Cannot find ninja.') + + cmd = runner + if not builddir.samefile('.'): + cmd.extend(['-C', builddir.as_posix()]) + + # If the value is set to < 1 then don't set anything, which let's + # ninja/samu decide what to do. + if options.jobs > 0: + cmd.extend(['-j', str(options.jobs)]) + if options.load_average > 0: + cmd.extend(['-l', str(options.load_average)]) + + if options.verbose: + cmd.append('-v') + + cmd += options.ninja_args + + # operands must be processed after options/option-arguments + if options.targets: + intro_data = parse_introspect_data(builddir) + for t in options.targets: + cmd.extend(generate_target_names_ninja(ParsedTargetName(t), builddir, intro_data)) + if options.clean: + cmd.append('clean') + + return cmd, None + +def generate_target_name_vs(target: ParsedTargetName, builddir: Path, introspect_data: dict) -> str: + intro_target = get_target_from_intro_data(target, builddir, introspect_data) + + assert intro_target['type'] not in {'alias', 'run'}, 'Should not reach here: `run` targets must be handle above' + + # Normalize project name + # Source: https://docs.microsoft.com/en-us/visualstudio/msbuild/how-to-build-specific-targets-in-solutions-by-using-msbuild-exe + target_name = re.sub(r"[\%\$\@\;\.\(\)']", '_', intro_target['id']) # type: str + rel_path = Path(intro_target['filename'][0]).relative_to(builddir.resolve()).parent + if rel_path != Path('.'): + target_name = str(rel_path / target_name) + return target_name + +def get_parsed_args_vs(options: 'argparse.Namespace', builddir: Path) -> T.Tuple[T.List[str], T.Optional[T.Dict[str, str]]]: + slns = list(builddir.glob('*.sln')) + assert len(slns) == 1, 'More than one solution in a project?' + sln = slns[0] + + cmd = ['msbuild'] + + if options.targets: + intro_data = parse_introspect_data(builddir) + has_run_target = any( + get_target_from_intro_data(ParsedTargetName(t), builddir, intro_data)['type'] in {'alias', 'run'} + for t in options.targets) + + if has_run_target: + # `run` target can't be used the same way as other targets on `vs` backend. + # They are defined as disabled projects, which can't be invoked as `.sln` + # target and have to be invoked directly as project instead. + # Issue: https://github.com/microsoft/msbuild/issues/4772 + + if len(options.targets) > 1: + raise MesonException('Only one target may be specified when `run` target type is used on this backend.') + intro_target = get_target_from_intro_data(ParsedTargetName(options.targets[0]), builddir, intro_data) + proj_dir = Path(intro_target['filename'][0]).parent + proj = proj_dir/'{}.vcxproj'.format(intro_target['id']) + cmd += [str(proj.resolve())] + else: + cmd += [str(sln.resolve())] + cmd.extend(['-target:{}'.format(generate_target_name_vs(ParsedTargetName(t), builddir, intro_data)) for t in options.targets]) + else: + cmd += [str(sln.resolve())] + + if options.clean: + cmd.extend(['-target:Clean']) + + # In msbuild `-maxCpuCount` with no number means "detect cpus", the default is `-maxCpuCount:1` + if options.jobs > 0: + cmd.append(f'-maxCpuCount:{options.jobs}') + else: + cmd.append('-maxCpuCount') + + if options.load_average: + mlog.warning('Msbuild does not have a load-average switch, ignoring.') + + if not options.verbose: + cmd.append('-verbosity:minimal') + + cmd += options.vs_args + + # Remove platform from env if set so that msbuild does not + # pick x86 platform when solution platform is Win32 + env = os.environ.copy() + env.pop('PLATFORM', None) + + return cmd, env + +def get_parsed_args_xcode(options: 'argparse.Namespace', builddir: Path) -> T.Tuple[T.List[str], T.Optional[T.Dict[str, str]]]: + runner = 'xcodebuild' + if not shutil.which(runner): + raise MesonException('Cannot find xcodebuild, did you install XCode?') + + # No argument to switch directory + os.chdir(str(builddir)) + + cmd = [runner, '-parallelizeTargets'] + + if options.targets: + for t in options.targets: + cmd += ['-target', t] + + if options.clean: + if options.targets: + cmd += ['clean'] + else: + cmd += ['-alltargets', 'clean'] + # Otherwise xcodebuild tries to delete the builddir and fails + cmd += ['-UseNewBuildSystem=FALSE'] + + if options.jobs > 0: + cmd.extend(['-jobs', str(options.jobs)]) + + if options.load_average > 0: + mlog.warning('xcodebuild does not have a load-average switch, ignoring') + + if options.verbose: + # xcodebuild is already quite verbose, and -quiet doesn't print any + # status messages + pass + + cmd += options.xcode_args + return cmd, None + +def add_arguments(parser: 'argparse.ArgumentParser') -> None: + """Add compile specific arguments.""" + parser.add_argument( + 'targets', + metavar='TARGET', + nargs='*', + default=None, + help='Targets to build. Target has the following format: [PATH_TO_TARGET/]TARGET_NAME[:TARGET_TYPE].') + parser.add_argument( + '--clean', + action='store_true', + help='Clean the build directory.' + ) + parser.add_argument('-C', dest='wd', action=RealPathAction, + help='directory to cd into before running') + + parser.add_argument( + '-j', '--jobs', + action='store', + default=0, + type=int, + help='The number of worker jobs to run (if supported). If the value is less than 1 the build program will guess.' + ) + parser.add_argument( + '-l', '--load-average', + action='store', + default=0, + type=float, + help='The system load average to try to maintain (if supported).' + ) + parser.add_argument( + '-v', '--verbose', + action='store_true', + help='Show more verbose output.' + ) + parser.add_argument( + '--ninja-args', + type=array_arg, + default=[], + help='Arguments to pass to `ninja` (applied only on `ninja` backend).' + ) + parser.add_argument( + '--vs-args', + type=array_arg, + default=[], + help='Arguments to pass to `msbuild` (applied only on `vs` backend).' + ) + parser.add_argument( + '--xcode-args', + type=array_arg, + default=[], + help='Arguments to pass to `xcodebuild` (applied only on `xcode` backend).' + ) + +def run(options: 'argparse.Namespace') -> int: + bdir = Path(options.wd) + validate_builddir(bdir) + if options.targets and options.clean: + raise MesonException('`TARGET` and `--clean` can\'t be used simultaneously') + + b = build.load(options.wd) + cdata = b.environment.coredata + need_vsenv = T.cast('bool', cdata.get_option(mesonlib.OptionKey('vsenv'))) + if setup_vsenv(need_vsenv): + mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') + + cmd = [] # type: T.List[str] + env = None # type: T.Optional[T.Dict[str, str]] + + backend = cdata.get_option(mesonlib.OptionKey('backend')) + assert isinstance(backend, str) + mlog.log(mlog.green('INFO:'), 'autodetecting backend as', backend) + if backend == 'ninja': + cmd, env = get_parsed_args_ninja(options, bdir) + elif backend.startswith('vs'): + cmd, env = get_parsed_args_vs(options, bdir) + elif backend == 'xcode': + cmd, env = get_parsed_args_xcode(options, bdir) + else: + raise MesonException( + f'Backend `{backend}` is not yet supported by `compile`. Use generated project files directly instead.') + + mlog.log(mlog.green('INFO:'), 'calculating backend command to run:', join_args(cmd)) + p, *_ = mesonlib.Popen_safe(cmd, stdout=sys.stdout.buffer, stderr=sys.stderr.buffer, env=env) + + return p.returncode diff --git a/devtools/meson/mesonbuild/mconf.py b/devtools/meson/mesonbuild/mconf.py new file mode 100644 index 0000000..ddd2ee2 --- /dev/null +++ b/devtools/meson/mesonbuild/mconf.py @@ -0,0 +1,336 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import itertools +import shutil +import os +import textwrap +import typing as T +import collections + +from . import build +from . import coredata +from . import environment +from . import mesonlib +from . import mintro +from . import mlog +from .ast import AstIDGenerator +from .mesonlib import MachineChoice, OptionKey + +if T.TYPE_CHECKING: + import argparse + + # cannot be TV_Loggable, because non-ansidecorators do direct string concat + LOGLINE = T.Union[str, mlog.AnsiDecorator] + +def add_arguments(parser: 'argparse.ArgumentParser') -> None: + coredata.register_builtin_arguments(parser) + parser.add_argument('builddir', nargs='?', default='.') + parser.add_argument('--clearcache', action='store_true', default=False, + help='Clear cached state (e.g. found dependencies)') + parser.add_argument('--no-pager', action='store_false', dest='pager', + help='Do not redirect output to a pager') + +def stringify(val: T.Any) -> str: + if isinstance(val, bool): + return str(val).lower() + elif isinstance(val, list): + s = ', '.join(stringify(i) for i in val) + return f'[{s}]' + elif val is None: + return '' + else: + return str(val) + + +class ConfException(mesonlib.MesonException): + pass + + +class Conf: + def __init__(self, build_dir: str): + self.build_dir = os.path.abspath(os.path.realpath(build_dir)) + if 'meson.build' in [os.path.basename(self.build_dir), self.build_dir]: + self.build_dir = os.path.dirname(self.build_dir) + self.build = None + self.max_choices_line_length = 60 + self.name_col: T.List[LOGLINE] = [] + self.value_col: T.List[LOGLINE] = [] + self.choices_col: T.List[LOGLINE] = [] + self.descr_col: T.List[LOGLINE] = [] + self.all_subprojects: T.Set[str] = set() + + if os.path.isdir(os.path.join(self.build_dir, 'meson-private')): + self.build = build.load(self.build_dir) + self.source_dir = self.build.environment.get_source_dir() + self.coredata = self.build.environment.coredata + self.default_values_only = False + elif os.path.isfile(os.path.join(self.build_dir, environment.build_filename)): + # Make sure that log entries in other parts of meson don't interfere with the JSON output + with mlog.no_logging(): + self.source_dir = os.path.abspath(os.path.realpath(self.build_dir)) + intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()]) + intr.analyze() + self.coredata = intr.coredata + self.default_values_only = True + else: + raise ConfException(f'Directory {build_dir} is neither a Meson build directory nor a project source directory.') + + def clear_cache(self) -> None: + self.coredata.clear_cache() + + def set_options(self, options: T.Dict[OptionKey, str]) -> bool: + return self.coredata.set_options(options) + + def save(self) -> None: + # Do nothing when using introspection + if self.default_values_only: + return + coredata.save(self.coredata, self.build_dir) + # We don't write the build file because any changes to it + # are erased when Meson is executed the next time, i.e. when + # Ninja is run. + + def print_aligned(self) -> None: + """Do the actual printing. + + This prints the generated output in an aligned, pretty form. it aims + for a total width of 160 characters, but will use whatever the tty + reports it's value to be. Though this is much wider than the standard + 80 characters of terminals, and even than the newer 120, compressing + it to those lengths makes the output hard to read. + + Each column will have a specific width, and will be line wrapped. + """ + total_width = shutil.get_terminal_size(fallback=(160, 0))[0] + _col = max(total_width // 5, 20) + last_column = total_width - (3 * _col) - 3 + four_column = (_col, _col, _col, last_column if last_column > 1 else _col) + + for line in zip(self.name_col, self.value_col, self.choices_col, self.descr_col): + if not any(line): + mlog.log('') + continue + + # This is a header, like `Subproject foo:`, + # We just want to print that and get on with it + if line[0] and not any(line[1:]): + mlog.log(line[0]) + continue + + def wrap_text(text: LOGLINE, width: int) -> mlog.TV_LoggableList: + raw = text.text if isinstance(text, mlog.AnsiDecorator) else text + indent = ' ' if raw.startswith('[') else '' + wrapped_ = textwrap.wrap(raw, width, subsequent_indent=indent) + # We cast this because https://github.com/python/mypy/issues/1965 + # mlog.TV_LoggableList does not provide __len__ for stringprotocol + if isinstance(text, mlog.AnsiDecorator): + wrapped = T.cast('T.List[LOGLINE]', [mlog.AnsiDecorator(i, text.code) for i in wrapped_]) + else: + wrapped = T.cast('T.List[LOGLINE]', wrapped_) + # Add padding here to get even rows, as `textwrap.wrap()` will + # only shorten, not lengthen each item + return [str(i) + ' ' * (width - len(i)) for i in wrapped] + + # wrap will take a long string, and create a list of strings no + # longer than the size given. Then that list can be zipped into, to + # print each line of the output, such the that columns are printed + # to the right width, row by row. + name = wrap_text(line[0], four_column[0]) + val = wrap_text(line[1], four_column[1]) + choice = wrap_text(line[2], four_column[2]) + desc = wrap_text(line[3], four_column[3]) + for l in itertools.zip_longest(name, val, choice, desc, fillvalue=''): + items = [l[i] if l[i] else ' ' * four_column[i] for i in range(4)] + mlog.log(*items) + + def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, 'coredata.MutableKeyedOptionDictType']: + result: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = {} + for k, o in options.items(): + if k.subproject: + self.all_subprojects.add(k.subproject) + result.setdefault(k.subproject, {})[k] = o + return result + + def _add_line(self, name: LOGLINE, value: LOGLINE, choices: LOGLINE, descr: LOGLINE) -> None: + if isinstance(name, mlog.AnsiDecorator): + name.text = ' ' * self.print_margin + name.text + else: + name = ' ' * self.print_margin + name + self.name_col.append(name) + self.value_col.append(value) + self.choices_col.append(choices) + self.descr_col.append(descr) + + def add_option(self, name: str, descr: str, value: T.Any, choices: T.Any) -> None: + value = stringify(value) + choices = stringify(choices) + self._add_line(mlog.green(name), mlog.yellow(value), mlog.blue(choices), descr) + + def add_title(self, title: str) -> None: + newtitle = mlog.cyan(title) + descr = mlog.cyan('Description') + value = mlog.cyan('Default Value' if self.default_values_only else 'Current Value') + choices = mlog.cyan('Possible Values') + self._add_line('', '', '', '') + self._add_line(newtitle, value, choices, descr) + self._add_line('-' * len(newtitle), '-' * len(value), '-' * len(choices), '-' * len(descr)) + + def add_section(self, section: str) -> None: + self.print_margin = 0 + self._add_line('', '', '', '') + self._add_line(mlog.normal_yellow(section + ':'), '', '', '') + self.print_margin = 2 + + def print_options(self, title: str, options: 'coredata.KeyedOptionDictType') -> None: + if not options: + return + if title: + self.add_title(title) + auto = T.cast('coredata.UserFeatureOption', self.coredata.options[OptionKey('auto_features')]) + for k, o in sorted(options.items()): + printable_value = o.printable_value() + root = k.as_root() + if o.yielding and k.subproject and root in self.coredata.options: + printable_value = '' + if isinstance(o, coredata.UserFeatureOption) and o.is_auto(): + printable_value = auto.printable_value() + self.add_option(str(root), o.description, printable_value, o.choices) + + def print_conf(self, pager: bool) -> None: + if pager: + mlog.start_pager() + + def print_default_values_warning() -> None: + mlog.warning('The source directory instead of the build directory was specified.') + mlog.warning('Only the default values for the project are printed.') + + if self.default_values_only: + print_default_values_warning() + mlog.log('') + + mlog.log('Core properties:') + mlog.log(' Source dir', self.source_dir) + if not self.default_values_only: + mlog.log(' Build dir ', self.build_dir) + + dir_option_names = set(coredata.BUILTIN_DIR_OPTIONS) + test_option_names = {OptionKey('errorlogs'), + OptionKey('stdsplit')} + + dir_options: 'coredata.MutableKeyedOptionDictType' = {} + test_options: 'coredata.MutableKeyedOptionDictType' = {} + core_options: 'coredata.MutableKeyedOptionDictType' = {} + module_options: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = collections.defaultdict(dict) + for k, v in self.coredata.options.items(): + if k in dir_option_names: + dir_options[k] = v + elif k in test_option_names: + test_options[k] = v + elif k.module: + # Ignore module options if we did not use that module during + # configuration. + if self.build and k.module not in self.build.modules: + continue + module_options[k.module][k] = v + elif k.is_builtin(): + core_options[k] = v + + host_core_options = self.split_options_per_subproject({k: v for k, v in core_options.items() if k.machine is MachineChoice.HOST}) + build_core_options = self.split_options_per_subproject({k: v for k, v in core_options.items() if k.machine is MachineChoice.BUILD}) + host_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_compiler() and k.machine is MachineChoice.HOST}) + build_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_compiler() and k.machine is MachineChoice.BUILD}) + project_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_project()}) + show_build_options = self.default_values_only or self.build.environment.is_cross_build() + + self.add_section('Main project options') + self.print_options('Core options', host_core_options['']) + if show_build_options: + self.print_options('', build_core_options['']) + self.print_options('Backend options', {k: v for k, v in self.coredata.options.items() if k.is_backend()}) + self.print_options('Base options', {k: v for k, v in self.coredata.options.items() if k.is_base()}) + self.print_options('Compiler options', host_compiler_options.get('', {})) + if show_build_options: + self.print_options('', build_compiler_options.get('', {})) + for mod, mod_options in module_options.items(): + self.print_options(f'{mod} module options', mod_options) + self.print_options('Directories', dir_options) + self.print_options('Testing options', test_options) + self.print_options('Project options', project_options.get('', {})) + for subproject in sorted(self.all_subprojects): + if subproject == '': + continue + self.add_section('Subproject ' + subproject) + if subproject in host_core_options: + self.print_options('Core options', host_core_options[subproject]) + if subproject in build_core_options and show_build_options: + self.print_options('', build_core_options[subproject]) + if subproject in host_compiler_options: + self.print_options('Compiler options', host_compiler_options[subproject]) + if subproject in build_compiler_options and show_build_options: + self.print_options('', build_compiler_options[subproject]) + if subproject in project_options: + self.print_options('Project options', project_options[subproject]) + self.print_aligned() + + # Print the warning twice so that the user shouldn't be able to miss it + if self.default_values_only: + mlog.log('') + print_default_values_warning() + + self.print_nondefault_buildtype_options() + + def print_nondefault_buildtype_options(self) -> None: + mismatching = self.coredata.get_nondefault_buildtype_args() + if not mismatching: + return + mlog.log("\nThe following option(s) have a different value than the build type default\n") + mlog.log(' current default') + for m in mismatching: + mlog.log(f'{m[0]:21}{m[1]:10}{m[2]:10}') + +def run(options: argparse.Namespace) -> int: + coredata.parse_cmd_line_options(options) + builddir = os.path.abspath(os.path.realpath(options.builddir)) + print_only = not options.cmd_line_options and not options.clearcache + c = None + try: + c = Conf(builddir) + if c.default_values_only and not print_only: + raise mesonlib.MesonException('No valid build directory found, cannot modify options.') + if c.default_values_only or print_only: + c.print_conf(options.pager) + return 0 + + save = False + if options.cmd_line_options: + save = c.set_options(options.cmd_line_options) + coredata.update_cmd_line_file(builddir, options) + if options.clearcache: + c.clear_cache() + save = True + if save: + c.save() + mintro.update_build_options(c.coredata, c.build.environment.info_dir) + mintro.write_meson_info_file(c.build, []) + except ConfException as e: + mlog.log('Meson configurator encountered an error:') + if c is not None and c.build is not None: + mintro.write_meson_info_file(c.build, [e]) + raise e + except BrokenPipeError: + # Pager quit before we wrote everything. + pass + return 0 diff --git a/devtools/meson/mesonbuild/mdevenv.py b/devtools/meson/mesonbuild/mdevenv.py new file mode 100644 index 0000000..9c29847 --- /dev/null +++ b/devtools/meson/mesonbuild/mdevenv.py @@ -0,0 +1,231 @@ +from __future__ import annotations + +import os, subprocess +import argparse +import tempfile +import shutil +import itertools + +from pathlib import Path +from . import build, minstall +from .mesonlib import (MesonException, is_windows, setup_vsenv, OptionKey, + get_wine_shortpath, MachineChoice) +from . import mlog + +import typing as T +if T.TYPE_CHECKING: + from .backends import InstallData + +POWERSHELL_EXES = {'pwsh.exe', 'powershell.exe'} + +def add_arguments(parser: argparse.ArgumentParser) -> None: + parser.add_argument('-C', dest='builddir', type=Path, default='.', + help='Path to build directory') + parser.add_argument('--workdir', '-w', type=Path, default=None, + help='Directory to cd into before running (default: builddir, Since 1.0.0)') + parser.add_argument('--dump', nargs='?', const=True, + help='Only print required environment (Since 0.62.0) ' + + 'Takes an optional file path (Since 1.1.0)') + parser.add_argument('--dump-format', default='export', + choices=['sh', 'export', 'vscode'], + help='Format used with --dump (Since 1.1.0)') + parser.add_argument('devcmd', nargs=argparse.REMAINDER, metavar='command', + help='Command to run in developer environment (default: interactive shell)') + +def get_windows_shell() -> T.Optional[str]: + mesonbuild = Path(__file__).parent + script = mesonbuild / 'scripts' / 'cmd_or_ps.ps1' + for shell in POWERSHELL_EXES: + try: + command = [shell, '-noprofile', '-executionpolicy', 'bypass', '-file', str(script)] + result = subprocess.check_output(command) + return result.decode().strip() + except (subprocess.CalledProcessError, OSError): + pass + return None + +def reduce_winepath(env: T.Dict[str, str]) -> None: + winepath = env.get('WINEPATH') + if not winepath: + return + winecmd = shutil.which('wine64') or shutil.which('wine') + if not winecmd: + return + env['WINEPATH'] = get_wine_shortpath([winecmd], winepath.split(';')) + mlog.log('Meson detected wine and has set WINEPATH accordingly') + +def get_env(b: build.Build, dump_fmt: T.Optional[str]) -> T.Tuple[T.Dict[str, str], T.Set[str]]: + extra_env = build.EnvironmentVariables() + extra_env.set('MESON_DEVENV', ['1']) + extra_env.set('MESON_PROJECT_NAME', [b.project_name]) + + sysroot = b.environment.properties[MachineChoice.HOST].get_sys_root() + if sysroot: + extra_env.set('QEMU_LD_PREFIX', [sysroot]) + + env = {} if dump_fmt else os.environ.copy() + default_fmt = '${0}' if dump_fmt in {'sh', 'export'} else None + varnames = set() + for i in itertools.chain(b.devenv, {extra_env}): + env = i.get_env(env, default_fmt) + varnames |= i.get_names() + + reduce_winepath(env) + + return env, varnames + +def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List[str]: + from .dependencies.pkgconfig import PkgConfigDependency + result = [] + dep = PkgConfigDependency('bash-completion', b.environment, + {'required': False, 'silent': True, 'version': '>=2.10'}) + if dep.found(): + prefix = b.environment.coredata.get_option(OptionKey('prefix')) + assert isinstance(prefix, str), 'for mypy' + datadir = b.environment.coredata.get_option(OptionKey('datadir')) + assert isinstance(datadir, str), 'for mypy' + datadir_abs = os.path.join(prefix, datadir) + completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=['datadir', datadir_abs]) + assert isinstance(completionsdir, str), 'for mypy' + completionsdir_path = Path(completionsdir) + for f in install_data.data: + if completionsdir_path in Path(f.install_path).parents: + result.append(f.path) + return result + +def add_gdb_auto_load(autoload_path: Path, gdb_helper: str, fname: Path) -> None: + # Copy or symlink the GDB helper into our private directory tree + destdir = autoload_path / fname.parent + destdir.mkdir(parents=True, exist_ok=True) + try: + if is_windows(): + shutil.copy(gdb_helper, str(destdir / os.path.basename(gdb_helper))) + else: + os.symlink(gdb_helper, str(destdir / os.path.basename(gdb_helper))) + except (FileExistsError, shutil.SameFileError): + pass + +def write_gdb_script(privatedir: Path, install_data: 'InstallData', workdir: Path) -> None: + if not shutil.which('gdb'): + return + bdir = privatedir.parent + autoload_basedir = privatedir / 'gdb-auto-load' + autoload_path = Path(autoload_basedir, *bdir.parts[1:]) + have_gdb_helpers = False + for d in install_data.data: + if d.path.endswith('-gdb.py') or d.path.endswith('-gdb.gdb') or d.path.endswith('-gdb.scm'): + # This GDB helper is made for a specific shared library, search if + # we have it in our builddir. + libname = Path(d.path).name.rsplit('-', 1)[0] + for t in install_data.targets: + path = Path(t.fname) + if path.name == libname: + add_gdb_auto_load(autoload_path, d.path, path) + have_gdb_helpers = True + if have_gdb_helpers: + gdbinit_line = f'add-auto-load-scripts-directory {autoload_basedir}\n' + gdbinit_path = bdir / '.gdbinit' + first_time = False + try: + with gdbinit_path.open('r+', encoding='utf-8') as f: + if gdbinit_line not in f.readlines(): + f.write(gdbinit_line) + first_time = True + except FileNotFoundError: + gdbinit_path.write_text(gdbinit_line, encoding='utf-8') + first_time = True + if first_time: + gdbinit_path = gdbinit_path.resolve() + workdir_path = workdir.resolve() + rel_path = gdbinit_path.relative_to(workdir_path) + mlog.log('Meson detected GDB helpers and added config in', mlog.bold(str(rel_path))) + mlog.log('To load it automatically you might need to:') + mlog.log(' - Add', mlog.bold(f'add-auto-load-safe-path {gdbinit_path.parent}'), + 'in', mlog.bold('~/.gdbinit')) + if gdbinit_path.parent != workdir_path: + mlog.log(' - Change current workdir to', mlog.bold(str(rel_path.parent)), + 'or use', mlog.bold(f'--init-command {rel_path}')) + +def dump(devenv: T.Dict[str, str], varnames: T.Set[str], dump_format: T.Optional[str], output: T.Optional[T.TextIO] = None) -> None: + for name in varnames: + print(f'{name}="{devenv[name]}"', file=output) + if dump_format == 'export': + print(f'export {name}', file=output) + +def run(options: argparse.Namespace) -> int: + privatedir = Path(options.builddir) / 'meson-private' + buildfile = privatedir / 'build.dat' + if not buildfile.is_file(): + raise MesonException(f'Directory {options.builddir!r} does not seem to be a Meson build directory.') + b = build.load(options.builddir) + workdir = options.workdir or options.builddir + + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) # Call it before get_env to get vsenv vars as well + dump_fmt = options.dump_format if options.dump else None + devenv, varnames = get_env(b, dump_fmt) + if options.dump: + if options.devcmd: + raise MesonException('--dump option does not allow running other command.') + if options.dump is True: + dump(devenv, varnames, dump_fmt) + else: + with open(options.dump, "w", encoding='utf-8') as output: + dump(devenv, varnames, dump_fmt, output) + return 0 + + if b.environment.need_exe_wrapper(): + m = 'An executable wrapper could be required' + exe_wrapper = b.environment.get_exe_wrapper() + if exe_wrapper: + cmd = ' '.join(exe_wrapper.get_command()) + m += f': {cmd}' + mlog.log(m) + + install_data = minstall.load_install_data(str(privatedir / 'install.dat')) + write_gdb_script(privatedir, install_data, workdir) + + args = options.devcmd + if not args: + prompt_prefix = f'[{b.project_name}]' + shell_env = os.environ.get("SHELL") + # Prefer $SHELL in a MSYS2 bash despite it being Windows + if shell_env and os.path.exists(shell_env): + args = [shell_env] + elif is_windows(): + shell = get_windows_shell() + if not shell: + mlog.warning('Failed to determine Windows shell, fallback to cmd.exe') + if shell in POWERSHELL_EXES: + args = [shell, '-NoLogo', '-NoExit'] + prompt = f'function global:prompt {{ "{prompt_prefix} PS " + $PWD + "> "}}' + args += ['-Command', prompt] + else: + args = [os.environ.get("COMSPEC", r"C:\WINDOWS\system32\cmd.exe")] + args += ['/k', f'prompt {prompt_prefix} $P$G'] + else: + args = [os.environ.get("SHELL", os.path.realpath("/bin/sh"))] + if "bash" in args[0]: + # Let the GC remove the tmp file + tmprc = tempfile.NamedTemporaryFile(mode='w') + tmprc.write('[ -e ~/.bashrc ] && . ~/.bashrc\n') + if not os.environ.get("MESON_DISABLE_PS1_OVERRIDE"): + tmprc.write(f'export PS1="{prompt_prefix} $PS1"\n') + for f in bash_completion_files(b, install_data): + tmprc.write(f'. "{f}"\n') + tmprc.flush() + args.append("--rcfile") + args.append(tmprc.name) + else: + # Try to resolve executable using devenv's PATH + abs_path = shutil.which(args[0], path=devenv.get('PATH', None)) + args[0] = abs_path or args[0] + + try: + return subprocess.call(args, close_fds=False, + env=devenv, + cwd=workdir) + except subprocess.CalledProcessError as e: + return e.returncode + except FileNotFoundError: + raise MesonException(f'Command not found: {args[0]}') diff --git a/devtools/meson/mesonbuild/mdist.py b/devtools/meson/mesonbuild/mdist.py new file mode 100644 index 0000000..089056b --- /dev/null +++ b/devtools/meson/mesonbuild/mdist.py @@ -0,0 +1,383 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +import abc +import argparse +import gzip +import os +import sys +import shlex +import shutil +import subprocess +import tarfile +import tempfile +import hashlib +import typing as T + +from dataclasses import dataclass +from glob import glob +from pathlib import Path +from mesonbuild.environment import detect_ninja +from mesonbuild.mesonlib import (MesonException, RealPathAction, quiet_git, + windows_proof_rmtree, setup_vsenv, OptionKey) +from mesonbuild.msetup import add_arguments as msetup_argparse +from mesonbuild.wrap import wrap +from mesonbuild import mlog, build, coredata +from .scripts.meson_exe import run_exe + +if T.TYPE_CHECKING: + from ._typing import ImmutableListProtocol + from .mesonlib import ExecutableSerialisation + +archive_choices = ['gztar', 'xztar', 'zip'] + +archive_extension = {'gztar': '.tar.gz', + 'xztar': '.tar.xz', + 'zip': '.zip'} + +def add_arguments(parser: argparse.ArgumentParser) -> None: + parser.add_argument('-C', dest='wd', action=RealPathAction, + help='directory to cd into before running') + parser.add_argument('--allow-dirty', action='store_true', + help='Allow even when repository contains uncommitted changes.') + parser.add_argument('--formats', default='xztar', + help='Comma separated list of archive types to create. Supports xztar (default), gztar, and zip.') + parser.add_argument('--include-subprojects', action='store_true', + help='Include source code of subprojects that have been used for the build.') + parser.add_argument('--no-tests', action='store_true', + help='Do not build and test generated packages.') + + +def create_hash(fname: str) -> None: + hashname = fname + '.sha256sum' + m = hashlib.sha256() + m.update(open(fname, 'rb').read()) + with open(hashname, 'w', encoding='utf-8') as f: + # A space and an asterisk because that is the format defined by GNU coreutils + # and accepted by busybox and the Perl shasum tool. + f.write('{} *{}\n'.format(m.hexdigest(), os.path.basename(fname))) + + +msg_uncommitted_changes = 'Repository has uncommitted changes that will not be included in the dist tarball' + +def handle_dirty_opt(msg: str, allow_dirty: bool) -> None: + if allow_dirty: + mlog.warning(msg) + else: + mlog.error(msg + '\n' + 'Use --allow-dirty to ignore the warning and proceed anyway') + sys.exit(1) + +def is_git(src_root: str) -> bool: + ''' + Checks if meson.build file at the root source directory is tracked by git. + It could be a subproject part of the parent project git repository. + ''' + return quiet_git(['ls-files', '--error-unmatch', 'meson.build'], src_root)[0] + +def is_hg(src_root: str) -> bool: + return os.path.isdir(os.path.join(src_root, '.hg')) + + +@dataclass +class Dist(metaclass=abc.ABCMeta): + dist_name: str + src_root: str + bld_root: str + dist_scripts: T.List[ExecutableSerialisation] + subprojects: T.Dict[str, str] + options: argparse.Namespace + + def __post_init__(self) -> None: + self.dist_sub = os.path.join(self.bld_root, 'meson-dist') + self.distdir = os.path.join(self.dist_sub, self.dist_name) + + @abc.abstractmethod + def create_dist(self, archives: T.List[str]) -> T.List[str]: + pass + + def run_dist_scripts(self) -> None: + assert os.path.isabs(self.distdir) + env = {} + env['MESON_DIST_ROOT'] = self.distdir + env['MESON_SOURCE_ROOT'] = self.src_root + env['MESON_BUILD_ROOT'] = self.bld_root + for d in self.dist_scripts: + if d.subproject and d.subproject not in self.subprojects: + continue + subdir = self.subprojects.get(d.subproject, '') + env['MESON_PROJECT_DIST_ROOT'] = os.path.join(self.distdir, subdir) + env['MESON_PROJECT_SOURCE_ROOT'] = os.path.join(self.src_root, subdir) + env['MESON_PROJECT_BUILD_ROOT'] = os.path.join(self.bld_root, subdir) + name = ' '.join(d.cmd_args) + print(f'Running custom dist script {name!r}') + try: + rc = run_exe(d, env) + if rc != 0: + sys.exit('Dist script errored out') + except OSError: + print(f'Failed to run dist script {name!r}') + sys.exit(1) + + +class GitDist(Dist): + def git_root(self, dir_: str) -> Path: + # Cannot use --show-toplevel here because git in our CI prints cygwin paths + # that python cannot resolve. Workaround this by taking parent of src_root. + prefix = quiet_git(['rev-parse', '--show-prefix'], dir_, check=True)[1].strip() + if not prefix: + return Path(dir_) + prefix_level = len(Path(prefix).parents) + return Path(dir_).parents[prefix_level - 1] + + def have_dirty_index(self) -> bool: + '''Check whether there are uncommitted changes in git''' + ret = subprocess.call(['git', '-C', self.src_root, 'diff-index', '--quiet', 'HEAD']) + return ret == 1 + + def copy_git(self, src: T.Union[str, os.PathLike], distdir: str, revision: str = 'HEAD', + prefix: T.Optional[str] = None, subdir: T.Optional[str] = None) -> None: + cmd = ['git', 'archive', '--format', 'tar', revision] + if prefix is not None: + cmd.insert(2, f'--prefix={prefix}/') + if subdir is not None: + cmd.extend(['--', subdir]) + with tempfile.TemporaryFile() as f: + subprocess.check_call(cmd, cwd=src, stdout=f) + f.seek(0) + t = tarfile.open(fileobj=f) # [ignore encoding] + t.extractall(path=distdir) + + def process_git_project(self, src_root: str, distdir: str) -> None: + if self.have_dirty_index(): + handle_dirty_opt(msg_uncommitted_changes, self.options.allow_dirty) + if os.path.exists(distdir): + windows_proof_rmtree(distdir) + repo_root = self.git_root(src_root) + if repo_root.samefile(src_root): + os.makedirs(distdir) + self.copy_git(src_root, distdir) + else: + subdir = Path(src_root).relative_to(repo_root) + tmp_distdir = distdir + '-tmp' + if os.path.exists(tmp_distdir): + windows_proof_rmtree(tmp_distdir) + os.makedirs(tmp_distdir) + self.copy_git(repo_root, tmp_distdir, subdir=str(subdir)) + Path(tmp_distdir, subdir).rename(distdir) + windows_proof_rmtree(tmp_distdir) + self.process_submodules(src_root, distdir) + + def process_submodules(self, src: str, distdir: str) -> None: + module_file = os.path.join(src, '.gitmodules') + if not os.path.exists(module_file): + return + cmd = ['git', 'submodule', 'status', '--cached', '--recursive'] + modlist = subprocess.check_output(cmd, cwd=src, universal_newlines=True).splitlines() + for submodule in modlist: + status = submodule[:1] + sha1, rest = submodule[1:].split(' ', 1) + subpath = rest.rsplit(' ', 1)[0] + + if status == '-': + mlog.warning(f'Submodule {subpath!r} is not checked out and cannot be added to the dist') + continue + elif status in {'+', 'U'}: + handle_dirty_opt(f'Submodule {subpath!r} has uncommitted changes that will not be included in the dist tarball', self.options.allow_dirty) + + self.copy_git(os.path.join(src, subpath), distdir, revision=sha1, prefix=subpath) + + def create_dist(self, archives: T.List[str]) -> T.List[str]: + self.process_git_project(self.src_root, self.distdir) + for path in self.subprojects.values(): + sub_src_root = os.path.join(self.src_root, path) + sub_distdir = os.path.join(self.distdir, path) + if os.path.exists(sub_distdir): + continue + if is_git(sub_src_root): + self.process_git_project(sub_src_root, sub_distdir) + else: + shutil.copytree(sub_src_root, sub_distdir) + self.run_dist_scripts() + output_names = [] + for a in archives: + compressed_name = self.distdir + archive_extension[a] + shutil.make_archive(self.distdir, a, root_dir=self.dist_sub, base_dir=self.dist_name) + output_names.append(compressed_name) + windows_proof_rmtree(self.distdir) + return output_names + + +class HgDist(Dist): + def have_dirty_index(self) -> bool: + '''Check whether there are uncommitted changes in hg''' + out = subprocess.check_output(['hg', '-R', self.src_root, 'summary']) + return b'commit: (clean)' not in out + + def create_dist(self, archives: T.List[str]) -> T.List[str]: + if self.have_dirty_index(): + handle_dirty_opt(msg_uncommitted_changes, self.options.allow_dirty) + if self.dist_scripts: + mlog.warning('dist scripts are not supported in Mercurial projects') + + os.makedirs(self.dist_sub, exist_ok=True) + tarname = os.path.join(self.dist_sub, self.dist_name + '.tar') + xzname = tarname + '.xz' + gzname = tarname + '.gz' + zipname = os.path.join(self.dist_sub, self.dist_name + '.zip') + # Note that -X interprets relative paths using the current working + # directory, not the repository root, so this must be an absolute path: + # https://bz.mercurial-scm.org/show_bug.cgi?id=6267 + # + # .hg[a-z]* is used instead of .hg* to keep .hg_archival.txt, which may + # be useful to link the tarball to the Mercurial revision for either + # manual inspection or in case any code interprets it for a --version or + # similar. + subprocess.check_call(['hg', 'archive', '-R', self.src_root, '-S', '-t', 'tar', + '-X', self.src_root + '/.hg[a-z]*', tarname]) + output_names = [] + if 'xztar' in archives: + import lzma + with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf: + shutil.copyfileobj(tf, xf) + output_names.append(xzname) + if 'gztar' in archives: + with gzip.open(gzname, 'wb') as zf, open(tarname, 'rb') as tf: + shutil.copyfileobj(tf, zf) + output_names.append(gzname) + os.unlink(tarname) + if 'zip' in archives: + subprocess.check_call(['hg', 'archive', '-R', self.src_root, '-S', '-t', 'zip', zipname]) + output_names.append(zipname) + return output_names + + +def run_dist_steps(meson_command: T.List[str], unpacked_src_dir: str, builddir: str, installdir: str, ninja_args: T.List[str]) -> int: + if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0: + print('Running Meson on distribution package failed') + return 1 + if subprocess.call(ninja_args, cwd=builddir) != 0: + print('Compiling the distribution package failed') + return 1 + if subprocess.call(ninja_args + ['test'], cwd=builddir) != 0: + print('Running unit tests on the distribution package failed') + return 1 + myenv = os.environ.copy() + myenv['DESTDIR'] = installdir + if subprocess.call(ninja_args + ['install'], cwd=builddir, env=myenv) != 0: + print('Installing the distribution package failed') + return 1 + return 0 + +def check_dist(packagename: str, meson_command: ImmutableListProtocol[str], extra_meson_args: T.List[str], bld_root: str, privdir: str) -> int: + print(f'Testing distribution package {packagename}') + unpackdir = os.path.join(privdir, 'dist-unpack') + builddir = os.path.join(privdir, 'dist-build') + installdir = os.path.join(privdir, 'dist-install') + for p in (unpackdir, builddir, installdir): + if os.path.exists(p): + windows_proof_rmtree(p) + os.mkdir(p) + ninja_args = detect_ninja() + shutil.unpack_archive(packagename, unpackdir) + unpacked_files = glob(os.path.join(unpackdir, '*')) + assert len(unpacked_files) == 1 + unpacked_src_dir = unpacked_files[0] + meson_command += ['setup'] + meson_command += create_cmdline_args(bld_root) + meson_command += extra_meson_args + + ret = run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_args) + if ret > 0: + print(f'Dist check build directory was {builddir}') + else: + windows_proof_rmtree(unpackdir) + windows_proof_rmtree(builddir) + windows_proof_rmtree(installdir) + print(f'Distribution package {packagename} tested') + return ret + +def create_cmdline_args(bld_root: str) -> T.List[str]: + parser = argparse.ArgumentParser() + msetup_argparse(parser) + args = parser.parse_args([]) + coredata.parse_cmd_line_options(args) + coredata.read_cmd_line_file(bld_root, args) + args.cmd_line_options.pop(OptionKey('backend'), '') + return shlex.split(coredata.format_cmd_line_options(args)) + +def determine_archives_to_generate(options: argparse.Namespace) -> T.List[str]: + result = [] + for i in options.formats.split(','): + if i not in archive_choices: + sys.exit(f'Value "{i}" not one of permitted values {archive_choices}.') + result.append(i) + if len(i) == 0: + sys.exit('No archive types specified.') + return result + +def run(options: argparse.Namespace) -> int: + buildfile = Path(options.wd) / 'meson-private' / 'build.dat' + if not buildfile.is_file(): + raise MesonException(f'Directory {options.wd!r} does not seem to be a Meson build directory.') + b = build.load(options.wd) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) + # This import must be load delayed, otherwise it will get the default + # value of None. + from mesonbuild.mesonlib import get_meson_command + src_root = b.environment.source_dir + bld_root = b.environment.build_dir + priv_dir = os.path.join(bld_root, 'meson-private') + + dist_name = b.project_name + '-' + b.project_version + + archives = determine_archives_to_generate(options) + + subprojects = {} + extra_meson_args = [] + if options.include_subprojects: + subproject_dir = os.path.join(src_root, b.subproject_dir) + for sub in b.subprojects: + directory = wrap.get_directory(subproject_dir, sub) + subprojects[sub] = os.path.join(b.subproject_dir, directory) + extra_meson_args.append('-Dwrap_mode=nodownload') + + cls: T.Type[Dist] + if is_git(src_root): + cls = GitDist + elif is_hg(src_root): + if subprojects: + print('--include-subprojects option currently not supported with Mercurial') + return 1 + cls = HgDist + else: + print('Dist currently only works with Git or Mercurial repos') + return 1 + + project = cls(dist_name, src_root, bld_root, b.dist_scripts, subprojects, options) + names = project.create_dist(archives) + + if names is None: + return 1 + rc = 0 + if not options.no_tests: + # Check only one. + rc = check_dist(names[0], get_meson_command(), extra_meson_args, bld_root, priv_dir) + if rc == 0: + for name in names: + create_hash(name) + print('Created', name) + return rc diff --git a/devtools/meson/mesonbuild/mesondata.py b/devtools/meson/mesonbuild/mesondata.py new file mode 100644 index 0000000..da641fd --- /dev/null +++ b/devtools/meson/mesonbuild/mesondata.py @@ -0,0 +1,48 @@ +# Copyright 2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +import importlib.resources +from pathlib import PurePosixPath, Path +import typing as T + +if T.TYPE_CHECKING: + from .environment import Environment + +class DataFile: + def __init__(self, path: str) -> None: + self.path = PurePosixPath(path) + + def write_once(self, path: Path) -> None: + if not path.exists(): + data = importlib.resources.read_text( # [ignore encoding] it's on the next lines, Mr. Lint + ('mesonbuild' / self.path.parent).as_posix().replace('/', '.'), + self.path.name, + encoding='utf-8') + path.write_text(data, encoding='utf-8') + + def write_to_private(self, env: 'Environment') -> Path: + try: + resource = importlib.resources.files('mesonbuild') / self.path + if isinstance(resource, Path): + return resource + except AttributeError: + # fall through to python 3.7 compatible code + pass + + out_file = Path(env.scratch_dir) / 'data' / self.path.name + out_file.parent.mkdir(exist_ok=True) + self.write_once(out_file) + return out_file diff --git a/devtools/meson/mesonbuild/mesonlib.py b/devtools/meson/mesonbuild/mesonlib.py new file mode 100644 index 0000000..be69a12 --- /dev/null +++ b/devtools/meson/mesonbuild/mesonlib.py @@ -0,0 +1,35 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright 2012-2021 The Meson development team +# Copyright © 2021 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# pylint: skip-file + +"""Helper functions and classes.""" + +import os + +from .utils.core import * +from .utils.vsenv import * + +from .utils.universal import * + +# Here we import either the posix implementations, the windows implementations, +# or a generic no-op implementation +if os.name == 'posix': + from .utils.posix import * +elif os.name == 'nt': + from .utils.win32 import * +else: + from .utils.platform import * diff --git a/devtools/meson/mesonbuild/mesonmain.py b/devtools/meson/mesonbuild/mesonmain.py new file mode 100644 index 0000000..72a7ab9 --- /dev/null +++ b/devtools/meson/mesonbuild/mesonmain.py @@ -0,0 +1,297 @@ +# Copyright 2012-2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +# Work around some pathlib bugs... + +from . import _pathlib +import sys +sys.modules['pathlib'] = _pathlib + +# This file is an entry point for all commands, including scripts. Include the +# strict minimum python modules for performance reasons. +import os.path +import platform +import importlib +import argparse + +from .utils.core import MesonException, MesonBugException +from . import mlog + +def errorhandler(e, command): + import traceback + if isinstance(e, MesonException): + mlog.exception(e) + logfile = mlog.shutdown() + if logfile is not None: + mlog.log("\nA full log can be found at", mlog.bold(logfile)) + if os.environ.get('MESON_FORCE_BACKTRACE'): + raise e + return 1 + else: + # We assume many types of traceback are Meson logic bugs, but most + # particularly anything coming from the interpreter during `setup`. + # Some things definitely aren't: + # - PermissionError is always a problem in the user environment + # - runpython doesn't run Meson's own code, even though it is + # dispatched by our run() + if os.environ.get('MESON_FORCE_BACKTRACE'): + raise e + traceback.print_exc() + + if command == 'runpython': + return 2 + elif isinstance(e, OSError): + mlog.exception("Unhandled python OSError. This is probably not a Meson bug, " + "but an issue with your build environment.") + return e.errno + else: # Exception + msg = 'Unhandled python exception' + if all(getattr(e, a, None) is not None for a in ['file', 'lineno', 'colno']): + e = MesonBugException(msg, e.file, e.lineno, e.colno) # type: ignore + else: + e = MesonBugException(msg) + mlog.exception(e) + return 2 + +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ +class CommandLineParser: + def __init__(self): + # only import these once we do full argparse processing + from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv + from .scripts import env2mfile + from .wrap import wraptool + import shutil + + self.term_width = shutil.get_terminal_size().columns + self.formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=int(self.term_width / 2), width=self.term_width) + + self.commands = {} + self.hidden_commands = [] + self.parser = argparse.ArgumentParser(prog='meson', formatter_class=self.formatter) + self.subparsers = self.parser.add_subparsers(title='Commands', dest='command', + description='If no command is specified it defaults to setup command.') + self.add_command('setup', msetup.add_arguments, msetup.run, + help_msg='Configure the project') + self.add_command('configure', mconf.add_arguments, mconf.run, + help_msg='Change project options',) + self.add_command('dist', mdist.add_arguments, mdist.run, + help_msg='Generate release archive',) + self.add_command('install', minstall.add_arguments, minstall.run, + help_msg='Install the project') + self.add_command('introspect', mintro.add_arguments, mintro.run, + help_msg='Introspect project') + self.add_command('init', minit.add_arguments, minit.run, + help_msg='Create a new project') + self.add_command('test', mtest.add_arguments, mtest.run, + help_msg='Run tests') + self.add_command('wrap', wraptool.add_arguments, wraptool.run, + help_msg='Wrap tools') + self.add_command('subprojects', msubprojects.add_arguments, msubprojects.run, + help_msg='Manage subprojects') + self.add_command('rewrite', lambda parser: rewriter.add_arguments(parser, self.formatter), rewriter.run, + help_msg='Modify the project definition') + self.add_command('compile', mcompile.add_arguments, mcompile.run, + help_msg='Build the project') + self.add_command('devenv', mdevenv.add_arguments, mdevenv.run, + help_msg='Run commands in developer environment') + self.add_command('env2mfile', env2mfile.add_arguments, env2mfile.run, + help_msg='Convert current environment to a cross or native file') + # Add new commands above this line to list them in help command + self.add_command('help', self.add_help_arguments, self.run_help_command, + help_msg='Print help of a subcommand') + + # Hidden commands + self.add_command('runpython', self.add_runpython_arguments, self.run_runpython_command, + help_msg=argparse.SUPPRESS) + self.add_command('unstable-coredata', munstable_coredata.add_arguments, munstable_coredata.run, + help_msg=argparse.SUPPRESS) + + def add_command(self, name, add_arguments_func, run_func, help_msg, aliases=None): + aliases = aliases or [] + # FIXME: Cannot have hidden subparser: + # https://bugs.python.org/issue22848 + if help_msg == argparse.SUPPRESS: + p = argparse.ArgumentParser(prog='meson ' + name, formatter_class=self.formatter) + self.hidden_commands.append(name) + else: + p = self.subparsers.add_parser(name, help=help_msg, aliases=aliases, formatter_class=self.formatter) + add_arguments_func(p) + p.set_defaults(run_func=run_func) + for i in [name] + aliases: + self.commands[i] = p + + def add_runpython_arguments(self, parser: argparse.ArgumentParser): + parser.add_argument('-c', action='store_true', dest='eval_arg', default=False) + parser.add_argument('--version', action='version', version=platform.python_version()) + parser.add_argument('script_file') + parser.add_argument('script_args', nargs=argparse.REMAINDER) + + def run_runpython_command(self, options): + sys.argv[1:] = options.script_args + if options.eval_arg: + exec(options.script_file) + else: + import runpy + sys.path.insert(0, os.path.dirname(options.script_file)) + runpy.run_path(options.script_file, run_name='__main__') + return 0 + + def add_help_arguments(self, parser): + parser.add_argument('command', nargs='?', choices=list(self.commands.keys())) + + def run_help_command(self, options): + if options.command: + self.commands[options.command].print_help() + else: + self.parser.print_help() + return 0 + + def run(self, args): + implicit_setup_command_notice = False + # If first arg is not a known command, assume user wants to run the setup + # command. + known_commands = list(self.commands.keys()) + ['-h', '--help'] + if not args or args[0] not in known_commands: + implicit_setup_command_notice = True + args = ['setup'] + args + + # Hidden commands have their own parser instead of using the global one + if args[0] in self.hidden_commands: + command = args[0] + parser = self.commands[command] + args = args[1:] + else: + parser = self.parser + command = None + + from . import mesonlib + args = mesonlib.expand_arguments(args) + options = parser.parse_args(args) + + if command is None: + command = options.command + + # Bump the version here in order to add a pre-exit warning that we are phasing out + # support for old python. If this is already the oldest supported version, then + # this can never be true and does nothing. + pending_python_deprecation_notice = \ + command in {'setup', 'compile', 'test', 'install'} and sys.version_info < (3, 7) + + try: + return options.run_func(options) + except Exception as e: + return errorhandler(e, command) + finally: + if implicit_setup_command_notice: + mlog.warning('Running the setup command as `meson [options]` instead of ' + '`meson setup [options]` is ambiguous and deprecated.', fatal=False) + if pending_python_deprecation_notice: + mlog.notice('You are using Python 3.6 which is EOL. Starting with v0.62.0, ' + 'Meson will require Python 3.7 or newer', fatal=False) + mlog.shutdown() + +def run_script_command(script_name, script_args): + # Map script name to module name for those that doesn't match + script_map = {'exe': 'meson_exe', + 'install': 'meson_install', + 'delsuffix': 'delwithsuffix', + 'gtkdoc': 'gtkdochelper', + 'hotdoc': 'hotdochelper', + 'regencheck': 'regen_checker'} + module_name = script_map.get(script_name, script_name) + + try: + module = importlib.import_module('mesonbuild.scripts.' + module_name) + except ModuleNotFoundError as e: + mlog.exception(e) + return 1 + + try: + return module.run(script_args) + except MesonException as e: + mlog.error(f'Error in {script_name} helper script:') + mlog.exception(e) + return 1 + +def ensure_stdout_accepts_unicode(): + if sys.stdout.encoding and not sys.stdout.encoding.upper().startswith('UTF-'): + sys.stdout.reconfigure(errors='surrogateescape') + +def set_meson_command(mainfile): + # Set the meson command that will be used to run scripts and so on + from . import mesonlib + mesonlib.set_meson_command(mainfile) + +def run(original_args, mainfile): + if os.environ.get('MESON_SHOW_DEPRECATIONS'): + # workaround for https://bugs.python.org/issue34624 + import warnings + for typ in [DeprecationWarning, SyntaxWarning, FutureWarning, PendingDeprecationWarning]: + warnings.filterwarnings('error', category=typ, module='mesonbuild') + warnings.filterwarnings('ignore', message=".*importlib-resources.*") + + if sys.version_info >= (3, 10) and os.environ.get('MESON_RUNNING_IN_PROJECT_TESTS'): + # workaround for https://bugs.python.org/issue34624 + import warnings + warnings.filterwarnings('error', category=EncodingWarning, module='mesonbuild') + # python 3.11 adds a warning that in 3.15, UTF-8 mode will be default. + # This is fantastic news, we'd love that. Less fantastic: this warning is silly, + # we *want* these checks to be affected. Plus, the recommended alternative API + # would (in addition to warning people when UTF-8 mode removed the problem) also + # require using a minimum python version of 3.11 (in which the warning was added) + # or add verbose if/else soup. + warnings.filterwarnings('ignore', message="UTF-8 Mode affects .*getpreferredencoding", category=EncodingWarning) + + # Meson gets confused if stdout can't output Unicode, if the + # locale isn't Unicode, just force stdout to accept it. This tries + # to emulate enough of PEP 540 to work elsewhere. + ensure_stdout_accepts_unicode() + + # https://github.com/mesonbuild/meson/issues/3653 + if sys.platform == 'cygwin' and os.environ.get('MSYSTEM', '') not in ['MSYS', '']: + mlog.error('This python3 seems to be msys/python on MSYS2 Windows, but you are in a MinGW environment') + mlog.error('Please install and use mingw-w64-x86_64-python3 and/or mingw-w64-x86_64-meson with Pacman') + return 2 + + args = original_args[:] + + # Special handling of internal commands called from backends, they don't + # need to go through argparse. + if len(args) >= 2 and args[0] == '--internal': + if args[1] == 'regenerate': + set_meson_command(mainfile) + from . import msetup + try: + return msetup.run(['--reconfigure'] + args[2:]) + except Exception as e: + return errorhandler(e, 'setup') + else: + return run_script_command(args[1], args[2:]) + + set_meson_command(mainfile) + return CommandLineParser().run(args) + +def main(): + # Always resolve the command path so Ninja can find it for regen, tests, etc. + if 'meson.exe' in sys.executable: + assert os.path.isabs(sys.executable) + launcher = sys.executable + else: + launcher = os.path.abspath(sys.argv[0]) + return run(sys.argv[1:], launcher) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/devtools/meson/mesonbuild/minit.py b/devtools/meson/mesonbuild/minit.py new file mode 100644 index 0000000..7cca9cf --- /dev/null +++ b/devtools/meson/mesonbuild/minit.py @@ -0,0 +1,199 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Code that creates simple startup projects.""" + +from pathlib import Path +from enum import Enum +import subprocess +import shutil +import sys +import os +import re +from glob import glob +from mesonbuild import build, mesonlib, mlog +from mesonbuild.coredata import FORBIDDEN_TARGET_NAMES +from mesonbuild.environment import detect_ninja +from mesonbuild.templates.samplefactory import sameple_generator +import typing as T + +if T.TYPE_CHECKING: + import argparse + +''' +we currently have one meson template at this time. +''' +from mesonbuild.templates.mesontemplates import create_meson_build + +FORTRAN_SUFFIXES = {'.f', '.for', '.F', '.f90', '.F90'} +LANG_SUFFIXES = {'.c', '.cc', '.cpp', '.cs', '.cu', '.d', '.m', '.mm', '.rs', '.java', '.vala'} | FORTRAN_SUFFIXES +LANG_SUPPORTED = {'c', 'cpp', 'cs', 'cuda', 'd', 'fortran', 'java', 'rust', 'objc', 'objcpp', 'vala'} + +DEFAULT_PROJECT = 'executable' +DEFAULT_VERSION = '0.1' +class DEFAULT_TYPES(Enum): + EXE = 'executable' + LIB = 'library' + +INFO_MESSAGE = '''Sample project created. To build it run the +following commands: + +meson setup builddir +meson compile -C builddir +''' + + +def create_sample(options: 'argparse.Namespace') -> None: + ''' + Based on what arguments are passed we check for a match in language + then check for project type and create new Meson samples project. + ''' + sample_gen = sameple_generator(options) + if options.type == DEFAULT_TYPES['EXE'].value: + sample_gen.create_executable() + elif options.type == DEFAULT_TYPES['LIB'].value: + sample_gen.create_library() + else: + raise RuntimeError('Unreachable code') + print(INFO_MESSAGE) + +def autodetect_options(options: 'argparse.Namespace', sample: bool = False) -> None: + ''' + Here we autodetect options for args not passed in so don't have to + think about it. + ''' + if not options.name: + options.name = Path().resolve().stem + if not re.match('[a-zA-Z_][a-zA-Z0-9]*', options.name) and sample: + raise SystemExit(f'Name of current directory "{options.name}" is not usable as a sample project name.\n' + 'Specify a project name with --name.') + print(f'Using "{options.name}" (name of current directory) as project name.') + if not options.executable: + options.executable = options.name + print(f'Using "{options.executable}" (project name) as name of executable to build.') + if options.executable in FORBIDDEN_TARGET_NAMES: + raise mesonlib.MesonException(f'Executable name {options.executable!r} is reserved for Meson internal use. ' + 'Refusing to init an invalid project.') + if sample: + # The rest of the autodetection is not applicable to generating sample projects. + return + if not options.srcfiles: + srcfiles = [] + for f in (f for f in Path().iterdir() if f.is_file()): + if f.suffix in LANG_SUFFIXES: + srcfiles.append(f) + if not srcfiles: + raise SystemExit('No recognizable source files found.\n' + 'Run meson init in an empty directory to create a sample project.') + options.srcfiles = srcfiles + print("Detected source files: " + ' '.join(str(s) for s in srcfiles)) + options.srcfiles = [Path(f) for f in options.srcfiles] + if not options.language: + for f in options.srcfiles: + if f.suffix == '.c': + options.language = 'c' + break + if f.suffix in {'.cc', '.cpp'}: + options.language = 'cpp' + break + if f.suffix == '.cs': + options.language = 'cs' + break + if f.suffix == '.cu': + options.language = 'cuda' + break + if f.suffix == '.d': + options.language = 'd' + break + if f.suffix in FORTRAN_SUFFIXES: + options.language = 'fortran' + break + if f.suffix == '.rs': + options.language = 'rust' + break + if f.suffix == '.m': + options.language = 'objc' + break + if f.suffix == '.mm': + options.language = 'objcpp' + break + if f.suffix == '.java': + options.language = 'java' + break + if f.suffix == '.vala': + options.language = 'vala' + break + if not options.language: + raise SystemExit("Can't autodetect language, please specify it with -l.") + print("Detected language: " + options.language) + +def add_arguments(parser: 'argparse.ArgumentParser') -> None: + ''' + Here we add args for that the user can passed when making a new + Meson project. + ''' + parser.add_argument("srcfiles", metavar="sourcefile", nargs="*", help="source files. default: all recognized files in current directory") + parser.add_argument('-C', dest='wd', action=mesonlib.RealPathAction, + help='directory to cd into before running') + parser.add_argument("-n", "--name", help="project name. default: name of current directory") + parser.add_argument("-e", "--executable", help="executable name. default: project name") + parser.add_argument("-d", "--deps", help="dependencies, comma-separated") + parser.add_argument("-l", "--language", choices=sorted(LANG_SUPPORTED), help="project language. default: autodetected based on source files") + parser.add_argument("-b", "--build", action='store_true', help="build after generation") + parser.add_argument("--builddir", default='build', help="directory for build") + parser.add_argument("-f", "--force", action="store_true", help="force overwrite of existing files and directories.") + parser.add_argument('--type', default=DEFAULT_PROJECT, choices=('executable', 'library'), help=f"project type. default: {DEFAULT_PROJECT} based project") + parser.add_argument('--version', default=DEFAULT_VERSION, help=f"project version. default: {DEFAULT_VERSION}") + +def run(options: 'argparse.Namespace') -> int: + ''' + Here we generate the new Meson sample project. + ''' + if not Path(options.wd).exists(): + sys.exit('Project source root directory not found. Run this command in source directory root.') + os.chdir(options.wd) + + if not glob('*'): + autodetect_options(options, sample=True) + if not options.language: + print('Defaulting to generating a C language project.') + options.language = 'c' + create_sample(options) + else: + autodetect_options(options) + if Path('meson.build').is_file() and not options.force: + raise SystemExit('meson.build already exists. Use --force to overwrite.') + create_meson_build(options) + if options.build: + if Path(options.builddir).is_dir() and options.force: + print('Build directory already exists, deleting it.') + shutil.rmtree(options.builddir) + print('Building...') + cmd = mesonlib.get_meson_command() + ['setup', options.builddir] + ret = subprocess.run(cmd) + if ret.returncode: + raise SystemExit + + b = build.load(options.builddir) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(mesonlib.OptionKey('vsenv'))) + vsenv_active = mesonlib.setup_vsenv(need_vsenv) + if vsenv_active: + mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') + + cmd = detect_ninja() + ['-C', options.builddir] + ret = subprocess.run(cmd) + if ret.returncode: + raise SystemExit + return 0 diff --git a/devtools/meson/mesonbuild/minstall.py b/devtools/meson/mesonbuild/minstall.py new file mode 100644 index 0000000..4900691 --- /dev/null +++ b/devtools/meson/mesonbuild/minstall.py @@ -0,0 +1,864 @@ +# Copyright 2013-2014 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from glob import glob +import argparse +import errno +import os +import selectors +import shlex +import shutil +import subprocess +import sys +import typing as T +import re + +from . import build, coredata, environment +from .backend.backends import InstallData +from .mesonlib import (MesonException, Popen_safe, RealPathAction, is_windows, + is_aix, setup_vsenv, pickle_load, is_osx, OptionKey) +from .scripts import depfixer, destdir_join +from .scripts.meson_exe import run_exe +try: + from __main__ import __file__ as main_file +except ImportError: + # Happens when running as meson.exe which is native Windows. + # This is only used for pkexec which is not, so this is fine. + main_file = None + +if T.TYPE_CHECKING: + from .backend.backends import ( + ExecutableSerialisation, InstallDataBase, InstallEmptyDir, + InstallSymlinkData, TargetInstallData + ) + from .mesonlib import FileMode, EnvironOrDict + + try: + from typing import Protocol + except AttributeError: + from typing_extensions import Protocol # type: ignore + + class ArgumentType(Protocol): + """Typing information for the object returned by argparse.""" + no_rebuild: bool + only_changed: bool + profile: bool + quiet: bool + wd: str + destdir: str + dry_run: bool + skip_subprojects: str + tags: str + strip: bool + + +symlink_warning = '''Warning: trying to copy a symlink that points to a file. This will copy the file, +but this will be changed in a future version of Meson to copy the symlink as is. Please update your +build definitions so that it will not break when the change happens.''' + +selinux_updates: T.List[str] = [] + +def add_arguments(parser: argparse.ArgumentParser) -> None: + parser.add_argument('-C', dest='wd', action=RealPathAction, + help='directory to cd into before running') + parser.add_argument('--profile-self', action='store_true', dest='profile', + help=argparse.SUPPRESS) + parser.add_argument('--no-rebuild', default=False, action='store_true', + help='Do not rebuild before installing.') + parser.add_argument('--only-changed', default=False, action='store_true', + help='Only overwrite files that are older than the copied file.') + parser.add_argument('--quiet', default=False, action='store_true', + help='Do not print every file that was installed.') + parser.add_argument('--destdir', default=None, + help='Sets or overrides DESTDIR environment. (Since 0.57.0)') + parser.add_argument('--dry-run', '-n', action='store_true', + help='Doesn\'t actually install, but print logs. (Since 0.57.0)') + parser.add_argument('--skip-subprojects', nargs='?', const='*', default='', + help='Do not install files from given subprojects. (Since 0.58.0)') + parser.add_argument('--tags', default=None, + help='Install only targets having one of the given tags. (Since 0.60.0)') + parser.add_argument('--strip', action='store_true', + help='Strip targets even if strip option was not set during configure. (Since 0.62.0)') + +class DirMaker: + def __init__(self, lf: T.TextIO, makedirs: T.Callable[..., None]): + self.lf = lf + self.dirs: T.List[str] = [] + self.all_dirs: T.Set[str] = set() + self.makedirs_impl = makedirs + + def makedirs(self, path: str, exist_ok: bool = False) -> None: + dirname = os.path.normpath(path) + self.all_dirs.add(dirname) + dirs = [] + while dirname != os.path.dirname(dirname): + if dirname in self.dirs: + # In dry-run mode the directory does not exist but we would have + # created it with all its parents otherwise. + break + if not os.path.exists(dirname): + dirs.append(dirname) + dirname = os.path.dirname(dirname) + self.makedirs_impl(path, exist_ok=exist_ok) + + # store the directories in creation order, with the parent directory + # before the child directories. Future calls of makedir() will not + # create the parent directories, so the last element in the list is + # the last one to be created. That is the first one to be removed on + # __exit__ + dirs.reverse() + self.dirs += dirs + + def __enter__(self) -> 'DirMaker': + return self + + def __exit__(self, exception_type: T.Type[Exception], value: T.Any, traceback: T.Any) -> None: + self.dirs.reverse() + for d in self.dirs: + append_to_log(self.lf, d) + + +def load_install_data(fname: str) -> InstallData: + return pickle_load(fname, 'InstallData', InstallData) + +def is_executable(path: str, follow_symlinks: bool = False) -> bool: + '''Checks whether any of the "x" bits are set in the source file mode.''' + return bool(os.stat(path, follow_symlinks=follow_symlinks).st_mode & 0o111) + + +def append_to_log(lf: T.TextIO, line: str) -> None: + lf.write(line) + if not line.endswith('\n'): + lf.write('\n') + lf.flush() + + +def set_chown(path: str, user: T.Union[str, int, None] = None, + group: T.Union[str, int, None] = None, + dir_fd: T.Optional[int] = None, follow_symlinks: bool = True) -> None: + # shutil.chown will call os.chown without passing all the parameters + # and particularly follow_symlinks, thus we replace it temporary + # with a lambda with all the parameters so that follow_symlinks will + # be actually passed properly. + # Not nice, but better than actually rewriting shutil.chown until + # this python bug is fixed: https://bugs.python.org/issue18108 + real_os_chown = os.chown + + def chown(path: T.Union[int, str, 'os.PathLike[str]', bytes, 'os.PathLike[bytes]'], + uid: int, gid: int, *, dir_fd: T.Optional[int] = dir_fd, + follow_symlinks: bool = follow_symlinks) -> None: + """Override the default behavior of os.chown + + Use a real function rather than a lambda to help mypy out. Also real + functions are faster. + """ + real_os_chown(path, uid, gid, dir_fd=dir_fd, follow_symlinks=follow_symlinks) + + try: + os.chown = chown + shutil.chown(path, user, group) + finally: + os.chown = real_os_chown + + +def set_chmod(path: str, mode: int, dir_fd: T.Optional[int] = None, + follow_symlinks: bool = True) -> None: + try: + os.chmod(path, mode, dir_fd=dir_fd, follow_symlinks=follow_symlinks) + except (NotImplementedError, OSError, SystemError): + if not os.path.islink(path): + os.chmod(path, mode, dir_fd=dir_fd) + + +def sanitize_permissions(path: str, umask: T.Union[str, int]) -> None: + # TODO: with python 3.8 or typing_extensions we could replace this with + # `umask: T.Union[T.Literal['preserve'], int]`, which would be more correct + if umask == 'preserve': + return + assert isinstance(umask, int), 'umask should only be "preserver" or an integer' + new_perms = 0o777 if is_executable(path, follow_symlinks=False) else 0o666 + new_perms &= ~umask + try: + set_chmod(path, new_perms, follow_symlinks=False) + except PermissionError as e: + print(f'{path!r}: Unable to set permissions {new_perms!r}: {e.strerror}, ignoring...') + + +def set_mode(path: str, mode: T.Optional['FileMode'], default_umask: T.Union[str, int]) -> None: + if mode is None or all(m is None for m in [mode.perms_s, mode.owner, mode.group]): + # Just sanitize permissions with the default umask + sanitize_permissions(path, default_umask) + return + # No chown() on Windows, and must set one of owner/group + if not is_windows() and (mode.owner is not None or mode.group is not None): + try: + set_chown(path, mode.owner, mode.group, follow_symlinks=False) + except PermissionError as e: + print(f'{path!r}: Unable to set owner {mode.owner!r} and group {mode.group!r}: {e.strerror}, ignoring...') + except LookupError: + print(f'{path!r}: Nonexistent owner {mode.owner!r} or group {mode.group!r}: ignoring...') + except OSError as e: + if e.errno == errno.EINVAL: + print(f'{path!r}: Nonexistent numeric owner {mode.owner!r} or group {mode.group!r}: ignoring...') + else: + raise + # Must set permissions *after* setting owner/group otherwise the + # setuid/setgid bits will get wiped by chmod + # NOTE: On Windows you can set read/write perms; the rest are ignored + if mode.perms_s is not None: + try: + set_chmod(path, mode.perms, follow_symlinks=False) + except PermissionError as e: + print(f'{path!r}: Unable to set permissions {mode.perms_s!r}: {e.strerror}, ignoring...') + else: + sanitize_permissions(path, default_umask) + + +def restore_selinux_contexts() -> None: + ''' + Restores the SELinux context for files in @selinux_updates + + If $DESTDIR is set, do not warn if the call fails. + ''' + try: + subprocess.check_call(['selinuxenabled']) + except (FileNotFoundError, NotADirectoryError, OSError, PermissionError, subprocess.CalledProcessError): + # If we don't have selinux or selinuxenabled returned 1, failure + # is ignored quietly. + return + + if not shutil.which('restorecon'): + # If we don't have restorecon, failure is ignored quietly. + return + + if not selinux_updates: + # If the list of files is empty, do not try to call restorecon. + return + + proc, out, err = Popen_safe(['restorecon', '-F', '-f-', '-0'], ('\0'.join(f for f in selinux_updates) + '\0')) + if proc.returncode != 0: + print('Failed to restore SELinux context of installed files...', + 'Standard output:', out, + 'Standard error:', err, sep='\n') + +def get_destdir_path(destdir: str, fullprefix: str, path: str) -> str: + if os.path.isabs(path): + output = destdir_join(destdir, path) + else: + output = os.path.join(fullprefix, path) + return output + + +def check_for_stampfile(fname: str) -> str: + '''Some languages e.g. Rust have output files + whose names are not known at configure time. + Check if this is the case and return the real + file instead.''' + if fname.endswith('.so') or fname.endswith('.dll'): + if os.stat(fname).st_size == 0: + (base, suffix) = os.path.splitext(fname) + files = glob(base + '-*' + suffix) + if len(files) > 1: + print("Stale dynamic library files in build dir. Can't install.") + sys.exit(1) + if len(files) == 1: + return files[0] + elif fname.endswith('.a') or fname.endswith('.lib'): + if os.stat(fname).st_size == 0: + (base, suffix) = os.path.splitext(fname) + files = glob(base + '-*' + '.rlib') + if len(files) > 1: + print("Stale static library files in build dir. Can't install.") + sys.exit(1) + if len(files) == 1: + return files[0] + return fname + + +class Installer: + + def __init__(self, options: 'ArgumentType', lf: T.TextIO): + self.did_install_something = False + self.printed_symlink_error = False + self.options = options + self.lf = lf + self.preserved_file_count = 0 + self.dry_run = options.dry_run + # [''] means skip none, + # ['*'] means skip all, + # ['sub1', ...] means skip only those. + self.skip_subprojects = [i.strip() for i in options.skip_subprojects.split(',')] + self.tags = [i.strip() for i in options.tags.split(',')] if options.tags else None + + def remove(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + os.remove(*args, **kwargs) + + def symlink(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + os.symlink(*args, **kwargs) + + def makedirs(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + os.makedirs(*args, **kwargs) + + def copy(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + shutil.copy(*args, **kwargs) + + def copy2(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + shutil.copy2(*args, **kwargs) + + def copyfile(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + shutil.copyfile(*args, **kwargs) + + def copystat(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + shutil.copystat(*args, **kwargs) + + def fix_rpath(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + depfixer.fix_rpath(*args, **kwargs) + + def set_chown(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + set_chown(*args, **kwargs) + + def set_chmod(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + set_chmod(*args, **kwargs) + + def sanitize_permissions(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + sanitize_permissions(*args, **kwargs) + + def set_mode(self, *args: T.Any, **kwargs: T.Any) -> None: + if not self.dry_run: + set_mode(*args, **kwargs) + + def restore_selinux_contexts(self, destdir: str) -> None: + if not self.dry_run and not destdir: + restore_selinux_contexts() + + def Popen_safe(self, *args: T.Any, **kwargs: T.Any) -> T.Tuple[int, str, str]: + if not self.dry_run: + p, o, e = Popen_safe(*args, **kwargs) + return p.returncode, o, e + return 0, '', '' + + def run_exe(self, exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str]] = None) -> int: + if (not self.dry_run) or exe.dry_run: + return run_exe(exe, extra_env) + return 0 + + def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir, + InstallDataBase, InstallSymlinkData, + ExecutableSerialisation]) -> bool: + if d.subproject and (d.subproject in self.skip_subprojects or '*' in self.skip_subprojects): + return False + if self.tags and d.tag not in self.tags: + return False + return True + + def log(self, msg: str) -> None: + if not self.options.quiet: + print(msg) + + def should_preserve_existing_file(self, from_file: str, to_file: str) -> bool: + if not self.options.only_changed: + return False + # Always replace danging symlinks + if os.path.islink(from_file) and not os.path.isfile(from_file): + return False + from_time = os.stat(from_file).st_mtime + to_time = os.stat(to_file).st_mtime + return from_time <= to_time + + def do_copyfile(self, from_file: str, to_file: str, + makedirs: T.Optional[T.Tuple[T.Any, str]] = None) -> bool: + outdir = os.path.split(to_file)[0] + if not os.path.isfile(from_file) and not os.path.islink(from_file): + raise MesonException(f'Tried to install something that isn\'t a file: {from_file!r}') + # copyfile fails if the target file already exists, so remove it to + # allow overwriting a previous install. If the target is not a file, we + # want to give a readable error. + if os.path.exists(to_file): + if not os.path.isfile(to_file): + raise MesonException(f'Destination {to_file!r} already exists and is not a file') + if self.should_preserve_existing_file(from_file, to_file): + append_to_log(self.lf, f'# Preserving old file {to_file}\n') + self.preserved_file_count += 1 + return False + self.remove(to_file) + elif makedirs: + # Unpack tuple + dirmaker, outdir = makedirs + # Create dirs if needed + dirmaker.makedirs(outdir, exist_ok=True) + self.log(f'Installing {from_file} to {outdir}') + if os.path.islink(from_file): + if not os.path.exists(from_file): + # Dangling symlink. Replicate as is. + self.copy(from_file, outdir, follow_symlinks=False) + else: + # Remove this entire branch when changing the behaviour to duplicate + # symlinks rather than copying what they point to. + print(symlink_warning) + self.copy2(from_file, to_file) + else: + self.copy2(from_file, to_file) + selinux_updates.append(to_file) + append_to_log(self.lf, to_file) + return True + + def do_symlink(self, target: str, link: str, destdir: str, full_dst_dir: str, allow_missing: bool) -> bool: + abs_target = target + if not os.path.isabs(target): + abs_target = os.path.join(full_dst_dir, target) + elif not os.path.exists(abs_target) and not allow_missing: + abs_target = destdir_join(destdir, abs_target) + if not os.path.exists(abs_target) and not allow_missing: + raise MesonException(f'Tried to install symlink to missing file {abs_target}') + if os.path.exists(link): + if not os.path.islink(link): + raise MesonException(f'Destination {link!r} already exists and is not a symlink') + self.remove(link) + if not self.printed_symlink_error: + self.log(f'Installing symlink pointing to {target} to {link}') + try: + self.symlink(target, link, target_is_directory=os.path.isdir(abs_target)) + except (NotImplementedError, OSError): + if not self.printed_symlink_error: + print("Symlink creation does not work on this platform. " + "Skipping all symlinking.") + self.printed_symlink_error = True + return False + append_to_log(self.lf, link) + return True + + def do_copydir(self, data: InstallData, src_dir: str, dst_dir: str, + exclude: T.Optional[T.Tuple[T.Set[str], T.Set[str]]], + install_mode: 'FileMode', dm: DirMaker) -> None: + ''' + Copies the contents of directory @src_dir into @dst_dir. + + For directory + /foo/ + bar/ + excluded + foobar + file + do_copydir(..., '/foo', '/dst/dir', {'bar/excluded'}) creates + /dst/ + dir/ + bar/ + foobar + file + + Args: + src_dir: str, absolute path to the source directory + dst_dir: str, absolute path to the destination directory + exclude: (set(str), set(str)), tuple of (exclude_files, exclude_dirs), + each element of the set is a path relative to src_dir. + ''' + if not os.path.isabs(src_dir): + raise ValueError(f'src_dir must be absolute, got {src_dir}') + if not os.path.isabs(dst_dir): + raise ValueError(f'dst_dir must be absolute, got {dst_dir}') + if exclude is not None: + exclude_files, exclude_dirs = exclude + exclude_files = {os.path.normpath(x) for x in exclude_files} + exclude_dirs = {os.path.normpath(x) for x in exclude_dirs} + else: + exclude_files = exclude_dirs = set() + for root, dirs, files in os.walk(src_dir): + assert os.path.isabs(root) + for d in dirs[:]: + abs_src = os.path.join(root, d) + filepart = os.path.relpath(abs_src, start=src_dir) + abs_dst = os.path.join(dst_dir, filepart) + # Remove these so they aren't visited by os.walk at all. + if filepart in exclude_dirs: + dirs.remove(d) + continue + if os.path.isdir(abs_dst): + continue + if os.path.exists(abs_dst): + print(f'Tried to copy directory {abs_dst} but a file of that name already exists.') + sys.exit(1) + dm.makedirs(abs_dst) + self.copystat(abs_src, abs_dst) + self.sanitize_permissions(abs_dst, data.install_umask) + for f in files: + abs_src = os.path.join(root, f) + filepart = os.path.relpath(abs_src, start=src_dir) + if filepart in exclude_files: + continue + abs_dst = os.path.join(dst_dir, filepart) + if os.path.isdir(abs_dst): + print(f'Tried to copy file {abs_dst} but a directory of that name already exists.') + sys.exit(1) + parent_dir = os.path.dirname(abs_dst) + if not os.path.isdir(parent_dir): + dm.makedirs(parent_dir) + self.copystat(os.path.dirname(abs_src), parent_dir) + # FIXME: what about symlinks? + self.do_copyfile(abs_src, abs_dst) + self.set_mode(abs_dst, install_mode, data.install_umask) + + def do_install(self, datafilename: str) -> None: + d = load_install_data(datafilename) + + destdir = self.options.destdir + if destdir is None: + destdir = os.environ.get('DESTDIR') + if destdir and not os.path.isabs(destdir): + destdir = os.path.join(d.build_dir, destdir) + # Override in the env because some scripts could use it and require an + # absolute path. + if destdir is not None: + os.environ['DESTDIR'] = destdir + destdir = destdir or '' + fullprefix = destdir_join(destdir, d.prefix) + + if d.install_umask != 'preserve': + assert isinstance(d.install_umask, int) + os.umask(d.install_umask) + + self.did_install_something = False + try: + with DirMaker(self.lf, self.makedirs) as dm: + self.install_subdirs(d, dm, destdir, fullprefix) # Must be first, because it needs to delete the old subtree. + self.install_targets(d, dm, destdir, fullprefix) + self.install_headers(d, dm, destdir, fullprefix) + self.install_man(d, dm, destdir, fullprefix) + self.install_emptydir(d, dm, destdir, fullprefix) + self.install_data(d, dm, destdir, fullprefix) + self.install_symlinks(d, dm, destdir, fullprefix) + self.restore_selinux_contexts(destdir) + self.run_install_script(d, destdir, fullprefix) + if not self.did_install_something: + self.log('Nothing to install.') + if not self.options.quiet and self.preserved_file_count > 0: + self.log('Preserved {} unchanged files, see {} for the full list' + .format(self.preserved_file_count, os.path.normpath(self.lf.name))) + except PermissionError: + if is_windows() or destdir != '' or not os.isatty(sys.stdout.fileno()) or not os.isatty(sys.stderr.fileno()): + # can't elevate to root except in an interactive unix environment *and* when not doing a destdir install + raise + rootcmd = os.environ.get('MESON_ROOT_CMD') or shutil.which('sudo') or shutil.which('doas') + pkexec = shutil.which('pkexec') + if rootcmd is None and pkexec is not None and 'PKEXEC_UID' not in os.environ: + rootcmd = pkexec + + if rootcmd is not None: + print('Installation failed due to insufficient permissions.') + s = selectors.DefaultSelector() + s.register(sys.stdin, selectors.EVENT_READ) + ans = None + for attempt in range(5): + print(f'Attempt to use {rootcmd} to gain elevated privileges? [y/n] ', end='', flush=True) + if s.select(30): + # we waited on sys.stdin *only* + ans = sys.stdin.readline().rstrip('\n') + else: + print() + break + if ans in {'y', 'n'}: + break + else: + if ans is not None: + raise MesonException('Answer not one of [y/n]') + if ans == 'y': + os.execlp(rootcmd, rootcmd, sys.executable, main_file, *sys.argv[1:], + '-C', os.getcwd(), '--no-rebuild') + raise + + def do_strip(self, strip_bin: T.List[str], fname: str, outname: str) -> None: + self.log(f'Stripping target {fname!r}.') + if is_osx(): + # macOS expects dynamic objects to be stripped with -x maximum. + # To also strip the debug info, -S must be added. + # See: https://www.unix.com/man-page/osx/1/strip/ + returncode, stdo, stde = self.Popen_safe(strip_bin + ['-S', '-x', outname]) + else: + returncode, stdo, stde = self.Popen_safe(strip_bin + [outname]) + if returncode != 0: + print('Could not strip file.\n') + print(f'Stdout:\n{stdo}\n') + print(f'Stderr:\n{stde}\n') + sys.exit(1) + + def install_subdirs(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for i in d.install_subdirs: + if not self.should_install(i): + continue + self.did_install_something = True + full_dst_dir = get_destdir_path(destdir, fullprefix, i.install_path) + self.log(f'Installing subdir {i.path} to {full_dst_dir}') + dm.makedirs(full_dst_dir, exist_ok=True) + self.do_copydir(d, i.path, full_dst_dir, i.exclude, i.install_mode, dm) + + def install_data(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for i in d.data: + if not self.should_install(i): + continue + fullfilename = i.path + outfilename = get_destdir_path(destdir, fullprefix, i.install_path) + outdir = os.path.dirname(outfilename) + if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir)): + self.did_install_something = True + self.set_mode(outfilename, i.install_mode, d.install_umask) + + def install_symlinks(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for s in d.symlinks: + if not self.should_install(s): + continue + full_dst_dir = get_destdir_path(destdir, fullprefix, s.install_path) + full_link_name = get_destdir_path(destdir, fullprefix, s.name) + dm.makedirs(full_dst_dir, exist_ok=True) + if self.do_symlink(s.target, full_link_name, destdir, full_dst_dir, s.allow_missing): + self.did_install_something = True + + def install_man(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for m in d.man: + if not self.should_install(m): + continue + full_source_filename = m.path + outfilename = get_destdir_path(destdir, fullprefix, m.install_path) + outdir = os.path.dirname(outfilename) + if self.do_copyfile(full_source_filename, outfilename, makedirs=(dm, outdir)): + self.did_install_something = True + self.set_mode(outfilename, m.install_mode, d.install_umask) + + def install_emptydir(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for e in d.emptydir: + if not self.should_install(e): + continue + self.did_install_something = True + full_dst_dir = get_destdir_path(destdir, fullprefix, e.path) + self.log(f'Installing new directory {full_dst_dir}') + if os.path.isfile(full_dst_dir): + print(f'Tried to create directory {full_dst_dir} but a file of that name already exists.') + sys.exit(1) + dm.makedirs(full_dst_dir, exist_ok=True) + self.set_mode(full_dst_dir, e.install_mode, d.install_umask) + + def install_headers(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for t in d.headers: + if not self.should_install(t): + continue + fullfilename = t.path + fname = os.path.basename(fullfilename) + outdir = get_destdir_path(destdir, fullprefix, t.install_path) + outfilename = os.path.join(outdir, fname) + if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir)): + self.did_install_something = True + self.set_mode(outfilename, t.install_mode, d.install_umask) + + def run_install_script(self, d: InstallData, destdir: str, fullprefix: str) -> None: + env = {'MESON_SOURCE_ROOT': d.source_dir, + 'MESON_BUILD_ROOT': d.build_dir, + 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in d.mesonintrospect]), + } + if self.options.quiet: + env['MESON_INSTALL_QUIET'] = '1' + if self.dry_run: + env['MESON_INSTALL_DRY_RUN'] = '1' + + for i in d.install_scripts: + if not self.should_install(i): + continue + + if i.installdir_map is not None: + mapp = i.installdir_map + else: + mapp = {'prefix': d.prefix} + localenv = env.copy() + localenv.update({'MESON_INSTALL_'+k.upper(): os.path.join(d.prefix, v) for k, v in mapp.items()}) + localenv.update({'MESON_INSTALL_DESTDIR_'+k.upper(): get_destdir_path(destdir, fullprefix, v) for k, v in mapp.items()}) + + name = ' '.join(i.cmd_args) + if i.skip_if_destdir and destdir: + self.log(f'Skipping custom install script because DESTDIR is set {name!r}') + continue + self.did_install_something = True # Custom script must report itself if it does nothing. + self.log(f'Running custom install script {name!r}') + try: + rc = self.run_exe(i, localenv) + except OSError: + print(f'FAILED: install script \'{name}\' could not be run, stopped') + # POSIX shells return 127 when a command could not be found + sys.exit(127) + if rc != 0: + print(f'FAILED: install script \'{name}\' exit code {rc}, stopped') + sys.exit(rc) + + def install_targets(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for t in d.targets: + # In AIX, we archive our shared libraries. When we install any package in AIX we need to + # install the archive in which the shared library exists. The below code does the same. + # We change the .so files having lt_version or so_version to archive file install. + if is_aix(): + if '.so' in t.fname: + t.fname = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', t.fname.replace('.so', '.a')) + if not self.should_install(t): + continue + if not os.path.exists(t.fname): + # For example, import libraries of shared modules are optional + if t.optional: + self.log(f'File {t.fname!r} not found, skipping') + continue + else: + raise MesonException(f'File {t.fname!r} could not be found') + file_copied = False # not set when a directory is copied + fname = check_for_stampfile(t.fname) + outdir = get_destdir_path(destdir, fullprefix, t.outdir) + outname = os.path.join(outdir, os.path.basename(fname)) + final_path = os.path.join(d.prefix, t.outdir, os.path.basename(fname)) + should_strip = t.strip or (t.can_strip and self.options.strip) + install_rpath = t.install_rpath + install_name_mappings = t.install_name_mappings + install_mode = t.install_mode + if not os.path.exists(fname): + raise MesonException(f'File {fname!r} could not be found') + elif os.path.isfile(fname): + file_copied = self.do_copyfile(fname, outname, makedirs=(dm, outdir)) + if should_strip and d.strip_bin is not None: + if fname.endswith('.jar'): + self.log('Not stripping jar target: {}'.format(os.path.basename(fname))) + continue + self.do_strip(d.strip_bin, fname, outname) + if fname.endswith('.js'): + # Emscripten outputs js files and optionally a wasm file. + # If one was generated, install it as well. + wasm_source = os.path.splitext(fname)[0] + '.wasm' + if os.path.exists(wasm_source): + wasm_output = os.path.splitext(outname)[0] + '.wasm' + file_copied = self.do_copyfile(wasm_source, wasm_output) + elif os.path.isdir(fname): + fname = os.path.join(d.build_dir, fname.rstrip('/')) + outname = os.path.join(outdir, os.path.basename(fname)) + dm.makedirs(outdir, exist_ok=True) + self.do_copydir(d, fname, outname, None, install_mode, dm) + else: + raise RuntimeError(f'Unknown file type for {fname!r}') + if file_copied: + self.did_install_something = True + try: + self.fix_rpath(outname, t.rpath_dirs_to_remove, install_rpath, final_path, + install_name_mappings, verbose=False) + except SystemExit as e: + if isinstance(e.code, int) and e.code == 0: + pass + else: + raise + # file mode needs to be set last, after strip/depfixer editing + self.set_mode(outname, install_mode, d.install_umask) + +def rebuild_all(wd: str, backend: str) -> bool: + if backend == 'none': + # nothing to build... + return True + if backend != 'ninja': + print('Only ninja backend is supported to rebuild the project before installation.') + return True + + ninja = environment.detect_ninja() + if not ninja: + print("Can't find ninja, can't rebuild test.") + return False + + def drop_privileges() -> T.Tuple[T.Optional[EnvironOrDict], T.Optional[T.Callable[[], None]]]: + if not is_windows() and os.geteuid() == 0: + import pwd + env = os.environ.copy() + + if os.environ.get('SUDO_USER') is not None: + orig_user = env.pop('SUDO_USER') + orig_uid = env.pop('SUDO_UID', 0) + orig_gid = env.pop('SUDO_GID', 0) + try: + homedir = pwd.getpwuid(int(orig_uid)).pw_dir + except KeyError: + # `sudo chroot` leaves behind stale variable and builds as root without a user + return None, None + elif os.environ.get('DOAS_USER') is not None: + orig_user = env.pop('DOAS_USER') + try: + pwdata = pwd.getpwnam(orig_user) + except KeyError: + # `doas chroot` leaves behind stale variable and builds as root without a user + return None, None + orig_uid = pwdata.pw_uid + orig_gid = pwdata.pw_gid + homedir = pwdata.pw_dir + else: + return None, None + + if os.stat(os.path.join(wd, 'build.ninja')).st_uid != int(orig_uid): + # the entire build process is running with sudo, we can't drop privileges + return None, None + + env['USER'] = orig_user + env['HOME'] = homedir + + def wrapped() -> None: + print(f'Dropping privileges to {orig_user!r} before running ninja...') + if orig_gid is not None: + os.setgid(int(orig_gid)) + if orig_uid is not None: + os.setuid(int(orig_uid)) + + return env, wrapped + else: + return None, None + + env, preexec_fn = drop_privileges() + ret = subprocess.run(ninja + ['-C', wd], env=env, preexec_fn=preexec_fn).returncode + if ret != 0: + print(f'Could not rebuild {wd}') + return False + + return True + + +def run(opts: 'ArgumentType') -> int: + datafilename = 'meson-private/install.dat' + private_dir = os.path.dirname(datafilename) + log_dir = os.path.join(private_dir, '../meson-logs') + if not os.path.exists(os.path.join(opts.wd, datafilename)): + sys.exit('Install data not found. Run this command in build directory root.') + if not opts.no_rebuild: + b = build.load(opts.wd) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) + backend = T.cast('str', b.environment.coredata.get_option(coredata.OptionKey('backend'))) + if not rebuild_all(opts.wd, backend): + sys.exit(-1) + os.chdir(opts.wd) + with open(os.path.join(log_dir, 'install-log.txt'), 'w', encoding='utf-8') as lf: + installer = Installer(opts, lf) + append_to_log(lf, '# List of files installed by Meson') + append_to_log(lf, '# Does not contain files installed by custom scripts.') + if opts.profile: + import cProfile as profile + fname = os.path.join(private_dir, 'profile-installer.log') + profile.runctx('installer.do_install(datafilename)', globals(), locals(), filename=fname) + else: + installer.do_install(datafilename) + return 0 diff --git a/devtools/meson/mesonbuild/mintro.py b/devtools/meson/mesonbuild/mintro.py new file mode 100644 index 0000000..ab303b3 --- /dev/null +++ b/devtools/meson/mesonbuild/mintro.py @@ -0,0 +1,672 @@ +# Copyright 2014-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""This is a helper script for IDE developers. It allows you to +extract information such as list of targets, files, compiler flags, +tests and so on. All output is in JSON for simple parsing. + +Currently only works for the Ninja backend. Others use generated +project files and don't need this info.""" + +from contextlib import redirect_stdout +import collections +import dataclasses +import json +import os +from pathlib import Path, PurePath +import sys +import typing as T + +from . import build, mesonlib, coredata as cdata +from .ast import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstJSONPrinter +from .backend import backends +from .dependencies import Dependency +from . import environment +from .interpreterbase import ObjectHolder +from .mesonlib import OptionKey +from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode + +if T.TYPE_CHECKING: + import argparse + + from .interpreter import Interpreter + from .mparser import BaseNode + +def get_meson_info_file(info_dir: str) -> str: + return os.path.join(info_dir, 'meson-info.json') + +def get_meson_introspection_version() -> str: + return '1.0.0' + +def get_meson_introspection_required_version() -> T.List[str]: + return ['>=1.0', '<2.0'] + +class IntroCommand: + def __init__(self, + desc: str, + func: T.Optional[T.Callable[[], T.Union[dict, list]]] = None, + no_bd: T.Optional[T.Callable[[IntrospectionInterpreter], T.Union[dict, list]]] = None) -> None: + self.desc = desc + '.' + self.func = func + self.no_bd = no_bd + +def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None, + builddata: T.Optional[build.Build] = None, + backend: T.Optional[backends.Backend] = None, + sourcedir: T.Optional[str] = None) -> 'T.Mapping[str, IntroCommand]': + if backend and builddata: + benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks()) + testdata = backend.create_test_serialisation(builddata.get_tests()) + installdata = backend.create_install_data() + interpreter = backend.interpreter + else: + benchmarkdata = testdata = installdata = None + + # Enforce key order for argparse + return collections.OrderedDict([ + ('ast', IntroCommand('Dump the AST of the meson file', no_bd=dump_ast)), + ('benchmarks', IntroCommand('List all benchmarks', func=lambda: list_benchmarks(benchmarkdata))), + ('buildoptions', IntroCommand('List all build options', func=lambda: list_buildoptions(coredata), no_bd=list_buildoptions_from_source)), + ('buildsystem_files', IntroCommand('List files that make up the build system', func=lambda: list_buildsystem_files(builddata, interpreter))), + ('compilers', IntroCommand('List used compilers', func=lambda: list_compilers(coredata))), + ('dependencies', IntroCommand('List external dependencies', func=lambda: list_deps(coredata, backend), no_bd=list_deps_from_source)), + ('scan_dependencies', IntroCommand('Scan for dependencies used in the meson.build file', no_bd=list_deps_from_source)), + ('installed', IntroCommand('List all installed files and directories', func=lambda: list_installed(installdata))), + ('install_plan', IntroCommand('List all installed files and directories with their details', func=lambda: list_install_plan(installdata))), + ('machines', IntroCommand('Information about host, build, and target machines', func=lambda: list_machines(builddata))), + ('projectinfo', IntroCommand('Information about projects', func=lambda: list_projinfo(builddata), no_bd=list_projinfo_from_source)), + ('targets', IntroCommand('List top level targets', func=lambda: list_targets(builddata, installdata, backend), no_bd=list_targets_from_source)), + ('tests', IntroCommand('List all unit tests', func=lambda: list_tests(testdata))), + ]) + +def add_arguments(parser: argparse.ArgumentParser) -> None: + intro_types = get_meson_introspection_types() + for key, val in intro_types.items(): + flag = '--' + key.replace('_', '-') + parser.add_argument(flag, action='store_true', dest=key, default=False, help=val.desc) + + parser.add_argument('--backend', choices=sorted(cdata.backendlist), dest='backend', default='ninja', + help='The backend to use for the --buildoptions introspection.') + parser.add_argument('-a', '--all', action='store_true', dest='all', default=False, + help='Print all available information.') + parser.add_argument('-i', '--indent', action='store_true', dest='indent', default=False, + help='Enable pretty printed JSON.') + parser.add_argument('-f', '--force-object-output', action='store_true', dest='force_dict', default=False, + help='Always use the new JSON format for multiple entries (even for 0 and 1 introspection commands)') + parser.add_argument('builddir', nargs='?', default='.', help='The build directory') + +def dump_ast(intr: IntrospectionInterpreter) -> T.Dict[str, T.Any]: + printer = AstJSONPrinter() + intr.ast.accept(printer) + return printer.result + +def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]: + res = {} + if installdata is not None: + for t in installdata.targets: + res[os.path.join(installdata.build_dir, t.fname)] = \ + os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname)) + for i in installdata.data: + res[i.path] = os.path.join(installdata.prefix, i.install_path) + for i in installdata.headers: + res[i.path] = os.path.join(installdata.prefix, i.install_path, os.path.basename(i.path)) + for i in installdata.man: + res[i.path] = os.path.join(installdata.prefix, i.install_path) + for i in installdata.install_subdirs: + res[i.path] = os.path.join(installdata.prefix, i.install_path) + for s in installdata.symlinks: + basename = os.path.basename(s.name) + res[basename] = os.path.join(installdata.prefix, s.install_path, basename) + return res + +def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]: + plan = { + 'targets': { + os.path.join(installdata.build_dir, target.fname): { + 'destination': target.out_name, + 'tag': target.tag or None, + 'subproject': target.subproject or None, + } + for target in installdata.targets + }, + } # type: T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]] + for key, data_list in { + 'data': installdata.data, + 'man': installdata.man, + 'headers': installdata.headers, + 'install_subdirs': installdata.install_subdirs + }.items(): + # Mypy doesn't recognize SubdirInstallData as a subclass of InstallDataBase + for data in data_list: # type: ignore[attr-defined] + data_type = data.data_type or key + install_path_name = data.install_path_name + if key == 'headers': # in the headers, install_path_name is the directory + install_path_name = os.path.join(install_path_name, os.path.basename(data.path)) + + entry = { + 'destination': install_path_name, + 'tag': data.tag or None, + 'subproject': data.subproject or None, + } + + if key == 'install_subdirs': + exclude_files, exclude_dirs = data.exclude or ([], []) + entry['exclude_dirs'] = list(exclude_dirs) + entry['exclude_files'] = list(exclude_files) + + plan[data_type] = plan.get(data_type, {}) + plan[data_type][data.path] = entry + + return plan + +def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str: + if coredata.get_option(OptionKey('layout')) == 'flat': + return 'meson-out' + else: + return subdir + +def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]: + tlist = [] # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]] + root_dir = Path(intr.source_root) + + def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]: + res = [] # type: T.List[Path] + for n in node_list: + args = [] # type: T.List[BaseNode] + if isinstance(n, FunctionNode): + args = list(n.args.arguments) + if n.func_name in BUILD_TARGET_FUNCTIONS: + args.pop(0) + elif isinstance(n, ArrayNode): + args = n.args.arguments + elif isinstance(n, ArgumentNode): + args = n.arguments + for j in args: + if isinstance(j, StringNode): + assert isinstance(j.value, str) + res += [Path(j.value)] + elif isinstance(j, str): + res += [Path(j)] + res = [root_dir / i['subdir'] / x for x in res] + res = [x.resolve() for x in res] + return res + + for i in intr.targets: + sources = nodes_to_paths(i['sources']) + extra_f = nodes_to_paths(i['extra_files']) + outdir = get_target_dir(intr.coredata, i['subdir']) + + tlist += [{ + 'name': i['name'], + 'id': i['id'], + 'type': i['type'], + 'defined_in': i['defined_in'], + 'filename': [os.path.join(outdir, x) for x in i['outputs']], + 'build_by_default': i['build_by_default'], + 'target_sources': [{ + 'language': 'unknown', + 'compiler': [], + 'parameters': [], + 'sources': [str(x) for x in sources], + 'generated_sources': [] + }], + 'depends': [], + 'extra_files': [str(x) for x in extra_f], + 'subproject': None, # Subprojects are not supported + 'installed': i['installed'] + }] + + return tlist + +def list_targets(builddata: build.Build, installdata: backends.InstallData, backend: backends.Backend) -> T.List[T.Any]: + tlist = [] # type: T.List[T.Any] + build_dir = builddata.environment.get_build_dir() + src_dir = builddata.environment.get_source_dir() + + # Fast lookup table for installation files + install_lookuptable = {} + for i in installdata.targets: + basename = os.path.basename(i.fname) + install_lookuptable[basename] = [str(PurePath(installdata.prefix, i.outdir, basename))] + for s in installdata.symlinks: + # Symlink's target must already be in the table. They share the same list + # to support symlinks to symlinks recursively, such as .so -> .so.0 -> .so.1.2.3 + basename = os.path.basename(s.name) + try: + install_lookuptable[basename] = install_lookuptable[os.path.basename(s.target)] + install_lookuptable[basename].append(str(PurePath(installdata.prefix, s.install_path, basename))) + except KeyError: + pass + + for (idname, target) in builddata.get_targets().items(): + if not isinstance(target, build.Target): + raise RuntimeError('The target object in `builddata.get_targets()` is not of type `build.Target`. Please file a bug with this error message.') + + outdir = get_target_dir(builddata.environment.coredata, target.subdir) + t = { + 'name': target.get_basename(), + 'id': idname, + 'type': target.get_typename(), + 'defined_in': os.path.normpath(os.path.join(src_dir, target.subdir, environment.build_filename)), + 'filename': [os.path.join(build_dir, outdir, x) for x in target.get_outputs()], + 'build_by_default': target.build_by_default, + 'target_sources': backend.get_introspection_data(idname, target), + 'extra_files': [os.path.normpath(os.path.join(src_dir, x.subdir, x.fname)) for x in target.extra_files], + 'subproject': target.subproject or None, + 'dependencies': [d.name for d in getattr(target, 'external_deps', [])], + 'depends': [lib.get_id() for lib in getattr(target, 'dependencies', [])] + } + + vs_module_defs = getattr(target, 'vs_module_defs', None) + if vs_module_defs is not None: + t['vs_module_defs'] = vs_module_defs.relative_name() + win_subsystem = getattr(target, 'win_subsystem', None) + if win_subsystem is not None: + t['win_subsystem'] = win_subsystem + + if installdata and target.should_install(): + t['installed'] = True + ifn = [install_lookuptable.get(x, [None]) for x in target.get_outputs()] + t['install_filename'] = [x for sublist in ifn for x in sublist] # flatten the list + else: + t['installed'] = False + tlist.append(t) + return tlist + +def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]: + subprojects = [i['name'] for i in intr.project_data['subprojects']] + return list_buildoptions(intr.coredata, subprojects) + +def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]: + optlist = [] # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]] + subprojects = subprojects or [] + + dir_option_names = set(cdata.BUILTIN_DIR_OPTIONS) + test_option_names = {OptionKey('errorlogs'), + OptionKey('stdsplit')} + + dir_options: 'cdata.MutableKeyedOptionDictType' = {} + test_options: 'cdata.MutableKeyedOptionDictType' = {} + core_options: 'cdata.MutableKeyedOptionDictType' = {} + for k, v in coredata.options.items(): + if k in dir_option_names: + dir_options[k] = v + elif k in test_option_names: + test_options[k] = v + elif k.is_builtin(): + core_options[k] = v + if not v.yielding: + for s in subprojects: + core_options[k.evolve(subproject=s)] = v + + def add_keys(options: 'cdata.KeyedOptionDictType', section: str) -> None: + for key, opt in sorted(options.items()): + optdict = {'name': str(key), 'value': opt.value, 'section': section, + 'machine': key.machine.get_lower_case_name() if coredata.is_per_machine_option(key) else 'any'} + if isinstance(opt, cdata.UserStringOption): + typestr = 'string' + elif isinstance(opt, cdata.UserBooleanOption): + typestr = 'boolean' + elif isinstance(opt, cdata.UserComboOption): + optdict['choices'] = opt.choices + typestr = 'combo' + elif isinstance(opt, cdata.UserIntegerOption): + typestr = 'integer' + elif isinstance(opt, cdata.UserArrayOption): + typestr = 'array' + if opt.choices: + optdict['choices'] = opt.choices + else: + raise RuntimeError("Unknown option type") + optdict['type'] = typestr + optdict['description'] = opt.description + optlist.append(optdict) + + add_keys(core_options, 'core') + add_keys({k: v for k, v in coredata.options.items() if k.is_backend()}, 'backend') + add_keys({k: v for k, v in coredata.options.items() if k.is_base()}, 'base') + add_keys( + {k: v for k, v in sorted(coredata.options.items(), key=lambda i: i[0].machine) if k.is_compiler()}, + 'compiler', + ) + add_keys(dir_options, 'directory') + add_keys({k: v for k, v in coredata.options.items() if k.is_project()}, 'user') + add_keys(test_options, 'test') + return optlist + +def find_buildsystem_files_list(src_dir: str) -> T.List[str]: + build_files = frozenset({'meson.build', 'meson.options', 'meson_options.txt'}) + # I feel dirty about this. But only slightly. + filelist: T.List[str] = [] + for root, _, files in os.walk(src_dir): + filelist.extend(os.path.relpath(os.path.join(root, f), src_dir) + for f in build_files.intersection(files)) + return filelist + +def list_buildsystem_files(builddata: build.Build, interpreter: Interpreter) -> T.List[str]: + src_dir = builddata.environment.get_source_dir() + filelist = list(interpreter.get_build_def_files()) + filelist = [PurePath(src_dir, x).as_posix() for x in filelist] + return filelist + +def list_compilers(coredata: cdata.CoreData) -> T.Dict[str, T.Dict[str, T.Dict[str, str]]]: + compilers: T.Dict[str, T.Dict[str, T.Dict[str, str]]] = {} + for machine in ('host', 'build'): + compilers[machine] = {} + for language, compiler in getattr(coredata.compilers, machine).items(): + compilers[machine][language] = { + 'id': compiler.get_id(), + 'exelist': compiler.get_exelist(), + 'linker_exelist': compiler.get_linker_exelist(), + 'file_suffixes': compiler.file_suffixes, + 'default_suffix': compiler.get_default_suffix(), + 'version': compiler.version, + 'full_version': compiler.full_version, + 'linker_id': compiler.get_linker_id(), + } + return compilers + +def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool]]]: + result = [] # type: T.List[T.Dict[str, T.Union[str, bool]]] + for i in intr.dependencies: + keys = [ + 'name', + 'required', + 'version', + 'has_fallback', + 'conditional', + ] + result += [{k: v for k, v in i.items() if k in keys}] + return result + +def list_deps(coredata: cdata.CoreData, backend: backends.Backend) -> T.List[T.Dict[str, T.Union[str, T.List[str]]]]: + result: T.Dict[str, T.Dict[str, T.Union[str, T.List[str]]]] = {} + + def _src_to_str(src_file: T.Union[mesonlib.FileOrString, build.CustomTarget, build.StructuredSources, build.CustomTargetIndex, build.GeneratedList]) -> T.List[str]: + if isinstance(src_file, str): + return [src_file] + if isinstance(src_file, mesonlib.File): + return [src_file.absolute_path(backend.source_dir, backend.build_dir)] + if isinstance(src_file, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)): + return src_file.get_outputs() + if isinstance(src_file, build.StructuredSources): + return [f for s in src_file.as_list() for f in _src_to_str(s)] + raise mesonlib.MesonBugException(f'Invalid file type {type(src_file)}.') + + def _create_result(d: Dependency, varname: T.Optional[str] = None) -> T.Dict[str, T.Any]: + return { + 'name': d.name, + 'type': d.type_name, + 'version': d.get_version(), + 'compile_args': d.get_compile_args(), + 'link_args': d.get_link_args(), + 'include_directories': [i for idirs in d.get_include_dirs() for i in idirs.to_string_list(backend.source_dir)], + 'sources': [f for s in d.get_sources() for f in _src_to_str(s)], + 'extra_files': [f for s in d.get_extra_files() for f in _src_to_str(s)], + 'dependencies': [e.name for e in d.ext_deps], + 'depends': [lib.get_id() for lib in getattr(d, 'libraries', [])], + 'meson_variables': [varname] if varname else [], + } + + for d in coredata.deps.host.values(): + if d.found(): + result[d.name] = _create_result(d) + + for varname, holder in backend.interpreter.variables.items(): + if isinstance(holder, ObjectHolder): + d = holder.held_object + if isinstance(d, Dependency) and d.found(): + if d.name in result: + T.cast(T.List[str], result[d.name]['meson_variables']).append(varname) + else: + result[d.name] = _create_result(d, varname) + + return list(result.values()) + +def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]: + result = [] # type: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]] + for t in testdata: + to = {} # type: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]] + if isinstance(t.fname, str): + fname = [t.fname] + else: + fname = t.fname + to['cmd'] = fname + t.cmd_args + if isinstance(t.env, build.EnvironmentVariables): + to['env'] = t.env.get_env({}) + else: + to['env'] = t.env + to['name'] = t.name + to['workdir'] = t.workdir + to['timeout'] = t.timeout + to['suite'] = t.suite + to['is_parallel'] = t.is_parallel + to['priority'] = t.priority + to['protocol'] = str(t.protocol) + to['depends'] = t.depends + to['extra_paths'] = t.extra_paths + result.append(to) + return result + +def list_tests(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]: + return get_test_list(testdata) + +def list_benchmarks(benchdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]: + return get_test_list(benchdata) + +def list_machines(builddata: build.Build) -> T.Dict[str, T.Dict[str, T.Union[str, bool]]]: + machines: T.Dict[str, T.Dict[str, T.Union[str, bool]]] = {} + for m in ('host', 'build', 'target'): + machine = getattr(builddata.environment.machines, m) + machines[m] = dataclasses.asdict(machine) + machines[m]['is_64_bit'] = machine.is_64_bit + machines[m]['exe_suffix'] = machine.get_exe_suffix() + machines[m]['object_suffix'] = machine.get_object_suffix() + return machines + +def list_projinfo(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]: + result = {'version': builddata.project_version, + 'descriptive_name': builddata.project_name, + 'subproject_dir': builddata.subproject_dir} # type: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]] + subprojects = [] + for k, v in builddata.subprojects.items(): + c = {'name': k, + 'version': v, + 'descriptive_name': builddata.projects.get(k)} # type: T.Dict[str, str] + subprojects.append(c) + result['subprojects'] = subprojects + return result + +def list_projinfo_from_source(intr: IntrospectionInterpreter) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]: + sourcedir = intr.source_root + files = find_buildsystem_files_list(sourcedir) + files = [os.path.normpath(x) for x in files] + + for i in intr.project_data['subprojects']: + basedir = os.path.join(intr.subproject_dir, i['name']) + i['buildsystem_files'] = [x for x in files if x.startswith(basedir)] + files = [x for x in files if not x.startswith(basedir)] + + intr.project_data['buildsystem_files'] = files + intr.project_data['subproject_dir'] = intr.subproject_dir + return intr.project_data + +def print_results(options: argparse.Namespace, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: int) -> int: + if not results and not options.force_dict: + print('No command specified') + return 1 + elif len(results) == 1 and not options.force_dict: + # Make to keep the existing output format for a single option + print(json.dumps(results[0][1], indent=indent)) + else: + out = {} + for i in results: + out[i[0]] = i[1] + print(json.dumps(out, indent=indent)) + return 0 + +def get_infodir(builddir: T.Optional[str] = None) -> str: + infodir = 'meson-info' + if builddir is not None: + infodir = os.path.join(builddir, infodir) + return infodir + +def get_info_file(infodir: str, kind: T.Optional[str] = None) -> str: + return os.path.join(infodir, + 'meson-info.json' if not kind else f'intro-{kind}.json') + +def load_info_file(infodir: str, kind: T.Optional[str] = None) -> T.Any: + with open(get_info_file(infodir, kind), encoding='utf-8') as fp: + return json.load(fp) + +def run(options: argparse.Namespace) -> int: + datadir = 'meson-private' + infodir = get_infodir(options.builddir) + if options.builddir is not None: + datadir = os.path.join(options.builddir, datadir) + indent = 4 if options.indent else None + results = [] # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] + sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] + intro_types = get_meson_introspection_types(sourcedir=sourcedir) + + if 'meson.build' in [os.path.basename(options.builddir), options.builddir]: + # Make sure that log entries in other parts of meson don't interfere with the JSON output + with redirect_stdout(sys.stderr): + backend = backends.get_backend_from_name(options.backend) + assert backend is not None + intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()]) + intr.analyze() + + for key, val in intro_types.items(): + if (not options.all and not getattr(options, key, False)) or not val.no_bd: + continue + results += [(key, val.no_bd(intr))] + return print_results(options, results, indent) + + try: + raw = load_info_file(infodir) + intro_vers = raw.get('introspection', {}).get('version', {}).get('full', '0.0.0') + except FileNotFoundError: + if not os.path.isdir(datadir) or not os.path.isdir(infodir): + print('Current directory is not a meson build directory.\n' + 'Please specify a valid build dir or change the working directory to it.') + else: + print('Introspection file {} does not exist.\n' + 'It is also possible that the build directory was generated with an old\n' + 'meson version. Please regenerate it in this case.'.format(get_info_file(infodir))) + return 1 + + vers_to_check = get_meson_introspection_required_version() + for i in vers_to_check: + if not mesonlib.version_compare(intro_vers, i): + print('Introspection version {} is not supported. ' + 'The required version is: {}' + .format(intro_vers, ' and '.join(vers_to_check))) + return 1 + + # Extract introspection information from JSON + for i, v in intro_types.items(): + if not v.func: + continue + if not options.all and not getattr(options, i, False): + continue + try: + results += [(i, load_info_file(infodir, i))] + except FileNotFoundError: + print('Introspection file {} does not exist.'.format(get_info_file(infodir, i))) + return 1 + + return print_results(options, results, indent) + +updated_introspection_files = [] # type: T.List[str] + +def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], info_dir: str) -> None: + for kind, data in intro_info: + out_file = os.path.join(info_dir, f'intro-{kind}.json') + tmp_file = os.path.join(info_dir, 'tmp_dump.json') + with open(tmp_file, 'w', encoding='utf-8') as fp: + json.dump(data, fp) + fp.flush() # Not sure if this is needed + os.replace(tmp_file, out_file) + updated_introspection_files.append(kind) + +def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None: + coredata = builddata.environment.get_coredata() + intro_types = get_meson_introspection_types(coredata=coredata, builddata=builddata, backend=backend) + intro_info = [] # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] + + for key, val in intro_types.items(): + if not val.func: + continue + intro_info += [(key, val.func())] + + write_intro_info(intro_info, builddata.environment.info_dir) + +def update_build_options(coredata: cdata.CoreData, info_dir: str) -> None: + intro_info = [ + ('buildoptions', list_buildoptions(coredata)) + ] + + write_intro_info(intro_info, info_dir) + +def split_version_string(version: str) -> T.Dict[str, T.Union[str, int]]: + vers_list = version.split('.') + return { + 'full': version, + 'major': int(vers_list[0] if len(vers_list) > 0 else 0), + 'minor': int(vers_list[1] if len(vers_list) > 1 else 0), + 'patch': int(vers_list[2] if len(vers_list) > 2 else 0) + } + +def write_meson_info_file(builddata: build.Build, errors: list, build_files_updated: bool = False) -> None: + info_dir = builddata.environment.info_dir + info_file = get_meson_info_file(info_dir) + intro_types = get_meson_introspection_types() + intro_info = {} + + for i, v in intro_types.items(): + if not v.func: + continue + intro_info[i] = { + 'file': f'intro-{i}.json', + 'updated': i in updated_introspection_files + } + + info_data = { + 'meson_version': split_version_string(cdata.version), + 'directories': { + 'source': builddata.environment.get_source_dir(), + 'build': builddata.environment.get_build_dir(), + 'info': info_dir, + }, + 'introspection': { + 'version': split_version_string(get_meson_introspection_version()), + 'information': intro_info, + }, + 'build_files_updated': build_files_updated, + } + + if errors: + info_data['error'] = True + info_data['error_list'] = [x if isinstance(x, str) else str(x) for x in errors] + else: + info_data['error'] = False + + # Write the data to disc + tmp_file = os.path.join(info_dir, 'tmp_dump.json') + with open(tmp_file, 'w', encoding='utf-8') as fp: + json.dump(info_data, fp) + fp.flush() + os.replace(tmp_file, info_file) diff --git a/devtools/meson/mesonbuild/mlog.py b/devtools/meson/mesonbuild/mlog.py new file mode 100644 index 0000000..3c95ee8 --- /dev/null +++ b/devtools/meson/mesonbuild/mlog.py @@ -0,0 +1,547 @@ +# Copyright 2013-2014 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This is (mostly) a standalone module used to write logging +information about Meson runs. Some output goes to screen, +some to logging dir and some goes to both.""" + +from __future__ import annotations + +import enum +import os +import io +import sys +import time +import platform +import shlex +import subprocess +import shutil +import typing as T +from contextlib import contextmanager +from dataclasses import dataclass, field +from pathlib import Path + +if T.TYPE_CHECKING: + from ._typing import StringProtocol, SizedStringProtocol + + from .mparser import BaseNode + + TV_Loggable = T.Union[str, 'AnsiDecorator', StringProtocol] + TV_LoggableList = T.List[TV_Loggable] + +def is_windows() -> bool: + platname = platform.system().lower() + return platname == 'windows' + +def _windows_ansi() -> bool: + # windll only exists on windows, so mypy will get mad + from ctypes import windll, byref # type: ignore + from ctypes.wintypes import DWORD + + kernel = windll.kernel32 + stdout = kernel.GetStdHandle(-11) + mode = DWORD() + if not kernel.GetConsoleMode(stdout, byref(mode)): + return False + # ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0x4 + # If the call to enable VT processing fails (returns 0), we fallback to + # original behavior + return bool(kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')) + +def colorize_console() -> bool: + _colorize_console = getattr(sys.stdout, 'colorize_console', None) # type: bool + if _colorize_console is not None: + return _colorize_console + + try: + if is_windows(): + _colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi() + else: + _colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM', 'dumb') != 'dumb' + except Exception: + _colorize_console = False + + sys.stdout.colorize_console = _colorize_console # type: ignore[attr-defined] + return _colorize_console + +def setup_console() -> None: + # on Windows, a subprocess might call SetConsoleMode() on the console + # connected to stdout and turn off ANSI escape processing. Call this after + # running a subprocess to ensure we turn it on again. + if is_windows(): + try: + delattr(sys.stdout, 'colorize_console') + except AttributeError: + pass + +_in_ci = 'CI' in os.environ + + +class _Severity(enum.Enum): + + NOTICE = enum.auto() + WARNING = enum.auto() + ERROR = enum.auto() + DEPRECATION = enum.auto() + +@dataclass +class _Logger: + + log_dir: T.Optional[str] = None + log_depth: T.List[str] = field(default_factory=list) + log_file: T.Optional[T.TextIO] = None + log_timestamp_start: T.Optional[float] = None + log_fatal_warnings = False + log_disable_stdout = False + log_errors_only = False + logged_once: T.Set[T.Tuple[str, ...]] = field(default_factory=set) + log_warnings_counter = 0 + log_pager: T.Optional['subprocess.Popen'] = None + + _LOG_FNAME: T.ClassVar[str] = 'meson-log.txt' + + @contextmanager + def no_logging(self) -> T.Iterator[None]: + self.log_disable_stdout = True + try: + yield + finally: + self.log_disable_stdout = False + + @contextmanager + def force_logging(self) -> T.Iterator[None]: + restore = self.log_disable_stdout + self.log_disable_stdout = False + try: + yield + finally: + self.log_disable_stdout = restore + + def set_quiet(self) -> None: + self.log_errors_only = True + + def set_verbose(self) -> None: + self.log_errors_only = False + + def set_timestamp_start(self, start: float) -> None: + self.log_timestamp_start = start + + def shutdown(self) -> T.Optional[str]: + if self.log_file is not None: + path = self.log_file.name + exception_around_goer = self.log_file + self.log_file = None + exception_around_goer.close() + return path + self.stop_pager() + return None + + def start_pager(self) -> None: + if not colorize_console(): + return + pager_cmd = [] + if 'PAGER' in os.environ: + pager_cmd = shlex.split(os.environ['PAGER']) + else: + less = shutil.which('less') + if not less and is_windows(): + git = shutil.which('git') + if git: + path = Path(git).parents[1] / 'usr' / 'bin' + less = shutil.which('less', path=str(path)) + if less: + pager_cmd = [less] + if not pager_cmd: + return + try: + # Set 'LESS' environment variable, rather than arguments in + # pager_cmd, to also support the case where the user has 'PAGER' + # set to 'less'. Arguments set are: + # "R" : support color + # "X" : do not clear the screen when leaving the pager + # "F" : skip the pager if content fits into the screen + env = os.environ.copy() + if 'LESS' not in env: + env['LESS'] = 'RXF' + # Set "-c" for lv to support color + if 'LV' not in env: + env['LV'] = '-c' + self.log_pager = subprocess.Popen(pager_cmd, stdin=subprocess.PIPE, + text=True, encoding='utf-8', env=env) + except Exception as e: + # Ignore errors, unless it is a user defined pager. + if 'PAGER' in os.environ: + from .mesonlib import MesonException + raise MesonException(f'Failed to start pager: {str(e)}') + + def stop_pager(self) -> None: + if self.log_pager: + try: + self.log_pager.stdin.flush() + self.log_pager.stdin.close() + except BrokenPipeError: + pass + self.log_pager.wait() + self.log_pager = None + + def initialize(self, logdir: str, fatal_warnings: bool = False) -> None: + self.log_dir = logdir + self.log_file = open(os.path.join(logdir, self._LOG_FNAME), 'w', encoding='utf-8') + self.log_fatal_warnings = fatal_warnings + + def process_markup(self, args: T.Sequence[TV_Loggable], keep: bool) -> T.List[str]: + arr = [] # type: T.List[str] + if self.log_timestamp_start is not None: + arr = ['[{:.3f}]'.format(time.monotonic() - self.log_timestamp_start)] + for arg in args: + if arg is None: + continue + if isinstance(arg, str): + arr.append(arg) + elif isinstance(arg, AnsiDecorator): + arr.append(arg.get_text(keep)) + else: + arr.append(str(arg)) + return arr + + def force_print(self, *args: str, nested: bool, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + if self.log_disable_stdout: + return + iostr = io.StringIO() + print(*args, sep=sep, end=end, file=iostr) + + raw = iostr.getvalue() + if self.log_depth: + prepend = self.log_depth[-1] + '| ' if nested else '' + lines = [] + for l in raw.split('\n'): + l = l.strip() + lines.append(prepend + l if l else '') + raw = '\n'.join(lines) + + # _Something_ is going to get printed. + try: + output = self.log_pager.stdin if self.log_pager else None + print(raw, end='', file=output) + except UnicodeEncodeError: + cleaned = raw.encode('ascii', 'replace').decode('ascii') + print(cleaned, end='') + + def debug(self, *args: TV_Loggable, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + arr = process_markup(args, False) + if self.log_file is not None: + print(*arr, file=self.log_file, sep=sep, end=end) + self.log_file.flush() + + def _log(self, *args: TV_Loggable, is_error: bool = False, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + arr = process_markup(args, False) + if self.log_file is not None: + print(*arr, file=self.log_file, sep=sep, end=end) + self.log_file.flush() + if colorize_console(): + arr = process_markup(args, True) + if not self.log_errors_only or is_error: + force_print(*arr, nested=nested, sep=sep, end=end) + + def _debug_log_cmd(self, cmd: str, args: T.List[str]) -> None: + if not _in_ci: + return + args = [f'"{x}"' for x in args] # Quote all args, just in case + self.debug('!meson_ci!/{} {}'.format(cmd, ' '.join(args))) + + def cmd_ci_include(self, file: str) -> None: + self._debug_log_cmd('ci_include', [file]) + + def log(self, *args: TV_Loggable, is_error: bool = False, + once: bool = False, nested: bool = True, + sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + if once: + self._log_once(*args, is_error=is_error, nested=nested, sep=sep, end=end) + else: + self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + + def _log_once(self, *args: TV_Loggable, is_error: bool = False, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + """Log variant that only prints a given message one time per meson invocation. + + This considers ansi decorated values by the values they wrap without + regard for the AnsiDecorator itself. + """ + def to_str(x: TV_Loggable) -> str: + if isinstance(x, str): + return x + if isinstance(x, AnsiDecorator): + return x.text + return str(x) + t = tuple(to_str(a) for a in args) + if t in self.logged_once: + return + self.logged_once.add(t) + self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + + def _log_error(self, severity: _Severity, *rargs: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None, + is_error: bool = True) -> None: + from .mesonlib import MesonException, relpath + + # The typing requirements here are non-obvious. Lists are invariant, + # therefore T.List[A] and T.List[T.Union[A, B]] are not able to be joined + if severity is _Severity.NOTICE: + label = [bold('NOTICE:')] # type: TV_LoggableList + elif severity is _Severity.WARNING: + label = [yellow('WARNING:')] + elif severity is _Severity.ERROR: + label = [red('ERROR:')] + elif severity is _Severity.DEPRECATION: + label = [red('DEPRECATION:')] + # rargs is a tuple, not a list + args = label + list(rargs) + + if location is not None: + location_file = relpath(location.filename, os.getcwd()) + location_str = get_error_location_string(location_file, location.lineno) + # Unions are frankly awful, and we have to T.cast here to get mypy + # to understand that the list concatenation is safe + location_list = T.cast('TV_LoggableList', [location_str]) + args = location_list + args + + log(*args, once=once, nested=nested, sep=sep, end=end, is_error=is_error) + + self.log_warnings_counter += 1 + + if self.log_fatal_warnings and fatal: + raise MesonException("Fatal warnings enabled, aborting") + + def error(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.ERROR, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=True) + + def warning(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.WARNING, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=True) + + def deprecation(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.DEPRECATION, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=True) + + def notice(self, *args: TV_Loggable, + once: bool = False, fatal: bool = True, + location: T.Optional[BaseNode] = None, + nested: bool = True, sep: T.Optional[str] = None, + end: T.Optional[str] = None) -> None: + return self._log_error(_Severity.NOTICE, *args, once=once, fatal=fatal, location=location, + nested=nested, sep=sep, end=end, is_error=False) + + def exception(self, e: Exception, prefix: T.Optional[AnsiDecorator] = None) -> None: + if prefix is None: + prefix = red('ERROR:') + self.log() + args = [] # type: T.List[T.Union[AnsiDecorator, str]] + if all(getattr(e, a, None) is not None for a in ['file', 'lineno', 'colno']): + # Mypy doesn't follow hasattr, and it's pretty easy to visually inspect + # that this is correct, so we'll just ignore it. + path = get_relative_path(Path(e.file), Path(os.getcwd())) # type: ignore + args.append(f'{path}:{e.lineno}:{e.colno}:') # type: ignore + if prefix: + args.append(prefix) + args.append(str(e)) + + with self.force_logging(): + self.log(*args, is_error=True) + + @contextmanager + def nested(self, name: str = '') -> T.Generator[None, None, None]: + self.log_depth.append(name) + try: + yield + finally: + self.log_depth.pop() + + def get_log_dir(self) -> str: + return self.log_dir + + def get_log_depth(self) -> int: + return len(self.log_depth) + + @contextmanager + def nested_warnings(self) -> T.Iterator[None]: + old = self.log_warnings_counter + self.log_warnings_counter = 0 + try: + yield + finally: + self.log_warnings_counter = old + + def get_warning_count(self) -> int: + return self.log_warnings_counter + +_logger = _Logger() +cmd_ci_include = _logger.cmd_ci_include +debug = _logger.debug +deprecation = _logger.deprecation +error = _logger.error +exception = _logger.exception +force_print = _logger.force_print +get_log_depth = _logger.get_log_depth +get_log_dir = _logger.get_log_dir +get_warning_count = _logger.get_warning_count +initialize = _logger.initialize +log = _logger.log +nested = _logger.nested +nested_warnings = _logger.nested_warnings +no_logging = _logger.no_logging +notice = _logger.notice +process_markup = _logger.process_markup +set_quiet = _logger.set_quiet +set_timestamp_start = _logger.set_timestamp_start +set_verbose = _logger.set_verbose +shutdown = _logger.shutdown +start_pager = _logger.start_pager +stop_pager = _logger.stop_pager +warning = _logger.warning + +class AnsiDecorator: + plain_code = "\033[0m" + + def __init__(self, text: str, code: str, quoted: bool = False): + self.text = text + self.code = code + self.quoted = quoted + + def get_text(self, with_codes: bool) -> str: + text = self.text + if with_codes and self.code: + text = self.code + self.text + AnsiDecorator.plain_code + if self.quoted: + text = f'"{text}"' + return text + + def __len__(self) -> int: + return len(self.text) + + def __str__(self) -> str: + return self.get_text(colorize_console()) + +class AnsiText: + def __init__(self, *args: 'SizedStringProtocol'): + self.args = args + + def __len__(self) -> int: + return sum(len(x) for x in self.args) + + def __str__(self) -> str: + return ''.join(str(x) for x in self.args) + + +def bold(text: str, quoted: bool = False) -> AnsiDecorator: + return AnsiDecorator(text, "\033[1m", quoted=quoted) + +def italic(text: str, quoted: bool = False) -> AnsiDecorator: + return AnsiDecorator(text, "\033[3m", quoted=quoted) + +def plain(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "") + +def red(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[1;31m") + +def green(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[1;32m") + +def yellow(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[1;33m") + +def blue(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[1;34m") + +def cyan(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[1;36m") + +def normal_red(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[31m") + +def normal_green(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[32m") + +def normal_yellow(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[33m") + +def normal_blue(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[34m") + +def normal_cyan(text: str) -> AnsiDecorator: + return AnsiDecorator(text, "\033[36m") + +def get_error_location_string(fname: StringProtocol, lineno: int) -> str: + return f'{fname}:{lineno}:' + +def get_relative_path(target: Path, current: Path) -> Path: + """Get the path to target from current""" + # Go up "current" until we find a common ancestor to target + acc = ['.'] + for part in [current, *current.parents]: + try: + path = target.relative_to(part) + return Path(*acc, path) + except ValueError: + pass + acc += ['..'] + + # we failed, should not get here + return target + +# Format a list for logging purposes as a string. It separates +# all but the last item with commas, and the last with 'and'. +def format_list(input_list: T.List[str]) -> str: + l = len(input_list) + if l > 2: + return ' and '.join([', '.join(input_list[:-1]), input_list[-1]]) + elif l == 2: + return ' and '.join(input_list) + elif l == 1: + return input_list[0] + else: + return '' + + +def code_line(text: str, line: str, colno: int) -> str: + """Print a line with a caret pointing to the colno + + :param text: A message to display before the line + :param line: The line of code to be pointed to + :param colno: The column number to point at + :return: A formatted string of the text, line, and a caret + """ + return f'{text}\n{line}\n{" " * colno}^' diff --git a/devtools/meson/mesonbuild/modules/__init__.py b/devtools/meson/mesonbuild/modules/__init__.py new file mode 100644 index 0000000..7ef87b2 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/__init__.py @@ -0,0 +1,279 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file contains the base representation for import('modname') + +from __future__ import annotations +import dataclasses +import typing as T + +from .. import build, mesonlib +from ..build import IncludeDirs +from ..interpreterbase.decorators import noKwargs, noPosargs +from ..mesonlib import relpath, HoldableObject, MachineChoice +from ..programs import ExternalProgram + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + from ..interpreter.interpreterobjects import MachineHolder + from ..interpreterbase import TYPE_var, TYPE_kwargs + from ..programs import OverrideProgram + from ..wrap import WrapMode + from ..build import Executable + from ..dependencies import Dependency + +class ModuleState: + """Object passed to all module methods. + + This is a WIP API provided to modules, it should be extended to have everything + needed so modules does not touch any other part of Meson internal APIs. + """ + + def __init__(self, interpreter: 'Interpreter') -> None: + # Keep it private, it should be accessed only through methods. + self._interpreter = interpreter + + self.source_root = interpreter.environment.get_source_dir() + self.build_to_src = relpath(interpreter.environment.get_source_dir(), + interpreter.environment.get_build_dir()) + self.subproject = interpreter.subproject + self.subdir = interpreter.subdir + self.root_subdir = interpreter.root_subdir + self.current_lineno = interpreter.current_lineno + self.environment = interpreter.environment + self.project_name = interpreter.build.project_name + self.project_version = interpreter.build.dep_manifest[interpreter.active_projectname].version + # The backend object is under-used right now, but we will need it: + # https://github.com/mesonbuild/meson/issues/1419 + self.backend = interpreter.backend + self.targets = interpreter.build.targets + self.data = interpreter.build.data + self.headers = interpreter.build.get_headers() + self.man = interpreter.build.get_man() + self.global_args = interpreter.build.global_args.host + self.project_args = interpreter.build.projects_args.host.get(interpreter.subproject, {}) + self.build_machine = T.cast('MachineHolder', interpreter.builtin['build_machine']).held_object + self.host_machine = T.cast('MachineHolder', interpreter.builtin['host_machine']).held_object + self.target_machine = T.cast('MachineHolder', interpreter.builtin['target_machine']).held_object + self.current_node = interpreter.current_node + + def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDirs]], prefix: str = '-I') -> T.List[str]: + if not include_dirs: + return [] + + srcdir = self.environment.get_source_dir() + builddir = self.environment.get_build_dir() + + dirs_str: T.List[str] = [] + for dirs in include_dirs: + if isinstance(dirs, str): + dirs_str += [f'{prefix}{dirs}'] + else: + dirs_str.extend([f'{prefix}{i}' for i in dirs.to_string_list(srcdir, builddir)]) + dirs_str.extend([f'{prefix}{i}' for i in dirs.get_extra_build_dirs()]) + + return dirs_str + + def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.FileOrString]], + required: bool = True, + version_func: T.Optional[T.Callable[[T.Union[ExternalProgram, Executable, OverrideProgram]], str]] = None, + wanted: T.Optional[str] = None, silent: bool = False, + for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, Executable, OverrideProgram]: + if not isinstance(prog, list): + prog = [prog] + return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, + wanted=wanted, silent=silent, for_machine=for_machine) + + def find_tool(self, name: str, depname: str, varname: str, required: bool = True, + wanted: T.Optional[str] = None) -> T.Union['Executable', ExternalProgram, 'OverrideProgram']: + # Look in overrides in case it's built as subproject + progobj = self._interpreter.program_from_overrides([name], []) + if progobj is not None: + return progobj + + # Look in machine file + prog_list = self.environment.lookup_binary_entry(MachineChoice.HOST, name) + if prog_list is not None: + return ExternalProgram.from_entry(name, prog_list) + + # Check if pkgconfig has a variable + dep = self.dependency(depname, native=True, required=False, wanted=wanted) + if dep.found() and dep.type_name == 'pkgconfig': + value = dep.get_variable(pkgconfig=varname) + if value: + return ExternalProgram(name, [value]) + + # Normal program lookup + return self.find_program(name, required=required, wanted=wanted) + + def dependency(self, depname: str, native: bool = False, required: bool = True, + wanted: T.Optional[str] = None) -> 'Dependency': + kwargs: T.Dict[str, object] = {'native': native, 'required': required} + if wanted: + kwargs['version'] = wanted + # FIXME: Even if we fix the function, mypy still can't figure out what's + # going on here. And we really dont want to call interpreter + # implementations of meson functions anyway. + return self._interpreter.func_dependency(self.current_node, [depname], kwargs) # type: ignore + + def test(self, args: T.Tuple[str, T.Union[build.Executable, build.Jar, 'ExternalProgram', mesonlib.File]], + workdir: T.Optional[str] = None, + env: T.Union[T.List[str], T.Dict[str, str], str] = None, + depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]] = None) -> None: + kwargs = {'workdir': workdir, + 'env': env, + 'depends': depends, + } + # typed_* takes a list, and gives a tuple to func_test. Violating that constraint + # makes the universe (or at least use of this function) implode + real_args = list(args) + # TODO: Use interpreter internal API, but we need to go through @typed_kwargs + self._interpreter.func_test(self.current_node, real_args, kwargs) + + def get_option(self, name: str, subproject: str = '', + machine: MachineChoice = MachineChoice.HOST, + lang: T.Optional[str] = None, + module: T.Optional[str] = None) -> T.Union[T.List[str], str, int, bool, 'WrapMode']: + return self.environment.coredata.get_option(mesonlib.OptionKey(name, subproject, machine, lang, module)) + + def is_user_defined_option(self, name: str, subproject: str = '', + machine: MachineChoice = MachineChoice.HOST, + lang: T.Optional[str] = None, + module: T.Optional[str] = None) -> bool: + key = mesonlib.OptionKey(name, subproject, machine, lang, module) + return key in self._interpreter.user_defined_options.cmd_line_options + + def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T.Iterable[IncludeDirs]: + """Convert raw include directory arguments to only IncludeDirs + + :param dirs: An iterable of strings and IncludeDirs + :return: None + :yield: IncludeDirs objects + """ + for d in dirs: + if isinstance(d, IncludeDirs): + yield d + else: + yield self._interpreter.build_incdir_object([d]) + + def add_language(self, lang: str, for_machine: MachineChoice) -> None: + self._interpreter.add_languages([lang], True, for_machine) + +class ModuleObject(HoldableObject): + """Base class for all objects returned by modules + """ + def __init__(self) -> None: + self.methods: T.Dict[ + str, + T.Callable[[ModuleState, T.List['TYPE_var'], 'TYPE_kwargs'], T.Union[ModuleReturnValue, 'TYPE_var']] + ] = {} + + +class MutableModuleObject(ModuleObject): + pass + + +@dataclasses.dataclass +class ModuleInfo: + + """Metadata about a Module.""" + + name: str + added: T.Optional[str] = None + deprecated: T.Optional[str] = None + unstable: bool = False + stabilized: T.Optional[str] = None + + +class NewExtensionModule(ModuleObject): + + """Class for modern modules + + provides the found method. + """ + + INFO: ModuleInfo + + def __init__(self) -> None: + super().__init__() + self.methods.update({ + 'found': self.found_method, + }) + + @noPosargs + @noKwargs + def found_method(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool: + return self.found() + + @staticmethod + def found() -> bool: + return True + + def postconf_hook(self, b: build.Build) -> None: + pass + +# FIXME: Port all modules to stop using self.interpreter and use API on +# ModuleState instead. Modules should stop using this class and instead use +# ModuleObject base class. +class ExtensionModule(NewExtensionModule): + def __init__(self, interpreter: 'Interpreter') -> None: + super().__init__() + self.interpreter = interpreter + +class NotFoundExtensionModule(NewExtensionModule): + + """Class for modern modules + + provides the found method. + """ + + def __init__(self, name: str) -> None: + super().__init__() + self.INFO = ModuleInfo(name) + + @staticmethod + def found() -> bool: + return False + + +def is_module_library(fname: mesonlib.FileOrString) -> bool: + ''' + Check if the file is a library-like file generated by a module-specific + target, such as GirTarget or TypelibTarget + ''' + suffix = fname.split('.')[-1] + return suffix in {'gir', 'typelib'} + + +class ModuleReturnValue: + def __init__(self, return_value: T.Optional['TYPE_var'], + new_objects: T.Sequence[T.Union['TYPE_var', 'build.ExecutableSerialisation']]) -> None: + self.return_value = return_value + assert isinstance(new_objects, list) + self.new_objects: T.List[T.Union['TYPE_var', 'build.ExecutableSerialisation']] = new_objects + +class GResourceTarget(build.CustomTarget): + pass + +class GResourceHeaderTarget(build.CustomTarget): + pass + +class GirTarget(build.CustomTarget): + pass + +class TypelibTarget(build.CustomTarget): + pass + +class VapiTarget(build.CustomTarget): + pass diff --git a/devtools/meson/mesonbuild/modules/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/modules/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08234c836128427b45f0e25f569a62872a1cea43 GIT binary patch literal 10701 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/modules/cmake.py b/devtools/meson/mesonbuild/modules/cmake.py new file mode 100644 index 0000000..c6048f9 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/cmake.py @@ -0,0 +1,450 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import re +import os, os.path, pathlib +import shutil +import typing as T + +from . import ExtensionModule, ModuleReturnValue, ModuleObject, ModuleInfo + +from .. import build, mesonlib, mlog, dependencies +from ..cmake import TargetOptions, cmake_defines_to_args +from ..interpreter import SubprojectHolder +from ..interpreter.type_checking import REQUIRED_KW, INSTALL_DIR_KW, NoneType, in_set_validator +from ..interpreterbase import ( + FeatureNew, + FeatureNewKwargs, + + stringArgs, + permittedKwargs, + noPosargs, + noKwargs, + + InvalidArguments, + InterpreterException, + + typed_pos_args, + typed_kwargs, + KwargInfo, + ContainerTypeInfo, +) + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from ..cmake import SingleTargetOptions + from ..environment import Environment + from ..interpreter import Interpreter, kwargs + from ..interpreterbase import TYPE_kwargs, TYPE_var + + class WriteBasicPackageVersionFile(TypedDict): + + arch_independent: bool + compatibility: str + install_dir: T.Optional[str] + name: str + version: str + + class ConfigurePackageConfigFile(TypedDict): + + configuration: T.Union[build.ConfigurationData, dict] + input: T.Union[str, mesonlib.File] + install_dir: T.Optional[str] + name: str + + class Subproject(kwargs.ExtractRequired): + + options: T.Optional[CMakeSubprojectOptions] + cmake_options: T.List[str] + + +COMPATIBILITIES = ['AnyNewerVersion', 'SameMajorVersion', 'SameMinorVersion', 'ExactVersion'] + +# Taken from https://github.com/Kitware/CMake/blob/master/Modules/CMakePackageConfigHelpers.cmake +PACKAGE_INIT_BASE = ''' +####### Expanded from \\@PACKAGE_INIT\\@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was @inputFileName@ ######## + +get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_RELATIVE_PATH@" ABSOLUTE) +''' +PACKAGE_INIT_EXT = ''' +# Use original install prefix when loaded through a "/usr move" +# cross-prefix symbolic link such as /lib -> /usr/lib. +get_filename_component(_realCurr "${CMAKE_CURRENT_LIST_DIR}" REALPATH) +get_filename_component(_realOrig "@absInstallDir@" REALPATH) +if(_realCurr STREQUAL _realOrig) + set(PACKAGE_PREFIX_DIR "@installPrefix@") +endif() +unset(_realOrig) +unset(_realCurr) +''' +PACKAGE_INIT_SET_AND_CHECK = ''' +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +#################################################################################### +''' + +class CMakeSubproject(ModuleObject): + def __init__(self, subp: SubprojectHolder): + assert isinstance(subp, SubprojectHolder) + assert subp.cm_interpreter is not None + super().__init__() + self.subp = subp + self.cm_interpreter = subp.cm_interpreter + self.methods.update({'get_variable': self.get_variable, + 'dependency': self.dependency, + 'include_directories': self.include_directories, + 'target': self.target, + 'target_type': self.target_type, + 'target_list': self.target_list, + 'found': self.found_method, + }) + + def _args_to_info(self, args: T.List[str]) -> T.Dict[str, str]: + if len(args) != 1: + raise InterpreterException('Exactly one argument is required.') + + tgt = args[0] + res = self.cm_interpreter.target_info(tgt) + if res is None: + raise InterpreterException(f'The CMake target {tgt} does not exist\n' + + ' Use the following command in your meson.build to list all available targets:\n\n' + + ' message(\'CMake targets:\\n - \' + \'\\n - \'.join(.target_list()))') + + # Make sure that all keys are present (if not this is a bug) + assert all(x in res for x in ['inc', 'src', 'dep', 'tgt', 'func']) + return res + + @noKwargs + @stringArgs + def get_variable(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> TYPE_var: + return self.subp.get_variable_method(args, kwargs) + + @FeatureNewKwargs('dependency', '0.56.0', ['include_type']) + @permittedKwargs({'include_type'}) + @stringArgs + def dependency(self, state: ModuleState, args: T.List[str], kwargs: T.Dict[str, str]) -> dependencies.Dependency: + info = self._args_to_info(args) + if info['func'] == 'executable': + raise InvalidArguments(f'{args[0]} is an executable and does not support the dependency() method. Use target() instead.') + orig = self.get_variable(state, [info['dep']], {}) + assert isinstance(orig, dependencies.Dependency) + actual = orig.include_type + if 'include_type' in kwargs and kwargs['include_type'] != actual: + mlog.debug('Current include type is {}. Converting to requested {}'.format(actual, kwargs['include_type'])) + return orig.generate_system_dependency(kwargs['include_type']) + return orig + + @noKwargs + @stringArgs + def include_directories(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> build.IncludeDirs: + info = self._args_to_info(args) + return self.get_variable(state, [info['inc']], kwargs) + + @noKwargs + @stringArgs + def target(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> build.Target: + info = self._args_to_info(args) + return self.get_variable(state, [info['tgt']], kwargs) + + @noKwargs + @stringArgs + def target_type(self, state: ModuleState, args: T.List[str], kwargs: TYPE_kwargs) -> str: + info = self._args_to_info(args) + return info['func'] + + @noPosargs + @noKwargs + def target_list(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> T.List[str]: + return self.cm_interpreter.target_list() + + @noPosargs + @noKwargs + @FeatureNew('CMakeSubproject.found()', '0.53.2') + def found_method(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> bool: + return self.subp is not None + + +class CMakeSubprojectOptions(ModuleObject): + def __init__(self) -> None: + super().__init__() + self.cmake_options = [] # type: T.List[str] + self.target_options = TargetOptions() + + self.methods.update( + { + 'add_cmake_defines': self.add_cmake_defines, + 'set_override_option': self.set_override_option, + 'set_install': self.set_install, + 'append_compile_args': self.append_compile_args, + 'append_link_args': self.append_link_args, + 'clear': self.clear, + } + ) + + def _get_opts(self, kwargs: dict) -> SingleTargetOptions: + if 'target' in kwargs: + return self.target_options[kwargs['target']] + return self.target_options.global_options + + @typed_pos_args('subproject_options.add_cmake_defines', varargs=dict) + @noKwargs + def add_cmake_defines(self, state: ModuleState, args: T.Tuple[T.List[T.Dict[str, TYPE_var]]], kwargs: TYPE_kwargs) -> None: + self.cmake_options += cmake_defines_to_args(args[0]) + + @typed_pos_args('subproject_options.set_override_option', str, str) + @permittedKwargs({'target'}) + def set_override_option(self, state: ModuleState, args: T.Tuple[str, str], kwargs: TYPE_kwargs) -> None: + self._get_opts(kwargs).set_opt(args[0], args[1]) + + @typed_pos_args('subproject_options.set_install', bool) + @permittedKwargs({'target'}) + def set_install(self, state: ModuleState, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> None: + self._get_opts(kwargs).set_install(args[0]) + + @typed_pos_args('subproject_options.append_compile_args', str, varargs=str, min_varargs=1) + @permittedKwargs({'target'}) + def append_compile_args(self, state: ModuleState, args: T.Tuple[str, T.List[str]], kwargs: TYPE_kwargs) -> None: + self._get_opts(kwargs).append_args(args[0], args[1]) + + @typed_pos_args('subproject_options.append_compile_args', varargs=str, min_varargs=1) + @permittedKwargs({'target'}) + def append_link_args(self, state: ModuleState, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> None: + self._get_opts(kwargs).append_link_args(args[0]) + + @noPosargs + @noKwargs + def clear(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> None: + self.cmake_options.clear() + self.target_options = TargetOptions() + + +class CmakeModule(ExtensionModule): + cmake_detected = False + cmake_root = None + + INFO = ModuleInfo('cmake', '0.50.0') + + def __init__(self, interpreter: Interpreter) -> None: + super().__init__(interpreter) + self.methods.update({ + 'write_basic_package_version_file': self.write_basic_package_version_file, + 'configure_package_config_file': self.configure_package_config_file, + 'subproject': self.subproject, + 'subproject_options': self.subproject_options, + }) + + def detect_voidp_size(self, env: Environment) -> int: + compilers = env.coredata.compilers.host + compiler = compilers.get('c', None) + if not compiler: + compiler = compilers.get('cpp', None) + + if not compiler: + raise mesonlib.MesonException('Requires a C or C++ compiler to compute sizeof(void *).') + + return compiler.sizeof('void *', '', env)[0] + + def detect_cmake(self, state: ModuleState) -> bool: + if self.cmake_detected: + return True + + cmakebin = state.find_program('cmake', silent=False) + if not cmakebin.found(): + return False + + p, stdout, stderr = mesonlib.Popen_safe(cmakebin.get_command() + ['--system-information', '-G', 'Ninja'])[0:3] + if p.returncode != 0: + mlog.log(f'error retrieving cmake information: returnCode={p.returncode} stdout={stdout} stderr={stderr}') + return False + + match = re.search('\nCMAKE_ROOT \\"([^"]+)"\n', stdout.strip()) + if not match: + mlog.log('unable to determine cmake root') + return False + + cmakePath = pathlib.PurePath(match.group(1)) + self.cmake_root = os.path.join(*cmakePath.parts) + self.cmake_detected = True + return True + + @noPosargs + @typed_kwargs( + 'cmake.write_basic_package_version_file', + KwargInfo('arch_independent', bool, default=False, since='0.62.0'), + KwargInfo('compatibility', str, default='AnyNewerVersion', validator=in_set_validator(set(COMPATIBILITIES))), + KwargInfo('name', str, required=True), + KwargInfo('version', str, required=True), + INSTALL_DIR_KW, + ) + def write_basic_package_version_file(self, state: ModuleState, args: TYPE_var, kwargs: 'WriteBasicPackageVersionFile') -> ModuleReturnValue: + arch_independent = kwargs['arch_independent'] + compatibility = kwargs['compatibility'] + name = kwargs['name'] + version = kwargs['version'] + + if not self.detect_cmake(state): + raise mesonlib.MesonException('Unable to find cmake') + + pkgroot = pkgroot_name = kwargs['install_dir'] + if pkgroot is None: + pkgroot = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('libdir')), 'cmake', name) + pkgroot_name = os.path.join('{libdir}', 'cmake', name) + + template_file = os.path.join(self.cmake_root, 'Modules', f'BasicConfigVersion-{compatibility}.cmake.in') + if not os.path.exists(template_file): + raise mesonlib.MesonException(f'your cmake installation doesn\'t support the {compatibility} compatibility') + + version_file = os.path.join(state.environment.scratch_dir, f'{name}ConfigVersion.cmake') + + conf: T.Dict[str, T.Union[str, bool, int]] = { + 'CVF_VERSION': version, + 'CMAKE_SIZEOF_VOID_P': str(self.detect_voidp_size(state.environment)), + 'CVF_ARCH_INDEPENDENT': arch_independent, + } + mesonlib.do_conf_file(template_file, version_file, build.ConfigurationData(conf), 'meson') + + res = build.Data([mesonlib.File(True, state.environment.get_scratch_dir(), version_file)], pkgroot, pkgroot_name, None, state.subproject) + return ModuleReturnValue(res, [res]) + + def create_package_file(self, infile: str, outfile: str, PACKAGE_RELATIVE_PATH: str, extra: str, confdata: build.ConfigurationData) -> None: + package_init = PACKAGE_INIT_BASE.replace('@PACKAGE_RELATIVE_PATH@', PACKAGE_RELATIVE_PATH) + package_init = package_init.replace('@inputFileName@', os.path.basename(infile)) + package_init += extra + package_init += PACKAGE_INIT_SET_AND_CHECK + + try: + with open(infile, encoding='utf-8') as fin: + data = fin.readlines() + except Exception as e: + raise mesonlib.MesonException(f'Could not read input file {infile}: {e!s}') + + result = [] + regex = mesonlib.get_variable_regex('cmake@') + for line in data: + line = line.replace('@PACKAGE_INIT@', package_init) + line, _missing = mesonlib.do_replacement(regex, line, 'cmake@', confdata) + + result.append(line) + + outfile_tmp = outfile + "~" + with open(outfile_tmp, "w", encoding='utf-8') as fout: + fout.writelines(result) + + shutil.copymode(infile, outfile_tmp) + mesonlib.replace_if_different(outfile, outfile_tmp) + + @noPosargs + @typed_kwargs( + 'cmake.configure_package_config_file', + KwargInfo('configuration', (build.ConfigurationData, dict), required=True), + KwargInfo('input', + (str, mesonlib.File, ContainerTypeInfo(list, mesonlib.File)), required=True, + validator=lambda x: 'requires exactly one file' if isinstance(x, list) and len(x) != 1 else None, + convertor=lambda x: x[0] if isinstance(x, list) else x), + KwargInfo('name', str, required=True), + INSTALL_DIR_KW, + ) + def configure_package_config_file(self, state: ModuleState, args: TYPE_var, kwargs: 'ConfigurePackageConfigFile') -> build.Data: + inputfile = kwargs['input'] + if isinstance(inputfile, str): + inputfile = mesonlib.File.from_source_file(state.environment.source_dir, state.subdir, inputfile) + + ifile_abs = inputfile.absolute_path(state.environment.source_dir, state.environment.build_dir) + + name = kwargs['name'] + + (ofile_path, ofile_fname) = os.path.split(os.path.join(state.subdir, f'{name}Config.cmake')) + ofile_abs = os.path.join(state.environment.build_dir, ofile_path, ofile_fname) + + install_dir = kwargs['install_dir'] + if install_dir is None: + install_dir = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('libdir')), 'cmake', name) + + conf = kwargs['configuration'] + if isinstance(conf, dict): + FeatureNew.single_use('cmake.configure_package_config_file dict as configuration', '0.62.0', state.subproject, location=state.current_node) + conf = build.ConfigurationData(conf) + + prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix')) + abs_install_dir = install_dir + if not os.path.isabs(abs_install_dir): + abs_install_dir = os.path.join(prefix, install_dir) + + # path used in cmake scripts are POSIX even on Windows + PACKAGE_RELATIVE_PATH = pathlib.PurePath(os.path.relpath(prefix, abs_install_dir)).as_posix() + extra = '' + if re.match('^(/usr)?/lib(64)?/.+', abs_install_dir): + extra = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir) + extra = extra.replace('@installPrefix@', prefix) + + self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf) + conf.used = True + + conffile = os.path.normpath(inputfile.relative_name()) + self.interpreter.build_def_files.add(conffile) + + res = build.Data([mesonlib.File(True, ofile_path, ofile_fname)], install_dir, install_dir, None, state.subproject) + self.interpreter.build.data.append(res) + + return res + + @FeatureNew('subproject', '0.51.0') + @typed_pos_args('cmake.subproject', str) + @typed_kwargs( + 'cmake.subproject', + REQUIRED_KW, + KwargInfo('options', (CMakeSubprojectOptions, NoneType), since='0.55.0'), + KwargInfo( + 'cmake_options', + ContainerTypeInfo(list, str), + default=[], + listify=True, + deprecated='0.55.0', + deprecated_message='Use options instead', + ), + ) + def subproject(self, state: ModuleState, args: T.Tuple[str], kwargs_: Subproject) -> T.Union[SubprojectHolder, CMakeSubproject]: + if kwargs_['cmake_options'] and kwargs_['options'] is not None: + raise InterpreterException('"options" cannot be used together with "cmake_options"') + dirname = args[0] + kw: kwargs.DoSubproject = { + 'required': kwargs_['required'], + 'options': kwargs_['options'], + 'cmake_options': kwargs_['cmake_options'], + 'default_options': {}, + 'version': [], + } + subp = self.interpreter.do_subproject(dirname, 'cmake', kw) + if not subp.found(): + return subp + return CMakeSubproject(subp) + + @FeatureNew('subproject_options', '0.55.0') + @noKwargs + @noPosargs + def subproject_options(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) -> CMakeSubprojectOptions: + return CMakeSubprojectOptions() + +def initialize(*args: T.Any, **kwargs: T.Any) -> CmakeModule: + return CmakeModule(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/cuda.py b/devtools/meson/mesonbuild/modules/cuda.py new file mode 100644 index 0000000..6f809cb --- /dev/null +++ b/devtools/meson/mesonbuild/modules/cuda.py @@ -0,0 +1,390 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import typing as T +import re + +from ..mesonlib import version_compare +from ..compilers.cuda import CudaCompiler + +from . import NewExtensionModule, ModuleInfo + +from ..interpreterbase import ( + flatten, permittedKwargs, noKwargs, + InvalidArguments +) + +if T.TYPE_CHECKING: + from . import ModuleState + from ..compilers import Compiler + +class CudaModule(NewExtensionModule): + + INFO = ModuleInfo('CUDA', '0.50.0', unstable=True) + + def __init__(self, *args, **kwargs): + super().__init__() + self.methods.update({ + "min_driver_version": self.min_driver_version, + "nvcc_arch_flags": self.nvcc_arch_flags, + "nvcc_arch_readable": self.nvcc_arch_readable, + }) + + @noKwargs + def min_driver_version(self, state: 'ModuleState', + args: T.Tuple[str], + kwargs: T.Dict[str, T.Any]) -> str: + argerror = InvalidArguments('min_driver_version must have exactly one positional argument: ' + + 'a CUDA Toolkit version string. Beware that, since CUDA 11.0, ' + + 'the CUDA Toolkit\'s components (including NVCC) are versioned ' + + 'independently from each other (and the CUDA Toolkit as a whole).') + + if len(args) != 1 or not isinstance(args[0], str): + raise argerror + + cuda_version = args[0] + driver_version_table = [ + {'cuda_version': '>=12.0.0', 'windows': '527.41', 'linux': '525.60.13'}, + {'cuda_version': '>=11.8.0', 'windows': '522.06', 'linux': '520.61.05'}, + {'cuda_version': '>=11.7.1', 'windows': '516.31', 'linux': '515.48.07'}, + {'cuda_version': '>=11.7.0', 'windows': '516.01', 'linux': '515.43.04'}, + {'cuda_version': '>=11.6.1', 'windows': '511.65', 'linux': '510.47.03'}, + {'cuda_version': '>=11.6.0', 'windows': '511.23', 'linux': '510.39.01'}, + {'cuda_version': '>=11.5.1', 'windows': '496.13', 'linux': '495.29.05'}, + {'cuda_version': '>=11.5.0', 'windows': '496.04', 'linux': '495.29.05'}, + {'cuda_version': '>=11.4.3', 'windows': '472.50', 'linux': '470.82.01'}, + {'cuda_version': '>=11.4.1', 'windows': '471.41', 'linux': '470.57.02'}, + {'cuda_version': '>=11.4.0', 'windows': '471.11', 'linux': '470.42.01'}, + {'cuda_version': '>=11.3.0', 'windows': '465.89', 'linux': '465.19.01'}, + {'cuda_version': '>=11.2.2', 'windows': '461.33', 'linux': '460.32.03'}, + {'cuda_version': '>=11.2.1', 'windows': '461.09', 'linux': '460.32.03'}, + {'cuda_version': '>=11.2.0', 'windows': '460.82', 'linux': '460.27.03'}, + {'cuda_version': '>=11.1.1', 'windows': '456.81', 'linux': '455.32'}, + {'cuda_version': '>=11.1.0', 'windows': '456.38', 'linux': '455.23'}, + {'cuda_version': '>=11.0.3', 'windows': '451.82', 'linux': '450.51.06'}, + {'cuda_version': '>=11.0.2', 'windows': '451.48', 'linux': '450.51.05'}, + {'cuda_version': '>=11.0.1', 'windows': '451.22', 'linux': '450.36.06'}, + {'cuda_version': '>=10.2.89', 'windows': '441.22', 'linux': '440.33'}, + {'cuda_version': '>=10.1.105', 'windows': '418.96', 'linux': '418.39'}, + {'cuda_version': '>=10.0.130', 'windows': '411.31', 'linux': '410.48'}, + {'cuda_version': '>=9.2.148', 'windows': '398.26', 'linux': '396.37'}, + {'cuda_version': '>=9.2.88', 'windows': '397.44', 'linux': '396.26'}, + {'cuda_version': '>=9.1.85', 'windows': '391.29', 'linux': '390.46'}, + {'cuda_version': '>=9.0.76', 'windows': '385.54', 'linux': '384.81'}, + {'cuda_version': '>=8.0.61', 'windows': '376.51', 'linux': '375.26'}, + {'cuda_version': '>=8.0.44', 'windows': '369.30', 'linux': '367.48'}, + {'cuda_version': '>=7.5.16', 'windows': '353.66', 'linux': '352.31'}, + {'cuda_version': '>=7.0.28', 'windows': '347.62', 'linux': '346.46'}, + ] + + driver_version = 'unknown' + for d in driver_version_table: + if version_compare(cuda_version, d['cuda_version']): + driver_version = d.get(state.host_machine.system, d['linux']) + break + + return driver_version + + @permittedKwargs(['detected']) + def nvcc_arch_flags(self, state: 'ModuleState', + args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], + kwargs: T.Dict[str, T.Any]) -> T.List[str]: + nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) + ret = self._nvcc_arch_flags(*nvcc_arch_args)[0] + return ret + + @permittedKwargs(['detected']) + def nvcc_arch_readable(self, state: 'ModuleState', + args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], + kwargs: T.Dict[str, T.Any]) -> T.List[str]: + nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) + ret = self._nvcc_arch_flags(*nvcc_arch_args)[1] + return ret + + @staticmethod + def _break_arch_string(s): + s = re.sub('[ \t\r\n,;]+', ';', s) + s = s.strip(';').split(';') + return s + + @staticmethod + def _detected_cc_from_compiler(c): + if isinstance(c, CudaCompiler): + return c.detected_cc + return '' + + @staticmethod + def _version_from_compiler(c): + if isinstance(c, CudaCompiler): + return c.version + if isinstance(c, str): + return c + return 'unknown' + + def _validate_nvcc_arch_args(self, args, kwargs): + argerror = InvalidArguments('The first argument must be an NVCC compiler object, or its version string!') + + if len(args) < 1: + raise argerror + else: + compiler = args[0] + cuda_version = self._version_from_compiler(compiler) + if cuda_version == 'unknown': + raise argerror + + arch_list = [] if len(args) <= 1 else flatten(args[1:]) + arch_list = [self._break_arch_string(a) for a in arch_list] + arch_list = flatten(arch_list) + if len(arch_list) > 1 and not set(arch_list).isdisjoint({'All', 'Common', 'Auto'}): + raise InvalidArguments('''The special architectures 'All', 'Common' and 'Auto' must appear alone, as a positional argument!''') + arch_list = arch_list[0] if len(arch_list) == 1 else arch_list + + detected = kwargs.get('detected', self._detected_cc_from_compiler(compiler)) + detected = flatten([detected]) + detected = [self._break_arch_string(a) for a in detected] + detected = flatten(detected) + if not set(detected).isdisjoint({'All', 'Common', 'Auto'}): + raise InvalidArguments('''The special architectures 'All', 'Common' and 'Auto' must appear alone, as a positional argument!''') + + return cuda_version, arch_list, detected + + def _filter_cuda_arch_list(self, cuda_arch_list, lo=None, hi=None, saturate=None): + """ + Filter CUDA arch list (no codenames) for >= low and < hi architecture + bounds, and deduplicate. + If saturate is provided, architectures >= hi are replaced with saturate. + """ + + filtered_cuda_arch_list = [] + for arch in cuda_arch_list: + if arch: + if lo and version_compare(arch, '<' + lo): + continue + if hi and version_compare(arch, '>=' + hi): + if not saturate: + continue + arch = saturate + if arch not in filtered_cuda_arch_list: + filtered_cuda_arch_list.append(arch) + return filtered_cuda_arch_list + + def _nvcc_arch_flags(self, cuda_version, cuda_arch_list='Auto', detected=''): + """ + Using the CUDA Toolkit version and the target architectures, compute + the NVCC architecture flags. + """ + + # Replicates much of the logic of + # https://github.com/Kitware/CMake/blob/master/Modules/FindCUDA/select_compute_arch.cmake + # except that a bug with cuda_arch_list="All" is worked around by + # tracking both lower and upper limits on GPU architectures. + + cuda_known_gpu_architectures = ['Fermi', 'Kepler', 'Maxwell'] # noqa: E221 + cuda_common_gpu_architectures = ['3.0', '3.5', '5.0'] # noqa: E221 + cuda_hi_limit_gpu_architecture = None # noqa: E221 + cuda_lo_limit_gpu_architecture = '2.0' # noqa: E221 + cuda_all_gpu_architectures = ['3.0', '3.2', '3.5', '5.0'] # noqa: E221 + + if version_compare(cuda_version, '<7.0'): + cuda_hi_limit_gpu_architecture = '5.2' + + if version_compare(cuda_version, '>=7.0'): + cuda_known_gpu_architectures += ['Kepler+Tegra', 'Kepler+Tesla', 'Maxwell+Tegra'] # noqa: E221 + cuda_common_gpu_architectures += ['5.2'] # noqa: E221 + + if version_compare(cuda_version, '<8.0'): + cuda_common_gpu_architectures += ['5.2+PTX'] # noqa: E221 + cuda_hi_limit_gpu_architecture = '6.0' # noqa: E221 + + if version_compare(cuda_version, '>=8.0'): + cuda_known_gpu_architectures += ['Pascal', 'Pascal+Tegra'] # noqa: E221 + cuda_common_gpu_architectures += ['6.0', '6.1'] # noqa: E221 + cuda_all_gpu_architectures += ['6.0', '6.1', '6.2'] # noqa: E221 + + if version_compare(cuda_version, '<9.0'): + cuda_common_gpu_architectures += ['6.1+PTX'] # noqa: E221 + cuda_hi_limit_gpu_architecture = '7.0' # noqa: E221 + + if version_compare(cuda_version, '>=9.0'): + cuda_known_gpu_architectures += ['Volta', 'Xavier'] # noqa: E221 + cuda_common_gpu_architectures += ['7.0'] # noqa: E221 + cuda_all_gpu_architectures += ['7.0', '7.2'] # noqa: E221 + # https://docs.nvidia.com/cuda/archive/9.0/cuda-toolkit-release-notes/index.html#unsupported-features + cuda_lo_limit_gpu_architecture = '3.0' # noqa: E221 + + if version_compare(cuda_version, '<10.0'): + cuda_common_gpu_architectures += ['7.2+PTX'] # noqa: E221 + cuda_hi_limit_gpu_architecture = '8.0' # noqa: E221 + + if version_compare(cuda_version, '>=10.0'): + cuda_known_gpu_architectures += ['Turing'] # noqa: E221 + cuda_common_gpu_architectures += ['7.5'] # noqa: E221 + cuda_all_gpu_architectures += ['7.5'] # noqa: E221 + + if version_compare(cuda_version, '<11.0'): + cuda_common_gpu_architectures += ['7.5+PTX'] # noqa: E221 + cuda_hi_limit_gpu_architecture = '8.0' # noqa: E221 + + # need to account for the fact that Ampere is commonly assumed to include + # SM8.0 and SM8.6 even though CUDA 11.0 doesn't support SM8.6 + cuda_ampere_bin = ['8.0'] + cuda_ampere_ptx = ['8.0'] + if version_compare(cuda_version, '>=11.0'): + cuda_known_gpu_architectures += ['Ampere'] # noqa: E221 + cuda_common_gpu_architectures += ['8.0'] # noqa: E221 + cuda_all_gpu_architectures += ['8.0'] # noqa: E221 + # https://docs.nvidia.com/cuda/archive/11.0/cuda-toolkit-release-notes/index.html#deprecated-features + cuda_lo_limit_gpu_architecture = '3.5' # noqa: E221 + + if version_compare(cuda_version, '<11.1'): + cuda_common_gpu_architectures += ['8.0+PTX'] # noqa: E221 + cuda_hi_limit_gpu_architecture = '8.6' # noqa: E221 + + if version_compare(cuda_version, '>=11.1'): + cuda_ampere_bin += ['8.6'] # noqa: E221 + cuda_ampere_ptx = ['8.6'] # noqa: E221 + + cuda_common_gpu_architectures += ['8.6'] # noqa: E221 + cuda_all_gpu_architectures += ['8.6'] # noqa: E221 + + if version_compare(cuda_version, '<11.8'): + cuda_common_gpu_architectures += ['8.6+PTX'] # noqa: E221 + cuda_hi_limit_gpu_architecture = '8.7' # noqa: E221 + + if version_compare(cuda_version, '>=11.8'): + cuda_known_gpu_architectures += ['Orin', 'Lovelace', 'Hopper'] # noqa: E221 + cuda_common_gpu_architectures += ['8.9', '9.0', '9.0+PTX'] # noqa: E221 + cuda_all_gpu_architectures += ['8.7', '8.9', '9.0'] # noqa: E221 + + if version_compare(cuda_version, '<12'): + cuda_hi_limit_gpu_architecture = '9.1' # noqa: E221 + + if version_compare(cuda_version, '>=12.0'): + # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features (Current) + # https://docs.nvidia.com/cuda/archive/12.0/cuda-toolkit-release-notes/index.html#deprecated-features (Eventual?) + cuda_lo_limit_gpu_architecture = '5.0' # noqa: E221 + + if version_compare(cuda_version, '<13'): + cuda_hi_limit_gpu_architecture = '10.0' # noqa: E221 + + if not cuda_arch_list: + cuda_arch_list = 'Auto' + + if cuda_arch_list == 'All': # noqa: E271 + cuda_arch_list = cuda_known_gpu_architectures + elif cuda_arch_list == 'Common': # noqa: E271 + cuda_arch_list = cuda_common_gpu_architectures + elif cuda_arch_list == 'Auto': # noqa: E271 + if detected: + if isinstance(detected, list): + cuda_arch_list = detected + else: + cuda_arch_list = self._break_arch_string(detected) + cuda_arch_list = self._filter_cuda_arch_list(cuda_arch_list, + cuda_lo_limit_gpu_architecture, + cuda_hi_limit_gpu_architecture, + cuda_common_gpu_architectures[-1]) + else: + cuda_arch_list = cuda_common_gpu_architectures + elif isinstance(cuda_arch_list, str): + cuda_arch_list = self._break_arch_string(cuda_arch_list) + + cuda_arch_list = sorted(x for x in set(cuda_arch_list) if x) + + cuda_arch_bin = [] + cuda_arch_ptx = [] + for arch_name in cuda_arch_list: + arch_bin = [] + arch_ptx = [] + add_ptx = arch_name.endswith('+PTX') + if add_ptx: + arch_name = arch_name[:-len('+PTX')] + + if re.fullmatch('[0-9]+\\.[0-9](\\([0-9]+\\.[0-9]\\))?', arch_name): + arch_bin, arch_ptx = [arch_name], [arch_name] + else: + arch_bin, arch_ptx = { + 'Fermi': (['2.0', '2.1(2.0)'], []), + 'Kepler+Tegra': (['3.2'], []), + 'Kepler+Tesla': (['3.7'], []), + 'Kepler': (['3.0', '3.5'], ['3.5']), + 'Maxwell+Tegra': (['5.3'], []), + 'Maxwell': (['5.0', '5.2'], ['5.2']), + 'Pascal': (['6.0', '6.1'], ['6.1']), + 'Pascal+Tegra': (['6.2'], []), + 'Volta': (['7.0'], ['7.0']), + 'Xavier': (['7.2'], []), + 'Turing': (['7.5'], ['7.5']), + 'Ampere': (cuda_ampere_bin, cuda_ampere_ptx), + 'Orin': (['8.7'], []), + 'Lovelace': (['8.9'], ['8.9']), + 'Hopper': (['9.0'], ['9.0']), + }.get(arch_name, (None, None)) + + if arch_bin is None: + raise InvalidArguments(f'Unknown CUDA Architecture Name {arch_name}!') + + cuda_arch_bin += arch_bin + + if add_ptx: + if not arch_ptx: + arch_ptx = arch_bin + cuda_arch_ptx += arch_ptx + + cuda_arch_bin = sorted(set(cuda_arch_bin)) + cuda_arch_ptx = sorted(set(cuda_arch_ptx)) + + nvcc_flags = [] + nvcc_archs_readable = [] + + for arch in cuda_arch_bin: + arch, codev = re.fullmatch( + '([0-9]+\\.[0-9])(?:\\(([0-9]+\\.[0-9])\\))?', arch).groups() + + if version_compare(arch, '<' + cuda_lo_limit_gpu_architecture): + continue + if cuda_hi_limit_gpu_architecture and version_compare(arch, '>=' + cuda_hi_limit_gpu_architecture): + continue + + if codev: + arch = arch.replace('.', '') + codev = codev.replace('.', '') + nvcc_flags += ['-gencode', 'arch=compute_' + codev + ',code=sm_' + arch] + nvcc_archs_readable += ['sm_' + arch] + else: + arch = arch.replace('.', '') + nvcc_flags += ['-gencode', 'arch=compute_' + arch + ',code=sm_' + arch] + nvcc_archs_readable += ['sm_' + arch] + + for arch in cuda_arch_ptx: + arch, codev = re.fullmatch( + '([0-9]+\\.[0-9])(?:\\(([0-9]+\\.[0-9])\\))?', arch).groups() + + if codev: + arch = codev + + if version_compare(arch, '<' + cuda_lo_limit_gpu_architecture): + continue + if cuda_hi_limit_gpu_architecture and version_compare(arch, '>=' + cuda_hi_limit_gpu_architecture): + continue + + arch = arch.replace('.', '') + nvcc_flags += ['-gencode', 'arch=compute_' + arch + ',code=compute_' + arch] + nvcc_archs_readable += ['compute_' + arch] + + return nvcc_flags, nvcc_archs_readable + +def initialize(*args, **kwargs): + return CudaModule(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/dlang.py b/devtools/meson/mesonbuild/modules/dlang.py new file mode 100644 index 0000000..6d5359f --- /dev/null +++ b/devtools/meson/mesonbuild/modules/dlang.py @@ -0,0 +1,137 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file contains the detection logic for external dependencies that +# are UI-related. +from __future__ import annotations + +import json +import os + +from . import ExtensionModule, ModuleInfo +from .. import mlog +from ..dependencies import Dependency +from ..dependencies.dub import DubDependency +from ..interpreterbase import typed_pos_args +from ..mesonlib import Popen_safe, MesonException + +class DlangModule(ExtensionModule): + class_dubbin = None + init_dub = False + + INFO = ModuleInfo('dlang', '0.48.0') + + def __init__(self, interpreter): + super().__init__(interpreter) + self.methods.update({ + 'generate_dub_file': self.generate_dub_file, + }) + + def _init_dub(self, state): + if DlangModule.class_dubbin is None: + self.dubbin = DubDependency.class_dubbin + DlangModule.class_dubbin = self.dubbin + else: + self.dubbin = DlangModule.class_dubbin + + if DlangModule.class_dubbin is None: + self.dubbin = self.check_dub(state) + DlangModule.class_dubbin = self.dubbin + else: + self.dubbin = DlangModule.class_dubbin + + if not self.dubbin: + if not self.dubbin: + raise MesonException('DUB not found.') + + @typed_pos_args('dlang.generate_dub_file', str, str) + def generate_dub_file(self, state, args, kwargs): + if not DlangModule.init_dub: + self._init_dub(state) + + config = { + 'name': args[0] + } + + config_path = os.path.join(args[1], 'dub.json') + if os.path.exists(config_path): + with open(config_path, encoding='utf-8') as ofile: + try: + config = json.load(ofile) + except ValueError: + mlog.warning('Failed to load the data in dub.json') + + warn_publishing = ['description', 'license'] + for arg in warn_publishing: + if arg not in kwargs and \ + arg not in config: + mlog.warning('Without', mlog.bold(arg), 'the DUB package can\'t be published') + + for key, value in kwargs.items(): + if key == 'dependencies': + config[key] = {} + if isinstance(value, list): + for dep in value: + if isinstance(dep, Dependency): + name = dep.get_name() + ret, res = self._call_dubbin(['describe', name]) + if ret == 0: + version = dep.get_version() + if version is None: + config[key][name] = '' + else: + config[key][name] = version + elif isinstance(value, Dependency): + name = value.get_name() + ret, res = self._call_dubbin(['describe', name]) + if ret == 0: + version = value.get_version() + if version is None: + config[key][name] = '' + else: + config[key][name] = version + else: + config[key] = value + + with open(config_path, 'w', encoding='utf-8') as ofile: + ofile.write(json.dumps(config, indent=4, ensure_ascii=False)) + + def _call_dubbin(self, args, env=None): + p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2] + return p.returncode, out.strip() + + def check_dub(self, state): + dubbin = state.find_program('dub', silent=True) + if dubbin.found(): + try: + p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2] + if p.returncode != 0: + mlog.warning('Found dub {!r} but couldn\'t run it' + ''.format(' '.join(dubbin.get_command()))) + # Set to False instead of None to signify that we've already + # searched for it and not found it + dubbin = False + except (FileNotFoundError, PermissionError): + dubbin = False + else: + dubbin = False + if dubbin: + mlog.log('Found DUB:', mlog.bold(dubbin.get_path()), + '(%s)' % out.strip()) + else: + mlog.log('Found DUB:', mlog.red('NO')) + return dubbin + +def initialize(*args, **kwargs): + return DlangModule(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/external_project.py b/devtools/meson/mesonbuild/modules/external_project.py new file mode 100644 index 0000000..a1d8514 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/external_project.py @@ -0,0 +1,313 @@ +# Copyright 2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from pathlib import Path +import os +import shlex +import subprocess +import typing as T + +from . import ExtensionModule, ModuleReturnValue, NewExtensionModule, ModuleInfo +from .. import mlog, build +from ..compilers.compilers import CFLAGS_MAPPING +from ..envconfig import ENV_VAR_PROG_MAP +from ..dependencies import InternalDependency +from ..dependencies.pkgconfig import PkgConfigDependency +from ..interpreterbase import FeatureNew +from ..interpreter.type_checking import ENV_KW, DEPENDS_KW +from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args +from ..mesonlib import (EnvironmentException, MesonException, Popen_safe, MachineChoice, + get_variable_regex, do_replacement, join_args, OptionKey) + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from .._typing import ImmutableListProtocol + from ..build import BuildTarget, CustomTarget + from ..interpreter import Interpreter + from ..interpreterbase import TYPE_var + + class Dependency(TypedDict): + + subdir: str + + class AddProject(TypedDict): + + configure_options: T.List[str] + cross_configure_options: T.List[str] + verbose: bool + env: build.EnvironmentVariables + depends: T.List[T.Union[BuildTarget, CustomTarget]] + + +class ExternalProject(NewExtensionModule): + + make: ImmutableListProtocol[str] + + def __init__(self, + state: 'ModuleState', + configure_command: str, + configure_options: T.List[str], + cross_configure_options: T.List[str], + env: build.EnvironmentVariables, + verbose: bool, + extra_depends: T.List[T.Union['BuildTarget', 'CustomTarget']]): + super().__init__() + self.methods.update({'dependency': self.dependency_method, + }) + + self.subdir = Path(state.subdir) + self.project_version = state.project_version + self.subproject = state.subproject + self.env = state.environment + self.build_machine = state.build_machine + self.host_machine = state.host_machine + self.configure_command = configure_command + self.configure_options = configure_options + self.cross_configure_options = cross_configure_options + self.verbose = verbose + self.user_env = env + + self.src_dir = Path(self.env.get_source_dir(), self.subdir) + self.build_dir = Path(self.env.get_build_dir(), self.subdir, 'build') + self.install_dir = Path(self.env.get_build_dir(), self.subdir, 'dist') + _p = self.env.coredata.get_option(OptionKey('prefix')) + assert isinstance(_p, str), 'for mypy' + self.prefix = Path(_p) + _l = self.env.coredata.get_option(OptionKey('libdir')) + assert isinstance(_l, str), 'for mypy' + self.libdir = Path(_l) + _i = self.env.coredata.get_option(OptionKey('includedir')) + assert isinstance(_i, str), 'for mypy' + self.includedir = Path(_i) + self.name = self.src_dir.name + + # On Windows if the prefix is "c:/foo" and DESTDIR is "c:/bar", `make` + # will install files into "c:/bar/c:/foo" which is an invalid path. + # Work around that issue by removing the drive from prefix. + if self.prefix.drive: + self.prefix = self.prefix.relative_to(self.prefix.drive) + + # self.prefix is an absolute path, so we cannot append it to another path. + self.rel_prefix = self.prefix.relative_to(self.prefix.root) + + self._configure(state) + + self.targets = self._create_targets(extra_depends) + + def _configure(self, state: 'ModuleState') -> None: + if self.configure_command == 'waf': + FeatureNew('Waf external project', '0.60.0').use(self.subproject, state.current_node) + waf = state.find_program('waf') + configure_cmd = waf.get_command() + configure_cmd += ['configure', '-o', str(self.build_dir)] + workdir = self.src_dir + self.make = waf.get_command() + ['build'] + else: + # Assume it's the name of a script in source dir, like 'configure', + # 'autogen.sh', etc). + configure_path = Path(self.src_dir, self.configure_command) + configure_prog = state.find_program(configure_path.as_posix()) + configure_cmd = configure_prog.get_command() + workdir = self.build_dir + self.make = state.find_program('make').get_command() + + d = [('PREFIX', '--prefix=@PREFIX@', self.prefix.as_posix()), + ('LIBDIR', '--libdir=@PREFIX@/@LIBDIR@', self.libdir.as_posix()), + ('INCLUDEDIR', None, self.includedir.as_posix()), + ] + self._validate_configure_options(d, state) + + configure_cmd += self._format_options(self.configure_options, d) + + if self.env.is_cross_build(): + host = '{}-{}-{}'.format(self.host_machine.cpu_family, + self.build_machine.system, + self.host_machine.system) + d = [('HOST', None, host)] + configure_cmd += self._format_options(self.cross_configure_options, d) + + # Set common env variables like CFLAGS, CC, etc. + link_exelist: T.List[str] = [] + link_args: T.List[str] = [] + self.run_env = os.environ.copy() + for lang, compiler in self.env.coredata.compilers[MachineChoice.HOST].items(): + if any(lang not in i for i in (ENV_VAR_PROG_MAP, CFLAGS_MAPPING)): + continue + cargs = self.env.coredata.get_external_args(MachineChoice.HOST, lang) + assert isinstance(cargs, list), 'for mypy' + self.run_env[ENV_VAR_PROG_MAP[lang]] = self._quote_and_join(compiler.get_exelist()) + self.run_env[CFLAGS_MAPPING[lang]] = self._quote_and_join(cargs) + if not link_exelist: + link_exelist = compiler.get_linker_exelist() + _l = self.env.coredata.get_external_link_args(MachineChoice.HOST, lang) + assert isinstance(_l, list), 'for mypy' + link_args = _l + if link_exelist: + # FIXME: Do not pass linker because Meson uses CC as linker wrapper, + # but autotools often expects the real linker (e.h. GNU ld). + # self.run_env['LD'] = self._quote_and_join(link_exelist) + pass + self.run_env['LDFLAGS'] = self._quote_and_join(link_args) + + self.run_env = self.user_env.get_env(self.run_env) + self.run_env = PkgConfigDependency.setup_env(self.run_env, self.env, MachineChoice.HOST, + uninstalled=True) + + self.build_dir.mkdir(parents=True, exist_ok=True) + self._run('configure', configure_cmd, workdir) + + def _quote_and_join(self, array: T.List[str]) -> str: + return ' '.join([shlex.quote(i) for i in array]) + + def _validate_configure_options(self, variables: T.List[T.Tuple[str, str, str]], state: 'ModuleState') -> None: + # Ensure the user at least try to pass basic info to the build system, + # like the prefix, libdir, etc. + for key, default, val in variables: + if default is None: + continue + key_format = f'@{key}@' + for option in self.configure_options: + if key_format in option: + break + else: + FeatureNew('Default configure_option', '0.57.0').use(self.subproject, state.current_node) + self.configure_options.append(default) + + def _format_options(self, options: T.List[str], variables: T.List[T.Tuple[str, str, str]]) -> T.List[str]: + out: T.List[str] = [] + missing = set() + regex = get_variable_regex('meson') + confdata: T.Dict[str, T.Tuple[str, T.Optional[str]]] = {k: (v, None) for k, _, v in variables} + for o in options: + arg, missing_vars = do_replacement(regex, o, 'meson', confdata) + missing.update(missing_vars) + out.append(arg) + if missing: + var_list = ", ".join(repr(m) for m in sorted(missing)) + raise EnvironmentException( + f"Variables {var_list} in configure options are missing.") + return out + + def _run(self, step: str, command: T.List[str], workdir: Path) -> None: + mlog.log(f'External project {self.name}:', mlog.bold(step)) + m = 'Running command ' + str(command) + ' in directory ' + str(workdir) + '\n' + log_filename = Path(mlog.get_log_dir(), f'{self.name}-{step}.log') + output = None + if not self.verbose: + output = open(log_filename, 'w', encoding='utf-8') + output.write(m + '\n') + output.flush() + else: + mlog.log(m) + p, *_ = Popen_safe(command, cwd=workdir, env=self.run_env, + stderr=subprocess.STDOUT, + stdout=output) + if p.returncode != 0: + m = f'{step} step returned error code {p.returncode}.' + if not self.verbose: + m += '\nSee logs: ' + str(log_filename) + raise MesonException(m) + + def _create_targets(self, extra_depends: T.List[T.Union['BuildTarget', 'CustomTarget']]) -> T.List['TYPE_var']: + cmd = self.env.get_build_command() + cmd += ['--internal', 'externalproject', + '--name', self.name, + '--srcdir', self.src_dir.as_posix(), + '--builddir', self.build_dir.as_posix(), + '--installdir', self.install_dir.as_posix(), + '--logdir', mlog.get_log_dir(), + '--make', join_args(self.make), + ] + if self.verbose: + cmd.append('--verbose') + + self.target = build.CustomTarget( + self.name, + self.subdir.as_posix(), + self.subproject, + self.env, + cmd + ['@OUTPUT@', '@DEPFILE@'], + [], + [f'{self.name}.stamp'], + depfile=f'{self.name}.d', + console=True, + extra_depends=extra_depends, + ) + + idir = build.InstallDir(self.subdir.as_posix(), + Path('dist', self.rel_prefix).as_posix(), + install_dir='.', + install_dir_name='.', + install_mode=None, + exclude=None, + strip_directory=True, + from_source_dir=False, + subproject=self.subproject) + + return [self.target, idir] + + @typed_pos_args('external_project.dependency', str) + @typed_kwargs('external_project.dependency', KwargInfo('subdir', str, default='')) + def dependency_method(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Dependency') -> InternalDependency: + libname = args[0] + + abs_includedir = Path(self.install_dir, self.rel_prefix, self.includedir) + if kwargs['subdir']: + abs_includedir = Path(abs_includedir, kwargs['subdir']) + abs_libdir = Path(self.install_dir, self.rel_prefix, self.libdir) + + version = self.project_version + compile_args = [f'-I{abs_includedir}'] + link_args = [f'-L{abs_libdir}', f'-l{libname}'] + sources = self.target + dep = InternalDependency(version, [], compile_args, link_args, [], + [], [sources], [], [], {}, [], [], []) + return dep + + +class ExternalProjectModule(ExtensionModule): + + INFO = ModuleInfo('External build system', '0.56.0', unstable=True) + + def __init__(self, interpreter: 'Interpreter'): + super().__init__(interpreter) + self.methods.update({'add_project': self.add_project, + }) + + @typed_pos_args('external_project_mod.add_project', str) + @typed_kwargs( + 'external_project.add_project', + KwargInfo('configure_options', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('cross_configure_options', ContainerTypeInfo(list, str), default=['--host=@HOST@'], listify=True), + KwargInfo('verbose', bool, default=False), + ENV_KW, + DEPENDS_KW.evolve(since='0.63.0'), + ) + def add_project(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'AddProject') -> ModuleReturnValue: + configure_command = args[0] + project = ExternalProject(state, + configure_command, + kwargs['configure_options'], + kwargs['cross_configure_options'], + kwargs['env'], + kwargs['verbose'], + kwargs['depends']) + return ModuleReturnValue(project, project.targets) + + +def initialize(interp: 'Interpreter') -> ExternalProjectModule: + return ExternalProjectModule(interp) diff --git a/devtools/meson/mesonbuild/modules/fs.py b/devtools/meson/mesonbuild/modules/fs.py new file mode 100644 index 0000000..53174d2 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/fs.py @@ -0,0 +1,317 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +from pathlib import Path, PurePath, PureWindowsPath +import hashlib +import os +import typing as T + +from . import ExtensionModule, ModuleReturnValue, ModuleInfo +from .. import mlog +from ..build import CustomTarget, InvalidArguments +from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType +from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs +from ..mesonlib import ( + File, + MesonException, + has_path_sep, + path_is_in_root, +) + +if T.TYPE_CHECKING: + from . import ModuleState + from ..interpreter import Interpreter + from ..mesonlib import FileOrString, FileMode + + from typing_extensions import TypedDict + + class ReadKwArgs(TypedDict): + """Keyword Arguments for fs.read.""" + + encoding: str + + class CopyKw(TypedDict): + + """Kwargs for fs.copy""" + + install: bool + install_dir: T.Optional[str] + install_mode: FileMode + install_tag: T.Optional[str] + + +class FSModule(ExtensionModule): + + INFO = ModuleInfo('fs', '0.53.0') + + def __init__(self, interpreter: 'Interpreter') -> None: + super().__init__(interpreter) + self.methods.update({ + 'expanduser': self.expanduser, + 'is_absolute': self.is_absolute, + 'as_posix': self.as_posix, + 'exists': self.exists, + 'is_symlink': self.is_symlink, + 'is_file': self.is_file, + 'is_dir': self.is_dir, + 'hash': self.hash, + 'size': self.size, + 'is_samepath': self.is_samepath, + 'replace_suffix': self.replace_suffix, + 'parent': self.parent, + 'name': self.name, + 'stem': self.stem, + 'read': self.read, + 'copyfile': self.copyfile, + }) + + def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: + """ + make an absolute path from a relative path, WITHOUT resolving symlinks + """ + if isinstance(arg, File): + return Path(arg.absolute_path(state.source_root, self.interpreter.environment.get_build_dir())) + return Path(state.source_root) / Path(state.subdir) / Path(arg).expanduser() + + def _resolve_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: + """ + resolves symlinks and makes absolute a directory relative to calling meson.build, + if not already absolute + """ + path = self._absolute_dir(state, arg) + try: + # accommodate unresolvable paths e.g. symlink loops + path = path.resolve() + except Exception: + # return the best we could do + pass + return path + + @noKwargs + @FeatureNew('fs.expanduser', '0.54.0') + @typed_pos_args('fs.expanduser', str) + def expanduser(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: + return str(Path(args[0]).expanduser()) + + @noKwargs + @FeatureNew('fs.is_absolute', '0.54.0') + @typed_pos_args('fs.is_absolute', (str, File)) + def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: + if isinstance(args[0], File): + FeatureNew('fs.is_absolute_file', '0.59.0').use(state.subproject) + return PurePath(str(args[0])).is_absolute() + + @noKwargs + @FeatureNew('fs.as_posix', '0.54.0') + @typed_pos_args('fs.as_posix', str) + def as_posix(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: + """ + this function assumes you are passing a Windows path, even if on a Unix-like system + and so ALL '\' are turned to '/', even if you meant to escape a character + """ + return PureWindowsPath(args[0]).as_posix() + + @noKwargs + @typed_pos_args('fs.exists', str) + def exists(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: + return self._resolve_dir(state, args[0]).exists() + + @noKwargs + @typed_pos_args('fs.is_symlink', (str, File)) + def is_symlink(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: + if isinstance(args[0], File): + FeatureNew('fs.is_symlink_file', '0.59.0').use(state.subproject) + return self._absolute_dir(state, args[0]).is_symlink() + + @noKwargs + @typed_pos_args('fs.is_file', str) + def is_file(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: + return self._resolve_dir(state, args[0]).is_file() + + @noKwargs + @typed_pos_args('fs.is_dir', str) + def is_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: + return self._resolve_dir(state, args[0]).is_dir() + + @noKwargs + @typed_pos_args('fs.hash', (str, File), str) + def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: + if isinstance(args[0], File): + FeatureNew('fs.hash_file', '0.59.0').use(state.subproject) + file = self._resolve_dir(state, args[0]) + if not file.is_file(): + raise MesonException(f'{file} is not a file and therefore cannot be hashed') + try: + h = hashlib.new(args[1]) + except ValueError: + raise MesonException('hash algorithm {} is not available'.format(args[1])) + mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, file.stat().st_size)) + h.update(file.read_bytes()) + return h.hexdigest() + + @noKwargs + @typed_pos_args('fs.size', (str, File)) + def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> int: + if isinstance(args[0], File): + FeatureNew('fs.size_file', '0.59.0').use(state.subproject) + file = self._resolve_dir(state, args[0]) + if not file.is_file(): + raise MesonException(f'{file} is not a file and therefore cannot be sized') + try: + return file.stat().st_size + except ValueError: + raise MesonException('{} size could not be determined'.format(args[0])) + + @noKwargs + @typed_pos_args('fs.is_samepath', (str, File), (str, File)) + def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: + if isinstance(args[0], File) or isinstance(args[1], File): + FeatureNew('fs.is_samepath_file', '0.59.0').use(state.subproject) + file1 = self._resolve_dir(state, args[0]) + file2 = self._resolve_dir(state, args[1]) + if not file1.exists(): + return False + if not file2.exists(): + return False + try: + return file1.samefile(file2) + except OSError: + return False + + @noKwargs + @typed_pos_args('fs.replace_suffix', (str, File), str) + def replace_suffix(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: + if isinstance(args[0], File): + FeatureNew('fs.replace_suffix_file', '0.59.0').use(state.subproject) + original = PurePath(str(args[0])) + new = original.with_suffix(args[1]) + return str(new) + + @noKwargs + @typed_pos_args('fs.parent', (str, File)) + def parent(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: + if isinstance(args[0], File): + FeatureNew('fs.parent_file', '0.59.0').use(state.subproject) + original = PurePath(str(args[0])) + new = original.parent + return str(new) + + @noKwargs + @typed_pos_args('fs.name', (str, File)) + def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: + if isinstance(args[0], File): + FeatureNew('fs.name_file', '0.59.0').use(state.subproject) + original = PurePath(str(args[0])) + new = original.name + return str(new) + + @noKwargs + @typed_pos_args('fs.stem', (str, File)) + @FeatureNew('fs.stem', '0.54.0') + def stem(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: + if isinstance(args[0], File): + FeatureNew('fs.stem_file', '0.59.0').use(state.subproject) + original = PurePath(str(args[0])) + new = original.stem + return str(new) + + @FeatureNew('fs.read', '0.57.0') + @typed_pos_args('fs.read', (str, File)) + @typed_kwargs('fs.read', KwargInfo('encoding', str, default='utf-8')) + def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'ReadKwArgs') -> str: + """Read a file from the source tree and return its value as a decoded + string. + + If the encoding is not specified, the file is assumed to be utf-8 + encoded. Paths must be relative by default (to prevent accidents) and + are forbidden to be read from the build directory (to prevent build + loops) + """ + path = args[0] + encoding = kwargs['encoding'] + src_dir = self.interpreter.environment.source_dir + sub_dir = self.interpreter.subdir + build_dir = self.interpreter.environment.get_build_dir() + + if isinstance(path, File): + if path.is_built: + raise MesonException( + 'fs.read_file does not accept built files() objects') + path = os.path.join(src_dir, path.relative_name()) + else: + if sub_dir: + src_dir = os.path.join(src_dir, sub_dir) + path = os.path.join(src_dir, path) + + path = os.path.abspath(path) + if path_is_in_root(Path(path), Path(build_dir), resolve=True): + raise MesonException('path must not be in the build tree') + try: + with open(path, encoding=encoding) as f: + data = f.read() + except FileNotFoundError: + raise MesonException(f'File {args[0]} does not exist.') + except UnicodeDecodeError: + raise MesonException(f'decoding failed for {args[0]}') + # Reconfigure when this file changes as it can contain data used by any + # part of the build configuration (e.g. `project(..., version: + # fs.read_file('VERSION')` or `configure_file(...)` + self.interpreter.add_build_def_file(path) + return data + + @FeatureNew('fs.copyfile', '0.64.0') + @typed_pos_args('fs.copyfile', (File, str), optargs=[str]) + @typed_kwargs( + 'fs.copyfile', + INSTALL_KW, + INSTALL_MODE_KW, + INSTALL_TAG_KW, + KwargInfo('install_dir', (str, NoneType)), + ) + def copyfile(self, state: ModuleState, args: T.Tuple[FileOrString, T.Optional[str]], + kwargs: CopyKw) -> ModuleReturnValue: + """Copy a file into the build directory at build time.""" + if kwargs['install'] and not kwargs['install_dir']: + raise InvalidArguments('"install_dir" must be specified when "install" is true') + + src = self.interpreter.source_strings_to_files([args[0]])[0] + + # The input is allowed to have path separators, but the output may not, + # so use the basename for the default case + dest = args[1] if args[1] else os.path.basename(src.fname) + if has_path_sep(dest): + raise InvalidArguments('Destination path may not have path separators') + + ct = CustomTarget( + dest, + state.subdir, + state.subproject, + state.environment, + state.environment.get_build_command() + ['--internal', 'copy', '@INPUT@', '@OUTPUT@'], + [src], + [dest], + build_by_default=True, + install=kwargs['install'], + install_dir=[kwargs['install_dir']], + install_mode=kwargs['install_mode'], + install_tag=[kwargs['install_tag']], + backend=state.backend, + ) + + return ModuleReturnValue(ct, [ct]) + + +def initialize(*args: T.Any, **kwargs: T.Any) -> FSModule: + return FSModule(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/gnome.py b/devtools/meson/mesonbuild/modules/gnome.py new file mode 100644 index 0000000..2ce039f --- /dev/null +++ b/devtools/meson/mesonbuild/modules/gnome.py @@ -0,0 +1,2187 @@ +# Copyright 2015-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +'''This module provides helper functions for Gnome/GLib related +functionality such as gobject-introspection, gresources and gtk-doc''' +from __future__ import annotations + +import copy +import itertools +import functools +import os +import subprocess +import textwrap +import typing as T + +from . import ( + ExtensionModule, GirTarget, GResourceHeaderTarget, GResourceTarget, ModuleInfo, + ModuleReturnValue, TypelibTarget, VapiTarget, +) +from .. import build +from .. import interpreter +from .. import mesonlib +from .. import mlog +from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments +from ..dependencies import Dependency, InternalDependency +from ..dependencies.pkgconfig import PkgConfigDependency +from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, SOURCES_KW, in_set_validator +from ..interpreterbase import noPosargs, noKwargs, FeatureNew, FeatureDeprecated +from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo +from ..interpreterbase.decorators import typed_pos_args +from ..mesonlib import ( + MachineChoice, MesonException, OrderedSet, Popen_safe, join_args, quote_arg +) +from ..programs import OverrideProgram +from ..scripts.gettext import read_linguas + +if T.TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + + from . import ModuleState + from ..build import BuildTarget + from ..compilers import Compiler + from ..interpreter import Interpreter + from ..interpreterbase import TYPE_var, TYPE_kwargs + from ..mesonlib import FileOrString + from ..programs import ExternalProgram + + class PostInstall(TypedDict): + glib_compile_schemas: bool + gio_querymodules: T.List[str] + gtk_update_icon_cache: bool + update_desktop_database: bool + update_mime_database: bool + + class CompileSchemas(TypedDict): + + build_by_default: bool + depend_files: T.List[FileOrString] + + class Yelp(TypedDict): + + languages: T.List[str] + media: T.List[str] + sources: T.List[str] + symlink_media: bool + + class CompileResources(TypedDict): + + build_by_default: bool + c_name: T.Optional[str] + dependencies: T.List[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]] + export: bool + extra_args: T.List[str] + gresource_bundle: bool + install: bool + install_dir: T.Optional[str] + install_header: bool + source_dir: T.List[str] + + class GenerateGir(TypedDict): + + build_by_default: bool + dependencies: T.List[Dependency] + export_packages: T.List[str] + extra_args: T.List[str] + fatal_warnings: bool + header: T.List[str] + identifier_prefix: T.List[str] + include_directories: T.List[T.Union[build.IncludeDirs, str]] + includes: T.List[T.Union[str, GirTarget]] + install: bool + install_dir_gir: T.Optional[str] + install_dir_typelib: T.Optional[str] + link_with: T.List[T.Union[build.SharedLibrary, build.StaticLibrary]] + namespace: str + nsversion: str + sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] + symbol_prefix: T.List[str] + + class GtkDoc(TypedDict): + + src_dir: T.List[T.Union[str, build.IncludeDirs]] + main_sgml: str + main_xml: str + module_version: str + namespace: str + mode: Literal['xml', 'smgl', 'auto', 'none'] + html_args: T.List[str] + scan_args: T.List[str] + scanobjs_args: T.List[str] + fixxref_args: T.List[str] + mkdb_args: T.List[str] + content_files: T.List[T.Union[build.GeneratedTypes, FileOrString]] + ignore_headers: T.List[str] + install_dir: T.List[str] + check: bool + install: bool + gobject_typesfile: T.List[FileOrString] + html_assets: T.List[FileOrString] + expand_content_files: T.List[FileOrString] + c_args: T.List[str] + include_directories: T.List[T.Union[str, build.IncludeDirs]] + dependencies: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]] + + class GdbusCodegen(TypedDict): + + sources: T.List[FileOrString] + extra_args: T.List[str] + interface_prefix: T.Optional[str] + namespace: T.Optional[str] + object_manager: bool + build_by_default: bool + annotations: T.List[T.List[str]] + install_header: bool + install_dir: T.Optional[str] + docbook: T.Optional[str] + autocleanup: Literal['all', 'none', 'objects', 'default'] + + class GenMarshal(TypedDict): + + build_always: T.Optional[str] + build_always_stale: T.Optional[bool] + build_by_default: T.Optional[bool] + depend_files: T.List[mesonlib.File] + extra_args: T.List[str] + install_dir: T.Optional[str] + install_header: bool + internal: bool + nostdinc: bool + prefix: T.Optional[str] + skip_source: bool + sources: T.List[FileOrString] + stdinc: bool + valist_marshallers: bool + + class GenerateVapi(TypedDict): + + sources: T.List[T.Union[str, GirTarget]] + install_dir: T.Optional[str] + install: bool + vapi_dirs: T.List[str] + metadata_dirs: T.List[str] + gir_dirs: T.List[str] + packages: T.List[T.Union[str, InternalDependency]] + + class _MkEnumsCommon(TypedDict): + + sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] + install_header: bool + install_dir: T.Optional[str] + identifier_prefix: T.Optional[str] + symbol_prefix: T.Optional[str] + + class MkEnumsSimple(_MkEnumsCommon): + + header_prefix: str + decorator: str + function_prefix: str + body_prefix: str + + class MkEnums(_MkEnumsCommon): + + c_template: T.Optional[FileOrString] + h_template: T.Optional[FileOrString] + comments: T.Optional[str] + eprod: T.Optional[str] + fhead: T.Optional[str] + fprod: T.Optional[str] + ftail: T.Optional[str] + vhead: T.Optional[str] + vprod: T.Optional[str] + vtail: T.Optional[str] + depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]] + + ToolType = T.Union[Executable, ExternalProgram, OverrideProgram] + + +# Differs from the CustomTarget version in that it straight defaults to True +_BUILD_BY_DEFAULT: KwargInfo[bool] = KwargInfo( + 'build_by_default', bool, default=True, +) + +_EXTRA_ARGS_KW: KwargInfo[T.List[str]] = KwargInfo( + 'extra_args', + ContainerTypeInfo(list, str), + default=[], + listify=True, +) + +_MK_ENUMS_COMMON_KWS: T.List[KwargInfo] = [ + INSTALL_KW.evolve(name='install_header'), + INSTALL_DIR_KW, + KwargInfo( + 'sources', + ContainerTypeInfo(list, (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), + listify=True, + required=True, + ), + KwargInfo('identifier_prefix', (str, NoneType)), + KwargInfo('symbol_prefix', (str, NoneType)), +] + +def annotations_validator(annotations: T.List[T.Union[str, T.List[str]]]) -> T.Optional[str]: + """Validate gdbus-codegen annotations argument""" + + badlist = 'must be made up of 3 strings for ELEMENT, KEY, and VALUE' + + if not annotations: + return None + elif all(isinstance(annot, str) for annot in annotations): + if len(annotations) == 3: + return None + else: + return badlist + elif not all(isinstance(annot, list) for annot in annotations): + for c, annot in enumerate(annotations): + if not isinstance(annot, list): + return f'element {c+1} must be a list' + else: + for c, annot in enumerate(annotations): + if len(annot) != 3 or not all(isinstance(i, str) for i in annot): + return f'element {c+1} {badlist}' + return None + +# gresource compilation is broken due to the way +# the resource compiler and Ninja clash about it +# +# https://github.com/ninja-build/ninja/issues/1184 +# https://bugzilla.gnome.org/show_bug.cgi?id=774368 +gresource_dep_needed_version = '>= 2.51.1' + +class GnomeModule(ExtensionModule): + + INFO = ModuleInfo('gnome') + + def __init__(self, interpreter: 'Interpreter') -> None: + super().__init__(interpreter) + self.gir_dep: T.Optional[Dependency] = None + self.giscanner: T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]] = None + self.gicompiler: T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]] = None + self.install_glib_compile_schemas = False + self.install_gio_querymodules: T.List[str] = [] + self.install_gtk_update_icon_cache = False + self.install_update_desktop_database = False + self.install_update_mime_database = False + self.devenv: T.Optional[build.EnvironmentVariables] = None + self.native_glib_version: T.Optional[str] = None + self.methods.update({ + 'post_install': self.post_install, + 'compile_resources': self.compile_resources, + 'generate_gir': self.generate_gir, + 'compile_schemas': self.compile_schemas, + 'yelp': self.yelp, + 'gtkdoc': self.gtkdoc, + 'gtkdoc_html_dir': self.gtkdoc_html_dir, + 'gdbus_codegen': self.gdbus_codegen, + 'mkenums': self.mkenums, + 'mkenums_simple': self.mkenums_simple, + 'genmarshal': self.genmarshal, + 'generate_vapi': self.generate_vapi, + }) + + def _get_native_glib_version(self, state: 'ModuleState') -> str: + if self.native_glib_version is None: + glib_dep = PkgConfigDependency('glib-2.0', state.environment, + {'native': True, 'required': False}) + if glib_dep.found(): + self.native_glib_version = glib_dep.get_version() + else: + mlog.warning('Could not detect glib version, assuming 2.54. ' + 'You may get build errors if your glib is older.') + self.native_glib_version = '2.54' + return self.native_glib_version + + @mesonlib.run_once + def __print_gresources_warning(self, state: 'ModuleState') -> None: + if not mesonlib.version_compare(self._get_native_glib_version(state), + gresource_dep_needed_version): + mlog.warning('GLib compiled dependencies do not work reliably with \n' + 'the current version of GLib. See the following upstream issue:', + mlog.bold('https://bugzilla.gnome.org/show_bug.cgi?id=774368'), + once=True, fatal=False) + + @staticmethod + def _print_gdbus_warning() -> None: + mlog.warning('Code generated with gdbus_codegen() requires the root directory be added to\n' + ' include_directories of targets with GLib < 2.51.3:', + mlog.bold('https://github.com/mesonbuild/meson/issues/1387'), + once=True, fatal=False) + + @staticmethod + def _find_tool(state: 'ModuleState', tool: str) -> 'ToolType': + tool_map = { + 'gio-querymodules': 'gio-2.0', + 'glib-compile-schemas': 'gio-2.0', + 'glib-compile-resources': 'gio-2.0', + 'gdbus-codegen': 'gio-2.0', + 'glib-genmarshal': 'glib-2.0', + 'glib-mkenums': 'glib-2.0', + 'g-ir-scanner': 'gobject-introspection-1.0', + 'g-ir-compiler': 'gobject-introspection-1.0', + } + depname = tool_map[tool] + varname = tool.replace('-', '_') + return state.find_tool(tool, depname, varname) + + @typed_kwargs( + 'gnome.post_install', + KwargInfo('glib_compile_schemas', bool, default=False), + KwargInfo('gio_querymodules', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('gtk_update_icon_cache', bool, default=False), + KwargInfo('update_desktop_database', bool, default=False, since='0.59.0'), + KwargInfo('update_mime_database', bool, default=False, since='0.64.0'), + ) + @noPosargs + @FeatureNew('gnome.post_install', '0.57.0') + def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'PostInstall') -> ModuleReturnValue: + rv: T.List['build.ExecutableSerialisation'] = [] + datadir_abs = os.path.join(state.environment.get_prefix(), state.environment.get_datadir()) + if kwargs['glib_compile_schemas'] and not self.install_glib_compile_schemas: + self.install_glib_compile_schemas = True + prog = self._find_tool(state, 'glib-compile-schemas') + schemasdir = os.path.join(datadir_abs, 'glib-2.0', 'schemas') + script = state.backend.get_executable_serialisation([prog, schemasdir]) + script.skip_if_destdir = True + rv.append(script) + for d in kwargs['gio_querymodules']: + if d not in self.install_gio_querymodules: + self.install_gio_querymodules.append(d) + prog = self._find_tool(state, 'gio-querymodules') + moduledir = os.path.join(state.environment.get_prefix(), d) + script = state.backend.get_executable_serialisation([prog, moduledir]) + script.skip_if_destdir = True + rv.append(script) + if kwargs['gtk_update_icon_cache'] and not self.install_gtk_update_icon_cache: + self.install_gtk_update_icon_cache = True + prog = state.find_program('gtk4-update-icon-cache', required=False) + found = isinstance(prog, build.Executable) or prog.found() + if not found: + prog = state.find_program('gtk-update-icon-cache') + icondir = os.path.join(datadir_abs, 'icons', 'hicolor') + script = state.backend.get_executable_serialisation([prog, '-q', '-t', '-f', icondir]) + script.skip_if_destdir = True + rv.append(script) + if kwargs['update_desktop_database'] and not self.install_update_desktop_database: + self.install_update_desktop_database = True + prog = state.find_program('update-desktop-database') + appdir = os.path.join(datadir_abs, 'applications') + script = state.backend.get_executable_serialisation([prog, '-q', appdir]) + script.skip_if_destdir = True + rv.append(script) + if kwargs['update_mime_database'] and not self.install_update_mime_database: + self.install_update_mime_database = True + prog = state.find_program('update-mime-database') + appdir = os.path.join(datadir_abs, 'mime') + script = state.backend.get_executable_serialisation([prog, appdir]) + script.skip_if_destdir = True + rv.append(script) + return ModuleReturnValue(None, rv) + + @typed_pos_args('gnome.compile_resources', str, (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) + @typed_kwargs( + 'gnome.compile_resources', + _BUILD_BY_DEFAULT, + _EXTRA_ARGS_KW, + INSTALL_KW, + INSTALL_KW.evolve(name='install_header', since='0.37.0'), + INSTALL_DIR_KW, + KwargInfo('c_name', (str, NoneType)), + KwargInfo('dependencies', ContainerTypeInfo(list, (mesonlib.File, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True), + KwargInfo('export', bool, default=False, since='0.37.0'), + KwargInfo('gresource_bundle', bool, default=False, since='0.37.0'), + KwargInfo('source_dir', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrString'], + kwargs: 'CompileResources') -> 'ModuleReturnValue': + self.__print_gresources_warning(state) + glib_version = self._get_native_glib_version(state) + + glib_compile_resources = self._find_tool(state, 'glib-compile-resources') + cmd: T.List[T.Union['ToolType', str]] = [glib_compile_resources, '@INPUT@'] + + source_dirs = kwargs['source_dir'] + dependencies = kwargs['dependencies'] + + target_name, input_file = args + + # Validate dependencies + subdirs: T.List[str] = [] + depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]] = [] + for dep in dependencies: + if isinstance(dep, mesonlib.File): + subdirs.append(dep.subdir) + else: + depends.append(dep) + subdirs.append(dep.get_subdir()) + if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): + m = 'The "dependencies" argument of gnome.compile_resources() cannot\n' \ + 'be used with the current version of glib-compile-resources due to\n' \ + '' + raise MesonException(m) + + if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): + # Resource xml files generated at build-time cannot be used with + # gnome.compile_resources() because we need to scan the xml for + # dependencies. Use configure_file() instead to generate it at + # configure-time + if isinstance(input_file, mesonlib.File): + # glib-compile-resources will be run inside the source dir, + # so we need either 'src_to_build' or the absolute path. + # Absolute path is the easiest choice. + if input_file.is_built: + ifile = os.path.join(state.environment.get_build_dir(), input_file.subdir, input_file.fname) + else: + ifile = os.path.join(input_file.subdir, input_file.fname) + + elif isinstance(input_file, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)): + raise MesonException('Resource xml files generated at build-time cannot be used with ' + 'gnome.compile_resources() in the current version of glib-compile-resources ' + 'because we need to scan the xml for dependencies due to ' + '\nUse ' + 'configure_file() instead to generate it at configure-time.') + else: + ifile = os.path.join(state.subdir, input_file) + + depend_files, depends, subdirs = self._get_gresource_dependencies( + state, ifile, source_dirs, dependencies) + + # Make source dirs relative to build dir now + source_dirs = [os.path.join(state.build_to_src, state.subdir, d) for d in source_dirs] + # Ensure build directories of generated deps are included + source_dirs += subdirs + # Always include current directory, but after paths set by user + source_dirs.append(os.path.join(state.build_to_src, state.subdir)) + + for source_dir in OrderedSet(source_dirs): + cmd += ['--sourcedir', source_dir] + + if kwargs['c_name']: + cmd += ['--c-name', kwargs['c_name']] + if not kwargs['export']: + cmd += ['--internal'] + + cmd += ['--generate', '--target', '@OUTPUT@'] + cmd += kwargs['extra_args'] + + gresource = kwargs['gresource_bundle'] + if gresource: + output = f'{target_name}.gresource' + name = f'{target_name}_gresource' + else: + if 'c' in state.environment.coredata.compilers.host: + output = f'{target_name}.c' + name = f'{target_name}_c' + elif 'cpp' in state.environment.coredata.compilers.host: + output = f'{target_name}.cpp' + name = f'{target_name}_cpp' + else: + raise MesonException('Compiling GResources into code is only supported in C and C++ projects') + + if kwargs['install'] and not gresource: + raise MesonException('The install kwarg only applies to gresource bundles, see install_header') + + install_header = kwargs['install_header'] + if install_header and gresource: + raise MesonException('The install_header kwarg does not apply to gresource bundles') + if install_header and not kwargs['export']: + raise MesonException('GResource header is installed yet export is not enabled') + + depfile: T.Optional[str] = None + target_cmd: T.List[T.Union['ToolType', str]] + if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): + # This will eventually go out of sync if dependencies are added + target_cmd = cmd + else: + depfile = f'{output}.d' + depend_files = [] + target_cmd = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@'] + target_c = GResourceTarget( + name, + state.subdir, + state.subproject, + state.environment, + target_cmd, + [input_file], + [output], + build_by_default=kwargs['build_by_default'], + depfile=depfile, + depend_files=depend_files, + extra_depends=depends, + install=kwargs['install'], + install_dir=[kwargs['install_dir']] if kwargs['install_dir'] else [], + install_tag=['runtime'], + ) + + if gresource: # Only one target for .gresource files + return ModuleReturnValue(target_c, [target_c]) + + install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')) + assert isinstance(install_dir, str), 'for mypy' + target_h = GResourceHeaderTarget( + f'{target_name}_h', + state.subdir, + state.subproject, + state.environment, + cmd, + [input_file], + [f'{target_name}.h'], + build_by_default=kwargs['build_by_default'], + extra_depends=depends, + install=install_header, + install_dir=[install_dir], + install_tag=['devel'], + ) + rv = [target_c, target_h] + return ModuleReturnValue(rv, rv) + + @staticmethod + def _get_gresource_dependencies( + state: 'ModuleState', input_file: str, source_dirs: T.List[str], + dependencies: T.Sequence[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]] + ) -> T.Tuple[T.List[mesonlib.FileOrString], T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]], T.List[str]]: + + cmd = ['glib-compile-resources', + input_file, + '--generate-dependencies'] + + # Prefer generated files over source files + cmd += ['--sourcedir', state.subdir] # Current build dir + for source_dir in source_dirs: + cmd += ['--sourcedir', os.path.join(state.subdir, source_dir)] + + try: + pc, stdout, stderr = Popen_safe(cmd, cwd=state.environment.get_source_dir()) + except (FileNotFoundError, PermissionError): + raise MesonException('Could not execute glib-compile-resources.') + if pc.returncode != 0: + m = f'glib-compile-resources failed to get dependencies for {cmd[1]}:\n{stderr}' + mlog.warning(m) + raise subprocess.CalledProcessError(pc.returncode, cmd) + + raw_dep_files: T.List[str] = stdout.split('\n')[:-1] + + depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]] = [] + subdirs: T.List[str] = [] + dep_files: T.List[mesonlib.FileOrString] = [] + for resfile in raw_dep_files.copy(): + resbasename = os.path.basename(resfile) + for dep in dependencies: + if isinstance(dep, mesonlib.File): + if dep.fname != resbasename: + continue + raw_dep_files.remove(resfile) + dep_files.append(dep) + subdirs.append(dep.subdir) + break + elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): + fname = None + outputs = {(o, os.path.basename(o)) for o in dep.get_outputs()} + for o, baseo in outputs: + if baseo == resbasename: + fname = o + break + if fname is not None: + raw_dep_files.remove(resfile) + depends.append(dep) + subdirs.append(dep.get_subdir()) + break + else: + # In generate-dependencies mode, glib-compile-resources doesn't raise + # an error for missing resources but instead prints whatever filename + # was listed in the input file. That's good because it means we can + # handle resource files that get generated as part of the build, as + # follows. + # + # If there are multiple generated resource files with the same basename + # then this code will get confused. + try: + f = mesonlib.File.from_source_file(state.environment.get_source_dir(), + ".", resfile) + except MesonException: + raise MesonException( + f'Resource "{resfile}" listed in "{input_file}" was not found. ' + 'If this is a generated file, pass the target that generates ' + 'it to gnome.compile_resources() using the "dependencies" ' + 'keyword argument.') + raw_dep_files.remove(resfile) + dep_files.append(f) + dep_files.extend(raw_dep_files) + return dep_files, depends, subdirs + + def _get_link_args(self, state: 'ModuleState', + lib: T.Union[build.SharedLibrary, build.StaticLibrary], + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], + include_rpath: bool = False, + use_gir_args: bool = False + ) -> T.Tuple[T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: + link_command: T.List[str] = [] + new_depends = list(depends) + # Construct link args + if isinstance(lib, build.SharedLibrary): + libdir = os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(lib)) + link_command.append('-L' + libdir) + if include_rpath: + link_command.append('-Wl,-rpath,' + libdir) + new_depends.append(lib) + # Needed for the following binutils bug: + # https://github.com/mesonbuild/meson/issues/1911 + # However, g-ir-scanner does not understand -Wl,-rpath + # so we need to use -L instead + for d in state.backend.determine_rpath_dirs(lib): + d = os.path.join(state.environment.get_build_dir(), d) + link_command.append('-L' + d) + if include_rpath: + link_command.append('-Wl,-rpath,' + d) + if use_gir_args and self._gir_has_option('--extra-library'): + link_command.append('--extra-library=' + lib.name) + else: + link_command.append('-l' + lib.name) + return link_command, new_depends + + def _get_dependencies_flags_raw( + self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + state: 'ModuleState', + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], + include_rpath: bool, + use_gir_args: bool, + ) -> T.Tuple[OrderedSet[str], OrderedSet[T.Union[str, T.Tuple[str, str]]], OrderedSet[T.Union[str, T.Tuple[str, str]]], OrderedSet[str], + T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: + cflags: OrderedSet[str] = OrderedSet() + # External linker flags that can't be de-duped reliably because they + # require two args in order, such as -framework AVFoundation will be stored as a tuple. + internal_ldflags: OrderedSet[T.Union[str, T.Tuple[str, str]]] = OrderedSet() + external_ldflags: OrderedSet[T.Union[str, T.Tuple[str, str]]] = OrderedSet() + gi_includes: OrderedSet[str] = OrderedSet() + deps = mesonlib.listify(deps) + depends = list(depends) + + for dep in deps: + if isinstance(dep, Dependency): + girdir = dep.get_variable(pkgconfig='girdir', internal='girdir', default_value='') + if girdir: + assert isinstance(girdir, str), 'for mypy' + gi_includes.update([girdir]) + if isinstance(dep, InternalDependency): + cflags.update(dep.get_compile_args()) + cflags.update(state.get_include_args(dep.include_directories)) + for lib in dep.libraries: + if isinstance(lib, build.SharedLibrary): + _ld, depends = self._get_link_args(state, lib, depends, include_rpath) + internal_ldflags.update(_ld) + libdepflags = self._get_dependencies_flags_raw(lib.get_external_deps(), state, depends, include_rpath, + use_gir_args) + cflags.update(libdepflags[0]) + internal_ldflags.update(libdepflags[1]) + external_ldflags.update(libdepflags[2]) + gi_includes.update(libdepflags[3]) + depends = libdepflags[4] + extdepflags = self._get_dependencies_flags_raw(dep.ext_deps, state, depends, include_rpath, + use_gir_args) + cflags.update(extdepflags[0]) + internal_ldflags.update(extdepflags[1]) + external_ldflags.update(extdepflags[2]) + gi_includes.update(extdepflags[3]) + depends = extdepflags[4] + for source in dep.sources: + if isinstance(source, GirTarget): + gi_includes.update([os.path.join(state.environment.get_build_dir(), + source.get_subdir())]) + # This should be any dependency other than an internal one. + elif isinstance(dep, Dependency): + cflags.update(dep.get_compile_args()) + ldflags = iter(dep.get_link_args(raw=True)) + for flag in ldflags: + if (os.path.isabs(flag) and + # For PkgConfigDependency only: + getattr(dep, 'is_libtool', False)): + lib_dir = os.path.dirname(flag) + external_ldflags.update([f'-L{lib_dir}']) + if include_rpath: + external_ldflags.update([f'-Wl,-rpath {lib_dir}']) + libname = os.path.basename(flag) + if libname.startswith("lib"): + libname = libname[3:] + libname = libname.split(".so")[0] + flag = f"-l{libname}" + # FIXME: Hack to avoid passing some compiler options in + if flag.startswith("-W"): + continue + # If it's a framework arg, slurp the framework name too + # to preserve the order of arguments + if flag == '-framework': + external_ldflags.update([(flag, next(ldflags))]) + else: + external_ldflags.update([flag]) + elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): + cflags.update(state.get_include_args(dep.get_include_dirs())) + depends.append(dep) + else: + mlog.log(f'dependency {dep!r} not handled to build gir files') + continue + + if use_gir_args and self._gir_has_option('--extra-library'): + def fix_ldflags(ldflags: T.Iterable[T.Union[str, T.Tuple[str, str]]]) -> OrderedSet[T.Union[str, T.Tuple[str, str]]]: + fixed_ldflags: OrderedSet[T.Union[str, T.Tuple[str, str]]] = OrderedSet() + for ldflag in ldflags: + if isinstance(ldflag, str) and ldflag.startswith("-l"): + ldflag = ldflag.replace('-l', '--extra-library=', 1) + fixed_ldflags.add(ldflag) + return fixed_ldflags + internal_ldflags = fix_ldflags(internal_ldflags) + external_ldflags = fix_ldflags(external_ldflags) + return cflags, internal_ldflags, external_ldflags, gi_includes, depends + + def _get_dependencies_flags( + self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + state: 'ModuleState', + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], + include_rpath: bool = False, + use_gir_args: bool = False, + ) -> T.Tuple[OrderedSet[str], T.List[str], T.List[str], OrderedSet[str], + T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: + + cflags, internal_ldflags_raw, external_ldflags_raw, gi_includes, depends = self._get_dependencies_flags_raw(deps, state, depends, include_rpath, use_gir_args) + internal_ldflags: T.List[str] = [] + external_ldflags: T.List[str] = [] + + # Extract non-deduplicable argument groups out of the tuples. + for ldflag in internal_ldflags_raw: + if isinstance(ldflag, str): + internal_ldflags.append(ldflag) + else: + internal_ldflags.extend(ldflag) + for ldflag in external_ldflags_raw: + if isinstance(ldflag, str): + external_ldflags.append(ldflag) + else: + external_ldflags.extend(ldflag) + + return cflags, internal_ldflags, external_ldflags, gi_includes, depends + + def _unwrap_gir_target(self, girtarget: T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState' + ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary]: + if not isinstance(girtarget, (build.Executable, build.SharedLibrary, + build.StaticLibrary)): + raise MesonException(f'Gir target must be an executable or library but is "{girtarget}" of type {type(girtarget).__name__}') + + STATIC_BUILD_REQUIRED_VERSION = ">=1.58.1" + if isinstance(girtarget, (build.StaticLibrary)) and \ + not mesonlib.version_compare( + self._get_gir_dep(state)[0].get_version(), + STATIC_BUILD_REQUIRED_VERSION): + raise MesonException('Static libraries can only be introspected with GObject-Introspection ' + STATIC_BUILD_REQUIRED_VERSION) + + return girtarget + + def _devenv_prepend(self, varname: str, value: str) -> None: + if self.devenv is None: + self.devenv = build.EnvironmentVariables() + self.devenv.prepend(varname, [value]) + + def postconf_hook(self, b: build.Build) -> None: + if self.devenv is not None: + b.devenv.append(self.devenv) + + def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram'], + T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram']]: + if not self.gir_dep: + self.gir_dep = state.dependency('gobject-introspection-1.0') + self.giscanner = self._find_tool(state, 'g-ir-scanner') + self.gicompiler = self._find_tool(state, 'g-ir-compiler') + return self.gir_dep, self.giscanner, self.gicompiler + + @functools.lru_cache(maxsize=None) + def _gir_has_option(self, option: str) -> bool: + exe = self.giscanner + if isinstance(exe, OverrideProgram): + # Handle overridden g-ir-scanner + assert option in {'--extra-library', '--sources-top-dirs'} + return True + p, o, _ = Popen_safe(exe.get_command() + ['--help'], stderr=subprocess.STDOUT) + return p.returncode == 0 and option in o + + # May mutate depends and gir_inc_dirs + @staticmethod + def _scan_include(state: 'ModuleState', includes: T.List[T.Union[str, GirTarget]] + ) -> T.Tuple[T.List[str], T.List[str], T.List[GirTarget]]: + ret: T.List[str] = [] + gir_inc_dirs: T.List[str] = [] + depends: T.List[GirTarget] = [] + + for inc in includes: + if isinstance(inc, str): + ret += [f'--include={inc}'] + elif isinstance(inc, GirTarget): + gir_inc_dirs .append(os.path.join(state.environment.get_build_dir(), inc.get_subdir())) + ret.append(f"--include-uninstalled={os.path.join(inc.get_subdir(), inc.get_basename())}") + depends.append(inc) + + return ret, gir_inc_dirs, depends + + @staticmethod + def _scan_langs(state: 'ModuleState', langs: T.Iterable[str]) -> T.List[str]: + ret: T.List[str] = [] + + for lang in langs: + link_args = state.environment.coredata.get_external_link_args(MachineChoice.HOST, lang) + for link_arg in link_args: + if link_arg.startswith('-L'): + ret.append(link_arg) + + return ret + + @staticmethod + def _scan_gir_targets(state: 'ModuleState', girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Union[str, build.Executable]]: + ret: T.List[T.Union[str, build.Executable]] = [] + + for girtarget in girtargets: + if isinstance(girtarget, build.Executable): + ret += ['--program', girtarget] + else: + # Because of https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/72 + # we can't use the full path until this is merged. + libpath = os.path.join(girtarget.get_subdir(), girtarget.get_filename()) + # Must use absolute paths here because g-ir-scanner will not + # add them to the runtime path list if they're relative. This + # means we cannot use @BUILD_ROOT@ + build_root = state.environment.get_build_dir() + if isinstance(girtarget, build.SharedLibrary): + # need to put our output directory first as we need to use the + # generated libraries instead of any possibly installed system/prefix + # ones. + ret += ["-L{}/{}".format(build_root, os.path.dirname(libpath))] + libname = girtarget.get_basename() + else: + libname = os.path.join(f"{build_root}/{libpath}") + ret += ['--library', libname] + # Needed for the following binutils bug: + # https://github.com/mesonbuild/meson/issues/1911 + # However, g-ir-scanner does not understand -Wl,-rpath + # so we need to use -L instead + for d in state.backend.determine_rpath_dirs(girtarget): + d = os.path.join(state.environment.get_build_dir(), d) + ret.append('-L' + d) + + return ret + + @staticmethod + def _get_girtargets_langs_compilers(girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Tuple[str, 'Compiler']]: + ret: T.List[T.Tuple[str, 'Compiler']] = [] + for girtarget in girtargets: + for lang, compiler in girtarget.compilers.items(): + # XXX: Can you use g-i with any other language? + if lang in {'c', 'cpp', 'objc', 'objcpp', 'd'}: + ret.append((lang, compiler)) + break + + return ret + + @staticmethod + def _get_gir_targets_deps(girtargets: T.Sequence[build.BuildTarget] + ) -> T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Dependency]]: + ret: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Dependency]] = [] + for girtarget in girtargets: + ret += girtarget.get_all_link_deps() + ret += girtarget.get_external_deps() + return ret + + @staticmethod + def _get_gir_targets_inc_dirs(girtargets: T.Sequence[build.BuildTarget]) -> OrderedSet[build.IncludeDirs]: + ret: OrderedSet = OrderedSet() + for girtarget in girtargets: + ret.update(girtarget.get_include_dirs()) + return ret + + @staticmethod + def _get_langs_compilers_flags(state: 'ModuleState', langs_compilers: T.List[T.Tuple[str, 'Compiler']] + ) -> T.Tuple[T.List[str], T.List[str], T.List[str]]: + cflags: T.List[str] = [] + internal_ldflags: T.List[str] = [] + external_ldflags: T.List[str] = [] + + for lang, compiler in langs_compilers: + if state.global_args.get(lang): + cflags += state.global_args[lang] + if state.project_args.get(lang): + cflags += state.project_args[lang] + if mesonlib.OptionKey('b_sanitize') in compiler.base_options: + sanitize = state.environment.coredata.options[mesonlib.OptionKey('b_sanitize')].value + cflags += compiler.sanitizer_compile_args(sanitize) + sanitize = sanitize.split(',') + # These must be first in ldflags + if 'address' in sanitize: + internal_ldflags += ['-lasan'] + if 'thread' in sanitize: + internal_ldflags += ['-ltsan'] + if 'undefined' in sanitize: + internal_ldflags += ['-lubsan'] + # FIXME: Linking directly to lib*san is not recommended but g-ir-scanner + # does not understand -f LDFLAGS. https://bugzilla.gnome.org/show_bug.cgi?id=783892 + # ldflags += compiler.sanitizer_link_args(sanitize) + + return cflags, internal_ldflags, external_ldflags + + @staticmethod + def _make_gir_filelist(state: 'ModuleState', srcdir: str, ns: str, + nsversion: str, girtargets: T.Sequence[build.BuildTarget], + libsources: T.Sequence[T.Union[ + str, mesonlib.File, build.GeneratedList, + build.CustomTarget, build.CustomTargetIndex]] + ) -> str: + gir_filelist_dir = state.backend.get_target_private_dir_abs(girtargets[0]) + if not os.path.isdir(gir_filelist_dir): + os.mkdir(gir_filelist_dir) + gir_filelist_filename = os.path.join(gir_filelist_dir, f'{ns}_{nsversion}_gir_filelist') + + with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist: + for s in libsources: + if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): + for custom_output in s.get_outputs(): + gir_filelist.write(os.path.join(state.environment.get_build_dir(), + state.backend.get_target_dir(s), + custom_output) + '\n') + elif isinstance(s, mesonlib.File): + gir_filelist.write(s.rel_to_builddir(state.build_to_src) + '\n') + elif isinstance(s, build.GeneratedList): + for gen_src in s.get_outputs(): + gir_filelist.write(os.path.join(srcdir, gen_src) + '\n') + else: + gir_filelist.write(os.path.join(srcdir, s) + '\n') + + return gir_filelist_filename + + @staticmethod + def _make_gir_target( + state: 'ModuleState', + girfile: str, + scan_command: T.Sequence[T.Union['FileOrString', Executable, ExternalProgram, OverrideProgram]], + generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]], + depends: T.Sequence[T.Union['FileOrString', build.BuildTarget, 'build.GeneratedTypes', build.StructuredSources]], + kwargs: T.Dict[str, T.Any]) -> GirTarget: + install = kwargs['install_gir'] + if install is None: + install = kwargs['install'] + + install_dir = kwargs['install_dir_gir'] + if install_dir is None: + install_dir = os.path.join(state.environment.get_datadir(), 'gir-1.0') + elif install_dir is False: + install = False + + # g-ir-scanner uses pkg-config to find libraries such as glib. They could + # be built as subproject in which case we need to trick it to use + # -uninstalled.pc files Meson generated. It also must respect pkgconfig + # settings user could have set in machine file, like PKG_CONFIG_LIBDIR, + # SYSROOT, etc. + run_env = PkgConfigDependency.get_env(state.environment, MachineChoice.HOST, uninstalled=True) + # g-ir-scanner uses Python's distutils to find the compiler, which uses 'CC' + cc_exelist = state.environment.coredata.compilers.host['c'].get_exelist() + run_env.set('CC', [quote_arg(x) for x in cc_exelist], ' ') + run_env.merge(kwargs['env']) + + return GirTarget( + girfile, + state.subdir, + state.subproject, + state.environment, + scan_command, + generated_files, + [girfile], + build_by_default=kwargs['build_by_default'], + extra_depends=depends, + install=install, + install_dir=[install_dir], + install_tag=['devel'], + env=run_env, + ) + + @staticmethod + def _make_typelib_target(state: 'ModuleState', typelib_output: str, + typelib_cmd: T.Sequence[T.Union[str, build.Executable, ExternalProgram, build.CustomTarget]], + generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]], + kwargs: T.Dict[str, T.Any]) -> TypelibTarget: + install = kwargs['install_typelib'] + if install is None: + install = kwargs['install'] + + install_dir = kwargs['install_dir_typelib'] + if install_dir is None: + install_dir = os.path.join(state.environment.get_libdir(), 'girepository-1.0') + elif install_dir is False: + install = False + + return TypelibTarget( + typelib_output, + state.subdir, + state.subproject, + state.environment, + typelib_cmd, + generated_files, + [typelib_output], + install=install, + install_dir=[install_dir], + install_tag=['typelib'], + build_by_default=kwargs['build_by_default'], + env=kwargs['env'], + ) + + @staticmethod + def _gather_typelib_includes_and_update_depends( + state: 'ModuleState', + deps: T.Sequence[T.Union[Dependency, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]] + ) -> T.Tuple[T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: + # Need to recursively add deps on GirTarget sources from our + # dependencies and also find the include directories needed for the + # typelib generation custom target below. + typelib_includes: T.List[str] = [] + new_depends = list(depends) + for dep in deps: + # Add a dependency on each GirTarget listed in dependencies and add + # the directory where it will be generated to the typelib includes + if isinstance(dep, InternalDependency): + for source in dep.sources: + if isinstance(source, GirTarget) and source not in depends: + new_depends.append(source) + subdir = os.path.join(state.environment.get_build_dir(), + source.get_subdir()) + if subdir not in typelib_includes: + typelib_includes.append(subdir) + # Do the same, but for dependencies of dependencies. These are + # stored in the list of generated sources for each link dep (from + # girtarget.get_all_link_deps() above). + # FIXME: Store this in the original form from declare_dependency() + # so it can be used here directly. + elif isinstance(dep, build.SharedLibrary): + for g_source in dep.generated: + if isinstance(g_source, GirTarget): + subdir = os.path.join(state.environment.get_build_dir(), + g_source.get_subdir()) + if subdir not in typelib_includes: + typelib_includes.append(subdir) + if isinstance(dep, Dependency): + girdir = dep.get_variable(pkgconfig='girdir', internal='girdir', default_value='') + assert isinstance(girdir, str), 'for mypy' + if girdir and girdir not in typelib_includes: + typelib_includes.append(girdir) + return typelib_includes, new_depends + + @staticmethod + def _get_external_args_for_langs(state: 'ModuleState', langs: T.List[str]) -> T.List[str]: + ret: T.List[str] = [] + for lang in langs: + ret += mesonlib.listify(state.environment.coredata.get_external_args(MachineChoice.HOST, lang)) + return ret + + @staticmethod + def _get_scanner_cflags(cflags: T.Iterable[str]) -> T.Iterable[str]: + 'g-ir-scanner only accepts -I/-D/-U; must ignore all other flags' + for f in cflags: + # _FORTIFY_SOURCE depends on / works together with -O, on the other hand this + # just invokes the preprocessor anyway + if f.startswith(('-D', '-U', '-I')) and not f.startswith('-D_FORTIFY_SOURCE'): + yield f + + @staticmethod + def _get_scanner_ldflags(ldflags: T.Iterable[str]) -> T.Iterable[str]: + 'g-ir-scanner only accepts -L/-l; must ignore -F and other linker flags' + for f in ldflags: + if f.startswith(('-L', '-l', '--extra-library')): + yield f + + @typed_pos_args('gnome.generate_gir', varargs=(build.Executable, build.SharedLibrary, build.StaticLibrary), min_varargs=1) + @typed_kwargs( + 'gnome.generate_gir', + INSTALL_KW, + _BUILD_BY_DEFAULT.evolve(since='0.40.0'), + _EXTRA_ARGS_KW, + ENV_KW.evolve(since='1.2.0'), + KwargInfo('dependencies', ContainerTypeInfo(list, Dependency), default=[], listify=True), + KwargInfo('export_packages', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('fatal_warnings', bool, default=False, since='0.55.0'), + KwargInfo('header', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('identifier_prefix', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('include_directories', ContainerTypeInfo(list, (str, build.IncludeDirs)), default=[], listify=True), + KwargInfo('includes', ContainerTypeInfo(list, (str, GirTarget)), default=[], listify=True), + KwargInfo('install_gir', (bool, NoneType), since='0.61.0'), + KwargInfo('install_dir_gir', (str, bool, NoneType), + deprecated_values={False: ('0.61.0', 'Use install_gir to disable installation')}, + validator=lambda x: 'as boolean can only be false' if x is True else None), + KwargInfo('install_typelib', (bool, NoneType), since='0.61.0'), + KwargInfo('install_dir_typelib', (str, bool, NoneType), + deprecated_values={False: ('0.61.0', 'Use install_typelib to disable installation')}, + validator=lambda x: 'as boolean can only be false' if x is True else None), + KwargInfo('link_with', ContainerTypeInfo(list, (build.SharedLibrary, build.StaticLibrary)), default=[], listify=True), + KwargInfo('namespace', str, required=True), + KwargInfo('nsversion', str, required=True), + KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True), + KwargInfo('symbol_prefix', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[build.Executable, build.SharedLibrary, build.StaticLibrary]]], + kwargs: 'GenerateGir') -> ModuleReturnValue: + # Ensure we have a C compiler even in C++ projects. + state.add_language('c', MachineChoice.HOST) + + girtargets = [self._unwrap_gir_target(arg, state) for arg in args[0]] + if len(girtargets) > 1 and any(isinstance(el, build.Executable) for el in girtargets): + raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable') + + gir_dep, giscanner, gicompiler = self._get_gir_dep(state) + + ns = kwargs['namespace'] + nsversion = kwargs['nsversion'] + libsources = kwargs['sources'] + + girfile = f'{ns}-{nsversion}.gir' + srcdir = os.path.join(state.environment.get_source_dir(), state.subdir) + builddir = os.path.join(state.environment.get_build_dir(), state.subdir) + + depends: T.List[T.Union['FileOrString', 'build.GeneratedTypes', build.BuildTarget, build.StructuredSources]] = [] + depends.extend(gir_dep.sources) + depends.extend(girtargets) + + langs_compilers = self._get_girtargets_langs_compilers(girtargets) + cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers) + deps = self._get_gir_targets_deps(girtargets) + deps += kwargs['dependencies'] + deps += [gir_dep] + typelib_includes, depends = self._gather_typelib_includes_and_update_depends(state, deps, depends) + # ldflags will be misinterpreted by gir scanner (showing + # spurious dependencies) but building GStreamer fails if they + # are not used here. + dep_cflags, dep_internal_ldflags, dep_external_ldflags, gi_includes, depends = \ + self._get_dependencies_flags(deps, state, depends, use_gir_args=True) + scan_cflags = [] + scan_cflags += list(self._get_scanner_cflags(cflags)) + scan_cflags += list(self._get_scanner_cflags(dep_cflags)) + scan_cflags += list(self._get_scanner_cflags(self._get_external_args_for_langs(state, [lc[0] for lc in langs_compilers]))) + scan_internal_ldflags = [] + scan_internal_ldflags += list(self._get_scanner_ldflags(internal_ldflags)) + scan_internal_ldflags += list(self._get_scanner_ldflags(dep_internal_ldflags)) + scan_external_ldflags = [] + scan_external_ldflags += list(self._get_scanner_ldflags(external_ldflags)) + scan_external_ldflags += list(self._get_scanner_ldflags(dep_external_ldflags)) + girtargets_inc_dirs = self._get_gir_targets_inc_dirs(girtargets) + inc_dirs = kwargs['include_directories'] + + gir_inc_dirs: T.List[str] = [] + + scan_command: T.List[T.Union[str, build.Executable, 'ExternalProgram', 'OverrideProgram']] = [giscanner] + scan_command += ['--quiet'] + scan_command += ['--no-libtool'] + scan_command += ['--namespace=' + ns, '--nsversion=' + nsversion] + scan_command += ['--warn-all'] + scan_command += ['--output', '@OUTPUT@'] + scan_command += [f'--c-include={h}' for h in kwargs['header']] + scan_command += kwargs['extra_args'] + scan_command += ['-I' + srcdir, '-I' + builddir] + scan_command += state.get_include_args(girtargets_inc_dirs) + scan_command += ['--filelist=' + self._make_gir_filelist(state, srcdir, ns, nsversion, girtargets, libsources)] + for l in kwargs['link_with']: + _cflags, depends = self._get_link_args(state, l, depends, use_gir_args=True) + scan_command.extend(_cflags) + _cmd, _ginc, _deps = self._scan_include(state, kwargs['includes']) + scan_command.extend(_cmd) + gir_inc_dirs.extend(_ginc) + depends.extend(_deps) + + scan_command += [f'--symbol-prefix={p}' for p in kwargs['symbol_prefix']] + scan_command += [f'--identifier-prefix={p}' for p in kwargs['identifier_prefix']] + scan_command += [f'--pkg-export={p}' for p in kwargs['export_packages']] + scan_command += ['--cflags-begin'] + scan_command += scan_cflags + scan_command += ['--cflags-end'] + scan_command += state.get_include_args(inc_dirs) + scan_command += state.get_include_args(itertools.chain(gi_includes, gir_inc_dirs, inc_dirs), prefix='--add-include-path=') + scan_command += list(scan_internal_ldflags) + scan_command += self._scan_gir_targets(state, girtargets) + scan_command += self._scan_langs(state, [lc[0] for lc in langs_compilers]) + scan_command += list(scan_external_ldflags) + + if self._gir_has_option('--sources-top-dirs'): + scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_source_dir(), state.root_subdir)] + scan_command += ['--sources-top-dirs', os.path.join(state.environment.get_build_dir(), state.root_subdir)] + + if '--warn-error' in scan_command: + FeatureDeprecated.single_use('gnome.generate_gir argument --warn-error', '0.55.0', + state.subproject, 'Use "fatal_warnings" keyword argument', state.current_node) + if kwargs['fatal_warnings']: + scan_command.append('--warn-error') + + generated_files = [f for f in libsources if isinstance(f, (GeneratedList, CustomTarget, CustomTargetIndex))] + + scan_target = self._make_gir_target( + state, girfile, scan_command, generated_files, depends, + # We have to cast here because mypy can't figure this out + T.cast('T.Dict[str, T.Any]', kwargs)) + + typelib_output = f'{ns}-{nsversion}.typelib' + typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@'] + typelib_cmd += state.get_include_args(gir_inc_dirs, prefix='--includedir=') + + for incdir in typelib_includes: + typelib_cmd += ["--includedir=" + incdir] + + typelib_target = self._make_typelib_target(state, typelib_output, typelib_cmd, generated_files, T.cast('T.Dict[str, T.Any]', kwargs)) + + self._devenv_prepend('GI_TYPELIB_PATH', os.path.join(state.environment.get_build_dir(), state.subdir)) + + rv = [scan_target, typelib_target] + + return ModuleReturnValue(rv, rv) + + @noPosargs + @typed_kwargs('gnome.compile_schemas', _BUILD_BY_DEFAULT.evolve(since='0.40.0'), DEPEND_FILES_KW) + def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'CompileSchemas') -> ModuleReturnValue: + srcdir = os.path.join(state.build_to_src, state.subdir) + outdir = state.subdir + + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-compile-schemas'), '--targetdir', outdir, srcdir] + if state.subdir == '': + targetname = 'gsettings-compile' + else: + targetname = 'gsettings-compile-' + state.subdir.replace('/', '_') + target_g = build.CustomTarget( + targetname, + state.subdir, + state.subproject, + state.environment, + cmd, + [], + ['gschemas.compiled'], + build_by_default=kwargs['build_by_default'], + depend_files=kwargs['depend_files'], + ) + self._devenv_prepend('GSETTINGS_SCHEMA_DIR', os.path.join(state.environment.get_build_dir(), state.subdir)) + return ModuleReturnValue(target_g, [target_g]) + + @typed_pos_args('gnome.yelp', str, varargs=str) + @typed_kwargs( + 'gnome.yelp', + KwargInfo( + 'languages', ContainerTypeInfo(list, str), + listify=True, default=[], + deprecated='0.43.0', + deprecated_message='Use a LINGUAS file in the source directory instead', + ), + KwargInfo('media', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('sources', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('symlink_media', bool, default=True), + ) + def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Yelp') -> ModuleReturnValue: + project_id = args[0] + sources = kwargs['sources'] + if args[1]: + FeatureDeprecated.single_use('gnome.yelp more than one positional argument', '0.60.0', + state.subproject, 'use the "sources" keyword argument instead.', state.current_node) + if not sources: + sources = args[1] + if not sources: + raise MesonException('Yelp requires a list of sources') + elif args[1]: + mlog.warning('"gnome.yelp" ignores positional sources arguments when the "sources" keyword argument is set') + sources_files = [mesonlib.File.from_source_file(state.environment.source_dir, + os.path.join(state.subdir, 'C'), + s) for s in sources] + + langs = kwargs['languages'] + if not langs: + langs = read_linguas(os.path.join(state.environment.source_dir, state.subdir)) + + media = kwargs['media'] + symlinks = kwargs['symlink_media'] + targets: T.List[T.Union['build.Target', build.Data, build.SymlinkData]] = [] + potargets: T.List[build.RunTarget] = [] + + itstool = state.find_program('itstool') + msgmerge = state.find_program('msgmerge') + msgfmt = state.find_program('msgfmt') + + install_dir = os.path.join(state.environment.get_datadir(), 'help') + c_install_dir = os.path.join(install_dir, 'C', project_id) + c_data = build.Data(sources_files, c_install_dir, c_install_dir, + mesonlib.FileMode(), state.subproject, install_tag='doc') + targets.append(c_data) + + media_files: T.List[mesonlib.File] = [] + for m in media: + f = mesonlib.File.from_source_file(state.environment.source_dir, + os.path.join(state.subdir, 'C'), m) + media_files.append(f) + m_install_dir = os.path.join(c_install_dir, os.path.dirname(m)) + m_data = build.Data([f], m_install_dir, m_install_dir, + mesonlib.FileMode(), state.subproject, install_tag='doc') + targets.append(m_data) + + pot_file = os.path.join('@SOURCE_ROOT@', state.subdir, 'C', project_id + '.pot') + pot_sources = [os.path.join('@SOURCE_ROOT@', state.subdir, 'C', s) for s in sources] + pot_args: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [itstool, '-o', pot_file] + pot_args.extend(pot_sources) + pottarget = build.RunTarget(f'help-{project_id}-pot', pot_args, [], + os.path.join(state.subdir, 'C'), state.subproject, + state.environment) + targets.append(pottarget) + + for l in langs: + l_subdir = os.path.join(state.subdir, l) + l_install_dir = os.path.join(install_dir, l, project_id) + + for i, m in enumerate(media): + m_dir = os.path.dirname(m) + m_install_dir = os.path.join(l_install_dir, m_dir) + l_data: T.Union[build.Data, build.SymlinkData] + if symlinks: + link_target = os.path.join(os.path.relpath(c_install_dir, start=m_install_dir), m) + l_data = build.SymlinkData(link_target, os.path.basename(m), + m_install_dir, state.subproject, install_tag='doc') + else: + try: + m_file = mesonlib.File.from_source_file(state.environment.source_dir, l_subdir, m) + except MesonException: + m_file = media_files[i] + l_data = build.Data([m_file], m_install_dir, m_install_dir, + mesonlib.FileMode(), state.subproject, install_tag='doc') + targets.append(l_data) + + po_file = l + '.po' + po_args: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [ + msgmerge, '-q', '-o', + os.path.join('@SOURCE_ROOT@', l_subdir, po_file), + os.path.join('@SOURCE_ROOT@', l_subdir, po_file), pot_file] + potarget = build.RunTarget(f'help-{project_id}-{l}-update-po', + po_args, [pottarget], l_subdir, state.subproject, + state.environment) + targets.append(potarget) + potargets.append(potarget) + + gmo_file = project_id + '-' + l + '.gmo' + gmotarget = build.CustomTarget( + f'help-{project_id}-{l}-gmo', + l_subdir, + state.subproject, + state.environment, + [msgfmt, '@INPUT@', '-o', '@OUTPUT@'], + [po_file], + [gmo_file], + install_tag=['doc'], + ) + targets.append(gmotarget) + + mergetarget = build.CustomTarget( + f'help-{project_id}-{l}', + l_subdir, + state.subproject, + state.environment, + [itstool, '-m', os.path.join(l_subdir, gmo_file), '--lang', l, '-o', '@OUTDIR@', '@INPUT@'], + sources_files, + sources, + extra_depends=[gmotarget], + install=True, + install_dir=[l_install_dir], + install_tag=['doc'], + ) + targets.append(mergetarget) + + allpotarget = build.AliasTarget(f'help-{project_id}-update-po', potargets, + state.subdir, state.subproject, state.environment) + targets.append(allpotarget) + + return ModuleReturnValue(None, targets) + + @typed_pos_args('gnome.gtkdoc', str) + @typed_kwargs( + 'gnome.gtkdoc', + KwargInfo('c_args', ContainerTypeInfo(list, str), since='0.48.0', default=[], listify=True), + KwargInfo('check', bool, default=False, since='0.52.0'), + KwargInfo('content_files', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True), + KwargInfo( + 'dependencies', + ContainerTypeInfo(list, (Dependency, build.SharedLibrary, build.StaticLibrary)), + listify=True, default=[]), + KwargInfo('expand_content_files', ContainerTypeInfo(list, (str, mesonlib.File)), default=[], listify=True), + KwargInfo('fixxref_args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('gobject_typesfile', ContainerTypeInfo(list, (str, mesonlib.File)), default=[], listify=True), + KwargInfo('html_args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('html_assets', ContainerTypeInfo(list, (str, mesonlib.File)), default=[], listify=True), + KwargInfo('ignore_headers', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo( + 'include_directories', + ContainerTypeInfo(list, (str, build.IncludeDirs)), + listify=True, default=[]), + KwargInfo('install', bool, default=True), + KwargInfo('install_dir', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('main_sgml', (str, NoneType)), + KwargInfo('main_xml', (str, NoneType)), + KwargInfo('mkdb_args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo( + 'mode', str, default='auto', since='0.37.0', + validator=in_set_validator({'xml', 'sgml', 'none', 'auto'})), + KwargInfo('module_version', str, default='', since='0.48.0'), + KwargInfo('namespace', str, default='', since='0.37.0'), + KwargInfo('scan_args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('scanobjs_args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('src_dir', ContainerTypeInfo(list, (str, build.IncludeDirs)), listify=True, required=True), + ) + def gtkdoc(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GtkDoc') -> ModuleReturnValue: + modulename = args[0] + main_file = kwargs['main_sgml'] + main_xml = kwargs['main_xml'] + if main_xml is not None: + if main_file is not None: + raise InvalidArguments('gnome.gtkdoc: main_xml and main_sgml are exclusive arguments') + main_file = main_xml + moduleversion = kwargs['module_version'] + targetname = modulename + ('-' + moduleversion if moduleversion else '') + '-doc' + command = state.environment.get_build_command() + + namespace = kwargs['namespace'] + + # Ensure we have a C compiler even in C++ projects. + state.add_language('c', MachineChoice.HOST) + + def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: + for f in files: + if isinstance(f, mesonlib.File): + yield f.absolute_path(state.environment.get_source_dir(), state.environment.get_build_dir()) + else: + yield os.path.join(state.environment.get_source_dir(), state.subdir, f) + + src_dirs = kwargs['src_dir'] + header_dirs: T.List[str] = [] + for src_dir in src_dirs: + if isinstance(src_dir, build.IncludeDirs): + header_dirs.extend(src_dir.to_string_list(state.environment.get_source_dir(), + state.environment.get_build_dir())) + else: + header_dirs.append(src_dir) + + t_args: T.List[str] = [ + '--internal', 'gtkdoc', + '--sourcedir=' + state.environment.get_source_dir(), + '--builddir=' + state.environment.get_build_dir(), + '--subdir=' + state.subdir, + '--headerdirs=' + '@@'.join(header_dirs), + '--mainfile=' + main_file, + '--modulename=' + modulename, + '--moduleversion=' + moduleversion, + '--mode=' + kwargs['mode']] + for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']: + program_name = 'gtkdoc-' + tool + program = state.find_program(program_name) + path = program.get_path() + assert path is not None, "This shouldn't be possible since program should be found" + t_args.append(f'--{program_name}={path}') + if namespace: + t_args.append('--namespace=' + namespace) + exe_wrapper = state.environment.get_exe_wrapper() + if exe_wrapper: + t_args.append('--run=' + ' '.join(exe_wrapper.get_command())) + t_args.append(f'--htmlargs={"@@".join(kwargs["html_args"])}') + t_args.append(f'--scanargs={"@@".join(kwargs["scan_args"])}') + t_args.append(f'--scanobjsargs={"@@".join(kwargs["scanobjs_args"])}') + t_args.append(f'--gobjects-types-file={"@@".join(abs_filenames(kwargs["gobject_typesfile"]))}') + t_args.append(f'--fixxrefargs={"@@".join(kwargs["fixxref_args"])}') + t_args.append(f'--mkdbargs={"@@".join(kwargs["mkdb_args"])}') + t_args.append(f'--html-assets={"@@".join(abs_filenames(kwargs["html_assets"]))}') + + depends: T.List['build.GeneratedTypes'] = [] + content_files = [] + for s in kwargs['content_files']: + if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): + depends.append(s) + for o in s.get_outputs(): + content_files.append(os.path.join(state.environment.get_build_dir(), + state.backend.get_target_dir(s), + o)) + elif isinstance(s, mesonlib.File): + content_files.append(s.absolute_path(state.environment.get_source_dir(), + state.environment.get_build_dir())) + elif isinstance(s, build.GeneratedList): + depends.append(s) + for gen_src in s.get_outputs(): + content_files.append(os.path.join(state.environment.get_source_dir(), + state.subdir, + gen_src)) + else: + content_files.append(os.path.join(state.environment.get_source_dir(), + state.subdir, + s)) + t_args += ['--content-files=' + '@@'.join(content_files)] + + t_args.append(f'--expand-content-files={"@@".join(abs_filenames(kwargs["expand_content_files"]))}') + t_args.append(f'--ignore-headers={"@@".join(kwargs["ignore_headers"])}') + t_args.append(f'--installdir={"@@".join(kwargs["install_dir"])}') + build_args, new_depends = self._get_build_args(kwargs['c_args'], kwargs['include_directories'], + kwargs['dependencies'], state, depends) + t_args.extend(build_args) + new_depends.extend(depends) + custom_target = build.CustomTarget( + targetname, + state.subdir, + state.subproject, + state.environment, + command + t_args, + [], + [f'{modulename}-decl.txt'], + build_always_stale=True, + extra_depends=new_depends, + ) + alias_target = build.AliasTarget(targetname, [custom_target], state.subdir, state.subproject, state.environment) + if kwargs['check']: + check_cmd = state.find_program('gtkdoc-check') + check_env = ['DOC_MODULE=' + modulename, + 'DOC_MAIN_SGML_FILE=' + main_file] + check_args = (targetname + '-check', check_cmd) + check_workdir = os.path.join(state.environment.get_build_dir(), state.subdir) + state.test(check_args, env=check_env, workdir=check_workdir, depends=[custom_target]) + res: T.List[T.Union[build.Target, build.ExecutableSerialisation]] = [custom_target, alias_target] + if kwargs['install']: + res.append(state.backend.get_executable_serialisation(command + t_args, tag='doc')) + return ModuleReturnValue(custom_target, res) + + def _get_build_args(self, c_args: T.List[str], inc_dirs: T.List[T.Union[str, build.IncludeDirs]], + deps: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]], + state: 'ModuleState', + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes']]) -> T.Tuple[ + T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: + args: T.List[str] = [] + cflags = c_args.copy() + deps_cflags, internal_ldflags, external_ldflags, _gi_includes, new_depends = \ + self._get_dependencies_flags(deps, state, depends, include_rpath=True) + + cflags.extend(deps_cflags) + cflags.extend(state.get_include_args(inc_dirs)) + ldflags: T.List[str] = [] + ldflags.extend(internal_ldflags) + ldflags.extend(external_ldflags) + + cflags.extend(state.environment.coredata.get_external_args(MachineChoice.HOST, 'c')) + ldflags.extend(state.environment.coredata.get_external_link_args(MachineChoice.HOST, 'c')) + compiler = state.environment.coredata.compilers[MachineChoice.HOST]['c'] + + compiler_flags = self._get_langs_compilers_flags(state, [('c', compiler)]) + cflags.extend(compiler_flags[0]) + ldflags.extend(compiler_flags[1]) + ldflags.extend(compiler_flags[2]) + if compiler: + args += ['--cc=%s' % join_args(compiler.get_exelist())] + args += ['--ld=%s' % join_args(compiler.get_linker_exelist())] + if cflags: + args += ['--cflags=%s' % join_args(cflags)] + if ldflags: + args += ['--ldflags=%s' % join_args(ldflags)] + + return args, new_depends + + @noKwargs + @typed_pos_args('gnome.gtkdoc_html_dir', str) + def gtkdoc_html_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> str: + return os.path.join('share/gtk-doc/html', args[0]) + + @typed_pos_args('gnome.gdbus_codegen', str, optargs=[(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)]) + @typed_kwargs( + 'gnome.gdbus_codegen', + _BUILD_BY_DEFAULT.evolve(since='0.40.0'), + SOURCES_KW.evolve(since='0.46.0'), + KwargInfo('extra_args', ContainerTypeInfo(list, str), since='0.47.0', default=[], listify=True), + KwargInfo('interface_prefix', (str, NoneType)), + KwargInfo('namespace', (str, NoneType)), + KwargInfo('object_manager', bool, default=False), + KwargInfo( + 'annotations', ContainerTypeInfo(list, (list, str)), + default=[], + validator=annotations_validator, + convertor=lambda x: [x] if x and isinstance(x[0], str) else x, + ), + KwargInfo('install_header', bool, default=False, since='0.46.0'), + KwargInfo('docbook', (str, NoneType)), + KwargInfo( + 'autocleanup', str, default='default', since='0.47.0', + validator=in_set_validator({'all', 'none', 'objects'})), + INSTALL_DIR_KW.evolve(since='0.46.0') + ) + def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Union['FileOrString', build.GeneratedTypes]]], + kwargs: 'GdbusCodegen') -> ModuleReturnValue: + namebase = args[0] + xml_files: T.List[T.Union['FileOrString', build.GeneratedTypes]] = [args[1]] if args[1] else [] + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'gdbus-codegen')] + cmd.extend(kwargs['extra_args']) + + # Autocleanup supported? + glib_version = self._get_native_glib_version(state) + if not mesonlib.version_compare(glib_version, '>= 2.49.1'): + # Warn if requested, silently disable if not + if kwargs['autocleanup'] != 'default': + mlog.warning(f'Glib version ({glib_version}) is too old to support the \'autocleanup\' ' + 'kwarg, need 2.49.1 or newer') + else: + # Handle legacy glib versions that don't have autocleanup + ac = kwargs['autocleanup'] + if ac == 'default': + ac = 'all' + cmd.extend(['--c-generate-autocleanup', ac]) + + if kwargs['interface_prefix'] is not None: + cmd.extend(['--interface-prefix', kwargs['interface_prefix']]) + if kwargs['namespace'] is not None: + cmd.extend(['--c-namespace', kwargs['namespace']]) + if kwargs['object_manager']: + cmd.extend(['--c-generate-object-manager']) + xml_files.extend(kwargs['sources']) + build_by_default = kwargs['build_by_default'] + + # Annotations are a bit ugly in that they are a list of lists of strings... + for annot in kwargs['annotations']: + cmd.append('--annotate') + cmd.extend(annot) + + targets = [] + install_header = kwargs['install_header'] + install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')) + assert isinstance(install_dir, str), 'for mypy' + + output = namebase + '.c' + # Added in https://gitlab.gnome.org/GNOME/glib/commit/e4d68c7b3e8b01ab1a4231bf6da21d045cb5a816 (2.55.2) + # Fixed in https://gitlab.gnome.org/GNOME/glib/commit/cd1f82d8fc741a2203582c12cc21b4dacf7e1872 (2.56.2) + if mesonlib.version_compare(glib_version, '>= 2.56.2'): + c_cmd = cmd + ['--body', '--output', '@OUTPUT@', '@INPUT@'] + else: + if kwargs['docbook'] is not None: + docbook = kwargs['docbook'] + + cmd += ['--generate-docbook', docbook] + + # https://git.gnome.org/browse/glib/commit/?id=ee09bb704fe9ccb24d92dd86696a0e6bb8f0dc1a + if mesonlib.version_compare(glib_version, '>= 2.51.3'): + cmd += ['--output-directory', '@OUTDIR@', '--generate-c-code', namebase, '@INPUT@'] + else: + self._print_gdbus_warning() + cmd += ['--generate-c-code', '@OUTDIR@/' + namebase, '@INPUT@'] + c_cmd = cmd + + cfile_custom_target = build.CustomTarget( + output, + state.subdir, + state.subproject, + state.environment, + c_cmd, + xml_files, + [output], + build_by_default=build_by_default, + ) + targets.append(cfile_custom_target) + + output = namebase + '.h' + if mesonlib.version_compare(glib_version, '>= 2.56.2'): + hfile_cmd = cmd + ['--header', '--output', '@OUTPUT@', '@INPUT@'] + depends = [] + else: + hfile_cmd = cmd + depends = [cfile_custom_target] + + hfile_custom_target = build.CustomTarget( + output, + state.subdir, + state.subproject, + state.environment, + hfile_cmd, + xml_files, + [output], + build_by_default=build_by_default, + extra_depends=depends, + install=install_header, + install_dir=[install_dir], + install_tag=['devel'], + ) + targets.append(hfile_custom_target) + + if kwargs['docbook'] is not None: + docbook = kwargs['docbook'] + # The docbook output is always ${docbook}-${name_of_xml_file} + output = namebase + '-docbook' + outputs = [] + for f in xml_files: + outputs.append('{}-{}'.format(docbook, os.path.basename(str(f)))) + + if mesonlib.version_compare(glib_version, '>= 2.56.2'): + docbook_cmd = cmd + ['--output-directory', '@OUTDIR@', '--generate-docbook', docbook, '@INPUT@'] + depends = [] + else: + docbook_cmd = cmd + depends = [cfile_custom_target] + + docbook_custom_target = build.CustomTarget( + output, + state.subdir, + state.subproject, + state.environment, + docbook_cmd, + xml_files, + outputs, + build_by_default=build_by_default, + extra_depends=depends, + ) + targets.append(docbook_custom_target) + + return ModuleReturnValue(targets, targets) + + @typed_pos_args('gnome.mkenums', str) + @typed_kwargs( + 'gnome.mkenums', + *_MK_ENUMS_COMMON_KWS, + DEPENDS_KW, + KwargInfo('c_template', (str, mesonlib.File, NoneType)), + KwargInfo('h_template', (str, mesonlib.File, NoneType)), + KwargInfo('comments', (str, NoneType)), + KwargInfo('eprod', (str, NoneType)), + KwargInfo('fhead', (str, NoneType)), + KwargInfo('fprod', (str, NoneType)), + KwargInfo('ftail', (str, NoneType)), + KwargInfo('vhead', (str, NoneType)), + KwargInfo('vprod', (str, NoneType)), + KwargInfo('vtail', (str, NoneType)), + ) + def mkenums(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEnums') -> ModuleReturnValue: + basename = args[0] + + c_template = kwargs['c_template'] + if isinstance(c_template, mesonlib.File): + c_template = c_template.absolute_path(state.environment.source_dir, state.environment.build_dir) + h_template = kwargs['h_template'] + if isinstance(h_template, mesonlib.File): + h_template = h_template.absolute_path(state.environment.source_dir, state.environment.build_dir) + + cmd: T.List[str] = [] + known_kwargs = ['comments', 'eprod', 'fhead', 'fprod', 'ftail', + 'identifier_prefix', 'symbol_prefix', + 'vhead', 'vprod', 'vtail'] + for arg in known_kwargs: + # mypy can't figure this out + if kwargs[arg]: # type: ignore + cmd += ['--' + arg.replace('_', '-'), kwargs[arg]] # type: ignore + + targets: T.List[CustomTarget] = [] + + h_target: T.Optional[CustomTarget] = None + if h_template is not None: + h_output = os.path.basename(os.path.splitext(h_template)[0]) + # We always set template as the first element in the source array + # so --template consumes it. + h_cmd = cmd + ['--template', '@INPUT@'] + h_sources: T.List[T.Union[FileOrString, 'build.GeneratedTypes']] = [h_template] + h_sources.extend(kwargs['sources']) + h_target = self._make_mkenum_impl( + state, h_sources, h_output, h_cmd, install=kwargs['install_header'], + install_dir=kwargs['install_dir']) + targets.append(h_target) + + if c_template is not None: + c_output = os.path.basename(os.path.splitext(c_template)[0]) + # We always set template as the first element in the source array + # so --template consumes it. + c_cmd = cmd + ['--template', '@INPUT@'] + c_sources: T.List[T.Union[FileOrString, 'build.GeneratedTypes']] = [c_template] + c_sources.extend(kwargs['sources']) + + depends = kwargs['depends'].copy() + if h_target is not None: + depends.append(h_target) + c_target = self._make_mkenum_impl( + state, c_sources, c_output, c_cmd, depends=depends) + targets.insert(0, c_target) + + if c_template is None and h_template is None: + generic_cmd = cmd + ['@INPUT@'] + target = self._make_mkenum_impl( + state, kwargs['sources'], basename, generic_cmd, + install=kwargs['install_header'], + install_dir=kwargs['install_dir']) + return ModuleReturnValue(target, [target]) + else: + return ModuleReturnValue(targets, targets) + + @FeatureNew('gnome.mkenums_simple', '0.42.0') + @typed_pos_args('gnome.mkenums_simple', str) + @typed_kwargs( + 'gnome.mkenums_simple', + *_MK_ENUMS_COMMON_KWS, + KwargInfo('header_prefix', str, default=''), + KwargInfo('function_prefix', str, default=''), + KwargInfo('body_prefix', str, default=''), + KwargInfo('decorator', str, default=''), + ) + def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEnumsSimple') -> ModuleReturnValue: + hdr_filename = f'{args[0]}.h' + body_filename = f'{args[0]}.c' + + header_prefix = kwargs['header_prefix'] + decl_decorator = kwargs['decorator'] + func_prefix = kwargs['function_prefix'] + body_prefix = kwargs['body_prefix'] + + cmd: T.List[str] = [] + if kwargs['identifier_prefix']: + cmd.extend(['--identifier-prefix', kwargs['identifier_prefix']]) + if kwargs['symbol_prefix']: + cmd.extend(['--symbol-prefix', kwargs['symbol_prefix']]) + + c_cmd = cmd.copy() + # Maybe we should write our own template files into the build dir + # instead, but that seems like much more work, nice as it would be. + fhead = '' + if body_prefix != '': + fhead += '%s\n' % body_prefix + fhead += '#include "%s"\n' % hdr_filename + for hdr in kwargs['sources']: + fhead += '#include "{}"\n'.format(os.path.basename(str(hdr))) + fhead += textwrap.dedent( + ''' + #define C_ENUM(v) ((gint) v) + #define C_FLAGS(v) ((guint) v) + ''') + c_cmd.extend(['--fhead', fhead]) + + c_cmd.append('--fprod') + c_cmd.append(textwrap.dedent( + ''' + /* enumerations from "@basename@" */ + ''')) + + c_cmd.append('--vhead') + c_cmd.append(textwrap.dedent( + f''' + GType + {func_prefix}@enum_name@_get_type (void) + {{ + static gsize gtype_id = 0; + static const G@Type@Value values[] = {{''')) + + c_cmd.extend(['--vprod', ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },']) + + c_cmd.append('--vtail') + c_cmd.append(textwrap.dedent( + ''' { 0, NULL, NULL } + }; + if (g_once_init_enter (>ype_id)) { + GType new_type = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (>ype_id, new_type); + } + return (GType) gtype_id; + }''')) + c_cmd.append('@INPUT@') + + c_file = self._make_mkenum_impl(state, kwargs['sources'], body_filename, c_cmd) + + # .h file generation + h_cmd = cmd.copy() + + h_cmd.append('--fhead') + h_cmd.append(textwrap.dedent( + f'''#pragma once + + #include + {header_prefix} + + G_BEGIN_DECLS + ''')) + + h_cmd.append('--fprod') + h_cmd.append(textwrap.dedent( + ''' + /* enumerations from "@basename@" */ + ''')) + + h_cmd.append('--vhead') + h_cmd.append(textwrap.dedent( + f''' + {decl_decorator} + GType {func_prefix}@enum_name@_get_type (void); + #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({func_prefix}@enum_name@_get_type())''')) + + h_cmd.append('--ftail') + h_cmd.append(textwrap.dedent( + ''' + G_END_DECLS''')) + h_cmd.append('@INPUT@') + + h_file = self._make_mkenum_impl( + state, kwargs['sources'], hdr_filename, h_cmd, + install=kwargs['install_header'], + install_dir=kwargs['install_dir']) + + return ModuleReturnValue([c_file, h_file], [c_file, h_file]) + + def _make_mkenum_impl( + self, + state: 'ModuleState', + sources: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]], + output: str, + cmd: T.List[str], + *, + install: bool = False, + install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None, + depends: T.Optional[T.Sequence[T.Union[CustomTarget, CustomTargetIndex, BuildTarget]]] = None + ) -> build.CustomTarget: + real_cmd: T.List[T.Union[str, 'ToolType']] = [self._find_tool(state, 'glib-mkenums')] + real_cmd.extend(cmd) + _install_dir = install_dir or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')) + assert isinstance(_install_dir, str), 'for mypy' + + return build.CustomTarget( + output, + state.subdir, + state.subproject, + state.environment, + real_cmd, + sources, + [output], + capture=True, + install=install, + install_dir=[_install_dir], + install_tag=['devel'], + extra_depends=depends, + # https://github.com/mesonbuild/meson/issues/973 + absolute_paths=True, + ) + + @typed_pos_args('gnome.genmarshal', str) + @typed_kwargs( + 'gnome.genmarshal', + DEPEND_FILES_KW.evolve(since='0.61.0'), + DEPENDS_KW.evolve(since='0.61.0'), + INSTALL_KW.evolve(name='install_header'), + INSTALL_DIR_KW, + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('internal', bool, default=False), + KwargInfo('nostdinc', bool, default=False), + KwargInfo('prefix', (str, NoneType)), + KwargInfo('skip_source', bool, default=False), + KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File), allow_empty=False), listify=True, required=True), + KwargInfo('stdinc', bool, default=False), + KwargInfo('valist_marshallers', bool, default=False), + ) + def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarshal') -> ModuleReturnValue: + output = args[0] + sources = kwargs['sources'] + + new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3') + + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-genmarshal')] + if kwargs['prefix']: + cmd.extend(['--prefix', kwargs['prefix']]) + if kwargs['extra_args']: + if new_genmarshal: + cmd.extend(kwargs['extra_args']) + else: + mlog.warning('The current version of GLib does not support extra arguments \n' + 'for glib-genmarshal. You need at least GLib 2.53.3. See ', + mlog.bold('https://github.com/mesonbuild/meson/pull/2049'), + once=True, fatal=False) + for k in ['internal', 'nostdinc', 'skip_source', 'stdinc', 'valist_marshallers']: + # Mypy can't figure out that this is correct + if kwargs[k]: # type: ignore + cmd.append(f'--{k.replace("_", "-")}') + + install_header = kwargs['install_header'] + capture = False + + # https://github.com/GNOME/glib/commit/0fbc98097fac4d3e647684f344e508abae109fdf + if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.51.0'): + cmd += ['--output', '@OUTPUT@'] + else: + capture = True + + header_file = output + '.h' + h_cmd = cmd + ['--header', '@INPUT@'] + if new_genmarshal: + h_cmd += ['--pragma-once'] + header = build.CustomTarget( + output + '_h', + state.subdir, + state.subproject, + state.environment, + h_cmd, + sources, + [header_file], + install=install_header, + install_dir=[kwargs['install_dir']] if kwargs['install_dir'] else [], + install_tag=['devel'], + capture=capture, + depend_files=kwargs['depend_files'], + ) + + c_cmd = cmd + ['--body', '@INPUT@'] + extra_deps: T.List[build.CustomTarget] = [] + if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.4'): + # Silence any warnings about missing prototypes + c_cmd += ['--include-header', header_file] + extra_deps.append(header) + body = build.CustomTarget( + output + '_c', + state.subdir, + state.subproject, + state.environment, + c_cmd, + sources, + [f'{output}.c'], + capture=capture, + depend_files=kwargs['depend_files'], + extra_depends=extra_deps, + ) + + rv = [body, header] + return ModuleReturnValue(rv, rv) + + def _extract_vapi_packages(self, state: 'ModuleState', packages: T.List[T.Union[InternalDependency, str]], + ) -> T.Tuple[T.List[str], T.List[VapiTarget], T.List[str], T.List[str], T.List[str]]: + ''' + Packages are special because we need to: + - Get a list of packages for the .deps file + - Get a list of depends for any VapiTargets + - Get package name from VapiTargets + - Add include dirs for any VapiTargets + ''' + if not packages: + return [], [], [], [], [] + vapi_depends: T.List[VapiTarget] = [] + vapi_packages: T.List[str] = [] + vapi_includes: T.List[str] = [] + vapi_args: T.List[str] = [] + remaining_args = [] + for arg in packages: + if isinstance(arg, InternalDependency): + targets = [t for t in arg.sources if isinstance(t, VapiTarget)] + for target in targets: + srcdir = os.path.join(state.environment.get_source_dir(), + target.get_subdir()) + outdir = os.path.join(state.environment.get_build_dir(), + target.get_subdir()) + outfile = target.get_outputs()[0][:-5] # Strip .vapi + vapi_args.append('--vapidir=' + outdir) + vapi_args.append('--girdir=' + outdir) + vapi_args.append('--pkg=' + outfile) + vapi_depends.append(target) + vapi_packages.append(outfile) + vapi_includes.append(srcdir) + else: + assert isinstance(arg, str), 'for mypy' + vapi_args.append(f'--pkg={arg}') + vapi_packages.append(arg) + remaining_args.append(arg) + + # TODO: this is supposed to take IncludeDirs, but it never worked + return vapi_args, vapi_depends, vapi_packages, vapi_includes, remaining_args + + def _generate_deps(self, state: 'ModuleState', library: str, packages: T.List[str], install_dir: str) -> build.Data: + outdir = state.environment.scratch_dir + fname = os.path.join(outdir, library + '.deps') + with open(fname, 'w', encoding='utf-8') as ofile: + for package in packages: + ofile.write(package + '\n') + return build.Data([mesonlib.File(True, outdir, fname)], install_dir, install_dir, mesonlib.FileMode(), state.subproject) + + def _get_vapi_link_with(self, target: build.CustomTarget) -> T.List[build.LibTypes]: + link_with: T.List[build.LibTypes] = [] + for dep in target.get_target_dependencies(): + if isinstance(dep, build.SharedLibrary): + link_with.append(dep) + elif isinstance(dep, GirTarget): + link_with += self._get_vapi_link_with(dep) + return link_with + + @typed_pos_args('gnome.generate_vapi', str) + @typed_kwargs( + 'gnome.generate_vapi', + INSTALL_KW, + INSTALL_DIR_KW, + KwargInfo( + 'sources', + ContainerTypeInfo(list, (str, GirTarget), allow_empty=False), + listify=True, + required=True, + ), + KwargInfo('vapi_dirs', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('metadata_dirs', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('gir_dirs', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('packages', ContainerTypeInfo(list, (str, InternalDependency)), listify=True, default=[]), + ) + def generate_vapi(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenerateVapi') -> ModuleReturnValue: + created_values: T.List[T.Union[Dependency, build.Data]] = [] + library = args[0] + build_dir = os.path.join(state.environment.get_build_dir(), state.subdir) + source_dir = os.path.join(state.environment.get_source_dir(), state.subdir) + pkg_cmd, vapi_depends, vapi_packages, vapi_includes, packages = self._extract_vapi_packages(state, kwargs['packages']) + cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] + cmd = [state.find_program('vapigen'), '--quiet', f'--library={library}', f'--directory={build_dir}'] + cmd.extend([f'--vapidir={d}' for d in kwargs['vapi_dirs']]) + cmd.extend([f'--metadatadir={d}' for d in kwargs['metadata_dirs']]) + cmd.extend([f'--girdir={d}' for d in kwargs['gir_dirs']]) + cmd += pkg_cmd + cmd += ['--metadatadir=' + source_dir] + + inputs = kwargs['sources'] + + link_with: T.List[build.LibTypes] = [] + for i in inputs: + if isinstance(i, str): + cmd.append(os.path.join(source_dir, i)) + elif isinstance(i, GirTarget): + link_with += self._get_vapi_link_with(i) + subdir = os.path.join(state.environment.get_build_dir(), + i.get_subdir()) + gir_file = os.path.join(subdir, i.get_outputs()[0]) + cmd.append(gir_file) + + vapi_output = library + '.vapi' + datadir = state.environment.coredata.get_option(mesonlib.OptionKey('datadir')) + assert isinstance(datadir, str), 'for mypy' + install_dir = kwargs['install_dir'] or os.path.join(datadir, 'vala', 'vapi') + + if kwargs['install']: + # We shouldn't need this locally but we install it + deps_target = self._generate_deps(state, library, vapi_packages, install_dir) + created_values.append(deps_target) + vapi_target = VapiTarget( + vapi_output, + state.subdir, + state.subproject, + state.environment, + command=cmd, + sources=inputs, + outputs=[vapi_output], + extra_depends=vapi_depends, + install=kwargs['install'], + install_dir=[install_dir], + install_tag=['devel'], + ) + + # So to try our best to get this to just work we need: + # - link with the correct library + # - include the vapi and dependent vapi files in sources + # - add relevant directories to include dirs + incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)] + sources = [vapi_target] + vapi_depends + rv = InternalDependency(None, incs, [], [], link_with, [], sources, [], [], {}, [], [], []) + created_values.append(rv) + return ModuleReturnValue(rv, created_values) + +def initialize(interp: 'Interpreter') -> GnomeModule: + mod = GnomeModule(interp) + mod.interpreter.append_holder_map(GResourceTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(GResourceHeaderTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(GirTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(TypelibTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(VapiTarget, interpreter.CustomTargetHolder) + return mod diff --git a/devtools/meson/mesonbuild/modules/hotdoc.py b/devtools/meson/mesonbuild/modules/hotdoc.py new file mode 100644 index 0000000..ad5ae30 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/hotdoc.py @@ -0,0 +1,471 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +'''This module provides helper functions for generating documentation using hotdoc''' + +import os +import subprocess + +from mesonbuild import mesonlib +from mesonbuild import mlog, build +from mesonbuild.coredata import MesonException +from . import ModuleReturnValue, ModuleInfo +from . import ExtensionModule +from ..dependencies import Dependency, InternalDependency +from ..interpreterbase import ( + InvalidArguments, noPosargs, noKwargs, typed_kwargs, FeatureDeprecated, + ContainerTypeInfo, KwargInfo, typed_pos_args +) +from ..interpreter import CustomTargetHolder +from ..interpreter.type_checking import NoneType +from ..programs import ExternalProgram + + +def ensure_list(value): + if not isinstance(value, list): + return [value] + return value + + +MIN_HOTDOC_VERSION = '0.8.100' + +file_types = (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex) + + +class HotdocTargetBuilder: + + def __init__(self, name, state, hotdoc, interpreter, kwargs): + self.hotdoc = hotdoc + self.build_by_default = kwargs.pop('build_by_default', False) + self.kwargs = kwargs + self.name = name + self.state = state + self.interpreter = interpreter + self.include_paths = mesonlib.OrderedSet() + + self.builddir = state.environment.get_build_dir() + self.sourcedir = state.environment.get_source_dir() + self.subdir = state.subdir + self.build_command = state.environment.get_build_command() + + self.cmd = ['conf', '--project-name', name, "--disable-incremental-build", + '--output', os.path.join(self.builddir, self.subdir, self.name + '-doc')] + + self._extra_extension_paths = set() + self.extra_assets = set() + self.extra_depends = [] + self._subprojects = [] + + def process_known_arg(self, option, argname=None, value_processor=None): + if not argname: + argname = option.strip("-").replace("-", "_") + + value = self.kwargs.pop(argname) + if value is not None and value_processor: + value = value_processor(value) + + self.set_arg_value(option, value) + + def set_arg_value(self, option, value): + if value is None: + return + + if isinstance(value, bool): + if value: + self.cmd.append(option) + elif isinstance(value, list): + # Do not do anything on empty lists + if value: + # https://bugs.python.org/issue9334 (from 2010 :( ) + # The syntax with nargs=+ is inherently ambiguous + # A workaround for this case is to simply prefix with a space + # every value starting with a dash + escaped_value = [] + for e in value: + if isinstance(e, str) and e.startswith('-'): + escaped_value += [' %s' % e] + else: + escaped_value += [e] + if option: + self.cmd.extend([option] + escaped_value) + else: + self.cmd.extend(escaped_value) + else: + # argparse gets confused if value(s) start with a dash. + # When an option expects a single value, the unambiguous way + # to specify it is with = + if isinstance(value, str): + self.cmd.extend([f'{option}={value}']) + else: + self.cmd.extend([option, value]) + + def check_extra_arg_type(self, arg, value): + if isinstance(value, list): + for v in value: + self.check_extra_arg_type(arg, v) + return + + valid_types = (str, bool, mesonlib.File, build.IncludeDirs, build.CustomTarget, build.CustomTargetIndex, build.BuildTarget) + if not isinstance(value, valid_types): + raise InvalidArguments('Argument "{}={}" should be of type: {}.'.format( + arg, value, [t.__name__ for t in valid_types])) + + def process_extra_args(self): + for arg, value in self.kwargs.items(): + option = "--" + arg.replace("_", "-") + self.check_extra_arg_type(arg, value) + self.set_arg_value(option, value) + + def get_value(self, types, argname, default=None, value_processor=None, + mandatory=False, force_list=False): + if not isinstance(types, list): + types = [types] + try: + uvalue = value = self.kwargs.pop(argname) + if value_processor: + value = value_processor(value) + + for t in types: + if isinstance(value, t): + if force_list and not isinstance(value, list): + return [value], uvalue + return value, uvalue + raise MesonException(f"{argname} field value {value} is not valid," + f" valid types are {types}") + except KeyError: + if mandatory: + raise MesonException(f"{argname} mandatory field not found") + + if default is not None: + return default, default + + return None, None + + def add_extension_paths(self, paths): + for path in paths: + if path in self._extra_extension_paths: + continue + + self._extra_extension_paths.add(path) + self.cmd.extend(["--extra-extension-path", path]) + + def replace_dirs_in_string(self, string): + return string.replace("@SOURCE_ROOT@", self.sourcedir).replace("@BUILD_ROOT@", self.builddir) + + def process_gi_c_source_roots(self): + if self.hotdoc.run_hotdoc(['--has-extension=gi-extension']) != 0: + return + + value = self.kwargs.pop('gi_c_source_roots') + value.extend([ + os.path.join(self.sourcedir, self.state.root_subdir), + os.path.join(self.builddir, self.state.root_subdir) + ]) + + self.cmd += ['--gi-c-source-roots'] + value + + def process_dependencies(self, deps): + cflags = set() + for dep in mesonlib.listify(ensure_list(deps)): + if isinstance(dep, InternalDependency): + inc_args = self.state.get_include_args(dep.include_directories) + cflags.update([self.replace_dirs_in_string(x) + for x in inc_args]) + cflags.update(self.process_dependencies(dep.libraries)) + cflags.update(self.process_dependencies(dep.sources)) + cflags.update(self.process_dependencies(dep.ext_deps)) + elif isinstance(dep, Dependency): + cflags.update(dep.get_compile_args()) + elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): + self.extra_depends.append(dep) + for incd in dep.get_include_dirs(): + cflags.update(incd.get_incdirs()) + elif isinstance(dep, HotdocTarget): + # Recurse in hotdoc target dependencies + self.process_dependencies(dep.get_target_dependencies()) + self._subprojects.extend(dep.subprojects) + self.process_dependencies(dep.subprojects) + self.include_paths.add(os.path.join(self.builddir, dep.hotdoc_conf.subdir)) + self.cmd += ['--extra-assets=' + p for p in dep.extra_assets] + self.add_extension_paths(dep.extra_extension_paths) + elif isinstance(dep, (build.CustomTarget, build.BuildTarget)): + self.extra_depends.append(dep) + elif isinstance(dep, build.CustomTargetIndex): + self.extra_depends.append(dep.target) + + return [f.strip('-I') for f in cflags] + + def process_extra_assets(self): + self._extra_assets = self.kwargs.pop('extra_assets') + + for assets_path in self._extra_assets: + self.cmd.extend(["--extra-assets", assets_path]) + + def process_subprojects(self): + value = self.kwargs.pop('subprojects') + + self.process_dependencies(value) + self._subprojects.extend(value) + + def flatten_config_command(self): + cmd = [] + for arg in mesonlib.listify(self.cmd, flatten=True): + if isinstance(arg, mesonlib.File): + arg = arg.absolute_path(self.state.environment.get_source_dir(), + self.state.environment.get_build_dir()) + elif isinstance(arg, build.IncludeDirs): + for inc_dir in arg.get_incdirs(): + cmd.append(os.path.join(self.sourcedir, arg.get_curdir(), inc_dir)) + cmd.append(os.path.join(self.builddir, arg.get_curdir(), inc_dir)) + + continue + elif isinstance(arg, (build.BuildTarget, build.CustomTarget)): + self.extra_depends.append(arg) + arg = self.interpreter.backend.get_target_filename_abs(arg) + elif isinstance(arg, build.CustomTargetIndex): + self.extra_depends.append(arg.target) + arg = self.interpreter.backend.get_target_filename_abs(arg) + + cmd.append(arg) + + return cmd + + def generate_hotdoc_config(self): + cwd = os.path.abspath(os.curdir) + ncwd = os.path.join(self.sourcedir, self.subdir) + mlog.log('Generating Hotdoc configuration for: ', mlog.bold(self.name)) + os.chdir(ncwd) + if self.hotdoc.run_hotdoc(self.flatten_config_command()) != 0: + raise MesonException('hotdoc failed to configure') + os.chdir(cwd) + + def ensure_file(self, value): + if isinstance(value, list): + res = [] + for val in value: + res.append(self.ensure_file(val)) + return res + + if isinstance(value, str): + return mesonlib.File.from_source_file(self.sourcedir, self.subdir, value) + + return value + + def ensure_dir(self, value): + if os.path.isabs(value): + _dir = value + else: + _dir = os.path.join(self.sourcedir, self.subdir, value) + + if not os.path.isdir(_dir): + raise InvalidArguments(f'"{_dir}" is not a directory.') + + return os.path.relpath(_dir, os.path.join(self.builddir, self.subdir)) + + def check_forbidden_args(self): + for arg in ['conf_file']: + if arg in self.kwargs: + raise InvalidArguments(f'Argument "{arg}" is forbidden.') + + def make_targets(self): + self.check_forbidden_args() + self.process_known_arg("--index", value_processor=self.ensure_file) + self.process_known_arg("--project-version") + self.process_known_arg("--sitemap", value_processor=self.ensure_file) + self.process_known_arg("--html-extra-theme", value_processor=self.ensure_dir) + self.include_paths.update(self.ensure_dir(v) for v in self.kwargs.pop('include_paths')) + self.process_known_arg('--c-include-directories', argname="dependencies", value_processor=self.process_dependencies) + self.process_gi_c_source_roots() + self.process_extra_assets() + self.add_extension_paths(self.kwargs.pop('extra_extension_paths')) + self.process_subprojects() + self.extra_depends.extend(self.kwargs.pop('depends')) + + install = self.kwargs.pop('install') + self.process_extra_args() + + fullname = self.name + '-doc' + hotdoc_config_name = fullname + '.json' + hotdoc_config_path = os.path.join( + self.builddir, self.subdir, hotdoc_config_name) + with open(hotdoc_config_path, 'w', encoding='utf-8') as f: + f.write('{}') + + self.cmd += ['--conf-file', hotdoc_config_path] + self.include_paths.add(os.path.join(self.builddir, self.subdir)) + self.include_paths.add(os.path.join(self.sourcedir, self.subdir)) + + depfile = os.path.join(self.builddir, self.subdir, self.name + '.deps') + self.cmd += ['--deps-file-dest', depfile] + + for path in self.include_paths: + self.cmd.extend(['--include-path', path]) + + if self.state.environment.coredata.get_option(mesonlib.OptionKey('werror', subproject=self.state.subproject)): + self.cmd.append('--fatal-warnings') + self.generate_hotdoc_config() + + target_cmd = self.build_command + ["--internal", "hotdoc"] + \ + self.hotdoc.get_command() + ['run', '--conf-file', hotdoc_config_name] + \ + ['--builddir', os.path.join(self.builddir, self.subdir)] + + target = HotdocTarget(fullname, + subdir=self.subdir, + subproject=self.state.subproject, + environment=self.state.environment, + hotdoc_conf=mesonlib.File.from_built_file( + self.subdir, hotdoc_config_name), + extra_extension_paths=self._extra_extension_paths, + extra_assets=self._extra_assets, + subprojects=self._subprojects, + command=target_cmd, + extra_depends=self.extra_depends, + outputs=[fullname], + sources=[], + depfile=os.path.basename(depfile), + build_by_default=self.build_by_default) + + install_script = None + if install: + datadir = os.path.join(self.state.get_option('prefix'), self.state.get_option('datadir')) + devhelp = self.kwargs.get('devhelp_activate', False) + if not isinstance(devhelp, bool): + FeatureDeprecated.single_use('hotdoc.generate_doc() devhelp_activate must be boolean', '1.1.0', self.state.subproject) + devhelp = False + if devhelp: + install_from = os.path.join(fullname, 'devhelp') + install_to = os.path.join(datadir, 'devhelp') + else: + install_from = os.path.join(fullname, 'html') + install_to = os.path.join(datadir, 'doc', self.name, 'html') + + install_script = self.state.backend.get_executable_serialisation(self.build_command + [ + "--internal", "hotdoc", + "--install", install_from, + "--docdir", install_to, + '--name', self.name, + '--builddir', os.path.join(self.builddir, self.subdir)] + + self.hotdoc.get_command() + + ['run', '--conf-file', hotdoc_config_name]) + install_script.tag = 'doc' + + return (target, install_script) + + +class HotdocTargetHolder(CustomTargetHolder): + def __init__(self, target, interp): + super().__init__(target, interp) + self.methods.update({'config_path': self.config_path_method}) + + @noPosargs + @noKwargs + def config_path_method(self, *args, **kwargs): + conf = self.held_object.hotdoc_conf.absolute_path(self.interpreter.environment.source_dir, + self.interpreter.environment.build_dir) + return conf + + +class HotdocTarget(build.CustomTarget): + def __init__(self, name, subdir, subproject, hotdoc_conf, extra_extension_paths, extra_assets, + subprojects, environment, **kwargs): + super().__init__(name, subdir, subproject, environment, **kwargs, absolute_paths=True) + self.hotdoc_conf = hotdoc_conf + self.extra_extension_paths = extra_extension_paths + self.extra_assets = extra_assets + self.subprojects = subprojects + + def __getstate__(self): + # Make sure we do not try to pickle subprojects + res = self.__dict__.copy() + res['subprojects'] = [] + + return res + + +class HotDocModule(ExtensionModule): + + INFO = ModuleInfo('hotdoc', '0.48.0') + + def __init__(self, interpreter): + super().__init__(interpreter) + self.hotdoc = ExternalProgram('hotdoc') + if not self.hotdoc.found(): + raise MesonException('hotdoc executable not found') + version = self.hotdoc.get_version(interpreter) + if not mesonlib.version_compare(version, f'>={MIN_HOTDOC_VERSION}'): + raise MesonException(f'hotdoc {MIN_HOTDOC_VERSION} required but not found.)') + + def run_hotdoc(cmd): + return subprocess.run(self.hotdoc.get_command() + cmd, stdout=subprocess.DEVNULL).returncode + + self.hotdoc.run_hotdoc = run_hotdoc + self.methods.update({ + 'has_extensions': self.has_extensions, + 'generate_doc': self.generate_doc, + }) + + @noKwargs + @typed_pos_args('hotdoc.has_extensions', varargs=str, min_varargs=1) + def has_extensions(self, state, args, kwargs): + return self.hotdoc.run_hotdoc([f'--has-extension={extension}' for extension in args[0]]) == 0 + + @typed_pos_args('hotdoc.generate_doc', str) + @typed_kwargs( + 'hotdoc.generate_doc', + KwargInfo('sitemap', file_types, required=True), + KwargInfo('index', file_types, required=True), + KwargInfo('project_version', str, required=True), + KwargInfo('html_extra_theme', (str, NoneType)), + KwargInfo('include_paths', ContainerTypeInfo(list, str), listify=True, default=[]), + # --c-include-directories + KwargInfo( + 'dependencies', + ContainerTypeInfo(list, (Dependency, build.StaticLibrary, build.SharedLibrary, + build.CustomTarget, build.CustomTargetIndex)), + listify=True, + default=[], + ), + KwargInfo( + 'depends', + ContainerTypeInfo(list, (build.CustomTarget, build.CustomTargetIndex)), + listify=True, + default=[], + since='0.64.1', + ), + KwargInfo('gi_c_source_roots', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('extra_assets', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('extra_extension_paths', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('subprojects', ContainerTypeInfo(list, HotdocTarget), listify=True, default=[]), + KwargInfo('install', bool, default=False), + allow_unknown=True + ) + def generate_doc(self, state, args, kwargs): + project_name = args[0] + if any(isinstance(x, (build.CustomTarget, build.CustomTargetIndex)) for x in kwargs['dependencies']): + FeatureDeprecated.single_use('hotdoc.generate_doc dependencies argument with custom_target', + '0.64.1', state.subproject, 'use `depends`', state.current_node) + builder = HotdocTargetBuilder(project_name, state, self.hotdoc, self.interpreter, kwargs) + target, install_script = builder.make_targets() + targets = [target] + if install_script: + targets.append(install_script) + + return ModuleReturnValue(targets[0], targets) + + +def initialize(interpreter): + mod = HotDocModule(interpreter) + mod.interpreter.append_holder_map(HotdocTarget, HotdocTargetHolder) + return mod diff --git a/devtools/meson/mesonbuild/modules/i18n.py b/devtools/meson/mesonbuild/modules/i18n.py new file mode 100644 index 0000000..11dd9ef --- /dev/null +++ b/devtools/meson/mesonbuild/modules/i18n.py @@ -0,0 +1,399 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from os import path +import typing as T + +from . import ExtensionModule, ModuleReturnValue, ModuleInfo +from .. import build +from .. import mesonlib +from .. import mlog +from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, INSTALL_TAG_KW, OUTPUT_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, in_set_validator +from ..interpreterbase import FeatureNew +from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args +from ..programs import ExternalProgram +from ..scripts.gettext import read_linguas + +if T.TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + + from . import ModuleState + from ..build import Target + from ..interpreter import Interpreter + from ..interpreterbase import TYPE_var + + class MergeFile(TypedDict): + + input: T.List[T.Union[ + str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, + build.ExtractedObjects, build.GeneratedList, ExternalProgram, + mesonlib.File]] + output: str + build_by_default: bool + install: bool + install_dir: T.Optional[str] + install_tag: T.Optional[str] + args: T.List[str] + data_dirs: T.List[str] + po_dir: str + type: Literal['xml', 'desktop'] + + class Gettext(TypedDict): + + args: T.List[str] + data_dirs: T.List[str] + install: bool + install_dir: T.Optional[str] + languages: T.List[str] + preset: T.Optional[str] + + class ItsJoinFile(TypedDict): + + input: T.List[T.Union[ + str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, + build.ExtractedObjects, build.GeneratedList, ExternalProgram, + mesonlib.File]] + output: str + build_by_default: bool + install: bool + install_dir: T.Optional[str] + install_tag: T.Optional[str] + its_files: T.List[str] + mo_targets: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]] + + +_ARGS: KwargInfo[T.List[str]] = KwargInfo( + 'args', + ContainerTypeInfo(list, str), + default=[], + listify=True, +) + +_DATA_DIRS: KwargInfo[T.List[str]] = KwargInfo( + 'data_dirs', + ContainerTypeInfo(list, str), + default=[], + listify=True +) + +PRESET_ARGS = { + 'glib': [ + '--from-code=UTF-8', + '--add-comments', + + # https://developer.gnome.org/glib/stable/glib-I18N.html + '--keyword=_', + '--keyword=N_', + '--keyword=C_:1c,2', + '--keyword=NC_:1c,2', + '--keyword=g_dcgettext:2', + '--keyword=g_dngettext:2,3', + '--keyword=g_dpgettext2:2c,3', + + '--flag=N_:1:pass-c-format', + '--flag=C_:2:pass-c-format', + '--flag=NC_:2:pass-c-format', + '--flag=g_dngettext:2:pass-c-format', + '--flag=g_strdup_printf:1:c-format', + '--flag=g_string_printf:2:c-format', + '--flag=g_string_append_printf:2:c-format', + '--flag=g_error_new:3:c-format', + '--flag=g_set_error:4:c-format', + '--flag=g_markup_printf_escaped:1:c-format', + '--flag=g_log:3:c-format', + '--flag=g_print:1:c-format', + '--flag=g_printerr:1:c-format', + '--flag=g_printf:1:c-format', + '--flag=g_fprintf:2:c-format', + '--flag=g_sprintf:2:c-format', + '--flag=g_snprintf:3:c-format', + ] +} + + +class I18nModule(ExtensionModule): + + INFO = ModuleInfo('i18n') + + def __init__(self, interpreter: 'Interpreter'): + super().__init__(interpreter) + self.methods.update({ + 'merge_file': self.merge_file, + 'gettext': self.gettext, + 'itstool_join': self.itstool_join, + }) + self.tools: T.Dict[str, T.Optional[T.Union[ExternalProgram, build.Executable]]] = { + 'itstool': None, + 'msgfmt': None, + 'msginit': None, + 'msgmerge': None, + 'xgettext': None, + } + + @staticmethod + def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]: + """Returns source directories of relative paths""" + src_dir = path.join(state.environment.get_source_dir(), state.subdir) + return [path.join(src_dir, d) for d in dirs] + + @FeatureNew('i18n.merge_file', '0.37.0') + @noPosargs + @typed_kwargs( + 'i18n.merge_file', + CT_BUILD_BY_DEFAULT, + CT_INPUT_KW, + KwargInfo('install_dir', (str, NoneType)), + INSTALL_TAG_KW, + OUTPUT_KW, + INSTALL_KW, + _ARGS.evolve(since='0.51.0'), + _DATA_DIRS.evolve(since='0.41.0'), + KwargInfo('po_dir', str, required=True), + KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})), + ) + def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue: + if self.tools['msgfmt'] is None or not self.tools['msgfmt'].found(): + self.tools['msgfmt'] = state.find_program('msgfmt', for_machine=mesonlib.MachineChoice.BUILD) + if isinstance(self.tools['msgfmt'], ExternalProgram): + try: + have_version = self.tools['msgfmt'].get_version() + except mesonlib.MesonException as e: + raise mesonlib.MesonException('i18n.merge_file requires GNU msgfmt') from e + want_version = '>=0.19' if kwargs['type'] == 'desktop' else '>=0.19.7' + if not mesonlib.version_compare(have_version, want_version): + msg = f'i18n.merge_file requires GNU msgfmt {want_version} to produce files of type: ' + kwargs['type'] + f' (got: {have_version})' + raise mesonlib.MesonException(msg) + podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir']) + + ddirs = self._get_data_dirs(state, kwargs['data_dirs']) + datadirs = '--datadirs=' + ':'.join(ddirs) if ddirs else None + + command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, + build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = [] + command.extend(state.environment.get_build_command()) + command.extend([ + '--internal', 'msgfmthelper', + '--msgfmt=' + self.tools['msgfmt'].get_path(), + ]) + if datadirs: + command.append(datadirs) + command.extend(['@INPUT@', '@OUTPUT@', kwargs['type'], podir]) + if kwargs['args']: + command.append('--') + command.extend(kwargs['args']) + + build_by_default = kwargs['build_by_default'] + if build_by_default is None: + build_by_default = kwargs['install'] + + install_tag = [kwargs['install_tag']] if kwargs['install_tag'] is not None else None + + ct = build.CustomTarget( + '', + state.subdir, + state.subproject, + state.environment, + command, + kwargs['input'], + [kwargs['output']], + build_by_default=build_by_default, + install=kwargs['install'], + install_dir=[kwargs['install_dir']] if kwargs['install_dir'] is not None else None, + install_tag=install_tag, + ) + + return ModuleReturnValue(ct, [ct]) + + @typed_pos_args('i18n.gettext', str) + @typed_kwargs( + 'i18n.gettext', + _ARGS, + _DATA_DIRS.evolve(since='0.36.0'), + INSTALL_KW.evolve(default=True), + INSTALL_DIR_KW.evolve(since='0.50.0'), + KwargInfo('languages', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo( + 'preset', + (str, NoneType), + validator=in_set_validator(set(PRESET_ARGS)), + since='0.37.0', + ), + ) + def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue: + for tool, strict in [('msgfmt', True), ('msginit', False), ('msgmerge', False), ('xgettext', False)]: + if self.tools[tool] is None: + self.tools[tool] = state.find_program(tool, required=False, for_machine=mesonlib.MachineChoice.BUILD) + # still not found? + if not self.tools[tool].found(): + if strict: + mlog.warning('Gettext not found, all translation (po) targets will be ignored.', + once=True, location=state.current_node) + return ModuleReturnValue(None, []) + else: + mlog.warning(f'{tool!r} not found, maintainer targets will not work', + once=True, fatal=False, location=state.current_node) + packagename = args[0] + pkg_arg = f'--pkgname={packagename}' + + languages = kwargs['languages'] + lang_arg = '--langs=' + '@@'.join(languages) if languages else None + + _datadirs = ':'.join(self._get_data_dirs(state, kwargs['data_dirs'])) + datadirs = f'--datadirs={_datadirs}' if _datadirs else None + + extra_args = kwargs['args'] + targets: T.List['Target'] = [] + gmotargets: T.List['build.CustomTarget'] = [] + + preset = kwargs['preset'] + if preset: + preset_args = PRESET_ARGS[preset] + extra_args = list(mesonlib.OrderedSet(preset_args + extra_args)) + + extra_arg = '--extra-args=' + '@@'.join(extra_args) if extra_args else None + + source_root = path.join(state.source_root, state.root_subdir) + subdir = path.relpath(state.subdir, start=state.root_subdir) if state.subdir else None + + potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg] + potargs.append(f'--source-root={source_root}') + if subdir: + potargs.append(f'--subdir={subdir}') + if datadirs: + potargs.append(datadirs) + if extra_arg: + potargs.append(extra_arg) + if self.tools['xgettext'].found(): + potargs.append('--xgettext=' + self.tools['xgettext'].get_path()) + pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject, + state.environment, default_env=False) + targets.append(pottarget) + + install = kwargs['install'] + install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('localedir')) + assert isinstance(install_dir, str), 'for mypy' + if not languages: + languages = read_linguas(path.join(state.environment.source_dir, state.subdir)) + for l in languages: + po_file = mesonlib.File.from_source_file(state.environment.source_dir, + state.subdir, l+'.po') + gmotarget = build.CustomTarget( + f'{packagename}-{l}.mo', + path.join(state.subdir, l, 'LC_MESSAGES'), + state.subproject, + state.environment, + [self.tools['msgfmt'], '-o', '@OUTPUT@', '@INPUT@'], + [po_file], + [f'{packagename}.mo'], + install=install, + # We have multiple files all installed as packagename+'.mo' in different install subdirs. + # What we really wanted to do, probably, is have a rename: kwarg, but that's not available + # to custom_targets. Crude hack: set the build target's subdir manually. + # Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir. + install_dir=[path.join(install_dir, l, 'LC_MESSAGES')], + install_tag=['i18n'], + ) + targets.append(gmotarget) + gmotargets.append(gmotarget) + + allgmotarget = build.AliasTarget(packagename + '-gmo', gmotargets, state.subdir, state.subproject, + state.environment) + targets.append(allgmotarget) + + updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg] + updatepoargs.append(f'--source-root={source_root}') + if subdir: + updatepoargs.append(f'--subdir={subdir}') + if lang_arg: + updatepoargs.append(lang_arg) + if datadirs: + updatepoargs.append(datadirs) + if extra_arg: + updatepoargs.append(extra_arg) + for tool in ['msginit', 'msgmerge']: + if self.tools[tool].found(): + updatepoargs.append(f'--{tool}=' + self.tools[tool].get_path()) + updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject, + state.environment, default_env=False) + targets.append(updatepotarget) + + return ModuleReturnValue([gmotargets, pottarget, updatepotarget], targets) + + @FeatureNew('i18n.itstool_join', '0.62.0') + @noPosargs + @typed_kwargs( + 'i18n.itstool_join', + CT_BUILD_BY_DEFAULT, + CT_INPUT_KW, + KwargInfo('install_dir', (str, NoneType)), + INSTALL_TAG_KW, + OUTPUT_KW, + INSTALL_KW, + _ARGS.evolve(), + KwargInfo('its_files', ContainerTypeInfo(list, str)), + KwargInfo('mo_targets', ContainerTypeInfo(list, build.CustomTarget), required=True), + ) + def itstool_join(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'ItsJoinFile') -> ModuleReturnValue: + if self.tools['itstool'] is None: + self.tools['itstool'] = state.find_program('itstool', for_machine=mesonlib.MachineChoice.BUILD) + mo_targets = kwargs['mo_targets'] + its_files = kwargs.get('its_files', []) + + mo_fnames = [] + for target in mo_targets: + mo_fnames.append(path.join(target.get_subdir(), target.get_outputs()[0])) + + command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, + build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = [] + command.extend(state.environment.get_build_command()) + command.extend([ + '--internal', 'itstool', 'join', + '-i', '@INPUT@', + '-o', '@OUTPUT@', + '--itstool=' + self.tools['itstool'].get_path(), + ]) + if its_files: + for fname in its_files: + if not path.isabs(fname): + fname = path.join(state.environment.source_dir, state.subdir, fname) + command.extend(['--its', fname]) + command.extend(mo_fnames) + + build_by_default = kwargs['build_by_default'] + if build_by_default is None: + build_by_default = kwargs['install'] + + install_tag = [kwargs['install_tag']] if kwargs['install_tag'] is not None else None + + ct = build.CustomTarget( + '', + state.subdir, + state.subproject, + state.environment, + command, + kwargs['input'], + [kwargs['output']], + build_by_default=build_by_default, + extra_depends=mo_targets, + install=kwargs['install'], + install_dir=[kwargs['install_dir']] if kwargs['install_dir'] is not None else None, + install_tag=install_tag, + ) + + return ModuleReturnValue(ct, [ct]) + + +def initialize(interp: 'Interpreter') -> I18nModule: + return I18nModule(interp) diff --git a/devtools/meson/mesonbuild/modules/icestorm.py b/devtools/meson/mesonbuild/modules/icestorm.py new file mode 100644 index 0000000..8c1c6f1 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/icestorm.py @@ -0,0 +1,131 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import itertools +import typing as T + +from . import ExtensionModule, ModuleReturnValue, ModuleInfo +from .. import build +from .. import mesonlib +from ..interpreter.type_checking import CT_INPUT_KW +from ..interpreterbase.decorators import KwargInfo, typed_kwargs, typed_pos_args + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from ..interpreter import Interpreter + from ..programs import ExternalProgram + + class ProjectKwargs(TypedDict): + + sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] + constraint_file: T.Union[mesonlib.FileOrString, build.GeneratedTypes] + +class IceStormModule(ExtensionModule): + + INFO = ModuleInfo('FPGA/Icestorm', '0.45.0', unstable=True) + + def __init__(self, interpreter: Interpreter) -> None: + super().__init__(interpreter) + self.tools: T.Dict[str, T.Union[ExternalProgram, build.Executable]] = {} + self.methods.update({ + 'project': self.project, + }) + + def detect_tools(self, state: ModuleState) -> None: + self.tools['yosys'] = state.find_program('yosys') + self.tools['arachne'] = state.find_program('arachne-pnr') + self.tools['icepack'] = state.find_program('icepack') + self.tools['iceprog'] = state.find_program('iceprog') + self.tools['icetime'] = state.find_program('icetime') + + @typed_pos_args('icestorm.project', str, + varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, + build.GeneratedList)) + @typed_kwargs( + 'icestorm.project', + CT_INPUT_KW.evolve(name='sources'), + KwargInfo( + 'constraint_file', + (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), + required=True, + ) + ) + def project(self, state: ModuleState, + args: T.Tuple[str, T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]], + kwargs: ProjectKwargs) -> ModuleReturnValue: + if not self.tools: + self.detect_tools(state) + proj_name, arg_sources = args + all_sources = self.interpreter.source_strings_to_files( + list(itertools.chain(arg_sources, kwargs['sources']))) + + blif_target = build.CustomTarget( + f'{proj_name}_blif', + state.subdir, + state.subproject, + state.environment, + [self.tools['yosys'], '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@'], + all_sources, + [f'{proj_name}.blif'], + ) + + asc_target = build.CustomTarget( + f'{proj_name}_asc', + state.subdir, + state.subproject, + state.environment, + [self.tools['arachne'], '-q', '-d', '1k', '-p', '@INPUT@', '-o', '@OUTPUT@'], + [kwargs['constraint_file'], blif_target], + [f'{proj_name}.asc'], + ) + + bin_target = build.CustomTarget( + f'{proj_name}_bin', + state.subdir, + state.subproject, + state.environment, + [self.tools['icepack'], '@INPUT@', '@OUTPUT@'], + [asc_target], + [f'{proj_name}.bin'], + build_by_default=True, + ) + + upload_target = build.RunTarget( + f'{proj_name}-upload', + [self.tools['iceprog'], bin_target], + [], + state.subdir, + state.subproject, + state.environment, + ) + + time_target = build.RunTarget( + f'{proj_name}-time', + [self.tools['icetime'], bin_target], + [], + state.subdir, + state.subproject, + state.environment, + ) + + return ModuleReturnValue( + None, + [blif_target, asc_target, bin_target, upload_target, time_target]) + + +def initialize(interp: Interpreter) -> IceStormModule: + return IceStormModule(interp) diff --git a/devtools/meson/mesonbuild/modules/java.py b/devtools/meson/mesonbuild/modules/java.py new file mode 100644 index 0000000..f6e4484 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/java.py @@ -0,0 +1,117 @@ +# Copyright 2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import pathlib +import typing as T + +from mesonbuild import mesonlib +from mesonbuild.build import CustomTarget, CustomTargetIndex, GeneratedList, Target +from mesonbuild.compilers import detect_compiler_for +from mesonbuild.interpreterbase.decorators import ContainerTypeInfo, FeatureDeprecated, FeatureNew, KwargInfo, typed_pos_args, typed_kwargs +from mesonbuild.mesonlib import version_compare, MachineChoice +from . import NewExtensionModule, ModuleReturnValue, ModuleInfo +from ..interpreter.type_checking import NoneType + +if T.TYPE_CHECKING: + from . import ModuleState + from ..compilers import Compiler + from ..interpreter import Interpreter + +class JavaModule(NewExtensionModule): + + INFO = ModuleInfo('java', '0.60.0') + + def __init__(self, interpreter: Interpreter): + super().__init__() + self.methods.update({ + 'generate_native_headers': self.generate_native_headers, + 'native_headers': self.native_headers, + }) + + def __get_java_compiler(self, state: ModuleState) -> Compiler: + if 'java' not in state.environment.coredata.compilers[MachineChoice.BUILD]: + detect_compiler_for(state.environment, 'java', MachineChoice.BUILD, False) + return state.environment.coredata.compilers[MachineChoice.BUILD]['java'] + + @FeatureNew('java.generate_native_headers', '0.62.0') + @FeatureDeprecated('java.generate_native_headers', '1.0.0') + @typed_pos_args( + 'java.generate_native_headers', + varargs=(str, mesonlib.File, Target, CustomTargetIndex, GeneratedList)) + @typed_kwargs( + 'java.generate_native_headers', + KwargInfo('classes', ContainerTypeInfo(list, str), default=[], listify=True, required=True), + KwargInfo('package', (str, NoneType), default=None)) + def generate_native_headers(self, state: ModuleState, args: T.Tuple[T.List[mesonlib.FileOrString]], + kwargs: T.Dict[str, T.Optional[str]]) -> ModuleReturnValue: + return self.__native_headers(state, args, kwargs) + + @FeatureNew('java.native_headers', '1.0.0') + @typed_pos_args( + 'java.native_headers', + varargs=(str, mesonlib.File, Target, CustomTargetIndex, GeneratedList)) + @typed_kwargs( + 'java.native_headers', + KwargInfo('classes', ContainerTypeInfo(list, str), default=[], listify=True, required=True), + KwargInfo('package', (str, NoneType), default=None)) + def native_headers(self, state: ModuleState, args: T.Tuple[T.List[mesonlib.FileOrString]], + kwargs: T.Dict[str, T.Optional[str]]) -> ModuleReturnValue: + return self.__native_headers(state, args, kwargs) + + def __native_headers(self, state: ModuleState, args: T.Tuple[T.List[mesonlib.FileOrString]], + kwargs: T.Dict[str, T.Optional[str]]) -> ModuleReturnValue: + classes = T.cast('T.List[str]', kwargs.get('classes')) + package = kwargs.get('package') + + if package: + sanitized_package = package.replace("-", "_").replace(".", "_") + + headers: T.List[str] = [] + for clazz in classes: + sanitized_clazz = clazz.replace(".", "_") + if package: + headers.append(f'{sanitized_package}_{sanitized_clazz}.h') + else: + headers.append(f'{sanitized_clazz}.h') + + javac = self.__get_java_compiler(state) + + command = mesonlib.listify([ + javac.exelist, + '-d', + '@PRIVATE_DIR@', + '-h', + state.subdir, + '@INPUT@', + ]) + + prefix = classes[0] if not package else package + + target = CustomTarget(f'{prefix}-native-headers', + state.subdir, + state.subproject, + state.environment, + command, + sources=args[0], outputs=headers, backend=state.backend) + + # It is only known that 1.8.0 won't pre-create the directory. 11 and 16 + # do not exhibit this behavior. + if version_compare(javac.version, '1.8.0'): + pathlib.Path(state.backend.get_target_private_dir_abs(target)).mkdir(parents=True, exist_ok=True) + + return ModuleReturnValue(target, [target]) + +def initialize(*args: T.Any, **kwargs: T.Any) -> JavaModule: + return JavaModule(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/keyval.py b/devtools/meson/mesonbuild/modules/keyval.py new file mode 100644 index 0000000..48afe81 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/keyval.py @@ -0,0 +1,75 @@ +# Copyright 2017, 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import typing as T + +from . import ExtensionModule, ModuleInfo +from .. import mesonlib +from ..interpreterbase import noKwargs, typed_pos_args + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + from . import ModuleState + +class KeyvalModule(ExtensionModule): + + INFO = ModuleInfo('keyval', '0.55.0', stabilized='0.56.0') + + def __init__(self, interp: 'Interpreter'): + super().__init__(interp) + self.methods.update({ + 'load': self.load, + }) + + @staticmethod + def _load_file(path_to_config: str) -> T.Dict[str, str]: + result: T.Dict[str, str] = {} + try: + with open(path_to_config, encoding='utf-8') as f: + for line in f: + if '#' in line: + comment_idx = line.index('#') + line = line[:comment_idx] + line = line.strip() + try: + name, val = line.split('=', 1) + except ValueError: + continue + result[name.strip()] = val.strip() + except OSError as e: + raise mesonlib.MesonException(f'Failed to load {path_to_config}: {e}') + + return result + + @noKwargs + @typed_pos_args('keyval.load', (str, mesonlib.File)) + def load(self, state: 'ModuleState', args: T.Tuple['mesonlib.FileOrString'], kwargs: T.Dict[str, T.Any]) -> T.Dict[str, str]: + s = args[0] + is_built = False + if isinstance(s, mesonlib.File): + is_built = is_built or s.is_built + s = s.absolute_path(self.interpreter.environment.source_dir, self.interpreter.environment.build_dir) + else: + s = os.path.join(self.interpreter.environment.source_dir, s) + + if not is_built: + self.interpreter.build_def_files.add(s) + + return self._load_file(s) + + +def initialize(interp: 'Interpreter') -> KeyvalModule: + return KeyvalModule(interp) diff --git a/devtools/meson/mesonbuild/modules/modtest.py b/devtools/meson/mesonbuild/modules/modtest.py new file mode 100644 index 0000000..15f8237 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/modtest.py @@ -0,0 +1,44 @@ +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import typing as T + +from . import ExtensionModule, ModuleInfo +from ..interpreterbase import noKwargs, noPosargs + +if T.TYPE_CHECKING: + from . import ModuleState + from ..interpreter.interpreter import Interpreter + from ..interpreterbase.baseobjects import TYPE_kwargs, TYPE_var + + +class TestModule(ExtensionModule): + + INFO = ModuleInfo('modtest') + + def __init__(self, interpreter: Interpreter) -> None: + super().__init__(interpreter) + self.methods.update({ + 'print_hello': self.print_hello, + }) + + @noKwargs + @noPosargs + def print_hello(self, state: ModuleState, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None: + print('Hello from a Meson module') + + +def initialize(interp: Interpreter) -> TestModule: + return TestModule(interp) diff --git a/devtools/meson/mesonbuild/modules/pkgconfig.py b/devtools/meson/mesonbuild/modules/pkgconfig.py new file mode 100644 index 0000000..63025a5 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/pkgconfig.py @@ -0,0 +1,748 @@ +# Copyright 2015-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +from collections import defaultdict +from dataclasses import dataclass +from pathlib import PurePath +import os +import typing as T + +from . import NewExtensionModule, ModuleInfo +from . import ModuleReturnValue +from .. import build +from .. import dependencies +from .. import mesonlib +from .. import mlog +from ..coredata import BUILTIN_DIR_OPTIONS +from ..dependencies.pkgconfig import PkgConfigDependency +from ..interpreter.type_checking import D_MODULE_VERSIONS_KW, INSTALL_DIR_KW, VARIABLES_KW, NoneType +from ..interpreterbase import FeatureNew, FeatureDeprecated +from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from .. import mparser + from ..interpreter import Interpreter + + ANY_DEP = T.Union[dependencies.Dependency, build.BuildTargetTypes, str] + LIBS = T.Union[build.LibTypes, str] + + class GenerateKw(TypedDict): + + version: T.Optional[str] + name: T.Optional[str] + filebase: T.Optional[str] + description: T.Optional[str] + url: str + subdirs: T.List[str] + conflicts: T.List[str] + dataonly: bool + libraries: T.List[ANY_DEP] + libraries_private: T.List[ANY_DEP] + requires: T.List[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]] + requires_private: T.List[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]] + install_dir: T.Optional[str] + d_module_versions: T.List[T.Union[str, int]] + extra_cflags: T.List[str] + variables: T.Dict[str, str] + uninstalled_variables: T.Dict[str, str] + unescaped_variables: T.Dict[str, str] + unescaped_uninstalled_variables: T.Dict[str, str] + + +_PKG_LIBRARIES: KwargInfo[T.List[T.Union[str, dependencies.Dependency, build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]]] = KwargInfo( + 'libraries', + ContainerTypeInfo(list, (str, dependencies.Dependency, + build.SharedLibrary, build.StaticLibrary, + build.CustomTarget, build.CustomTargetIndex)), + default=[], + listify=True, +) + +_PKG_REQUIRES: KwargInfo[T.List[T.Union[str, build.SharedLibrary, build.StaticLibrary, dependencies.Dependency]]] = KwargInfo( + 'requires', + ContainerTypeInfo(list, (str, build.SharedLibrary, build.StaticLibrary, dependencies.Dependency)), + default=[], + listify=True, +) + + +def _as_str(obj: object) -> str: + assert isinstance(obj, str) + return obj + + +@dataclass +class MetaData: + + filebase: str + display_name: str + location: mparser.BaseNode + warned: bool = False + + +class DependenciesHelper: + def __init__(self, state: ModuleState, name: str, metadata: T.Dict[str, MetaData]) -> None: + self.state = state + self.name = name + self.metadata = metadata + self.pub_libs: T.List[LIBS] = [] + self.pub_reqs: T.List[str] = [] + self.priv_libs: T.List[LIBS] = [] + self.priv_reqs: T.List[str] = [] + self.cflags: T.List[str] = [] + self.version_reqs: T.DefaultDict[str, T.Set[str]] = defaultdict(set) + self.link_whole_targets: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex, build.StaticLibrary]] = [] + self.uninstalled_incdirs: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() + + def add_pub_libs(self, libs: T.List[ANY_DEP]) -> None: + p_libs, reqs, cflags = self._process_libs(libs, True) + self.pub_libs = p_libs + self.pub_libs # prepend to preserve dependencies + self.pub_reqs += reqs + self.cflags += cflags + + def add_priv_libs(self, libs: T.List[ANY_DEP]) -> None: + p_libs, reqs, _ = self._process_libs(libs, False) + self.priv_libs = p_libs + self.priv_libs + self.priv_reqs += reqs + + def add_pub_reqs(self, reqs: T.List[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]]) -> None: + self.pub_reqs += self._process_reqs(reqs) + + def add_priv_reqs(self, reqs: T.List[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]]) -> None: + self.priv_reqs += self._process_reqs(reqs) + + def _check_generated_pc_deprecation(self, obj: T.Union[build.CustomTarget, build.CustomTargetIndex, build.StaticLibrary, build.SharedLibrary]) -> None: + if obj.get_id() in self.metadata: + return + data = self.metadata[obj.get_id()] + if data.warned: + return + mlog.deprecation('Library', mlog.bold(obj.name), 'was passed to the ' + '"libraries" keyword argument of a previous call ' + 'to generate() method instead of first positional ' + 'argument.', 'Adding', mlog.bold(data.display_name), + 'to "Requires" field, but this is a deprecated ' + 'behaviour that will change in a future version ' + 'of Meson. Please report the issue if this ' + 'warning cannot be avoided in your case.', + location=data.location) + data.warned = True + + def _process_reqs(self, reqs: T.Sequence[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]]) -> T.List[str]: + '''Returns string names of requirements''' + processed_reqs: T.List[str] = [] + for obj in mesonlib.listify(reqs): + if not isinstance(obj, str): + FeatureNew.single_use('pkgconfig.generate requirement from non-string object', '0.46.0', self.state.subproject) + if (isinstance(obj, (build.CustomTarget, build.CustomTargetIndex, build.SharedLibrary, build.StaticLibrary)) + and obj.get_id() in self.metadata): + self._check_generated_pc_deprecation(obj) + processed_reqs.append(self.metadata[obj.get_id()].filebase) + elif isinstance(obj, PkgConfigDependency): + if obj.found(): + processed_reqs.append(obj.name) + self.add_version_reqs(obj.name, obj.version_reqs) + elif isinstance(obj, str): + name, version_req = self.split_version_req(obj) + processed_reqs.append(name) + self.add_version_reqs(name, [version_req] if version_req is not None else None) + elif isinstance(obj, dependencies.Dependency) and not obj.found(): + pass + elif isinstance(obj, dependencies.ExternalDependency) and obj.name == 'threads': + pass + else: + raise mesonlib.MesonException('requires argument not a string, ' + 'library with pkgconfig-generated file ' + f'or pkgconfig-dependency object, got {obj!r}') + return processed_reqs + + def add_cflags(self, cflags: T.List[str]) -> None: + self.cflags += mesonlib.stringlistify(cflags) + + def _add_uninstalled_incdirs(self, incdirs: T.List[build.IncludeDirs], subdir: T.Optional[str] = None) -> None: + for i in incdirs: + curdir = i.get_curdir() + for d in i.get_incdirs(): + path = os.path.join(curdir, d) + self.uninstalled_incdirs.add(path) + if subdir is not None: + self.uninstalled_incdirs.add(subdir) + + def _process_libs( + self, libs: T.List[ANY_DEP], public: bool + ) -> T.Tuple[T.List[T.Union[str, build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]], T.List[str], T.List[str]]: + libs = mesonlib.listify(libs) + processed_libs: T.List[T.Union[str, build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]] = [] + processed_reqs: T.List[str] = [] + processed_cflags: T.List[str] = [] + for obj in libs: + if (isinstance(obj, (build.CustomTarget, build.CustomTargetIndex, build.SharedLibrary, build.StaticLibrary)) + and obj.get_id() in self.metadata): + self._check_generated_pc_deprecation(obj) + processed_reqs.append(self.metadata[obj.get_id()].filebase) + elif isinstance(obj, dependencies.ExternalDependency) and obj.name == 'valgrind': + pass + elif isinstance(obj, PkgConfigDependency): + if obj.found(): + processed_reqs.append(obj.name) + self.add_version_reqs(obj.name, obj.version_reqs) + elif isinstance(obj, dependencies.InternalDependency): + if obj.found(): + if obj.objects: + raise mesonlib.MesonException('.pc file cannot refer to individual object files.') + processed_libs += obj.get_link_args() + processed_cflags += obj.get_compile_args() + self._add_lib_dependencies(obj.libraries, obj.whole_libraries, obj.ext_deps, public, private_external_deps=True) + self._add_uninstalled_incdirs(obj.get_include_dirs()) + elif isinstance(obj, dependencies.Dependency): + if obj.found(): + processed_libs += obj.get_link_args() + processed_cflags += obj.get_compile_args() + elif isinstance(obj, build.SharedLibrary) and obj.shared_library_only: + # Do not pull dependencies for shared libraries because they are + # only required for static linking. Adding private requires has + # the side effect of exposing their cflags, which is the + # intended behaviour of pkg-config but force Debian to add more + # than needed build deps. + # See https://bugs.freedesktop.org/show_bug.cgi?id=105572 + processed_libs.append(obj) + self._add_uninstalled_incdirs(obj.get_include_dirs(), obj.get_subdir()) + elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)): + processed_libs.append(obj) + self._add_uninstalled_incdirs(obj.get_include_dirs(), obj.get_subdir()) + # If there is a static library in `Libs:` all its deps must be + # public too, otherwise the generated pc file will never be + # usable without --static. + self._add_lib_dependencies(obj.link_targets, + obj.link_whole_targets, + obj.external_deps, + isinstance(obj, build.StaticLibrary) and public) + elif isinstance(obj, (build.CustomTarget, build.CustomTargetIndex)): + if not obj.is_linkable_target(): + raise mesonlib.MesonException('library argument contains a not linkable custom_target.') + FeatureNew.single_use('custom_target in pkgconfig.generate libraries', '0.58.0', self.state.subproject) + processed_libs.append(obj) + elif isinstance(obj, str): + processed_libs.append(obj) + else: + raise mesonlib.MesonException(f'library argument of type {type(obj).__name__} not a string, library or dependency object.') + + return processed_libs, processed_reqs, processed_cflags + + def _add_lib_dependencies( + self, link_targets: T.Sequence[build.BuildTargetTypes], + link_whole_targets: T.Sequence[T.Union[build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]], + external_deps: T.List[dependencies.Dependency], + public: bool, + private_external_deps: bool = False) -> None: + add_libs = self.add_pub_libs if public else self.add_priv_libs + # Recursively add all linked libraries + for t in link_targets: + # Internal libraries (uninstalled static library) will be promoted + # to link_whole, treat them as such here. + if t.is_internal(): + # `is_internal` shouldn't return True for anything but a + # StaticLibrary, or a CustomTarget that is a StaticLibrary + assert isinstance(t, (build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex)), 'for mypy' + self._add_link_whole(t, public) + else: + add_libs([t]) + for t in link_whole_targets: + self._add_link_whole(t, public) + # And finally its external dependencies + if private_external_deps: + self.add_priv_libs(T.cast('T.List[ANY_DEP]', external_deps)) + else: + add_libs(T.cast('T.List[ANY_DEP]', external_deps)) + + def _add_link_whole(self, t: T.Union[build.CustomTarget, build.CustomTargetIndex, build.StaticLibrary], public: bool) -> None: + # Don't include static libraries that we link_whole. But we still need to + # include their dependencies: a static library we link_whole + # could itself link to a shared library or an installed static library. + # Keep track of link_whole_targets so we can remove them from our + # lists in case a library is link_with and link_whole at the same time. + # See remove_dups() below. + self.link_whole_targets.append(t) + if isinstance(t, build.BuildTarget): + self._add_lib_dependencies(t.link_targets, t.link_whole_targets, t.external_deps, public) + + def add_version_reqs(self, name: str, version_reqs: T.Optional[T.List[str]]) -> None: + if version_reqs: + # Note that pkg-config is picky about whitespace. + # 'foo > 1.2' is ok but 'foo>1.2' is not. + # foo, bar' is ok, but 'foo,bar' is not. + self.version_reqs[name].update(version_reqs) + + def split_version_req(self, s: str) -> T.Tuple[str, T.Optional[str]]: + for op in ['>=', '<=', '!=', '==', '=', '>', '<']: + pos = s.find(op) + if pos > 0: + return s[0:pos].strip(), s[pos:].strip() + return s, None + + def format_vreq(self, vreq: str) -> str: + # vreq are '>=1.0' and pkgconfig wants '>= 1.0' + for op in ['>=', '<=', '!=', '==', '=', '>', '<']: + if vreq.startswith(op): + return op + ' ' + vreq[len(op):] + return vreq + + def format_reqs(self, reqs: T.List[str]) -> str: + result: T.List[str] = [] + for name in reqs: + vreqs = self.version_reqs.get(name, None) + if vreqs: + result += [name + ' ' + self.format_vreq(vreq) for vreq in vreqs] + else: + result += [name] + return ', '.join(result) + + def remove_dups(self) -> None: + # Set of ids that have already been handled and should not be added any more + exclude: T.Set[str] = set() + + # We can't just check if 'x' is excluded because we could have copies of + # the same SharedLibrary object for example. + def _ids(x: T.Union[str, build.CustomTarget, build.CustomTargetIndex, build.StaticLibrary, build.SharedLibrary]) -> T.Iterable[str]: + if isinstance(x, str): + yield x + else: + if x.get_id() in self.metadata: + yield self.metadata[x.get_id()].display_name + yield x.get_id() + + # Exclude 'x' in all its forms and return if it was already excluded + def _add_exclude(x: T.Union[str, build.CustomTarget, build.CustomTargetIndex, build.StaticLibrary, build.SharedLibrary]) -> bool: + was_excluded = False + for i in _ids(x): + if i in exclude: + was_excluded = True + else: + exclude.add(i) + return was_excluded + + # link_whole targets are already part of other targets, exclude them all. + for t in self.link_whole_targets: + _add_exclude(t) + + # Mypy thinks these overlap, but since List is invariant they don't, + # `List[str]`` is not a valid input to `List[str | BuildTarget]`. + # pylance/pyright gets this right, but for mypy we have to ignore the + # error + @T.overload + def _fn(xs: T.List[str], libs: bool = False) -> T.List[str]: ... # type: ignore + + @T.overload + def _fn(xs: T.List[LIBS], libs: bool = False) -> T.List[LIBS]: ... + + def _fn(xs: T.Union[T.List[str], T.List[LIBS]], libs: bool = False) -> T.Union[T.List[str], T.List[LIBS]]: + # Remove duplicates whilst preserving original order + result = [] + for x in xs: + # Don't de-dup unknown strings to avoid messing up arguments like: + # ['-framework', 'CoreAudio', '-framework', 'CoreMedia'] + known_flags = ['-pthread'] + cannot_dedup = libs and isinstance(x, str) and \ + not x.startswith(('-l', '-L')) and \ + x not in known_flags + if not cannot_dedup and _add_exclude(x): + continue + result.append(x) + return result + + # Handle lists in priority order: public items can be excluded from + # private and Requires can excluded from Libs. + self.pub_reqs = _fn(self.pub_reqs) + self.pub_libs = _fn(self.pub_libs, True) + self.priv_reqs = _fn(self.priv_reqs) + self.priv_libs = _fn(self.priv_libs, True) + # Reset exclude list just in case some values can be both cflags and libs. + exclude = set() + self.cflags = _fn(self.cflags) + +class PkgConfigModule(NewExtensionModule): + + INFO = ModuleInfo('pkgconfig') + + # Track already generated pkg-config files This is stored as a class + # variable so that multiple `import()`s share metadata + devenv: T.Optional[build.EnvironmentVariables] = None + _metadata: T.ClassVar[T.Dict[str, MetaData]] = {} + + def __init__(self) -> None: + super().__init__() + self.methods.update({ + 'generate': self.generate, + }) + + def postconf_hook(self, b: build.Build) -> None: + if self.devenv is not None: + b.devenv.append(self.devenv) + + def _get_lname(self, l: T.Union[build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex], + msg: str, pcfile: str) -> str: + if isinstance(l, (build.CustomTargetIndex, build.CustomTarget)): + basename = os.path.basename(l.get_filename()) + name = os.path.splitext(basename)[0] + if name.startswith('lib'): + name = name[3:] + return name + # Nothing special + if not l.name_prefix_set: + return l.name + # Sometimes people want the library to start with 'lib' everywhere, + # which is achieved by setting name_prefix to '' and the target name to + # 'libfoo'. In that case, try to get the pkg-config '-lfoo' arg correct. + if l.prefix == '' and l.name.startswith('lib'): + return l.name[3:] + # If the library is imported via an import library which is always + # named after the target name, '-lfoo' is correct. + if isinstance(l, build.SharedLibrary) and l.import_filename: + return l.name + # In other cases, we can't guarantee that the compiler will be able to + # find the library via '-lfoo', so tell the user that. + mlog.warning(msg.format(l.name, 'name_prefix', l.name, pcfile)) + return l.name + + def _escape(self, value: T.Union[str, PurePath]) -> str: + ''' + We cannot use quote_arg because it quotes with ' and " which does not + work with pkg-config and pkgconf at all. + ''' + # We should always write out paths with / because pkg-config requires + # spaces to be quoted with \ and that messes up on Windows: + # https://bugs.freedesktop.org/show_bug.cgi?id=103203 + if isinstance(value, PurePath): + value = value.as_posix() + return value.replace(' ', r'\ ') + + def _make_relative(self, prefix: T.Union[PurePath, str], subdir: T.Union[PurePath, str]) -> str: + prefix = PurePath(prefix) + subdir = PurePath(subdir) + try: + libdir = subdir.relative_to(prefix) + except ValueError: + libdir = subdir + # pathlib joining makes sure absolute libdir is not appended to '${prefix}' + return ('${prefix}' / libdir).as_posix() + + def _generate_pkgconfig_file(self, state: ModuleState, deps: DependenciesHelper, + subdirs: T.List[str], name: str, + description: str, url: str, version: str, + pcfile: str, conflicts: T.List[str], + variables: T.List[T.Tuple[str, str]], + unescaped_variables: T.List[T.Tuple[str, str]], + uninstalled: bool = False, dataonly: bool = False, + pkgroot: T.Optional[str] = None) -> None: + coredata = state.environment.get_coredata() + referenced_vars = set() + optnames = [x.name for x in BUILTIN_DIR_OPTIONS.keys()] + + if not dataonly: + # includedir is always implied, although libdir may not be + # needed for header-only libraries + referenced_vars |= {'prefix', 'includedir'} + if deps.pub_libs or deps.priv_libs: + referenced_vars |= {'libdir'} + # also automatically infer variables referenced in other variables + implicit_vars_warning = False + redundant_vars_warning = False + varnames = set() + varstrings = set() + for k, v in variables + unescaped_variables: + varnames |= {k} + varstrings |= {v} + for optname in optnames: + optvar = f'${{{optname}}}' + if any(x.startswith(optvar) for x in varstrings): + if optname in varnames: + redundant_vars_warning = True + else: + # these 3 vars were always "implicit" + if dataonly or optname not in {'prefix', 'includedir', 'libdir'}: + implicit_vars_warning = True + referenced_vars |= {'prefix', optname} + if redundant_vars_warning: + FeatureDeprecated.single_use('pkgconfig.generate variable for builtin directories', '0.62.0', + state.subproject, 'They will be automatically included when referenced', + state.current_node) + if implicit_vars_warning: + FeatureNew.single_use('pkgconfig.generate implicit variable for builtin directories', '0.62.0', + state.subproject, location=state.current_node) + + if uninstalled: + outdir = os.path.join(state.environment.build_dir, 'meson-uninstalled') + if not os.path.exists(outdir): + os.mkdir(outdir) + prefix = PurePath(state.environment.get_build_dir()) + srcdir = PurePath(state.environment.get_source_dir()) + else: + outdir = state.environment.scratch_dir + prefix = PurePath(_as_str(coredata.get_option(mesonlib.OptionKey('prefix')))) + if pkgroot: + pkgroot_ = PurePath(pkgroot) + if not pkgroot_.is_absolute(): + pkgroot_ = prefix / pkgroot + elif prefix not in pkgroot_.parents: + raise mesonlib.MesonException('Pkgconfig prefix cannot be outside of the prefix ' + 'when pkgconfig.relocatable=true. ' + f'Pkgconfig prefix is {pkgroot_.as_posix()}.') + prefix = PurePath('${pcfiledir}', os.path.relpath(prefix, pkgroot_)) + fname = os.path.join(outdir, pcfile) + with open(fname, 'w', encoding='utf-8') as ofile: + for optname in optnames: + if optname in referenced_vars - varnames: + if optname == 'prefix': + ofile.write('prefix={}\n'.format(self._escape(prefix))) + else: + dirpath = PurePath(_as_str(coredata.get_option(mesonlib.OptionKey(optname)))) + ofile.write('{}={}\n'.format(optname, self._escape('${prefix}' / dirpath))) + if uninstalled and not dataonly: + ofile.write('srcdir={}\n'.format(self._escape(srcdir))) + if variables or unescaped_variables: + ofile.write('\n') + for k, v in variables: + ofile.write('{}={}\n'.format(k, self._escape(v))) + for k, v in unescaped_variables: + ofile.write(f'{k}={v}\n') + ofile.write('\n') + ofile.write(f'Name: {name}\n') + if len(description) > 0: + ofile.write(f'Description: {description}\n') + if len(url) > 0: + ofile.write(f'URL: {url}\n') + ofile.write(f'Version: {version}\n') + reqs_str = deps.format_reqs(deps.pub_reqs) + if len(reqs_str) > 0: + ofile.write(f'Requires: {reqs_str}\n') + reqs_str = deps.format_reqs(deps.priv_reqs) + if len(reqs_str) > 0: + ofile.write(f'Requires.private: {reqs_str}\n') + if len(conflicts) > 0: + ofile.write('Conflicts: {}\n'.format(' '.join(conflicts))) + + def generate_libs_flags(libs: T.List[LIBS]) -> T.Iterable[str]: + msg = 'Library target {0!r} has {1!r} set. Compilers ' \ + 'may not find it from its \'-l{2}\' linker flag in the ' \ + '{3!r} pkg-config file.' + Lflags = [] + for l in libs: + if isinstance(l, str): + yield l + else: + install_dir: T.Union[str, bool] + if uninstalled: + install_dir = os.path.dirname(state.backend.get_target_filename_abs(l)) + else: + _i = l.get_custom_install_dir() + install_dir = _i[0] if _i else None + if install_dir is False: + continue + if isinstance(l, build.BuildTarget) and 'cs' in l.compilers: + if isinstance(install_dir, str): + Lflag = '-r{}/{}'.format(self._escape(self._make_relative(prefix, install_dir)), l.filename) + else: # install_dir is True + Lflag = '-r${libdir}/%s' % l.filename + else: + if isinstance(install_dir, str): + Lflag = '-L{}'.format(self._escape(self._make_relative(prefix, install_dir))) + else: # install_dir is True + Lflag = '-L${libdir}' + if Lflag not in Lflags: + Lflags.append(Lflag) + yield Lflag + lname = self._get_lname(l, msg, pcfile) + # If using a custom suffix, the compiler may not be able to + # find the library + if isinstance(l, build.BuildTarget) and l.name_suffix_set: + mlog.warning(msg.format(l.name, 'name_suffix', lname, pcfile)) + if isinstance(l, (build.CustomTarget, build.CustomTargetIndex)) or 'cs' not in l.compilers: + yield f'-l{lname}' + + if len(deps.pub_libs) > 0: + ofile.write('Libs: {}\n'.format(' '.join(generate_libs_flags(deps.pub_libs)))) + if len(deps.priv_libs) > 0: + ofile.write('Libs.private: {}\n'.format(' '.join(generate_libs_flags(deps.priv_libs)))) + + cflags: T.List[str] = [] + if uninstalled: + for d in deps.uninstalled_incdirs: + for basedir in ['${prefix}', '${srcdir}']: + path = self._escape(PurePath(basedir, d).as_posix()) + cflags.append(f'-I{path}') + else: + for d in subdirs: + if d == '.': + cflags.append('-I${includedir}') + else: + cflags.append(self._escape(PurePath('-I${includedir}') / d)) + cflags += [self._escape(f) for f in deps.cflags] + if cflags and not dataonly: + ofile.write('Cflags: {}\n'.format(' '.join(cflags))) + + @typed_pos_args('pkgconfig.generate', optargs=[(build.SharedLibrary, build.StaticLibrary)]) + @typed_kwargs( + 'pkgconfig.generate', + D_MODULE_VERSIONS_KW.evolve(since='0.43.0'), + INSTALL_DIR_KW, + KwargInfo('conflicts', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('dataonly', bool, default=False, since='0.54.0'), + KwargInfo('description', (str, NoneType)), + KwargInfo('extra_cflags', ContainerTypeInfo(list, str), default=[], listify=True, since='0.42.0'), + KwargInfo('filebase', (str, NoneType), validator=lambda x: 'must not be an empty string' if x == '' else None), + KwargInfo('name', (str, NoneType), validator=lambda x: 'must not be an empty string' if x == '' else None), + KwargInfo('subdirs', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('url', str, default=''), + KwargInfo('version', (str, NoneType)), + VARIABLES_KW.evolve(name="unescaped_uninstalled_variables", since='0.59.0'), + VARIABLES_KW.evolve(name="unescaped_variables", since='0.59.0'), + VARIABLES_KW.evolve(name="uninstalled_variables", since='0.54.0', since_values={dict: '0.56.0'}), + VARIABLES_KW.evolve(since='0.41.0', since_values={dict: '0.56.0'}), + _PKG_LIBRARIES, + _PKG_LIBRARIES.evolve(name='libraries_private'), + _PKG_REQUIRES, + _PKG_REQUIRES.evolve(name='requires_private'), + ) + def generate(self, state: ModuleState, + args: T.Tuple[T.Optional[T.Union[build.SharedLibrary, build.StaticLibrary]]], + kwargs: GenerateKw) -> ModuleReturnValue: + default_version = state.project_version + default_install_dir: T.Optional[str] = None + default_description: T.Optional[str] = None + default_name: T.Optional[str] = None + mainlib: T.Optional[T.Union[build.SharedLibrary, build.StaticLibrary]] = None + default_subdirs = ['.'] + if args[0]: + FeatureNew.single_use('pkgconfig.generate optional positional argument', '0.46.0', state.subproject) + mainlib = args[0] + default_name = mainlib.name + default_description = state.project_name + ': ' + mainlib.name + install_dir = mainlib.get_custom_install_dir() + if install_dir and isinstance(install_dir[0], str): + default_install_dir = os.path.join(install_dir[0], 'pkgconfig') + else: + if kwargs['version'] is None: + FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject) + msg = ('pkgconfig.generate: if a library is not passed as a ' + 'positional argument, the {!r} keyword argument is ' + 'required.') + if kwargs['name'] is None: + raise build.InvalidArguments(msg.format('name')) + if kwargs['description'] is None: + raise build.InvalidArguments(msg.format('description')) + + dataonly = kwargs['dataonly'] + if dataonly: + default_subdirs = [] + blocked_vars = ['libraries', 'libraries_private', 'requires_private', 'extra_cflags', 'subdirs'] + if any(kwargs[k] for k in blocked_vars): # type: ignore + raise mesonlib.MesonException(f'Cannot combine dataonly with any of {blocked_vars}') + default_install_dir = os.path.join(state.environment.get_datadir(), 'pkgconfig') + + subdirs = kwargs['subdirs'] or default_subdirs + version = kwargs['version'] if kwargs['version'] is not None else default_version + name = kwargs['name'] if kwargs['name'] is not None else default_name + assert isinstance(name, str), 'for mypy' + filebase = kwargs['filebase'] if kwargs['filebase'] is not None else name + description = kwargs['description'] if kwargs['description'] is not None else default_description + url = kwargs['url'] + conflicts = kwargs['conflicts'] + + # Prepend the main library to public libraries list. This is required + # so dep.add_pub_libs() can handle dependency ordering correctly and put + # extra libraries after the main library. + libraries = kwargs['libraries'].copy() + if mainlib: + libraries.insert(0, mainlib) + + deps = DependenciesHelper(state, filebase, self._metadata) + deps.add_pub_libs(libraries) + deps.add_priv_libs(kwargs['libraries_private']) + deps.add_pub_reqs(kwargs['requires']) + deps.add_priv_reqs(kwargs['requires_private']) + deps.add_cflags(kwargs['extra_cflags']) + + dversions = kwargs['d_module_versions'] + if dversions: + compiler = state.environment.coredata.compilers.host.get('d') + if compiler: + deps.add_cflags(compiler.get_feature_args({'versions': dversions}, None)) + + deps.remove_dups() + + def parse_variable_list(vardict: T.Dict[str, str]) -> T.List[T.Tuple[str, str]]: + reserved = ['prefix', 'libdir', 'includedir'] + variables = [] + for name, value in vardict.items(): + if not dataonly and name in reserved: + raise mesonlib.MesonException(f'Variable "{name}" is reserved') + variables.append((name, value)) + return variables + + variables = parse_variable_list(kwargs['variables']) + unescaped_variables = parse_variable_list(kwargs['unescaped_variables']) + + pcfile = filebase + '.pc' + pkgroot = pkgroot_name = kwargs['install_dir'] or default_install_dir + if pkgroot is None: + if mesonlib.is_freebsd(): + pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(mesonlib.OptionKey('prefix'))), 'libdata', 'pkgconfig') + pkgroot_name = os.path.join('{prefix}', 'libdata', 'pkgconfig') + elif mesonlib.is_haiku(): + pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(mesonlib.OptionKey('prefix'))), 'develop', 'lib', 'pkgconfig') + pkgroot_name = os.path.join('{prefix}', 'develop', 'lib', 'pkgconfig') + else: + pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(mesonlib.OptionKey('libdir'))), 'pkgconfig') + pkgroot_name = os.path.join('{libdir}', 'pkgconfig') + relocatable = state.get_option('relocatable', module='pkgconfig') + self._generate_pkgconfig_file(state, deps, subdirs, name, description, url, + version, pcfile, conflicts, variables, + unescaped_variables, False, dataonly, + pkgroot=pkgroot if relocatable else None) + res = build.Data([mesonlib.File(True, state.environment.get_scratch_dir(), pcfile)], pkgroot, pkgroot_name, None, state.subproject, install_tag='devel') + variables = parse_variable_list(kwargs['uninstalled_variables']) + unescaped_variables = parse_variable_list(kwargs['unescaped_uninstalled_variables']) + + pcfile = filebase + '-uninstalled.pc' + self._generate_pkgconfig_file(state, deps, subdirs, name, description, url, + version, pcfile, conflicts, variables, + unescaped_variables, uninstalled=True, dataonly=dataonly) + # Associate the main library with this generated pc file. If the library + # is used in any subsequent call to the generated, it will generate a + # 'Requires:' or 'Requires.private:'. + # Backward compatibility: We used to set 'generated_pc' on all public + # libraries instead of just the main one. Keep doing that but warn if + # anyone is relying on that deprecated behaviour. + if mainlib: + if mainlib.get_id() not in self._metadata: + self._metadata[mainlib.get_id()] = MetaData( + filebase, name, state.current_node) + else: + mlog.warning('Already generated a pkg-config file for', mlog.bold(mainlib.name)) + else: + for lib in deps.pub_libs: + if not isinstance(lib, str) and lib.get_id() not in self._metadata: + self._metadata[lib.get_id()] = MetaData( + filebase, name, state.current_node) + if self.devenv is None: + self.devenv = PkgConfigDependency.get_env(state.environment, mesonlib.MachineChoice.HOST, uninstalled=True) + return ModuleReturnValue(res, [res]) + + +def initialize(interp: Interpreter) -> PkgConfigModule: + return PkgConfigModule() diff --git a/devtools/meson/mesonbuild/modules/python.py b/devtools/meson/mesonbuild/modules/python.py new file mode 100644 index 0000000..ac74e13 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/python.py @@ -0,0 +1,487 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import copy, json, os, shutil +import typing as T + +from . import ExtensionModule, ModuleInfo +from .. import mesonlib +from .. import mlog +from ..coredata import UserFeatureOption +from ..build import known_shmod_kwargs +from ..dependencies import NotFoundDependency +from ..dependencies.detect import get_dep_identifier, find_external_dependency +from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase +from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs +from ..interpreter import primitives as P_OBJ +from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW +from ..interpreterbase import ( + noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo, + InvalidArguments, typed_pos_args, typed_kwargs, KwargInfo, + FeatureNew, FeatureNewKwargs, disablerIfNotFound +) +from ..mesonlib import MachineChoice +from ..programs import ExternalProgram, NonExistingExternalProgram + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from ..build import Build, SharedModule, Data + from ..dependencies import Dependency + from ..interpreter import Interpreter + from ..interpreter.kwargs import ExtractRequired + from ..interpreterbase.interpreterbase import TYPE_var, TYPE_kwargs + + class PyInstallKw(TypedDict): + + pure: T.Optional[bool] + subdir: str + install_tag: T.Optional[str] + + class FindInstallationKw(ExtractRequired): + + disabler: bool + modules: T.List[str] + pure: T.Optional[bool] + + +mod_kwargs = {'subdir'} +mod_kwargs.update(known_shmod_kwargs) +mod_kwargs -= {'name_prefix', 'name_suffix'} + + +class PythonExternalProgram(BasicPythonExternalProgram): + + # This is a ClassVar instead of an instance bool, because although an + # installation is cached, we actually copy it, modify attributes such as pure, + # and return a temporary one rather than the cached object. + run_bytecompile: T.ClassVar[T.Dict[str, bool]] = {} + + def sanity(self, state: T.Optional['ModuleState'] = None) -> bool: + ret = super().sanity() + if ret: + self.platlib = self._get_path(state, 'platlib') + self.purelib = self._get_path(state, 'purelib') + return ret + + def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None: + rel_path = self.info['install_paths'][key][1:] + if not state: + # This happens only from run_project_tests.py + return rel_path + value = state.get_option(f'{key}dir', module='python') + if value: + if state.is_user_defined_option('install_env', module='python'): + raise mesonlib.MesonException(f'python.{key}dir and python.install_env are mutually exclusive') + return value + + install_env = state.get_option('install_env', module='python') + if install_env == 'auto': + install_env = 'venv' if self.info['is_venv'] else 'system' + + if install_env == 'system': + rel_path = os.path.join(self.info['variables']['prefix'], rel_path) + elif install_env == 'venv': + if not self.info['is_venv']: + raise mesonlib.MesonException('python.install_env cannot be set to "venv" unless you are in a venv!') + # inside a venv, deb_system is *never* active hence info['paths'] may be wrong + rel_path = self.info['sysconfig_paths'][key] + + return rel_path + + +_PURE_KW = KwargInfo('pure', (bool, NoneType)) +_SUBDIR_KW = KwargInfo('subdir', str, default='') + + +class PythonInstallation(ExternalProgramHolder): + def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): + ExternalProgramHolder.__init__(self, python, interpreter) + info = python.info + prefix = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('prefix')) + assert isinstance(prefix, str), 'for mypy' + self.variables = info['variables'] + self.suffix = info['suffix'] + self.paths = info['paths'] + self.pure = python.pure + self.platlib_install_path = os.path.join(prefix, python.platlib) + self.purelib_install_path = os.path.join(prefix, python.purelib) + self.version = info['version'] + self.platform = info['platform'] + self.is_pypy = info['is_pypy'] + self.link_libpython = info['link_libpython'] + self.methods.update({ + 'extension_module': self.extension_module_method, + 'dependency': self.dependency_method, + 'install_sources': self.install_sources_method, + 'get_install_dir': self.get_install_dir_method, + 'language_version': self.language_version_method, + 'found': self.found_method, + 'has_path': self.has_path_method, + 'get_path': self.get_path_method, + 'has_variable': self.has_variable_method, + 'get_variable': self.get_variable_method, + 'path': self.path_method, + }) + + @permittedKwargs(mod_kwargs) + def extension_module_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> 'SharedModule': + if 'install_dir' in kwargs: + if 'subdir' in kwargs: + raise InvalidArguments('"subdir" and "install_dir" are mutually exclusive') + else: + subdir = kwargs.pop('subdir', '') + if not isinstance(subdir, str): + raise InvalidArguments('"subdir" argument must be a string.') + + kwargs['install_dir'] = self._get_install_dir_impl(False, subdir) + + new_deps = mesonlib.extract_as_list(kwargs, 'dependencies') + has_pydep = any(isinstance(dep, _PythonDependencyBase) for dep in new_deps) + if not has_pydep: + pydep = self._dependency_method_impl({}) + if not pydep.found(): + raise mesonlib.MesonException('Python dependency not found') + new_deps.append(pydep) + FeatureNew.single_use('python_installation.extension_module with implicit dependency on python', + '0.63.0', self.subproject, 'use python_installation.dependency()', + self.current_node) + kwargs['dependencies'] = new_deps + + # msys2's python3 has "-cpython-36m.dll", we have to be clever + # FIXME: explain what the specific cleverness is here + split, suffix = self.suffix.rsplit('.', 1) + args[0] += split + + kwargs['name_prefix'] = '' + kwargs['name_suffix'] = suffix + + if 'gnu_symbol_visibility' not in kwargs and \ + (self.is_pypy or mesonlib.version_compare(self.version, '>=3.9')): + kwargs['gnu_symbol_visibility'] = 'inlineshidden' + + return self.interpreter.func_shared_module(None, args, kwargs) + + def _dependency_method_impl(self, kwargs: TYPE_kwargs) -> Dependency: + for_machine = self.interpreter.machine_from_native_kwarg(kwargs) + identifier = get_dep_identifier(self._full_path(), kwargs) + + dep = self.interpreter.coredata.deps[for_machine].get(identifier) + if dep is not None: + return dep + + new_kwargs = kwargs.copy() + new_kwargs['required'] = False + candidates = python_factory(self.interpreter.environment, for_machine, new_kwargs, self.held_object) + dep = find_external_dependency('python', self.interpreter.environment, new_kwargs, candidates) + + self.interpreter.coredata.deps[for_machine].put(identifier, dep) + return dep + + @disablerIfNotFound + @permittedKwargs(permitted_dependency_kwargs | {'embed'}) + @FeatureNewKwargs('python_installation.dependency', '0.53.0', ['embed']) + @noPosargs + def dependency_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> 'Dependency': + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) + if disabled: + mlog.log('Dependency', mlog.bold('python'), 'skipped: feature', mlog.bold(feature), 'disabled') + return NotFoundDependency('python', self.interpreter.environment) + else: + dep = self._dependency_method_impl(kwargs) + if required and not dep.found(): + raise mesonlib.MesonException('Python dependency not found') + return dep + + @typed_pos_args('install_data', varargs=(str, mesonlib.File)) + @typed_kwargs( + 'python_installation.install_sources', + _PURE_KW, + _SUBDIR_KW, + PRESERVE_PATH_KW, + KwargInfo('install_tag', (str, NoneType), since='0.60.0') + ) + def install_sources_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File]]], + kwargs: 'PyInstallKw') -> 'Data': + self.held_object.run_bytecompile[self.version] = True + tag = kwargs['install_tag'] or 'python-runtime' + pure = kwargs['pure'] if kwargs['pure'] is not None else self.pure + install_dir = self._get_install_dir_impl(pure, kwargs['subdir']) + return self.interpreter.install_data_impl( + self.interpreter.source_strings_to_files(args[0]), + install_dir, + mesonlib.FileMode(), rename=None, tag=tag, install_data_type='python', + install_dir_name=install_dir.optname, + preserve_path=kwargs['preserve_path']) + + @noPosargs + @typed_kwargs('python_installation.install_dir', _PURE_KW, _SUBDIR_KW) + def get_install_dir_method(self, args: T.List['TYPE_var'], kwargs: 'PyInstallKw') -> str: + self.held_object.run_bytecompile[self.version] = True + pure = kwargs['pure'] if kwargs['pure'] is not None else self.pure + return self._get_install_dir_impl(pure, kwargs['subdir']) + + def _get_install_dir_impl(self, pure: bool, subdir: str) -> P_OBJ.OptionString: + if pure: + base = self.purelib_install_path + name = '{py_purelib}' + else: + base = self.platlib_install_path + name = '{py_platlib}' + + return P_OBJ.OptionString(os.path.join(base, subdir), os.path.join(name, subdir)) + + @noPosargs + @noKwargs + def language_version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return self.version + + @typed_pos_args('python_installation.has_path', str) + @noKwargs + def has_path_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: + return args[0] in self.paths + + @typed_pos_args('python_installation.get_path', str, optargs=[object]) + @noKwargs + def get_path_method(self, args: T.Tuple[str, T.Optional['TYPE_var']], kwargs: 'TYPE_kwargs') -> 'TYPE_var': + path_name, fallback = args + try: + return self.paths[path_name] + except KeyError: + if fallback is not None: + return fallback + raise InvalidArguments(f'{path_name} is not a valid path name') + + @typed_pos_args('python_installation.has_variable', str) + @noKwargs + def has_variable_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: + return args[0] in self.variables + + @typed_pos_args('python_installation.get_variable', str, optargs=[object]) + @noKwargs + def get_variable_method(self, args: T.Tuple[str, T.Optional['TYPE_var']], kwargs: 'TYPE_kwargs') -> 'TYPE_var': + var_name, fallback = args + try: + return self.variables[var_name] + except KeyError: + if fallback is not None: + return fallback + raise InvalidArguments(f'{var_name} is not a valid variable name') + + @noPosargs + @noKwargs + @FeatureNew('Python module path method', '0.50.0') + def path_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: + return super().path_method(args, kwargs) + + +class PythonModule(ExtensionModule): + + INFO = ModuleInfo('python', '0.46.0') + + def __init__(self, interpreter: 'Interpreter') -> None: + super().__init__(interpreter) + self.installations: T.Dict[str, ExternalProgram] = {} + self.methods.update({ + 'find_installation': self.find_installation, + }) + + def _get_install_scripts(self) -> T.List[mesonlib.ExecutableSerialisation]: + backend = self.interpreter.backend + ret = [] + optlevel = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('bytecompile', module='python')) + if optlevel == -1: + return ret + if not any(PythonExternalProgram.run_bytecompile.values()): + return ret + + installdata = backend.create_install_data() + py_files = [] + + def should_append(f, isdir: bool = False): + # This uses the install_plan decorated names to see if the original source was propagated via + # install_sources() or get_install_dir(). + return f.startswith(('{py_platlib}', '{py_purelib}')) and (f.endswith('.py') or isdir) + + for t in installdata.targets: + if should_append(t.out_name): + py_files.append((t.out_name, os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname)))) + for d in installdata.data: + if should_append(d.install_path_name): + py_files.append((d.install_path_name, os.path.join(installdata.prefix, d.install_path))) + for d in installdata.install_subdirs: + if should_append(d.install_path_name, True): + py_files.append((d.install_path_name, os.path.join(installdata.prefix, d.install_path))) + + import importlib.resources + pycompile = os.path.join(self.interpreter.environment.get_scratch_dir(), 'pycompile.py') + with open(pycompile, 'wb') as f: + f.write(importlib.resources.read_binary('mesonbuild.scripts', 'pycompile.py')) + + for i in self.installations.values(): + if isinstance(i, PythonExternalProgram) and i.run_bytecompile[i.info['version']]: + i = T.cast(PythonExternalProgram, i) + manifest = f'python-{i.info["version"]}-installed.json' + manifest_json = [] + for name, f in py_files: + if f.startswith((os.path.join(installdata.prefix, i.platlib), os.path.join(installdata.prefix, i.purelib))): + manifest_json.append(name) + with open(os.path.join(self.interpreter.environment.get_scratch_dir(), manifest), 'w', encoding='utf-8') as f: + json.dump(manifest_json, f) + cmd = i.command + [pycompile, manifest, str(optlevel)] + + script = backend.get_executable_serialisation(cmd, verbose=True, tag='python-runtime', + installdir_map={'py_purelib': i.purelib, 'py_platlib': i.platlib}) + ret.append(script) + return ret + + def postconf_hook(self, b: Build) -> None: + b.install_scripts.extend(self._get_install_scripts()) + + # https://www.python.org/dev/peps/pep-0397/ + @staticmethod + def _get_win_pythonpath(name_or_path: str) -> T.Optional[str]: + if not name_or_path.startswith(('python2', 'python3')): + return None + if not shutil.which('py'): + # program not installed, return without an exception + return None + ver = f'-{name_or_path[6:]}' + cmd = ['py', ver, '-c', "import sysconfig; print(sysconfig.get_config_var('BINDIR'))"] + _, stdout, _ = mesonlib.Popen_safe(cmd) + directory = stdout.strip() + if os.path.exists(directory): + return os.path.join(directory, 'python') + else: + return None + + def _find_installation_impl(self, state: 'ModuleState', display_name: str, name_or_path: str, required: bool) -> ExternalProgram: + if not name_or_path: + python = PythonExternalProgram('python3', mesonlib.python_command) + else: + tmp_python = ExternalProgram.from_entry(display_name, name_or_path) + python = PythonExternalProgram(display_name, ext_prog=tmp_python) + + if not python.found() and mesonlib.is_windows(): + pythonpath = self._get_win_pythonpath(name_or_path) + if pythonpath is not None: + name_or_path = pythonpath + python = PythonExternalProgram(name_or_path) + + # Last ditch effort, python2 or python3 can be named python + # on various platforms, let's not give up just yet, if an executable + # named python is available and has a compatible version, let's use + # it + if not python.found() and name_or_path in {'python2', 'python3'}: + tmp_python = ExternalProgram.from_entry(display_name, 'python') + python = PythonExternalProgram(name_or_path, ext_prog=tmp_python) + + if python.found(): + if python.sanity(state): + return python + else: + sanitymsg = f'{python} is not a valid python or it is missing distutils' + if required: + raise mesonlib.MesonException(sanitymsg) + else: + mlog.warning(sanitymsg, location=state.current_node) + + return NonExistingExternalProgram(python.name) + + @disablerIfNotFound + @typed_pos_args('python.find_installation', optargs=[str]) + @typed_kwargs( + 'python.find_installation', + KwargInfo('required', (bool, UserFeatureOption), default=True), + KwargInfo('disabler', bool, default=False, since='0.49.0'), + KwargInfo('modules', ContainerTypeInfo(list, str), listify=True, default=[], since='0.51.0'), + _PURE_KW.evolve(default=True, since='0.64.0'), + ) + def find_installation(self, state: 'ModuleState', args: T.Tuple[T.Optional[str]], + kwargs: 'FindInstallationKw') -> ExternalProgram: + feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0') + disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check) + + # FIXME: this code is *full* of sharp corners. It assumes that it's + # going to get a string value (or now a list of length 1), of `python2` + # or `python3` which is completely nonsense. On windows the value could + # easily be `['py', '-3']`, or `['py', '-3.7']` to get a very specific + # version of python. On Linux we might want a python that's not in + # $PATH, or that uses a wrapper of some kind. + np: T.List[str] = state.environment.lookup_binary_entry(MachineChoice.HOST, 'python') or [] + fallback = args[0] + display_name = fallback or 'python' + if not np and fallback is not None: + np = [fallback] + name_or_path = np[0] if np else None + + if disabled: + mlog.log('Program', name_or_path or 'python', 'found:', mlog.red('NO'), '(disabled by:', mlog.bold(feature), ')') + return NonExistingExternalProgram() + + python = self.installations.get(name_or_path) + if not python: + python = self._find_installation_impl(state, display_name, name_or_path, required) + self.installations[name_or_path] = python + + want_modules = kwargs['modules'] + found_modules: T.List[str] = [] + missing_modules: T.List[str] = [] + if python.found() and want_modules: + for mod in want_modules: + p, *_ = mesonlib.Popen_safe( + python.command + + ['-c', f'import {mod}']) + if p.returncode != 0: + missing_modules.append(mod) + else: + found_modules.append(mod) + + msg: T.List['mlog.TV_Loggable'] = ['Program', python.name] + if want_modules: + msg.append('({})'.format(', '.join(want_modules))) + msg.append('found:') + if python.found() and not missing_modules: + msg.extend([mlog.green('YES'), '({})'.format(' '.join(python.command))]) + else: + msg.append(mlog.red('NO')) + if found_modules: + msg.append('modules:') + msg.append(', '.join(found_modules)) + + mlog.log(*msg) + + if not python.found(): + if required: + raise mesonlib.MesonException('{} not found'.format(name_or_path or 'python')) + return NonExistingExternalProgram(python.name) + elif missing_modules: + if required: + raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules))) + return NonExistingExternalProgram(python.name) + else: + python = copy.copy(python) + python.pure = kwargs['pure'] + python.run_bytecompile.setdefault(python.info['version'], False) + return python + + raise mesonlib.MesonBugException('Unreachable code was reached (PythonModule.find_installation).') + + +def initialize(interpreter: 'Interpreter') -> PythonModule: + mod = PythonModule(interpreter) + mod.interpreter.append_holder_map(PythonExternalProgram, PythonInstallation) + return mod diff --git a/devtools/meson/mesonbuild/modules/python3.py b/devtools/meson/mesonbuild/modules/python3.py new file mode 100644 index 0000000..065e8d7 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/python3.py @@ -0,0 +1,85 @@ +# Copyright 2016-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import sysconfig +from .. import mesonlib + +from . import ExtensionModule, ModuleInfo +from ..interpreterbase import typed_pos_args, noPosargs, noKwargs, permittedKwargs +from ..build import known_shmod_kwargs +from ..programs import ExternalProgram + + +class Python3Module(ExtensionModule): + + INFO = ModuleInfo('python3', '0.38.0', deprecated='0.48.0') + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.methods.update({ + 'extension_module': self.extension_module, + 'find_python': self.find_python, + 'language_version': self.language_version, + 'sysconfig_path': self.sysconfig_path, + }) + + @permittedKwargs(known_shmod_kwargs) + def extension_module(self, state, args, kwargs): + if 'name_prefix' in kwargs: + raise mesonlib.MesonException('Name_prefix is set automatically, specifying it is forbidden.') + if 'name_suffix' in kwargs: + raise mesonlib.MesonException('Name_suffix is set automatically, specifying it is forbidden.') + host_system = state.host_machine.system + if host_system == 'darwin': + # Default suffix is 'dylib' but Python does not use it for extensions. + suffix = 'so' + elif host_system == 'windows': + # On Windows the extension is pyd for some unexplainable reason. + suffix = 'pyd' + else: + suffix = [] + kwargs['name_prefix'] = '' + kwargs['name_suffix'] = suffix + return self.interpreter.func_shared_module(None, args, kwargs) + + @noPosargs + @noKwargs + def find_python(self, state, args, kwargs): + command = state.environment.lookup_binary_entry(mesonlib.MachineChoice.HOST, 'python3') + if command is not None: + py3 = ExternalProgram.from_entry('python3', command) + else: + py3 = ExternalProgram('python3', mesonlib.python_command, silent=True) + return py3 + + @noPosargs + @noKwargs + def language_version(self, state, args, kwargs): + return sysconfig.get_python_version() + + @noKwargs + @typed_pos_args('python3.sysconfig_path', str) + def sysconfig_path(self, state, args, kwargs): + path_name = args[0] + valid_names = sysconfig.get_path_names() + if path_name not in valid_names: + raise mesonlib.MesonException(f'{path_name} is not a valid path name {valid_names}.') + + # Get a relative path without a prefix, e.g. lib/python3.6/site-packages + return sysconfig.get_path(path_name, vars={'base': '', 'platbase': '', 'installed_base': ''})[1:] + + +def initialize(*args, **kwargs): + return Python3Module(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/qt.py b/devtools/meson/mesonbuild/modules/qt.py new file mode 100644 index 0000000..ad438db --- /dev/null +++ b/devtools/meson/mesonbuild/modules/qt.py @@ -0,0 +1,611 @@ +# Copyright 2015 The Meson development team +# Copyright © 2021 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import shutil +import typing as T +import xml.etree.ElementTree as ET + +from . import ModuleReturnValue, ExtensionModule +from .. import build +from .. import coredata +from .. import mlog +from ..dependencies import find_external_dependency, Dependency, ExternalLibrary, InternalDependency +from ..mesonlib import MesonException, File, version_compare, Popen_safe +from ..interpreter import extract_required_kwarg +from ..interpreter.type_checking import INSTALL_DIR_KW, INSTALL_KW, NoneType +from ..interpreterbase import ContainerTypeInfo, FeatureDeprecated, KwargInfo, noPosargs, FeatureNew, typed_kwargs +from ..programs import NonExistingExternalProgram + +if T.TYPE_CHECKING: + from . import ModuleState + from ..dependencies.qt import QtPkgConfigDependency, QmakeQtDependency + from ..interpreter import Interpreter + from ..interpreter import kwargs + from ..mesonlib import FileOrString + from ..programs import ExternalProgram + + QtDependencyType = T.Union[QtPkgConfigDependency, QmakeQtDependency] + + from typing_extensions import TypedDict + + class ResourceCompilerKwArgs(TypedDict): + + """Keyword arguments for the Resource Compiler method.""" + + name: T.Optional[str] + sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + extra_args: T.List[str] + method: str + + class UICompilerKwArgs(TypedDict): + + """Keyword arguments for the Ui Compiler method.""" + + sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + extra_args: T.List[str] + method: str + + class MocCompilerKwArgs(TypedDict): + + """Keyword arguments for the Moc Compiler method.""" + + sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + headers: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + extra_args: T.List[str] + method: str + include_directories: T.List[T.Union[str, build.IncludeDirs]] + dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + + class PreprocessKwArgs(TypedDict): + + sources: T.List[FileOrString] + moc_sources: T.List[T.Union[FileOrString, build.CustomTarget]] + moc_headers: T.List[T.Union[FileOrString, build.CustomTarget]] + qresources: T.List[FileOrString] + ui_files: T.List[T.Union[FileOrString, build.CustomTarget]] + moc_extra_arguments: T.List[str] + rcc_extra_arguments: T.List[str] + uic_extra_arguments: T.List[str] + include_directories: T.List[T.Union[str, build.IncludeDirs]] + dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + method: str + + class HasToolKwArgs(kwargs.ExtractRequired): + + method: str + + class CompileTranslationsKwArgs(TypedDict): + + build_by_default: bool + install: bool + install_dir: T.Optional[str] + method: str + qresource: T.Optional[str] + rcc_extra_arguments: T.List[str] + ts_files: T.List[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + +class QtBaseModule(ExtensionModule): + _tools_detected = False + _rcc_supports_depfiles = False + _moc_supports_depfiles = False + + def __init__(self, interpreter: 'Interpreter', qt_version: int = 5): + ExtensionModule.__init__(self, interpreter) + self.qt_version = qt_version + # It is important that this list does not change order as the order of + # the returned ExternalPrograms will change as well + self.tools: T.Dict[str, T.Union[ExternalProgram, build.Executable]] = { + 'moc': NonExistingExternalProgram('moc'), + 'uic': NonExistingExternalProgram('uic'), + 'rcc': NonExistingExternalProgram('rcc'), + 'lrelease': NonExistingExternalProgram('lrelease'), + } + self.methods.update({ + 'has_tools': self.has_tools, + 'preprocess': self.preprocess, + 'compile_translations': self.compile_translations, + 'compile_resources': self.compile_resources, + 'compile_ui': self.compile_ui, + 'compile_moc': self.compile_moc, + }) + + def compilers_detect(self, state: 'ModuleState', qt_dep: 'QtDependencyType') -> None: + """Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH""" + wanted = f'== {qt_dep.version}' + + def gen_bins() -> T.Generator[T.Tuple[str, str], None, None]: + for b in self.tools: + if qt_dep.bindir: + yield os.path.join(qt_dep.bindir, b), b + if qt_dep.libexecdir: + yield os.path.join(qt_dep.libexecdir, b), b + # prefer the (official) or (unofficial) -qt + # of the tool to the plain one, as we + # don't know what the unsuffixed one points to without calling it. + yield f'{b}{qt_dep.qtver}', b + yield f'{b}-qt{qt_dep.qtver}', b + yield b, b + + for b, name in gen_bins(): + if self.tools[name].found(): + continue + + if name == 'lrelease': + arg = ['-version'] + elif version_compare(qt_dep.version, '>= 5'): + arg = ['--version'] + else: + arg = ['-v'] + + # Ensure that the version of qt and each tool are the same + def get_version(p: T.Union[ExternalProgram, build.Executable]) -> str: + _, out, err = Popen_safe(p.get_command() + arg) + if name == 'lrelease' or not qt_dep.version.startswith('4'): + care = out + else: + care = err + return care.rsplit(' ', maxsplit=1)[-1].replace(')', '').strip() + + p = state.find_program(b, required=False, + version_func=get_version, + wanted=wanted) + if p.found(): + self.tools[name] = p + + def _detect_tools(self, state: 'ModuleState', method: str, required: bool = True) -> None: + if self._tools_detected: + return + self._tools_detected = True + mlog.log(f'Detecting Qt{self.qt_version} tools') + kwargs = {'required': required, 'modules': 'Core', 'method': method} + # Just pick one to make mypy happy + qt = T.cast('QtPkgConfigDependency', find_external_dependency(f'qt{self.qt_version}', state.environment, kwargs)) + if qt.found(): + # Get all tools and then make sure that they are the right version + self.compilers_detect(state, qt) + if version_compare(qt.version, '>=5.15.0'): + self._moc_supports_depfiles = True + else: + mlog.warning('moc dependencies will not work properly until you move to Qt >= 5.15', fatal=False) + if version_compare(qt.version, '>=5.14.0'): + self._rcc_supports_depfiles = True + else: + mlog.warning('rcc dependencies will not work properly until you move to Qt >= 5.14:', + mlog.bold('https://bugreports.qt.io/browse/QTBUG-45460'), fatal=False) + else: + suffix = f'-qt{self.qt_version}' + self.tools['moc'] = NonExistingExternalProgram(name='moc' + suffix) + self.tools['uic'] = NonExistingExternalProgram(name='uic' + suffix) + self.tools['rcc'] = NonExistingExternalProgram(name='rcc' + suffix) + self.tools['lrelease'] = NonExistingExternalProgram(name='lrelease' + suffix) + + @staticmethod + def _qrc_nodes(state: 'ModuleState', rcc_file: 'FileOrString') -> T.Tuple[str, T.List[str]]: + abspath: str + if isinstance(rcc_file, str): + abspath = os.path.join(state.environment.source_dir, state.subdir, rcc_file) + else: + abspath = rcc_file.absolute_path(state.environment.source_dir, state.environment.build_dir) + rcc_dirname = os.path.dirname(abspath) + + # FIXME: what error are we actually trying to check here? (probably parse errors?) + try: + tree = ET.parse(abspath) + root = tree.getroot() + result: T.List[str] = [] + for child in root[0]: + if child.tag != 'file': + mlog.warning("malformed rcc file: ", os.path.join(state.subdir, str(rcc_file))) + break + elif child.text is None: + raise MesonException(f' element without a path in {os.path.join(state.subdir, str(rcc_file))}') + else: + result.append(child.text) + + return rcc_dirname, result + except MesonException: + raise + except Exception: + raise MesonException(f'Unable to parse resource file {abspath}') + + def _parse_qrc_deps(self, state: 'ModuleState', + rcc_file_: T.Union['FileOrString', build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]) -> T.List[File]: + result: T.List[File] = [] + inputs: T.Sequence['FileOrString'] = [] + if isinstance(rcc_file_, (str, File)): + inputs = [rcc_file_] + else: + inputs = rcc_file_.get_outputs() + + for rcc_file in inputs: + rcc_dirname, nodes = self._qrc_nodes(state, rcc_file) + for resource_path in nodes: + # We need to guess if the pointed resource is: + # a) in build directory -> implies a generated file + # b) in source directory + # c) somewhere else external dependency file to bundle + # + # Also from qrc documentation: relative path are always from qrc file + # So relative path must always be computed from qrc file ! + if os.path.isabs(resource_path): + # a) + if resource_path.startswith(os.path.abspath(state.environment.build_dir)): + resource_relpath = os.path.relpath(resource_path, state.environment.build_dir) + result.append(File(is_built=True, subdir='', fname=resource_relpath)) + # either b) or c) + else: + result.append(File(is_built=False, subdir=state.subdir, fname=resource_path)) + else: + path_from_rcc = os.path.normpath(os.path.join(rcc_dirname, resource_path)) + # a) + if path_from_rcc.startswith(state.environment.build_dir): + result.append(File(is_built=True, subdir=state.subdir, fname=resource_path)) + # b) + else: + result.append(File(is_built=False, subdir=state.subdir, fname=path_from_rcc)) + return result + + @FeatureNew('qt.has_tools', '0.54.0') + @noPosargs + @typed_kwargs( + 'qt.has_tools', + KwargInfo('required', (bool, coredata.UserFeatureOption), default=False), + KwargInfo('method', str, default='auto'), + ) + def has_tools(self, state: 'ModuleState', args: T.Tuple, kwargs: 'HasToolKwArgs') -> bool: + method = kwargs.get('method', 'auto') + # We have to cast here because TypedDicts are invariant, even though + # ExtractRequiredKwArgs is a subset of HasToolKwArgs, type checkers + # will insist this is wrong + disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, default=False) + if disabled: + mlog.log('qt.has_tools skipped: feature', mlog.bold(feature), 'disabled') + return False + self._detect_tools(state, method, required=False) + for tool in self.tools.values(): + if not tool.found(): + if required: + raise MesonException('Qt tools not found') + return False + return True + + @FeatureNew('qt.compile_resources', '0.59.0') + @noPosargs + @typed_kwargs( + 'qt.compile_resources', + KwargInfo('name', (str, NoneType)), + KwargInfo( + 'sources', + ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), allow_empty=False), + listify=True, + required=True, + ), + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('method', str, default='auto') + ) + def compile_resources(self, state: 'ModuleState', args: T.Tuple, kwargs: 'ResourceCompilerKwArgs') -> ModuleReturnValue: + """Compile Qt resources files. + + Uses CustomTargets to generate .cpp files from .qrc files. + """ + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']): + FeatureNew.single_use('qt.compile_resources: custom_target or generator for "sources" keyword argument', + '0.60.0', state.subproject, location=state.current_node) + out = self._compile_resources_impl(state, kwargs) + return ModuleReturnValue(out, [out]) + + def _compile_resources_impl(self, state: 'ModuleState', kwargs: 'ResourceCompilerKwArgs') -> T.List[build.CustomTarget]: + # Avoid the FeatureNew when dispatching from preprocess + self._detect_tools(state, kwargs['method']) + if not self.tools['rcc'].found(): + err_msg = ("{0} sources specified and couldn't find {1}, " + "please check your qt{2} installation") + raise MesonException(err_msg.format('RCC', f'rcc-qt{self.qt_version}', self.qt_version)) + + # List of generated CustomTargets + targets: T.List[build.CustomTarget] = [] + + # depfile arguments + DEPFILE_ARGS: T.List[str] = ['--depfile', '@DEPFILE@'] if self._rcc_supports_depfiles else [] + + name = kwargs['name'] + sources: T.List['FileOrString'] = [] + for s in kwargs['sources']: + if isinstance(s, (str, File)): + sources.append(s) + else: + sources.extend(s.get_outputs()) + extra_args = kwargs['extra_args'] + + # If a name was set generate a single .cpp file from all of the qrc + # files, otherwise generate one .cpp file per qrc file. + if name: + qrc_deps: T.List[File] = [] + for s in sources: + qrc_deps.extend(self._parse_qrc_deps(state, s)) + + res_target = build.CustomTarget( + name, + state.subdir, + state.subproject, + state.environment, + self.tools['rcc'].get_command() + ['-name', name, '-o', '@OUTPUT@'] + extra_args + ['@INPUT@'] + DEPFILE_ARGS, + sources, + [f'{name}.cpp'], + depend_files=qrc_deps, + depfile=f'{name}.d', + ) + targets.append(res_target) + else: + for rcc_file in sources: + qrc_deps = self._parse_qrc_deps(state, rcc_file) + if isinstance(rcc_file, str): + basename = os.path.basename(rcc_file) + else: + basename = os.path.basename(rcc_file.fname) + name = f'qt{self.qt_version}-{basename.replace(".", "_")}' + res_target = build.CustomTarget( + name, + state.subdir, + state.subproject, + state.environment, + self.tools['rcc'].get_command() + ['-name', '@BASENAME@', '-o', '@OUTPUT@'] + extra_args + ['@INPUT@'] + DEPFILE_ARGS, + [rcc_file], + [f'{name}.cpp'], + depend_files=qrc_deps, + depfile=f'{name}.d', + ) + targets.append(res_target) + + return targets + + @FeatureNew('qt.compile_ui', '0.59.0') + @noPosargs + @typed_kwargs( + 'qt.compile_ui', + KwargInfo( + 'sources', + ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), allow_empty=False), + listify=True, + required=True, + ), + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('method', str, default='auto') + ) + def compile_ui(self, state: 'ModuleState', args: T.Tuple, kwargs: 'UICompilerKwArgs') -> ModuleReturnValue: + """Compile UI resources into cpp headers.""" + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']): + FeatureNew.single_use('qt.compile_ui: custom_target or generator for "sources" keyword argument', + '0.60.0', state.subproject, location=state.current_node) + out = self._compile_ui_impl(state, kwargs) + return ModuleReturnValue(out, [out]) + + def _compile_ui_impl(self, state: 'ModuleState', kwargs: 'UICompilerKwArgs') -> build.GeneratedList: + # Avoid the FeatureNew when dispatching from preprocess + self._detect_tools(state, kwargs['method']) + if not self.tools['uic'].found(): + err_msg = ("{0} sources specified and couldn't find {1}, " + "please check your qt{2} installation") + raise MesonException(err_msg.format('UIC', f'uic-qt{self.qt_version}', self.qt_version)) + + # TODO: This generator isn't added to the generator list in the Interpreter + gen = build.Generator( + self.tools['uic'], + kwargs['extra_args'] + ['-o', '@OUTPUT@', '@INPUT@'], + ['ui_@BASENAME@.h'], + name=f'Qt{self.qt_version} ui') + return gen.process_files(kwargs['sources'], state) + + @FeatureNew('qt.compile_moc', '0.59.0') + @noPosargs + @typed_kwargs( + 'qt.compile_moc', + KwargInfo( + 'sources', + ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), + listify=True, + default=[], + ), + KwargInfo( + 'headers', + ContainerTypeInfo(list, (File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), + listify=True, + default=[] + ), + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), + KwargInfo('method', str, default='auto'), + KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]), + KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]), + ) + def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerKwArgs') -> ModuleReturnValue: + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['headers']): + FeatureNew.single_use('qt.compile_moc: custom_target or generator for "headers" keyword argument', + '0.60.0', state.subproject, location=state.current_node) + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']): + FeatureNew.single_use('qt.compile_moc: custom_target or generator for "sources" keyword argument', + '0.60.0', state.subproject, location=state.current_node) + out = self._compile_moc_impl(state, kwargs) + return ModuleReturnValue(out, [out]) + + def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') -> T.List[build.GeneratedList]: + # Avoid the FeatureNew when dispatching from preprocess + self._detect_tools(state, kwargs['method']) + if not self.tools['moc'].found(): + err_msg = ("{0} sources specified and couldn't find {1}, " + "please check your qt{2} installation") + raise MesonException(err_msg.format('MOC', f'uic-qt{self.qt_version}', self.qt_version)) + + if not (kwargs['headers'] or kwargs['sources']): + raise build.InvalidArguments('At least one of the "headers" or "sources" keyword arguments must be provided and not empty') + + inc = state.get_include_args(include_dirs=kwargs['include_directories']) + compile_args: T.List[str] = [] + for dep in kwargs['dependencies']: + compile_args.extend(a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))) + if isinstance(dep, InternalDependency): + for incl in dep.include_directories: + compile_args.extend(f'-I{i}' for i in incl.to_string_list(self.interpreter.source_root, self.interpreter.environment.build_dir)) + + output: T.List[build.GeneratedList] = [] + + # depfile arguments (defaults to .d) + DEPFILE_ARGS: T.List[str] = ['--output-dep-file'] if self._moc_supports_depfiles else [] + + arguments = kwargs['extra_args'] + DEPFILE_ARGS + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@'] + if kwargs['headers']: + moc_gen = build.Generator( + self.tools['moc'], arguments, ['moc_@BASENAME@.cpp'], + depfile='moc_@BASENAME@.cpp.d', + name=f'Qt{self.qt_version} moc header') + output.append(moc_gen.process_files(kwargs['headers'], state)) + if kwargs['sources']: + moc_gen = build.Generator( + self.tools['moc'], arguments, ['@BASENAME@.moc'], + depfile='@BASENAME@.moc.d', + name=f'Qt{self.qt_version} moc source') + output.append(moc_gen.process_files(kwargs['sources'], state)) + + return output + + # We can't use typed_pos_args here, the signature is ambiguous + @typed_kwargs( + 'qt.preprocess', + KwargInfo('sources', ContainerTypeInfo(list, (File, str)), listify=True, default=[], deprecated='0.59.0'), + KwargInfo('qresources', ContainerTypeInfo(list, (File, str)), listify=True, default=[]), + KwargInfo('ui_files', ContainerTypeInfo(list, (File, str, build.CustomTarget)), listify=True, default=[]), + KwargInfo('moc_sources', ContainerTypeInfo(list, (File, str, build.CustomTarget)), listify=True, default=[]), + KwargInfo('moc_headers', ContainerTypeInfo(list, (File, str, build.CustomTarget)), listify=True, default=[]), + KwargInfo('moc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.44.0'), + KwargInfo('rcc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.49.0'), + KwargInfo('uic_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.49.0'), + KwargInfo('method', str, default='auto'), + KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]), + KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]), + ) + def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwargs: 'PreprocessKwArgs') -> ModuleReturnValue: + _sources = args[1:] + if _sources: + FeatureDeprecated.single_use('qt.preprocess positional sources', '0.59', state.subproject, location=state.current_node) + # List is invariant, os we have to cast... + sources = T.cast('T.List[T.Union[str, File, build.GeneratedList, build.CustomTarget]]', + _sources + kwargs['sources']) + for s in sources: + if not isinstance(s, (str, File)): + raise build.InvalidArguments('Variadic arguments to qt.preprocess must be Strings or Files') + method = kwargs['method'] + + if kwargs['qresources']: + # custom output name set? -> one output file, multiple otherwise + rcc_kwargs: 'ResourceCompilerKwArgs' = {'name': '', 'sources': kwargs['qresources'], 'extra_args': kwargs['rcc_extra_arguments'], 'method': method} + if args: + name = args[0] + if not isinstance(name, str): + raise build.InvalidArguments('First argument to qt.preprocess must be a string') + rcc_kwargs['name'] = name + sources.extend(self._compile_resources_impl(state, rcc_kwargs)) + + if kwargs['ui_files']: + ui_kwargs: 'UICompilerKwArgs' = {'sources': kwargs['ui_files'], 'extra_args': kwargs['uic_extra_arguments'], 'method': method} + sources.append(self._compile_ui_impl(state, ui_kwargs)) + + if kwargs['moc_headers'] or kwargs['moc_sources']: + moc_kwargs: 'MocCompilerKwArgs' = { + 'extra_args': kwargs['moc_extra_arguments'], + 'sources': kwargs['moc_sources'], + 'headers': kwargs['moc_headers'], + 'include_directories': kwargs['include_directories'], + 'dependencies': kwargs['dependencies'], + 'method': method, + } + sources.extend(self._compile_moc_impl(state, moc_kwargs)) + + return ModuleReturnValue(sources, [sources]) + + @FeatureNew('qt.compile_translations', '0.44.0') + @noPosargs + @typed_kwargs( + 'qt.compile_translations', + KwargInfo('build_by_default', bool, default=False), + INSTALL_KW, + INSTALL_DIR_KW, + KwargInfo('method', str, default='auto'), + KwargInfo('qresource', (str, NoneType), since='0.56.0'), + KwargInfo('rcc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.56.0'), + KwargInfo('ts_files', ContainerTypeInfo(list, (str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), listify=True, default=[]), + ) + def compile_translations(self, state: 'ModuleState', args: T.Tuple, kwargs: 'CompileTranslationsKwArgs') -> ModuleReturnValue: + ts_files = kwargs['ts_files'] + if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in ts_files): + FeatureNew.single_use('qt.compile_translations: custom_target or generator for "ts_files" keyword argument', + '0.60.0', state.subproject, location=state.current_node) + if kwargs['install'] and not kwargs['install_dir']: + raise MesonException('qt.compile_translations: "install_dir" keyword argument must be set when "install" is true.') + qresource = kwargs['qresource'] + if qresource: + if ts_files: + raise MesonException('qt.compile_translations: Cannot specify both ts_files and qresource') + if os.path.dirname(qresource) != '': + raise MesonException('qt.compile_translations: qresource file name must not contain a subdirectory.') + qresource_file = File.from_built_file(state.subdir, qresource) + infile_abs = os.path.join(state.environment.source_dir, qresource_file.relative_name()) + outfile_abs = os.path.join(state.environment.build_dir, qresource_file.relative_name()) + os.makedirs(os.path.dirname(outfile_abs), exist_ok=True) + shutil.copy2(infile_abs, outfile_abs) + self.interpreter.add_build_def_file(infile_abs) + + _, nodes = self._qrc_nodes(state, qresource_file) + for c in nodes: + if c.endswith('.qm'): + ts_files.append(c.rstrip('.qm') + '.ts') + else: + raise MesonException(f'qt.compile_translations: qresource can only contain qm files, found {c}') + results = self.preprocess(state, [], {'qresources': qresource_file, 'rcc_extra_arguments': kwargs['rcc_extra_arguments']}) + self._detect_tools(state, kwargs['method']) + translations: T.List[build.CustomTarget] = [] + for ts in ts_files: + if not self.tools['lrelease'].found(): + raise MesonException('qt.compile_translations: ' + + self.tools['lrelease'].name + ' not found') + if qresource: + # In this case we know that ts_files is always a List[str], as + # it's generated above and no ts_files are passed in. However, + # mypy can't figure that out so we use assert to assure it that + # what we're doing is safe + assert isinstance(ts, str), 'for mypy' + outdir = os.path.dirname(os.path.normpath(os.path.join(state.subdir, ts))) + ts = os.path.basename(ts) + else: + outdir = state.subdir + cmd: T.List[T.Union[ExternalProgram, build.Executable, str]] = [self.tools['lrelease'], '@INPUT@', '-qm', '@OUTPUT@'] + lrelease_target = build.CustomTarget( + f'qt{self.qt_version}-compile-{ts}', + outdir, + state.subproject, + state.environment, + cmd, + [ts], + ['@BASENAME@.qm'], + install=kwargs['install'], + install_dir=[kwargs['install_dir']], + install_tag=['i18n'], + build_by_default=kwargs['build_by_default'], + ) + translations.append(lrelease_target) + if qresource: + return ModuleReturnValue(results.return_value[0], [results.new_objects, translations]) + else: + return ModuleReturnValue(translations, [translations]) diff --git a/devtools/meson/mesonbuild/modules/qt4.py b/devtools/meson/mesonbuild/modules/qt4.py new file mode 100644 index 0000000..6bdf1c5 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/qt4.py @@ -0,0 +1,34 @@ +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import typing as T + +from .qt import QtBaseModule +from . import ModuleInfo + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + + +class Qt4Module(QtBaseModule): + + INFO = ModuleInfo('qt4') + + def __init__(self, interpreter: Interpreter): + QtBaseModule.__init__(self, interpreter, qt_version=4) + + +def initialize(interp: Interpreter) -> Qt4Module: + return Qt4Module(interp) diff --git a/devtools/meson/mesonbuild/modules/qt5.py b/devtools/meson/mesonbuild/modules/qt5.py new file mode 100644 index 0000000..d9f0a5e --- /dev/null +++ b/devtools/meson/mesonbuild/modules/qt5.py @@ -0,0 +1,34 @@ +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import typing as T + +from .qt import QtBaseModule +from . import ModuleInfo + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + + +class Qt5Module(QtBaseModule): + + INFO = ModuleInfo('qt5') + + def __init__(self, interpreter: Interpreter): + QtBaseModule.__init__(self, interpreter, qt_version=5) + + +def initialize(interp: Interpreter) -> Qt5Module: + return Qt5Module(interp) diff --git a/devtools/meson/mesonbuild/modules/qt6.py b/devtools/meson/mesonbuild/modules/qt6.py new file mode 100644 index 0000000..cafc531 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/qt6.py @@ -0,0 +1,33 @@ +# Copyright 2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import typing as T + +from .qt import QtBaseModule +from . import ModuleInfo + +if T.TYPE_CHECKING: + from ..interpreter import Interpreter + +class Qt6Module(QtBaseModule): + + INFO = ModuleInfo('qt6', '0.57.0') + + def __init__(self, interpreter: Interpreter): + QtBaseModule.__init__(self, interpreter, qt_version=6) + + +def initialize(interp: Interpreter) -> Qt6Module: + return Qt6Module(interp) diff --git a/devtools/meson/mesonbuild/modules/rust.py b/devtools/meson/mesonbuild/modules/rust.py new file mode 100644 index 0000000..e6e5c63 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/rust.py @@ -0,0 +1,278 @@ +# Copyright © 2020-2023 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import typing as T + +from . import ExtensionModule, ModuleReturnValue, ModuleInfo +from .. import mlog +from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, InvalidArguments, Jar, StructuredSources +from ..compilers.compilers import are_asserts_disabled +from ..dependencies import Dependency, ExternalLibrary +from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES +from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs +from ..mesonlib import File + +if T.TYPE_CHECKING: + from . import ModuleState + from ..build import LibTypes + from ..interpreter import Interpreter + from ..interpreter import kwargs as _kwargs + from ..interpreter.interpreter import SourceInputs, SourceOutputs + from ..programs import ExternalProgram, OverrideProgram + + from typing_extensions import TypedDict + + class FuncTest(_kwargs.BaseTest): + + dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + is_parallel: bool + link_with: T.List[LibTypes] + rust_args: T.List[str] + + class FuncBindgen(TypedDict): + + args: T.List[str] + c_args: T.List[str] + include_directories: T.List[IncludeDirs] + input: T.List[SourceInputs] + output: str + dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + + +class RustModule(ExtensionModule): + + """A module that holds helper functions for rust.""" + + INFO = ModuleInfo('rust', '0.57.0', stabilized='1.0.0') + + def __init__(self, interpreter: Interpreter) -> None: + super().__init__(interpreter) + self._bindgen_bin: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None + self.methods.update({ + 'test': self.test, + 'bindgen': self.bindgen, + }) + + @typed_pos_args('rust.test', str, BuildTarget) + @typed_kwargs( + 'rust.test', + *TEST_KWS, + DEPENDENCIES_KW, + LINK_WITH_KW.evolve(since='1.2.0'), + KwargInfo( + 'rust_args', + ContainerTypeInfo(list, str), + listify=True, + default=[], + since='1.2.0', + ), + KwargInfo('is_parallel', bool, default=False), + ) + def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: FuncTest) -> ModuleReturnValue: + """Generate a rust test target from a given rust target. + + Rust puts it's unitests inside it's main source files, unlike most + languages that put them in external files. This means that normally + you have to define two separate targets with basically the same + arguments to get tests: + + ```meson + rust_lib_sources = [...] + rust_lib = static_library( + 'rust_lib', + rust_lib_sources, + ) + + rust_lib_test = executable( + 'rust_lib_test', + rust_lib_sources, + rust_args : ['--test'], + ) + + test( + 'rust_lib_test', + rust_lib_test, + protocol : 'rust', + ) + ``` + + This is all fine, but not very DRY. This method makes it much easier + to define rust tests: + + ```meson + rust = import('unstable-rust') + + rust_lib = static_library( + 'rust_lib', + [sources], + ) + + rust.test('rust_lib_test', rust_lib) + ``` + """ + if any(isinstance(t, Jar) for t in kwargs.get('link_with', [])): + raise InvalidArguments('Rust tests cannot link with Jar targets') + + name = args[0] + base_target: BuildTarget = args[1] + if not base_target.uses_rust(): + raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target') + extra_args = kwargs['args'] + + # Delete any arguments we don't want passed + if '--test' in extra_args: + mlog.warning('Do not add --test to rustmod.test arguments') + extra_args.remove('--test') + if '--format' in extra_args: + mlog.warning('Do not add --format to rustmod.test arguments') + i = extra_args.index('--format') + # Also delete the argument to --format + del extra_args[i + 1] + del extra_args[i] + for i, a in enumerate(extra_args): + if isinstance(a, str) and a.startswith('--format='): + del extra_args[i] + break + + # We need to cast here, as currently these don't have protocol in them, but test itself does. + tkwargs = T.cast('_kwargs.FuncTest', kwargs.copy()) + + tkwargs['args'] = extra_args + ['--test', '--format', 'pretty'] + tkwargs['protocol'] = 'rust' + + new_target_kwargs = base_target.original_kwargs.copy() + # Don't mutate the shallow copied list, instead replace it with a new + # one + new_target_kwargs['rust_args'] = \ + new_target_kwargs.get('rust_args', []) + kwargs['rust_args'] + ['--test'] + new_target_kwargs['install'] = False + new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + kwargs['dependencies'] + new_target_kwargs['link_with'] = new_target_kwargs.get('link_with', []) + kwargs['link_with'] + + sources = T.cast('T.List[SourceOutputs]', base_target.sources.copy()) + sources.extend(base_target.generated) + + new_target = Executable( + name, base_target.subdir, state.subproject, base_target.for_machine, + sources, base_target.structured_sources, + base_target.objects, base_target.environment, base_target.compilers, + new_target_kwargs + ) + + test = self.interpreter.make_test( + self.interpreter.current_node, (name, new_target), tkwargs) + + return ModuleReturnValue(None, [new_target, test]) + + @noPosargs + @typed_kwargs( + 'rust.bindgen', + KwargInfo('c_args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo('args', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo( + 'input', + ContainerTypeInfo(list, (File, GeneratedList, BuildTarget, BothLibraries, ExtractedObjects, CustomTargetIndex, CustomTarget, str), allow_empty=False), + default=[], + listify=True, + required=True, + ), + INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), + OUTPUT_KW, + DEPENDENCIES_KW.evolve(since='1.0.0'), + ) + def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> ModuleReturnValue: + """Wrapper around bindgen to simplify it's use. + + The main thing this simplifies is the use of `include_directory` + objects, instead of having to pass a plethora of `-I` arguments. + """ + header, *_deps = self.interpreter.source_strings_to_files(kwargs['input']) + + # Split File and Target dependencies to add pass to CustomTarget + depends: T.List[SourceOutputs] = [] + depend_files: T.List[File] = [] + for d in _deps: + if isinstance(d, File): + depend_files.append(d) + else: + depends.append(d) + + # Copy to avoid subsequent calls mutating the original + # TODO: if we want this to be per-machine we'll need a native kwarg + clang_args = state.environment.properties.host.get_bindgen_clang_args().copy() + + for i in state.process_include_dirs(kwargs['include_directories']): + # bindgen always uses clang, so it's safe to hardcode -I here + clang_args.extend([f'-I{x}' for x in i.to_string_list( + state.environment.get_source_dir(), state.environment.get_build_dir())]) + if are_asserts_disabled(state.environment.coredata.options): + clang_args.append('-DNDEBUG') + + for de in kwargs['dependencies']: + for i in de.get_include_dirs(): + clang_args.extend([f'-I{x}' for x in i.to_string_list( + state.environment.get_source_dir(), state.environment.get_build_dir())]) + clang_args.extend(de.get_all_compile_args()) + for s in de.get_sources(): + if isinstance(s, File): + depend_files.append(s) + elif isinstance(s, CustomTarget): + depends.append(s) + + clang_args.extend(state.global_args.get('c', [])) + clang_args.extend(state.project_args.get('c', [])) + cargs = state.get_option('args', state.subproject, lang='c') + assert isinstance(cargs, list), 'for mypy' + clang_args.extend(cargs) + + if self._bindgen_bin is None: + self._bindgen_bin = state.find_program('bindgen') + + name: str + if isinstance(header, File): + name = header.fname + elif isinstance(header, (BuildTarget, BothLibraries, ExtractedObjects, StructuredSources)): + raise InterpreterException('bindgen source file must be a C header, not an object or build target') + else: + name = header.get_outputs()[0] + + cmd = self._bindgen_bin.get_command() + \ + [ + '@INPUT@', '--output', + os.path.join(state.environment.build_dir, '@OUTPUT@') + ] + \ + kwargs['args'] + ['--'] + kwargs['c_args'] + clang_args + \ + ['-MD', '-MQ', '@INPUT@', '-MF', '@DEPFILE@'] + + target = CustomTarget( + f'rustmod-bindgen-{name}'.replace('/', '_'), + state.subdir, + state.subproject, + state.environment, + cmd, + [header], + [kwargs['output']], + depfile='@PLAINNAME@.d', + extra_depends=depends, + depend_files=depend_files, + backend=state.backend, + ) + + return ModuleReturnValue([target], [target]) + + +def initialize(interp: Interpreter) -> RustModule: + return RustModule(interp) diff --git a/devtools/meson/mesonbuild/modules/simd.py b/devtools/meson/mesonbuild/modules/simd.py new file mode 100644 index 0000000..3ee0858 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/simd.py @@ -0,0 +1,88 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mesonlib, compilers, mlog +from .. import build + +from . import ExtensionModule, ModuleInfo + +class SimdModule(ExtensionModule): + + INFO = ModuleInfo('SIMD', '0.42.0', unstable=True) + + def __init__(self, interpreter): + super().__init__(interpreter) + # FIXME add Altivec and AVX512. + self.isets = ('mmx', + 'sse', + 'sse2', + 'sse3', + 'ssse3', + 'sse41', + 'sse42', + 'avx', + 'avx2', + 'neon', + ) + self.methods.update({ + 'check': self.check, + }) + + def check(self, state, args, kwargs): + result = [] + if len(args) != 1: + raise mesonlib.MesonException('Check requires one argument, a name prefix for checks.') + prefix = args[0] + if not isinstance(prefix, str): + raise mesonlib.MesonException('Argument must be a string.') + if 'compiler' not in kwargs: + raise mesonlib.MesonException('Must specify compiler keyword') + if 'sources' in kwargs: + raise mesonlib.MesonException('SIMD module does not support the "sources" keyword') + basic_kwargs = {} + for key, value in kwargs.items(): + if key not in self.isets and key != 'compiler': + basic_kwargs[key] = value + compiler = kwargs['compiler'] + if not isinstance(compiler, compilers.compilers.Compiler): + raise mesonlib.MesonException('Compiler argument must be a compiler object.') + conf = build.ConfigurationData() + for iset in self.isets: + if iset not in kwargs: + continue + iset_fname = kwargs[iset] # Might also be an array or Files. static_library will validate. + args = compiler.get_instruction_set_args(iset) + if args is None: + mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) + continue + if args: + if not compiler.has_multi_arguments(args, state.environment)[0]: + mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) + continue + mlog.log('Compiler supports %s:' % iset, mlog.green('YES')) + conf.values['HAVE_' + iset.upper()] = ('1', 'Compiler supports %s.' % iset) + libname = prefix + '_' + iset + lib_kwargs = {'sources': iset_fname, + } + lib_kwargs.update(basic_kwargs) + langarg_key = compiler.get_language() + '_args' + old_lang_args = mesonlib.extract_as_list(lib_kwargs, langarg_key) + all_lang_args = old_lang_args + args + lib_kwargs[langarg_key] = all_lang_args + result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs)) + return [result, conf] + +def initialize(*args, **kwargs): + return SimdModule(*args, **kwargs) diff --git a/devtools/meson/mesonbuild/modules/sourceset.py b/devtools/meson/mesonbuild/modules/sourceset.py new file mode 100644 index 0000000..c35416e --- /dev/null +++ b/devtools/meson/mesonbuild/modules/sourceset.py @@ -0,0 +1,307 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import typing as T + +from . import ExtensionModule, ModuleObject, MutableModuleObject, ModuleInfo +from .. import build +from .. import dependencies +from .. import mesonlib +from ..interpreterbase import ( + noPosargs, noKwargs, + InterpreterException, InvalidArguments, InvalidCode, FeatureNew, +) +from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args +from ..mesonlib import OrderedSet + +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from ..interpreter import Interpreter + from ..interpreterbase import TYPE_var, TYPE_kwargs + + class AddKwargs(TypedDict): + + when: T.List[T.Union[str, dependencies.Dependency]] + if_true: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes, dependencies.Dependency]] + if_false: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] + + class AddAllKw(TypedDict): + + when: T.List[T.Union[str, dependencies.Dependency]] + if_true: T.List[SourceSetImpl] + + class ApplyKw(TypedDict): + + strict: bool + + +_WHEN_KW: KwargInfo[T.List[T.Union[str, dependencies.Dependency]]] = KwargInfo( + 'when', + ContainerTypeInfo(list, (str, dependencies.Dependency)), + listify=True, + default=[], +) + + +class SourceSetRule(T.NamedTuple): + keys: T.List[str] + """Configuration keys that enable this rule if true""" + + deps: T.List[dependencies.Dependency] + """Dependencies that enable this rule if true""" + + sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] + """Source files added when this rule's conditions are true""" + + extra_deps: T.List[dependencies.Dependency] + """Dependencies added when this rule's conditions are true, but + that do not make the condition false if they're absent.""" + + sourcesets: T.List[SourceSetImpl] + """Other sourcesets added when this rule's conditions are true""" + + if_false: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] + """Source files added when this rule's conditions are false""" + + +class SourceFiles(T.NamedTuple): + sources: OrderedSet[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] + deps: OrderedSet[dependencies.Dependency] + + +class SourceSet: + """Base class to avoid circular references. + + Because of error messages, this class is called SourceSet, and the actual + implementation is an Impl. + """ + + +class SourceSetImpl(SourceSet, MutableModuleObject): + def __init__(self, interpreter: Interpreter): + super().__init__() + self.rules: T.List[SourceSetRule] = [] + self.subproject = interpreter.subproject + self.environment = interpreter.environment + self.subdir = interpreter.subdir + self.frozen = False + self.methods.update({ + 'add': self.add_method, + 'add_all': self.add_all_method, + 'all_sources': self.all_sources_method, + 'all_dependencies': self.all_dependencies_method, + 'apply': self.apply_method, + }) + + def check_source_files(self, args: T.Sequence[T.Union[mesonlib.FileOrString, build.GeneratedTypes, dependencies.Dependency]], + ) -> T.Tuple[T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]], T.List[dependencies.Dependency]]: + sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]] = [] + deps: T.List[dependencies.Dependency] = [] + for x in args: + if isinstance(x, dependencies.Dependency): + deps.append(x) + else: + sources.append(x) + to_check: T.List[str] = [] + + # Get the actual output names to check + for s in sources: + if isinstance(s, str): + to_check.append(s) + elif isinstance(s, mesonlib.File): + to_check.append(s.fname) + else: + to_check.extend(s.get_outputs()) + mesonlib.check_direntry_issues(to_check) + return sources, deps + + def check_conditions(self, args: T.Sequence[T.Union[str, dependencies.Dependency]] + ) -> T.Tuple[T.List[str], T.List[dependencies.Dependency]]: + keys: T.List[str] = [] + deps: T.List[dependencies.Dependency] = [] + for x in args: + if isinstance(x, str): + keys.append(x) + else: + deps.append(x) + return keys, deps + + @typed_pos_args('sourceset.add', varargs=(str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex, dependencies.Dependency)) + @typed_kwargs( + 'sourceset.add', + _WHEN_KW, + KwargInfo( + 'if_true', + ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex, dependencies.Dependency)), + listify=True, + default=[], + ), + KwargInfo( + 'if_false', + ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), + listify=True, + default=[], + ), + ) + def add_method(self, state: ModuleState, + args: T.Tuple[T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes, dependencies.Dependency]]], + kwargs: AddKwargs) -> None: + if self.frozen: + raise InvalidCode('Tried to use \'add\' after querying the source set') + when = kwargs['when'] + if_true = kwargs['if_true'] + if_false = kwargs['if_false'] + if not any([when, if_true, if_false]): + if_true = args[0] + elif args[0]: + raise InterpreterException('add called with both positional and keyword arguments') + keys, dependencies = self.check_conditions(when) + sources, extra_deps = self.check_source_files(if_true) + if_false, _ = self.check_source_files(if_false) + self.rules.append(SourceSetRule(keys, dependencies, sources, extra_deps, [], if_false)) + + @typed_pos_args('sourceset.add_all', varargs=SourceSet) + @typed_kwargs( + 'sourceset.add_all', + _WHEN_KW, + KwargInfo( + 'if_true', + ContainerTypeInfo(list, SourceSet), + listify=True, + default=[], + ) + ) + def add_all_method(self, state: ModuleState, args: T.Tuple[T.List[SourceSetImpl]], + kwargs: AddAllKw) -> None: + if self.frozen: + raise InvalidCode('Tried to use \'add_all\' after querying the source set') + when = kwargs['when'] + if_true = kwargs['if_true'] + if not when and not if_true: + if_true = args[0] + elif args[0]: + raise InterpreterException('add_all called with both positional and keyword arguments') + keys, dependencies = self.check_conditions(when) + for s in if_true: + if not isinstance(s, SourceSetImpl): + raise InvalidCode('Arguments to \'add_all\' after the first must be source sets') + s.frozen = True + self.rules.append(SourceSetRule(keys, dependencies, [], [], if_true, [])) + + def collect(self, enabled_fn: T.Callable[[str], bool], + all_sources: bool, + into: T.Optional['SourceFiles'] = None) -> SourceFiles: + if not into: + into = SourceFiles(OrderedSet(), OrderedSet()) + for entry in self.rules: + if all(x.found() for x in entry.deps) and \ + all(enabled_fn(key) for key in entry.keys): + into.sources.update(entry.sources) + into.deps.update(entry.deps) + into.deps.update(entry.extra_deps) + for ss in entry.sourcesets: + ss.collect(enabled_fn, all_sources, into) + if not all_sources: + continue + into.sources.update(entry.if_false) + return into + + @noKwargs + @noPosargs + def all_sources_method(self, state: ModuleState, args: T.List[TYPE_var], kwargs: TYPE_kwargs + ) -> T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]: + self.frozen = True + files = self.collect(lambda x: True, True) + return list(files.sources) + + @noKwargs + @noPosargs + @FeatureNew('source_set.all_dependencies() method', '0.52.0') + def all_dependencies_method(self, state: ModuleState, args: T.List[TYPE_var], kwargs: TYPE_kwargs + ) -> T.List[dependencies.Dependency]: + self.frozen = True + files = self.collect(lambda x: True, True) + return list(files.deps) + + @typed_pos_args('sourceset.apply', (build.ConfigurationData, dict)) + @typed_kwargs('sourceset.apply', KwargInfo('strict', bool, default=True)) + def apply_method(self, state: ModuleState, args: T.Tuple[T.Union[build.ConfigurationData, T.Dict[str, TYPE_var]]], kwargs: ApplyKw) -> SourceFilesObject: + config_data = args[0] + self.frozen = True + strict = kwargs['strict'] + if isinstance(config_data, dict): + def _get_from_config_data(key: str) -> bool: + assert isinstance(config_data, dict), 'for mypy' + if strict and key not in config_data: + raise InterpreterException(f'Entry {key} not in configuration dictionary.') + return bool(config_data.get(key, False)) + else: + config_cache: T.Dict[str, bool] = {} + + def _get_from_config_data(key: str) -> bool: + assert isinstance(config_data, build.ConfigurationData), 'for mypy' + if key not in config_cache: + if key in config_data: + config_cache[key] = bool(config_data.get(key)[0]) + elif strict: + raise InvalidArguments(f'sourceset.apply: key "{key}" not in passed configuration, and strict set.') + else: + config_cache[key] = False + return config_cache[key] + + files = self.collect(_get_from_config_data, False) + res = SourceFilesObject(files) + return res + +class SourceFilesObject(ModuleObject): + def __init__(self, files: SourceFiles): + super().__init__() + self.files = files + self.methods.update({ + 'sources': self.sources_method, + 'dependencies': self.dependencies_method, + }) + + @noPosargs + @noKwargs + def sources_method(self, state: ModuleState, args: T.List[TYPE_var], kwargs: TYPE_kwargs + ) -> T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]: + return list(self.files.sources) + + @noPosargs + @noKwargs + def dependencies_method(self, state: ModuleState, args: T.List[TYPE_var], kwargs: TYPE_kwargs + ) -> T.List[dependencies.Dependency]: + return list(self.files.deps) + +class SourceSetModule(ExtensionModule): + + INFO = ModuleInfo('sourceset', '0.51.0') + + def __init__(self, interpreter: Interpreter): + super().__init__(interpreter) + self.methods.update({ + 'source_set': self.source_set, + }) + + @noKwargs + @noPosargs + def source_set(self, state: ModuleState, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> SourceSetImpl: + return SourceSetImpl(self.interpreter) + +def initialize(interp: Interpreter) -> SourceSetModule: + return SourceSetModule(interp) diff --git a/devtools/meson/mesonbuild/modules/wayland.py b/devtools/meson/mesonbuild/modules/wayland.py new file mode 100644 index 0000000..99f71d0 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/wayland.py @@ -0,0 +1,160 @@ +# Copyright 2022 Mark Bolhuis + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations +import os +import typing as T + +from . import ExtensionModule, ModuleReturnValue, ModuleInfo +from ..build import CustomTarget +from ..interpreter.type_checking import NoneType, in_set_validator +from ..interpreterbase import typed_pos_args, typed_kwargs, KwargInfo +from ..mesonlib import File, MesonException + +if T.TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + + from . import ModuleState + from ..build import Executable + from ..dependencies import Dependency + from ..interpreter import Interpreter + from ..programs import ExternalProgram + from ..mesonlib import FileOrString + + class ScanXML(TypedDict): + + public: bool + client: bool + server: bool + include_core_only: bool + + class FindProtocol(TypedDict): + + state: Literal['stable', 'staging', 'unstable'] + version: T.Optional[int] + +class WaylandModule(ExtensionModule): + + INFO = ModuleInfo('wayland', '0.62.0', unstable=True) + + def __init__(self, interpreter: Interpreter) -> None: + super().__init__(interpreter) + + self.protocols_dep: T.Optional[Dependency] = None + self.pkgdatadir: T.Optional[str] = None + self.scanner_bin: T.Optional[T.Union[ExternalProgram, Executable]] = None + + self.methods.update({ + 'scan_xml': self.scan_xml, + 'find_protocol': self.find_protocol, + }) + + @typed_pos_args('wayland.scan_xml', varargs=(str, File), min_varargs=1) + @typed_kwargs( + 'wayland.scan_xml', + KwargInfo('public', bool, default=False), + KwargInfo('client', bool, default=True), + KwargInfo('server', bool, default=False), + KwargInfo('include_core_only', bool, default=True, since='0.64.0'), + ) + def scan_xml(self, state: ModuleState, args: T.Tuple[T.List[FileOrString]], kwargs: ScanXML) -> ModuleReturnValue: + if self.scanner_bin is None: + # wayland-scanner from BUILD machine must have same version as wayland + # libraries from HOST machine. + dep = state.dependency('wayland-client') + self.scanner_bin = state.find_tool('wayland-scanner', 'wayland-scanner', 'wayland_scanner', + wanted=dep.version) + + scope = 'public' if kwargs['public'] else 'private' + # We have to cast because mypy can't deduce these are literals + sides = [i for i in T.cast("T.List[Literal['client', 'server']]", ['client', 'server']) if kwargs[i]] + if not sides: + raise MesonException('At least one of client or server keyword argument must be set to true.') + + xml_files = self.interpreter.source_strings_to_files(args[0]) + targets: T.List[CustomTarget] = [] + for xml_file in xml_files: + name = os.path.splitext(os.path.basename(xml_file.fname))[0] + + code = CustomTarget( + f'{name}-protocol', + state.subdir, + state.subproject, + state.environment, + [self.scanner_bin, f'{scope}-code', '@INPUT@', '@OUTPUT@'], + [xml_file], + [f'{name}-protocol.c'], + backend=state.backend, + ) + targets.append(code) + + for side in sides: + command = [self.scanner_bin, f'{side}-header', '@INPUT@', '@OUTPUT@'] + if kwargs['include_core_only']: + command.append('--include-core-only') + + header = CustomTarget( + f'{name}-{side}-protocol', + state.subdir, + state.subproject, + state.environment, + command, + [xml_file], + [f'{name}-{side}-protocol.h'], + backend=state.backend, + ) + targets.append(header) + + return ModuleReturnValue(targets, targets) + + @typed_pos_args('wayland.find_protocol', str) + @typed_kwargs( + 'wayland.find_protocol', + KwargInfo('state', str, default='stable', validator=in_set_validator({'stable', 'staging', 'unstable'})), + KwargInfo('version', (int, NoneType)), + ) + def find_protocol(self, state: ModuleState, args: T.Tuple[str], kwargs: FindProtocol) -> File: + base_name = args[0] + xml_state = kwargs['state'] + version = kwargs['version'] + + if xml_state != 'stable' and version is None: + raise MesonException(f'{xml_state} protocols require a version number.') + + if xml_state == 'stable' and version is not None: + raise MesonException('stable protocols do not require a version number.') + + if self.protocols_dep is None: + self.protocols_dep = state.dependency('wayland-protocols') + + if self.pkgdatadir is None: + self.pkgdatadir = self.protocols_dep.get_variable(pkgconfig='pkgdatadir', internal='pkgdatadir') + + if xml_state == 'stable': + xml_name = f'{base_name}.xml' + elif xml_state == 'staging': + xml_name = f'{base_name}-v{version}.xml' + else: + xml_name = f'{base_name}-unstable-v{version}.xml' + + path = os.path.join(self.pkgdatadir, xml_state, base_name, xml_name) + + if not os.path.exists(path): + raise MesonException(f'The file {path} does not exist.') + + return File.from_absolute_file(path) + + +def initialize(interpreter: Interpreter) -> WaylandModule: + return WaylandModule(interpreter) diff --git a/devtools/meson/mesonbuild/modules/windows.py b/devtools/meson/mesonbuild/modules/windows.py new file mode 100644 index 0000000..f9c7c57 --- /dev/null +++ b/devtools/meson/mesonbuild/modules/windows.py @@ -0,0 +1,214 @@ +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import enum +import os +import re +import typing as T + + +from . import ExtensionModule, ModuleInfo +from . import ModuleReturnValue +from .. import mesonlib, build +from .. import mlog +from ..interpreter.type_checking import DEPEND_FILES_KW, DEPENDS_KW, INCLUDE_DIRECTORIES +from ..interpreterbase.decorators import ContainerTypeInfo, FeatureNew, KwargInfo, typed_kwargs, typed_pos_args +from ..mesonlib import MachineChoice, MesonException +from ..programs import ExternalProgram + +if T.TYPE_CHECKING: + from . import ModuleState + from ..compilers import Compiler + from ..interpreter import Interpreter + + from typing_extensions import TypedDict + + class CompileResources(TypedDict): + + depend_files: T.List[mesonlib.FileOrString] + depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] + include_directories: T.List[T.Union[str, build.IncludeDirs]] + args: T.List[str] + + class RcKwargs(TypedDict): + output: str + input: T.List[T.Union[mesonlib.FileOrString, build.CustomTargetIndex]] + depfile: T.Optional[str] + depend_files: T.List[mesonlib.FileOrString] + depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] + command: T.List[T.Union[str, ExternalProgram]] + +class ResourceCompilerType(enum.Enum): + windres = 1 + rc = 2 + wrc = 3 + +class WindowsModule(ExtensionModule): + + INFO = ModuleInfo('windows') + + def __init__(self, interpreter: 'Interpreter'): + super().__init__(interpreter) + self._rescomp: T.Optional[T.Tuple[ExternalProgram, ResourceCompilerType]] = None + self.methods.update({ + 'compile_resources': self.compile_resources, + }) + + def detect_compiler(self, compilers: T.Dict[str, 'Compiler']) -> 'Compiler': + for l in ('c', 'cpp'): + if l in compilers: + return compilers[l] + raise MesonException('Resource compilation requires a C or C++ compiler.') + + def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[ExternalProgram, ResourceCompilerType]: + # FIXME: Does not handle `native: true` executables, see + # See https://github.com/mesonbuild/meson/issues/1531 + # Take a parameter instead of the hardcoded definition below + for_machine = MachineChoice.HOST + + if self._rescomp: + return self._rescomp + + # Will try cross / native file and then env var + rescomp = ExternalProgram.from_bin_list(state.environment, for_machine, 'windres') + + if not rescomp or not rescomp.found(): + comp = self.detect_compiler(state.environment.coredata.compilers[for_machine]) + if comp.id in {'msvc', 'clang-cl', 'intel-cl'} or (comp.linker and comp.linker.id in {'link', 'lld-link'}): + # Microsoft compilers uses rc irrespective of the frontend + rescomp = ExternalProgram('rc', silent=True) + else: + rescomp = ExternalProgram('windres', silent=True) + + if not rescomp.found(): + raise MesonException('Could not find Windows resource compiler') + + for (arg, match, rc_type) in [ + ('/?', '^.*Microsoft.*Resource Compiler.*$', ResourceCompilerType.rc), + ('/?', 'LLVM Resource Converter.*$', ResourceCompilerType.rc), + ('--version', '^.*GNU windres.*$', ResourceCompilerType.windres), + ('--version', '^.*Wine Resource Compiler.*$', ResourceCompilerType.wrc), + ]: + p, o, e = mesonlib.Popen_safe(rescomp.get_command() + [arg]) + m = re.search(match, o, re.MULTILINE) + if m: + mlog.log('Windows resource compiler: %s' % m.group()) + self._rescomp = (rescomp, rc_type) + break + else: + raise MesonException('Could not determine type of Windows resource compiler') + + return self._rescomp + + @typed_pos_args('windows.compile_resources', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex), min_varargs=1) + @typed_kwargs( + 'windows.compile_resources', + DEPEND_FILES_KW.evolve(since='0.47.0'), + DEPENDS_KW.evolve(since='0.47.0'), + INCLUDE_DIRECTORIES, + KwargInfo('args', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def compile_resources(self, state: 'ModuleState', + args: T.Tuple[T.List[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]], + kwargs: 'CompileResources') -> ModuleReturnValue: + extra_args = kwargs['args'].copy() + wrc_depend_files = kwargs['depend_files'] + wrc_depends = kwargs['depends'] + for d in wrc_depends: + if isinstance(d, build.CustomTarget): + extra_args += state.get_include_args([ + build.IncludeDirs('', [], False, [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(d))]) + ]) + extra_args += state.get_include_args(kwargs['include_directories']) + + rescomp, rescomp_type = self._find_resource_compiler(state) + if rescomp_type == ResourceCompilerType.rc: + # RC is used to generate .res files, a special binary resource + # format, which can be passed directly to LINK (apparently LINK uses + # CVTRES internally to convert this to a COFF object) + suffix = 'res' + res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@'] + elif rescomp_type == ResourceCompilerType.windres: + # ld only supports object files, so windres is used to generate a + # COFF object + suffix = 'o' + res_args = extra_args + ['@INPUT@', '@OUTPUT@'] + + m = 'Argument {!r} has a space which may not work with windres due to ' \ + 'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933' + for arg in extra_args: + if ' ' in arg: + mlog.warning(m.format(arg), fatal=False) + else: + suffix = 'o' + res_args = extra_args + ['@INPUT@', '-o', '@OUTPUT@'] + + res_targets: T.List[build.CustomTarget] = [] + + def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, build.CustomTargetIndex]]]: + for src in args[0]: + if isinstance(src, str): + yield os.path.join(state.subdir, src), src, src + elif isinstance(src, mesonlib.File): + yield src.relative_name(), src.fname, src + elif isinstance(src, build.CustomTargetIndex): + FeatureNew.single_use('windows.compile_resource CustomTargetIndex in positional arguments', '0.61.0', + state.subproject, location=state.current_node) + # This dance avoids a case where two indexes of the same + # target are given as separate arguments. + yield (f'{src.get_id()}_{src.target.get_outputs().index(src.output)}', + f'windows_compile_resources_{src.get_filename()}', src) + else: + if len(src.get_outputs()) > 1: + FeatureNew.single_use('windows.compile_resource CustomTarget with multiple outputs in positional arguments', + '0.61.0', state.subproject, location=state.current_node) + for i, out in enumerate(src.get_outputs()): + # Chances are that src.get_filename() is already the name of that + # target, add a prefix to avoid name clash. + yield f'{src.get_id()}_{i}', f'windows_compile_resources_{i}_{out}', src[i] + + for name, name_formatted, src in get_names(): + # Path separators are not allowed in target names + name = name.replace('/', '_').replace('\\', '_').replace(':', '_') + name_formatted = name_formatted.replace('/', '_').replace('\\', '_').replace(':', '_') + output = f'{name}_@BASENAME@.{suffix}' + command: T.List[T.Union[str, ExternalProgram]] = [] + command.append(rescomp) + command.extend(res_args) + depfile: T.Optional[str] = None + # instruct binutils windres to generate a preprocessor depfile + if rescomp_type == ResourceCompilerType.windres: + depfile = f'{output}.d' + command.extend(['--preprocessor-arg=-MD', + '--preprocessor-arg=-MQ@OUTPUT@', + '--preprocessor-arg=-MF@DEPFILE@']) + + res_targets.append(build.CustomTarget( + name_formatted, + state.subdir, + state.subproject, + state.environment, + command, + [src], + [output], + depfile=depfile, + depend_files=wrc_depend_files, + extra_depends=wrc_depends, + )) + + return ModuleReturnValue(res_targets, [res_targets]) + +def initialize(interp: 'Interpreter') -> WindowsModule: + return WindowsModule(interp) diff --git a/devtools/meson/mesonbuild/mparser.py b/devtools/meson/mesonbuild/mparser.py new file mode 100644 index 0000000..85f1ef3 --- /dev/null +++ b/devtools/meson/mesonbuild/mparser.py @@ -0,0 +1,954 @@ +# Copyright 2014-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations +from dataclasses import dataclass, field +import re +import codecs +import os +import typing as T + +from .mesonlib import MesonException +from . import mlog + +if T.TYPE_CHECKING: + from typing_extensions import Literal + + from .ast import AstVisitor + +# This is the regex for the supported escape sequences of a regular string +# literal, like 'abc\x00' +ESCAPE_SEQUENCE_SINGLE_RE = re.compile(r''' + ( \\U[A-Fa-f0-9]{8} # 8-digit hex escapes + | \\u[A-Fa-f0-9]{4} # 4-digit hex escapes + | \\x[A-Fa-f0-9]{2} # 2-digit hex escapes + | \\[0-7]{1,3} # Octal escapes + | \\N\{[^}]+\} # Unicode characters by name + | \\[\\'abfnrtv] # Single-character escapes + )''', re.UNICODE | re.VERBOSE) + +def decode_match(match: T.Match[str]) -> str: + return codecs.decode(match.group(0).encode(), 'unicode_escape') + +class ParseException(MesonException): + + ast: T.Optional[CodeBlockNode] = None + + def __init__(self, text: str, line: str, lineno: int, colno: int) -> None: + # Format as error message, followed by the line with the error, followed by a caret to show the error column. + super().__init__(mlog.code_line(text, line, colno)) + self.lineno = lineno + self.colno = colno + +class BlockParseException(ParseException): + def __init__( + self, + text: str, + line: str, + lineno: int, + colno: int, + start_line: str, + start_lineno: int, + start_colno: int, + ) -> None: + # This can be formatted in two ways - one if the block start and end are on the same line, and a different way if they are on different lines. + + if lineno == start_lineno: + # If block start and end are on the same line, it is formatted as: + # Error message + # Followed by the line with the error + # Followed by a caret to show the block start + # Followed by underscores + # Followed by a caret to show the block end. + MesonException.__init__(self, "{}\n{}\n{}".format(text, line, '{}^{}^'.format(' ' * start_colno, '_' * (colno - start_colno - 1)))) + else: + # If block start and end are on different lines, it is formatted as: + # Error message + # Followed by the line with the error + # Followed by a caret to show the error column. + # Followed by a message saying where the block started. + # Followed by the line of the block start. + # Followed by a caret for the block start. + MesonException.__init__(self, "%s\n%s\n%s\nFor a block that started at %d,%d\n%s\n%s" % (text, line, '%s^' % (' ' * colno), start_lineno, start_colno, start_line, "%s^" % (' ' * start_colno))) + self.lineno = lineno + self.colno = colno + +TV_TokenTypes = T.TypeVar('TV_TokenTypes', int, str, bool) + +@dataclass(eq=False) +class Token(T.Generic[TV_TokenTypes]): + tid: str + filename: str + line_start: int + lineno: int + colno: int + bytespan: T.Tuple[int, int] + value: TV_TokenTypes + + def __eq__(self, other: object) -> bool: + if isinstance(other, str): + return self.tid == other + elif isinstance(other, Token): + return self.tid == other.tid + return NotImplemented + +class Lexer: + def __init__(self, code: str): + self.code = code + self.keywords = {'true', 'false', 'if', 'else', 'elif', + 'endif', 'and', 'or', 'not', 'foreach', 'endforeach', + 'in', 'continue', 'break'} + self.future_keywords = {'return'} + self.in_unit_test = 'MESON_RUNNING_IN_PROJECT_TESTS' in os.environ + if self.in_unit_test: + self.keywords.update({'testcase', 'endtestcase'}) + self.token_specification = [ + # Need to be sorted longest to shortest. + ('ignore', re.compile(r'[ \t]')), + ('multiline_fstring', re.compile(r"f'''(.|\n)*?'''", re.M)), + ('fstring', re.compile(r"f'([^'\\]|(\\.))*'")), + ('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')), + ('number', re.compile(r'0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+|0|[1-9]\d*')), + ('eol_cont', re.compile(r'\\\n')), + ('eol', re.compile(r'\n')), + ('multiline_string', re.compile(r"'''(.|\n)*?'''", re.M)), + ('comment', re.compile(r'#.*')), + ('lparen', re.compile(r'\(')), + ('rparen', re.compile(r'\)')), + ('lbracket', re.compile(r'\[')), + ('rbracket', re.compile(r'\]')), + ('lcurl', re.compile(r'\{')), + ('rcurl', re.compile(r'\}')), + ('dblquote', re.compile(r'"')), + ('string', re.compile(r"'([^'\\]|(\\.))*'")), + ('comma', re.compile(r',')), + ('plusassign', re.compile(r'\+=')), + ('dot', re.compile(r'\.')), + ('plus', re.compile(r'\+')), + ('dash', re.compile(r'-')), + ('star', re.compile(r'\*')), + ('percent', re.compile(r'%')), + ('fslash', re.compile(r'/')), + ('colon', re.compile(r':')), + ('equal', re.compile(r'==')), + ('nequal', re.compile(r'!=')), + ('assign', re.compile(r'=')), + ('le', re.compile(r'<=')), + ('lt', re.compile(r'<')), + ('ge', re.compile(r'>=')), + ('gt', re.compile(r'>')), + ('questionmark', re.compile(r'\?')), + ] + + def getline(self, line_start: int) -> str: + return self.code[line_start:self.code.find('\n', line_start)] + + def lex(self, filename: str) -> T.Generator[Token, None, None]: + line_start = 0 + lineno = 1 + loc = 0 + par_count = 0 + bracket_count = 0 + curl_count = 0 + col = 0 + while loc < len(self.code): + matched = False + value = None # type: T.Union[str, bool, int] + for (tid, reg) in self.token_specification: + mo = reg.match(self.code, loc) + if mo: + curline = lineno + curline_start = line_start + col = mo.start() - line_start + matched = True + span_start = loc + loc = mo.end() + span_end = loc + bytespan = (span_start, span_end) + match_text = mo.group() + if tid in {'ignore', 'comment'}: + break + elif tid == 'lparen': + par_count += 1 + elif tid == 'rparen': + par_count -= 1 + elif tid == 'lbracket': + bracket_count += 1 + elif tid == 'rbracket': + bracket_count -= 1 + elif tid == 'lcurl': + curl_count += 1 + elif tid == 'rcurl': + curl_count -= 1 + elif tid == 'dblquote': + raise ParseException('Double quotes are not supported. Use single quotes.', self.getline(line_start), lineno, col) + elif tid in {'string', 'fstring'}: + # Handle here and not on the regexp to give a better error message. + if match_text.find("\n") != -1: + msg = ("Newline character in a string detected, use ''' (three single quotes) " + "for multiline strings instead.\n" + "This will become a hard error in a future Meson release.") + mlog.warning(mlog.code_line(msg, self.getline(line_start), col), location=BaseNode(lineno, col, filename)) + value = match_text[2 if tid == 'fstring' else 1:-1] + value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, value) + elif tid in {'multiline_string', 'multiline_fstring'}: + # For multiline strings, parse out the value and pass + # through the normal string logic. + # For multiline format strings, we have to emit a + # different AST node so we can add a feature check, + # but otherwise, it follows the normal fstring logic. + if tid == 'multiline_string': + value = match_text[3:-3] + tid = 'string' + else: + value = match_text[4:-3] + lines = match_text.split('\n') + if len(lines) > 1: + lineno += len(lines) - 1 + line_start = mo.end() - len(lines[-1]) + elif tid == 'number': + value = int(match_text, base=0) + elif tid == 'eol_cont': + lineno += 1 + line_start = loc + break + elif tid == 'eol': + lineno += 1 + line_start = loc + if par_count > 0 or bracket_count > 0 or curl_count > 0: + break + elif tid == 'id': + if match_text in self.keywords: + tid = match_text + else: + if match_text in self.future_keywords: + mlog.warning(f"Identifier '{match_text}' will become a reserved keyword in a future release. Please rename it.", + location=BaseNode(lineno, col, filename)) + value = match_text + yield Token(tid, filename, curline_start, curline, col, bytespan, value) + break + if not matched: + raise ParseException('lexer', self.getline(line_start), lineno, col) + +@dataclass +class BaseNode: + lineno: int + colno: int + filename: str = field(hash=False) + end_lineno: int = field(hash=False) + end_colno: int = field(hash=False) + + def __init__(self, lineno: int, colno: int, filename: str, end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None) -> None: + self.lineno = lineno + self.colno = colno + self.filename = filename + self.end_lineno = end_lineno if end_lineno is not None else lineno + self.end_colno = end_colno if end_colno is not None else colno + + # Attributes for the visitors + self.level = 0 + self.ast_id = '' + self.condition_level = 0 + + def accept(self, visitor: 'AstVisitor') -> None: + fname = 'visit_{}'.format(type(self).__name__) + if hasattr(visitor, fname): + func = getattr(visitor, fname) + if callable(func): + func(self) + +@dataclass(unsafe_hash=True) +class ElementaryNode(T.Generic[TV_TokenTypes], BaseNode): + + value: TV_TokenTypes + bytespan: T.Tuple[int, int] = field(hash=False) + + def __init__(self, token: Token[TV_TokenTypes]): + super().__init__(token.lineno, token.colno, token.filename) + self.value = token.value + self.bytespan = token.bytespan + +class BooleanNode(ElementaryNode[bool]): + pass + +class IdNode(ElementaryNode[str]): + def __str__(self) -> str: + return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) + +class NumberNode(ElementaryNode[int]): + pass + +class StringNode(ElementaryNode[str]): + def __str__(self) -> str: + return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) + +class FormatStringNode(ElementaryNode[str]): + def __str__(self) -> str: + return f"Format string node: '{self.value}' ({self.lineno}, {self.colno})." + +class MultilineFormatStringNode(FormatStringNode): + def __str__(self) -> str: + return f"Multiline Format string node: '{self.value}' ({self.lineno}, {self.colno})." + +class ContinueNode(ElementaryNode): + pass + +class BreakNode(ElementaryNode): + pass + +@dataclass(unsafe_hash=True) +class ArgumentNode(BaseNode): + + arguments: T.List[BaseNode] = field(hash=False) + commas: T.List[Token] = field(hash=False) + kwargs: T.Dict[BaseNode, BaseNode] = field(hash=False) + + def __init__(self, token: Token[TV_TokenTypes]): + super().__init__(token.lineno, token.colno, token.filename) + self.arguments = [] + self.commas = [] + self.kwargs = {} + self.order_error = False + + def prepend(self, statement: BaseNode) -> None: + if self.num_kwargs() > 0: + self.order_error = True + if not isinstance(statement, EmptyNode): + self.arguments = [statement] + self.arguments + + def append(self, statement: BaseNode) -> None: + if self.num_kwargs() > 0: + self.order_error = True + if not isinstance(statement, EmptyNode): + self.arguments += [statement] + + def set_kwarg(self, name: IdNode, value: BaseNode) -> None: + if any((isinstance(x, IdNode) and name.value == x.value) for x in self.kwargs): + mlog.warning(f'Keyword argument "{name.value}" defined multiple times.', location=self) + mlog.warning('This will be an error in future Meson releases.') + self.kwargs[name] = value + + def set_kwarg_no_check(self, name: BaseNode, value: BaseNode) -> None: + self.kwargs[name] = value + + def num_args(self) -> int: + return len(self.arguments) + + def num_kwargs(self) -> int: + return len(self.kwargs) + + def incorrect_order(self) -> bool: + return self.order_error + + def __len__(self) -> int: + return self.num_args() # Fixme + +@dataclass(unsafe_hash=True) +class ArrayNode(BaseNode): + + args: ArgumentNode + + def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int): + super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) + self.args = args + +@dataclass(unsafe_hash=True) +class DictNode(BaseNode): + + args: ArgumentNode + + def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int): + super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) + self.args = args + +class EmptyNode(BaseNode): + pass + +@dataclass(unsafe_hash=True) +class OrNode(BaseNode): + + left: BaseNode + right: BaseNode + + def __init__(self, left: BaseNode, right: BaseNode): + super().__init__(left.lineno, left.colno, left.filename) + self.left = left + self.right = right + +@dataclass(unsafe_hash=True) +class AndNode(BaseNode): + + left: BaseNode + right: BaseNode + + def __init__(self, left: BaseNode, right: BaseNode): + super().__init__(left.lineno, left.colno, left.filename) + self.left = left + self.right = right + +@dataclass(unsafe_hash=True) +class ComparisonNode(BaseNode): + + left: BaseNode + right: BaseNode + ctype: COMPARISONS + + def __init__(self, ctype: COMPARISONS, left: BaseNode, right: BaseNode): + super().__init__(left.lineno, left.colno, left.filename) + self.left = left + self.right = right + self.ctype = ctype + +@dataclass(unsafe_hash=True) +class ArithmeticNode(BaseNode): + + left: BaseNode + right: BaseNode + # TODO: use a Literal for operation + operation: str + + def __init__(self, operation: str, left: BaseNode, right: BaseNode): + super().__init__(left.lineno, left.colno, left.filename) + self.left = left + self.right = right + self.operation = operation + + +@dataclass(unsafe_hash=True) +class NotNode(BaseNode): + + value: BaseNode + + def __init__(self, token: Token[TV_TokenTypes], value: BaseNode): + super().__init__(token.lineno, token.colno, token.filename) + self.value = value + +@dataclass(unsafe_hash=True) +class CodeBlockNode(BaseNode): + + lines: T.List[BaseNode] = field(hash=False) + + def __init__(self, token: Token[TV_TokenTypes]): + super().__init__(token.lineno, token.colno, token.filename) + self.lines = [] + +@dataclass(unsafe_hash=True) +class IndexNode(BaseNode): + + iobject: BaseNode + index: BaseNode + + def __init__(self, iobject: BaseNode, index: BaseNode): + super().__init__(iobject.lineno, iobject.colno, iobject.filename) + self.iobject = iobject + self.index = index + +@dataclass(unsafe_hash=True) +class MethodNode(BaseNode): + + source_object: BaseNode + name: str + args: ArgumentNode + + def __init__(self, filename: str, lineno: int, colno: int, source_object: BaseNode, name: str, args: ArgumentNode): + super().__init__(lineno, colno, filename) + self.source_object = source_object + self.name = name + assert isinstance(self.name, str) + self.args = args + +@dataclass(unsafe_hash=True) +class FunctionNode(BaseNode): + + func_name: str + args: ArgumentNode + + def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, func_name: str, args: ArgumentNode): + super().__init__(lineno, colno, filename, end_lineno=end_lineno, end_colno=end_colno) + self.func_name = func_name + assert isinstance(func_name, str) + self.args = args + + +@dataclass(unsafe_hash=True) +class AssignmentNode(BaseNode): + + var_name: str + value: BaseNode + + def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode): + super().__init__(lineno, colno, filename) + self.var_name = var_name + assert isinstance(var_name, str) + self.value = value + + +@dataclass(unsafe_hash=True) +class PlusAssignmentNode(BaseNode): + + var_name: str + value: BaseNode + + def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode): + super().__init__(lineno, colno, filename) + self.var_name = var_name + assert isinstance(var_name, str) + self.value = value + + +@dataclass(unsafe_hash=True) +class ForeachClauseNode(BaseNode): + + varnames: T.List[str] = field(hash=False) + items: BaseNode + block: CodeBlockNode + + def __init__(self, token: Token, varnames: T.List[str], items: BaseNode, block: CodeBlockNode): + super().__init__(token.lineno, token.colno, token.filename) + self.varnames = varnames + self.items = items + self.block = block + + +@dataclass(unsafe_hash=True) +class IfNode(BaseNode): + + condition: BaseNode + block: CodeBlockNode + + def __init__(self, linenode: BaseNode, condition: BaseNode, block: CodeBlockNode): + super().__init__(linenode.lineno, linenode.colno, linenode.filename) + self.condition = condition + self.block = block + + +@dataclass(unsafe_hash=True) +class IfClauseNode(BaseNode): + + ifs: T.List[IfNode] = field(hash=False) + elseblock: T.Union[EmptyNode, CodeBlockNode] + + def __init__(self, linenode: BaseNode): + super().__init__(linenode.lineno, linenode.colno, linenode.filename) + self.ifs = [] + self.elseblock = None + +@dataclass(unsafe_hash=True) +class TestCaseClauseNode(BaseNode): + + condition: BaseNode + block: CodeBlockNode + + def __init__(self, condition: BaseNode, block: CodeBlockNode): + super().__init__(condition.lineno, condition.colno, condition.filename) + self.condition = condition + self.block = block + +@dataclass(unsafe_hash=True) +class UMinusNode(BaseNode): + + value: BaseNode + + def __init__(self, current_location: Token, value: BaseNode): + super().__init__(current_location.lineno, current_location.colno, current_location.filename) + self.value = value + + +@dataclass(unsafe_hash=True) +class TernaryNode(BaseNode): + + condition: BaseNode + trueblock: BaseNode + falseblock: BaseNode + + def __init__(self, condition: BaseNode, trueblock: BaseNode, falseblock: BaseNode): + super().__init__(condition.lineno, condition.colno, condition.filename) + self.condition = condition + self.trueblock = trueblock + self.falseblock = falseblock + +if T.TYPE_CHECKING: + COMPARISONS = Literal['==', '!=', '<', '<=', '>=', '>', 'in', 'notin'] + +comparison_map: T.Mapping[str, COMPARISONS] = { + 'equal': '==', + 'nequal': '!=', + 'lt': '<', + 'le': '<=', + 'gt': '>', + 'ge': '>=', + 'in': 'in', + 'not in': 'notin', +} + +# Recursive descent parser for Meson's definition language. +# Very basic apart from the fact that we have many precedence +# levels so there are not enough words to describe them all. +# Enter numbering: +# +# 1 assignment +# 2 or +# 3 and +# 4 comparison +# 5 arithmetic +# 6 negation +# 7 funcall, method call +# 8 parentheses +# 9 plain token + +class Parser: + def __init__(self, code: str, filename: str): + self.lexer = Lexer(code) + self.stream = self.lexer.lex(filename) + self.current = Token('eof', '', 0, 0, 0, (0, 0), None) # type: Token + self.getsym() + self.in_ternary = False + + def getsym(self) -> None: + try: + self.current = next(self.stream) + except StopIteration: + self.current = Token('eof', '', self.current.line_start, self.current.lineno, self.current.colno + self.current.bytespan[1] - self.current.bytespan[0], (0, 0), None) + + def getline(self) -> str: + return self.lexer.getline(self.current.line_start) + + def accept(self, s: str) -> bool: + if self.current.tid == s: + self.getsym() + return True + return False + + def accept_any(self, tids: T.Tuple[str, ...]) -> str: + tid = self.current.tid + if tid in tids: + self.getsym() + return tid + return '' + + def expect(self, s: str) -> bool: + if self.accept(s): + return True + raise ParseException(f'Expecting {s} got {self.current.tid}.', self.getline(), self.current.lineno, self.current.colno) + + def block_expect(self, s: str, block_start: Token) -> bool: + if self.accept(s): + return True + raise BlockParseException(f'Expecting {s} got {self.current.tid}.', self.getline(), self.current.lineno, self.current.colno, self.lexer.getline(block_start.line_start), block_start.lineno, block_start.colno) + + def parse(self) -> CodeBlockNode: + block = self.codeblock() + try: + self.expect('eof') + except ParseException as e: + e.ast = block + raise + return block + + def statement(self) -> BaseNode: + return self.e1() + + def e1(self) -> BaseNode: + left = self.e2() + if self.accept('plusassign'): + value = self.e1() + if not isinstance(left, IdNode): + raise ParseException('Plusassignment target must be an id.', self.getline(), left.lineno, left.colno) + assert isinstance(left.value, str) + return PlusAssignmentNode(left.filename, left.lineno, left.colno, left.value, value) + elif self.accept('assign'): + value = self.e1() + if not isinstance(left, IdNode): + raise ParseException('Assignment target must be an id.', + self.getline(), left.lineno, left.colno) + assert isinstance(left.value, str) + return AssignmentNode(left.filename, left.lineno, left.colno, left.value, value) + elif self.accept('questionmark'): + if self.in_ternary: + raise ParseException('Nested ternary operators are not allowed.', + self.getline(), left.lineno, left.colno) + self.in_ternary = True + trueblock = self.e1() + self.expect('colon') + falseblock = self.e1() + self.in_ternary = False + return TernaryNode(left, trueblock, falseblock) + return left + + def e2(self) -> BaseNode: + left = self.e3() + while self.accept('or'): + if isinstance(left, EmptyNode): + raise ParseException('Invalid or clause.', + self.getline(), left.lineno, left.colno) + left = OrNode(left, self.e3()) + return left + + def e3(self) -> BaseNode: + left = self.e4() + while self.accept('and'): + if isinstance(left, EmptyNode): + raise ParseException('Invalid and clause.', + self.getline(), left.lineno, left.colno) + left = AndNode(left, self.e4()) + return left + + def e4(self) -> BaseNode: + left = self.e5() + for nodename, operator_type in comparison_map.items(): + if self.accept(nodename): + return ComparisonNode(operator_type, left, self.e5()) + if self.accept('not') and self.accept('in'): + return ComparisonNode('notin', left, self.e5()) + return left + + def e5(self) -> BaseNode: + return self.e5addsub() + + def e5addsub(self) -> BaseNode: + op_map = { + 'plus': 'add', + 'dash': 'sub', + } + left = self.e5muldiv() + while True: + op = self.accept_any(tuple(op_map.keys())) + if op: + left = ArithmeticNode(op_map[op], left, self.e5muldiv()) + else: + break + return left + + def e5muldiv(self) -> BaseNode: + op_map = { + 'percent': 'mod', + 'star': 'mul', + 'fslash': 'div', + } + left = self.e6() + while True: + op = self.accept_any(tuple(op_map.keys())) + if op: + left = ArithmeticNode(op_map[op], left, self.e6()) + else: + break + return left + + def e6(self) -> BaseNode: + if self.accept('not'): + return NotNode(self.current, self.e7()) + if self.accept('dash'): + return UMinusNode(self.current, self.e7()) + return self.e7() + + def e7(self) -> BaseNode: + left = self.e8() + block_start = self.current + if self.accept('lparen'): + args = self.args() + self.block_expect('rparen', block_start) + if not isinstance(left, IdNode): + raise ParseException('Function call must be applied to plain id', + self.getline(), left.lineno, left.colno) + assert isinstance(left.value, str) + left = FunctionNode(left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left.value, args) + go_again = True + while go_again: + go_again = False + if self.accept('dot'): + go_again = True + left = self.method_call(left) + if self.accept('lbracket'): + go_again = True + left = self.index_call(left) + return left + + def e8(self) -> BaseNode: + block_start = self.current + if self.accept('lparen'): + e = self.statement() + self.block_expect('rparen', block_start) + return e + elif self.accept('lbracket'): + args = self.args() + self.block_expect('rbracket', block_start) + return ArrayNode(args, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + elif self.accept('lcurl'): + key_values = self.key_values() + self.block_expect('rcurl', block_start) + return DictNode(key_values, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + else: + return self.e9() + + def e9(self) -> BaseNode: + t = self.current + if self.accept('true'): + t.value = True + return BooleanNode(t) + if self.accept('false'): + t.value = False + return BooleanNode(t) + if self.accept('id'): + return IdNode(t) + if self.accept('number'): + return NumberNode(t) + if self.accept('string'): + return StringNode(t) + if self.accept('fstring'): + return FormatStringNode(t) + if self.accept('multiline_fstring'): + return MultilineFormatStringNode(t) + return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) + + def key_values(self) -> ArgumentNode: + s = self.statement() # type: BaseNode + a = ArgumentNode(self.current) + + while not isinstance(s, EmptyNode): + if self.accept('colon'): + a.set_kwarg_no_check(s, self.statement()) + potential = self.current + if not self.accept('comma'): + return a + a.commas.append(potential) + else: + raise ParseException('Only key:value pairs are valid in dict construction.', + self.getline(), s.lineno, s.colno) + s = self.statement() + return a + + def args(self) -> ArgumentNode: + s = self.statement() # type: BaseNode + a = ArgumentNode(self.current) + + while not isinstance(s, EmptyNode): + potential = self.current + if self.accept('comma'): + a.commas.append(potential) + a.append(s) + elif self.accept('colon'): + if not isinstance(s, IdNode): + raise ParseException('Dictionary key must be a plain identifier.', + self.getline(), s.lineno, s.colno) + a.set_kwarg(s, self.statement()) + potential = self.current + if not self.accept('comma'): + return a + a.commas.append(potential) + else: + a.append(s) + return a + s = self.statement() + return a + + def method_call(self, source_object: BaseNode) -> MethodNode: + methodname = self.e9() + if not isinstance(methodname, IdNode): + raise ParseException('Method name must be plain id', + self.getline(), self.current.lineno, self.current.colno) + assert isinstance(methodname.value, str) + self.expect('lparen') + args = self.args() + self.expect('rparen') + method = MethodNode(methodname.filename, methodname.lineno, methodname.colno, source_object, methodname.value, args) + if self.accept('dot'): + return self.method_call(method) + return method + + def index_call(self, source_object: BaseNode) -> IndexNode: + index_statement = self.statement() + self.expect('rbracket') + return IndexNode(source_object, index_statement) + + def foreachblock(self) -> ForeachClauseNode: + t = self.current + self.expect('id') + assert isinstance(t.value, str) + varname = t + varnames = [t.value] # type: T.List[str] + + if self.accept('comma'): + t = self.current + self.expect('id') + assert isinstance(t.value, str) + varnames.append(t.value) + + self.expect('colon') + items = self.statement() + block = self.codeblock() + return ForeachClauseNode(varname, varnames, items, block) + + def ifblock(self) -> IfClauseNode: + condition = self.statement() + clause = IfClauseNode(condition) + self.expect('eol') + block = self.codeblock() + clause.ifs.append(IfNode(clause, condition, block)) + self.elseifblock(clause) + clause.elseblock = self.elseblock() + return clause + + def elseifblock(self, clause: IfClauseNode) -> None: + while self.accept('elif'): + s = self.statement() + self.expect('eol') + b = self.codeblock() + clause.ifs.append(IfNode(s, s, b)) + + def elseblock(self) -> T.Union[CodeBlockNode, EmptyNode]: + if self.accept('else'): + self.expect('eol') + return self.codeblock() + return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) + + def testcaseblock(self) -> TestCaseClauseNode: + condition = self.statement() + self.expect('eol') + block = self.codeblock() + return TestCaseClauseNode(condition, block) + + def line(self) -> BaseNode: + block_start = self.current + if self.current == 'eol': + return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) + if self.accept('if'): + ifblock = self.ifblock() + self.block_expect('endif', block_start) + return ifblock + if self.accept('foreach'): + forblock = self.foreachblock() + self.block_expect('endforeach', block_start) + return forblock + if self.accept('continue'): + return ContinueNode(self.current) + if self.accept('break'): + return BreakNode(self.current) + if self.lexer.in_unit_test and self.accept('testcase'): + block = self.testcaseblock() + self.block_expect('endtestcase', block_start) + return block + return self.statement() + + def codeblock(self) -> CodeBlockNode: + block = CodeBlockNode(self.current) + cond = True + try: + while cond: + curline = self.line() + if not isinstance(curline, EmptyNode): + block.lines.append(curline) + cond = self.accept('eol') + except ParseException as e: + e.ast = block + raise + return block diff --git a/devtools/meson/mesonbuild/msetup.py b/devtools/meson/mesonbuild/msetup.py new file mode 100644 index 0000000..61d66f2 --- /dev/null +++ b/devtools/meson/mesonbuild/msetup.py @@ -0,0 +1,360 @@ +# Copyright 2016-2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import argparse, datetime, glob, json, os, platform, shutil, sys, tempfile, time +import cProfile as profile +from pathlib import Path +import typing as T + +from . import build, coredata, environment, interpreter, mesonlib, mintro, mlog +from .mesonlib import MesonException + +git_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated. +* +''' + +hg_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated. +syntax: glob +**/* +''' + + +def add_arguments(parser: argparse.ArgumentParser) -> None: + coredata.register_builtin_arguments(parser) + parser.add_argument('--native-file', + default=[], + action='append', + help='File containing overrides for native compilation environment.') + parser.add_argument('--cross-file', + default=[], + action='append', + help='File describing cross compilation environment.') + parser.add_argument('-v', '--version', action='version', + version=coredata.version) + parser.add_argument('--profile-self', action='store_true', dest='profile', + help=argparse.SUPPRESS) + parser.add_argument('--fatal-meson-warnings', action='store_true', dest='fatal_warnings', + help='Make all Meson warnings fatal') + parser.add_argument('--reconfigure', action='store_true', + help='Set options and reconfigure the project. Useful when new ' + + 'options have been added to the project and the default value ' + + 'is not working.') + parser.add_argument('--wipe', action='store_true', + help='Wipe build directory and reconfigure using previous command line options. ' + + 'Useful when build directory got corrupted, or when rebuilding with a ' + + 'newer version of meson.') + parser.add_argument('builddir', nargs='?', default=None) + parser.add_argument('sourcedir', nargs='?', default=None) + +class MesonApp: + def __init__(self, options: argparse.Namespace) -> None: + (self.source_dir, self.build_dir) = self.validate_dirs(options.builddir, + options.sourcedir, + options.reconfigure, + options.wipe) + if options.wipe: + # Make a copy of the cmd line file to make sure we can always + # restore that file if anything bad happens. For example if + # configuration fails we need to be able to wipe again. + restore = [] + with tempfile.TemporaryDirectory() as d: + for filename in [coredata.get_cmd_line_file(self.build_dir)] + glob.glob(os.path.join(self.build_dir, environment.Environment.private_dir, '*.ini')): + try: + restore.append((shutil.copy(filename, d), filename)) + except FileNotFoundError: + # validate_dirs() already verified that build_dir has + # a partial build or is empty. + pass + + coredata.read_cmd_line_file(self.build_dir, options) + + try: + # Don't delete the whole tree, just all of the files and + # folders in the tree. Otherwise calling wipe form the builddir + # will cause a crash + for l in os.listdir(self.build_dir): + l = os.path.join(self.build_dir, l) + if os.path.isdir(l) and not os.path.islink(l): + mesonlib.windows_proof_rmtree(l) + else: + mesonlib.windows_proof_rm(l) + finally: + self.add_vcs_ignore_files(self.build_dir) + for b, f in restore: + os.makedirs(os.path.dirname(f), exist_ok=True) + shutil.move(b, f) + + self.options = options + + def has_build_file(self, dirname: str) -> bool: + fname = os.path.join(dirname, environment.build_filename) + return os.path.exists(fname) + + def validate_core_dirs(self, dir1: str, dir2: str) -> T.Tuple[str, str]: + invalid_msg_prefix = f'Neither source directory {dir1!r} nor build directory {dir2!r}' + if dir1 is None: + if dir2 is None: + if not self.has_build_file('.') and self.has_build_file('..'): + dir2 = '..' + else: + raise MesonException('Must specify at least one directory name.') + dir1 = os.getcwd() + if dir2 is None: + dir2 = os.getcwd() + ndir1 = os.path.abspath(os.path.realpath(dir1)) + ndir2 = os.path.abspath(os.path.realpath(dir2)) + if not os.path.exists(ndir1) and not os.path.exists(ndir2): + raise MesonException(f'{invalid_msg_prefix} exist.') + try: + os.makedirs(ndir1, exist_ok=True) + except FileExistsError as e: + raise MesonException(f'{dir1} is not a directory') from e + try: + os.makedirs(ndir2, exist_ok=True) + except FileExistsError as e: + raise MesonException(f'{dir2} is not a directory') from e + if os.path.samefile(ndir1, ndir2): + # Fallback to textual compare if undefined entries found + has_undefined = any((s.st_ino == 0 and s.st_dev == 0) for s in (os.stat(ndir1), os.stat(ndir2))) + if not has_undefined or ndir1 == ndir2: + raise MesonException('Source and build directories must not be the same. Create a pristine build directory.') + if self.has_build_file(ndir1): + if self.has_build_file(ndir2): + raise MesonException(f'Both directories contain a build file {environment.build_filename}.') + return ndir1, ndir2 + if self.has_build_file(ndir2): + return ndir2, ndir1 + raise MesonException(f'{invalid_msg_prefix} contain a build file {environment.build_filename}.') + + def add_vcs_ignore_files(self, build_dir: str) -> None: + with open(os.path.join(build_dir, '.gitignore'), 'w', encoding='utf-8') as ofile: + ofile.write(git_ignore_file) + with open(os.path.join(build_dir, '.hgignore'), 'w', encoding='utf-8') as ofile: + ofile.write(hg_ignore_file) + + def validate_dirs(self, dir1: str, dir2: str, reconfigure: bool, wipe: bool) -> T.Tuple[str, str]: + (src_dir, build_dir) = self.validate_core_dirs(dir1, dir2) + if Path(build_dir) in Path(src_dir).parents: + raise MesonException(f'Build directory {build_dir} cannot be a parent of source directory {src_dir}') + if not os.listdir(build_dir): + self.add_vcs_ignore_files(build_dir) + return src_dir, build_dir + priv_dir = os.path.join(build_dir, 'meson-private') + has_valid_build = os.path.exists(os.path.join(priv_dir, 'coredata.dat')) + has_partial_build = os.path.isdir(priv_dir) + if has_valid_build: + if not reconfigure and not wipe: + print('Directory already configured.\n\n' + 'Just run your build command (e.g. ninja) and Meson will regenerate as necessary.\n' + 'If ninja fails, run "ninja reconfigure" or "meson setup --reconfigure"\n' + 'to force Meson to regenerate.\n\n' + 'If build failures persist, run "meson setup --wipe" to rebuild from scratch\n' + 'using the same options as passed when configuring the build.\n' + 'To change option values, run "meson configure" instead.') + # FIXME: This returns success and ignores new option values from CLI. + # We should either make this a hard error, or update options and + # return success. + # Note that making this an error would not be backward compatible (and also isn't + # universally agreed on): https://github.com/mesonbuild/meson/pull/4249. + raise SystemExit(0) + elif not has_partial_build and wipe: + raise MesonException(f'Directory is not empty and does not contain a previous build:\n{build_dir}') + return src_dir, build_dir + + # See class Backend's 'generate' for comments on capture args and returned dictionary. + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + env = environment.Environment(self.source_dir, self.build_dir, self.options) + mlog.initialize(env.get_log_dir(), self.options.fatal_warnings) + if self.options.profile: + mlog.set_timestamp_start(time.monotonic()) + with mesonlib.BuildDirLock(self.build_dir): + return self._generate(env, capture, vslite_ctx) + + def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: dict) -> T.Optional[dict]: + # Get all user defined options, including options that have been defined + # during a previous invocation or using meson configure. + user_defined_options = argparse.Namespace(**vars(self.options)) + coredata.read_cmd_line_file(self.build_dir, user_defined_options) + + mlog.debug('Build started at', datetime.datetime.now().isoformat()) + mlog.debug('Main binary:', sys.executable) + mlog.debug('Build Options:', coredata.format_cmd_line_options(user_defined_options)) + mlog.debug('Python system:', platform.system()) + mlog.log(mlog.bold('The Meson build system')) + mlog.log('Version:', coredata.version) + mlog.log('Source dir:', mlog.bold(self.source_dir)) + mlog.log('Build dir:', mlog.bold(self.build_dir)) + if env.is_cross_build(): + mlog.log('Build type:', mlog.bold('cross build')) + else: + mlog.log('Build type:', mlog.bold('native build')) + b = build.Build(env) + + intr = interpreter.Interpreter(b, user_defined_options=user_defined_options) + # Super hack because mlog.log and mlog.debug have different signatures, + # and there is currently no way to annotate them correctly, unionize them, or + # even to write `T.Callable[[*mlog.TV_Loggable], None]` + logger_fun = T.cast('T.Callable[[mlog.TV_Loggable, mlog.TV_Loggable], None]', + (mlog.log if env.is_cross_build() else mlog.debug)) + build_machine = intr.builtin['build_machine'] + host_machine = intr.builtin['host_machine'] + target_machine = intr.builtin['target_machine'] + assert isinstance(build_machine, interpreter.MachineHolder) + assert isinstance(host_machine, interpreter.MachineHolder) + assert isinstance(target_machine, interpreter.MachineHolder) + logger_fun('Build machine cpu family:', mlog.bold(build_machine.cpu_family_method([], {}))) + logger_fun('Build machine cpu:', mlog.bold(build_machine.cpu_method([], {}))) + mlog.log('Host machine cpu family:', mlog.bold(host_machine.cpu_family_method([], {}))) + mlog.log('Host machine cpu:', mlog.bold(host_machine.cpu_method([], {}))) + logger_fun('Target machine cpu family:', mlog.bold(target_machine.cpu_family_method([], {}))) + logger_fun('Target machine cpu:', mlog.bold(target_machine.cpu_method([], {}))) + try: + if self.options.profile: + fname = os.path.join(self.build_dir, 'meson-logs', 'profile-interpreter.log') + profile.runctx('intr.run()', globals(), locals(), filename=fname) + else: + intr.run() + except Exception as e: + mintro.write_meson_info_file(b, [e]) + raise + + cdf: T.Optional[str] = None + captured_compile_args: T.Optional[dict] = None + try: + dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat') + # We would like to write coredata as late as possible since we use the existence of + # this file to check if we generated the build file successfully. Since coredata + # includes settings, the build files must depend on it and appear newer. However, due + # to various kernel caches, we cannot guarantee that any time in Python is exactly in + # sync with the time that gets applied to any files. Thus, we dump this file as late as + # possible, but before build files, and if any error occurs, delete it. + cdf = env.dump_coredata() + + self.finalize_postconf_hooks(b, intr) + if self.options.profile: + fname = f'profile-{intr.backend.name}-backend.log' + fname = os.path.join(self.build_dir, 'meson-logs', fname) + profile.runctx('gen_result = intr.backend.generate(capture, vslite_ctx)', globals(), locals(), filename=fname) + captured_compile_args = locals()['gen_result'] + assert captured_compile_args is None or isinstance(captured_compile_args, dict) + else: + captured_compile_args = intr.backend.generate(capture, vslite_ctx) + + build.save(b, dumpfile) + if env.first_invocation: + # Use path resolved by coredata because they could have been + # read from a pipe and wrote into a private file. + self.options.cross_file = env.coredata.cross_files + self.options.native_file = env.coredata.config_files + coredata.write_cmd_line_file(self.build_dir, self.options) + else: + coredata.update_cmd_line_file(self.build_dir, self.options) + + # Generate an IDE introspection file with the same syntax as the already existing API + if self.options.profile: + fname = os.path.join(self.build_dir, 'meson-logs', 'profile-introspector.log') + profile.runctx('mintro.generate_introspection_file(b, intr.backend)', globals(), locals(), filename=fname) + else: + mintro.generate_introspection_file(b, intr.backend) + mintro.write_meson_info_file(b, [], True) + + # Post-conf scripts must be run after writing coredata or else introspection fails. + intr.backend.run_postconf_scripts() + + # collect warnings about unsupported build configurations; must be done after full arg processing + # by Interpreter() init, but this is most visible at the end + if env.coredata.options[mesonlib.OptionKey('backend')].value == 'xcode': + mlog.warning('xcode backend is currently unmaintained, patches welcome') + if env.coredata.options[mesonlib.OptionKey('layout')].value == 'flat': + mlog.warning('-Dlayout=flat is unsupported and probably broken. It was a failed experiment at ' + 'making Windows build artifacts runnable while uninstalled, due to PATH considerations, ' + 'but was untested by CI and anyways breaks reasonable use of conflicting targets in different subdirs. ' + 'Please consider using `meson devenv` instead. See https://github.com/mesonbuild/meson/pull/9243 ' + 'for details.') + + if self.options.profile: + fname = os.path.join(self.build_dir, 'meson-logs', 'profile-startup-modules.json') + mods = set(sys.modules.keys()) + mesonmods = {mod for mod in mods if (mod+'.').startswith('mesonbuild.')} + stdmods = sorted(mods - mesonmods) + data = {'stdlib': {'modules': stdmods, 'count': len(stdmods)}, 'meson': {'modules': sorted(mesonmods), 'count': len(mesonmods)}} + with open(fname, 'w', encoding='utf-8') as f: + json.dump(data, f) + + except Exception as e: + mintro.write_meson_info_file(b, [e]) + if cdf is not None: + old_cdf = cdf + '.prev' + if os.path.exists(old_cdf): + os.replace(old_cdf, cdf) + else: + os.unlink(cdf) + raise + + return captured_compile_args + + def finalize_postconf_hooks(self, b: build.Build, intr: interpreter.Interpreter) -> None: + b.devenv.append(intr.backend.get_devenv()) + for mod in intr.modules.values(): + mod.postconf_hook(b) + +def run_genvslite_setup(options: argparse.Namespace) -> None: + # With --genvslite, we essentially want to invoke multiple 'setup' iterations. I.e. - + # meson setup ... builddirprefix_debug + # meson setup ... builddirprefix_debugoptimized + # meson setup ... builddirprefix_release + # along with also setting up a new, thin/lite visual studio solution and projects with the multiple debug/opt/release configurations that + # invoke the appropriate 'meson compile ...' build commands upon the normal visual studio build/rebuild/clean actions, instead of using + # the native VS/msbuild system. + builddir_prefix = options.builddir + genvsliteval = options.cmd_line_options.pop(mesonlib.OptionKey('genvslite')) + # The command line may specify a '--backend' option, which doesn't make sense in conjunction with + # '--genvslite', where we always want to use a ninja back end - + k_backend = mesonlib.OptionKey('backend') + if k_backend in options.cmd_line_options.keys(): + if options.cmd_line_options[k_backend] != 'ninja': + raise MesonException('Explicitly specifying a backend option with \'genvslite\' is not necessary ' + '(the ninja backend is always used) but specifying a non-ninja backend ' + 'conflicts with a \'genvslite\' setup') + else: + options.cmd_line_options[k_backend] = 'ninja' + buildtypes_list = coredata.get_genvs_default_buildtype_list() + vslite_ctx = {} + + for buildtypestr in buildtypes_list: + options.builddir = f'{builddir_prefix}_{buildtypestr}' # E.g. builddir_release + options.cmd_line_options[mesonlib.OptionKey('buildtype')] = buildtypestr + app = MesonApp(options) + vslite_ctx[buildtypestr] = app.generate(capture=True) + #Now for generating the 'lite' solution and project files, which will use these builds we've just set up, above. + options.builddir = f'{builddir_prefix}_vs' + options.cmd_line_options[mesonlib.OptionKey('genvslite')] = genvsliteval + app = MesonApp(options) + app.generate(capture=False, vslite_ctx=vslite_ctx) + +def run(options: T.Union[argparse.Namespace, T.List[str]]) -> int: + if not isinstance(options, argparse.Namespace): + parser = argparse.ArgumentParser() + add_arguments(parser) + options = parser.parse_args(options) + coredata.parse_cmd_line_options(options) + + if mesonlib.OptionKey('genvslite') in options.cmd_line_options.keys(): + run_genvslite_setup(options) + else: + app = MesonApp(options) + app.generate() + + return 0 diff --git a/devtools/meson/mesonbuild/msubprojects.py b/devtools/meson/mesonbuild/msubprojects.py new file mode 100644 index 0000000..8f3231c --- /dev/null +++ b/devtools/meson/mesonbuild/msubprojects.py @@ -0,0 +1,736 @@ +from __future__ import annotations + +from dataclasses import dataclass, InitVar +import os, subprocess +import argparse +import asyncio +import threading +import copy +import shutil +from concurrent.futures.thread import ThreadPoolExecutor +from pathlib import Path +import typing as T +import tarfile +import zipfile + +from . import mlog +from .ast import IntrospectionInterpreter +from .mesonlib import quiet_git, GitException, Popen_safe, MesonException, windows_proof_rmtree +from .wrap.wrap import (Resolver, WrapException, ALL_TYPES, PackageDefinition, + parse_patch_url, update_wrap_file, get_releases) + +if T.TYPE_CHECKING: + from typing_extensions import Protocol + + SubParsers = argparse._SubParsersAction[argparse.ArgumentParser] + + class Arguments(Protocol): + sourcedir: str + num_processes: int + subprojects: T.List[str] + types: str + subprojects_func: T.Callable[[], bool] + allow_insecure: bool + + class UpdateArguments(Arguments): + rebase: bool + reset: bool + + class UpdateWrapDBArguments(Arguments): + force: bool + releases: T.Dict[str, T.Any] + + class CheckoutArguments(Arguments): + b: bool + branch_name: str + + class ForeachArguments(Arguments): + command: str + args: T.List[str] + + class PurgeArguments(Arguments): + confirm: bool + include_cache: bool + + class PackagefilesArguments(Arguments): + apply: bool + save: bool + +ALL_TYPES_STRING = ', '.join(ALL_TYPES) + +def read_archive_files(path: Path, base_path: Path) -> T.Set[Path]: + if path.suffix == '.zip': + with zipfile.ZipFile(path, 'r') as zip_archive: + archive_files = {base_path / i.filename for i in zip_archive.infolist()} + else: + with tarfile.open(path) as tar_archive: # [ignore encoding] + archive_files = {base_path / i.name for i in tar_archive} + return archive_files + +class Logger: + def __init__(self, total_tasks: int) -> None: + self.lock = threading.Lock() + self.total_tasks = total_tasks + self.completed_tasks = 0 + self.running_tasks: T.Set[str] = set() + self.should_erase_line = '' + + def flush(self) -> None: + if self.should_erase_line: + print(self.should_erase_line, end='\r') + self.should_erase_line = '' + + def print_progress(self) -> None: + line = f'Progress: {self.completed_tasks} / {self.total_tasks}' + max_len = shutil.get_terminal_size().columns - len(line) + running = ', '.join(self.running_tasks) + if len(running) + 3 > max_len: + running = running[:max_len - 6] + '...' + line = line + f' ({running})' + print(self.should_erase_line, line, sep='', end='\r') + self.should_erase_line = '\x1b[K' + + def start(self, wrap_name: str) -> None: + with self.lock: + self.running_tasks.add(wrap_name) + self.print_progress() + + def done(self, wrap_name: str, log_queue: T.List[T.Tuple[mlog.TV_LoggableList, T.Any]]) -> None: + with self.lock: + self.flush() + for args, kwargs in log_queue: + mlog.log(*args, **kwargs) + self.running_tasks.remove(wrap_name) + self.completed_tasks += 1 + self.print_progress() + + +@dataclass(eq=False) +class Runner: + logger: Logger + r: InitVar[Resolver] + wrap: PackageDefinition + repo_dir: str + options: 'Arguments' + + def __post_init__(self, r: Resolver) -> None: + # FIXME: Do a copy because Resolver.resolve() is stateful method that + # cannot be called from multiple threads. + self.wrap_resolver = copy.copy(r) + self.wrap_resolver.dirname = os.path.join(r.subdir_root, self.wrap.directory) + self.wrap_resolver.wrap = self.wrap + self.run_method: T.Callable[[], bool] = self.options.subprojects_func.__get__(self) + self.log_queue: T.List[T.Tuple[mlog.TV_LoggableList, T.Any]] = [] + + def log(self, *args: mlog.TV_Loggable, **kwargs: T.Any) -> None: + self.log_queue.append((list(args), kwargs)) + + def run(self) -> bool: + self.logger.start(self.wrap.name) + try: + result = self.run_method() + except MesonException as e: + self.log(mlog.red('Error:'), str(e)) + result = False + self.logger.done(self.wrap.name, self.log_queue) + return result + + @staticmethod + def pre_update_wrapdb(options: 'UpdateWrapDBArguments') -> None: + options.releases = get_releases(options.allow_insecure) + + def update_wrapdb(self) -> bool: + self.log(f'Checking latest WrapDB version for {self.wrap.name}...') + options = T.cast('UpdateWrapDBArguments', self.options) + + # Check if this wrap is in WrapDB + info = options.releases.get(self.wrap.name) + if not info: + self.log(' -> Wrap not found in wrapdb') + return True + + # Determine current version + try: + wrapdb_version = self.wrap.get('wrapdb_version') + branch, revision = wrapdb_version.split('-', 1) + except WrapException: + # Fallback to parsing the patch URL to determine current version. + # This won't work for projects that have upstream Meson support. + try: + patch_url = self.wrap.get('patch_url') + branch, revision = parse_patch_url(patch_url) + except WrapException: + if not options.force: + self.log(' ->', mlog.red('Could not determine current version, use --force to update any way')) + return False + branch = revision = None + + # Download latest wrap if version differs + latest_version = info['versions'][0] + new_branch, new_revision = latest_version.rsplit('-', 1) + if new_branch != branch or new_revision != revision: + filename = self.wrap.filename if self.wrap.has_wrap else f'{self.wrap.filename}.wrap' + update_wrap_file(filename, self.wrap.name, + new_branch, new_revision, + options.allow_insecure) + self.log(' -> New version downloaded:', mlog.blue(latest_version)) + else: + self.log(' -> Already at latest version:', mlog.blue(latest_version)) + + return True + + def update_file(self) -> bool: + options = T.cast('UpdateArguments', self.options) + if options.reset: + # Delete existing directory and redownload. It is possible that nothing + # changed but we have no way to know. Hopefully tarballs are still + # cached. + windows_proof_rmtree(self.repo_dir) + try: + self.wrap_resolver.resolve(self.wrap.name, 'meson') + self.log(' -> New version extracted') + return True + except WrapException as e: + self.log(' ->', mlog.red(str(e))) + return False + else: + # The subproject has not changed, or the new source and/or patch + # tarballs should be extracted in the same directory than previous + # version. + self.log(' -> Subproject has not changed, or the new source/patch needs to be extracted on the same location.') + self.log(' Pass --reset option to delete directory and redownload.') + return False + + def git_output(self, cmd: T.List[str]) -> str: + return quiet_git(cmd, self.repo_dir, check=True)[1] + + def git_verbose(self, cmd: T.List[str]) -> None: + self.log(self.git_output(cmd)) + + def git_stash(self) -> None: + # That git command return some output when there is something to stash. + # We don't want to stash when there is nothing to stash because that would + # print spurious "No local changes to save". + if quiet_git(['status', '--porcelain', ':!/.meson-subproject-wrap-hash.txt'], self.repo_dir)[1].strip(): + # Don't pipe stdout here because we want the user to see their changes have + # been saved. + # Note: `--all` is used, and not `--include-untracked`, to prevent + # a potential error if `.meson-subproject-wrap-hash.txt` matches a + # gitignore pattern. + # We must add the dot in addition to the negation, because older versions of git have a bug. + self.git_verbose(['stash', 'push', '--all', ':!/.meson-subproject-wrap-hash.txt', '.']) + + def git_show(self) -> None: + commit_message = self.git_output(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]']) + parts = [s.strip() for s in commit_message.split('\n')] + self.log(' ->', mlog.yellow(parts[0]), mlog.red(parts[1]), parts[2], mlog.blue(parts[3])) + + def git_rebase(self, revision: str) -> bool: + try: + self.git_output(['-c', 'rebase.autoStash=true', 'rebase', 'FETCH_HEAD']) + except GitException as e: + self.log(' -> Could not rebase', mlog.bold(self.repo_dir), 'onto', mlog.bold(revision)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + return True + + def git_reset(self, revision: str) -> bool: + try: + # Stash local changes, commits can always be found back in reflog, to + # avoid any data lost by mistake. + self.git_stash() + self.git_output(['reset', '--hard', 'FETCH_HEAD']) + self.wrap_resolver.apply_patch() + self.wrap_resolver.apply_diff_files() + except GitException as e: + self.log(' -> Could not reset', mlog.bold(self.repo_dir), 'to', mlog.bold(revision)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + return True + + def git_checkout(self, revision: str, create: bool = False) -> bool: + cmd = ['checkout', '--ignore-other-worktrees'] + if create: + cmd.append('-b') + cmd += [revision, '--'] + try: + # Stash local changes, commits can always be found back in reflog, to + # avoid any data lost by mistake. + self.git_stash() + self.git_output(cmd) + except GitException as e: + self.log(' -> Could not checkout', mlog.bold(revision), 'in', mlog.bold(self.repo_dir)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + return True + + def git_checkout_and_reset(self, revision: str) -> bool: + # revision could be a branch that already exists but is outdated, so we still + # have to reset after the checkout. + success = self.git_checkout(revision) + if success: + success = self.git_reset(revision) + return success + + def git_checkout_and_rebase(self, revision: str) -> bool: + # revision could be a branch that already exists but is outdated, so we still + # have to rebase after the checkout. + success = self.git_checkout(revision) + if success: + success = self.git_rebase(revision) + return success + + def update_git(self) -> bool: + options = T.cast('UpdateArguments', self.options) + if not os.path.exists(os.path.join(self.repo_dir, '.git')): + if options.reset: + # Delete existing directory and redownload + windows_proof_rmtree(self.repo_dir) + try: + self.wrap_resolver.resolve(self.wrap.name, 'meson') + self.update_git_done() + return True + except WrapException as e: + self.log(' ->', mlog.red(str(e))) + return False + else: + self.log(' -> Not a git repository.') + self.log('Pass --reset option to delete directory and redownload.') + return False + revision = self.wrap.values.get('revision') + url = self.wrap.values.get('url') + push_url = self.wrap.values.get('push-url') + if not revision or not url: + # It could be a detached git submodule for example. + self.log(' -> No revision or URL specified.') + return True + try: + origin_url = self.git_output(['remote', 'get-url', 'origin']).strip() + except GitException as e: + self.log(' -> Failed to determine current origin URL in', mlog.bold(self.repo_dir)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + if options.reset: + try: + self.git_output(['remote', 'set-url', 'origin', url]) + if push_url: + self.git_output(['remote', 'set-url', '--push', 'origin', push_url]) + except GitException as e: + self.log(' -> Failed to reset origin URL in', mlog.bold(self.repo_dir)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + elif url != origin_url: + self.log(f' -> URL changed from {origin_url!r} to {url!r}') + return False + try: + # Same as `git branch --show-current` but compatible with older git version + branch = self.git_output(['rev-parse', '--abbrev-ref', 'HEAD']).strip() + branch = branch if branch != 'HEAD' else '' + except GitException as e: + self.log(' -> Failed to determine current branch in', mlog.bold(self.repo_dir)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + if self.wrap_resolver.is_git_full_commit_id(revision) and \ + quiet_git(['rev-parse', '--verify', revision + '^{commit}'], self.repo_dir)[0]: + # The revision we need is both a commit and available. So we do not + # need to fetch it because it cannot be updated. Instead, trick + # git into setting FETCH_HEAD just in case, from the local commit. + self.git_output(['fetch', '.', revision]) + else: + try: + # Fetch only the revision we need, this avoids fetching useless branches. + # revision can be either a branch, tag or commit id. In all cases we want + # FETCH_HEAD to be set to the desired commit and "git checkout " + # to to either switch to existing/new branch, or detach to tag/commit. + # It is more complicated than it first appear, see discussion there: + # https://github.com/mesonbuild/meson/pull/7723#discussion_r488816189. + heads_refmap = '+refs/heads/*:refs/remotes/origin/*' + tags_refmap = '+refs/tags/*:refs/tags/*' + self.git_output(['fetch', '--refmap', heads_refmap, '--refmap', tags_refmap, 'origin', revision]) + except GitException as e: + self.log(' -> Could not fetch revision', mlog.bold(revision), 'in', mlog.bold(self.repo_dir)) + self.log(mlog.red(e.output)) + self.log(mlog.red(str(e))) + return False + + if branch == '': + # We are currently in detached mode + if options.reset: + success = self.git_checkout_and_reset(revision) + else: + success = self.git_checkout_and_rebase(revision) + elif branch == revision: + # We are in the same branch. A reset could still be needed in the case + # a force push happened on remote repository. + if options.reset: + success = self.git_reset(revision) + else: + success = self.git_rebase(revision) + else: + # We are in another branch, either the user created their own branch and + # we should rebase it, or revision changed in the wrap file and we need + # to checkout the new branch. + if options.reset: + success = self.git_checkout_and_reset(revision) + else: + success = self.git_rebase(revision) + if success: + self.update_git_done() + return success + + def update_git_done(self) -> None: + self.git_output(['submodule', 'update', '--checkout', '--recursive']) + self.git_show() + + def update_hg(self) -> bool: + revno = self.wrap.get('revision') + if revno.lower() == 'tip': + # Failure to do pull is not a fatal error, + # because otherwise you can't develop without + # a working net connection. + subprocess.call(['hg', 'pull'], cwd=self.repo_dir) + else: + if subprocess.call(['hg', 'checkout', revno], cwd=self.repo_dir) != 0: + subprocess.check_call(['hg', 'pull'], cwd=self.repo_dir) + subprocess.check_call(['hg', 'checkout', revno], cwd=self.repo_dir) + return True + + def update_svn(self) -> bool: + revno = self.wrap.get('revision') + _, out, _ = Popen_safe(['svn', 'info', '--show-item', 'revision', self.repo_dir]) + current_revno = out + if current_revno == revno: + return True + if revno.lower() == 'head': + # Failure to do pull is not a fatal error, + # because otherwise you can't develop without + # a working net connection. + subprocess.call(['svn', 'update'], cwd=self.repo_dir) + else: + subprocess.check_call(['svn', 'update', '-r', revno], cwd=self.repo_dir) + return True + + def update(self) -> bool: + self.log(f'Updating {self.wrap.name}...') + success = False + if not os.path.isdir(self.repo_dir): + self.log(' -> Not used.') + # It is not an error if we are updating all subprojects. + success = not self.options.subprojects + elif self.wrap.type == 'file': + success = self.update_file() + elif self.wrap.type == 'git': + success = self.update_git() + elif self.wrap.type == 'hg': + success = self.update_hg() + elif self.wrap.type == 'svn': + success = self.update_svn() + elif self.wrap.type is None: + self.log(' -> Cannot update subproject with no wrap file') + # It is not an error if we are updating all subprojects. + success = not self.options.subprojects + else: + self.log(' -> Cannot update', self.wrap.type, 'subproject') + if success and os.path.isdir(self.repo_dir): + self.wrap.update_hash_cache(self.repo_dir) + return success + + def checkout(self) -> bool: + options = T.cast('CheckoutArguments', self.options) + + if self.wrap.type != 'git' or not os.path.isdir(self.repo_dir): + return True + branch_name = options.branch_name if options.branch_name else self.wrap.get('revision') + if not branch_name: + # It could be a detached git submodule for example. + return True + self.log(f'Checkout {branch_name} in {self.wrap.name}...') + if self.git_checkout(branch_name, create=options.b): + self.git_show() + return True + return False + + def download(self) -> bool: + self.log(f'Download {self.wrap.name}...') + if os.path.isdir(self.repo_dir): + self.log(' -> Already downloaded') + return True + try: + self.wrap_resolver.resolve(self.wrap.name, 'meson') + self.log(' -> done') + except WrapException as e: + self.log(' ->', mlog.red(str(e))) + return False + return True + + def foreach(self) -> bool: + options = T.cast('ForeachArguments', self.options) + + self.log(f'Executing command in {self.repo_dir}') + if not os.path.isdir(self.repo_dir): + self.log(' -> Not downloaded yet') + return True + cmd = [options.command] + options.args + p, out, _ = Popen_safe(cmd, stderr=subprocess.STDOUT, cwd=self.repo_dir) + if p.returncode != 0: + err_message = "Command '{}' returned non-zero exit status {}.".format(" ".join(cmd), p.returncode) + self.log(' -> ', mlog.red(err_message)) + self.log(out, end='') + return False + + self.log(out, end='') + return True + + def purge(self) -> bool: + options = T.cast('PurgeArguments', self.options) + + # if subproject is not wrap-based, then don't remove it + if not self.wrap.type: + return True + + if self.wrap.redirected: + redirect_file = Path(self.wrap.original_filename).resolve() + if options.confirm: + redirect_file.unlink() + mlog.log(f'Deleting {redirect_file}') + + if self.wrap.type == 'redirect': + redirect_file = Path(self.wrap.filename).resolve() + if options.confirm: + redirect_file.unlink() + self.log(f'Deleting {redirect_file}') + + if options.include_cache: + packagecache = Path(self.wrap_resolver.cachedir).resolve() + try: + subproject_cache_file = packagecache / self.wrap.get("source_filename") + if subproject_cache_file.is_file(): + if options.confirm: + subproject_cache_file.unlink() + self.log(f'Deleting {subproject_cache_file}') + except WrapException: + pass + + try: + subproject_patch_file = packagecache / self.wrap.get("patch_filename") + if subproject_patch_file.is_file(): + if options.confirm: + subproject_patch_file.unlink() + self.log(f'Deleting {subproject_patch_file}') + except WrapException: + pass + + # Don't log that we will remove an empty directory. Since purge is + # parallelized, another thread could have deleted it already. + try: + if not any(packagecache.iterdir()): + windows_proof_rmtree(str(packagecache)) + except FileNotFoundError: + pass + + # NOTE: Do not use .resolve() here; the subproject directory may be a symlink + subproject_source_dir = Path(self.repo_dir) + # Resolve just the parent, just to print out the full path + subproject_source_dir = subproject_source_dir.parent.resolve() / subproject_source_dir.name + + # Don't follow symlink. This is covered by the next if statement, but why + # not be doubly sure. + if subproject_source_dir.is_symlink(): + if options.confirm: + subproject_source_dir.unlink() + self.log(f'Deleting {subproject_source_dir}') + return True + if not subproject_source_dir.is_dir(): + return True + + try: + if options.confirm: + windows_proof_rmtree(str(subproject_source_dir)) + self.log(f'Deleting {subproject_source_dir}') + except OSError as e: + mlog.error(f'Unable to remove: {subproject_source_dir}: {e}') + return False + + return True + + @staticmethod + def post_purge(options: 'PurgeArguments') -> None: + if not options.confirm: + mlog.log('') + mlog.log('Nothing has been deleted, run again with --confirm to apply.') + + def packagefiles(self) -> bool: + options = T.cast('PackagefilesArguments', self.options) + + if options.apply and options.save: + # not quite so nice as argparse failure + print('error: --apply and --save are mutually exclusive') + return False + if options.apply: + self.log(f'Re-applying patchfiles overlay for {self.wrap.name}...') + if not os.path.isdir(self.repo_dir): + self.log(' -> Not downloaded yet') + return True + self.wrap_resolver.apply_patch() + return True + if options.save: + if 'patch_directory' not in self.wrap.values: + mlog.error('can only save packagefiles to patch_directory') + return False + if 'source_filename' not in self.wrap.values: + mlog.error('can only save packagefiles from a [wrap-file]') + return False + archive_path = Path(self.wrap_resolver.cachedir, self.wrap.values['source_filename']) + lead_directory_missing = bool(self.wrap.values.get('lead_directory_missing', False)) + directory = Path(self.repo_dir) + packagefiles = Path(self.wrap.filesdir, self.wrap.values['patch_directory']) + + base_path = directory if lead_directory_missing else directory.parent + archive_files = read_archive_files(archive_path, base_path) + directory_files = set(directory.glob('**/*')) + + self.log(f'Saving {self.wrap.name} to {packagefiles}...') + shutil.rmtree(packagefiles) + for src_path in directory_files - archive_files: + if not src_path.is_file(): + continue + rel_path = src_path.relative_to(directory) + dst_path = packagefiles / rel_path + dst_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(src_path, dst_path) + return True + + +def add_common_arguments(p: argparse.ArgumentParser) -> None: + p.add_argument('--sourcedir', default='.', + help='Path to source directory') + p.add_argument('--types', default='', + help=f'Comma-separated list of subproject types. Supported types are: {ALL_TYPES_STRING} (default: all)') + p.add_argument('--num-processes', default=None, type=int, + help='How many parallel processes to use (Since 0.59.0).') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + +def add_subprojects_argument(p: argparse.ArgumentParser) -> None: + p.add_argument('subprojects', nargs='*', + help='List of subprojects (default: all)') + +def add_wrap_update_parser(subparsers: 'SubParsers') -> argparse.ArgumentParser: + p = subparsers.add_parser('update', help='Update wrap files from WrapDB (Since 0.63.0)') + p.add_argument('--force', default=False, action='store_true', + help='Update wraps that does not seems to come from WrapDB') + add_common_arguments(p) + add_subprojects_argument(p) + p.set_defaults(subprojects_func=Runner.update_wrapdb) + p.set_defaults(pre_func=Runner.pre_update_wrapdb) + return p + +def add_arguments(parser: argparse.ArgumentParser) -> None: + subparsers = parser.add_subparsers(title='Commands', dest='command') + subparsers.required = True + + p = subparsers.add_parser('update', help='Update all subprojects from wrap files') + p.add_argument('--rebase', default=True, action='store_true', + help='Rebase your branch on top of wrap\'s revision. ' + + 'Deprecated, it is now the default behaviour. (git only)') + p.add_argument('--reset', default=False, action='store_true', + help='Checkout wrap\'s revision and hard reset to that commit. (git only)') + add_common_arguments(p) + add_subprojects_argument(p) + p.set_defaults(subprojects_func=Runner.update) + + p = subparsers.add_parser('checkout', help='Checkout a branch (git only)') + p.add_argument('-b', default=False, action='store_true', + help='Create a new branch') + p.add_argument('branch_name', nargs='?', + help='Name of the branch to checkout or create (default: revision set in wrap file)') + add_common_arguments(p) + add_subprojects_argument(p) + p.set_defaults(subprojects_func=Runner.checkout) + + p = subparsers.add_parser('download', help='Ensure subprojects are fetched, even if not in use. ' + + 'Already downloaded subprojects are not modified. ' + + 'This can be used to pre-fetch all subprojects and avoid downloads during configure.') + add_common_arguments(p) + add_subprojects_argument(p) + p.set_defaults(subprojects_func=Runner.download) + + p = subparsers.add_parser('foreach', help='Execute a command in each subproject directory.') + p.add_argument('command', metavar='command ...', + help='Command to execute in each subproject directory') + p.add_argument('args', nargs=argparse.REMAINDER, + help=argparse.SUPPRESS) + add_common_arguments(p) + p.set_defaults(subprojects=[]) + p.set_defaults(subprojects_func=Runner.foreach) + + p = subparsers.add_parser('purge', help='Remove all wrap-based subproject artifacts') + add_common_arguments(p) + add_subprojects_argument(p) + p.add_argument('--include-cache', action='store_true', default=False, help='Remove the package cache as well') + p.add_argument('--confirm', action='store_true', default=False, help='Confirm the removal of subproject artifacts') + p.set_defaults(subprojects_func=Runner.purge) + p.set_defaults(post_func=Runner.post_purge) + + p = subparsers.add_parser('packagefiles', help='Manage the packagefiles overlay') + add_common_arguments(p) + add_subprojects_argument(p) + p.add_argument('--apply', action='store_true', default=False, help='Apply packagefiles to the subproject') + p.add_argument('--save', action='store_true', default=False, help='Save packagefiles from the subproject') + p.set_defaults(subprojects_func=Runner.packagefiles) + +def run(options: 'Arguments') -> int: + source_dir = os.path.relpath(os.path.realpath(options.sourcedir)) + if not os.path.isfile(os.path.join(source_dir, 'meson.build')): + mlog.error('Directory', mlog.bold(source_dir), 'does not seem to be a Meson source directory.') + return 1 + with mlog.no_logging(): + intr = IntrospectionInterpreter(source_dir, '', 'none') + intr.load_root_meson_file() + subproject_dir = intr.extract_subproject_dir() or 'subprojects' + if not os.path.isdir(os.path.join(source_dir, subproject_dir)): + mlog.log('Directory', mlog.bold(source_dir), 'does not seem to have subprojects.') + return 0 + r = Resolver(source_dir, subproject_dir, wrap_frontend=True, allow_insecure=options.allow_insecure, silent=True) + if options.subprojects: + wraps = [wrap for name, wrap in r.wraps.items() if name in options.subprojects] + else: + wraps = list(r.wraps.values()) + types = [t.strip() for t in options.types.split(',')] if options.types else [] + for t in types: + if t not in ALL_TYPES: + raise MesonException(f'Unknown subproject type {t!r}, supported types are: {ALL_TYPES_STRING}') + tasks: T.List[T.Awaitable[bool]] = [] + task_names: T.List[str] = [] + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + executor = ThreadPoolExecutor(options.num_processes) + if types: + wraps = [wrap for wrap in wraps if wrap.type in types] + pre_func = getattr(options, 'pre_func', None) + if pre_func: + pre_func(options) + logger = Logger(len(wraps)) + for wrap in wraps: + dirname = Path(subproject_dir, wrap.directory).as_posix() + runner = Runner(logger, r, wrap, dirname, options) + task = loop.run_in_executor(executor, runner.run) + tasks.append(task) + task_names.append(wrap.name) + results = loop.run_until_complete(asyncio.gather(*tasks)) + logger.flush() + post_func = getattr(options, 'post_func', None) + if post_func: + post_func(options) + failures = [name for name, success in zip(task_names, results) if not success] + if failures: + m = 'Please check logs above as command failed in some subprojects which could have been left in conflict state: ' + m += ', '.join(failures) + mlog.warning(m) + return len(failures) diff --git a/devtools/meson/mesonbuild/mtest.py b/devtools/meson/mesonbuild/mtest.py new file mode 100644 index 0000000..24cf082 --- /dev/null +++ b/devtools/meson/mesonbuild/mtest.py @@ -0,0 +1,2195 @@ +# Copyright 2016-2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# A tool to run tests in many different ways. +from __future__ import annotations + +from pathlib import Path +from collections import deque +from contextlib import suppress +from copy import deepcopy +from fnmatch import fnmatch +import argparse +import asyncio +import datetime +import enum +import json +import multiprocessing +import os +import pickle +import platform +import random +import re +import signal +import subprocess +import shlex +import sys +import textwrap +import time +import typing as T +import unicodedata +import xml.etree.ElementTree as et + +from . import build +from . import environment +from . import mlog +from .coredata import MesonVersionMismatchException, OptionKey, major_versions_differ +from .coredata import version as coredata_version +from .mesonlib import (MesonException, OrderedSet, RealPathAction, + get_wine_shortpath, join_args, split_args, setup_vsenv) +from .mintro import get_infodir, load_info_file +from .programs import ExternalProgram +from .backend.backends import TestProtocol, TestSerialisation + +if T.TYPE_CHECKING: + TYPE_TAPResult = T.Union['TAPParser.Test', + 'TAPParser.Error', + 'TAPParser.Version', + 'TAPParser.Plan', + 'TAPParser.UnknownLine', + 'TAPParser.Bailout'] + + +# GNU autotools interprets a return code of 77 from tests it executes to +# mean that the test should be skipped. +GNU_SKIP_RETURNCODE = 77 + +# GNU autotools interprets a return code of 99 from tests it executes to +# mean that the test failed even before testing what it is supposed to test. +GNU_ERROR_RETURNCODE = 99 + +# Exit if 3 Ctrl-C's are received within one second +MAX_CTRLC = 3 + +# Define unencodable xml characters' regex for replacing them with their +# printable representation +UNENCODABLE_XML_UNICHRS: T.List[T.Tuple[int, int]] = [ + (0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84), + (0x86, 0x9F), (0xFDD0, 0xFDEF), (0xFFFE, 0xFFFF)] +# Not narrow build +if sys.maxunicode >= 0x10000: + UNENCODABLE_XML_UNICHRS.extend([ + (0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), + (0x3FFFE, 0x3FFFF), (0x4FFFE, 0x4FFFF), + (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF), + (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), + (0x9FFFE, 0x9FFFF), (0xAFFFE, 0xAFFFF), + (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF), + (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), + (0xFFFFE, 0xFFFFF), (0x10FFFE, 0x10FFFF)]) +UNENCODABLE_XML_CHR_RANGES = [fr'{chr(low)}-{chr(high)}' for (low, high) in UNENCODABLE_XML_UNICHRS] +UNENCODABLE_XML_CHRS_RE = re.compile('([' + ''.join(UNENCODABLE_XML_CHR_RANGES) + '])') + + +def is_windows() -> bool: + platname = platform.system().lower() + return platname == 'windows' + +def is_cygwin() -> bool: + return sys.platform == 'cygwin' + +UNIWIDTH_MAPPING = {'F': 2, 'H': 1, 'W': 2, 'Na': 1, 'N': 1, 'A': 1} +def uniwidth(s: str) -> int: + result = 0 + for c in s: + w = unicodedata.east_asian_width(c) + result += UNIWIDTH_MAPPING[w] + return result + +def determine_worker_count() -> int: + varname = 'MESON_TESTTHREADS' + if varname in os.environ: + try: + num_workers = int(os.environ[varname]) + except ValueError: + print(f'Invalid value in {varname}, using 1 thread.') + num_workers = 1 + else: + try: + # Fails in some weird environments such as Debian + # reproducible build. + num_workers = multiprocessing.cpu_count() + except Exception: + num_workers = 1 + return num_workers + +def add_arguments(parser: argparse.ArgumentParser) -> None: + parser.add_argument('--maxfail', default=0, type=int, + help='Number of failing tests before aborting the ' + 'test run. (default: 0, to disable aborting on failure)') + parser.add_argument('--repeat', default=1, dest='repeat', type=int, + help='Number of times to run the tests.') + parser.add_argument('--no-rebuild', default=False, action='store_true', + help='Do not rebuild before running tests.') + parser.add_argument('--gdb', default=False, dest='gdb', action='store_true', + help='Run test under gdb.') + parser.add_argument('--gdb-path', default='gdb', dest='gdb_path', + help='Path to the gdb binary (default: gdb).') + parser.add_argument('--list', default=False, dest='list', action='store_true', + help='List available tests.') + parser.add_argument('--wrapper', default=None, dest='wrapper', type=split_args, + help='wrapper to run tests with (e.g. Valgrind)') + parser.add_argument('-C', dest='wd', action=RealPathAction, + # https://github.com/python/typeshed/issues/3107 + # https://github.com/python/mypy/issues/7177 + type=os.path.abspath, # type: ignore + help='directory to cd into before running') + parser.add_argument('--suite', default=[], dest='include_suites', action='append', metavar='SUITE', + help='Only run tests belonging to the given suite.') + parser.add_argument('--no-suite', default=[], dest='exclude_suites', action='append', metavar='SUITE', + help='Do not run tests belonging to the given suite.') + parser.add_argument('--no-stdsplit', default=True, dest='split', action='store_false', + help='Do not split stderr and stdout in test logs.') + parser.add_argument('--print-errorlogs', default=False, action='store_true', + help="Whether to print failing tests' logs.") + parser.add_argument('--benchmark', default=False, action='store_true', + help="Run benchmarks instead of tests.") + parser.add_argument('--logbase', default='testlog', + help="Base name for log file.") + parser.add_argument('--num-processes', default=determine_worker_count(), type=int, + help='How many parallel processes to use.') + parser.add_argument('-v', '--verbose', default=False, action='store_true', + help='Do not redirect stdout and stderr') + parser.add_argument('-q', '--quiet', default=False, action='store_true', + help='Produce less output to the terminal.') + parser.add_argument('-t', '--timeout-multiplier', type=float, default=None, + help='Define a multiplier for test timeout, for example ' + ' when running tests in particular conditions they might take' + ' more time to execute. (<= 0 to disable timeout)') + parser.add_argument('--setup', default=None, dest='setup', + help='Which test setup to use.') + parser.add_argument('--test-args', default=[], type=split_args, + help='Arguments to pass to the specified test(s) or all tests') + parser.add_argument('args', nargs='*', + help='Optional list of test names to run. "testname" to run all tests with that name, ' + '"subprojname:testname" to specifically run "testname" from "subprojname", ' + '"subprojname:" to run all tests defined by "subprojname".') + + +def print_safe(s: str) -> None: + end = '' if s[-1] == '\n' else '\n' + try: + print(s, end=end) + except UnicodeEncodeError: + s = s.encode('ascii', errors='backslashreplace').decode('ascii') + print(s, end=end) + +def join_lines(a: str, b: str) -> str: + if not a: + return b + if not b: + return a + return a + '\n' + b + +def dashes(s: str, dash: str, cols: int) -> str: + if not s: + return dash * cols + s = ' ' + s + ' ' + width = uniwidth(s) + first = (cols - width) // 2 + s = dash * first + s + return s + dash * (cols - first - width) + +def returncode_to_status(retcode: int) -> str: + # Note: We can't use `os.WIFSIGNALED(result.returncode)` and the related + # functions here because the status returned by subprocess is munged. It + # returns a negative value if the process was killed by a signal rather than + # the raw status returned by `wait()`. Also, If a shell sits between Meson + # the actual unit test that shell is likely to convert a termination due + # to a signal into an exit status of 128 plus the signal number. + if retcode < 0: + signum = -retcode + try: + signame = signal.Signals(signum).name + except ValueError: + signame = 'SIGinvalid' + return f'killed by signal {signum} {signame}' + + if retcode <= 128: + return f'exit status {retcode}' + + signum = retcode - 128 + try: + signame = signal.Signals(signum).name + except ValueError: + signame = 'SIGinvalid' + return f'(exit status {retcode} or signal {signum} {signame})' + +# TODO for Windows +sh_quote: T.Callable[[str], str] = lambda x: x +if not is_windows(): + sh_quote = shlex.quote + +def env_tuple_to_str(env: T.Iterable[T.Tuple[str, str]]) -> str: + return ''.join(["{}={} ".format(k, sh_quote(v)) for k, v in env]) + + +class TestException(MesonException): + pass + + +@enum.unique +class ConsoleUser(enum.Enum): + + # the logger can use the console + LOGGER = 0 + + # the console is used by gdb + GDB = 1 + + # the console is used to write stdout/stderr + STDOUT = 2 + + +@enum.unique +class TestResult(enum.Enum): + + PENDING = 'PENDING' + RUNNING = 'RUNNING' + OK = 'OK' + TIMEOUT = 'TIMEOUT' + INTERRUPT = 'INTERRUPT' + SKIP = 'SKIP' + FAIL = 'FAIL' + EXPECTEDFAIL = 'EXPECTEDFAIL' + UNEXPECTEDPASS = 'UNEXPECTEDPASS' + ERROR = 'ERROR' + + @staticmethod + def maxlen() -> int: + return 14 # len(UNEXPECTEDPASS) + + def is_ok(self) -> bool: + return self in {TestResult.OK, TestResult.EXPECTEDFAIL} + + def is_bad(self) -> bool: + return self in {TestResult.FAIL, TestResult.TIMEOUT, TestResult.INTERRUPT, + TestResult.UNEXPECTEDPASS, TestResult.ERROR} + + def is_finished(self) -> bool: + return self not in {TestResult.PENDING, TestResult.RUNNING} + + def was_killed(self) -> bool: + return self in (TestResult.TIMEOUT, TestResult.INTERRUPT) + + def colorize(self, s: str) -> mlog.AnsiDecorator: + if self.is_bad(): + decorator = mlog.red + elif self in (TestResult.SKIP, TestResult.EXPECTEDFAIL): + decorator = mlog.yellow + elif self.is_finished(): + decorator = mlog.green + else: + decorator = mlog.blue + return decorator(s) + + def get_text(self, colorize: bool) -> str: + result_str = '{res:{reslen}}'.format(res=self.value, reslen=self.maxlen()) + return self.colorize(result_str).get_text(colorize) + + def get_command_marker(self) -> str: + return str(self.colorize('>>> ')) + + +class TAPParser: + class Plan(T.NamedTuple): + num_tests: int + late: bool + skipped: bool + explanation: T.Optional[str] + + class Bailout(T.NamedTuple): + message: str + + class Test(T.NamedTuple): + number: int + name: str + result: TestResult + explanation: T.Optional[str] + + def __str__(self) -> str: + return f'{self.number} {self.name}'.strip() + + class Error(T.NamedTuple): + message: str + + class UnknownLine(T.NamedTuple): + message: str + lineno: int + + class Version(T.NamedTuple): + version: int + + _MAIN = 1 + _AFTER_TEST = 2 + _YAML = 3 + + _RE_BAILOUT = re.compile(r'Bail out!\s*(.*)') + _RE_DIRECTIVE = re.compile(r'(?:\s*\#\s*([Ss][Kk][Ii][Pp]\S*|[Tt][Oo][Dd][Oo])\b\s*(.*))?') + _RE_PLAN = re.compile(r'1\.\.([0-9]+)' + _RE_DIRECTIVE.pattern) + _RE_TEST = re.compile(r'((?:not )?ok)\s*(?:([0-9]+)\s*)?([^#]*)' + _RE_DIRECTIVE.pattern) + _RE_VERSION = re.compile(r'TAP version ([0-9]+)') + _RE_YAML_START = re.compile(r'(\s+)---.*') + _RE_YAML_END = re.compile(r'\s+\.\.\.\s*') + + found_late_test = False + bailed_out = False + plan: T.Optional[Plan] = None + lineno = 0 + num_tests = 0 + yaml_lineno: T.Optional[int] = None + yaml_indent = '' + state = _MAIN + version = 12 + + def parse_test(self, ok: bool, num: int, name: str, directive: T.Optional[str], explanation: T.Optional[str]) -> \ + T.Generator[T.Union['TAPParser.Test', 'TAPParser.Error'], None, None]: + name = name.strip() + explanation = explanation.strip() if explanation else None + if directive is not None: + directive = directive.upper() + if directive.startswith('SKIP'): + if ok: + yield self.Test(num, name, TestResult.SKIP, explanation) + return + elif directive == 'TODO': + yield self.Test(num, name, TestResult.UNEXPECTEDPASS if ok else TestResult.EXPECTEDFAIL, explanation) + return + else: + yield self.Error(f'invalid directive "{directive}"') + + yield self.Test(num, name, TestResult.OK if ok else TestResult.FAIL, explanation) + + async def parse_async(self, lines: T.AsyncIterator[str]) -> T.AsyncIterator[TYPE_TAPResult]: + async for line in lines: + for event in self.parse_line(line): + yield event + for event in self.parse_line(None): + yield event + + def parse(self, io: T.Iterator[str]) -> T.Iterator[TYPE_TAPResult]: + for line in io: + yield from self.parse_line(line) + yield from self.parse_line(None) + + def parse_line(self, line: T.Optional[str]) -> T.Iterator[TYPE_TAPResult]: + if line is not None: + self.lineno += 1 + line = line.rstrip() + + # YAML blocks are only accepted after a test + if self.state == self._AFTER_TEST: + if self.version >= 13: + m = self._RE_YAML_START.match(line) + if m: + self.state = self._YAML + self.yaml_lineno = self.lineno + self.yaml_indent = m.group(1) + return + self.state = self._MAIN + + elif self.state == self._YAML: + if self._RE_YAML_END.match(line): + self.state = self._MAIN + return + if line.startswith(self.yaml_indent): + return + yield self.Error(f'YAML block not terminated (started on line {self.yaml_lineno})') + self.state = self._MAIN + + assert self.state == self._MAIN + if not line or line.startswith('#'): + return + + m = self._RE_TEST.match(line) + if m: + if self.plan and self.plan.late and not self.found_late_test: + yield self.Error('unexpected test after late plan') + self.found_late_test = True + self.num_tests += 1 + num = self.num_tests if m.group(2) is None else int(m.group(2)) + if num != self.num_tests: + yield self.Error('out of order test numbers') + yield from self.parse_test(m.group(1) == 'ok', num, + m.group(3), m.group(4), m.group(5)) + self.state = self._AFTER_TEST + return + + m = self._RE_PLAN.match(line) + if m: + if self.plan: + yield self.Error('more than one plan found') + else: + num_tests = int(m.group(1)) + skipped = num_tests == 0 + if m.group(2): + if m.group(2).upper().startswith('SKIP'): + if num_tests > 0: + yield self.Error('invalid SKIP directive for plan') + skipped = True + else: + yield self.Error('invalid directive for plan') + self.plan = self.Plan(num_tests=num_tests, late=(self.num_tests > 0), + skipped=skipped, explanation=m.group(3)) + yield self.plan + return + + m = self._RE_BAILOUT.match(line) + if m: + yield self.Bailout(m.group(1)) + self.bailed_out = True + return + + m = self._RE_VERSION.match(line) + if m: + # The TAP version is only accepted as the first line + if self.lineno != 1: + yield self.Error('version number must be on the first line') + return + self.version = int(m.group(1)) + if self.version < 13: + yield self.Error('version number should be at least 13') + else: + yield self.Version(version=self.version) + return + + # unknown syntax + yield self.UnknownLine(line, self.lineno) + else: + # end of file + if self.state == self._YAML: + yield self.Error(f'YAML block not terminated (started on line {self.yaml_lineno})') + + if not self.bailed_out and self.plan and self.num_tests != self.plan.num_tests: + if self.num_tests < self.plan.num_tests: + yield self.Error(f'Too few tests run (expected {self.plan.num_tests}, got {self.num_tests})') + else: + yield self.Error(f'Too many tests run (expected {self.plan.num_tests}, got {self.num_tests})') + +class TestLogger: + def flush(self) -> None: + pass + + def start(self, harness: 'TestHarness') -> None: + pass + + def start_test(self, harness: 'TestHarness', test: 'TestRun') -> None: + pass + + def log_subtest(self, harness: 'TestHarness', test: 'TestRun', s: str, res: TestResult) -> None: + pass + + def log(self, harness: 'TestHarness', result: 'TestRun') -> None: + pass + + async def finish(self, harness: 'TestHarness') -> None: + pass + + def close(self) -> None: + pass + + +class TestFileLogger(TestLogger): + def __init__(self, filename: str, errors: str = 'replace') -> None: + self.filename = filename + self.file = open(filename, 'w', encoding='utf-8', errors=errors) + + def close(self) -> None: + if self.file: + self.file.close() + self.file = None + + +class ConsoleLogger(TestLogger): + ASCII_SPINNER = ['..', ':.', '.:'] + SPINNER = ["\U0001f311", "\U0001f312", "\U0001f313", "\U0001f314", + "\U0001f315", "\U0001f316", "\U0001f317", "\U0001f318"] + + SCISSORS = "\u2700 " + HLINE = "\u2015" + RTRI = "\u25B6 " + + def __init__(self) -> None: + self.running_tests = OrderedSet() # type: OrderedSet['TestRun'] + self.progress_test = None # type: T.Optional['TestRun'] + self.progress_task = None # type: T.Optional[asyncio.Future] + self.max_left_width = 0 # type: int + self.stop = False + # TODO: before 3.10 this cannot be created immediately, because + # it will create a new event loop + self.update: asyncio.Event + self.should_erase_line = '' + self.test_count = 0 + self.started_tests = 0 + self.spinner_index = 0 + try: + self.cols, _ = os.get_terminal_size(1) + self.is_tty = True + except OSError: + self.cols = 80 + self.is_tty = False + + self.output_start = dashes(self.SCISSORS, self.HLINE, self.cols - 2) + self.output_end = dashes('', self.HLINE, self.cols - 2) + self.sub = self.RTRI + self.spinner = self.SPINNER + try: + self.output_start.encode(sys.stdout.encoding or 'ascii') + except UnicodeEncodeError: + self.output_start = dashes('8<', '-', self.cols - 2) + self.output_end = dashes('', '-', self.cols - 2) + self.sub = '| ' + self.spinner = self.ASCII_SPINNER + + def flush(self) -> None: + if self.should_erase_line: + print(self.should_erase_line, end='') + self.should_erase_line = '' + + def print_progress(self, line: str) -> None: + print(self.should_erase_line, line, sep='', end='\r') + self.should_erase_line = '\x1b[K' + + def request_update(self) -> None: + self.update.set() + + def emit_progress(self, harness: 'TestHarness') -> None: + if self.progress_test is None: + self.flush() + return + + if len(self.running_tests) == 1: + count = f'{self.started_tests}/{self.test_count}' + else: + count = '{}-{}/{}'.format(self.started_tests - len(self.running_tests) + 1, + self.started_tests, self.test_count) + + left = '[{}] {} '.format(count, self.spinner[self.spinner_index]) + self.spinner_index = (self.spinner_index + 1) % len(self.spinner) + + right = '{spaces} {dur:{durlen}}'.format( + spaces=' ' * TestResult.maxlen(), + dur=int(time.time() - self.progress_test.starttime), + durlen=harness.duration_max_len) + if self.progress_test.timeout: + right += '/{timeout:{durlen}}'.format( + timeout=self.progress_test.timeout, + durlen=harness.duration_max_len) + right += 's' + details = self.progress_test.get_details() + if details: + right += ' ' + details + + line = harness.format(self.progress_test, colorize=True, + max_left_width=self.max_left_width, + left=left, right=right) + self.print_progress(line) + + def start(self, harness: 'TestHarness') -> None: + async def report_progress() -> None: + loop = asyncio.get_running_loop() + next_update = 0.0 + self.request_update() + while not self.stop: + await self.update.wait() + self.update.clear() + # We may get here simply because the progress line has been + # overwritten, so do not always switch. Only do so every + # second, or if the printed test has finished + if loop.time() >= next_update: + self.progress_test = None + next_update = loop.time() + 1 + loop.call_at(next_update, self.request_update) + + if (self.progress_test and + self.progress_test.res is not TestResult.RUNNING): + self.progress_test = None + + if not self.progress_test: + if not self.running_tests: + continue + # Pick a test in round robin order + self.progress_test = self.running_tests.pop(last=False) + self.running_tests.add(self.progress_test) + + self.emit_progress(harness) + self.flush() + + self.update = asyncio.Event() + self.test_count = harness.test_count + self.cols = max(self.cols, harness.max_left_width + 30) + + if self.is_tty and not harness.need_console: + # Account for "[aa-bb/cc] OO " in the progress report + self.max_left_width = 3 * len(str(self.test_count)) + 8 + self.progress_task = asyncio.ensure_future(report_progress()) + + def start_test(self, harness: 'TestHarness', test: 'TestRun') -> None: + if test.verbose and test.cmdline: + self.flush() + print(harness.format(test, mlog.colorize_console(), + max_left_width=self.max_left_width, + right=test.res.get_text(mlog.colorize_console()))) + print(test.res.get_command_marker() + test.cmdline) + if test.direct_stdout: + print(self.output_start, flush=True) + elif not test.needs_parsing: + print(flush=True) + + self.started_tests += 1 + self.running_tests.add(test) + self.running_tests.move_to_end(test, last=False) + self.request_update() + + def shorten_log(self, harness: 'TestHarness', result: 'TestRun') -> str: + if not result.verbose and not harness.options.print_errorlogs: + return '' + + log = result.get_log(mlog.colorize_console(), + stderr_only=result.needs_parsing) + if result.verbose: + return log + + lines = log.splitlines() + if len(lines) < 100: + return log + else: + return str(mlog.bold('Listing only the last 100 lines from a long log.\n')) + '\n'.join(lines[-100:]) + + def print_log(self, harness: 'TestHarness', result: 'TestRun') -> None: + if not result.verbose: + cmdline = result.cmdline + if not cmdline: + print(result.res.get_command_marker() + result.stdo) + return + print(result.res.get_command_marker() + cmdline) + + log = self.shorten_log(harness, result) + if log: + print(self.output_start) + print_safe(log) + print(self.output_end) + + def log_subtest(self, harness: 'TestHarness', test: 'TestRun', s: str, result: TestResult) -> None: + if test.verbose or (harness.options.print_errorlogs and result.is_bad()): + self.flush() + print(harness.format(test, mlog.colorize_console(), max_left_width=self.max_left_width, + prefix=self.sub, + middle=s, + right=result.get_text(mlog.colorize_console())), flush=True) + + self.request_update() + + def log(self, harness: 'TestHarness', result: 'TestRun') -> None: + self.running_tests.remove(result) + if result.res is TestResult.TIMEOUT and (result.verbose or + harness.options.print_errorlogs): + self.flush() + print(f'{result.name} time out (After {result.timeout} seconds)') + + if not harness.options.quiet or not result.res.is_ok(): + self.flush() + if result.cmdline and result.direct_stdout: + print(self.output_end) + print(harness.format(result, mlog.colorize_console(), max_left_width=self.max_left_width)) + else: + print(harness.format(result, mlog.colorize_console(), max_left_width=self.max_left_width), + flush=True) + if result.verbose or result.res.is_bad(): + self.print_log(harness, result) + if result.warnings: + print(flush=True) + for w in result.warnings: + print(w, flush=True) + print(flush=True) + if result.verbose or result.res.is_bad(): + print(flush=True) + + self.request_update() + + async def finish(self, harness: 'TestHarness') -> None: + self.stop = True + self.request_update() + if self.progress_task: + await self.progress_task + + if harness.collected_failures and \ + (harness.options.print_errorlogs or harness.options.verbose): + print("\nSummary of Failures:\n") + for i, result in enumerate(harness.collected_failures, 1): + print(harness.format(result, mlog.colorize_console())) + + print(harness.summary()) + + +class TextLogfileBuilder(TestFileLogger): + def start(self, harness: 'TestHarness') -> None: + self.file.write(f'Log of Meson test suite run on {datetime.datetime.now().isoformat()}\n\n') + inherit_env = env_tuple_to_str(os.environ.items()) + self.file.write(f'Inherited environment: {inherit_env}\n\n') + + def log(self, harness: 'TestHarness', result: 'TestRun') -> None: + title = f'{result.num}/{harness.test_count}' + self.file.write(dashes(title, '=', 78) + '\n') + self.file.write('test: ' + result.name + '\n') + starttime_str = time.strftime("%H:%M:%S", time.gmtime(result.starttime)) + self.file.write('start time: ' + starttime_str + '\n') + self.file.write('duration: ' + '%.2fs' % result.duration + '\n') + self.file.write('result: ' + result.get_exit_status() + '\n') + if result.cmdline: + self.file.write('command: ' + result.cmdline + '\n') + if result.stdo: + name = 'stdout' if harness.options.split else 'output' + self.file.write(dashes(name, '-', 78) + '\n') + self.file.write(result.stdo) + if result.stde: + self.file.write(dashes('stderr', '-', 78) + '\n') + self.file.write(result.stde) + self.file.write(dashes('', '=', 78) + '\n\n') + + async def finish(self, harness: 'TestHarness') -> None: + if harness.collected_failures: + self.file.write("\nSummary of Failures:\n\n") + for i, result in enumerate(harness.collected_failures, 1): + self.file.write(harness.format(result, False) + '\n') + self.file.write(harness.summary()) + + print(f'Full log written to {self.filename}') + + +class JsonLogfileBuilder(TestFileLogger): + def log(self, harness: 'TestHarness', result: 'TestRun') -> None: + jresult = {'name': result.name, + 'stdout': result.stdo, + 'result': result.res.value, + 'starttime': result.starttime, + 'duration': result.duration, + 'returncode': result.returncode, + 'env': result.env, + 'command': result.cmd} # type: T.Dict[str, T.Any] + if result.stde: + jresult['stderr'] = result.stde + self.file.write(json.dumps(jresult) + '\n') + + +class JunitBuilder(TestLogger): + + """Builder for Junit test results. + + Junit is impossible to stream out, it requires attributes counting the + total number of tests, failures, skips, and errors in the root element + and in each test suite. As such, we use a builder class to track each + test case, and calculate all metadata before writing it out. + + For tests with multiple results (like from a TAP test), we record the + test as a suite with the project_name.test_name. This allows us to track + each result separately. For tests with only one result (such as exit-code + tests) we record each one into a suite with the name project_name. The use + of the project_name allows us to sort subproject tests separately from + the root project. + """ + + def __init__(self, filename: str) -> None: + self.filename = filename + self.root = et.Element( + 'testsuites', tests='0', errors='0', failures='0') + self.suites = {} # type: T.Dict[str, et.Element] + + def log(self, harness: 'TestHarness', test: 'TestRun') -> None: + """Log a single test case.""" + if test.junit is not None: + for suite in test.junit.findall('.//testsuite'): + # Assume that we don't need to merge anything here... + suite.attrib['name'] = '{}.{}.{}'.format(test.project, test.name, suite.attrib['name']) + + # GTest can inject invalid attributes + for case in suite.findall('.//testcase[@result]'): + del case.attrib['result'] + for case in suite.findall('.//testcase[@timestamp]'): + del case.attrib['timestamp'] + for case in suite.findall('.//testcase[@file]'): + del case.attrib['file'] + for case in suite.findall('.//testcase[@line]'): + del case.attrib['line'] + self.root.append(suite) + return + + # In this case we have a test binary with multiple results. + # We want to record this so that each result is recorded + # separately + if test.results: + suitename = f'{test.project}.{test.name}' + assert suitename not in self.suites or harness.options.repeat > 1, 'duplicate suite' + + suite = self.suites[suitename] = et.Element( + 'testsuite', + name=suitename, + tests=str(len(test.results)), + errors=str(sum(1 for r in test.results if r.result in + {TestResult.INTERRUPT, TestResult.ERROR})), + failures=str(sum(1 for r in test.results if r.result in + {TestResult.FAIL, TestResult.UNEXPECTEDPASS, TestResult.TIMEOUT})), + skipped=str(sum(1 for r in test.results if r.result is TestResult.SKIP)), + time=str(test.duration), + ) + + for subtest in test.results: + # Both name and classname are required. Use the suite name as + # the class name, so that e.g. GitLab groups testcases correctly. + testcase = et.SubElement(suite, 'testcase', name=str(subtest), classname=suitename) + if subtest.result is TestResult.SKIP: + et.SubElement(testcase, 'skipped') + elif subtest.result is TestResult.ERROR: + et.SubElement(testcase, 'error') + elif subtest.result is TestResult.FAIL: + et.SubElement(testcase, 'failure') + elif subtest.result is TestResult.UNEXPECTEDPASS: + fail = et.SubElement(testcase, 'failure') + fail.text = 'Test unexpected passed.' + elif subtest.result is TestResult.INTERRUPT: + fail = et.SubElement(testcase, 'error') + fail.text = 'Test was interrupted by user.' + elif subtest.result is TestResult.TIMEOUT: + fail = et.SubElement(testcase, 'error') + fail.text = 'Test did not finish before configured timeout.' + if subtest.explanation: + et.SubElement(testcase, 'system-out').text = subtest.explanation + if test.stdo: + out = et.SubElement(suite, 'system-out') + out.text = replace_unencodable_xml_chars(test.stdo.rstrip()) + if test.stde: + err = et.SubElement(suite, 'system-err') + err.text = replace_unencodable_xml_chars(test.stde.rstrip()) + else: + if test.project not in self.suites: + suite = self.suites[test.project] = et.Element( + 'testsuite', name=test.project, tests='1', errors='0', + failures='0', skipped='0', time=str(test.duration)) + else: + suite = self.suites[test.project] + suite.attrib['tests'] = str(int(suite.attrib['tests']) + 1) + + testcase = et.SubElement(suite, 'testcase', name=test.name, + classname=test.project, time=str(test.duration)) + if test.res is TestResult.SKIP: + et.SubElement(testcase, 'skipped') + suite.attrib['skipped'] = str(int(suite.attrib['skipped']) + 1) + elif test.res is TestResult.ERROR: + et.SubElement(testcase, 'error') + suite.attrib['errors'] = str(int(suite.attrib['errors']) + 1) + elif test.res is TestResult.FAIL: + et.SubElement(testcase, 'failure') + suite.attrib['failures'] = str(int(suite.attrib['failures']) + 1) + if test.stdo: + out = et.SubElement(testcase, 'system-out') + out.text = replace_unencodable_xml_chars(test.stdo.rstrip()) + if test.stde: + err = et.SubElement(testcase, 'system-err') + err.text = replace_unencodable_xml_chars(test.stde.rstrip()) + + async def finish(self, harness: 'TestHarness') -> None: + """Calculate total test counts and write out the xml result.""" + for suite in self.suites.values(): + self.root.append(suite) + # Skipped is really not allowed in the "testsuits" element + for attr in ['tests', 'errors', 'failures']: + self.root.attrib[attr] = str(int(self.root.attrib[attr]) + int(suite.attrib[attr])) + + tree = et.ElementTree(self.root) + with open(self.filename, 'wb') as f: + tree.write(f, encoding='utf-8', xml_declaration=True) + + +class TestRun: + TEST_NUM = 0 + PROTOCOL_TO_CLASS: T.Dict[TestProtocol, T.Type['TestRun']] = {} + + def __new__(cls, test: TestSerialisation, *args: T.Any, **kwargs: T.Any) -> T.Any: + return super().__new__(TestRun.PROTOCOL_TO_CLASS[test.protocol]) + + def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str], + name: str, timeout: T.Optional[int], is_parallel: bool, verbose: bool): + self.res = TestResult.PENDING + self.test = test + self._num = None # type: T.Optional[int] + self.name = name + self.timeout = timeout + self.results = [] # type: T.List[TAPParser.Test] + self.returncode = None # type: T.Optional[int] + self.starttime = None # type: T.Optional[float] + self.duration = None # type: T.Optional[float] + self.stdo = '' + self.stde = '' + self.additional_error = '' + self.cmd = None # type: T.Optional[T.List[str]] + self.env = test_env # type: T.Dict[str, str] + self.should_fail = test.should_fail + self.project = test.project_name + self.junit = None # type: T.Optional[et.ElementTree] + self.is_parallel = is_parallel + self.verbose = verbose + self.warnings = [] # type: T.List[str] + + def start(self, cmd: T.List[str]) -> None: + self.res = TestResult.RUNNING + self.starttime = time.time() + self.cmd = cmd + + @property + def num(self) -> int: + if self._num is None: + TestRun.TEST_NUM += 1 + self._num = TestRun.TEST_NUM + return self._num + + @property + def direct_stdout(self) -> bool: + return self.verbose and not self.is_parallel and not self.needs_parsing + + def get_results(self) -> str: + if self.results: + # running or succeeded + passed = sum(x.result.is_ok() for x in self.results) + ran = sum(x.result is not TestResult.SKIP for x in self.results) + if passed == ran: + return f'{passed} subtests passed' + else: + return f'{passed}/{ran} subtests passed' + return '' + + def get_exit_status(self) -> str: + return returncode_to_status(self.returncode) + + def get_details(self) -> str: + if self.res is TestResult.PENDING: + return '' + if self.returncode: + return self.get_exit_status() + return self.get_results() + + def _complete(self) -> None: + if self.res == TestResult.RUNNING: + self.res = TestResult.OK + assert isinstance(self.res, TestResult) + if self.should_fail and self.res in (TestResult.OK, TestResult.FAIL): + self.res = TestResult.UNEXPECTEDPASS if self.res is TestResult.OK else TestResult.EXPECTEDFAIL + if self.stdo and not self.stdo.endswith('\n'): + self.stdo += '\n' + if self.stde and not self.stde.endswith('\n'): + self.stde += '\n' + self.duration = time.time() - self.starttime + + @property + def cmdline(self) -> T.Optional[str]: + if not self.cmd: + return None + test_only_env = set(self.env.items()) - set(os.environ.items()) + return env_tuple_to_str(test_only_env) + \ + ' '.join(sh_quote(x) for x in self.cmd) + + def complete_skip(self) -> None: + self.starttime = time.time() + self.returncode = GNU_SKIP_RETURNCODE + self.res = TestResult.SKIP + self._complete() + + def complete(self) -> None: + self._complete() + + def get_log(self, colorize: bool = False, stderr_only: bool = False) -> str: + stdo = '' if stderr_only else self.stdo + if self.stde or self.additional_error: + res = '' + if stdo: + res += mlog.cyan('stdout:').get_text(colorize) + '\n' + res += stdo + if res[-1:] != '\n': + res += '\n' + res += mlog.cyan('stderr:').get_text(colorize) + '\n' + res += join_lines(self.stde, self.additional_error) + else: + res = stdo + if res and res[-1:] != '\n': + res += '\n' + return res + + @property + def needs_parsing(self) -> bool: + return False + + async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> None: + async for l in lines: + pass + + +class TestRunExitCode(TestRun): + + def complete(self) -> None: + if self.res != TestResult.RUNNING: + pass + elif self.returncode == GNU_SKIP_RETURNCODE: + self.res = TestResult.SKIP + elif self.returncode == GNU_ERROR_RETURNCODE: + self.res = TestResult.ERROR + else: + self.res = TestResult.FAIL if bool(self.returncode) else TestResult.OK + super().complete() + +TestRun.PROTOCOL_TO_CLASS[TestProtocol.EXITCODE] = TestRunExitCode + + +class TestRunGTest(TestRunExitCode): + def complete(self) -> None: + filename = f'{self.test.name}.xml' + if self.test.workdir: + filename = os.path.join(self.test.workdir, filename) + + try: + with open(filename, 'r', encoding='utf8', errors='replace') as f: + self.junit = et.parse(f) + except FileNotFoundError: + # This can happen if the test fails to run or complete for some + # reason, like the rpath for libgtest isn't properly set. ExitCode + # will handle the failure, don't generate a stacktrace. + pass + except et.ParseError as e: + # ExitCode will handle the failure, don't generate a stacktrace. + mlog.error(f'Unable to parse {filename}: {e!s}') + + super().complete() + +TestRun.PROTOCOL_TO_CLASS[TestProtocol.GTEST] = TestRunGTest + + +class TestRunTAP(TestRun): + @property + def needs_parsing(self) -> bool: + return True + + def complete(self) -> None: + if self.returncode != 0 and not self.res.was_killed(): + self.res = TestResult.ERROR + self.stde = self.stde or '' + self.stde += f'\n(test program exited with status code {self.returncode})' + super().complete() + + async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> None: + res = None + warnings = [] # type: T.List[TAPParser.UnknownLine] + version = 12 + + async for i in TAPParser().parse_async(lines): + if isinstance(i, TAPParser.Version): + version = i.version + elif isinstance(i, TAPParser.Bailout): + res = TestResult.ERROR + harness.log_subtest(self, i.message, res) + elif isinstance(i, TAPParser.Test): + self.results.append(i) + if i.result.is_bad(): + res = TestResult.FAIL + harness.log_subtest(self, i.name or f'subtest {i.number}', i.result) + elif isinstance(i, TAPParser.UnknownLine): + warnings.append(i) + elif isinstance(i, TAPParser.Error): + self.additional_error += 'TAP parsing error: ' + i.message + res = TestResult.ERROR + + if warnings: + unknown = str(mlog.yellow('UNKNOWN')) + width = len(str(max(i.lineno for i in warnings))) + for w in warnings: + self.warnings.append(f'stdout: {w.lineno:{width}}: {unknown}: {w.message}') + if version > 13: + self.warnings.append('Unknown TAP output lines have been ignored. Please open a feature request to\n' + 'implement them, or prefix them with a # if they are not TAP syntax.') + else: + self.warnings.append(str(mlog.red('ERROR')) + ': Unknown TAP output lines for a supported TAP version.\n' + 'This is probably a bug in the test; if they are not TAP syntax, prefix them with a #') + if all(t.result is TestResult.SKIP for t in self.results): + # This includes the case where self.results is empty + res = TestResult.SKIP + + if res and self.res == TestResult.RUNNING: + self.res = res + +TestRun.PROTOCOL_TO_CLASS[TestProtocol.TAP] = TestRunTAP + + +class TestRunRust(TestRun): + @property + def needs_parsing(self) -> bool: + return True + + async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> None: + def parse_res(n: int, name: str, result: str) -> TAPParser.Test: + if result == 'ok': + return TAPParser.Test(n, name, TestResult.OK, None) + elif result == 'ignored': + return TAPParser.Test(n, name, TestResult.SKIP, None) + elif result == 'FAILED': + return TAPParser.Test(n, name, TestResult.FAIL, None) + return TAPParser.Test(n, name, TestResult.ERROR, + f'Unsupported output from rust test: {result}') + + n = 1 + async for line in lines: + if line.startswith('test ') and not line.startswith('test result'): + _, name, _, result = line.rstrip().split(' ') + name = name.replace('::', '.') + t = parse_res(n, name, result) + self.results.append(t) + harness.log_subtest(self, name, t.result) + n += 1 + + res = None + + if all(t.result is TestResult.SKIP for t in self.results): + # This includes the case where self.results is empty + res = TestResult.SKIP + elif any(t.result is TestResult.ERROR for t in self.results): + res = TestResult.ERROR + elif any(t.result is TestResult.FAIL for t in self.results): + res = TestResult.FAIL + + if res and self.res == TestResult.RUNNING: + self.res = res + +TestRun.PROTOCOL_TO_CLASS[TestProtocol.RUST] = TestRunRust + +# Check unencodable characters in xml output and replace them with +# their printable representation +def replace_unencodable_xml_chars(original_str: str) -> str: + # [1:-1] is needed for removing `'` characters from both start and end + # of the string + replacement_lambda = lambda illegal_chr: repr(illegal_chr.group())[1:-1] + return UNENCODABLE_XML_CHRS_RE.sub(replacement_lambda, original_str) + +def decode(stream: T.Union[None, bytes]) -> str: + if stream is None: + return '' + try: + return stream.decode('utf-8') + except UnicodeDecodeError: + return stream.decode('iso-8859-1', errors='ignore') + +async def read_decode(reader: asyncio.StreamReader, + queue: T.Optional['asyncio.Queue[T.Optional[str]]'], + console_mode: ConsoleUser) -> str: + stdo_lines = [] + try: + while not reader.at_eof(): + # Prefer splitting by line, as that produces nicer output + try: + line_bytes = await reader.readuntil(b'\n') + except asyncio.IncompleteReadError as e: + line_bytes = e.partial + except asyncio.LimitOverrunError as e: + line_bytes = await reader.readexactly(e.consumed) + if line_bytes: + line = decode(line_bytes) + stdo_lines.append(line) + if console_mode is ConsoleUser.STDOUT: + print(line, end='', flush=True) + if queue: + await queue.put(line) + return ''.join(stdo_lines) + except asyncio.CancelledError: + return ''.join(stdo_lines) + finally: + if queue: + await queue.put(None) + +def run_with_mono(fname: str) -> bool: + return fname.endswith('.exe') and not (is_windows() or is_cygwin()) + +def check_testdata(objs: T.List[TestSerialisation]) -> T.List[TestSerialisation]: + if not isinstance(objs, list): + raise MesonVersionMismatchException('', coredata_version) + for obj in objs: + if not isinstance(obj, TestSerialisation): + raise MesonVersionMismatchException('', coredata_version) + if not hasattr(obj, 'version'): + raise MesonVersionMismatchException('', coredata_version) + if major_versions_differ(obj.version, coredata_version): + raise MesonVersionMismatchException(obj.version, coredata_version) + return objs + +# Custom waiting primitives for asyncio + +async def queue_iter(q: 'asyncio.Queue[T.Optional[str]]') -> T.AsyncIterator[str]: + while True: + item = await q.get() + q.task_done() + if item is None: + break + yield item + +async def complete(future: asyncio.Future) -> None: + """Wait for completion of the given future, ignoring cancellation.""" + try: + await future + except asyncio.CancelledError: + pass + +async def complete_all(futures: T.Iterable[asyncio.Future], + timeout: T.Optional[T.Union[int, float]] = None) -> None: + """Wait for completion of all the given futures, ignoring cancellation. + If timeout is not None, raise an asyncio.TimeoutError after the given + time has passed. asyncio.TimeoutError is only raised if some futures + have not completed and none have raised exceptions, even if timeout + is zero.""" + + def check_futures(futures: T.Iterable[asyncio.Future]) -> None: + # Raise exceptions if needed + left = False + for f in futures: + if not f.done(): + left = True + elif not f.cancelled(): + f.result() + if left: + raise asyncio.TimeoutError + + # Python is silly and does not have a variant of asyncio.wait with an + # absolute time as deadline. + loop = asyncio.get_running_loop() + deadline = None if timeout is None else loop.time() + timeout + while futures and (timeout is None or timeout > 0): + done, futures = await asyncio.wait(futures, timeout=timeout, + return_when=asyncio.FIRST_EXCEPTION) + check_futures(done) + if deadline: + timeout = deadline - loop.time() + + check_futures(futures) + + +class TestSubprocess: + def __init__(self, p: asyncio.subprocess.Process, + stdout: T.Optional[int], stderr: T.Optional[int], + postwait_fn: T.Callable[[], None] = None): + self._process = p + self.stdout = stdout + self.stderr = stderr + self.stdo_task: T.Optional[asyncio.Task[None]] = None + self.stde_task: T.Optional[asyncio.Task[None]] = None + self.postwait_fn = postwait_fn # type: T.Callable[[], None] + self.all_futures = [] # type: T.List[asyncio.Future] + self.queue = None # type: T.Optional[asyncio.Queue[T.Optional[str]]] + + def stdout_lines(self) -> T.AsyncIterator[str]: + self.queue = asyncio.Queue() + return queue_iter(self.queue) + + def communicate(self, + test: 'TestRun', + console_mode: ConsoleUser) -> T.Tuple[T.Optional[T.Awaitable[str]], + T.Optional[T.Awaitable[str]]]: + async def collect_stdo(test: 'TestRun', + reader: asyncio.StreamReader, + console_mode: ConsoleUser) -> None: + test.stdo = await read_decode(reader, self.queue, console_mode) + + async def collect_stde(test: 'TestRun', + reader: asyncio.StreamReader, + console_mode: ConsoleUser) -> None: + test.stde = await read_decode(reader, None, console_mode) + + # asyncio.ensure_future ensures that printing can + # run in the background, even before it is awaited + if self.stdo_task is None and self.stdout is not None: + decode_coro = collect_stdo(test, self._process.stdout, console_mode) + self.stdo_task = asyncio.ensure_future(decode_coro) + self.all_futures.append(self.stdo_task) + if self.stderr is not None and self.stderr != asyncio.subprocess.STDOUT: + decode_coro = collect_stde(test, self._process.stderr, console_mode) + self.stde_task = asyncio.ensure_future(decode_coro) + self.all_futures.append(self.stde_task) + + return self.stdo_task, self.stde_task + + async def _kill(self) -> T.Optional[str]: + # Python does not provide multiplatform support for + # killing a process and all its children so we need + # to roll our own. + p = self._process + try: + if is_windows(): + subprocess.run(['taskkill', '/F', '/T', '/PID', str(p.pid)]) + else: + # Send a termination signal to the process group that setsid() + # created - giving it a chance to perform any cleanup. + os.killpg(p.pid, signal.SIGTERM) + + # Make sure the termination signal actually kills the process + # group, otherwise retry with a SIGKILL. + with suppress(asyncio.TimeoutError): + await asyncio.wait_for(p.wait(), timeout=0.5) + if p.returncode is not None: + return None + + os.killpg(p.pid, signal.SIGKILL) + + with suppress(asyncio.TimeoutError): + await asyncio.wait_for(p.wait(), timeout=1) + if p.returncode is not None: + return None + + # An earlier kill attempt has not worked for whatever reason. + # Try to kill it one last time with a direct call. + # If the process has spawned children, they will remain around. + p.kill() + with suppress(asyncio.TimeoutError): + await asyncio.wait_for(p.wait(), timeout=1) + if p.returncode is not None: + return None + return 'Test process could not be killed.' + except ProcessLookupError: + # Sometimes (e.g. with Wine) this happens. There's nothing + # we can do, probably the process already died so just wait + # for the event loop to pick that up. + await p.wait() + return None + finally: + if self.stdo_task: + self.stdo_task.cancel() + if self.stde_task: + self.stde_task.cancel() + + async def wait(self, test: 'TestRun') -> None: + p = self._process + + self.all_futures.append(asyncio.ensure_future(p.wait())) + try: + await complete_all(self.all_futures, timeout=test.timeout) + except asyncio.TimeoutError: + test.additional_error += await self._kill() or '' + test.res = TestResult.TIMEOUT + except asyncio.CancelledError: + # The main loop must have seen Ctrl-C. + test.additional_error += await self._kill() or '' + test.res = TestResult.INTERRUPT + finally: + if self.postwait_fn: + self.postwait_fn() + + test.returncode = p.returncode or 0 + +class SingleTestRunner: + + def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, + options: argparse.Namespace): + self.test = test + self.options = options + self.cmd = self._get_cmd() + + if self.cmd and self.test.extra_paths: + env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + env['PATH'] + winecmd = [] + for c in self.cmd: + winecmd.append(c) + if os.path.basename(c).startswith('wine'): + env['WINEPATH'] = get_wine_shortpath( + winecmd, + ['Z:' + p for p in self.test.extra_paths] + env.get('WINEPATH', '').split(';'), + self.test.workdir + ) + break + + # If MALLOC_PERTURB_ is not set, or if it is set to an empty value, + # (i.e., the test or the environment don't explicitly set it), set + # it ourselves. We do this unconditionally for regular tests + # because it is extremely useful to have. + # Setting MALLOC_PERTURB_="0" will completely disable this feature. + if ('MALLOC_PERTURB_' not in env or not env['MALLOC_PERTURB_']) and not options.benchmark: + env['MALLOC_PERTURB_'] = str(random.randint(1, 255)) + + if self.options.gdb or self.test.timeout is None or self.test.timeout <= 0: + timeout = None + elif self.options.timeout_multiplier is None: + timeout = self.test.timeout + elif self.options.timeout_multiplier <= 0: + timeout = None + else: + timeout = self.test.timeout * self.options.timeout_multiplier + + is_parallel = test.is_parallel and self.options.num_processes > 1 and not self.options.gdb + verbose = (test.verbose or self.options.verbose) and not self.options.quiet + self.runobj = TestRun(test, env, name, timeout, is_parallel, verbose) + + if self.options.gdb: + self.console_mode = ConsoleUser.GDB + elif self.runobj.direct_stdout: + self.console_mode = ConsoleUser.STDOUT + else: + self.console_mode = ConsoleUser.LOGGER + + def _get_test_cmd(self) -> T.Optional[T.List[str]]: + testentry = self.test.fname[0] + if self.options.no_rebuild and self.test.cmd_is_built and not os.path.isfile(testentry): + raise TestException(f'The test program {testentry!r} does not exist. Cannot run tests before building them.') + if testentry.endswith('.jar'): + return ['java', '-jar'] + self.test.fname + elif not self.test.is_cross_built and run_with_mono(testentry): + return ['mono'] + self.test.fname + elif self.test.cmd_is_exe and self.test.is_cross_built and self.test.needs_exe_wrapper: + if self.test.exe_wrapper is None: + # Can not run test on cross compiled executable + # because there is no execute wrapper. + return None + elif self.test.cmd_is_exe: + # If the command is not built (ie, its a python script), + # then we don't check for the exe-wrapper + if not self.test.exe_wrapper.found(): + msg = ('The exe_wrapper defined in the cross file {!r} was not ' + 'found. Please check the command and/or add it to PATH.') + raise TestException(msg.format(self.test.exe_wrapper.name)) + return self.test.exe_wrapper.get_command() + self.test.fname + return self.test.fname + + def _get_cmd(self) -> T.Optional[T.List[str]]: + test_cmd = self._get_test_cmd() + if not test_cmd: + return None + return TestHarness.get_wrapper(self.options) + test_cmd + + @property + def is_parallel(self) -> bool: + return self.runobj.is_parallel + + @property + def visible_name(self) -> str: + return self.runobj.name + + @property + def timeout(self) -> T.Optional[int]: + return self.runobj.timeout + + async def run(self, harness: 'TestHarness') -> TestRun: + if self.cmd is None: + self.stdo = 'Not run because cannot execute cross compiled binaries.' + harness.log_start_test(self.runobj) + self.runobj.complete_skip() + else: + cmd = self.cmd + self.test.cmd_args + self.options.test_args + self.runobj.start(cmd) + harness.log_start_test(self.runobj) + await self._run_cmd(harness, cmd) + return self.runobj + + async def _run_subprocess(self, args: T.List[str], *, + stdout: T.Optional[int], stderr: T.Optional[int], + env: T.Dict[str, str], cwd: T.Optional[str]) -> TestSubprocess: + # Let gdb handle ^C instead of us + if self.options.gdb: + previous_sigint_handler = signal.getsignal(signal.SIGINT) + # Make the meson executable ignore SIGINT while gdb is running. + signal.signal(signal.SIGINT, signal.SIG_IGN) + + def preexec_fn() -> None: + if self.options.gdb: + # Restore the SIGINT handler for the child process to + # ensure it can handle it. + signal.signal(signal.SIGINT, signal.SIG_DFL) + else: + # We don't want setsid() in gdb because gdb needs the + # terminal in order to handle ^C and not show tcsetpgrp() + # errors avoid not being able to use the terminal. + os.setsid() + + def postwait_fn() -> None: + if self.options.gdb: + # Let us accept ^C again + signal.signal(signal.SIGINT, previous_sigint_handler) + + p = await asyncio.create_subprocess_exec(*args, + stdout=stdout, + stderr=stderr, + env=env, + cwd=cwd, + preexec_fn=preexec_fn if not is_windows() else None) + return TestSubprocess(p, stdout=stdout, stderr=stderr, + postwait_fn=postwait_fn if not is_windows() else None) + + async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None: + if self.console_mode is ConsoleUser.GDB: + stdout = None + stderr = None + else: + stdout = asyncio.subprocess.PIPE + stderr = asyncio.subprocess.STDOUT \ + if not self.options.split and not self.runobj.needs_parsing \ + else asyncio.subprocess.PIPE + + extra_cmd = [] # type: T.List[str] + if self.test.protocol is TestProtocol.GTEST: + gtestname = self.test.name + if self.test.workdir: + gtestname = os.path.join(self.test.workdir, self.test.name) + extra_cmd.append(f'--gtest_output=xml:{gtestname}.xml') + + p = await self._run_subprocess(cmd + extra_cmd, + stdout=stdout, + stderr=stderr, + env=self.runobj.env, + cwd=self.test.workdir) + + if self.runobj.needs_parsing: + parse_coro = self.runobj.parse(harness, p.stdout_lines()) + parse_task = asyncio.ensure_future(parse_coro) + else: + parse_task = None + + stdo_task, stde_task = p.communicate(self.runobj, self.console_mode) + await p.wait(self.runobj) + + if parse_task: + await parse_task + if stdo_task: + await stdo_task + if stde_task: + await stde_task + + self.runobj.complete() + + +class TestHarness: + def __init__(self, options: argparse.Namespace): + self.options = options + self.collected_failures = [] # type: T.List[TestRun] + self.fail_count = 0 + self.expectedfail_count = 0 + self.unexpectedpass_count = 0 + self.success_count = 0 + self.skip_count = 0 + self.timeout_count = 0 + self.test_count = 0 + self.name_max_len = 0 + self.is_run = False + self.loggers = [] # type: T.List[TestLogger] + self.console_logger = ConsoleLogger() + self.loggers.append(self.console_logger) + self.need_console = False + self.ninja = None # type: T.List[str] + + self.logfile_base = None # type: T.Optional[str] + if self.options.logbase and not self.options.gdb: + namebase = None + self.logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase) + + if self.options.wrapper: + namebase = os.path.basename(self.get_wrapper(self.options)[0]) + elif self.options.setup: + namebase = self.options.setup.replace(":", "_") + + if namebase: + self.logfile_base += '-' + namebase.replace(' ', '_') + + self.prepare_build() + self.load_metadata() + + ss = set() + for t in self.tests: + for s in t.suite: + ss.add(s) + self.suites = list(ss) + + def get_console_logger(self) -> 'ConsoleLogger': + assert self.console_logger + return self.console_logger + + def prepare_build(self) -> None: + if self.options.no_rebuild: + return + + self.ninja = environment.detect_ninja() + if not self.ninja: + print("Can't find ninja, can't rebuild test.") + # If ninja can't be found return exit code 127, indicating command + # not found for shell, which seems appropriate here. This works + # nicely for `git bisect run`, telling it to abort - no point in + # continuing if there's no ninja. + sys.exit(127) + + def load_metadata(self) -> None: + startdir = os.getcwd() + try: + os.chdir(self.options.wd) + + # Before loading build / test data, make sure that the build + # configuration does not need to be regenerated. This needs to + # happen before rebuild_deps(), because we need the correct list of + # tests and their dependencies to compute + if not self.options.no_rebuild: + teststdo = subprocess.run(self.ninja + ['-n', 'build.ninja'], capture_output=True).stdout + if b'ninja: no work to do.' not in teststdo and b'samu: nothing to do' not in teststdo: + stdo = sys.stderr if self.options.list else sys.stdout + ret = subprocess.run(self.ninja + ['build.ninja'], stdout=stdo.fileno()) + if ret.returncode != 0: + raise TestException(f'Could not configure {self.options.wd!r}') + + self.build_data = build.load(os.getcwd()) + if not self.options.setup: + self.options.setup = self.build_data.test_setup_default_name + if self.options.benchmark: + self.tests = self.load_tests('meson_benchmark_setup.dat') + else: + self.tests = self.load_tests('meson_test_setup.dat') + finally: + os.chdir(startdir) + + def load_tests(self, file_name: str) -> T.List[TestSerialisation]: + datafile = Path('meson-private') / file_name + if not datafile.is_file(): + raise TestException(f'Directory {self.options.wd!r} does not seem to be a Meson build directory.') + with datafile.open('rb') as f: + objs = check_testdata(pickle.load(f)) + return objs + + def __enter__(self) -> 'TestHarness': + return self + + def __exit__(self, exc_type: T.Any, exc_value: T.Any, traceback: T.Any) -> None: + self.close_logfiles() + + def close_logfiles(self) -> None: + for l in self.loggers: + l.close() + self.console_logger = None + + def get_test_setup(self, test: T.Optional[TestSerialisation]) -> build.TestSetup: + if ':' in self.options.setup: + if self.options.setup not in self.build_data.test_setups: + sys.exit(f"Unknown test setup '{self.options.setup}'.") + return self.build_data.test_setups[self.options.setup] + else: + full_name = test.project_name + ":" + self.options.setup + if full_name not in self.build_data.test_setups: + sys.exit(f"Test setup '{self.options.setup}' not found from project '{test.project_name}'.") + return self.build_data.test_setups[full_name] + + def merge_setup_options(self, options: argparse.Namespace, test: TestSerialisation) -> T.Dict[str, str]: + current = self.get_test_setup(test) + if not options.gdb: + options.gdb = current.gdb + if options.gdb: + options.verbose = True + if options.timeout_multiplier is None: + options.timeout_multiplier = current.timeout_multiplier + # if options.env is None: + # options.env = current.env # FIXME, should probably merge options here. + if options.wrapper is None: + options.wrapper = current.exe_wrapper + elif current.exe_wrapper: + sys.exit('Conflict: both test setup and command line specify an exe wrapper.') + return current.env.get_env(os.environ.copy()) + + def get_test_runner(self, test: TestSerialisation) -> SingleTestRunner: + name = self.get_pretty_suite(test) + options = deepcopy(self.options) + if self.options.setup: + env = self.merge_setup_options(options, test) + else: + env = os.environ.copy() + test_env = test.env.get_env(env) + env.update(test_env) + if (test.is_cross_built and test.needs_exe_wrapper and + test.exe_wrapper and test.exe_wrapper.found()): + env['MESON_EXE_WRAPPER'] = join_args(test.exe_wrapper.get_command()) + return SingleTestRunner(test, env, name, options) + + def process_test_result(self, result: TestRun) -> None: + if result.res is TestResult.TIMEOUT: + self.timeout_count += 1 + elif result.res is TestResult.SKIP: + self.skip_count += 1 + elif result.res is TestResult.OK: + self.success_count += 1 + elif result.res in {TestResult.FAIL, TestResult.ERROR, TestResult.INTERRUPT}: + self.fail_count += 1 + elif result.res is TestResult.EXPECTEDFAIL: + self.expectedfail_count += 1 + elif result.res is TestResult.UNEXPECTEDPASS: + self.unexpectedpass_count += 1 + else: + sys.exit(f'Unknown test result encountered: {result.res}') + + if result.res.is_bad(): + self.collected_failures.append(result) + for l in self.loggers: + l.log(self, result) + + @property + def numlen(self) -> int: + return len(str(self.test_count)) + + @property + def max_left_width(self) -> int: + return 2 * self.numlen + 2 + + def get_test_num_prefix(self, num: int) -> str: + return '{num:{numlen}}/{testcount} '.format(numlen=self.numlen, + num=num, + testcount=self.test_count) + + def format(self, result: TestRun, colorize: bool, + max_left_width: int = 0, + prefix: str = '', + left: T.Optional[str] = None, + middle: T.Optional[str] = None, + right: T.Optional[str] = None) -> str: + if left is None: + left = self.get_test_num_prefix(result.num) + + # A non-default max_left_width lets the logger print more stuff before the + # name, while ensuring that the rightmost columns remain aligned. + max_left_width = max(max_left_width, self.max_left_width) + + if middle is None: + middle = result.name + extra_mid_width = max_left_width + self.name_max_len + 1 - uniwidth(middle) - uniwidth(left) - uniwidth(prefix) + middle += ' ' * max(1, extra_mid_width) + + if right is None: + right = '{res} {dur:{durlen}.2f}s'.format( + res=result.res.get_text(colorize), + dur=result.duration, + durlen=self.duration_max_len + 3) + details = result.get_details() + if details: + right += ' ' + details + return prefix + left + middle + right + + def summary(self) -> str: + return textwrap.dedent(''' + Ok: {:<4} + Expected Fail: {:<4} + Fail: {:<4} + Unexpected Pass: {:<4} + Skipped: {:<4} + Timeout: {:<4} + ''').format(self.success_count, self.expectedfail_count, self.fail_count, + self.unexpectedpass_count, self.skip_count, self.timeout_count) + + def total_failure_count(self) -> int: + return self.fail_count + self.unexpectedpass_count + self.timeout_count + + def doit(self) -> int: + if self.is_run: + raise RuntimeError('Test harness object can only be used once.') + self.is_run = True + tests = self.get_tests() + if not tests: + return 0 + if not self.options.no_rebuild and not rebuild_deps(self.ninja, self.options.wd, tests): + # We return 125 here in case the build failed. + # The reason is that exit code 125 tells `git bisect run` that the current + # commit should be skipped. Thus users can directly use `meson test` to + # bisect without needing to handle the does-not-build case separately in a + # wrapper script. + sys.exit(125) + + self.name_max_len = max(uniwidth(self.get_pretty_suite(test)) for test in tests) + self.options.num_processes = min(self.options.num_processes, + len(tests) * self.options.repeat) + startdir = os.getcwd() + try: + os.chdir(self.options.wd) + runners = [] # type: T.List[SingleTestRunner] + for i in range(self.options.repeat): + runners.extend(self.get_test_runner(test) for test in tests) + if i == 0: + self.duration_max_len = max(len(str(int(runner.timeout or 99))) + for runner in runners) + # Disable the progress report if it gets in the way + self.need_console = any(runner.console_mode is not ConsoleUser.LOGGER + for runner in runners) + + self.test_count = len(runners) + self.run_tests(runners) + finally: + os.chdir(startdir) + return self.total_failure_count() + + @staticmethod + def split_suite_string(suite: str) -> T.Tuple[str, str]: + if ':' in suite: + split = suite.split(':', 1) + assert len(split) == 2 + return split[0], split[1] + else: + return suite, "" + + @staticmethod + def test_in_suites(test: TestSerialisation, suites: T.List[str]) -> bool: + for suite in suites: + (prj_match, st_match) = TestHarness.split_suite_string(suite) + for prjst in test.suite: + (prj, st) = TestHarness.split_suite_string(prjst) + + # the SUITE can be passed as + # suite_name + # or + # project_name:suite_name + # so we need to select only the test belonging to project_name + + # this if handle the first case (i.e., SUITE == suite_name) + + # in this way we can run tests belonging to different + # (sub)projects which share the same suite_name + if not st_match and st == prj_match: + return True + + # these two conditions are needed to handle the second option + # i.e., SUITE == project_name:suite_name + + # in this way we select the only the tests of + # project_name with suite_name + if prj_match and prj != prj_match: + continue + if st_match and st != st_match: + continue + return True + return False + + def test_suitable(self, test: TestSerialisation) -> bool: + if TestHarness.test_in_suites(test, self.options.exclude_suites): + return False + + if self.options.include_suites: + # Both force inclusion (overriding add_test_setup) and exclude + # everything else + return TestHarness.test_in_suites(test, self.options.include_suites) + + if self.options.setup: + setup = self.get_test_setup(test) + if TestHarness.test_in_suites(test, setup.exclude_suites): + return False + + return True + + def tests_from_args(self, tests: T.List[TestSerialisation]) -> T.Generator[TestSerialisation, None, None]: + ''' + Allow specifying test names like "meson test foo1 foo2", where test('foo1', ...) + + Also support specifying the subproject to run tests from like + "meson test subproj:" (all tests inside subproj) or "meson test subproj:foo1" + to run foo1 inside subproj. Coincidentally also "meson test :foo1" to + run all tests with that name across all subprojects, which is + identical to "meson test foo1" + ''' + patterns: T.Dict[T.Tuple[str, str], bool] = {} + for arg in self.options.args: + # Replace empty components by wildcards: + # '' -> '*:*' + # 'name' -> '*:name' + # ':name' -> '*:name' + # 'proj:' -> 'proj:*' + if ':' in arg: + subproj, name = arg.split(':', maxsplit=1) + if name == '': + name = '*' + if subproj == '': # in case arg was ':' + subproj = '*' + else: + subproj, name = '*', arg + patterns[(subproj, name)] = False + + for t in tests: + # For each test, find the first matching pattern + # and mark it as used. yield the matching tests. + for subproj, name in list(patterns): + if fnmatch(t.project_name, subproj) and fnmatch(t.name, name): + patterns[(subproj, name)] = True + yield t + break + + for (subproj, name), was_used in patterns.items(): + if not was_used: + # For each unused pattern... + arg = f'{subproj}:{name}' + for t in tests: + # ... if it matches a test, then it wasn't used because another + # pattern matched the same test before. + # Report it as a warning. + if fnmatch(t.project_name, subproj) and fnmatch(t.name, name): + mlog.warning(f'{arg} test name is redundant and was not used') + break + else: + # If the pattern doesn't match any test, + # report it as an error. We don't want the `test` command to + # succeed on an invalid pattern. + raise MesonException(f'{arg} test name does not match any test') + + def get_tests(self, errorfile: T.Optional[T.IO] = None) -> T.List[TestSerialisation]: + if not self.tests: + print('No tests defined.', file=errorfile) + return [] + + tests = [t for t in self.tests if self.test_suitable(t)] + if self.options.args: + tests = list(self.tests_from_args(tests)) + + if not tests: + print('No suitable tests defined.', file=errorfile) + return [] + + return tests + + def flush_logfiles(self) -> None: + for l in self.loggers: + l.flush() + + def open_logfiles(self) -> None: + if not self.logfile_base: + return + + self.loggers.append(JunitBuilder(self.logfile_base + '.junit.xml')) + self.loggers.append(JsonLogfileBuilder(self.logfile_base + '.json')) + self.loggers.append(TextLogfileBuilder(self.logfile_base + '.txt', errors='surrogateescape')) + + @staticmethod + def get_wrapper(options: argparse.Namespace) -> T.List[str]: + wrap = [] # type: T.List[str] + if options.gdb: + wrap = [options.gdb_path, '--quiet'] + if options.repeat > 1: + wrap += ['-ex', 'run', '-ex', 'quit'] + # Signal the end of arguments to gdb + wrap += ['--args'] + if options.wrapper: + wrap += options.wrapper + return wrap + + def get_pretty_suite(self, test: TestSerialisation) -> str: + if len(self.suites) > 1 and test.suite: + rv = TestHarness.split_suite_string(test.suite[0])[0] + s = "+".join(TestHarness.split_suite_string(s)[1] for s in test.suite) + if s: + rv += ":" + return rv + s + " / " + test.name + else: + return test.name + + def run_tests(self, runners: T.List[SingleTestRunner]) -> None: + try: + self.open_logfiles() + + # TODO: this is the default for python 3.8 + if sys.platform == 'win32': + asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) + + asyncio.run(self._run_tests(runners)) + finally: + self.close_logfiles() + + def log_subtest(self, test: TestRun, s: str, res: TestResult) -> None: + for l in self.loggers: + l.log_subtest(self, test, s, res) + + def log_start_test(self, test: TestRun) -> None: + for l in self.loggers: + l.start_test(self, test) + + async def _run_tests(self, runners: T.List[SingleTestRunner]) -> None: + semaphore = asyncio.Semaphore(self.options.num_processes) + futures = deque() # type: T.Deque[asyncio.Future] + running_tests = {} # type: T.Dict[asyncio.Future, str] + interrupted = False + ctrlc_times = deque(maxlen=MAX_CTRLC) # type: T.Deque[float] + loop = asyncio.get_running_loop() + + async def run_test(test: SingleTestRunner) -> None: + async with semaphore: + if interrupted or (self.options.repeat > 1 and self.fail_count): + return + res = await test.run(self) + self.process_test_result(res) + maxfail = self.options.maxfail + if maxfail and self.fail_count >= maxfail and res.res.is_bad(): + cancel_all_tests() + + def test_done(f: asyncio.Future) -> None: + if not f.cancelled(): + f.result() + futures.remove(f) + try: + del running_tests[f] + except KeyError: + pass + + def cancel_one_test(warn: bool) -> None: + future = futures.popleft() + futures.append(future) + if warn: + self.flush_logfiles() + mlog.warning('CTRL-C detected, interrupting {}'.format(running_tests[future])) + del running_tests[future] + future.cancel() + + def cancel_all_tests() -> None: + nonlocal interrupted + interrupted = True + while running_tests: + cancel_one_test(False) + + def sigterm_handler() -> None: + if interrupted: + return + self.flush_logfiles() + mlog.warning('Received SIGTERM, exiting') + cancel_all_tests() + + def sigint_handler() -> None: + # We always pick the longest-running future that has not been cancelled + # If all the tests have been CTRL-C'ed, just stop + nonlocal interrupted + if interrupted: + return + ctrlc_times.append(loop.time()) + if len(ctrlc_times) == MAX_CTRLC and ctrlc_times[-1] - ctrlc_times[0] < 1: + self.flush_logfiles() + mlog.warning('CTRL-C detected, exiting') + cancel_all_tests() + elif running_tests: + cancel_one_test(True) + else: + self.flush_logfiles() + mlog.warning('CTRL-C detected, exiting') + interrupted = True + + for l in self.loggers: + l.start(self) + + if sys.platform != 'win32': + if os.getpgid(0) == os.getpid(): + loop.add_signal_handler(signal.SIGINT, sigint_handler) + else: + loop.add_signal_handler(signal.SIGINT, sigterm_handler) + loop.add_signal_handler(signal.SIGTERM, sigterm_handler) + try: + for runner in runners: + if not runner.is_parallel: + await complete_all(futures) + future = asyncio.ensure_future(run_test(runner)) + futures.append(future) + running_tests[future] = runner.visible_name + future.add_done_callback(test_done) + if not runner.is_parallel: + await complete(future) + if self.options.repeat > 1 and self.fail_count: + break + + await complete_all(futures) + finally: + if sys.platform != 'win32': + loop.remove_signal_handler(signal.SIGINT) + loop.remove_signal_handler(signal.SIGTERM) + for l in self.loggers: + await l.finish(self) + +def list_tests(th: TestHarness) -> bool: + tests = th.get_tests(errorfile=sys.stderr) + for t in tests: + print(th.get_pretty_suite(t)) + return not tests + +def rebuild_deps(ninja: T.List[str], wd: str, tests: T.List[TestSerialisation]) -> bool: + def convert_path_to_target(path: str) -> str: + path = os.path.relpath(path, wd) + if os.sep != '/': + path = path.replace(os.sep, '/') + return path + + assert len(ninja) > 0 + + depends = set() # type: T.Set[str] + targets = set() # type: T.Set[str] + intro_targets = {} # type: T.Dict[str, T.List[str]] + for target in load_info_file(get_infodir(wd), kind='targets'): + intro_targets[target['id']] = [ + convert_path_to_target(f) + for f in target['filename']] + for t in tests: + for d in t.depends: + if d in depends: + continue + depends.update(d) + targets.update(intro_targets[d]) + + ret = subprocess.run(ninja + ['-C', wd] + sorted(targets)).returncode + if ret != 0: + print(f'Could not rebuild {wd}') + return False + + return True + +def run(options: argparse.Namespace) -> int: + if options.benchmark: + options.num_processes = 1 + + if options.verbose and options.quiet: + print('Can not be both quiet and verbose at the same time.') + return 1 + + check_bin = None + if options.gdb: + options.verbose = True + if options.wrapper: + print('Must not specify both a wrapper and gdb at the same time.') + return 1 + check_bin = 'gdb' + + if options.wrapper: + check_bin = options.wrapper[0] + + if check_bin is not None: + exe = ExternalProgram(check_bin, silent=True) + if not exe.found(): + print(f'Could not find requested program: {check_bin!r}') + return 1 + + b = build.load(options.wd) + need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) + setup_vsenv(need_vsenv) + + if not options.no_rebuild: + backend = b.environment.coredata.get_option(OptionKey('backend')) + if backend == 'none': + # nothing to build... + options.no_rebuild = True + elif backend != 'ninja': + print('Only ninja backend is supported to rebuild tests before running them.') + # Disable, no point in trying to build anything later + options.no_rebuild = True + + with TestHarness(options) as th: + try: + if options.list: + return list_tests(th) + return th.doit() + except TestException as e: + print('Meson test encountered an error:\n') + if os.environ.get('MESON_FORCE_BACKTRACE'): + raise e + else: + print(e) + return 1 + +def run_with_args(args: T.List[str]) -> int: + parser = argparse.ArgumentParser(prog='meson test') + add_arguments(parser) + options = parser.parse_args(args) + return run(options) diff --git a/devtools/meson/mesonbuild/munstable_coredata.py b/devtools/meson/mesonbuild/munstable_coredata.py new file mode 100644 index 0000000..e6c543b --- /dev/null +++ b/devtools/meson/mesonbuild/munstable_coredata.py @@ -0,0 +1,115 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +from . import coredata as cdata +from .mesonlib import MachineChoice, OptionKey + +import os.path +import pprint +import textwrap + +def add_arguments(parser): + parser.add_argument('--all', action='store_true', dest='all', default=False, + help='Show data not used by current backend.') + + parser.add_argument('builddir', nargs='?', default='.', help='The build directory') + + +def dump_compilers(compilers): + for lang, compiler in compilers.items(): + print(' ' + lang + ':') + print(' Id: ' + compiler.id) + print(' Command: ' + ' '.join(compiler.exelist)) + if compiler.full_version: + print(' Full version: ' + compiler.full_version) + if compiler.version: + print(' Detected version: ' + compiler.version) + + +def dump_guids(d): + for name, value in d.items(): + print(' ' + name + ': ' + value) + + +def run(options): + datadir = 'meson-private' + if options.builddir is not None: + datadir = os.path.join(options.builddir, datadir) + if not os.path.isdir(datadir): + print('Current directory is not a build dir. Please specify it or ' + 'change the working directory to it.') + return 1 + + all_backends = options.all + + print('This is a dump of the internal unstable cache of meson. This is for debugging only.') + print('Do NOT parse, this will change from version to version in incompatible ways') + print('') + + coredata = cdata.load(options.builddir) + backend = coredata.get_option(OptionKey('backend')) + for k, v in sorted(coredata.__dict__.items()): + if k in {'backend_options', 'base_options', 'builtins', 'compiler_options', 'user_options'}: + # use `meson configure` to view these + pass + elif k in {'install_guid', 'test_guid', 'regen_guid'}: + if all_backends or backend.startswith('vs'): + print(k + ': ' + v) + elif k == 'target_guids': + if all_backends or backend.startswith('vs'): + print(k + ':') + dump_guids(v) + elif k == 'lang_guids': + if all_backends or backend.startswith('vs') or backend == 'xcode': + print(k + ':') + dump_guids(v) + elif k == 'meson_command': + if all_backends or backend.startswith('vs'): + print('Meson command used in build file regeneration: ' + ' '.join(v)) + elif k == 'pkgconf_envvar': + print('Last seen PKGCONFIG environment variable value: ' + v) + elif k == 'version': + print('Meson version: ' + v) + elif k == 'cross_files': + if v: + print('Cross File: ' + ' '.join(v)) + elif k == 'config_files': + if v: + print('Native File: ' + ' '.join(v)) + elif k == 'compilers': + for for_machine in MachineChoice: + print('Cached {} machine compilers:'.format( + for_machine.get_lower_case_name())) + dump_compilers(v[for_machine]) + elif k == 'deps': + def print_dep(dep_key, dep): + print(' ' + dep_key[0][1] + ": ") + print(' compile args: ' + repr(dep.get_compile_args())) + print(' link args: ' + repr(dep.get_link_args())) + if dep.get_sources(): + print(' sources: ' + repr(dep.get_sources())) + print(' version: ' + repr(dep.get_version())) + + for for_machine in iter(MachineChoice): + items_list = sorted(v[for_machine].items()) + if items_list: + print(f'Cached dependencies for {for_machine.get_lower_case_name()} machine') + for dep_key, deps in items_list: + for dep in deps: + print_dep(dep_key, dep) + else: + print(k + ':') + print(textwrap.indent(pprint.pformat(v), ' ')) diff --git a/devtools/meson/mesonbuild/optinterpreter.py b/devtools/meson/mesonbuild/optinterpreter.py new file mode 100644 index 0000000..8377614 --- /dev/null +++ b/devtools/meson/mesonbuild/optinterpreter.py @@ -0,0 +1,279 @@ +# Copyright 2013-2014 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import re +import typing as T + +from . import coredata +from . import mesonlib +from . import mparser +from . import mlog +from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo +from .interpreter.type_checking import NoneType, in_set_validator + +if T.TYPE_CHECKING: + from .interpreterbase import TYPE_var, TYPE_kwargs + from .interpreterbase import SubProject + from typing_extensions import TypedDict, Literal + + _DEPRECATED_ARGS = T.Union[bool, str, T.Dict[str, str], T.List[str]] + + FuncOptionArgs = TypedDict('FuncOptionArgs', { + 'type': str, + 'description': str, + 'yield': bool, + 'choices': T.Optional[T.List[str]], + 'value': object, + 'min': T.Optional[int], + 'max': T.Optional[int], + 'deprecated': _DEPRECATED_ARGS, + }) + + class StringArgs(TypedDict): + value: str + + class BooleanArgs(TypedDict): + value: bool + + class ComboArgs(TypedDict): + value: str + choices: T.List[str] + + class IntegerArgs(TypedDict): + value: int + min: T.Optional[int] + max: T.Optional[int] + + class StringArrayArgs(TypedDict): + value: T.Optional[T.Union[str, T.List[str]]] + choices: T.List[str] + + class FeatureArgs(TypedDict): + value: Literal['enabled', 'disabled', 'auto'] + choices: T.List[str] + + +class OptionException(mesonlib.MesonException): + pass + + +optname_regex = re.compile('[^a-zA-Z0-9_-]') + + +class OptionInterpreter: + def __init__(self, subproject: 'SubProject') -> None: + self.options: 'coredata.MutableKeyedOptionDictType' = {} + self.subproject = subproject + self.option_types: T.Dict[str, T.Callable[..., coredata.UserOption]] = { + 'string': self.string_parser, + 'boolean': self.boolean_parser, + 'combo': self.combo_parser, + 'integer': self.integer_parser, + 'array': self.string_array_parser, + 'feature': self.feature_parser, + } + + def process(self, option_file: str) -> None: + try: + with open(option_file, encoding='utf-8') as f: + ast = mparser.Parser(f.read(), option_file).parse() + except mesonlib.MesonException as me: + me.file = option_file + raise me + if not isinstance(ast, mparser.CodeBlockNode): + e = OptionException('Option file is malformed.') + e.lineno = ast.lineno() + e.file = option_file + raise e + for cur in ast.lines: + try: + self.current_node = cur + self.evaluate_statement(cur) + except mesonlib.MesonException as e: + e.lineno = cur.lineno + e.colno = cur.colno + e.file = option_file + raise e + except Exception as e: + raise mesonlib.MesonException( + str(e), lineno=cur.lineno, colno=cur.colno, file=option_file) + + def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var': + if isinstance(arg, str): + return arg + elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode, + mparser.NumberNode)): + return arg.value + elif isinstance(arg, mparser.ArrayNode): + return [self.reduce_single(curarg) for curarg in arg.args.arguments] + elif isinstance(arg, mparser.DictNode): + d = {} + for k, v in arg.args.kwargs.items(): + if not isinstance(k, mparser.StringNode): + raise OptionException('Dictionary keys must be a string literal') + d[k.value] = self.reduce_single(v) + return d + elif isinstance(arg, mparser.UMinusNode): + res = self.reduce_single(arg.value) + if not isinstance(res, (int, float)): + raise OptionException('Token after "-" is not a number') + FeatureNew.single_use('negative numbers in meson_options.txt', '0.54.1', self.subproject) + return -res + elif isinstance(arg, mparser.NotNode): + res = self.reduce_single(arg.value) + if not isinstance(res, bool): + raise OptionException('Token after "not" is not a a boolean') + FeatureNew.single_use('negation ("not") in meson_options.txt', '0.54.1', self.subproject) + return not res + elif isinstance(arg, mparser.ArithmeticNode): + l = self.reduce_single(arg.left) + r = self.reduce_single(arg.right) + if not (arg.operation == 'add' and isinstance(l, str) and isinstance(r, str)): + raise OptionException('Only string concatenation with the "+" operator is allowed') + FeatureNew.single_use('string concatenation in meson_options.txt', '0.55.0', self.subproject) + return l + r + else: + raise OptionException('Arguments may only be string, int, bool, or array of those.') + + def reduce_arguments(self, args: mparser.ArgumentNode) -> T.Tuple['TYPE_var', 'TYPE_kwargs']: + if args.incorrect_order(): + raise OptionException('All keyword arguments must be after positional arguments.') + reduced_pos = [self.reduce_single(arg) for arg in args.arguments] + reduced_kw = {} + for key in args.kwargs.keys(): + if not isinstance(key, mparser.IdNode): + raise OptionException('Keyword argument name is not a string.') + a = args.kwargs[key] + reduced_kw[key.value] = self.reduce_single(a) + return reduced_pos, reduced_kw + + def evaluate_statement(self, node: mparser.BaseNode) -> None: + if not isinstance(node, mparser.FunctionNode): + raise OptionException('Option file may only contain option definitions') + func_name = node.func_name + if func_name != 'option': + raise OptionException('Only calls to option() are allowed in option files.') + (posargs, kwargs) = self.reduce_arguments(node.args) + self.func_option(posargs, kwargs) + + @typed_kwargs( + 'option', + KwargInfo( + 'type', + str, + required=True, + validator=in_set_validator({'string', 'boolean', 'integer', 'combo', 'array', 'feature'}) + ), + KwargInfo('description', str, default=''), + KwargInfo( + 'deprecated', + (bool, str, ContainerTypeInfo(dict, str), ContainerTypeInfo(list, str)), + default=False, + since='0.60.0', + since_values={str: '0.63.0'}, + ), + KwargInfo('yield', bool, default=coredata.DEFAULT_YIELDING, since='0.45.0'), + allow_unknown=True, + ) + @typed_pos_args('option', str) + def func_option(self, args: T.Tuple[str], kwargs: 'FuncOptionArgs') -> None: + opt_name = args[0] + if optname_regex.search(opt_name) is not None: + raise OptionException('Option names can only contain letters, numbers or dashes.') + key = mesonlib.OptionKey.from_string(opt_name).evolve(subproject=self.subproject) + if not key.is_project(): + raise OptionException('Option name %s is reserved.' % opt_name) + + opt_type = kwargs['type'] + parser = self.option_types[opt_type] + description = kwargs['description'] or opt_name + + # Drop the arguments we've already consumed + n_kwargs = {k: v for k, v in kwargs.items() + if k not in {'type', 'description', 'deprecated', 'yield'}} + + opt = parser(description, (kwargs['yield'], kwargs['deprecated']), n_kwargs) + if key in self.options: + mlog.deprecation(f'Option {opt_name} already exists.') + self.options[key] = opt + + @typed_kwargs( + 'string option', + KwargInfo('value', str, default=''), + ) + def string_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> coredata.UserOption: + return coredata.UserStringOption(description, kwargs['value'], *args) + + @typed_kwargs( + 'boolean option', + KwargInfo( + 'value', + (bool, str), + default=True, + validator=lambda x: None if isinstance(x, bool) or x in {'true', 'false'} else 'boolean options must have boolean values', + deprecated_values={str: ('1.1.0', 'use a boolean, not a string')}, + ), + ) + def boolean_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption: + return coredata.UserBooleanOption(description, kwargs['value'], *args) + + @typed_kwargs( + 'combo option', + KwargInfo('value', (str, NoneType)), + KwargInfo('choices', ContainerTypeInfo(list, str, allow_empty=False), required=True), + ) + def combo_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> coredata.UserOption: + choices = kwargs['choices'] + value = kwargs['value'] + if value is None: + value = kwargs['choices'][0] + return coredata.UserComboOption(description, choices, value, *args) + + @typed_kwargs( + 'integer option', + KwargInfo( + 'value', + (int, str), + default=True, + deprecated_values={str: ('1.1.0', 'use an integer, not a string')}, + convertor=int, + ), + KwargInfo('min', (int, NoneType)), + KwargInfo('max', (int, NoneType)), + ) + def integer_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> coredata.UserOption: + value = kwargs['value'] + inttuple = (kwargs['min'], kwargs['max'], value) + return coredata.UserIntegerOption(description, inttuple, *args) + + @typed_kwargs( + 'string array option', + KwargInfo('value', (ContainerTypeInfo(list, str), str, NoneType)), + KwargInfo('choices', ContainerTypeInfo(list, str), default=[]), + ) + def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption: + choices = kwargs['choices'] + value = kwargs['value'] if kwargs['value'] is not None else choices + return coredata.UserArrayOption(description, value, + choices=choices, + yielding=args[0], + deprecated=args[1]) + + @typed_kwargs( + 'feature option', + KwargInfo('value', str, default='auto', validator=in_set_validator({'auto', 'enabled', 'disabled'})), + ) + def feature_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> coredata.UserOption: + return coredata.UserFeatureOption(description, kwargs['value'], *args) diff --git a/devtools/meson/mesonbuild/programs.py b/devtools/meson/mesonbuild/programs.py new file mode 100644 index 0000000..9bf1844 --- /dev/null +++ b/devtools/meson/mesonbuild/programs.py @@ -0,0 +1,378 @@ +# Copyright 2013-2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Representations and logic for External and Internal Programs.""" + +import functools +import os +import shutil +import stat +import sys +import re +import typing as T +from pathlib import Path + +from . import mesonlib +from . import mlog +from .mesonlib import MachineChoice, OrderedSet + +if T.TYPE_CHECKING: + from .environment import Environment + from .interpreter import Interpreter + + +class ExternalProgram(mesonlib.HoldableObject): + + """A program that is found on the system.""" + + windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd') + for_machine = MachineChoice.BUILD + + def __init__(self, name: str, command: T.Optional[T.List[str]] = None, + silent: bool = False, search_dir: T.Optional[str] = None, + extra_search_dirs: T.Optional[T.List[str]] = None): + self.name = name + self.path: T.Optional[str] = None + self.cached_version: T.Optional[str] = None + if command is not None: + self.command = mesonlib.listify(command) + if mesonlib.is_windows(): + cmd = self.command[0] + args = self.command[1:] + # Check whether the specified cmd is a path to a script, in + # which case we need to insert the interpreter. If not, try to + # use it as-is. + ret = self._shebang_to_cmd(cmd) + if ret: + self.command = ret + args + else: + self.command = [cmd] + args + else: + all_search_dirs = [search_dir] + if extra_search_dirs: + all_search_dirs += extra_search_dirs + for d in all_search_dirs: + self.command = self._search(name, d) + if self.found(): + break + + if self.found(): + # Set path to be the last item that is actually a file (in order to + # skip options in something like ['python', '-u', 'file.py']. If we + # can't find any components, default to the last component of the path. + for arg in reversed(self.command): + if arg is not None and os.path.isfile(arg): + self.path = arg + break + else: + self.path = self.command[-1] + + if not silent: + # ignore the warning because derived classes never call this __init__ + # method, and thus only the found() method of this class is ever executed + if self.found(): # lgtm [py/init-calls-subclass] + mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'), + '(%s)' % ' '.join(self.command)) + else: + mlog.log('Program', mlog.bold(name), 'found:', mlog.red('NO')) + + def summary_value(self) -> T.Union[str, mlog.AnsiDecorator]: + if not self.found(): + return mlog.red('NO') + return self.path + + def __repr__(self) -> str: + r = '<{} {!r} -> {!r}>' + return r.format(self.__class__.__name__, self.name, self.command) + + def description(self) -> str: + '''Human friendly description of the command''' + return ' '.join(self.command) + + def get_version(self, interpreter: T.Optional['Interpreter'] = None) -> str: + if not self.cached_version: + from . import build + raw_cmd = self.get_command() + ['--version'] + if interpreter: + res = interpreter.run_command_impl(interpreter.current_node, (self, ['--version']), + {'capture': True, + 'check': True, + 'env': build.EnvironmentVariables()}, + True) + o, e = res.stdout, res.stderr + else: + p, o, e = mesonlib.Popen_safe(raw_cmd) + if p.returncode != 0: + cmd_str = mesonlib.join_args(raw_cmd) + raise mesonlib.MesonException(f'Command {cmd_str!r} failed with status {p.returncode}.') + output = o.strip() + if not output: + output = e.strip() + match = re.search(r'([0-9][0-9\.]+)', output) + if not match: + raise mesonlib.MesonException(f'Could not find a version number in output of {raw_cmd!r}') + self.cached_version = match.group(1) + return self.cached_version + + @classmethod + def from_bin_list(cls, env: 'Environment', for_machine: MachineChoice, name: str) -> 'ExternalProgram': + # There is a static `for_machine` for this class because the binary + # always runs on the build platform. (It's host platform is our build + # platform.) But some external programs have a target platform, so this + # is what we are specifying here. + command = env.lookup_binary_entry(for_machine, name) + if command is None: + return NonExistingExternalProgram() + return cls.from_entry(name, command) + + @staticmethod + @functools.lru_cache(maxsize=None) + def _windows_sanitize_path(path: str) -> str: + # Ensure that we use USERPROFILE even when inside MSYS, MSYS2, Cygwin, etc. + if 'USERPROFILE' not in os.environ: + return path + # The WindowsApps directory is a bit of a problem. It contains + # some zero-sized .exe files which have "reparse points", that + # might either launch an installed application, or might open + # a page in the Windows Store to download the application. + # + # To handle the case where the python interpreter we're + # running on came from the Windows Store, if we see the + # WindowsApps path in the search path, replace it with + # dirname(sys.executable). + appstore_dir = Path(os.environ['USERPROFILE']) / 'AppData' / 'Local' / 'Microsoft' / 'WindowsApps' + paths = [] + for each in path.split(os.pathsep): + if Path(each) != appstore_dir: + paths.append(each) + elif 'WindowsApps' in sys.executable: + paths.append(os.path.dirname(sys.executable)) + return os.pathsep.join(paths) + + @staticmethod + def from_entry(name: str, command: T.Union[str, T.List[str]]) -> 'ExternalProgram': + if isinstance(command, list): + if len(command) == 1: + command = command[0] + # We cannot do any searching if the command is a list, and we don't + # need to search if the path is an absolute path. + if isinstance(command, list) or os.path.isabs(command): + if isinstance(command, str): + command = [command] + return ExternalProgram(name, command=command, silent=True) + assert isinstance(command, str) + # Search for the command using the specified string! + return ExternalProgram(command, silent=True) + + @staticmethod + def _shebang_to_cmd(script: str) -> T.Optional[T.List[str]]: + """ + Check if the file has a shebang and manually parse it to figure out + the interpreter to use. This is useful if the script is not executable + or if we're on Windows (which does not understand shebangs). + """ + try: + with open(script, encoding='utf-8') as f: + first_line = f.readline().strip() + if first_line.startswith('#!'): + # In a shebang, everything before the first space is assumed to + # be the command to run and everything after the first space is + # the single argument to pass to that command. So we must split + # exactly once. + commands = first_line[2:].split('#')[0].strip().split(maxsplit=1) + if mesonlib.is_windows(): + # Windows does not have UNIX paths so remove them, + # but don't remove Windows paths + if commands[0].startswith('/'): + commands[0] = commands[0].split('/')[-1] + if len(commands) > 0 and commands[0] == 'env': + commands = commands[1:] + # Windows does not ship python3.exe, but we know the path to it + if len(commands) > 0 and commands[0] == 'python3': + commands = mesonlib.python_command + commands[1:] + elif mesonlib.is_haiku(): + # Haiku does not have /usr, but a lot of scripts assume that + # /usr/bin/env always exists. Detect that case and run the + # script with the interpreter after it. + if commands[0] == '/usr/bin/env': + commands = commands[1:] + # We know what python3 is, we're running on it + if len(commands) > 0 and commands[0] == 'python3': + commands = mesonlib.python_command + commands[1:] + else: + # Replace python3 with the actual python3 that we are using + if commands[0] == '/usr/bin/env' and commands[1] == 'python3': + commands = mesonlib.python_command + commands[2:] + elif commands[0].split('/')[-1] == 'python3': + commands = mesonlib.python_command + commands[1:] + return commands + [script] + except Exception as e: + mlog.debug(str(e)) + mlog.debug(f'Unusable script {script!r}') + return None + + def _is_executable(self, path: str) -> bool: + suffix = os.path.splitext(path)[-1].lower()[1:] + execmask = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + if mesonlib.is_windows(): + if suffix in self.windows_exts: + return True + elif os.stat(path).st_mode & execmask: + return not os.path.isdir(path) + return False + + def _search_dir(self, name: str, search_dir: T.Optional[str]) -> T.Optional[list]: + if search_dir is None: + return None + trial = os.path.join(search_dir, name) + if os.path.exists(trial): + if self._is_executable(trial): + return [trial] + # Now getting desperate. Maybe it is a script file that is + # a) not chmodded executable, or + # b) we are on windows so they can't be directly executed. + return self._shebang_to_cmd(trial) + else: + if mesonlib.is_windows(): + for ext in self.windows_exts: + trial_ext = f'{trial}.{ext}' + if os.path.exists(trial_ext): + return [trial_ext] + return None + + def _search_windows_special_cases(self, name: str, command: str) -> T.List[T.Optional[str]]: + ''' + Lots of weird Windows quirks: + 1. PATH search for @name returns files with extensions from PATHEXT, + but only self.windows_exts are executable without an interpreter. + 2. @name might be an absolute path to an executable, but without the + extension. This works inside MinGW so people use it a lot. + 3. The script is specified without an extension, in which case we have + to manually search in PATH. + 4. More special-casing for the shebang inside the script. + ''' + if command: + # On Windows, even if the PATH search returned a full path, we can't be + # sure that it can be run directly if it's not a native executable. + # For instance, interpreted scripts sometimes need to be run explicitly + # with an interpreter if the file association is not done properly. + name_ext = os.path.splitext(command)[1] + if name_ext[1:].lower() in self.windows_exts: + # Good, it can be directly executed + return [command] + # Try to extract the interpreter from the shebang + commands = self._shebang_to_cmd(command) + if commands: + return commands + return [None] + # Maybe the name is an absolute path to a native Windows + # executable, but without the extension. This is technically wrong, + # but many people do it because it works in the MinGW shell. + if os.path.isabs(name): + for ext in self.windows_exts: + command = f'{name}.{ext}' + if os.path.exists(command): + return [command] + # On Windows, interpreted scripts must have an extension otherwise they + # cannot be found by a standard PATH search. So we do a custom search + # where we manually search for a script with a shebang in PATH. + search_dirs = self._windows_sanitize_path(os.environ.get('PATH', '')).split(';') + for search_dir in search_dirs: + commands = self._search_dir(name, search_dir) + if commands: + return commands + return [None] + + def _search(self, name: str, search_dir: T.Optional[str]) -> T.List[T.Optional[str]]: + ''' + Search in the specified dir for the specified executable by name + and if not found search in PATH + ''' + commands = self._search_dir(name, search_dir) + if commands: + return commands + # If there is a directory component, do not look in PATH + if os.path.dirname(name) and not os.path.isabs(name): + return [None] + # Do a standard search in PATH + path = os.environ.get('PATH', None) + if mesonlib.is_windows() and path: + path = self._windows_sanitize_path(path) + command = shutil.which(name, path=path) + if mesonlib.is_windows(): + return self._search_windows_special_cases(name, command) + # On UNIX-like platforms, shutil.which() is enough to find + # all executables whether in PATH or with an absolute path + return [command] + + def found(self) -> bool: + return self.command[0] is not None + + def get_command(self) -> T.List[str]: + return self.command[:] + + def get_path(self) -> T.Optional[str]: + return self.path + + def get_name(self) -> str: + return self.name + + +class NonExistingExternalProgram(ExternalProgram): # lgtm [py/missing-call-to-init] + "A program that will never exist" + + def __init__(self, name: str = 'nonexistingprogram') -> None: + self.name = name + self.command = [None] + self.path = None + + def __repr__(self) -> str: + r = '<{} {!r} -> {!r}>' + return r.format(self.__class__.__name__, self.name, self.command) + + def found(self) -> bool: + return False + + +class OverrideProgram(ExternalProgram): + + """A script overriding a program.""" + + +def find_external_program(env: 'Environment', for_machine: MachineChoice, name: str, + display_name: str, default_names: T.List[str], + allow_default_for_cross: bool = True) -> T.Generator['ExternalProgram', None, None]: + """Find an external program, checking the cross file plus any default options.""" + potential_names = OrderedSet(default_names) + potential_names.add(name) + # Lookup in cross or machine file. + for potential_name in potential_names: + potential_cmd = env.lookup_binary_entry(for_machine, potential_name) + if potential_cmd is not None: + mlog.debug(f'{display_name} binary for {for_machine} specified from cross file, native file, ' + f'or env var as {potential_cmd}') + yield ExternalProgram.from_entry(potential_name, potential_cmd) + # We never fallback if the user-specified option is no good, so + # stop returning options. + return + mlog.debug(f'{display_name} binary missing from cross or native file, or env var undefined.') + # Fallback on hard-coded defaults, if a default binary is allowed for use + # with cross targets, or if this is not a cross target + if allow_default_for_cross or not (for_machine is MachineChoice.HOST and env.is_cross_build(for_machine)): + for potential_path in default_names: + mlog.debug(f'Trying a default {display_name} fallback at', potential_path) + yield ExternalProgram(potential_path, silent=True) + else: + mlog.debug('Default target is not allowed for cross use') diff --git a/devtools/meson/mesonbuild/rewriter.py b/devtools/meson/mesonbuild/rewriter.py new file mode 100644 index 0000000..a9b2e88 --- /dev/null +++ b/devtools/meson/mesonbuild/rewriter.py @@ -0,0 +1,1070 @@ +#!/usr/bin/env python3 +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This class contains the basic functionality needed to run any interpreter +# or an interpreter-based tool. + +# This tool is used to manipulate an existing Meson build definition. +# +# - add a file to a target +# - remove files from a target +# - move targets +# - reindent? +from __future__ import annotations + +from .ast import IntrospectionInterpreter, BUILD_TARGET_FUNCTIONS, AstConditionLevel, AstIDGenerator, AstIndentationGenerator, AstPrinter +from mesonbuild.mesonlib import MesonException, setup_vsenv +from . import mlog, environment +from functools import wraps +from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode +import json, os, re, sys +import typing as T + +if T.TYPE_CHECKING: + from .mparser import BaseNode + +class RewriterException(MesonException): + pass + +def add_arguments(parser, formatter=None): + parser.add_argument('-s', '--sourcedir', type=str, default='.', metavar='SRCDIR', help='Path to source directory.') + parser.add_argument('-V', '--verbose', action='store_true', default=False, help='Enable verbose output') + parser.add_argument('-S', '--skip-errors', dest='skip', action='store_true', default=False, help='Skip errors instead of aborting') + subparsers = parser.add_subparsers(dest='type', title='Rewriter commands', description='Rewrite command to execute') + + # Target + tgt_parser = subparsers.add_parser('target', aliases=['tgt'], help='Modify a target', formatter_class=formatter) + tgt_parser.add_argument('-s', '--subdir', default='', dest='subdir', help='Subdirectory of the new target (only for the "add_target" action)') + tgt_parser.add_argument('--type', dest='tgt_type', choices=rewriter_keys['target']['target_type'][2], default='executable', + help='Type of the target to add (only for the "add_target" action)') + tgt_parser.add_argument('target', help='Name or ID of the target') + tgt_parser.add_argument('operation', choices=['add', 'rm', 'add_target', 'rm_target', 'add_extra_files', 'rm_extra_files', 'info'], + help='Action to execute') + tgt_parser.add_argument('sources', nargs='*', help='Sources to add/remove') + + # KWARGS + kw_parser = subparsers.add_parser('kwargs', help='Modify keyword arguments', formatter_class=formatter) + kw_parser.add_argument('operation', choices=rewriter_keys['kwargs']['operation'][2], + help='Action to execute') + kw_parser.add_argument('function', choices=list(rewriter_func_kwargs.keys()), + help='Function type to modify') + kw_parser.add_argument('id', help='ID of the function to modify (can be anything for "project")') + kw_parser.add_argument('kwargs', nargs='*', help='Pairs of keyword and value') + + # Default options + def_parser = subparsers.add_parser('default-options', aliases=['def'], help='Modify the project default options', formatter_class=formatter) + def_parser.add_argument('operation', choices=rewriter_keys['default_options']['operation'][2], + help='Action to execute') + def_parser.add_argument('options', nargs='*', help='Key, value pairs of configuration option') + + # JSON file/command + cmd_parser = subparsers.add_parser('command', aliases=['cmd'], help='Execute a JSON array of commands', formatter_class=formatter) + cmd_parser.add_argument('json', help='JSON string or file to execute') + +class RequiredKeys: + def __init__(self, keys): + self.keys = keys + + def __call__(self, f): + @wraps(f) + def wrapped(*wrapped_args, **wrapped_kwargs): + assert len(wrapped_args) >= 2 + cmd = wrapped_args[1] + for key, val in self.keys.items(): + typ = val[0] # The type of the value + default = val[1] # The default value -- None is required + choices = val[2] # Valid choices -- None is for everything + if key not in cmd: + if default is not None: + cmd[key] = default + else: + raise RewriterException('Key "{}" is missing in object for {}' + .format(key, f.__name__)) + if not isinstance(cmd[key], typ): + raise RewriterException('Invalid type of "{}". Required is {} but provided was {}' + .format(key, typ.__name__, type(cmd[key]).__name__)) + if choices is not None: + assert isinstance(choices, list) + if cmd[key] not in choices: + raise RewriterException('Invalid value of "{}": Possible values are {} but provided was "{}"' + .format(key, choices, cmd[key])) + return f(*wrapped_args, **wrapped_kwargs) + + return wrapped + +class MTypeBase: + def __init__(self, node: T.Optional[BaseNode] = None): + if node is None: + self.node = self._new_node() # lgtm [py/init-calls-subclass] (node creation does not depend on base class state) + else: + self.node = node + self.node_type = None + for i in self.supported_nodes(): # lgtm [py/init-calls-subclass] (listing nodes does not depend on base class state) + if isinstance(self.node, i): + self.node_type = i + + def _new_node(self): + # Overwrite in derived class + raise RewriterException('Internal error: _new_node of MTypeBase was called') + + def can_modify(self): + return self.node_type is not None + + def get_node(self): + return self.node + + def supported_nodes(self): + # Overwrite in derived class + return [] + + def set_value(self, value): + # Overwrite in derived class + mlog.warning('Cannot set the value of type', mlog.bold(type(self).__name__), '--> skipping') + + def add_value(self, value): + # Overwrite in derived class + mlog.warning('Cannot add a value of type', mlog.bold(type(self).__name__), '--> skipping') + + def remove_value(self, value): + # Overwrite in derived class + mlog.warning('Cannot remove a value of type', mlog.bold(type(self).__name__), '--> skipping') + + def remove_regex(self, value): + # Overwrite in derived class + mlog.warning('Cannot remove a regex in type', mlog.bold(type(self).__name__), '--> skipping') + +class MTypeStr(MTypeBase): + def __init__(self, node: T.Optional[BaseNode] = None): + super().__init__(node) + + def _new_node(self): + return StringNode(Token('', '', 0, 0, 0, None, '')) + + def supported_nodes(self): + return [StringNode] + + def set_value(self, value): + self.node.value = str(value) + +class MTypeBool(MTypeBase): + def __init__(self, node: T.Optional[BaseNode] = None): + super().__init__(node) + + def _new_node(self): + return BooleanNode(Token('', '', 0, 0, 0, None, False)) + + def supported_nodes(self): + return [BooleanNode] + + def set_value(self, value): + self.node.value = bool(value) + +class MTypeID(MTypeBase): + def __init__(self, node: T.Optional[BaseNode] = None): + super().__init__(node) + + def _new_node(self): + return IdNode(Token('', '', 0, 0, 0, None, '')) + + def supported_nodes(self): + return [IdNode] + + def set_value(self, value): + self.node.value = str(value) + +class MTypeList(MTypeBase): + def __init__(self, node: T.Optional[BaseNode] = None): + super().__init__(node) + + def _new_node(self): + return ArrayNode(ArgumentNode(Token('', '', 0, 0, 0, None, '')), 0, 0, 0, 0) + + def _new_element_node(self, value): + # Overwrite in derived class + raise RewriterException('Internal error: _new_element_node of MTypeList was called') + + def _ensure_array_node(self): + if not isinstance(self.node, ArrayNode): + tmp = self.node + self.node = self._new_node() + self.node.args.arguments += [tmp] + + def _check_is_equal(self, node, value) -> bool: + # Overwrite in derived class + return False + + def _check_regex_matches(self, node, regex: str) -> bool: + # Overwrite in derived class + return False + + def get_node(self): + if isinstance(self.node, ArrayNode): + if len(self.node.args.arguments) == 1: + return self.node.args.arguments[0] + return self.node + + def supported_element_nodes(self): + # Overwrite in derived class + return [] + + def supported_nodes(self): + return [ArrayNode] + self.supported_element_nodes() + + def set_value(self, value): + if not isinstance(value, list): + value = [value] + self._ensure_array_node() + self.node.args.arguments = [] # Remove all current nodes + for i in value: + self.node.args.arguments += [self._new_element_node(i)] + + def add_value(self, value): + if not isinstance(value, list): + value = [value] + self._ensure_array_node() + for i in value: + self.node.args.arguments += [self._new_element_node(i)] + + def _remove_helper(self, value, equal_func): + def check_remove_node(node): + for j in value: + if equal_func(i, j): + return True + return False + + if not isinstance(value, list): + value = [value] + self._ensure_array_node() + removed_list = [] + for i in self.node.args.arguments: + if not check_remove_node(i): + removed_list += [i] + self.node.args.arguments = removed_list + + def remove_value(self, value): + self._remove_helper(value, self._check_is_equal) + + def remove_regex(self, regex: str): + self._remove_helper(regex, self._check_regex_matches) + +class MTypeStrList(MTypeList): + def __init__(self, node: T.Optional[BaseNode] = None): + super().__init__(node) + + def _new_element_node(self, value): + return StringNode(Token('', '', 0, 0, 0, None, str(value))) + + def _check_is_equal(self, node, value) -> bool: + if isinstance(node, StringNode): + return node.value == value + return False + + def _check_regex_matches(self, node, regex: str) -> bool: + if isinstance(node, StringNode): + return re.match(regex, node.value) is not None + return False + + def supported_element_nodes(self): + return [StringNode] + +class MTypeIDList(MTypeList): + def __init__(self, node: T.Optional[BaseNode] = None): + super().__init__(node) + + def _new_element_node(self, value): + return IdNode(Token('', '', 0, 0, 0, None, str(value))) + + def _check_is_equal(self, node, value) -> bool: + if isinstance(node, IdNode): + return node.value == value + return False + + def _check_regex_matches(self, node, regex: str) -> bool: + if isinstance(node, StringNode): + return re.match(regex, node.value) is not None + return False + + def supported_element_nodes(self): + return [IdNode] + +rewriter_keys = { + 'default_options': { + 'operation': (str, None, ['set', 'delete']), + 'options': (dict, {}, None) + }, + 'kwargs': { + 'function': (str, None, None), + 'id': (str, None, None), + 'operation': (str, None, ['set', 'delete', 'add', 'remove', 'remove_regex', 'info']), + 'kwargs': (dict, {}, None) + }, + 'target': { + 'target': (str, None, None), + 'operation': (str, None, ['src_add', 'src_rm', 'target_rm', 'target_add', 'extra_files_add', 'extra_files_rm', 'info']), + 'sources': (list, [], None), + 'subdir': (str, '', None), + 'target_type': (str, 'executable', ['both_libraries', 'executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library']), + } +} + +rewriter_func_kwargs = { + 'dependency': { + 'language': MTypeStr, + 'method': MTypeStr, + 'native': MTypeBool, + 'not_found_message': MTypeStr, + 'required': MTypeBool, + 'static': MTypeBool, + 'version': MTypeStrList, + 'modules': MTypeStrList + }, + 'target': { + 'build_by_default': MTypeBool, + 'build_rpath': MTypeStr, + 'dependencies': MTypeIDList, + 'gui_app': MTypeBool, + 'link_with': MTypeIDList, + 'export_dynamic': MTypeBool, + 'implib': MTypeBool, + 'install': MTypeBool, + 'install_dir': MTypeStr, + 'install_rpath': MTypeStr, + 'pie': MTypeBool + }, + 'project': { + 'default_options': MTypeStrList, + 'meson_version': MTypeStr, + 'license': MTypeStrList, + 'subproject_dir': MTypeStr, + 'version': MTypeStr + } +} + +class Rewriter: + def __init__(self, sourcedir: str, generator: str = 'ninja', skip_errors: bool = False): + self.sourcedir = sourcedir + self.interpreter = IntrospectionInterpreter(sourcedir, '', generator, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()]) + self.skip_errors = skip_errors + self.modified_nodes = [] + self.to_remove_nodes = [] + self.to_add_nodes = [] + self.functions = { + 'default_options': self.process_default_options, + 'kwargs': self.process_kwargs, + 'target': self.process_target, + } + self.info_dump = None + + def analyze_meson(self): + mlog.log('Analyzing meson file:', mlog.bold(os.path.join(self.sourcedir, environment.build_filename))) + self.interpreter.analyze() + mlog.log(' -- Project:', mlog.bold(self.interpreter.project_data['descriptive_name'])) + mlog.log(' -- Version:', mlog.cyan(self.interpreter.project_data['version'])) + + def add_info(self, cmd_type: str, cmd_id: str, data: dict): + if self.info_dump is None: + self.info_dump = {} + if cmd_type not in self.info_dump: + self.info_dump[cmd_type] = {} + self.info_dump[cmd_type][cmd_id] = data + + def print_info(self): + if self.info_dump is None: + return + sys.stderr.write(json.dumps(self.info_dump, indent=2)) + + def on_error(self): + if self.skip_errors: + return mlog.cyan('-->'), mlog.yellow('skipping') + return mlog.cyan('-->'), mlog.red('aborting') + + def handle_error(self): + if self.skip_errors: + return None + raise MesonException('Rewriting the meson.build failed') + + def find_target(self, target: str): + def check_list(name: str) -> T.List[BaseNode]: + result = [] + for i in self.interpreter.targets: + if name in {i['name'], i['id']}: + result += [i] + return result + + targets = check_list(target) + if targets: + if len(targets) == 1: + return targets[0] + else: + mlog.error('There are multiple targets matching', mlog.bold(target)) + for i in targets: + mlog.error(' -- Target name', mlog.bold(i['name']), 'with ID', mlog.bold(i['id'])) + mlog.error('Please try again with the unique ID of the target', *self.on_error()) + self.handle_error() + return None + + # Check the assignments + tgt = None + if target in self.interpreter.assignments: + node = self.interpreter.assignments[target] + if isinstance(node, FunctionNode): + if node.func_name in {'executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries'}: + tgt = self.interpreter.assign_vals[target] + + return tgt + + def find_dependency(self, dependency: str): + def check_list(name: str): + for i in self.interpreter.dependencies: + if name == i['name']: + return i + return None + + dep = check_list(dependency) + if dep is not None: + return dep + + # Check the assignments + if dependency in self.interpreter.assignments: + node = self.interpreter.assignments[dependency] + if isinstance(node, FunctionNode): + if node.func_name == 'dependency': + name = self.interpreter.flatten_args(node.args)[0] + dep = check_list(name) + + return dep + + @RequiredKeys(rewriter_keys['default_options']) + def process_default_options(self, cmd): + # First, remove the old values + kwargs_cmd = { + 'function': 'project', + 'id': "/", + 'operation': 'remove_regex', + 'kwargs': { + 'default_options': [f'{x}=.*' for x in cmd['options'].keys()] + } + } + self.process_kwargs(kwargs_cmd) + + # Then add the new values + if cmd['operation'] != 'set': + return + + kwargs_cmd['operation'] = 'add' + kwargs_cmd['kwargs']['default_options'] = [] + + cdata = self.interpreter.coredata + options = { + **{str(k): v for k, v in cdata.options.items()}, + **{str(k): v for k, v in cdata.options.items()}, + **{str(k): v for k, v in cdata.options.items()}, + **{str(k): v for k, v in cdata.options.items()}, + **{str(k): v for k, v in cdata.options.items()}, + } + + for key, val in sorted(cmd['options'].items()): + if key not in options: + mlog.error('Unknown options', mlog.bold(key), *self.on_error()) + self.handle_error() + continue + + try: + val = options[key].validate_value(val) + except MesonException as e: + mlog.error('Unable to set', mlog.bold(key), mlog.red(str(e)), *self.on_error()) + self.handle_error() + continue + + kwargs_cmd['kwargs']['default_options'] += [f'{key}={val}'] + + self.process_kwargs(kwargs_cmd) + + @RequiredKeys(rewriter_keys['kwargs']) + def process_kwargs(self, cmd): + mlog.log('Processing function type', mlog.bold(cmd['function']), 'with id', mlog.cyan("'" + cmd['id'] + "'")) + if cmd['function'] not in rewriter_func_kwargs: + mlog.error('Unknown function type', cmd['function'], *self.on_error()) + return self.handle_error() + kwargs_def = rewriter_func_kwargs[cmd['function']] + + # Find the function node to modify + node = None + arg_node = None + if cmd['function'] == 'project': + # msys bash may expand '/' to a path. It will mangle '//' to '/' + # but in order to keep usage shell-agnostic, also allow `//` as + # the function ID such that it will work in both msys bash and + # other shells. + if {'/', '//'}.isdisjoint({cmd['id']}): + mlog.error('The ID for the function type project must be "/" or "//" not "' + cmd['id'] + '"', *self.on_error()) + return self.handle_error() + node = self.interpreter.project_node + arg_node = node.args + elif cmd['function'] == 'target': + tmp = self.find_target(cmd['id']) + if tmp: + node = tmp['node'] + arg_node = node.args + elif cmd['function'] == 'dependency': + tmp = self.find_dependency(cmd['id']) + if tmp: + node = tmp['node'] + arg_node = node.args + if not node: + mlog.error('Unable to find the function node') + assert isinstance(node, FunctionNode) + assert isinstance(arg_node, ArgumentNode) + # Transform the key nodes to plain strings + arg_node.kwargs = {k.value: v for k, v in arg_node.kwargs.items()} + + # Print kwargs info + if cmd['operation'] == 'info': + info_data = {} + for key, val in sorted(arg_node.kwargs.items()): + info_data[key] = None + if isinstance(val, ElementaryNode): + info_data[key] = val.value + elif isinstance(val, ArrayNode): + data_list = [] + for i in val.args.arguments: + element = None + if isinstance(i, ElementaryNode): + element = i.value + data_list += [element] + info_data[key] = data_list + + self.add_info('kwargs', '{}#{}'.format(cmd['function'], cmd['id']), info_data) + return # Nothing else to do + + # Modify the kwargs + num_changed = 0 + for key, val in sorted(cmd['kwargs'].items()): + if key not in kwargs_def: + mlog.error('Cannot modify unknown kwarg', mlog.bold(key), *self.on_error()) + self.handle_error() + continue + + # Remove the key from the kwargs + if cmd['operation'] == 'delete': + if key in arg_node.kwargs: + mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs') + del arg_node.kwargs[key] + num_changed += 1 + else: + mlog.log(' -- Key', mlog.bold(key), 'is already deleted') + continue + + if key not in arg_node.kwargs: + arg_node.kwargs[key] = None + modifier = kwargs_def[key](arg_node.kwargs[key]) + if not modifier.can_modify(): + mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify') + + # Apply the operation + val_str = str(val) + if cmd['operation'] == 'set': + mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str)) + modifier.set_value(val) + elif cmd['operation'] == 'add': + mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) + modifier.add_value(val) + elif cmd['operation'] == 'remove': + mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifier.remove_value(val) + elif cmd['operation'] == 'remove_regex': + mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifier.remove_regex(val) + + # Write back the result + arg_node.kwargs[key] = modifier.get_node() + num_changed += 1 + + # Convert the keys back to IdNode's + arg_node.kwargs = {IdNode(Token('', '', 0, 0, 0, None, k)): v for k, v in arg_node.kwargs.items()} + for k, v in arg_node.kwargs.items(): + k.level = v.level + if num_changed > 0 and node not in self.modified_nodes: + self.modified_nodes += [node] + + def find_assignment_node(self, node: BaseNode) -> AssignmentNode: + if node.ast_id and node.ast_id in self.interpreter.reverse_assignment: + return self.interpreter.reverse_assignment[node.ast_id] + return None + + @RequiredKeys(rewriter_keys['target']) + def process_target(self, cmd): + mlog.log('Processing target', mlog.bold(cmd['target']), 'operation', mlog.cyan(cmd['operation'])) + target = self.find_target(cmd['target']) + if target is None and cmd['operation'] != 'target_add': + mlog.error('Unknown target', mlog.bold(cmd['target']), *self.on_error()) + return self.handle_error() + + # Make source paths relative to the current subdir + def rel_source(src: str) -> str: + subdir = os.path.abspath(os.path.join(self.sourcedir, target['subdir'])) + if os.path.isabs(src): + return os.path.relpath(src, subdir) + elif not os.path.exists(src): + return src # Trust the user when the source doesn't exist + # Make sure that the path is relative to the subdir + return os.path.relpath(os.path.abspath(src), subdir) + + if target is not None: + cmd['sources'] = [rel_source(x) for x in cmd['sources']] + + # Utility function to get a list of the sources from a node + def arg_list_from_node(n): + args = [] + if isinstance(n, FunctionNode): + args = list(n.args.arguments) + if n.func_name in BUILD_TARGET_FUNCTIONS: + args.pop(0) + elif isinstance(n, ArrayNode): + args = n.args.arguments + elif isinstance(n, ArgumentNode): + args = n.arguments + return args + + to_sort_nodes = [] + + if cmd['operation'] == 'src_add': + node = None + if target['sources']: + node = target['sources'][0] + else: + node = target['node'] + assert node is not None + + # Generate the current source list + src_list = [] + for i in target['sources']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + src_list += [j.value] + + # Generate the new String nodes + to_append = [] + for i in sorted(set(cmd['sources'])): + if i in src_list: + mlog.log(' -- Source', mlog.green(i), 'is already defined for the target --> skipping') + continue + mlog.log(' -- Adding source', mlog.green(i), 'at', + mlog.yellow(f'{node.filename}:{node.lineno}')) + token = Token('string', node.filename, 0, 0, 0, None, i) + to_append += [StringNode(token)] + + # Append to the AST at the right place + arg_node = None + if isinstance(node, (FunctionNode, ArrayNode)): + arg_node = node.args + elif isinstance(node, ArgumentNode): + arg_node = node + assert arg_node is not None + arg_node.arguments += to_append + + # Mark the node as modified + if arg_node not in to_sort_nodes and not isinstance(node, FunctionNode): + to_sort_nodes += [arg_node] + if node not in self.modified_nodes: + self.modified_nodes += [node] + + elif cmd['operation'] == 'src_rm': + # Helper to find the exact string node and its parent + def find_node(src): + for i in target['sources']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + if j.value == src: + return i, j + return None, None + + for i in cmd['sources']: + # Try to find the node with the source string + root, string_node = find_node(i) + if root is None: + mlog.warning(' -- Unable to find source', mlog.green(i), 'in the target') + continue + + # Remove the found string node from the argument list + arg_node = None + if isinstance(root, (FunctionNode, ArrayNode)): + arg_node = root.args + elif isinstance(root, ArgumentNode): + arg_node = root + assert arg_node is not None + mlog.log(' -- Removing source', mlog.green(i), 'from', + mlog.yellow(f'{string_node.filename}:{string_node.lineno}')) + arg_node.arguments.remove(string_node) + + # Mark the node as modified + if arg_node not in to_sort_nodes and not isinstance(root, FunctionNode): + to_sort_nodes += [arg_node] + if root not in self.modified_nodes: + self.modified_nodes += [root] + + elif cmd['operation'] == 'extra_files_add': + tgt_function: FunctionNode = target['node'] + mark_array = True + try: + node = target['extra_files'][0] + except IndexError: + # Specifying `extra_files` with a list that flattens to empty gives an empty + # target['extra_files'] list, account for that. + try: + extra_files_key = next(k for k in tgt_function.args.kwargs.keys() if isinstance(k, IdNode) and k.value == 'extra_files') + node = tgt_function.args.kwargs[extra_files_key] + except StopIteration: + # Target has no extra_files kwarg, create one + node = ArrayNode(ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), tgt_function.end_lineno, tgt_function.end_colno, tgt_function.end_lineno, tgt_function.end_colno) + tgt_function.args.kwargs[IdNode(Token('string', tgt_function.filename, 0, 0, 0, None, 'extra_files'))] = node + mark_array = False + if tgt_function not in self.modified_nodes: + self.modified_nodes += [tgt_function] + target['extra_files'] = [node] + if isinstance(node, IdNode): + node = self.interpreter.assignments[node.value] + target['extra_files'] = [node] + if not isinstance(node, ArrayNode): + mlog.error('Target', mlog.bold(cmd['target']), 'extra_files argument must be a list', *self.on_error()) + return self.handle_error() + + # Generate the current extra files list + extra_files_list = [] + for i in target['extra_files']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + extra_files_list += [j.value] + + # Generate the new String nodes + to_append = [] + for i in sorted(set(cmd['sources'])): + if i in extra_files_list: + mlog.log(' -- Extra file', mlog.green(i), 'is already defined for the target --> skipping') + continue + mlog.log(' -- Adding extra file', mlog.green(i), 'at', + mlog.yellow(f'{node.filename}:{node.lineno}')) + token = Token('string', node.filename, 0, 0, 0, None, i) + to_append += [StringNode(token)] + + # Append to the AST at the right place + arg_node = node.args + arg_node.arguments += to_append + + # Mark the node as modified + if arg_node not in to_sort_nodes: + to_sort_nodes += [arg_node] + # If the extra_files array is newly created, don't mark it as its parent function node already is, + # otherwise this would cause double modification. + if mark_array and node not in self.modified_nodes: + self.modified_nodes += [node] + + elif cmd['operation'] == 'extra_files_rm': + # Helper to find the exact string node and its parent + def find_node(src): + for i in target['extra_files']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + if j.value == src: + return i, j + return None, None + + for i in cmd['sources']: + # Try to find the node with the source string + root, string_node = find_node(i) + if root is None: + mlog.warning(' -- Unable to find extra file', mlog.green(i), 'in the target') + continue + + # Remove the found string node from the argument list + arg_node = root.args + mlog.log(' -- Removing extra file', mlog.green(i), 'from', + mlog.yellow(f'{string_node.filename}:{string_node.lineno}')) + arg_node.arguments.remove(string_node) + + # Mark the node as modified + if arg_node not in to_sort_nodes and not isinstance(root, FunctionNode): + to_sort_nodes += [arg_node] + if root not in self.modified_nodes: + self.modified_nodes += [root] + + elif cmd['operation'] == 'target_add': + if target is not None: + mlog.error('Can not add target', mlog.bold(cmd['target']), 'because it already exists', *self.on_error()) + return self.handle_error() + + id_base = re.sub(r'[- ]', '_', cmd['target']) + target_id = id_base + '_exe' if cmd['target_type'] == 'executable' else '_lib' + source_id = id_base + '_sources' + filename = os.path.join(cmd['subdir'], environment.build_filename) + + # Build src list + src_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) + src_arr_node = ArrayNode(src_arg_node, 0, 0, 0, 0) + src_far_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) + src_fun_node = FunctionNode(filename, 0, 0, 0, 0, 'files', src_far_node) + src_ass_node = AssignmentNode(filename, 0, 0, source_id, src_fun_node) + src_arg_node.arguments = [StringNode(Token('string', filename, 0, 0, 0, None, x)) for x in cmd['sources']] + src_far_node.arguments = [src_arr_node] + + # Build target + tgt_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) + tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, cmd['target_type'], tgt_arg_node) + tgt_ass_node = AssignmentNode(filename, 0, 0, target_id, tgt_fun_node) + tgt_arg_node.arguments = [ + StringNode(Token('string', filename, 0, 0, 0, None, cmd['target'])), + IdNode(Token('string', filename, 0, 0, 0, None, source_id)) + ] + + src_ass_node.accept(AstIndentationGenerator()) + tgt_ass_node.accept(AstIndentationGenerator()) + self.to_add_nodes += [src_ass_node, tgt_ass_node] + + elif cmd['operation'] == 'target_rm': + to_remove = self.find_assignment_node(target['node']) + if to_remove is None: + to_remove = target['node'] + self.to_remove_nodes += [to_remove] + mlog.log(' -- Removing target', mlog.green(cmd['target']), 'at', + mlog.yellow(f'{to_remove.filename}:{to_remove.lineno}')) + + elif cmd['operation'] == 'info': + # T.List all sources in the target + src_list = [] + for i in target['sources']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + src_list += [j.value] + extra_files_list = [] + for i in target['extra_files']: + for j in arg_list_from_node(i): + if isinstance(j, StringNode): + extra_files_list += [j.value] + test_data = { + 'name': target['name'], + 'sources': src_list, + 'extra_files': extra_files_list + } + self.add_info('target', target['id'], test_data) + + # Sort files + for i in to_sort_nodes: + convert = lambda text: int(text) if text.isdigit() else text.lower() + alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] + path_sorter = lambda key: ([(key.count('/') <= idx, alphanum_key(x)) for idx, x in enumerate(key.split('/'))]) + + unknown = [x for x in i.arguments if not isinstance(x, StringNode)] + sources = [x for x in i.arguments if isinstance(x, StringNode)] + sources = sorted(sources, key=lambda x: path_sorter(x.value)) + i.arguments = unknown + sources + + def process(self, cmd): + if 'type' not in cmd: + raise RewriterException('Command has no key "type"') + if cmd['type'] not in self.functions: + raise RewriterException('Unknown command "{}". Supported commands are: {}' + .format(cmd['type'], list(self.functions.keys()))) + self.functions[cmd['type']](cmd) + + def apply_changes(self): + assert all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'filename') for x in self.modified_nodes) + assert all(hasattr(x, 'lineno') and hasattr(x, 'colno') and hasattr(x, 'filename') for x in self.to_remove_nodes) + assert all(isinstance(x, (ArrayNode, FunctionNode)) for x in self.modified_nodes) + assert all(isinstance(x, (ArrayNode, AssignmentNode, FunctionNode)) for x in self.to_remove_nodes) + # Sort based on line and column in reversed order + work_nodes = [{'node': x, 'action': 'modify'} for x in self.modified_nodes] + work_nodes += [{'node': x, 'action': 'rm'} for x in self.to_remove_nodes] + work_nodes = sorted(work_nodes, key=lambda x: (x['node'].lineno, x['node'].colno), reverse=True) + work_nodes += [{'node': x, 'action': 'add'} for x in self.to_add_nodes] + + # Generating the new replacement string + str_list = [] + for i in work_nodes: + new_data = '' + if i['action'] == 'modify' or i['action'] == 'add': + printer = AstPrinter() + i['node'].accept(printer) + printer.post_process() + new_data = printer.result.strip() + data = { + 'file': i['node'].filename, + 'str': new_data, + 'node': i['node'], + 'action': i['action'] + } + str_list += [data] + + # Load build files + files = {} + for i in str_list: + if i['file'] in files: + continue + fpath = os.path.realpath(os.path.join(self.sourcedir, i['file'])) + fdata = '' + # Create an empty file if it does not exist + if not os.path.exists(fpath): + with open(fpath, 'w', encoding='utf-8'): + pass + with open(fpath, encoding='utf-8') as fp: + fdata = fp.read() + + # Generate line offsets numbers + m_lines = fdata.splitlines(True) + offset = 0 + line_offsets = [] + for j in m_lines: + line_offsets += [offset] + offset += len(j) + + files[i['file']] = { + 'path': fpath, + 'raw': fdata, + 'offsets': line_offsets + } + + # Replace in source code + def remove_node(i): + offsets = files[i['file']]['offsets'] + raw = files[i['file']]['raw'] + node = i['node'] + line = node.lineno - 1 + col = node.colno + start = offsets[line] + col + end = start + if isinstance(node, (ArrayNode, FunctionNode)): + end = offsets[node.end_lineno - 1] + node.end_colno + + # Only removal is supported for assignments + elif isinstance(node, AssignmentNode) and i['action'] == 'rm': + if isinstance(node.value, (ArrayNode, FunctionNode)): + remove_node({'file': i['file'], 'str': '', 'node': node.value, 'action': 'rm'}) + raw = files[i['file']]['raw'] + while raw[end] != '=': + end += 1 + end += 1 # Handle the '=' + while raw[end] in {' ', '\n', '\t'}: + end += 1 + + files[i['file']]['raw'] = raw[:start] + i['str'] + raw[end:] + + for i in str_list: + if i['action'] in {'modify', 'rm'}: + remove_node(i) + elif i['action'] == 'add': + files[i['file']]['raw'] += i['str'] + '\n' + + # Write the files back + for key, val in files.items(): + mlog.log('Rewriting', mlog.yellow(key)) + with open(val['path'], 'w', encoding='utf-8') as fp: + fp.write(val['raw']) + +target_operation_map = { + 'add': 'src_add', + 'rm': 'src_rm', + 'add_target': 'target_add', + 'rm_target': 'target_rm', + 'add_extra_files': 'extra_files_add', + 'rm_extra_files': 'extra_files_rm', + 'info': 'info', +} + +def list_to_dict(in_list: T.List[str]) -> T.Dict[str, str]: + result = {} + it = iter(in_list) + try: + for i in it: + # calling next(it) is not a mistake, we're taking the next element from + # the iterator, avoiding the need to preprocess it into a sequence of + # key value pairs. + result[i] = next(it) + except StopIteration: + raise TypeError('in_list parameter of list_to_dict must have an even length.') + return result + +def generate_target(options) -> T.List[dict]: + return [{ + 'type': 'target', + 'target': options.target, + 'operation': target_operation_map[options.operation], + 'sources': options.sources, + 'subdir': options.subdir, + 'target_type': options.tgt_type, + }] + +def generate_kwargs(options) -> T.List[dict]: + return [{ + 'type': 'kwargs', + 'function': options.function, + 'id': options.id, + 'operation': options.operation, + 'kwargs': list_to_dict(options.kwargs), + }] + +def generate_def_opts(options) -> T.List[dict]: + return [{ + 'type': 'default_options', + 'operation': options.operation, + 'options': list_to_dict(options.options), + }] + +def generate_cmd(options) -> T.List[dict]: + if os.path.exists(options.json): + with open(options.json, encoding='utf-8') as fp: + return json.load(fp) + else: + return json.loads(options.json) + +# Map options.type to the actual type name +cli_type_map = { + 'target': generate_target, + 'tgt': generate_target, + 'kwargs': generate_kwargs, + 'default-options': generate_def_opts, + 'def': generate_def_opts, + 'command': generate_cmd, + 'cmd': generate_cmd, +} + +def run(options): + if not options.verbose: + mlog.set_quiet() + + try: + setup_vsenv() + rewriter = Rewriter(options.sourcedir, skip_errors=options.skip) + rewriter.analyze_meson() + + if options.type is None: + mlog.error('No command specified') + return 1 + + commands = cli_type_map[options.type](options) + + if not isinstance(commands, list): + raise TypeError('Command is not a list') + + for i in commands: + if not isinstance(i, object): + raise TypeError('Command is not an object') + rewriter.process(i) + + rewriter.apply_changes() + rewriter.print_info() + return 0 + except Exception as e: + raise e + finally: + mlog.set_verbose() diff --git a/devtools/meson/mesonbuild/scripts/__init__.py b/devtools/meson/mesonbuild/scripts/__init__.py new file mode 100644 index 0000000..7277771 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/__init__.py @@ -0,0 +1,21 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import PurePath + +def destdir_join(d1: str, d2: str) -> str: + if not d1: + return d2 + # c:\destdir + c:\prefix must produce c:\destdir\prefix + return str(PurePath(d1, *PurePath(d2).parts[1:])) diff --git a/devtools/meson/mesonbuild/scripts/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/scripts/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c45271e0ab1f96e3e5236a2e1ba32986b6b5a96 GIT binary patch literal 401 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/scripts/__pycache__/regen_checker.cpython-37.pyc b/devtools/meson/mesonbuild/scripts/__pycache__/regen_checker.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3a21f6e5a1f747231ba486ee391b85c0c11640b GIT binary patch literal 1873 zcmZWp&2Jk;6yKShU9Z<4anhtoKvWhI0z(s84jd35Xj23Nf@mX(7FVmy&Nx|TKg`TH zYNGXpz?pv_2lvQ@17{9M@K?;0Q*WF(@!mMDpo}$d-g|yK^WN`$-05^e2iC8D{XV(` z?oSk!%LnEIr{}0&fZ+}&xl@pc5ael2BWh1Ka_z|?W=}8j?CD1h?sAp~MKfx`H!k<` zuxLds%lmn|=tLdh8$94m9$vb<#oOPrs0*47@A4JiyJUQouYqm_G}rk0CFL9ZI>)+1W;K06XRao5uXdl1u|H!qtH}wI z0VfZfZ-a-9Zg6^maa|!g^N3S>^ANwb@p=%izkhJPckfilGku(uNBvCor;{CB?eIj4 zn|Nuvz+%wSuPZs0z&;#2rl@pbiq|XqVtt{>(=dCcaro(l>DPXD+;)n z*e?vNlwp%Z9~(BVveGo|burJRVE~3Ufzok-&=_wbvr2drVo&#St;a`a*YDg9}(y7GPErVCvkAHIH1{nPP`QAH2E>4F>RnC=6hsXKtq2ebo z@}Sp{J~f0)Rpo+OhleVa*+i@1;_38QK&*0ia%MsVW8u*@T(8!EIHXN_umcjX0M0g% zo1i^!9qfLVDgBMo@{w_Y8n$1RV!*8brej}?)2b+vlAFdd^cH-ZBG$MV>;`OGE3W}l z6HYkAdVx*2ThmSF$lG+FQm}5IQlK6j$UECV4|jF|Vj;^UH{r8H3)Ejd_8vIXgIl9e zRa2P?o2gJu4=1upg;FN8vBznW=U0Bq7r+|`L!@&Gkz+^DXOe6C0}$Zsg8q18 z#x#Rofy$qG+OIv`xS;A|9ehU~0wP~J_nogD4G8_u+6QZ2H^KV!zt*)s4|R)sI6YhE)?$8h?_dC%G^TrVck@rm_U@1Rf%#_0fqWg67J}Y#x?G)V0asvK zFV7AaxL~&~fLOj?CIviZn0TDQjE7P^{Z~{tSEMcW;N7C)(_Fld=~Ad_(;m!%#T00> LweEV*TMfuRBR1kT literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/scripts/clangformat.py b/devtools/meson/mesonbuild/scripts/clangformat.py new file mode 100644 index 0000000..c66df16 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/clangformat.py @@ -0,0 +1,65 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import argparse +import subprocess +from pathlib import Path + +from .run_tool import run_tool +from ..environment import detect_clangformat +from ..mesonlib import version_compare +from ..programs import ExternalProgram +import typing as T + +def run_clang_format(fname: Path, exelist: T.List[str], check: bool, cformat_ver: T.Optional[str]) -> subprocess.CompletedProcess: + clangformat_10 = False + if check and cformat_ver: + if version_compare(cformat_ver, '>=10'): + clangformat_10 = True + exelist = exelist + ['--dry-run', '--Werror'] + else: + original = fname.read_bytes() + before = fname.stat().st_mtime + ret = subprocess.run(exelist + ['-style=file', '-i', str(fname)]) + after = fname.stat().st_mtime + if before != after: + print('File reformatted: ', fname) + if check and not clangformat_10: + # Restore the original if only checking. + fname.write_bytes(original) + ret.returncode = 1 + return ret + +def run(args: T.List[str]) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('--check', action='store_true') + parser.add_argument('sourcedir') + parser.add_argument('builddir') + options = parser.parse_args(args) + + srcdir = Path(options.sourcedir) + builddir = Path(options.builddir) + + exelist = detect_clangformat() + if not exelist: + print('Could not execute clang-format "%s"' % ' '.join(exelist)) + return 1 + + if options.check: + cformat_ver = ExternalProgram('clang-format', exelist, silent=True).get_version() + else: + cformat_ver = None + + return run_tool('clang-format', srcdir, builddir, run_clang_format, exelist, options.check, cformat_ver) diff --git a/devtools/meson/mesonbuild/scripts/clangtidy.py b/devtools/meson/mesonbuild/scripts/clangtidy.py new file mode 100644 index 0000000..324a26e --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/clangtidy.py @@ -0,0 +1,35 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import argparse +import subprocess +from pathlib import Path + +from .run_tool import run_tool +import typing as T + +def run_clang_tidy(fname: Path, builddir: Path) -> subprocess.CompletedProcess: + return subprocess.run(['clang-tidy', '-p', str(builddir), str(fname)]) + +def run(args: T.List[str]) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('sourcedir') + parser.add_argument('builddir') + options = parser.parse_args(args) + + srcdir = Path(options.sourcedir) + builddir = Path(options.builddir) + + return run_tool('clang-tidy', srcdir, builddir, run_clang_tidy, builddir) diff --git a/devtools/meson/mesonbuild/scripts/cleantrees.py b/devtools/meson/mesonbuild/scripts/cleantrees.py new file mode 100644 index 0000000..3512f56 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/cleantrees.py @@ -0,0 +1,45 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import sys +import shutil +import pickle +import typing as T + +def rmtrees(build_dir: str, trees: T.List[str]) -> None: + for t in trees: + # Never delete trees outside of the builddir + if os.path.isabs(t): + print(f'Cannot delete dir with absolute path {t!r}') + continue + bt = os.path.join(build_dir, t) + # Skip if it doesn't exist, or if it is not a directory + if os.path.isdir(bt): + shutil.rmtree(bt, ignore_errors=True) + +def run(args: T.List[str]) -> int: + if len(args) != 1: + print('Cleaner script for Meson. Do not run on your own please.') + print('cleantrees.py ') + return 1 + with open(args[0], 'rb') as f: + data = pickle.load(f) + rmtrees(data.build_dir, data.trees) + # Never fail cleaning + return 0 + +if __name__ == '__main__': + run(sys.argv[1:]) diff --git a/devtools/meson/mesonbuild/scripts/cmake_run_ctgt.py b/devtools/meson/mesonbuild/scripts/cmake_run_ctgt.py new file mode 100644 index 0000000..755530a --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/cmake_run_ctgt.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import subprocess +import shutil +import sys +from pathlib import Path +import typing as T + +def run(argsv: T.List[str]) -> int: + commands = [[]] # type: T.List[T.List[str]] + SEPARATOR = ';;;' + + # Generate CMD parameters + parser = argparse.ArgumentParser(description='Wrapper for add_custom_command') + parser.add_argument('-d', '--directory', type=str, metavar='D', required=True, help='Working directory to cwd to') + parser.add_argument('-o', '--outputs', nargs='+', metavar='O', required=True, help='Expected output files') + parser.add_argument('-O', '--original-outputs', nargs='*', metavar='O', default=[], help='Output files expected by CMake') + parser.add_argument('commands', nargs=argparse.REMAINDER, help=f'A "{SEPARATOR}" separated list of commands') + + # Parse + args = parser.parse_args(argsv) + directory = Path(args.directory) + + dummy_target = None + if len(args.outputs) == 1 and len(args.original_outputs) == 0: + dummy_target = Path(args.outputs[0]) + elif len(args.outputs) != len(args.original_outputs): + print('Length of output list and original output list differ') + return 1 + + for i in args.commands: + if i == SEPARATOR: + commands += [[]] + continue + + i = i.replace('"', '') # Remove leftover quotes + commands[-1] += [i] + + # Execute + for i in commands: + # Skip empty lists + if not i: + continue + + cmd = [] + stdout = None + stderr = None + capture_file = '' + + for j in i: + if j in {'>', '>>'}: + stdout = subprocess.PIPE + continue + elif j in {'&>', '&>>'}: + stdout = subprocess.PIPE + stderr = subprocess.STDOUT + continue + + if stdout is not None or stderr is not None: + capture_file += j + else: + cmd += [j] + + try: + directory.mkdir(parents=True, exist_ok=True) + + res = subprocess.run(cmd, stdout=stdout, stderr=stderr, cwd=str(directory), check=True) + if capture_file: + out_file = directory / capture_file + out_file.write_bytes(res.stdout) + except subprocess.CalledProcessError: + return 1 + + if dummy_target: + dummy_target.touch() + return 0 + + # Copy outputs + zipped_outputs = zip([Path(x) for x in args.outputs], [Path(x) for x in args.original_outputs]) + for expected, generated in zipped_outputs: + do_copy = False + if not expected.exists(): + if not generated.exists(): + print('Unable to find generated file. This can cause the build to fail:') + print(generated) + do_copy = False + else: + do_copy = True + elif generated.exists(): + if generated.stat().st_mtime > expected.stat().st_mtime: + do_copy = True + + if do_copy: + if expected.exists(): + expected.unlink() + shutil.copyfile(str(generated), str(expected)) + + return 0 + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/cmd_or_ps.ps1 b/devtools/meson/mesonbuild/scripts/cmd_or_ps.ps1 new file mode 100644 index 0000000..96c32e2 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/cmd_or_ps.ps1 @@ -0,0 +1,17 @@ +# Copied from GStreamer project +# Author: Seungha Yang +# Xavier Claessens + +$i=1 +$ppid=$PID +do { + $ppid=(Get-CimInstance Win32_Process -Filter "ProcessId=$ppid").parentprocessid + $pname=(Get-Process -id $ppid).Name + if($pname -eq "cmd" -Or $pname -eq "powershell" -Or $pname -eq "pwsh") { + Write-Host ("{0}.exe" -f $pname) + Break + } + # not found yet, find grand parent + # 10 times iteration seems to be sufficient + $i++ +} while ($i -lt 10) diff --git a/devtools/meson/mesonbuild/scripts/copy.py b/devtools/meson/mesonbuild/scripts/copy.py new file mode 100644 index 0000000..dba13a5 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/copy.py @@ -0,0 +1,19 @@ +# SPDX-License-Identifer: Apache-2.0 +# Copyright © 2021 Intel Corporation +from __future__ import annotations + +"""Helper script to copy files at build time. + +This is easier than trying to detect whether to use copy, cp, or something else. +""" + +import shutil +import typing as T + + +def run(args: T.List[str]) -> int: + try: + shutil.copy2(args[0], args[1]) + except Exception: + return 1 + return 0 diff --git a/devtools/meson/mesonbuild/scripts/coverage.py b/devtools/meson/mesonbuild/scripts/coverage.py new file mode 100644 index 0000000..cb865d0 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/coverage.py @@ -0,0 +1,202 @@ +# Copyright 2017 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild import environment, mesonlib + +import argparse, re, sys, os, subprocess, pathlib, stat +import typing as T + +def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build_root: str, log_dir: str, use_llvm_cov: bool) -> int: + outfiles = [] + exitcode = 0 + + (gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() + + # load config files for tools if available in the source tree + # - lcov requires manually specifying a per-project config + # - gcovr picks up the per-project config, and also supports filtering files + # so don't exclude subprojects ourselves, if the project has a config, + # because they either don't want that, or should set it themselves + lcovrc = os.path.join(source_root, '.lcovrc') + if os.path.exists(lcovrc): + lcov_config = ['--config-file', lcovrc] + else: + lcov_config = [] + + gcovr_config = ['-e', re.escape(subproject_root)] + + # gcovr >= 4.2 requires a different syntax for out of source builds + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=4.2'): + gcovr_base_cmd = [gcovr_exe, '-r', source_root, build_root] + # it also started supporting the config file + if os.path.exists(os.path.join(source_root, 'gcovr.cfg')): + gcovr_config = [] + else: + gcovr_base_cmd = [gcovr_exe, '-r', build_root] + + if use_llvm_cov: + gcov_exe_args = ['--gcov-executable', llvm_cov_exe + ' gcov'] + else: + gcov_exe_args = [] + + if not outputs or 'xml' in outputs: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): + subprocess.check_call(gcovr_base_cmd + gcovr_config + + ['-x', + '-o', os.path.join(log_dir, 'coverage.xml') + ] + gcov_exe_args) + outfiles.append(('Xml', pathlib.Path(log_dir, 'coverage.xml'))) + elif outputs: + print('gcovr >= 3.3 needed to generate Xml coverage report') + exitcode = 1 + + if not outputs or 'sonarqube' in outputs: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=4.2'): + subprocess.check_call(gcovr_base_cmd + gcovr_config + + ['--sonarqube', + '-o', os.path.join(log_dir, 'sonarqube.xml'), + ] + gcov_exe_args) + outfiles.append(('Sonarqube', pathlib.Path(log_dir, 'sonarqube.xml'))) + elif outputs: + print('gcovr >= 4.2 needed to generate Xml coverage report') + exitcode = 1 + + if not outputs or 'text' in outputs: + if gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): + subprocess.check_call(gcovr_base_cmd + gcovr_config + + ['-o', os.path.join(log_dir, 'coverage.txt')] + + gcov_exe_args) + outfiles.append(('Text', pathlib.Path(log_dir, 'coverage.txt'))) + elif outputs: + print('gcovr >= 3.3 needed to generate text coverage report') + exitcode = 1 + + if not outputs or 'html' in outputs: + if lcov_exe and genhtml_exe: + htmloutdir = os.path.join(log_dir, 'coveragereport') + covinfo = os.path.join(log_dir, 'coverage.info') + initial_tracefile = covinfo + '.initial' + run_tracefile = covinfo + '.run' + raw_tracefile = covinfo + '.raw' + if use_llvm_cov: + # Create a shim to allow using llvm-cov as a gcov tool. + if mesonlib.is_windows(): + llvm_cov_shim_path = os.path.join(log_dir, 'llvm-cov.bat') + with open(llvm_cov_shim_path, 'w', encoding='utf-8') as llvm_cov_bat: + llvm_cov_bat.write(f'@"{llvm_cov_exe}" gcov %*') + else: + llvm_cov_shim_path = os.path.join(log_dir, 'llvm-cov.sh') + with open(llvm_cov_shim_path, 'w', encoding='utf-8') as llvm_cov_sh: + llvm_cov_sh.write(f'#!/usr/bin/env sh\nexec "{llvm_cov_exe}" gcov $@') + os.chmod(llvm_cov_shim_path, os.stat(llvm_cov_shim_path).st_mode | stat.S_IEXEC) + gcov_tool_args = ['--gcov-tool', llvm_cov_shim_path] + else: + gcov_tool_args = [] + subprocess.check_call([lcov_exe, + '--directory', build_root, + '--capture', + '--initial', + '--output-file', + initial_tracefile] + + lcov_config + + gcov_tool_args) + subprocess.check_call([lcov_exe, + '--directory', build_root, + '--capture', + '--output-file', run_tracefile, + '--no-checksum', + '--rc', 'lcov_branch_coverage=1'] + + lcov_config + + gcov_tool_args) + # Join initial and test results. + subprocess.check_call([lcov_exe, + '-a', initial_tracefile, + '-a', run_tracefile, + '--rc', 'lcov_branch_coverage=1', + '-o', raw_tracefile] + lcov_config) + # Remove all directories outside the source_root from the covinfo + subprocess.check_call([lcov_exe, + '--extract', raw_tracefile, + os.path.join(source_root, '*'), + '--rc', 'lcov_branch_coverage=1', + '--output-file', covinfo] + lcov_config) + # Remove all directories inside subproject dir + subprocess.check_call([lcov_exe, + '--remove', covinfo, + os.path.join(subproject_root, '*'), + '--rc', 'lcov_branch_coverage=1', + '--output-file', covinfo] + lcov_config) + subprocess.check_call([genhtml_exe, + '--prefix', build_root, + '--prefix', source_root, + '--output-directory', htmloutdir, + '--title', 'Code coverage', + '--legend', + '--show-details', + '--branch-coverage', + covinfo]) + outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) + elif gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): + htmloutdir = os.path.join(log_dir, 'coveragereport') + if not os.path.isdir(htmloutdir): + os.mkdir(htmloutdir) + subprocess.check_call(gcovr_base_cmd + gcovr_config + + ['--html', + '--html-details', + '--print-summary', + '-o', os.path.join(htmloutdir, 'index.html'), + ] + gcov_exe_args) + outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) + elif outputs: + print('lcov/genhtml or gcovr >= 3.3 needed to generate Html coverage report') + exitcode = 1 + + if not outputs and not outfiles: + print('Need gcovr or lcov/genhtml to generate any coverage reports') + exitcode = 1 + + if outfiles: + print('') + for (filetype, path) in outfiles: + print(filetype + ' coverage report can be found at', path.as_uri()) + + return exitcode + +def run(args: T.List[str]) -> int: + if not os.path.isfile('build.ninja'): + print('Coverage currently only works with the Ninja backend.') + return 1 + parser = argparse.ArgumentParser(description='Generate coverage reports') + parser.add_argument('--text', dest='outputs', action='append_const', + const='text', help='generate Text report') + parser.add_argument('--xml', dest='outputs', action='append_const', + const='xml', help='generate Xml report') + parser.add_argument('--sonarqube', dest='outputs', action='append_const', + const='sonarqube', help='generate Sonarqube Xml report') + parser.add_argument('--html', dest='outputs', action='append_const', + const='html', help='generate Html report') + parser.add_argument('--use_llvm_cov', action='store_true', + help='use llvm-cov') + parser.add_argument('source_root') + parser.add_argument('subproject_root') + parser.add_argument('build_root') + parser.add_argument('log_dir') + options = parser.parse_args(args) + return coverage(options.outputs, options.source_root, + options.subproject_root, options.build_root, + options.log_dir, options.use_llvm_cov) + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/delwithsuffix.py b/devtools/meson/mesonbuild/scripts/delwithsuffix.py new file mode 100644 index 0000000..f58b19c --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/delwithsuffix.py @@ -0,0 +1,37 @@ +# Copyright 2013 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os, sys +import typing as T + +def run(args: T.List[str]) -> int: + if len(args) != 2: + print('delwithsuffix.py ') + sys.exit(1) + + topdir = args[0] + suffix = args[1] + if suffix[0] != '.': + suffix = '.' + suffix + + for (root, _, files) in os.walk(topdir): + for f in files: + if f.endswith(suffix): + fullname = os.path.join(root, f) + os.unlink(fullname) + return 0 + +if __name__ == '__main__': + run(sys.argv[1:]) diff --git a/devtools/meson/mesonbuild/scripts/depfixer.py b/devtools/meson/mesonbuild/scripts/depfixer.py new file mode 100644 index 0000000..b9c58fe --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/depfixer.py @@ -0,0 +1,505 @@ +# Copyright 2013-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +import sys +import os +import stat +import struct +import shutil +import subprocess +import typing as T + +from ..mesonlib import OrderedSet, generate_list, Popen_safe + +SHT_STRTAB = 3 +DT_NEEDED = 1 +DT_RPATH = 15 +DT_RUNPATH = 29 +DT_STRTAB = 5 +DT_SONAME = 14 +DT_MIPS_RLD_MAP_REL = 1879048245 + +# Global cache for tools +INSTALL_NAME_TOOL = False + +class DataSizes: + def __init__(self, ptrsize: int, is_le: bool) -> None: + if is_le: + p = '<' + else: + p = '>' + self.Half = p + 'h' + self.HalfSize = 2 + self.Word = p + 'I' + self.WordSize = 4 + self.Sword = p + 'i' + self.SwordSize = 4 + if ptrsize == 64: + self.Addr = p + 'Q' + self.AddrSize = 8 + self.Off = p + 'Q' + self.OffSize = 8 + self.XWord = p + 'Q' + self.XWordSize = 8 + self.Sxword = p + 'q' + self.SxwordSize = 8 + else: + self.Addr = p + 'I' + self.AddrSize = 4 + self.Off = p + 'I' + self.OffSize = 4 + +class DynamicEntry(DataSizes): + def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None: + super().__init__(ptrsize, is_le) + self.ptrsize = ptrsize + if ptrsize == 64: + self.d_tag = struct.unpack(self.Sxword, ifile.read(self.SxwordSize))[0] + self.val = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] + else: + self.d_tag = struct.unpack(self.Sword, ifile.read(self.SwordSize))[0] + self.val = struct.unpack(self.Word, ifile.read(self.WordSize))[0] + + def write(self, ofile: T.BinaryIO) -> None: + if self.ptrsize == 64: + ofile.write(struct.pack(self.Sxword, self.d_tag)) + ofile.write(struct.pack(self.XWord, self.val)) + else: + ofile.write(struct.pack(self.Sword, self.d_tag)) + ofile.write(struct.pack(self.Word, self.val)) + +class SectionHeader(DataSizes): + def __init__(self, ifile: T.BinaryIO, ptrsize: int, is_le: bool) -> None: + super().__init__(ptrsize, is_le) + is_64 = ptrsize == 64 + +# Elf64_Word + self.sh_name = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Word + self.sh_type = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Xword + if is_64: + self.sh_flags = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] + else: + self.sh_flags = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Addr + self.sh_addr = struct.unpack(self.Addr, ifile.read(self.AddrSize))[0] +# Elf64_Off + self.sh_offset = struct.unpack(self.Off, ifile.read(self.OffSize))[0] +# Elf64_Xword + if is_64: + self.sh_size = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] + else: + self.sh_size = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Word + self.sh_link = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Word + self.sh_info = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Xword + if is_64: + self.sh_addralign = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] + else: + self.sh_addralign = struct.unpack(self.Word, ifile.read(self.WordSize))[0] +# Elf64_Xword + if is_64: + self.sh_entsize = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] + else: + self.sh_entsize = struct.unpack(self.Word, ifile.read(self.WordSize))[0] + +class Elf(DataSizes): + def __init__(self, bfile: str, verbose: bool = True) -> None: + self.bfile = bfile + self.verbose = verbose + self.sections = [] # type: T.List[SectionHeader] + self.dynamic = [] # type: T.List[DynamicEntry] + self.open_bf(bfile) + try: + (self.ptrsize, self.is_le) = self.detect_elf_type() + super().__init__(self.ptrsize, self.is_le) + self.parse_header() + self.parse_sections() + self.parse_dynamic() + except (struct.error, RuntimeError): + self.close_bf() + raise + + def open_bf(self, bfile: str) -> None: + self.bf = None + self.bf_perms = None + try: + self.bf = open(bfile, 'r+b') + except PermissionError as e: + self.bf_perms = stat.S_IMODE(os.lstat(bfile).st_mode) + os.chmod(bfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) + try: + self.bf = open(bfile, 'r+b') + except Exception: + os.chmod(bfile, self.bf_perms) + self.bf_perms = None + raise e + + def close_bf(self) -> None: + if self.bf is not None: + if self.bf_perms is not None: + os.fchmod(self.bf.fileno(), self.bf_perms) + self.bf_perms = None + self.bf.close() + self.bf = None + + def __enter__(self) -> 'Elf': + return self + + def __del__(self) -> None: + self.close_bf() + + def __exit__(self, exc_type: T.Any, exc_value: T.Any, traceback: T.Any) -> None: + self.close_bf() + + def detect_elf_type(self) -> T.Tuple[int, bool]: + data = self.bf.read(6) + if data[1:4] != b'ELF': + # This script gets called to non-elf targets too + # so just ignore them. + if self.verbose: + print(f'File {self.bfile!r} is not an ELF file.') + sys.exit(0) + if data[4] == 1: + ptrsize = 32 + elif data[4] == 2: + ptrsize = 64 + else: + sys.exit(f'File {self.bfile!r} has unknown ELF class.') + if data[5] == 1: + is_le = True + elif data[5] == 2: + is_le = False + else: + sys.exit(f'File {self.bfile!r} has unknown ELF endianness.') + return ptrsize, is_le + + def parse_header(self) -> None: + self.bf.seek(0) + self.e_ident = struct.unpack('16s', self.bf.read(16))[0] + self.e_type = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_machine = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_version = struct.unpack(self.Word, self.bf.read(self.WordSize))[0] + self.e_entry = struct.unpack(self.Addr, self.bf.read(self.AddrSize))[0] + self.e_phoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0] + self.e_shoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0] + self.e_flags = struct.unpack(self.Word, self.bf.read(self.WordSize))[0] + self.e_ehsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_phentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_phnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_shentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_shnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + self.e_shstrndx = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] + + def parse_sections(self) -> None: + self.bf.seek(self.e_shoff) + for _ in range(self.e_shnum): + self.sections.append(SectionHeader(self.bf, self.ptrsize, self.is_le)) + + def read_str(self) -> bytes: + arr = [] + x = self.bf.read(1) + while x != b'\0': + arr.append(x) + x = self.bf.read(1) + if x == b'': + raise RuntimeError('Tried to read past the end of the file') + return b''.join(arr) + + def find_section(self, target_name: bytes) -> T.Optional[SectionHeader]: + section_names = self.sections[self.e_shstrndx] + for i in self.sections: + self.bf.seek(section_names.sh_offset + i.sh_name) + name = self.read_str() + if name == target_name: + return i + return None + + def parse_dynamic(self) -> None: + sec = self.find_section(b'.dynamic') + if sec is None: + return + self.bf.seek(sec.sh_offset) + while True: + e = DynamicEntry(self.bf, self.ptrsize, self.is_le) + self.dynamic.append(e) + if e.d_tag == 0: + break + + @generate_list + def get_section_names(self) -> T.Generator[str, None, None]: + section_names = self.sections[self.e_shstrndx] + for i in self.sections: + self.bf.seek(section_names.sh_offset + i.sh_name) + yield self.read_str().decode() + + def get_soname(self) -> T.Optional[str]: + soname = None + strtab = None + for i in self.dynamic: + if i.d_tag == DT_SONAME: + soname = i + if i.d_tag == DT_STRTAB: + strtab = i + if soname is None or strtab is None: + return None + self.bf.seek(strtab.val + soname.val) + return self.read_str().decode() + + def get_entry_offset(self, entrynum: int) -> T.Optional[int]: + sec = self.find_section(b'.dynstr') + for i in self.dynamic: + if i.d_tag == entrynum: + res = sec.sh_offset + i.val + assert isinstance(res, int) + return res + return None + + def get_rpath(self) -> T.Optional[str]: + offset = self.get_entry_offset(DT_RPATH) + if offset is None: + return None + self.bf.seek(offset) + return self.read_str().decode() + + def get_runpath(self) -> T.Optional[str]: + offset = self.get_entry_offset(DT_RUNPATH) + if offset is None: + return None + self.bf.seek(offset) + return self.read_str().decode() + + @generate_list + def get_deps(self) -> T.Generator[str, None, None]: + sec = self.find_section(b'.dynstr') + for i in self.dynamic: + if i.d_tag == DT_NEEDED: + offset = sec.sh_offset + i.val + self.bf.seek(offset) + yield self.read_str().decode() + + def fix_deps(self, prefix: bytes) -> None: + sec = self.find_section(b'.dynstr') + deps = [] + for i in self.dynamic: + if i.d_tag == DT_NEEDED: + deps.append(i) + for i in deps: + offset = sec.sh_offset + i.val + self.bf.seek(offset) + name = self.read_str() + if name.startswith(prefix): + basename = name.rsplit(b'/', maxsplit=1)[-1] + padding = b'\0' * (len(name) - len(basename)) + newname = basename + padding + assert len(newname) == len(name) + self.bf.seek(offset) + self.bf.write(newname) + + def fix_rpath(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: bytes) -> None: + # The path to search for can be either rpath or runpath. + # Fix both of them to be sure. + self.fix_rpathtype_entry(fname, rpath_dirs_to_remove, new_rpath, DT_RPATH) + self.fix_rpathtype_entry(fname, rpath_dirs_to_remove, new_rpath, DT_RUNPATH) + + def fix_rpathtype_entry(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: bytes, entrynum: int) -> None: + rp_off = self.get_entry_offset(entrynum) + if rp_off is None: + if self.verbose: + print(f'File {fname!r} does not have an rpath. It should be a fully static executable.') + return + self.bf.seek(rp_off) + + old_rpath = self.read_str() + # Some rpath entries may come from multiple sources. + # Only add each one once. + new_rpaths = OrderedSet() # type: OrderedSet[bytes] + if new_rpath: + new_rpaths.update(new_rpath.split(b':')) + if old_rpath: + # Filter out build-only rpath entries + # added by get_link_dep_subdirs() or + # specified by user with build_rpath. + for rpath_dir in old_rpath.split(b':'): + if not (rpath_dir in rpath_dirs_to_remove or + rpath_dir == (b'X' * len(rpath_dir))): + if rpath_dir: + new_rpaths.add(rpath_dir) + + # Prepend user-specified new entries while preserving the ones that came from pkgconfig etc. + new_rpath = b':'.join(new_rpaths) + + if len(old_rpath) < len(new_rpath): + msg = "New rpath must not be longer than the old one.\n Old: {}\n New: {}".format(old_rpath.decode('utf-8'), new_rpath.decode('utf-8')) + sys.exit(msg) + # The linker does read-only string deduplication. If there is a + # string that shares a suffix with the rpath, they might get + # deduped. This means changing the rpath string might break something + # completely unrelated. This has already happened once with X.org. + # Thus we want to keep this change as small as possible to minimize + # the chance of obliterating other strings. It might still happen + # but our behavior is identical to what chrpath does and it has + # been in use for ages so based on that this should be rare. + if not new_rpath: + self.remove_rpath_entry(entrynum) + else: + self.bf.seek(rp_off) + self.bf.write(new_rpath) + self.bf.write(b'\0') + + def remove_rpath_entry(self, entrynum: int) -> None: + sec = self.find_section(b'.dynamic') + if sec is None: + return None + for (i, entry) in enumerate(self.dynamic): + if entry.d_tag == entrynum: + rpentry = self.dynamic[i] + rpentry.d_tag = 0 + self.dynamic = self.dynamic[:i] + self.dynamic[i + 1:] + [rpentry] + break + # DT_MIPS_RLD_MAP_REL is relative to the offset of the tag. Adjust it consequently. + for entry in self.dynamic[i:]: + if entry.d_tag == DT_MIPS_RLD_MAP_REL: + entry.val += 2 * (self.ptrsize // 8) + break + self.bf.seek(sec.sh_offset) + for entry in self.dynamic: + entry.write(self.bf) + return None + +def fix_elf(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Optional[bytes], verbose: bool = True) -> None: + if new_rpath is not None: + with Elf(fname, verbose) as e: + # note: e.get_rpath() and e.get_runpath() may be useful + e.fix_rpath(fname, rpath_dirs_to_remove, new_rpath) + +def get_darwin_rpaths_to_remove(fname: str) -> T.List[str]: + p, out, _ = Popen_safe(['otool', '-l', fname], stderr=subprocess.DEVNULL) + if p.returncode != 0: + raise subprocess.CalledProcessError(p.returncode, p.args, out) + result = [] + current_cmd = 'FOOBAR' + for line in out.split('\n'): + line = line.strip() + if ' ' not in line: + continue + key, value = line.strip().split(' ', 1) + if key == 'cmd': + current_cmd = value + if key == 'path' and current_cmd == 'LC_RPATH': + rp = value.split('(', 1)[0].strip() + result.append(rp) + return result + +def fix_darwin(fname: str, new_rpath: str, final_path: str, install_name_mappings: T.Dict[str, str]) -> None: + try: + rpaths = get_darwin_rpaths_to_remove(fname) + except subprocess.CalledProcessError: + # Otool failed, which happens when invoked on a + # non-executable target. Just return. + return + try: + args = [] + if rpaths: + # TODO: fix this properly, not totally clear how + # + # removing rpaths from binaries on macOS has tons of + # weird edge cases. For instance, if the user provided + # a '-Wl,-rpath' argument in LDFLAGS that happens to + # coincide with an rpath generated from a dependency, + # this would cause installation failures, as meson would + # generate install_name_tool calls with two identical + # '-delete_rpath' arguments, which install_name_tool + # fails on. Because meson itself ensures that it never + # adds duplicate rpaths, duplicate rpaths necessarily + # come from user variables. The idea of using OrderedSet + # is to remove *at most one* duplicate RPATH entry. This + # is not optimal, as it only respects the user's choice + # partially: if they provided a non-duplicate '-Wl,-rpath' + # argument, it gets removed, if they provided a duplicate + # one, it remains in the final binary. A potentially optimal + # solution would split all user '-Wl,-rpath' arguments from + # LDFLAGS, and later add them back with '-add_rpath'. + for rp in OrderedSet(rpaths): + args += ['-delete_rpath', rp] + subprocess.check_call(['install_name_tool', fname] + args, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + args = [] + if new_rpath: + args += ['-add_rpath', new_rpath] + # Rewrite -install_name @rpath/libfoo.dylib to /path/to/libfoo.dylib + if fname.endswith('dylib'): + args += ['-id', final_path] + if install_name_mappings: + for old, new in install_name_mappings.items(): + args += ['-change', old, new] + if args: + subprocess.check_call(['install_name_tool', fname] + args, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + except Exception as err: + raise SystemExit(err) + +def fix_jar(fname: str) -> None: + subprocess.check_call(['jar', 'xf', fname, 'META-INF/MANIFEST.MF']) + with open('META-INF/MANIFEST.MF', 'r+', encoding='utf-8') as f: + lines = f.readlines() + f.seek(0) + for line in lines: + if not line.startswith('Class-Path:'): + f.write(line) + f.truncate() + # jar -um doesn't allow removing existing attributes. Use -uM instead, + # which a) removes the existing manifest from the jar and b) disables + # special-casing for the manifest file, so we can re-add it as a normal + # archive member. This puts the manifest at the end of the jar rather + # than the beginning, but the spec doesn't forbid that. + subprocess.check_call(['jar', 'ufM', fname, 'META-INF/MANIFEST.MF']) + +def fix_rpath(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Union[str, bytes], final_path: str, install_name_mappings: T.Dict[str, str], verbose: bool = True) -> None: + global INSTALL_NAME_TOOL # pylint: disable=global-statement + # Static libraries, import libraries, debug information, headers, etc + # never have rpaths + # DLLs and EXE currently do not need runtime path fixing + if fname.endswith(('.a', '.lib', '.pdb', '.h', '.hpp', '.dll', '.exe')): + return + try: + if fname.endswith('.jar'): + fix_jar(fname) + return + if isinstance(new_rpath, str): + new_rpath = new_rpath.encode('utf8') + fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose) + return + except SystemExit as e: + if isinstance(e.code, int) and e.code == 0: + pass + else: + raise + # We don't look for this on import because it will do a useless PATH lookup + # on non-mac platforms. That can be expensive on some Windows machines + # (up to 30ms), which is significant with --only-changed. For details, see: + # https://github.com/mesonbuild/meson/pull/6612#discussion_r378581401 + if INSTALL_NAME_TOOL is False: + INSTALL_NAME_TOOL = bool(shutil.which('install_name_tool')) + if INSTALL_NAME_TOOL: + if isinstance(new_rpath, bytes): + new_rpath = new_rpath.decode('utf8') + fix_darwin(fname, new_rpath, final_path, install_name_mappings) diff --git a/devtools/meson/mesonbuild/scripts/depscan.py b/devtools/meson/mesonbuild/scripts/depscan.py new file mode 100644 index 0000000..3ae14c0 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/depscan.py @@ -0,0 +1,208 @@ +# Copyright 2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import json +import os +import pathlib +import pickle +import re +import sys +import typing as T + +from ..backend.ninjabackend import ninja_quote +from ..compilers.compilers import lang_suffixes + +if T.TYPE_CHECKING: + from ..backend.ninjabackend import TargetDependencyScannerInfo + +CPP_IMPORT_RE = re.compile(r'\w*import ([a-zA-Z0-9]+);') +CPP_EXPORT_RE = re.compile(r'\w*export module ([a-zA-Z0-9]+);') + +FORTRAN_INCLUDE_PAT = r"^\s*include\s*['\"](\w+\.\w+)['\"]" +FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$" +FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)" +FORTRAN_USE_PAT = r"^\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)" + +FORTRAN_MODULE_RE = re.compile(FORTRAN_MODULE_PAT, re.IGNORECASE) +FORTRAN_SUBMOD_RE = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE) +FORTRAN_USE_RE = re.compile(FORTRAN_USE_PAT, re.IGNORECASE) + +class DependencyScanner: + def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]): + with open(pickle_file, 'rb') as pf: + self.target_data: TargetDependencyScannerInfo = pickle.load(pf) + self.outfile = outfile + self.sources = sources + self.provided_by: T.Dict[str, str] = {} + self.exports: T.Dict[str, str] = {} + self.needs: T.Dict[str, T.List[str]] = {} + self.sources_with_exports: T.List[str] = [] + + def scan_file(self, fname: str) -> None: + suffix = os.path.splitext(fname)[1][1:] + if suffix != 'C': + suffix = suffix.lower() + if suffix in lang_suffixes['fortran']: + self.scan_fortran_file(fname) + elif suffix in lang_suffixes['cpp']: + self.scan_cpp_file(fname) + else: + sys.exit(f'Can not scan files with suffix .{suffix}.') + + def scan_fortran_file(self, fname: str) -> None: + fpath = pathlib.Path(fname) + modules_in_this_file = set() + for line in fpath.read_text(encoding='utf-8', errors='ignore').split('\n'): + import_match = FORTRAN_USE_RE.match(line) + export_match = FORTRAN_MODULE_RE.match(line) + submodule_export_match = FORTRAN_SUBMOD_RE.match(line) + if import_match: + needed = import_match.group(1).lower() + # In Fortran you have an using declaration also for the module + # you define in the same file. Prevent circular dependencies. + if needed not in modules_in_this_file: + if fname in self.needs: + self.needs[fname].append(needed) + else: + self.needs[fname] = [needed] + if export_match: + exported_module = export_match.group(1).lower() + assert exported_module not in modules_in_this_file + modules_in_this_file.add(exported_module) + if exported_module in self.provided_by: + raise RuntimeError(f'Multiple files provide module {exported_module}.') + self.sources_with_exports.append(fname) + self.provided_by[exported_module] = fname + self.exports[fname] = exported_module + if submodule_export_match: + # Store submodule "Foo" "Bar" as "foo:bar". + # A submodule declaration can be both an import and an export declaration: + # + # submodule (a1:a2) a3 + # - requires a1@a2.smod + # - produces a1@a3.smod + parent_module_name_full = submodule_export_match.group(1).lower() + parent_module_name = parent_module_name_full.split(':')[0] + submodule_name = submodule_export_match.group(2).lower() + concat_name = f'{parent_module_name}:{submodule_name}' + self.sources_with_exports.append(fname) + self.provided_by[concat_name] = fname + self.exports[fname] = concat_name + # Fortran requires that the immediate parent module must be built + # before the current one. Thus: + # + # submodule (parent) parent <- requires parent.mod (really parent.smod, but they are created at the same time) + # submodule (a1:a2) a3 <- requires a1@a2.smod + # + # a3 does not depend on the a1 parent module directly, only transitively. + if fname in self.needs: + self.needs[fname].append(parent_module_name_full) + else: + self.needs[fname] = [parent_module_name_full] + + def scan_cpp_file(self, fname: str) -> None: + fpath = pathlib.Path(fname) + for line in fpath.read_text(encoding='utf-8', errors='ignore').split('\n'): + import_match = CPP_IMPORT_RE.match(line) + export_match = CPP_EXPORT_RE.match(line) + if import_match: + needed = import_match.group(1) + if fname in self.needs: + self.needs[fname].append(needed) + else: + self.needs[fname] = [needed] + if export_match: + exported_module = export_match.group(1) + if exported_module in self.provided_by: + raise RuntimeError(f'Multiple files provide module {exported_module}.') + self.sources_with_exports.append(fname) + self.provided_by[exported_module] = fname + self.exports[fname] = exported_module + + def objname_for(self, src: str) -> str: + objname = self.target_data.source2object[src] + assert isinstance(objname, str) + return objname + + def module_name_for(self, src: str) -> str: + suffix = os.path.splitext(src)[1][1:].lower() + if suffix in lang_suffixes['fortran']: + exported = self.exports[src] + # Module foo:bar goes to a file name foo@bar.smod + # Module Foo goes to a file name foo.mod + namebase = exported.replace(':', '@') + if ':' in exported: + extension = 'smod' + else: + extension = 'mod' + return os.path.join(self.target_data.private_dir, f'{namebase}.{extension}') + elif suffix in lang_suffixes['cpp']: + return '{}.ifc'.format(self.exports[src]) + else: + raise RuntimeError('Unreachable code.') + + def scan(self) -> int: + for s in self.sources: + self.scan_file(s) + with open(self.outfile, 'w', encoding='utf-8') as ofile: + ofile.write('ninja_dyndep_version = 1\n') + for src in self.sources: + objfilename = self.objname_for(src) + mods_and_submods_needed = [] + module_files_generated = [] + module_files_needed = [] + if src in self.sources_with_exports: + module_files_generated.append(self.module_name_for(src)) + if src in self.needs: + for modname in self.needs[src]: + if modname not in self.provided_by: + # Nothing provides this module, we assume that it + # comes from a dependency library somewhere and is + # already built by the time this compilation starts. + pass + else: + mods_and_submods_needed.append(modname) + + for modname in mods_and_submods_needed: + provider_src = self.provided_by[modname] + provider_modfile = self.module_name_for(provider_src) + # Prune self-dependencies + if provider_src != src: + module_files_needed.append(provider_modfile) + + quoted_objfilename = ninja_quote(objfilename, True) + quoted_module_files_generated = [ninja_quote(x, True) for x in module_files_generated] + quoted_module_files_needed = [ninja_quote(x, True) for x in module_files_needed] + if quoted_module_files_generated: + mod_gen = '| ' + ' '.join(quoted_module_files_generated) + else: + mod_gen = '' + if quoted_module_files_needed: + mod_dep = '| ' + ' '.join(quoted_module_files_needed) + else: + mod_dep = '' + build_line = 'build {} {}: dyndep {}'.format(quoted_objfilename, + mod_gen, + mod_dep) + ofile.write(build_line + '\n') + return 0 + +def run(args: T.List[str]) -> int: + assert len(args) == 3, 'got wrong number of arguments!' + pickle_file, outfile, jsonfile = args + with open(jsonfile, encoding='utf-8') as f: + sources = json.load(f) + scanner = DependencyScanner(pickle_file, outfile, sources) + return scanner.scan() diff --git a/devtools/meson/mesonbuild/scripts/dirchanger.py b/devtools/meson/mesonbuild/scripts/dirchanger.py new file mode 100644 index 0000000..60c4f12 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/dirchanger.py @@ -0,0 +1,30 @@ +# Copyright 2015-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +'''CD into dir given as first argument and execute +the command given in the rest of the arguments.''' + +import os, subprocess, sys +import typing as T + +def run(args: T.List[str]) -> int: + dirname = args[0] + command = args[1:] + + os.chdir(dirname) + return subprocess.call(command) + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/env2mfile.py b/devtools/meson/mesonbuild/scripts/env2mfile.py new file mode 100644 index 0000000..df93730 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/env2mfile.py @@ -0,0 +1,402 @@ +# Copyright 2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import sys, os, subprocess, shutil +import shlex +import typing as T + +from .. import envconfig +from .. import mlog +from ..compilers import compilers +from ..compilers.detect import defaults as compiler_names + +if T.TYPE_CHECKING: + import argparse + +def has_for_build() -> bool: + for cenv in envconfig.ENV_VAR_COMPILER_MAP.values(): + if os.environ.get(cenv + '_FOR_BUILD'): + return True + return False + +def add_arguments(parser: 'argparse.ArgumentParser') -> None: + parser.add_argument('--debarch', default=None, + help='The dpkg architecture to generate.') + parser.add_argument('--gccsuffix', default="", + help='A particular gcc version suffix if necessary.') + parser.add_argument('-o', required=True, dest='outfile', + help='The output file.') + parser.add_argument('--cross', default=False, action='store_true', + help='Generate a cross compilation file.') + parser.add_argument('--native', default=False, action='store_true', + help='Generate a native compilation file.') + parser.add_argument('--system', default=None, + help='Define system for cross compilation.') + parser.add_argument('--subsystem', default=None, + help='Define subsystem for cross compilation.') + parser.add_argument('--kernel', default=None, + help='Define kernel for cross compilation.') + parser.add_argument('--cpu', default=None, + help='Define cpu for cross compilation.') + parser.add_argument('--cpu-family', default=None, + help='Define cpu family for cross compilation.') + parser.add_argument('--endian', default='little', choices=['big', 'little'], + help='Define endianness for cross compilation.') + +class MachineInfo: + def __init__(self) -> None: + self.compilers: T.Dict[str, T.List[str]] = {} + self.binaries: T.Dict[str, T.List[str]] = {} + self.properties: T.Dict[str, T.Union[str, T.List[str]]] = {} + self.compile_args: T.Dict[str, T.List[str]] = {} + self.link_args: T.Dict[str, T.List[str]] = {} + self.cmake: T.Dict[str, T.Union[str, T.List[str]]] = {} + + self.system: T.Optional[str] = None + self.subsystem: T.Optional[str] = None + self.kernel: T.Optional[str] = None + self.cpu: T.Optional[str] = None + self.cpu_family: T.Optional[str] = None + self.endian: T.Optional[str] = None + +#parser = argparse.ArgumentParser(description='''Generate cross compilation definition file for the Meson build system. +# +#If you do not specify the --arch argument, Meson assumes that running +#plain 'dpkg-architecture' will return correct information for the +#host system. +# +#This script must be run in an environment where CPPFLAGS et al are set to the +#same values used in the actual compilation. +#''' +#) + +def locate_path(program: str) -> T.List[str]: + if os.path.isabs(program): + return [program] + for d in os.get_exec_path(): + f = os.path.join(d, program) + if os.access(f, os.X_OK): + return [f] + raise ValueError("%s not found on $PATH" % program) + +def write_args_line(ofile: T.TextIO, name: str, args: T.Union[str, T.List[str]]) -> None: + if len(args) == 0: + return + if isinstance(args, str): + ostr = name + "= '" + args + "'\n" + else: + ostr = name + ' = [' + ostr += ', '.join("'" + i + "'" for i in args) + ostr += ']\n' + ofile.write(ostr) + +def get_args_from_envvars(infos: MachineInfo) -> None: + cppflags = shlex.split(os.environ.get('CPPFLAGS', '')) + cflags = shlex.split(os.environ.get('CFLAGS', '')) + cxxflags = shlex.split(os.environ.get('CXXFLAGS', '')) + objcflags = shlex.split(os.environ.get('OBJCFLAGS', '')) + objcxxflags = shlex.split(os.environ.get('OBJCXXFLAGS', '')) + ldflags = shlex.split(os.environ.get('LDFLAGS', '')) + + c_args = cppflags + cflags + cpp_args = cppflags + cxxflags + c_link_args = cflags + ldflags + cpp_link_args = cxxflags + ldflags + + objc_args = cppflags + objcflags + objcpp_args = cppflags + objcxxflags + objc_link_args = objcflags + ldflags + objcpp_link_args = objcxxflags + ldflags + + if c_args: + infos.compile_args['c'] = c_args + if c_link_args: + infos.link_args['c'] = c_link_args + if cpp_args: + infos.compile_args['cpp'] = cpp_args + if cpp_link_args: + infos.link_args['cpp'] = cpp_link_args + if objc_args: + infos.compile_args['objc'] = objc_args + if objc_link_args: + infos.link_args['objc'] = objc_link_args + if objcpp_args: + infos.compile_args['objcpp'] = objcpp_args + if objcpp_link_args: + infos.link_args['objcpp'] = objcpp_link_args + +deb_cpu_family_map = { + 'mips64el': 'mips64', + 'i686': 'x86', + 'powerpc64le': 'ppc64', +} + +deb_cpu_map = { + 'armhf': 'arm7hlf', + 'mips64el': 'mips64', + 'powerpc64le': 'ppc64', +} + +def deb_detect_cmake(infos: MachineInfo, data: T.Dict[str, str]) -> None: + system_name_map = {'linux': 'Linux', 'kfreebsd': 'kFreeBSD', 'hurd': 'GNU'} + system_processor_map = {'arm': 'armv7l', 'mips64el': 'mips64', 'powerpc64le': 'ppc64le'} + + infos.cmake["CMAKE_C_COMPILER"] = infos.compilers['c'] + try: + infos.cmake["CMAKE_CXX_COMPILER"] = infos.compilers['cpp'] + except KeyError: + pass + infos.cmake["CMAKE_SYSTEM_NAME"] = system_name_map[data['DEB_HOST_ARCH_OS']] + infos.cmake["CMAKE_SYSTEM_PROCESSOR"] = system_processor_map.get(data['DEB_HOST_GNU_CPU'], + data['DEB_HOST_GNU_CPU']) + +def deb_compiler_lookup(infos: MachineInfo, compilerstems: T.List[T.Tuple[str, str]], host_arch: str, gccsuffix: str) -> None: + for langname, stem in compilerstems: + compilername = f'{host_arch}-{stem}{gccsuffix}' + try: + p = locate_path(compilername) + infos.compilers[langname] = p + except ValueError: + pass + +def detect_cross_debianlike(options: T.Any) -> MachineInfo: + if options.debarch == 'auto': + cmd = ['dpkg-architecture'] + else: + cmd = ['dpkg-architecture', '-a' + options.debarch] + output = subprocess.check_output(cmd, universal_newlines=True, + stderr=subprocess.DEVNULL) + data = {} + for line in output.split('\n'): + line = line.strip() + if line == '': + continue + k, v = line.split('=', 1) + data[k] = v + host_arch = data['DEB_HOST_GNU_TYPE'] + host_os = data['DEB_HOST_ARCH_OS'] + host_subsystem = host_os + host_kernel = 'linux' + host_cpu_family = deb_cpu_family_map.get(data['DEB_HOST_GNU_CPU'], + data['DEB_HOST_GNU_CPU']) + host_cpu = deb_cpu_map.get(data['DEB_HOST_ARCH'], + data['DEB_HOST_ARCH']) + host_endian = data['DEB_HOST_ARCH_ENDIAN'] + + compilerstems = [('c', 'gcc'), + ('cpp', 'g++'), + ('objc', 'gobjc'), + ('objcpp', 'gobjc++')] + infos = MachineInfo() + deb_compiler_lookup(infos, compilerstems, host_arch, options.gccsuffix) + if len(infos.compilers) == 0: + print('Warning: no compilers were detected.') + infos.binaries['ar'] = locate_path("%s-ar" % host_arch) + infos.binaries['strip'] = locate_path("%s-strip" % host_arch) + infos.binaries['objcopy'] = locate_path("%s-objcopy" % host_arch) + infos.binaries['ld'] = locate_path("%s-ld" % host_arch) + try: + infos.binaries['cmake'] = locate_path("cmake") + deb_detect_cmake(infos, data) + except ValueError: + pass + try: + infos.binaries['pkg-config'] = locate_path("%s-pkg-config" % host_arch) + except ValueError: + pass # pkg-config is optional + try: + infos.binaries['cups-config'] = locate_path("cups-config") + except ValueError: + pass + infos.system = host_os + infos.subsystem = host_subsystem + infos.kernel = host_kernel + infos.cpu_family = host_cpu_family + infos.cpu = host_cpu + infos.endian = host_endian + + get_args_from_envvars(infos) + return infos + +def write_machine_file(infos: MachineInfo, ofilename: str, write_system_info: bool) -> None: + tmpfilename = ofilename + '~' + with open(tmpfilename, 'w', encoding='utf-8') as ofile: + ofile.write('[binaries]\n') + ofile.write('# Compilers\n') + for langname in sorted(infos.compilers.keys()): + compiler = infos.compilers[langname] + write_args_line(ofile, langname, compiler) + ofile.write('\n') + + ofile.write('# Other binaries\n') + for exename in sorted(infos.binaries.keys()): + exe = infos.binaries[exename] + write_args_line(ofile, exename, exe) + ofile.write('\n') + + ofile.write('[properties]\n') + all_langs = list(set(infos.compile_args.keys()).union(set(infos.link_args.keys()))) + all_langs.sort() + for lang in all_langs: + if lang in infos.compile_args: + write_args_line(ofile, lang + '_args', infos.compile_args[lang]) + if lang in infos.link_args: + write_args_line(ofile, lang + '_link_args', infos.link_args[lang]) + for k, v in infos.properties.items(): + write_args_line(ofile, k, v) + ofile.write('\n') + + if infos.cmake: + ofile.write('[cmake]\n\n') + for k, v in infos.cmake.items(): + write_args_line(ofile, k, v) + ofile.write('\n') + + if write_system_info: + ofile.write('[host_machine]\n') + ofile.write(f"cpu = '{infos.cpu}'\n") + ofile.write(f"cpu_family = '{infos.cpu_family}'\n") + ofile.write(f"endian = '{infos.endian}'\n") + ofile.write(f"system = '{infos.system}'\n") + if infos.subsystem: + ofile.write(f"subsystem = '{infos.subsystem}'\n") + if infos.kernel: + ofile.write(f"kernel = '{infos.kernel}'\n") + + os.replace(tmpfilename, ofilename) + +def detect_language_args_from_envvars(langname: str, envvar_suffix: str = '') -> T.Tuple[T.List[str], T.List[str]]: + ldflags = tuple(shlex.split(os.environ.get('LDFLAGS' + envvar_suffix, ''))) + compile_args = [] + if langname in compilers.CFLAGS_MAPPING: + compile_args = shlex.split(os.environ.get(compilers.CFLAGS_MAPPING[langname] + envvar_suffix, '')) + if langname in compilers.LANGUAGES_USING_CPPFLAGS: + cppflags = tuple(shlex.split(os.environ.get('CPPFLAGS' + envvar_suffix, ''))) + lang_compile_args = list(cppflags) + compile_args + else: + lang_compile_args = compile_args + lang_link_args = list(ldflags) + compile_args + return (lang_compile_args, lang_link_args) + +def detect_compilers_from_envvars(envvar_suffix: str = '') -> MachineInfo: + infos = MachineInfo() + for langname, envvarname in envconfig.ENV_VAR_COMPILER_MAP.items(): + compilerstr = os.environ.get(envvarname + envvar_suffix) + if not compilerstr: + continue + compiler = shlex.split(compilerstr) + infos.compilers[langname] = compiler + lang_compile_args, lang_link_args = detect_language_args_from_envvars(langname, envvar_suffix) + if lang_compile_args: + infos.compile_args[langname] = lang_compile_args + if lang_link_args: + infos.link_args[langname] = lang_link_args + return infos + +def detect_binaries_from_envvars(infos: MachineInfo, envvar_suffix: str = '') -> None: + for binname, envvar_base in envconfig.ENV_VAR_TOOL_MAP.items(): + envvar = envvar_base + envvar_suffix + binstr = os.environ.get(envvar) + if binstr: + infos.binaries[binname] = shlex.split(binstr) + +def detect_properties_from_envvars(infos: MachineInfo, envvar_suffix: str = '') -> None: + var = os.environ.get('PKG_CONFIG_LIBDIR' + envvar_suffix) + if var is not None: + infos.properties['pkg_config_libdir'] = var + var = os.environ.get('PKG_CONFIG_SYSROOT_DIR' + envvar_suffix) + if var is not None: + infos.properties['sys_root'] = var + +def detect_cross_system(infos: MachineInfo, options: T.Any) -> None: + for optname in ('system', 'subsystem', 'kernel', 'cpu', 'cpu_family', 'endian'): + v = getattr(options, optname) + if not v: + mlog.error(f'Cross property "{optname}" missing, set it with --{optname.replace("_", "-")}.') + sys.exit(1) + setattr(infos, optname, v) + +def detect_cross_env(options: T.Any) -> MachineInfo: + if options.debarch: + print('Detecting cross environment via dpkg-reconfigure.') + infos = detect_cross_debianlike(options) + else: + print('Detecting cross environment via environment variables.') + infos = detect_compilers_from_envvars() + detect_cross_system(infos, options) + detect_binaries_from_envvars(infos) + detect_properties_from_envvars(infos) + return infos + +def add_compiler_if_missing(infos: MachineInfo, langname: str, exe_names: T.List[str]) -> None: + if langname in infos.compilers: + return + for exe_name in exe_names: + lookup = shutil.which(exe_name) + if not lookup: + continue + compflags, linkflags = detect_language_args_from_envvars(langname) + infos.compilers[langname] = [lookup] + if compflags: + infos.compile_args[langname] = compflags + if linkflags: + infos.link_args[langname] = linkflags + return + +def detect_missing_native_compilers(infos: MachineInfo) -> None: + # T.Any per-platform special detection should go here. + for langname, exes in compiler_names.items(): + if langname not in envconfig.ENV_VAR_COMPILER_MAP: + continue + add_compiler_if_missing(infos, langname, exes) + +def detect_missing_native_binaries(infos: MachineInfo) -> None: + # T.Any per-platform special detection should go here. + for toolname in sorted(envconfig.ENV_VAR_TOOL_MAP.keys()): + if toolname in infos.binaries: + continue + exe = shutil.which(toolname) + if exe: + infos.binaries[toolname] = [exe] + +def detect_native_env(options: T.Any) -> MachineInfo: + use_for_build = has_for_build() + if use_for_build: + mlog.log('Using FOR_BUILD envvars for detection') + esuffix = '_FOR_BUILD' + else: + mlog.log('Using regular envvars for detection.') + esuffix = '' + infos = detect_compilers_from_envvars(esuffix) + detect_missing_native_compilers(infos) + detect_binaries_from_envvars(infos, esuffix) + detect_missing_native_binaries(infos) + detect_properties_from_envvars(infos, esuffix) + return infos + +def run(options: T.Any) -> None: + if options.cross and options.native: + sys.exit('You can only specify either --cross or --native, not both.') + if not options.cross and not options.native: + sys.exit('You must specify --cross or --native.') + mlog.notice('This functionality is experimental and subject to change.') + detect_cross = options.cross + if detect_cross: + infos = detect_cross_env(options) + write_system_info = True + else: + infos = detect_native_env(options) + write_system_info = False + write_machine_file(infos, options.outfile, write_system_info) diff --git a/devtools/meson/mesonbuild/scripts/externalproject.py b/devtools/meson/mesonbuild/scripts/externalproject.py new file mode 100644 index 0000000..17c2251 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/externalproject.py @@ -0,0 +1,116 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import argparse +import multiprocessing +import subprocess +from pathlib import Path +import typing as T + +from ..mesonlib import Popen_safe, split_args + +class ExternalProject: + def __init__(self, options: argparse.Namespace): + self.name = options.name + self.src_dir = options.srcdir + self.build_dir = options.builddir + self.install_dir = options.installdir + self.log_dir = options.logdir + self.verbose = options.verbose + self.stampfile = options.stampfile + self.depfile = options.depfile + self.make = split_args(options.make) + + def write_depfile(self) -> None: + with open(self.depfile, 'w', encoding='utf-8') as f: + f.write(f'{self.stampfile}: \\\n') + for dirpath, dirnames, filenames in os.walk(self.src_dir): + dirnames[:] = [d for d in dirnames if not d.startswith('.')] + for fname in filenames: + if fname.startswith('.'): + continue + path = Path(dirpath, fname) + f.write(' {} \\\n'.format(path.as_posix().replace(' ', '\\ '))) + + def write_stampfile(self) -> None: + with open(self.stampfile, 'w', encoding='utf-8'): + pass + + def supports_jobs_flag(self) -> bool: + p, o, e = Popen_safe(self.make + ['--version']) + if p.returncode == 0 and ('GNU Make' in o or 'waf' in o): + return True + return False + + def build(self) -> int: + make_cmd = self.make.copy() + if self.supports_jobs_flag(): + make_cmd.append(f'-j{multiprocessing.cpu_count()}') + rc = self._run('build', make_cmd) + if rc != 0: + return rc + + install_cmd = self.make.copy() + install_env = {} + install_env['DESTDIR'] = self.install_dir + install_cmd.append('install') + rc = self._run('install', install_cmd, install_env) + if rc != 0: + return rc + + self.write_depfile() + self.write_stampfile() + + return 0 + + def _run(self, step: str, command: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> int: + m = 'Running command ' + str(command) + ' in directory ' + str(self.build_dir) + '\n' + log_filename = Path(self.log_dir, f'{self.name}-{step}.log') + output = None + if not self.verbose: + output = open(log_filename, 'w', encoding='utf-8') + output.write(m + '\n') + output.flush() + else: + print(m) + run_env = os.environ.copy() + if env: + run_env.update(env) + p, o, e = Popen_safe(command, stderr=subprocess.STDOUT, stdout=output, + cwd=self.build_dir, + env=run_env) + if p.returncode != 0: + m = f'{step} step returned error code {p.returncode}.' + if not self.verbose: + m += '\nSee logs: ' + str(log_filename) + print(m) + return p.returncode + +def run(args: T.List[str]) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('--name') + parser.add_argument('--srcdir') + parser.add_argument('--builddir') + parser.add_argument('--installdir') + parser.add_argument('--logdir') + parser.add_argument('--make') + parser.add_argument('--verbose', action='store_true') + parser.add_argument('stampfile') + parser.add_argument('depfile') + + options = parser.parse_args(args) + ep = ExternalProject(options) + return ep.build() diff --git a/devtools/meson/mesonbuild/scripts/gettext.py b/devtools/meson/mesonbuild/scripts/gettext.py new file mode 100644 index 0000000..4a6bb9c --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/gettext.py @@ -0,0 +1,96 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import argparse +import subprocess +import typing as T + +parser = argparse.ArgumentParser() +parser.add_argument('command') +parser.add_argument('--pkgname', default='') +parser.add_argument('--datadirs', default='') +parser.add_argument('--langs', default='') +parser.add_argument('--localedir', default='') +parser.add_argument('--source-root', default='') +parser.add_argument('--subdir', default='') +parser.add_argument('--xgettext', default='xgettext') +parser.add_argument('--msgmerge', default='msgmerge') +parser.add_argument('--msginit', default='msginit') +parser.add_argument('--extra-args', default='') + +def read_linguas(src_sub: str) -> T.List[str]: + # Syntax of this file is documented here: + # https://www.gnu.org/software/gettext/manual/html_node/po_002fLINGUAS.html + linguas = os.path.join(src_sub, 'LINGUAS') + try: + langs = [] + with open(linguas, encoding='utf-8') as f: + for line in f: + line = line.strip() + if line and not line.startswith('#'): + langs += line.split() + return langs + except (FileNotFoundError, PermissionError): + print(f'Could not find file LINGUAS in {src_sub}') + return [] + +def run_potgen(src_sub: str, xgettext: str, pkgname: str, datadirs: str, args: T.List[str], source_root: str) -> int: + listfile = os.path.join(src_sub, 'POTFILES.in') + if not os.path.exists(listfile): + listfile = os.path.join(src_sub, 'POTFILES') + if not os.path.exists(listfile): + print('Could not find file POTFILES in %s' % src_sub) + return 1 + + child_env = os.environ.copy() + if datadirs: + child_env['GETTEXTDATADIRS'] = datadirs + + ofile = os.path.join(src_sub, pkgname + '.pot') + return subprocess.call([xgettext, '--package-name=' + pkgname, '-p', src_sub, '-f', listfile, + '-D', source_root, '-k_', '-o', ofile] + args, + env=child_env) + +def update_po(src_sub: str, msgmerge: str, msginit: str, pkgname: str, langs: T.List[str]) -> int: + potfile = os.path.join(src_sub, pkgname + '.pot') + for l in langs: + pofile = os.path.join(src_sub, l + '.po') + if os.path.exists(pofile): + subprocess.check_call([msgmerge, '-q', '-o', pofile, pofile, potfile]) + else: + subprocess.check_call([msginit, '--input', potfile, '--output-file', pofile, '--locale', l, '--no-translator']) + return 0 + +def run(args: T.List[str]) -> int: + options = parser.parse_args(args) + subcmd = options.command + langs = options.langs.split('@@') if options.langs else None + extra_args = options.extra_args.split('@@') if options.extra_args else [] + subdir = options.subdir + src_sub = os.path.join(options.source_root, subdir) + + if not langs: + langs = read_linguas(src_sub) + + if subcmd == 'pot': + return run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args, options.source_root) + elif subcmd == 'update_po': + if run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args, options.source_root) != 0: + return 1 + return update_po(src_sub, options.msgmerge, options.msginit, options.pkgname, langs) + else: + print('Unknown subcommand.') + return 1 diff --git a/devtools/meson/mesonbuild/scripts/gtkdochelper.py b/devtools/meson/mesonbuild/scripts/gtkdochelper.py new file mode 100644 index 0000000..ded952d --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/gtkdochelper.py @@ -0,0 +1,296 @@ +# Copyright 2015-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import sys, os +import subprocess +import shutil +import argparse +from ..mesonlib import MesonException, Popen_safe, is_windows, is_cygwin, split_args +from . import destdir_join +import typing as T + +parser = argparse.ArgumentParser() + +parser.add_argument('--sourcedir', dest='sourcedir') +parser.add_argument('--builddir', dest='builddir') +parser.add_argument('--subdir', dest='subdir') +parser.add_argument('--headerdirs', dest='headerdirs') +parser.add_argument('--mainfile', dest='mainfile') +parser.add_argument('--modulename', dest='modulename') +parser.add_argument('--moduleversion', dest='moduleversion') +parser.add_argument('--htmlargs', dest='htmlargs', default='') +parser.add_argument('--scanargs', dest='scanargs', default='') +parser.add_argument('--scanobjsargs', dest='scanobjsargs', default='') +parser.add_argument('--gobjects-types-file', dest='gobject_typesfile', default='') +parser.add_argument('--fixxrefargs', dest='fixxrefargs', default='') +parser.add_argument('--mkdbargs', dest='mkdbargs', default='') +parser.add_argument('--ld', dest='ld', default='') +parser.add_argument('--cc', dest='cc', default='') +parser.add_argument('--ldflags', dest='ldflags', default='') +parser.add_argument('--cflags', dest='cflags', default='') +parser.add_argument('--content-files', dest='content_files', default='') +parser.add_argument('--expand-content-files', dest='expand_content_files', default='') +parser.add_argument('--html-assets', dest='html_assets', default='') +parser.add_argument('--ignore-headers', dest='ignore_headers', default='') +parser.add_argument('--namespace', dest='namespace', default='') +parser.add_argument('--mode', dest='mode', default='') +parser.add_argument('--installdir', dest='install_dir') +parser.add_argument('--run', dest='run', default='') +for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']: + program_name = 'gtkdoc-' + tool + parser.add_argument('--' + program_name, dest=program_name.replace('-', '_')) + +def gtkdoc_run_check(cmd: T.List[str], cwd: str, library_paths: T.Optional[T.List[str]] = None) -> None: + if library_paths is None: + library_paths = [] + + env = dict(os.environ) + if is_windows() or is_cygwin(): + if 'PATH' in env: + library_paths.extend(env['PATH'].split(os.pathsep)) + env['PATH'] = os.pathsep.join(library_paths) + else: + if 'LD_LIBRARY_PATH' in env: + library_paths.extend(env['LD_LIBRARY_PATH'].split(os.pathsep)) + env['LD_LIBRARY_PATH'] = os.pathsep.join(library_paths) + + if is_windows(): + cmd.insert(0, sys.executable) + + # Put stderr into stdout since we want to print it out anyway. + # This preserves the order of messages. + p, out = Popen_safe(cmd, cwd=cwd, env=env, stderr=subprocess.STDOUT)[0:2] + if p.returncode != 0: + err_msg = [f"{cmd!r} failed with status {p.returncode:d}"] + if out: + err_msg.append(out) + raise MesonException('\n'.join(err_msg)) + elif out: + # Unfortunately Windows cmd.exe consoles may be using a codepage + # that might choke print() with a UnicodeEncodeError, so let's + # ignore such errors for now, as a compromise as we are outputting + # console output here... + try: + print(out) + except UnicodeEncodeError: + pass + +def build_gtkdoc(source_root: str, build_root: str, doc_subdir: str, src_subdirs: T.List[str], + main_file: str, module: str, module_version: str, + html_args: T.List[str], scan_args: T.List[str], fixxref_args: T.List[str], mkdb_args: T.List[str], + gobject_typesfile: str, scanobjs_args: T.List[str], run: str, ld: str, cc: str, ldflags: str, cflags: str, + html_assets: T.List[str], content_files: T.List[str], ignore_headers: T.List[str], namespace: str, + expand_content_files: T.List[str], mode: str, options: argparse.Namespace) -> None: + print("Building documentation for %s" % module) + + src_dir_args = [] + for src_dir in src_subdirs: + if not os.path.isabs(src_dir): + dirs = [os.path.join(source_root, src_dir), + os.path.join(build_root, src_dir)] + else: + dirs = [src_dir] + src_dir_args += ['--source-dir=' + d for d in dirs] + + doc_src = os.path.join(source_root, doc_subdir) + abs_out = os.path.join(build_root, doc_subdir) + htmldir = os.path.join(abs_out, 'html') + + content_files += [main_file] + sections = os.path.join(doc_src, module + "-sections.txt") + if os.path.exists(sections): + content_files.append(sections) + + overrides = os.path.join(doc_src, module + "-overrides.txt") + if os.path.exists(overrides): + content_files.append(overrides) + + # Copy files to build directory + for f in content_files: + # FIXME: Use mesonlib.File objects so we don't need to do this + if not os.path.isabs(f): + f = os.path.join(doc_src, f) + elif os.path.commonpath([f, build_root]) == build_root: + continue + shutil.copyfile(f, os.path.join(abs_out, os.path.basename(f))) + + shutil.rmtree(htmldir, ignore_errors=True) + try: + os.mkdir(htmldir) + except Exception: + pass + + for f in html_assets: + f_abs = os.path.join(doc_src, f) + shutil.copyfile(f_abs, os.path.join(htmldir, os.path.basename(f_abs))) + + scan_cmd = [options.gtkdoc_scan, '--module=' + module] + src_dir_args + if ignore_headers: + scan_cmd.append('--ignore-headers=' + ' '.join(ignore_headers)) + # Add user-specified arguments + scan_cmd += scan_args + gtkdoc_run_check(scan_cmd, abs_out) + + # Use the generated types file when available, otherwise gobject_typesfile + # would often be a path to source dir instead of build dir. + if '--rebuild-types' in scan_args: + gobject_typesfile = os.path.join(abs_out, module + '.types') + + if gobject_typesfile: + scanobjs_cmd = [options.gtkdoc_scangobj] + scanobjs_args + scanobjs_cmd += ['--types=' + gobject_typesfile, + '--module=' + module, + '--run=' + run, + '--cflags=' + cflags, + '--ldflags=' + ldflags, + '--cc=' + cc, + '--ld=' + ld, + '--output-dir=' + abs_out] + + library_paths = [] + for ldflag in split_args(ldflags): + if ldflag.startswith('-Wl,-rpath,'): + library_paths.append(ldflag[11:]) + + gtkdoc_run_check(scanobjs_cmd, build_root, library_paths) + + # Make docbook files + if mode == 'auto': + # Guessing is probably a poor idea but these keeps compat + # with previous behavior + if main_file.endswith('sgml'): + modeflag = '--sgml-mode' + else: + modeflag = '--xml-mode' + elif mode == 'xml': + modeflag = '--xml-mode' + elif mode == 'sgml': + modeflag = '--sgml-mode' + else: # none + modeflag = None + + mkdb_cmd = [options.gtkdoc_mkdb, + '--module=' + module, + '--output-format=xml', + '--expand-content-files=' + ' '.join(expand_content_files), + ] + src_dir_args + if namespace: + mkdb_cmd.append('--name-space=' + namespace) + if modeflag: + mkdb_cmd.append(modeflag) + if main_file: + # Yes, this is the flag even if the file is in xml. + mkdb_cmd.append('--main-sgml-file=' + main_file) + # Add user-specified arguments + mkdb_cmd += mkdb_args + gtkdoc_run_check(mkdb_cmd, abs_out) + + # Make HTML documentation + mkhtml_cmd = [options.gtkdoc_mkhtml, + '--path=' + os.pathsep.join((doc_src, abs_out)), + module, + ] + html_args + if main_file: + mkhtml_cmd.append('../' + main_file) + else: + mkhtml_cmd.append('%s-docs.xml' % module) + # html gen must be run in the HTML dir + gtkdoc_run_check(mkhtml_cmd, htmldir) + + # Fix cross-references in HTML files + fixref_cmd = [options.gtkdoc_fixxref, + '--module=' + module, + '--module-dir=html'] + fixxref_args + gtkdoc_run_check(fixref_cmd, abs_out) + + if module_version: + shutil.move(os.path.join(htmldir, f'{module}.devhelp2'), + os.path.join(htmldir, f'{module}-{module_version}.devhelp2')) + +def install_gtkdoc(build_root: str, doc_subdir: str, install_prefix: str, datadir: str, module: str) -> None: + source = os.path.join(build_root, doc_subdir, 'html') + final_destination = os.path.join(install_prefix, datadir, module) + shutil.rmtree(final_destination, ignore_errors=True) + shutil.copytree(source, final_destination) + +def run(args: T.List[str]) -> int: + options = parser.parse_args(args) + if options.htmlargs: + htmlargs = options.htmlargs.split('@@') + else: + htmlargs = [] + if options.scanargs: + scanargs = options.scanargs.split('@@') + else: + scanargs = [] + if options.scanobjsargs: + scanobjsargs = options.scanobjsargs.split('@@') + else: + scanobjsargs = [] + if options.fixxrefargs: + fixxrefargs = options.fixxrefargs.split('@@') + else: + fixxrefargs = [] + if options.mkdbargs: + mkdbargs = options.mkdbargs.split('@@') + else: + mkdbargs = [] + build_gtkdoc( + options.sourcedir, + options.builddir, + options.subdir, + options.headerdirs.split('@@'), + options.mainfile, + options.modulename, + options.moduleversion, + htmlargs, + scanargs, + fixxrefargs, + mkdbargs, + options.gobject_typesfile, + scanobjsargs, + options.run, + options.ld, + options.cc, + options.ldflags, + options.cflags, + options.html_assets.split('@@') if options.html_assets else [], + options.content_files.split('@@') if options.content_files else [], + options.ignore_headers.split('@@') if options.ignore_headers else [], + options.namespace, + options.expand_content_files.split('@@') if options.expand_content_files else [], + options.mode, + options) + + if 'MESON_INSTALL_PREFIX' in os.environ: + destdir = os.environ.get('DESTDIR', '') + install_prefix = destdir_join(destdir, os.environ['MESON_INSTALL_PREFIX']) + if options.install_dir: + install_dir = options.install_dir + else: + install_dir = options.modulename + if options.moduleversion: + install_dir += '-' + options.moduleversion + if os.path.isabs(install_dir): + install_dir = destdir_join(destdir, install_dir) + install_gtkdoc(options.builddir, + options.subdir, + install_prefix, + 'share/gtk-doc/html', + install_dir) + return 0 + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/hotdochelper.py b/devtools/meson/mesonbuild/scripts/hotdochelper.py new file mode 100644 index 0000000..80365a0 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/hotdochelper.py @@ -0,0 +1,40 @@ +from __future__ import annotations + +import os +import shutil +import subprocess + +from . import destdir_join + +import argparse +import typing as T + +parser = argparse.ArgumentParser() +parser.add_argument('--install') +parser.add_argument('--extra-extension-path', action="append", default=[]) +parser.add_argument('--name') +parser.add_argument('--builddir') +parser.add_argument('--project-version') +parser.add_argument('--docdir') + + +def run(argv: T.List[str]) -> int: + options, args = parser.parse_known_args(argv) + subenv = os.environ.copy() + + val = subenv.get('PYTHONPATH') + paths = [val] if val else [] + subenv['PYTHONPATH'] = os.pathsep.join(paths + options.extra_extension_path) + + res = subprocess.call(args, cwd=options.builddir, env=subenv) + if res != 0: + return res + + if options.install: + source_dir = os.path.join(options.builddir, options.install) + destdir = os.environ.get('DESTDIR', '') + installdir = destdir_join(destdir, options.docdir) + + shutil.rmtree(installdir, ignore_errors=True) + shutil.copytree(source_dir, installdir) + return 0 diff --git a/devtools/meson/mesonbuild/scripts/itstool.py b/devtools/meson/mesonbuild/scripts/itstool.py new file mode 100644 index 0000000..0bfcaf9 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/itstool.py @@ -0,0 +1,86 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import argparse +import subprocess +import tempfile +import shutil +import typing as T + +parser = argparse.ArgumentParser() +parser.add_argument('command') +parser.add_argument('--build-dir', default='') +parser.add_argument('-i', '--input', default='') +parser.add_argument('-o', '--output', default='') +parser.add_argument('--itstool', default='itstool') +parser.add_argument('--its', action='append', default=[]) +parser.add_argument('mo_files', nargs='+') + + +def run_join(build_dir: str, itstool: str, its_files: T.List[str], mo_files: T.List[str], + in_fname: str, out_fname: str) -> int: + if not mo_files: + print('No mo files specified to use for translation.') + return 1 + + with tempfile.TemporaryDirectory(prefix=os.path.basename(in_fname), dir=build_dir) as tmp_dir: + # copy mo files to have the right names so itstool can infer their locale + locale_mo_files = [] + for mo_file in mo_files: + if not os.path.exists(mo_file): + print(f'Could not find mo file {mo_file}') + return 1 + if not mo_file.endswith('.mo'): + print(f'File is not a mo file: {mo_file}') + return 1 + # determine locale of this mo file + parts = mo_file.partition('LC_MESSAGES') + if parts[0].endswith((os.sep, '/')): + locale = os.path.basename(parts[0][:-1]) + else: + locale = os.path.basename(parts[0]) + tmp_mo_fname = os.path.join(tmp_dir, locale + '.mo') + shutil.copy(mo_file, tmp_mo_fname) + locale_mo_files.append(tmp_mo_fname) + + cmd = [itstool] + if its_files: + for fname in its_files: + cmd.extend(['-i', fname]) + cmd.extend(['-j', in_fname, + '-o', out_fname]) + cmd.extend(locale_mo_files) + + return subprocess.call(cmd) + + +def run(args: T.List[str]) -> int: + options = parser.parse_args(args) + command = options.command + build_dir = os.environ.get('MESON_BUILD_ROOT', os.getcwd()) + if options.build_dir: + build_dir = options.build_dir + + if command == 'join': + return run_join(build_dir, + options.itstool, + options.its, + options.mo_files, + options.input, + options.output) + else: + print('Unknown subcommand.') + return 1 diff --git a/devtools/meson/mesonbuild/scripts/meson_exe.py b/devtools/meson/mesonbuild/scripts/meson_exe.py new file mode 100644 index 0000000..da89dd4 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/meson_exe.py @@ -0,0 +1,125 @@ +# Copyright 2013-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import sys +import argparse +import pickle +import subprocess +import typing as T +import locale + +from ..utils.core import ExecutableSerialisation + +def buildparser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description='Custom executable wrapper for Meson. Do not run on your own, mmm\'kay?') + parser.add_argument('--unpickle') + parser.add_argument('--capture') + parser.add_argument('--feed') + return parser + +def run_exe(exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str]] = None) -> int: + if exe.exe_wrapper: + if not exe.exe_wrapper.found(): + raise AssertionError('BUG: Can\'t run cross-compiled exe {!r} with not-found ' + 'wrapper {!r}'.format(exe.cmd_args[0], exe.exe_wrapper.get_path())) + cmd_args = exe.exe_wrapper.get_command() + exe.cmd_args + else: + cmd_args = exe.cmd_args + child_env = os.environ.copy() + if extra_env: + child_env.update(extra_env) + if exe.env: + child_env = exe.env.get_env(child_env) + if exe.extra_paths: + child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) + + child_env['PATH']) + if exe.exe_wrapper and any('wine' in i for i in exe.exe_wrapper.get_command()): + from .. import mesonlib + child_env['WINEPATH'] = mesonlib.get_wine_shortpath( + exe.exe_wrapper.get_command(), + ['Z:' + p for p in exe.extra_paths] + child_env.get('WINEPATH', '').split(';'), + exe.workdir + ) + + stdin = None + if exe.feed: + stdin = open(exe.feed, 'rb') + + pipe = subprocess.PIPE + if exe.verbose: + assert not exe.capture, 'Cannot capture and print to console at the same time' + pipe = None + + p = subprocess.Popen(cmd_args, env=child_env, cwd=exe.workdir, + close_fds=False, stdin=stdin, stdout=pipe, stderr=pipe) + stdout, stderr = p.communicate() + + if stdin is not None: + stdin.close() + + if p.returncode == 0xc0000135: + # STATUS_DLL_NOT_FOUND on Windows indicating a common problem that is otherwise hard to diagnose + strerror = 'Failed to run due to missing DLLs, with path: ' + child_env['PATH'] + raise FileNotFoundError(p.returncode, strerror, cmd_args) + + if p.returncode != 0: + if exe.pickled: + print(f'while executing {cmd_args!r}') + if exe.verbose: + return p.returncode + encoding = locale.getpreferredencoding() + if not exe.capture: + print('--- stdout ---') + print(stdout.decode(encoding=encoding, errors='replace')) + print('--- stderr ---') + print(stderr.decode(encoding=encoding, errors='replace')) + return p.returncode + + if exe.capture: + skip_write = False + try: + with open(exe.capture, 'rb') as cur: + skip_write = cur.read() == stdout + except OSError: + pass + if not skip_write: + with open(exe.capture, 'wb') as output: + output.write(stdout) + + return 0 + +def run(args: T.List[str]) -> int: + parser = buildparser() + options, cmd_args = parser.parse_known_args(args) + # argparse supports double dash to separate options and positional arguments, + # but the user has to remove it manually. + if cmd_args and cmd_args[0] == '--': + cmd_args = cmd_args[1:] + if not options.unpickle and not cmd_args: + parser.error('either --unpickle or executable and arguments are required') + if options.unpickle: + if cmd_args or options.capture or options.feed: + parser.error('no other arguments can be used with --unpickle') + with open(options.unpickle, 'rb') as f: + exe = pickle.load(f) + exe.pickled = True + else: + exe = ExecutableSerialisation(cmd_args, capture=options.capture, feed=options.feed) + + return run_exe(exe) + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/msgfmthelper.py b/devtools/meson/mesonbuild/scripts/msgfmthelper.py new file mode 100644 index 0000000..28bcc8b --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/msgfmthelper.py @@ -0,0 +1,39 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import argparse +import subprocess +import os +import typing as T + +parser = argparse.ArgumentParser() +parser.add_argument('input') +parser.add_argument('output') +parser.add_argument('type') +parser.add_argument('podir') +parser.add_argument('--msgfmt', default='msgfmt') +parser.add_argument('--datadirs', default='') +parser.add_argument('args', default=[], metavar='extra msgfmt argument', nargs='*') + + +def run(args: T.List[str]) -> int: + options = parser.parse_args(args) + env = None + if options.datadirs: + env = os.environ.copy() + env.update({'GETTEXTDATADIRS': options.datadirs}) + return subprocess.call([options.msgfmt, '--' + options.type, '-d', options.podir, + '--template', options.input, '-o', options.output] + options.args, + env=env) diff --git a/devtools/meson/mesonbuild/scripts/pycompile.py b/devtools/meson/mesonbuild/scripts/pycompile.py new file mode 100644 index 0000000..b236a1c --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/pycompile.py @@ -0,0 +1,65 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ignore all lints for this file, since it is run by python2 as well + +# type: ignore +# pylint: disable=deprecated-module + +import json, os, subprocess, sys +from compileall import compile_file + +quiet = int(os.environ.get('MESON_INSTALL_QUIET', 0)) + +def compileall(files): + for f in files: + # f is prefixed by {py_xxxxlib}, both variants are 12 chars + # the key is the middle 10 chars of the prefix + key = f[1:11].upper() + f = f[12:] + + ddir = None + fullpath = os.environ['MESON_INSTALL_DESTDIR_'+key] + f + f = os.environ['MESON_INSTALL_'+key] + f + + if fullpath != f: + ddir = os.path.dirname(f) + + if os.path.isdir(fullpath): + for root, _, files in os.walk(fullpath): + if ddir is not None: + ddir = root.replace(fullpath, f, 1) + for dirf in files: + if dirf.endswith('.py'): + fullpath = os.path.join(root, dirf) + compile_file(fullpath, ddir, force=True, quiet=quiet) + else: + compile_file(fullpath, ddir, force=True, quiet=quiet) + +def run(manifest): + data_file = os.path.join(os.path.dirname(__file__), manifest) + with open(data_file, 'rb') as f: + dat = json.load(f) + compileall(dat) + +if __name__ == '__main__': + manifest = sys.argv[1] + run(manifest) + if len(sys.argv) > 2: + optlevel = int(sys.argv[2]) + # python2 only needs one or the other + if optlevel == 1 or (sys.version_info >= (3,) and optlevel > 0): + subprocess.check_call([sys.executable, '-O'] + sys.argv[:2]) + if optlevel == 2: + subprocess.check_call([sys.executable, '-OO'] + sys.argv[:2]) diff --git a/devtools/meson/mesonbuild/scripts/python_info.py b/devtools/meson/mesonbuild/scripts/python_info.py new file mode 100644 index 0000000..9c3a079 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/python_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# ignore all lints for this file, since it is run by python2 as well + +# type: ignore +# pylint: disable=deprecated-module + +import sys + +# do not inject mesonbuild.scripts +# python -P would work too, but is exclusive to >=3.11 +if sys.path[0].endswith('scripts'): + del sys.path[0] + +import json, os, sysconfig +import distutils.command.install + +def get_distutils_paths(scheme=None, prefix=None): + import distutils.dist + distribution = distutils.dist.Distribution() + install_cmd = distribution.get_command_obj('install') + if prefix is not None: + install_cmd.prefix = prefix + if scheme: + install_cmd.select_scheme(scheme) + install_cmd.finalize_options() + return { + 'data': install_cmd.install_data, + 'include': os.path.dirname(install_cmd.install_headers), + 'platlib': install_cmd.install_platlib, + 'purelib': install_cmd.install_purelib, + 'scripts': install_cmd.install_scripts, + } + +# On Debian derivatives, the Python interpreter shipped by the distribution uses +# a custom install scheme, deb_system, for the system install, and changes the +# default scheme to a custom one pointing to /usr/local and replacing +# site-packages with dist-packages. +# See https://github.com/mesonbuild/meson/issues/8739. +# XXX: We should be using sysconfig, but Debian only patches distutils. + +if 'deb_system' in distutils.command.install.INSTALL_SCHEMES: + paths = get_distutils_paths(scheme='deb_system') + install_paths = get_distutils_paths(scheme='deb_system', prefix='') +else: + paths = sysconfig.get_paths() + empty_vars = {'base': '', 'platbase': '', 'installed_base': ''} + install_paths = sysconfig.get_paths(vars=empty_vars) + +def links_against_libpython(): + from distutils.core import Distribution, Extension + cmd = Distribution().get_command_obj('build_ext') + cmd.ensure_finalized() + return bool(cmd.get_libraries(Extension('dummy', []))) + +variables = sysconfig.get_config_vars() +variables.update({'base_prefix': getattr(sys, 'base_prefix', sys.prefix)}) + +if sys.version_info < (3, 0): + suffix = variables.get('SO') +elif sys.version_info < (3, 8, 7): + # https://bugs.python.org/issue?@action=redirect&bpo=39825 + from distutils.sysconfig import get_config_var + suffix = get_config_var('EXT_SUFFIX') +else: + suffix = variables.get('EXT_SUFFIX') + +print(json.dumps({ + 'variables': variables, + 'paths': paths, + 'sysconfig_paths': sysconfig.get_paths(), + 'install_paths': install_paths, + 'version': sysconfig.get_python_version(), + 'platform': sysconfig.get_platform(), + 'is_pypy': '__pypy__' in sys.builtin_module_names, + 'is_venv': sys.prefix != variables['base_prefix'], + 'link_libpython': links_against_libpython(), + 'suffix': suffix, +})) diff --git a/devtools/meson/mesonbuild/scripts/regen_checker.py b/devtools/meson/mesonbuild/scripts/regen_checker.py new file mode 100644 index 0000000..f3a6f3c --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/regen_checker.py @@ -0,0 +1,65 @@ +# Copyright 2015-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import sys, os +import pickle, subprocess +import typing as T +from ..coredata import CoreData +from ..backend.backends import RegenInfo +from ..mesonlib import OptionKey + +# This could also be used for XCode. + +def need_regen(regeninfo: RegenInfo, regen_timestamp: float) -> bool: + for i in regeninfo.depfiles: + curfile = os.path.join(regeninfo.build_dir, i) + curtime = os.stat(curfile).st_mtime + if curtime > regen_timestamp: + return True + # The timestamp file gets automatically deleted by MSBuild during a 'Clean' build. + # We must make sure to recreate it, even if we do not regenerate the solution. + # Otherwise, Visual Studio will always consider the REGEN project out of date. + print("Everything is up-to-date, regeneration of build files is not needed.") + from ..backend.vs2010backend import Vs2010Backend + Vs2010Backend.touch_regen_timestamp(regeninfo.build_dir) + return False + +def regen(regeninfo: RegenInfo, meson_command: T.List[str], backend: str) -> None: + cmd = meson_command + ['--internal', + 'regenerate', + regeninfo.build_dir, + regeninfo.source_dir, + '--backend=' + backend] + subprocess.check_call(cmd) + +def run(args: T.List[str]) -> int: + private_dir = args[0] + dumpfile = os.path.join(private_dir, 'regeninfo.dump') + coredata_file = os.path.join(private_dir, 'coredata.dat') + with open(dumpfile, 'rb') as f: + regeninfo = pickle.load(f) + assert isinstance(regeninfo, RegenInfo) + with open(coredata_file, 'rb') as f: + coredata = pickle.load(f) + assert isinstance(coredata, CoreData) + backend = coredata.get_option(OptionKey('backend')) + assert isinstance(backend, str) + regen_timestamp = os.stat(dumpfile).st_mtime + if need_regen(regeninfo, regen_timestamp): + regen(regeninfo, coredata.meson_command, backend) + return 0 + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/run_tool.py b/devtools/meson/mesonbuild/scripts/run_tool.py new file mode 100644 index 0000000..adf767a --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/run_tool.py @@ -0,0 +1,68 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import itertools +import fnmatch +from pathlib import Path +from concurrent.futures import ThreadPoolExecutor + +from ..compilers import lang_suffixes +from ..mesonlib import quiet_git +import typing as T + +if T.TYPE_CHECKING: + import subprocess + +def parse_pattern_file(fname: Path) -> T.List[str]: + patterns = [] + try: + with fname.open(encoding='utf-8') as f: + for line in f: + pattern = line.strip() + if pattern and not pattern.startswith('#'): + patterns.append(pattern) + except FileNotFoundError: + pass + return patterns + +def run_tool(name: str, srcdir: Path, builddir: Path, fn: T.Callable[..., subprocess.CompletedProcess], *args: T.Any) -> int: + patterns = parse_pattern_file(srcdir / f'.{name}-include') + globs: T.Union[T.List[T.List[Path]], T.List[T.Generator[Path, None, None]]] + if patterns: + globs = [srcdir.glob(p) for p in patterns] + else: + r, o = quiet_git(['ls-files'], srcdir) + if r: + globs = [[Path(srcdir, f) for f in o.splitlines()]] + else: + globs = [srcdir.glob('**/*')] + patterns = parse_pattern_file(srcdir / f'.{name}-ignore') + ignore = [str(builddir / '*')] + ignore.extend([str(srcdir / p) for p in patterns]) + suffixes = set(lang_suffixes['c']).union(set(lang_suffixes['cpp'])) + suffixes.add('h') + suffixes = {f'.{s}' for s in suffixes} + futures = [] + returncode = 0 + with ThreadPoolExecutor() as e: + for f in itertools.chain(*globs): + strf = str(f) + if f.is_dir() or f.suffix not in suffixes or \ + any(fnmatch.fnmatch(strf, i) for i in ignore): + continue + futures.append(e.submit(fn, f, *args)) + if futures: + returncode = max(x.result().returncode for x in futures) + return returncode diff --git a/devtools/meson/mesonbuild/scripts/scanbuild.py b/devtools/meson/mesonbuild/scripts/scanbuild.py new file mode 100644 index 0000000..9cfc75d --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/scanbuild.py @@ -0,0 +1,66 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import subprocess +import shutil +import tempfile +from ..environment import detect_ninja, detect_scanbuild +from ..coredata import get_cmd_line_file, CmdLineFileParser +from ..mesonlib import windows_proof_rmtree +from pathlib import Path +import typing as T +from ast import literal_eval +import os + +def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, logdir: Path, args: T.List[str]) -> int: + # In case of problems leave the temp directory around + # so it can be debugged. + scandir = tempfile.mkdtemp(dir=str(privdir)) + meson_cmd = exelist + args + build_cmd = exelist + ['-o', str(logdir)] + detect_ninja() + ['-C', scandir] + rc = subprocess.call(meson_cmd + [str(srcdir), scandir]) + if rc != 0: + return rc + rc = subprocess.call(build_cmd) + if rc == 0: + windows_proof_rmtree(scandir) + return rc + +def run(args: T.List[str]) -> int: + srcdir = Path(args[0]) + bldpath = Path(args[1]) + blddir = args[1] + meson_cmd = args[2:] + privdir = bldpath / 'meson-private' + logdir = bldpath / 'meson-logs' / 'scanbuild' + shutil.rmtree(str(logdir), ignore_errors=True) + + # if any cross or native files are specified we should use them + cmd = get_cmd_line_file(blddir) + data = CmdLineFileParser() + data.read(cmd) + + if 'cross_file' in data['properties']: + meson_cmd.extend([f'--cross-file={os.path.abspath(f)}' for f in literal_eval(data['properties']['cross_file'])]) + + if 'native_file' in data['properties']: + meson_cmd.extend([f'--native-file={os.path.abspath(f)}' for f in literal_eval(data['properties']['native_file'])]) + + exelist = detect_scanbuild() + if not exelist: + print('Could not execute scan-build "%s"' % ' '.join(exelist)) + return 1 + + return scanbuild(exelist, srcdir, bldpath, privdir, logdir, meson_cmd) diff --git a/devtools/meson/mesonbuild/scripts/symbolextractor.py b/devtools/meson/mesonbuild/scripts/symbolextractor.py new file mode 100644 index 0000000..08d839b --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/symbolextractor.py @@ -0,0 +1,333 @@ +# Copyright 2013-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script extracts the symbols of a given shared library +# into a file. If the symbols have not changed, the file is not +# touched. This information is used to skip link steps if the +# ABI has not changed. + +# This file is basically a reimplementation of +# http://cgit.freedesktop.org/libreoffice/core/commit/?id=3213cd54b76bc80a6f0516aac75a48ff3b2ad67c +from __future__ import annotations + +import typing as T +import os, sys +from .. import mesonlib +from .. import mlog +from ..mesonlib import Popen_safe +import argparse + +parser = argparse.ArgumentParser() + +parser.add_argument('--cross-host', default=None, dest='cross_host', + help='cross compilation host platform') +parser.add_argument('args', nargs='+') + +TOOL_WARNING_FILE = None +RELINKING_WARNING = 'Relinking will always happen on source changes.' + +def dummy_syms(outfilename: str) -> None: + """Just touch it so relinking happens always.""" + with open(outfilename, 'w', encoding='utf-8'): + pass + +def write_if_changed(text: str, outfilename: str) -> None: + try: + with open(outfilename, encoding='utf-8') as f: + oldtext = f.read() + if text == oldtext: + return + except FileNotFoundError: + pass + with open(outfilename, 'w', encoding='utf-8') as f: + f.write(text) + +def print_tool_warning(tools: T.List[str], msg: str, stderr: T.Optional[str] = None) -> None: + if os.path.exists(TOOL_WARNING_FILE): + return + m = f'{tools!r} {msg}. {RELINKING_WARNING}' + if stderr: + m += '\n' + stderr + mlog.warning(m) + # Write it out so we don't warn again + with open(TOOL_WARNING_FILE, 'w', encoding='utf-8'): + pass + +def get_tool(name: str) -> T.List[str]: + evar = name.upper() + if evar in os.environ: + import shlex + return shlex.split(os.environ[evar]) + return [name] + +def call_tool(name: str, args: T.List[str], **kwargs: T.Any) -> str: + tool = get_tool(name) + try: + p, output, e = Popen_safe(tool + args, **kwargs) + except FileNotFoundError: + print_tool_warning(tool, 'not found') + return None + except PermissionError: + print_tool_warning(tool, 'not usable') + return None + if p.returncode != 0: + print_tool_warning(tool, 'does not work', e) + return None + return output + +def call_tool_nowarn(tool: T.List[str], **kwargs: T.Any) -> T.Tuple[str, str]: + try: + p, output, e = Popen_safe(tool, **kwargs) + except FileNotFoundError: + return None, '{!r} not found\n'.format(tool[0]) + except PermissionError: + return None, '{!r} not usable\n'.format(tool[0]) + if p.returncode != 0: + return None, e + return output, None + +def gnu_syms(libfilename: str, outfilename: str) -> None: + # Get the name of the library + output = call_tool('readelf', ['-d', libfilename]) + if not output: + dummy_syms(outfilename) + return + result = [x for x in output.split('\n') if 'SONAME' in x] + assert len(result) <= 1 + # Get a list of all symbols exported + output = call_tool('nm', ['--dynamic', '--extern-only', '--defined-only', + '--format=posix', libfilename]) + if not output: + dummy_syms(outfilename) + return + for line in output.split('\n'): + if not line: + continue + line_split = line.split() + entry = line_split[0:2] + # Store the size of symbols pointing to data objects so we relink + # when those change, which is needed because of copy relocations + # https://github.com/mesonbuild/meson/pull/7132#issuecomment-628353702 + if line_split[1].upper() in {'B', 'G', 'D'} and len(line_split) >= 4: + entry += [line_split[3]] + result += [' '.join(entry)] + write_if_changed('\n'.join(result) + '\n', outfilename) + +def solaris_syms(libfilename: str, outfilename: str) -> None: + # gnu_syms() works with GNU nm & readelf, not Solaris nm & elfdump + origpath = os.environ['PATH'] + try: + os.environ['PATH'] = '/usr/gnu/bin:' + origpath + gnu_syms(libfilename, outfilename) + finally: + os.environ['PATH'] = origpath + +def osx_syms(libfilename: str, outfilename: str) -> None: + # Get the name of the library + output = call_tool('otool', ['-l', libfilename]) + if not output: + dummy_syms(outfilename) + return + arr = output.split('\n') + for (i, val) in enumerate(arr): + if 'LC_ID_DYLIB' in val: + match = i + break + result = [arr[match + 2], arr[match + 5]] # Libreoffice stores all 5 lines but the others seem irrelevant. + # Get a list of all symbols exported + output = call_tool('nm', ['--extern-only', '--defined-only', + '--format=posix', libfilename]) + if not output: + dummy_syms(outfilename) + return + result += [' '.join(x.split()[0:2]) for x in output.split('\n')] + write_if_changed('\n'.join(result) + '\n', outfilename) + +def openbsd_syms(libfilename: str, outfilename: str) -> None: + # Get the name of the library + output = call_tool('readelf', ['-d', libfilename]) + if not output: + dummy_syms(outfilename) + return + result = [x for x in output.split('\n') if 'SONAME' in x] + assert len(result) <= 1 + # Get a list of all symbols exported + output = call_tool('nm', ['-D', '-P', '-g', libfilename]) + if not output: + dummy_syms(outfilename) + return + # U = undefined (cope with the lack of --defined-only option) + result += [' '.join(x.split()[0:2]) for x in output.split('\n') if x and not x.endswith('U ')] + write_if_changed('\n'.join(result) + '\n', outfilename) + +def freebsd_syms(libfilename: str, outfilename: str) -> None: + # Get the name of the library + output = call_tool('readelf', ['-d', libfilename]) + if not output: + dummy_syms(outfilename) + return + result = [x for x in output.split('\n') if 'SONAME' in x] + assert len(result) <= 1 + # Get a list of all symbols exported + output = call_tool('nm', ['--dynamic', '--extern-only', '--defined-only', + '--format=posix', libfilename]) + if not output: + dummy_syms(outfilename) + return + + result += [' '.join(x.split()[0:2]) for x in output.split('\n')] + write_if_changed('\n'.join(result) + '\n', outfilename) + +def cygwin_syms(impfilename: str, outfilename: str) -> None: + # Get the name of the library + output = call_tool('dlltool', ['-I', impfilename]) + if not output: + dummy_syms(outfilename) + return + result = [output] + # Get the list of all symbols exported + output = call_tool('nm', ['--extern-only', '--defined-only', + '--format=posix', impfilename]) + if not output: + dummy_syms(outfilename) + return + for line in output.split('\n'): + if ' T ' not in line: + continue + result.append(line.split(maxsplit=1)[0]) + write_if_changed('\n'.join(result) + '\n', outfilename) + +def _get_implib_dllname(impfilename: str) -> T.Tuple[T.List[str], str]: + all_stderr = '' + # First try lib.exe, which is provided by MSVC. Then llvm-lib.exe, by LLVM + # for clang-cl. + # + # We cannot call get_tool on `lib` because it will look at the `LIB` env + # var which is the list of library paths MSVC will search for import + # libraries while linking. + for lib in (['lib'], get_tool('llvm-lib')): + output, e = call_tool_nowarn(lib + ['-list', impfilename]) + if output: + # The output is a list of DLLs that each symbol exported by the import + # library is available in. We only build import libraries that point to + # a single DLL, so we can pick any of these. Pick the last one for + # simplicity. Also skip the last line, which is empty. + return output.split('\n')[-2:-1], None + all_stderr += e + # Next, try dlltool.exe which is provided by MinGW + output, e = call_tool_nowarn(get_tool('dlltool') + ['-I', impfilename]) + if output: + return [output], None + all_stderr += e + return ([], all_stderr) + +def _get_implib_exports(impfilename: str) -> T.Tuple[T.List[str], str]: + all_stderr = '' + # Force dumpbin.exe to use en-US so we can parse its output + env = os.environ.copy() + env['VSLANG'] = '1033' + output, e = call_tool_nowarn(get_tool('dumpbin') + ['-exports', impfilename], env=env) + if output: + lines = output.split('\n') + start = lines.index('File Type: LIBRARY') + end = lines.index(' Summary') + return lines[start:end], None + all_stderr += e + # Next, try llvm-nm.exe provided by LLVM, then nm.exe provided by MinGW + for nm in ('llvm-nm', 'nm'): + output, e = call_tool_nowarn(get_tool(nm) + ['--extern-only', '--defined-only', + '--format=posix', impfilename]) + if output: + result = [] + for line in output.split('\n'): + if ' T ' not in line or line.startswith('.text'): + continue + result.append(line.split(maxsplit=1)[0]) + return result, None + all_stderr += e + return ([], all_stderr) + +def windows_syms(impfilename: str, outfilename: str) -> None: + # Get the name of the library + result, e = _get_implib_dllname(impfilename) + if not result: + print_tool_warning(['lib', 'llvm-lib', 'dlltool'], 'do not work or were not found', e) + dummy_syms(outfilename) + return + # Get a list of all symbols exported + symbols, e = _get_implib_exports(impfilename) + if not symbols: + print_tool_warning(['dumpbin', 'llvm-nm', 'nm'], 'do not work or were not found', e) + dummy_syms(outfilename) + return + result += symbols + write_if_changed('\n'.join(result) + '\n', outfilename) + +def gen_symbols(libfilename: str, impfilename: str, outfilename: str, cross_host: str) -> None: + if cross_host is not None: + # In case of cross builds just always relink. In theory we could + # determine the correct toolset, but we would need to use the correct + # `nm`, `readelf`, etc, from the cross info which requires refactoring. + dummy_syms(outfilename) + elif mesonlib.is_linux() or mesonlib.is_hurd(): + gnu_syms(libfilename, outfilename) + elif mesonlib.is_osx(): + osx_syms(libfilename, outfilename) + elif mesonlib.is_openbsd(): + openbsd_syms(libfilename, outfilename) + elif mesonlib.is_freebsd(): + freebsd_syms(libfilename, outfilename) + elif mesonlib.is_netbsd(): + freebsd_syms(libfilename, outfilename) + elif mesonlib.is_windows(): + if os.path.isfile(impfilename): + windows_syms(impfilename, outfilename) + else: + # No import library. Not sure how the DLL is being used, so just + # rebuild everything that links to it every time. + dummy_syms(outfilename) + elif mesonlib.is_cygwin(): + if os.path.isfile(impfilename): + cygwin_syms(impfilename, outfilename) + else: + # No import library. Not sure how the DLL is being used, so just + # rebuild everything that links to it every time. + dummy_syms(outfilename) + elif mesonlib.is_sunos(): + solaris_syms(libfilename, outfilename) + else: + if not os.path.exists(TOOL_WARNING_FILE): + mlog.warning('Symbol extracting has not been implemented for this ' + 'platform. ' + RELINKING_WARNING) + # Write it out so we don't warn again + with open(TOOL_WARNING_FILE, 'w', encoding='utf-8'): + pass + dummy_syms(outfilename) + +def run(args: T.List[str]) -> int: + global TOOL_WARNING_FILE # pylint: disable=global-statement + options = parser.parse_args(args) + if len(options.args) != 4: + print('symbolextractor.py ') + sys.exit(1) + privdir = os.path.join(options.args[0], 'meson-private') + TOOL_WARNING_FILE = os.path.join(privdir, 'symbolextractor_tool_warning_printed') + libfile = options.args[1] + impfile = options.args[2] # Only used on Windows + outfile = options.args[3] + gen_symbols(libfile, impfile, outfile, options.cross_host) + return 0 + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/tags.py b/devtools/meson/mesonbuild/scripts/tags.py new file mode 100644 index 0000000..c856807 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/tags.py @@ -0,0 +1,54 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import subprocess +from pathlib import Path +import typing as T + +def ls_as_bytestream() -> bytes: + if os.path.exists('.git'): + return subprocess.run(['git', 'ls-tree', '-r', '--name-only', 'HEAD'], + stdout=subprocess.PIPE).stdout + + files = [str(p) for p in Path('.').glob('**/*') + if not p.is_dir() and + not next((x for x in p.parts if x.startswith('.')), None)] + return '\n'.join(files).encode() + + +def cscope() -> int: + ls = b'\n'.join([b'"%s"' % f for f in ls_as_bytestream().split()]) + return subprocess.run(['cscope', '-v', '-b', '-i-'], input=ls).returncode + + +def ctags() -> int: + ls = ls_as_bytestream() + return subprocess.run(['ctags', '-L-'], input=ls).returncode + + +def etags() -> int: + ls = ls_as_bytestream() + return subprocess.run(['etags', '-'], input=ls).returncode + + +def run(args: T.List[str]) -> int: + tool_name = args[0] + srcdir_name = args[1] + os.chdir(srcdir_name) + assert tool_name in {'cscope', 'ctags', 'etags'} + res = globals()[tool_name]() + assert isinstance(res, int) + return res diff --git a/devtools/meson/mesonbuild/scripts/test_loaded_modules.py b/devtools/meson/mesonbuild/scripts/test_loaded_modules.py new file mode 100644 index 0000000..b3547be --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/test_loaded_modules.py @@ -0,0 +1,11 @@ +import sys +import json +import typing as T +from . import meson_exe + +# This script is used by run_unittests.py to verify we don't load too many +# modules when executing a wrapped command. +def run(args: T.List[str]) -> int: + meson_exe.run(args) + print(json.dumps(list(sys.modules.keys()))) + return 0 diff --git a/devtools/meson/mesonbuild/scripts/uninstall.py b/devtools/meson/mesonbuild/scripts/uninstall.py new file mode 100644 index 0000000..8548766 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/uninstall.py @@ -0,0 +1,51 @@ +# Copyright 2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import os +import typing as T + +logfile = 'meson-logs/install-log.txt' + +def do_uninstall(log: str) -> None: + failures = 0 + successes = 0 + for line in open(log, encoding='utf-8'): + if line.startswith('#'): + continue + fname = line.strip() + try: + if os.path.isdir(fname) and not os.path.islink(fname): + os.rmdir(fname) + else: + os.unlink(fname) + print('Deleted:', fname) + successes += 1 + except Exception as e: + print(f'Could not delete {fname}: {e}.') + failures += 1 + print('\nUninstall finished.\n') + print('Deleted:', successes) + print('Failed:', failures) + print('\nRemember that files created by custom scripts have not been removed.') + +def run(args: T.List[str]) -> int: + if args: + print('Weird error.') + return 1 + if not os.path.exists(logfile): + print('Log file does not exist, no installation has been done.') + return 0 + do_uninstall(logfile) + return 0 diff --git a/devtools/meson/mesonbuild/scripts/vcstagger.py b/devtools/meson/mesonbuild/scripts/vcstagger.py new file mode 100644 index 0000000..c484ee1 --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/vcstagger.py @@ -0,0 +1,45 @@ +# Copyright 2015-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import sys, os, subprocess, re +import typing as T + +def config_vcs_tag(infile: str, outfile: str, fallback: str, source_dir: str, replace_string: str, regex_selector: str, cmd: T.List[str]) -> None: + try: + output = subprocess.check_output(cmd, cwd=source_dir) + new_string = re.search(regex_selector, output.decode()).group(1).strip() + except Exception: + new_string = fallback + + with open(infile, encoding='utf-8') as f: + new_data = f.read().replace(replace_string, new_string) + if os.path.exists(outfile): + with open(outfile, encoding='utf-8') as f: + needs_update = f.read() != new_data + else: + needs_update = True + if needs_update: + with open(outfile, 'w', encoding='utf-8') as f: + f.write(new_data) + + +def run(args: T.List[str]) -> int: + infile, outfile, fallback, source_dir, replace_string, regex_selector = args[0:6] + command = args[6:] + config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, command) + return 0 + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) diff --git a/devtools/meson/mesonbuild/scripts/yasm.py b/devtools/meson/mesonbuild/scripts/yasm.py new file mode 100644 index 0000000..730ff3e --- /dev/null +++ b/devtools/meson/mesonbuild/scripts/yasm.py @@ -0,0 +1,22 @@ +import argparse +import subprocess +import typing as T + +def run(args: T.List[str]) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('--depfile') + options, yasm_cmd = parser.parse_known_args(args) + + # Compile + returncode = subprocess.call(yasm_cmd) + if returncode != 0: + return returncode + + # Capture and write depfile + ret = subprocess.run(yasm_cmd + ['-M'], capture_output=True) + if ret.returncode != 0: + return ret.returncode + with open(options.depfile, 'wb') as f: + f.write(ret.stdout) + + return 0 diff --git a/devtools/meson/mesonbuild/templates/__init__.py b/devtools/meson/mesonbuild/templates/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99cfaf58cf1f5bbfd1d584ab35465ce3f81e4f7d GIT binary patch literal 161 zcmZ?b<>g`kf;}G&r-A6lAOZ#$feZ&AE@lA|DGb33nv8xc8Hzx{2;!HQi&acYYFSKr zeojhpQF2U1j$ur3N_ISm4HPfQ&(A52$xSWJ&x4RjrI|S?F(s+F1v!Z&sl_qz@tJv< aCGqik1(mlrY;yBcN^?@}Kz4ivVg>+VpexY; literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/cpptemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/cpptemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc493361cc9467bbd8138a0d3350adbc7bf0ed7d GIT binary patch literal 4525 zcmcIo&5zs06(>dNi>tMrq;cZbO_*IYk{nyLlb}dtJ7}{G3>Ws+Xq*<6*Cn`|(Tcki zsm_q=tUgY0k&_FwmtJ!4-qQb}xBeGA73e8N4?PzM(BB(U615xqP$1NDKHi&o^X9!b zzc<{E*4Hf!&)@#@_x`WXYuZ1lGk;7pex{w%OEbjb}1+gjh>;}Mqu_# zX7u8msl{tlqP3Ys_M6Pc*j1jn9qV8Z$o8+KsPijkcbyxnUT^ZtO>) zMA!Pn9gYHi2gSB~Ue~luKlFlxar=fJ$yjiA_@QNOGT!$?Zr}gaFMsjz)&pnz=l4Fg zHzp$y?Q<`7LU+h#8LY5}8?k%9r5#2@O@=&-WoIYcxUR&}Ou^$sg!Z+JGMg#J zinxsj17F(s%ayh_Nb<^t(BD{!%|%|lZb97mANjOab9L9v%XZTnjhdIS;vp9jX0^L^ zbCS1biUI4nNf0~HNSPf29yTAlBJ{&OC*X%XxcQzMM>{$3kZ=bZx#_+0&b9ZOkJ^^S zKjZdI8>N@T?ry-L5;~a^NS%p{65%ZfP|Ocy>;?hWjYYyCBIYt~HFsU!o;lIE|LI3}?`+wQ!?+j75%*dw2>55CNW^Ut#skSwqm_rE}Xs}@EHJLq39`{iz;-x#U2*V4}7*3g7zos zFe#iUj_h_%tDMcv58+%{oJ4gRzj>~vOGW{{zAIeXu>UVyD!6^sVz!szSH5envtky& zWoAG3UxucA=Xj)W?F95}+7AX?@+AtR#eo*Vk)24+>^QP_6F)#>z-wXb3~92;NJTJI zfviAw6$}Zt31Zc1T~byxiM$skjyxLfMuAg+0D$|zXN-psmLsWy4V^?}LRg{~G*P4+ zo0sYYet6(K_TvH2S#7DEqw_?KpKoL?4@+*^_mB-?FeI~l*RUXE0^60gYv1D%Nk}HU zd5CnZNsz%Y0CxmM33lNc>hTae@s3&w6ja`Km@kmiBjIz|1)Q8Bwwj%0o9y!~n!iZ5 zzKDj(%koIZeAtv23=}+Y_c$&MAu7=UGN?@DWbh;5%_0!Nq1YA_R4F#+pgU{AETe-x zXBaW;FG~omCMZC^zP|@{&c%rexd0B*j>)!4Qf{cZufQVzAU$U6+G=t#i8;3}UJ@j17Lw&l^yZT{fozQ z(^=_Bt!FTUnP2Lx%qmalj+phTtcG6s3(eGe72F2vskJp4-OsLXUP;N+G^*(}Nd6mW z#Menrco7wSn4T8l>pkZ8I&)WW+^Ua~wbPW5-ENGHY7Rx6>}ArsP3C zt>%{>+&SxxlchB0uiAgNZ*_MVKit`i0w#sGGYGEjNOs^*8}vAe0=a{P8HHJ?@MQ-9 zGz#EGxr4*I=yXO$q5{4Dj8{@a(=ENGk6&4CwzJf8I|@0psbpyD;rgQdbgeo0Vd7T4E+y`>FA)99QTQ9>c_gS#U`s2xV4Ns z)u$v2clDw#W5{zjLpQuU`4-qf~dsW(PY<^~d9K68Eos07Yv!sS(4S5$#4X zWXEgDJ{@J6wkckL(iokCPr6pP4+`2@+e%An63*PdX{8^Dp&O^KFL`R^#fVJ2A?hUctdi>C6gdih#H*l+#-doKK`(ju#K1*s znG^m3vOI@E)4vDjy`i5$S;B98vEas2(-!`tud6e7mH+;Y#<%vY7`6*gTf;PWEV2tCtt zDrFV&UAjI`VoFLLrt@r_))ki|t0)pLLE}a6i4Dhu^t=JS%7Npobv3Q5{37d>2J_Q0TCjc1cDen>@!iXT&Pm5OUr(4tFyvX(-g+Kp^$9}-wdimyhgq1VouYvx<#S##Zd H+cf?MiUvrl literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/cstemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/cstemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe2c0651695cd118bedaa44f55c0c5801c477497 GIT binary patch literal 3614 zcmcgvPmkNy5r2>WL{ZwcojA4KIyJpHNGfdBMuEbylc0^0wh8Qw(KQf2UWefFJ?(Or zBGvaEy;-dU1c-y2oKucD>>l$G0<@=o3tn@|t;e9J&OB0DDPA-_1m>=W!+Gz`3}=2b zBfYz_;t{z1`JaCe4qhSTdwiH(7BGJzXNmk9FpMyok|FI=ioB5;L$hyc-b}5&#jL)~ z?7qXCeuFjoE_3_MzY^AD-c!OnZhmg|J!Wo@Uh4yh{@US43=3?tS3i66d-_PF%391Rvj zo+%jwYrWnb?H%g%eZf^BGXLgGHl5asKWppZP9lByuU{Qr=f-pztX*3Q&WW+w(2dFv zn1O$9{9S#z+gT1_=bGP%W#<|=^MnftN%U{~ox_@+>IKFJQIV=JAL%5+hDV+KNMw+p zFy&8p`t~0>k9(fSKjn}kpmCw1t(1c;c&Ji^b`E7;hk9NM8QFY;!<@x zTaip+I02`7-uSbh$IM71Pa?%@>>v)ZVz|Wxxbw#vBQ@@DZJPsr^m=z8{dL@`g{9y{ z;fui-ou9+_C1CQ!P&fnJ{{`VvA;u84jPEa1XLkLVl^9Tc!FR0U^8vQ3a(4W9_%VDDpWuqQ``i z3Eed&BsAb|!rf#96w&pbRob!`aZ$Qqm}H3x!_vYCmyNpD^^DSzJROvcy3fHdYldMp zp~7#;fA7C{dz0}eo7;KHq=+|n(wm!-?S;sLTtQvP%^_x>qFY6hvQ3zJqZE3R+>CJo zR(voz5DvHGYj|W=(pF$%}1X^*T*-mzxlYNp+NV4Kr%LiSeA5u zY!_;9{T95T3z*CqOcqE-yGF4tq|!V2t}t%tFb6uqJxiPiRdBK{xw5q|X9R|)*D4Lc zOA`u1G;pt-=KBBzyBHxNtQ?A=wD)n?m*;kPn&x3F!&$aUXP~Ekd11b!&CfSfHf+&E z)n~NoIFdZnl~sx(ats zQ;QmOd}SFi&uN%L1)W2C8Y({m^GiVm0ELjTPl1vHa_1Cz1LTbflqi73oH&!l#MbZv zsKVW5?l-NetDK30-#Y zQk(;>v>~ffXzOKKTc6))2aID42`&1Cv*-vZ13e+-Ln@Oez~G0Gljxg62z$~ty^!!{3 zqiT-x*J|l9x_eCxY;hHJt|8F??f}=HS19`5Z`J4VJ^F3^N?=(xS!WNvFmB7AB7U{T zD;&fzEI_CH9gq{ay8!u%0QAK_1inE%<1)QW$CpnnfLdX%f$bhWfOhYN;V@@KihMf^ z|4~F~wW3?GcmvFen?TByy6eZ#3BvHi=N=U;+=Rs{@K@C*@X_ttrEPn4Rm%V?U}#Xl zw|y`qa7vX|bVPNx3TDxkfz&^g5*P^r$7PjL9A?5tave#4-ia#}r@MyxR`piz Ytile7aBdrI>b_!mR?9kTy=s~N15%I%`Tzg` literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/ctemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/ctemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37298fb8b2ec9ec5fa8f2ab176ae699b50c4bc73 GIT binary patch literal 4301 zcmd5<&2JmW72oA9zm}9NCvM!NX)=|OkTh)CZcrd~;-Ix17%FVlXc82q-zGoiChTLpYyUo#xkcM#s(?ejF#MpN2`S zG4($2hoeYtpxN}F+Lm=`r2L(s&yqNh-lee5gzSg06pa6TWAnZ5v*~m};dg#<4^+-Q z#;_DC+3n9Z?%&ev#g=8Nd4Wuum;{7m^#~*p# zwae_&L8#em8#@T2h#|IYTe94hh?*Y@hD9KI>@pLfl0h0BvcQibe>;+F`;d*bRGKAy zmXf$A+*ZCi>|*&fqbGEgD)u8jJE+}ZM@J?&N~U8Kv+Eyt$H!i7)NIkrh*L|?5N0+{ z{`yiw7Yv<>FzF6pJNa+uhjE(*zS;?{uwdXTcKI?U`*Z!mew&!=d$-t)Ig#)hDSN4~ZEMWt{5nR=j?Nru&bsKSmU21APi>Z{!qMyhJ=Bcv#^7&9SVJN_OG& zcI&7Z<*sR6VXdHb1w!`WeuSOfWUZrOd~6s6(0DR3*@^{^S_i(0!+3{Ba$iQb-fKPX zc-|!dL29|M03(S6Mw}5_!P10nkHZLqfn*wf0<8!$_7Y-qZ@FSg!RUmUL8(YIzr@$m^Ox0MD zTY~(oo20545^*OUbA346P9naPlknUi6hg)j1%IScryS-$jfGKAVMbrl!;oH3CJN&{ zeh{VusACN37@0E>Gc#uLOb8wTM{w67gWx}tVZLTQdmuF;tjF602D;u+l-Ea8z!4Os zI*7o~OvbPzIBdh*BKdiqw}}d+zIhh0-RibFMY5UD@Vx$LcwxB`A)GJ^3L5+t988Z}aLZ_KhYu40`|=9iZh;acaX;Jv zyWn}6 zH1{0UJvbO#6LTWIBsDvpU#6>aUYi${X?D{+{Mk=`^6{Nd`R0!we9YEQrvCc>QvsWm zLUWe@y@kWrJ4GE_Hl!$qC(8chPsI-4;#AE3X9ezzTn1?=jf)H}5)*+tSx$Q(T{s%N!34|Bu?B_q+YsHdMp(%-@$wZ5>P+0QN8n%cXisl`j^9rTW{Aj975 zxLH|`M^a@q&cirNInP|OEvpuQ?36NB%c!4Ki@O0YxjN@4AzE|(N9*7B@7~-Ja(`XVhK$uIY0uWi20CjYxvzE4+soW*iU|)TDzrZ&U5Rzb8Js-;as$iOQ}08 z377o*)Ol7;E4x)%C8|&D=eBL7uBa_>YdLpnPe~SDzfWCSW&G%EPU??->0g~(zxu<+ znawAqZjjjrlkzz2Uwt2H)=*^=fy)%*<}!3A4da=vaZ1NkuR>+4E)bVBme8iiu8xk16i-3vFr;7+FSN2+7iB#H|F7cVbeTr zbTSDxar-+4XUFZC`y6qj_zCy7rPnP{MjRc?E9hPHRrF=_HS`tqb@Ww43^AWN)AF=3 ztxjEvvY}YJW#N6*Jg%jcX<0NxQ>*|9)wH%-?_1N_?{gefrj;e0cZyeC;x$h4#Oe~S zxy&=DIk$`&MXpl>pvvloOZCA(MxBSMbCj!BXm$e7E9y1S)J19t zuIk%pvhsL@ijzxtov3dRb(KyTEHL@zoVWz!S7{N=@$8zT`$A4UiRn(=z*$il%+8q; zmoWV<9ebHrUVbdu)HCD2Sl(-xGxAAR*~4RaN1x7u)dJ8EL4Rca0C~ELCQpGiBtZV9 zG+6$+X6BXNwCOv!csfA}d7Ua%Wzq~)+2i!Q8Amj3a{jBaALSfVGS%BSRs8@>wo(-5 z07ZcFg~}aUHE0o~nWBIHzsAp$*_z!fuX=_CVBw(t7=N~KkfO^Zd)qkHRH*LE=en!S zqX%!TND*N3K$G$68a3Ccxk1f$sQE56bm&5#d}OLg?Ze!(k5;il6O5Xrrd_+>uDVV4 JU9_I-{0IMm1xEk? literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/cudatemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/cudatemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ccf219554b7d33042dda4fd773a3dd082372566 GIT binary patch literal 4531 zcmd5=&5zs06(>dNi`re=O={O^KA1HcNsg`BNn50{9kjLs!-c&u8V5z?bqFqJwBjyB zsx#y|tB+G$y*jJ+tXmqhSmUwA8r=B8=rx$}iPm2Gmey$NX~PY}D0X8%3MIPM zC+=_*@Y`s%+|#kj%ErTCnB^jXPntg30Bl? z-XHkV#$RqUltS~$hG?aw+Fa$OD;Cs^|D8{3HCK1tykI|QdI@tuG`-QN`S1ePKHx&a z!FJbfPI7wIBmw;BCPC~(BNYG)c+h<0iqH>toq!+k;M)6Y9PR0uhqOD`(lzhhcQ5~< z`LJzS{Bv$!v(b7T`-B=_XDq=3cof4l{*<6r>{#Yp@5r?>Ci zyuEeHnIv(v&%-Pr^E8?>oqL~NzjOPB?Kq5kfgEwK#e#r;K8i%#CS^R39B)v00=|5v zKU~fXncuhO3SMf}%e1?3Ec~4$=8j{xS_i)Lcl^MQ5AD`w9?H#jd)3qzs#6=v%~CIm z&W#+o9=9h8az>}b@&Z>%``O)26g!Kr8a7IH0^jRGb5Yc4(=nhkxXW=kli>~*t+wsq z#K%`GYb5*wH|AX{ACwJ%U^Y{YWsSdHqQGRpUB-pe_X9oy6f6uqW^>VmZnxOO;`!0f z)M`5PkSyP|*I983 zfHU)-`;DP#|2t$N%sFS@A8^T+Kn#ilCW1pdk-&#IvUd_c05RaU1p0#)_&dTChnS1f zqXbLLlIXiJ%~gVYXvYHK0PH1l zx{88?%Y?0JwJsT}NMi4Xi6ak(J5k^i&OT6m;4{WUD9a(#!G@lNVuDuU7c5b%9F&*l z1b(>hJo4iKU|DUcox}1(jh}C1u1^KwE(#(XhI*Fo8Xlw)V7t#CjRfVX zVSiaAXf?qB?DhR!h;u29Qpg1WkakSIRhn`~&0_@-#RqjU6X)K`Yq<1;uL?L#&3&z| zQS-}1M-9vjmB%d2JV!?Y4u(|4oR}}THnc5|E^qS(M;;F@i67v_wVuwjUg=A%uQQ#M z9@lyXGno06&dRLvn68OgugYrZmA}+XtyjT?u%0$<;M#I8yTW-TrBu`CO<#i+coRgd zeW5+ok2GDI>U*WB=9KU@@HUtRHTqWDOv^GEago*>#}ED3aZ;1~npX4uv`eWedC*U* z`Lzf4&bs4d#mxDK_T9%fyW5N(Z0|+^lfv5`1edoZ+joctKaQe6ZlhF2Vb&^u*+vG9 z0>n{n)BS7F>x>RX1&03(UrB_fTY60&zgpOCXKCqH6mr;8$&l8=)ki(#`zP@rMzivjq49Sb1#lBUHtXKRCmTk$4gTE(YTz%{fi&K&Kk~Y#Bf~%y;e-x zaYH$%qkPjg#VfEGqjUI48-=T&ppCVyv?O?HAW21)#+HNV5rSw&K!mjXNcb^NUm5Tq zh#c~-Gk0)W=|^Jd#_8FDP_4Zfk}Y6}I_W*3^m;f+j)EZZV{paVqFJXwr#$@9z%6T8 z7yb^mJc&lrUq$%d)Hl$U@EN~R4CJwSiwM%MtPOls1pfo#`4N0-9wCB=pK%r$jyP$5 zE}hj7RRg^;-sV)Fl|ffPSMaXlUB$bGcMUN_7EFz4d0LrPr?sg`kykuzugvOStjl|bQKm9!qnJs8{3s~3zojNE zBT_ORmpTKLVB?zVBh}jLX(hX`rjJ-^HF1U-N@DR7G-){*0gf^a zXNmh7aW`m{!7@i*C*~<)uBP|t0t*Fvk@ja6{MBS{TPn{5fn|C^EnP_VpV9i~sdRK~Ud+)6;6w-!!8*1;$7KNUbef%)omCv4(jXdKqneJ3a&??_UlN}Q}Dki@4p~JHJ zF;(9xy{^+|{MvI4Qm(dLB{U~HfaaD%RW%8SUUQs3C2o*O6wZpbu(sGs16JQfmEgwnT^s}-bm=7EqMscJ1s zd>{y>vmE#-QEyPwq2}k*T%zVOHMHo`o{Un!Q@fgN?L&eJNg1|QTGMMM%!c{4dBR*b I-!Y9J0DD?WjQ{`u literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/dlangtemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/dlangtemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0aceaba81fbf385639b9c3e3310b44aa606bc75 GIT binary patch literal 3797 zcmd56z*7>HemB_{*Ig zm%#J4fBilF`g?@@13Syd0pjOmkEq`O!3eVi8CwI(Lb@huV|!p5+7`~hVa}k=>VpPr z44SMtXtCCy{cFP7%zZ|f%k3}hfy?YqiP!lC<$G4q3DY#wp-!??LD&5>98U!QEi{MW zHH(mO#&W^wI84&}ZZe)^Qd6aw4{ws)cU_+5WBTa#zx(9l4?hbIfAR2R`heb?O=Nb$ zBORpSm@jU^v?SF=Mqg=}q@%}AXedX@qqCVy;YniJM}{wWI?~7V-3RoZSB>HLnM^c~ zMcTjlo}xND<%*^mipa-2)yh9gZ|)n3kMBP5?i-P~Omdyel-?^ji-j4ul=azhqA2`V z*3$PXLF?P8q*apc-giOD^sm*5es6Q9y?xqay?vwRDVGYIN)KpnR?&-Ui19egg$}Zb zar*&%+&c?p3VsO$f6B#!_j^w~aP1#CI1}0^*Wplb&<35-r>JSBvRpm4V4ofle zoY634=rUlt^cH1_gfNS98i880kq*yku3+mli>XHciexB5dG5pXI|c>-1uoN21WQHz z6%01KY$nf^lge#hnYu+-8KQ5u?J_`rY=dzH?3Z2g{{-90H&+~Dwi{}jknaTLe}&{r zfCT((N2JmaO~53eOeaxLg%)rL)Ky#>U>V47;u6otD9rJ>?P8k{ANP!7OmFw(0|#LUb$*$K|YQXZ)M5q${R zWdpf@XM^le(U3mm3QmT~hn2H^cP4ap%F{)__yk5tJre&rk!pT6hoED+flmwj)amJ_N-$t=^r1eug#Fd$6Z1e6m*67f{=m#0+hrI=Fk zuOO!>gwrxdUSb05=PHtk$-OwG3aP1k%TnNfR}%N2@UbLzBP^rK2hJcoP^v$G4<`eQ zkwNWC5?jn-wP&q?&1~j;WwAPIJi}sL_L{5(z518LA%g~#=62CFQG8U^(5Pml5`tfR zZPaiB2u;2qFRTke8({eQYmTzoto_`_U-P=ETQdq&X=Ci^&o7Qt3-~Is1Y{6;I7*uhf zyX!|_+9^?OoZ~t2H82@wR|%}>tkrRe`|{kPCV62)nvqSMTQ|q2a5Bg#McrIrioIhl zL>4fpX{ED^Mx4oUsEaq2BS!0LycBKAHcEWONQ^?o1Czew>%f)WRkMSWUX3Kj(+!qZ zSC9#?)gCm&x(0!}VeLX&gTLvGjSya0xQZQWN8u)RUjwl{b}yU@h#kg|Ie)6XMOYnT zX+ysOUuSMD>OePvZosz%-zG#1Vm`O$^?767oI4n0!yzYi*8ZxyXz9kh!Ccm1T|h!p zw@%tInYaF2;sDmHjk%j+Y-eq(vp!~!vAd28iSCgI)o&1|Mcv$U;Dc2LF*9u%(q~?` zXynHGMWZYtg?r3H#wFH?VrS#(Q*_p@Yb(fLS}XQU{aP!2#m=&#nG9UvZCRs>wi(4d zU?3r11v6JDmhk(7Yy!3`-vFL`6B~r1{5~{AJ)b~kDJ8sx+#eu!7qwhsQeH>qYfC1S z?G;+DmCQ|ydTj$wiRrC)#b{W==#Np&EocTVE*_iRl{72qj@eq-DH^A6s~)MBQN3G% z6GY&}bPDp+J~Sny_W;liyd|s=+RH!3P;TwIb={i2y$$Y_M6ZeY7X1tP)(x=k!cQom zyFu`I9*T0rBtrQP=#}q7Q|we}H-cjw1eZp8mh9jpJTwx244%Mil4r~6)^}aQ^E#*~ z&f(_{D3Vwvig%1_P0sO`URS;{bq+28LLxlN(7uh-53%vFxr5DJY*62&DJ5l6L+hvI Yu70))GfYP4*1A?}&vBhy_@j>f9~zr#_W%F@ literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/fortrantemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/fortrantemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6a5ea1129e4316d31ce601e0032e87b9d2e6433 GIT binary patch literal 3645 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 RzZOfH(yH11lDq6We*!LgXte+U literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/objcpptemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/objcpptemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16392d72d103680ebf8a80263e4f0e5936e407c8 GIT binary patch literal 4431 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/rusttemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/rusttemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f03cc5d719b3d9080f9ba346e6e4f4c47d0c918 GIT binary patch literal 3105 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/__pycache__/valatemplates.cpython-37.pyc b/devtools/meson/mesonbuild/templates/__pycache__/valatemplates.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab47b3ac622843a7cf92a0507eedd67bb4e1d67d GIT binary patch literal 3392 zcmd5ZlCjZ-+wWg0haqm4WJU1TOe>%S%d_;1 z6-scXb2cuL6o?}MJ_8|V;5Zq}Gyg7w^fZD?fGQZr8rK>@J$2|CcLS6w6;aI}^rv~= z#PKvq#j0Or1_q{nny`Km)$3WNuOVI``~^j|G~$WeX9t)BdnOgC_OQ-~2+s3-+F_<3 zzma=}RVQF=_?3*iCIQnVJBdyceFQS&lAun(bEC`@CGf|3GqC3_`zSs^X95^&uYq^5 z7O)tC#Xb@W%8)9?b@3Yd=c&$5M7D~+Yj6rKCMkpsM^$Ay8<MB@~E# z$l@26gZ{9pRM%KO!8*NuEJMIu@Bj!wLdr?l`ie{`r@ZyV3oUMO`)kS_?mofWpc=Kg z2P5YzVw2E?+TSU=pF@rPV^yRlkTT}M9$yPDn>T^b8N5ZWa&jwk|jEdN*moi^MlaUs1KgAHh5ndLX(QtkyT`>Gl@G2w- z^{Gb}w;IPCURwGv&jeg~ZdFAma5tF;o$SH;Tl515LW393!Ao-7dS+da3u{G}lv}sS zs-^8^i`(e%r`9t^yT@&u#oJHm1*JsW+-pd^O1h*=)Yajgr#8+q-t-?XItPD_?=9ZB z_sheQMhj<%XDjLH!YTCh-UG1IgDWrRP*{QPHSgF(*SKhCyc5{+Ww1K*)`?Vh8yA?w zqXmB1lA^Q#(XtKW(n<4E2&0_?d`st4CR&s)AK_&lp%u~E#icvV}WpC4L;iQ`rDIkcL`1K7u0=BvV4WYLnfN#=mXj|}GywMEh z3+py9#LZE+iQzwixITu@>@X3vV`K=wQSVka%){bO|h;a2gTD2!;X=nGJ^*RU$tZdWcec;UBPTm{up@j6>JcZ z@-{T3Q_P{dR2p7I?hbNq;x1QUDPKqaD-Ax}BOA=#-tey?HRu?S$~Rzf_>$SGfz-Ef zzq{D%qI_$k1P>K%oAVhXjNjaoQ~WS~9@^VAL}4-B=2Ot5_MoY7jo7x~t+0*wUjJ-E z`K>$j4qd!<4d!cwK^sdiS^%ZjkD^)5ixlZz6v3xaT1iY%lvvVb08P17SKtXGcobdQ z98lTCNtihj|95;2uPLM+?K#`N;RRjXXj;IRCu}6~#wdSc9BZo2aP4+AROYWl0;O7F zO|2sQ8d7(#c^jLbV$;V4_q#NuqD*=4epQ|7H`_47RE1uvM?KfxwtIHR-m$I!0ejud AV*mgE literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/templates/cpptemplates.py b/devtools/meson/mesonbuild/templates/cpptemplates.py new file mode 100644 index 0000000..6e97761 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/cpptemplates.py @@ -0,0 +1,187 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +hello_cpp_template = '''#include + +#define PROJECT_NAME "{project_name}" + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + std::cout << argv[0] << "takes no arguments.\\n"; + return 1; + }} + std::cout << "This is project " << PROJECT_NAME << ".\\n"; + return 0; +}} +''' + +hello_cpp_meson_template = '''project('{project_name}', 'cpp', + version : '{version}', + default_options : ['warning_level=3', + 'cpp_std=c++14']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + +lib_hpp_template = '''#pragma once +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __declspec(dllexport) + #else + #define {utoken}_PUBLIC __declspec(dllimport) + #endif +#else + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) + #else + #define {utoken}_PUBLIC + #endif +#endif + +namespace {namespace} {{ + +class {utoken}_PUBLIC {class_name} {{ + +public: + {class_name}(); + int get_number() const; + +private: + + int number; + +}}; + +}} + +''' + +lib_cpp_template = '''#include <{header_file}> + +namespace {namespace} {{ + +{class_name}::{class_name}() {{ + number = 6; +}} + +int {class_name}::get_number() const {{ + return number; +}} + +}} +''' + +lib_cpp_test_template = '''#include <{header_file}> +#include + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + std::cout << argv[0] << " takes no arguments.\\n"; + return 1; + }} + {namespace}::{class_name} c; + return c.get_number() != 6; +}} +''' + +lib_cpp_meson_template = '''project('{project_name}', 'cpp', + version : '{version}', + default_options : ['warning_level=3', 'cpp_std=c++14']) + +# These arguments are only used to build the shared library +# not the executables that use the library. +lib_args = ['-DBUILDING_{utoken}'] + +shlib = shared_library('{lib_name}', '{source_file}', + install : true, + cpp_args : lib_args, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) + +# Make this library usable from the system's +# package manager. +install_headers('{header_file}', subdir : '{header_dir}') + +pkg_mod = import('pkgconfig') +pkg_mod.generate( + name : '{project_name}', + filebase : '{ltoken}', + description : 'Meson sample project.', + subdirs : '{header_dir}', + libraries : shlib, + version : '{version}', +) +''' + + +class CppProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.cpp' + open(source_name, 'w', encoding='utf-8').write(hello_cpp_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_cpp_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + test_exe_name = lowercase_token + '_test' + namespace = lowercase_token + lib_hpp_name = lowercase_token + '.hpp' + lib_cpp_name = lowercase_token + '.cpp' + test_cpp_name = lowercase_token + '_test.cpp' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'class_name': class_name, + 'namespace': namespace, + 'header_file': lib_hpp_name, + 'source_file': lib_cpp_name, + 'test_source_file': test_cpp_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_hpp_name, 'w', encoding='utf-8').write(lib_hpp_template.format(**kwargs)) + open(lib_cpp_name, 'w', encoding='utf-8').write(lib_cpp_template.format(**kwargs)) + open(test_cpp_name, 'w', encoding='utf-8').write(lib_cpp_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_cpp_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/cstemplates.py b/devtools/meson/mesonbuild/templates/cstemplates.py new file mode 100644 index 0000000..df09f61 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/cstemplates.py @@ -0,0 +1,136 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +hello_cs_template = '''using System; + +public class {class_name} {{ + const String PROJECT_NAME = "{project_name}"; + + static int Main(String[] args) {{ + if (args.Length > 0) {{ + System.Console.WriteLine(String.Format("{project_name} takes no arguments..")); + return 1; + }} + Console.WriteLine(String.Format("This is project {{0}}.", PROJECT_NAME)); + return 0; + }} +}} + +''' + +hello_cs_meson_template = '''project('{project_name}', 'cs', + version : '{version}', + default_options : ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + +lib_cs_template = ''' +public class {class_name} {{ + private const int number = 6; + + public int get_number() {{ + return number; + }} +}} + +''' + +lib_cs_test_template = '''using System; + +public class {class_test} {{ + static int Main(String[] args) {{ + if (args.Length > 0) {{ + System.Console.WriteLine("{project_name} takes no arguments.."); + return 1; + }} + {class_name} c = new {class_name}(); + Boolean result = true; + return result.CompareTo(c.get_number() != 6); + }} +}} + +''' + +lib_cs_meson_template = '''project('{project_name}', 'cs', + version : '{version}', + default_options : ['warning_level=3']) + +stlib = shared_library('{lib_name}', '{source_file}', + install : true, +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : stlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : stlib) + +''' + + +class CSharpProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + source_name = uppercase_token[0] + lowercase_token[1:] + '.cs' + open(source_name, 'w', encoding='utf-8').write( + hello_cs_template.format(project_name=self.name, + class_name=class_name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_cs_meson_template.format(project_name=self.name, + exe_name=self.name, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + class_test = uppercase_token[0] + lowercase_token[1:] + '_test' + project_test = lowercase_token + '_test' + lib_cs_name = uppercase_token[0] + lowercase_token[1:] + '.cs' + test_cs_name = uppercase_token[0] + lowercase_token[1:] + '_test.cs' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'class_test': class_test, + 'class_name': class_name, + 'source_file': lib_cs_name, + 'test_source_file': test_cs_name, + 'test_exe_name': project_test, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_cs_name, 'w', encoding='utf-8').write(lib_cs_template.format(**kwargs)) + open(test_cs_name, 'w', encoding='utf-8').write(lib_cs_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_cs_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/ctemplates.py b/devtools/meson/mesonbuild/templates/ctemplates.py new file mode 100644 index 0000000..0c7141a --- /dev/null +++ b/devtools/meson/mesonbuild/templates/ctemplates.py @@ -0,0 +1,168 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +lib_h_template = '''#pragma once +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __declspec(dllexport) + #else + #define {utoken}_PUBLIC __declspec(dllimport) + #endif +#else + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) + #else + #define {utoken}_PUBLIC + #endif +#endif + +int {utoken}_PUBLIC {function_name}(); + +''' + +lib_c_template = '''#include <{header_file}> + +/* This function will not be exported and is not + * directly callable by users of this library. + */ +int internal_function() {{ + return 0; +}} + +int {function_name}() {{ + return internal_function(); +}} +''' + +lib_c_test_template = '''#include <{header_file}> +#include + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + printf("%s takes no arguments.\\n", argv[0]); + return 1; + }} + return {function_name}(); +}} +''' + +lib_c_meson_template = '''project('{project_name}', 'c', + version : '{version}', + default_options : ['warning_level=3']) + +# These arguments are only used to build the shared library +# not the executables that use the library. +lib_args = ['-DBUILDING_{utoken}'] + +shlib = shared_library('{lib_name}', '{source_file}', + install : true, + c_args : lib_args, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) + +# Make this library usable from the system's +# package manager. +install_headers('{header_file}', subdir : '{header_dir}') + +pkg_mod = import('pkgconfig') +pkg_mod.generate( + name : '{project_name}', + filebase : '{ltoken}', + description : 'Meson sample project.', + subdirs : '{header_dir}', + libraries : shlib, + version : '{version}', +) +''' + +hello_c_template = '''#include + +#define PROJECT_NAME "{project_name}" + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + printf("%s takes no arguments.\\n", argv[0]); + return 1; + }} + printf("This is project %s.\\n", PROJECT_NAME); + return 0; +}} +''' + +hello_c_meson_template = '''project('{project_name}', 'c', + version : '{version}', + default_options : ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + + +class CProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.c' + open(source_name, 'w', encoding='utf-8').write(hello_c_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_c_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + function_name = lowercase_token[0:3] + '_func' + test_exe_name = lowercase_token + '_test' + lib_h_name = lowercase_token + '.h' + lib_c_name = lowercase_token + '.c' + test_c_name = lowercase_token + '_test.c' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'function_name': function_name, + 'header_file': lib_h_name, + 'source_file': lib_c_name, + 'test_source_file': test_c_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) + open(lib_c_name, 'w', encoding='utf-8').write(lib_c_template.format(**kwargs)) + open(test_c_name, 'w', encoding='utf-8').write(lib_c_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_c_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/cudatemplates.py b/devtools/meson/mesonbuild/templates/cudatemplates.py new file mode 100644 index 0000000..63abd2b --- /dev/null +++ b/devtools/meson/mesonbuild/templates/cudatemplates.py @@ -0,0 +1,187 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +hello_cuda_template = '''#include + +#define PROJECT_NAME "{project_name}" + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + std::cout << argv[0] << " takes no arguments.\\n"; + return 1; + }} + std::cout << "This is project " << PROJECT_NAME << ".\\n"; + return 0; +}} +''' + +hello_cuda_meson_template = '''project('{project_name}', ['cuda', 'cpp'], + version : '{version}', + default_options : ['warning_level=3', + 'cpp_std=c++14']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + +lib_h_template = '''#pragma once +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __declspec(dllexport) + #else + #define {utoken}_PUBLIC __declspec(dllimport) + #endif +#else + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) + #else + #define {utoken}_PUBLIC + #endif +#endif + +namespace {namespace} {{ + +class {utoken}_PUBLIC {class_name} {{ + +public: + {class_name}(); + int get_number() const; + +private: + + int number; + +}}; + +}} + +''' + +lib_cuda_template = '''#include <{header_file}> + +namespace {namespace} {{ + +{class_name}::{class_name}() {{ + number = 6; +}} + +int {class_name}::get_number() const {{ + return number; +}} + +}} +''' + +lib_cuda_test_template = '''#include <{header_file}> +#include + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + std::cout << argv[0] << " takes no arguments.\\n"; + return 1; + }} + {namespace}::{class_name} c; + return c.get_number() != 6; +}} +''' + +lib_cuda_meson_template = '''project('{project_name}', ['cuda', 'cpp'], + version : '{version}', + default_options : ['warning_level=3']) + +# These arguments are only used to build the shared library +# not the executables that use the library. +lib_args = ['-DBUILDING_{utoken}'] + +shlib = shared_library('{lib_name}', '{source_file}', + install : true, + cpp_args : lib_args, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) + +# Make this library usable from the system's +# package manager. +install_headers('{header_file}', subdir : '{header_dir}') + +pkg_mod = import('pkgconfig') +pkg_mod.generate( + name : '{project_name}', + filebase : '{ltoken}', + description : 'Meson sample project.', + subdirs : '{header_dir}', + libraries : shlib, + version : '{version}', +) +''' + + +class CudaProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.cu' + open(source_name, 'w', encoding='utf-8').write(hello_cuda_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_cuda_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + test_exe_name = lowercase_token + '_test' + namespace = lowercase_token + lib_h_name = lowercase_token + '.h' + lib_cuda_name = lowercase_token + '.cu' + test_cuda_name = lowercase_token + '_test.cu' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'class_name': class_name, + 'namespace': namespace, + 'header_file': lib_h_name, + 'source_file': lib_cuda_name, + 'test_source_file': test_cuda_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) + open(lib_cuda_name, 'w', encoding='utf-8').write(lib_cuda_template.format(**kwargs)) + open(test_cuda_name, 'w', encoding='utf-8').write(lib_cuda_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_cuda_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/dlangtemplates.py b/devtools/meson/mesonbuild/templates/dlangtemplates.py new file mode 100644 index 0000000..81840fe --- /dev/null +++ b/devtools/meson/mesonbuild/templates/dlangtemplates.py @@ -0,0 +1,145 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +hello_d_template = '''module main; +import std.stdio; + +enum PROJECT_NAME = "{project_name}"; + +int main(string[] args) {{ + if (args.length != 1){{ + writefln("%s takes no arguments.\\n", args[0]); + return 1; + }} + writefln("This is project %s.\\n", PROJECT_NAME); + return 0; +}} +''' + +hello_d_meson_template = '''project('{project_name}', 'd', + version : '{version}', + default_options: ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + +lib_d_template = '''module {module_file}; + +/* This function will not be exported and is not + * directly callable by users of this library. + */ +int internal_function() {{ + return 0; +}} + +int {function_name}() {{ + return internal_function(); +}} +''' + +lib_d_test_template = '''module {module_file}_test; +import std.stdio; +import {module_file}; + + +int main(string[] args) {{ + if (args.length != 1){{ + writefln("%s takes no arguments.\\n", args[0]); + return 1; + }} + return {function_name}(); +}} +''' + +lib_d_meson_template = '''project('{project_name}', 'd', + version : '{version}', + default_options : ['warning_level=3']) + +stlib = static_library('{lib_name}', '{source_file}', + install : true, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : stlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : stlib) + +# Make this library usable from the Dlang +# build system. +dlang_mod = import('dlang') +if find_program('dub', required: false).found() + dlang_mod.generate_dub_file(meson.project_name().to_lower(), meson.source_root(), + name : meson.project_name(), + license: meson.project_license(), + sourceFiles : '{source_file}', + description : 'Meson sample project.', + version : '{version}', + ) +endif +''' + + +class DlangProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.d' + open(source_name, 'w', encoding='utf-8').write(hello_d_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_d_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + function_name = lowercase_token[0:3] + '_func' + test_exe_name = lowercase_token + '_test' + lib_m_name = lowercase_token + lib_d_name = lowercase_token + '.d' + test_d_name = lowercase_token + '_test.d' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'function_name': function_name, + 'module_file': lib_m_name, + 'source_file': lib_d_name, + 'test_source_file': test_d_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_d_name, 'w', encoding='utf-8').write(lib_d_template.format(**kwargs)) + open(test_d_name, 'w', encoding='utf-8').write(lib_d_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_d_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/fortrantemplates.py b/devtools/meson/mesonbuild/templates/fortrantemplates.py new file mode 100644 index 0000000..00cd509 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/fortrantemplates.py @@ -0,0 +1,142 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + +lib_fortran_template = ''' +! This procedure will not be exported and is not +! directly callable by users of this library. + +module modfoo + +implicit none +private +public :: {function_name} + +contains + +integer function internal_function() + internal_function = 0 +end function internal_function + +integer function {function_name}() + {function_name} = internal_function() +end function {function_name} + +end module modfoo +''' + +lib_fortran_test_template = ''' +use modfoo + +print *,{function_name}() + +end program +''' + +lib_fortran_meson_template = '''project('{project_name}', 'fortran', + version : '{version}', + default_options : ['warning_level=3']) + +# These arguments are only used to build the shared library +# not the executables that use the library. +lib_args = ['-DBUILDING_{utoken}'] + +shlib = shared_library('{lib_name}', '{source_file}', + install : true, + fortran_args : lib_args, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) + +pkg_mod = import('pkgconfig') +pkg_mod.generate( + name : '{project_name}', + filebase : '{ltoken}', + description : 'Meson sample project.', + subdirs : '{header_dir}', + libraries : shlib, + version : '{version}', +) +''' + +hello_fortran_template = ''' +implicit none + +character(len=*), parameter :: PROJECT_NAME = "{project_name}" + +print *,"This is project ", PROJECT_NAME + +end program +''' + +hello_fortran_meson_template = '''project('{project_name}', 'fortran', + version : '{version}', + default_options : ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + + +class FortranProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.f90' + open(source_name, 'w', encoding='utf-8').write(hello_fortran_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_fortran_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + function_name = lowercase_token[0:3] + '_func' + test_exe_name = lowercase_token + '_test' + lib_fortran_name = lowercase_token + '.f90' + test_fortran_name = lowercase_token + '_test.f90' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'function_name': function_name, + 'source_file': lib_fortran_name, + 'test_source_file': test_fortran_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_fortran_name, 'w', encoding='utf-8').write(lib_fortran_template.format(**kwargs)) + open(test_fortran_name, 'w', encoding='utf-8').write(lib_fortran_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_fortran_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/javatemplates.py b/devtools/meson/mesonbuild/templates/javatemplates.py new file mode 100644 index 0000000..58d48ba --- /dev/null +++ b/devtools/meson/mesonbuild/templates/javatemplates.py @@ -0,0 +1,138 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +hello_java_template = ''' + +public class {class_name} {{ + final static String PROJECT_NAME = "{project_name}"; + + public static void main (String args[]) {{ + if(args.length != 0) {{ + System.out.println(args + " takes no arguments."); + System.exit(0); + }} + System.out.println("This is project " + PROJECT_NAME + "."); + System.exit(0); + }} +}} + +''' + +hello_java_meson_template = '''project('{project_name}', 'java', + version : '{version}', + default_options : ['warning_level=3']) + +exe = jar('{exe_name}', '{source_name}', + main_class : '{exe_name}', + install : true) + +test('basic', exe) +''' + +lib_java_template = ''' + +public class {class_name} {{ + final static int number = 6; + + public final int get_number() {{ + return number; + }} +}} + +''' + +lib_java_test_template = ''' + +public class {class_test} {{ + public static void main (String args[]) {{ + if(args.length != 0) {{ + System.out.println(args + " takes no arguments."); + System.exit(1); + }} + + {class_name} c = new {class_name}(); + Boolean result = true; + System.exit(result.compareTo(c.get_number() != 6)); + }} +}} + +''' + +lib_java_meson_template = '''project('{project_name}', 'java', + version : '{version}', + default_options : ['warning_level=3']) + +jarlib = jar('{class_name}', '{source_file}', + main_class : '{class_name}', + install : true, +) + +test_jar = jar('{class_test}', '{test_source_file}', + main_class : '{class_test}', + link_with : jarlib) +test('{test_name}', test_jar) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : jarlib) +''' + + +class JavaProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + source_name = uppercase_token[0] + lowercase_token[1:] + '.java' + open(source_name, 'w', encoding='utf-8').write( + hello_java_template.format(project_name=self.name, + class_name=class_name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_java_meson_template.format(project_name=self.name, + exe_name=class_name, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + class_test = uppercase_token[0] + lowercase_token[1:] + '_test' + lib_java_name = uppercase_token[0] + lowercase_token[1:] + '.java' + test_java_name = uppercase_token[0] + lowercase_token[1:] + '_test.java' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'class_test': class_test, + 'class_name': class_name, + 'source_file': lib_java_name, + 'test_source_file': test_java_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_java_name, 'w', encoding='utf-8').write(lib_java_template.format(**kwargs)) + open(test_java_name, 'w', encoding='utf-8').write(lib_java_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_java_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/mesontemplates.py b/devtools/meson/mesonbuild/templates/mesontemplates.py new file mode 100644 index 0000000..2868f7b --- /dev/null +++ b/devtools/meson/mesonbuild/templates/mesontemplates.py @@ -0,0 +1,77 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import argparse + +meson_executable_template = '''project('{project_name}', {language}, + version : '{version}', + default_options : [{default_options}]) + +executable('{executable}', + {sourcespec},{depspec} + install : true) +''' + + +meson_jar_template = '''project('{project_name}', '{language}', + version : '{version}', + default_options : [{default_options}]) + +jar('{executable}', + {sourcespec},{depspec} + main_class: '{main_class}', + install : true) +''' + + +def create_meson_build(options: argparse.Namespace) -> None: + if options.type != 'executable': + raise SystemExit('\nGenerating a meson.build file from existing sources is\n' + 'supported only for project type "executable".\n' + 'Run meson init in an empty directory to create a sample project.') + default_options = ['warning_level=3'] + if options.language == 'cpp': + # This shows how to set this very common option. + default_options += ['cpp_std=c++14'] + # If we get a meson.build autoformatter one day, this code could + # be simplified quite a bit. + formatted_default_options = ', '.join(f"'{x}'" for x in default_options) + sourcespec = ',\n '.join(f"'{x}'" for x in options.srcfiles) + depspec = '' + if options.deps: + depspec = '\n dependencies : [\n ' + depspec += ',\n '.join(f"dependency('{x}')" + for x in options.deps.split(',')) + depspec += '],' + if options.language != 'java': + language = f"'{options.language}'" if options.language != 'vala' else ['c', 'vala'] + content = meson_executable_template.format(project_name=options.name, + language=language, + version=options.version, + executable=options.executable, + sourcespec=sourcespec, + depspec=depspec, + default_options=formatted_default_options) + else: + content = meson_jar_template.format(project_name=options.name, + language=options.language, + version=options.version, + executable=options.executable, + main_class=options.name, + sourcespec=sourcespec, + depspec=depspec, + default_options=formatted_default_options) + open('meson.build', 'w', encoding='utf-8').write(content) + print('Generated meson.build file:\n\n' + content) diff --git a/devtools/meson/mesonbuild/templates/objcpptemplates.py b/devtools/meson/mesonbuild/templates/objcpptemplates.py new file mode 100644 index 0000000..450f2b0 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/objcpptemplates.py @@ -0,0 +1,168 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +lib_h_template = '''#pragma once +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __declspec(dllexport) + #else + #define {utoken}_PUBLIC __declspec(dllimport) + #endif +#else + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) + #else + #define {utoken}_PUBLIC + #endif +#endif + +int {utoken}_PUBLIC {function_name}(); + +''' + +lib_objcpp_template = '''#import <{header_file}> + +/* This function will not be exported and is not + * directly callable by users of this library. + */ +int internal_function() {{ + return 0; +}} + +int {function_name}() {{ + return internal_function(); +}} +''' + +lib_objcpp_test_template = '''#import <{header_file}> +#import + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + std::cout << argv[0] << " takes no arguments." << std::endl; + return 1; + }} + return {function_name}(); +}} +''' + +lib_objcpp_meson_template = '''project('{project_name}', 'objcpp', + version : '{version}', + default_options : ['warning_level=3']) + +# These arguments are only used to build the shared library +# not the executables that use the library. +lib_args = ['-DBUILDING_{utoken}'] + +shlib = shared_library('{lib_name}', '{source_file}', + install : true, + objcpp_args : lib_args, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) + +# Make this library usable from the system's +# package manager. +install_headers('{header_file}', subdir : '{header_dir}') + +pkg_mod = import('pkgconfig') +pkg_mod.generate( + name : '{project_name}', + filebase : '{ltoken}', + description : 'Meson sample project.', + subdirs : '{header_dir}', + libraries : shlib, + version : '{version}', +) +''' + +hello_objcpp_template = '''#import + +#define PROJECT_NAME "{project_name}" + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + std::cout << argv[0] << " takes no arguments." << std::endl; + return 1; + }} + std::cout << "This is project " << PROJECT_NAME << "." << std::endl; + return 0; +}} +''' + +hello_objcpp_meson_template = '''project('{project_name}', 'objcpp', + version : '{version}', + default_options : ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + + +class ObjCppProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.mm' + open(source_name, 'w', encoding='utf-8').write(hello_objcpp_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_objcpp_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + function_name = lowercase_token[0:3] + '_func' + test_exe_name = lowercase_token + '_test' + lib_h_name = lowercase_token + '.h' + lib_objcpp_name = lowercase_token + '.mm' + test_objcpp_name = lowercase_token + '_test.mm' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'function_name': function_name, + 'header_file': lib_h_name, + 'source_file': lib_objcpp_name, + 'test_source_file': test_objcpp_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) + open(lib_objcpp_name, 'w', encoding='utf-8').write(lib_objcpp_template.format(**kwargs)) + open(test_objcpp_name, 'w', encoding='utf-8').write(lib_objcpp_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_objcpp_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/objctemplates.py b/devtools/meson/mesonbuild/templates/objctemplates.py new file mode 100644 index 0000000..2e03526 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/objctemplates.py @@ -0,0 +1,168 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +lib_h_template = '''#pragma once +#if defined _WIN32 || defined __CYGWIN__ + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __declspec(dllexport) + #else + #define {utoken}_PUBLIC __declspec(dllimport) + #endif +#else + #ifdef BUILDING_{utoken} + #define {utoken}_PUBLIC __attribute__ ((visibility ("default"))) + #else + #define {utoken}_PUBLIC + #endif +#endif + +int {utoken}_PUBLIC {function_name}(); + +''' + +lib_objc_template = '''#import <{header_file}> + +/* This function will not be exported and is not + * directly callable by users of this library. + */ +int internal_function() {{ + return 0; +}} + +int {function_name}() {{ + return internal_function(); +}} +''' + +lib_objc_test_template = '''#import <{header_file}> +#import + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + printf("%s takes no arguments.\\n", argv[0]); + return 1; + }} + return {function_name}(); +}} +''' + +lib_objc_meson_template = '''project('{project_name}', 'objc', + version : '{version}', + default_options : ['warning_level=3']) + +# These arguments are only used to build the shared library +# not the executables that use the library. +lib_args = ['-DBUILDING_{utoken}'] + +shlib = shared_library('{lib_name}', '{source_file}', + install : true, + objc_args : lib_args, + gnu_symbol_visibility : 'hidden', +) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) + +# Make this library usable from the system's +# package manager. +install_headers('{header_file}', subdir : '{header_dir}') + +pkg_mod = import('pkgconfig') +pkg_mod.generate( + name : '{project_name}', + filebase : '{ltoken}', + description : 'Meson sample project.', + subdirs : '{header_dir}', + libraries : shlib, + version : '{version}', +) +''' + +hello_objc_template = '''#import + +#define PROJECT_NAME "{project_name}" + +int main(int argc, char **argv) {{ + if(argc != 1) {{ + printf("%s takes no arguments.\\n", argv[0]); + return 1; + }} + printf("This is project %s.\\n", PROJECT_NAME); + return 0; +}} +''' + +hello_objc_meson_template = '''project('{project_name}', 'objc', + version : '{version}', + default_options : ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + + +class ObjCProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.m' + open(source_name, 'w', encoding='utf-8').write(hello_objc_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_objc_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + function_name = lowercase_token[0:3] + '_func' + test_exe_name = lowercase_token + '_test' + lib_h_name = lowercase_token + '.h' + lib_objc_name = lowercase_token + '.m' + test_objc_name = lowercase_token + '_test.m' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'function_name': function_name, + 'header_file': lib_h_name, + 'source_file': lib_objc_name, + 'test_source_file': test_objc_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) + open(lib_objc_name, 'w', encoding='utf-8').write(lib_objc_template.format(**kwargs)) + open(test_objc_name, 'w', encoding='utf-8').write(lib_objc_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_objc_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/rusttemplates.py b/devtools/meson/mesonbuild/templates/rusttemplates.py new file mode 100644 index 0000000..0dde547 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/rusttemplates.py @@ -0,0 +1,115 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +lib_rust_template = '''#![crate_name = "{crate_file}"] + +/* This function will not be exported and is not + * directly callable by users of this library. + */ +fn internal_function() -> i32 {{ + return 0; +}} + +pub fn {function_name}() -> i32 {{ + return internal_function(); +}} +''' + +lib_rust_test_template = '''extern crate {crate_file}; + +fn main() {{ + println!("printing: {{}}", {crate_file}::{function_name}()); +}} +''' + + +lib_rust_meson_template = '''project('{project_name}', 'rust', + version : '{version}', + default_options : ['warning_level=3']) + +shlib = static_library('{lib_name}', '{source_file}', install : true) + +test_exe = executable('{test_exe_name}', '{test_source_file}', + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) +''' + +hello_rust_template = ''' +fn main() {{ + let project_name = "{project_name}"; + println!("This is project {{}}.\\n", project_name); +}} +''' + +hello_rust_meson_template = '''project('{project_name}', 'rust', + version : '{version}', + default_options : ['warning_level=3']) + +exe = executable('{exe_name}', '{source_name}', + install : true) + +test('basic', exe) +''' + + +class RustProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.rs' + open(source_name, 'w', encoding='utf-8').write(hello_rust_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_rust_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + function_name = lowercase_token[0:3] + '_func' + test_exe_name = lowercase_token + '_test' + lib_crate_name = lowercase_token + lib_rs_name = lowercase_token + '.rs' + test_rs_name = lowercase_token + '_test.rs' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'function_name': function_name, + 'crate_file': lib_crate_name, + 'source_file': lib_rs_name, + 'test_source_file': test_rs_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_rs_name, 'w', encoding='utf-8').write(lib_rust_template.format(**kwargs)) + open(test_rs_name, 'w', encoding='utf-8').write(lib_rust_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_rust_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/templates/samplefactory.py b/devtools/meson/mesonbuild/templates/samplefactory.py new file mode 100644 index 0000000..1950837 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/samplefactory.py @@ -0,0 +1,44 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.valatemplates import ValaProject +from mesonbuild.templates.fortrantemplates import FortranProject +from mesonbuild.templates.objcpptemplates import ObjCppProject +from mesonbuild.templates.dlangtemplates import DlangProject +from mesonbuild.templates.rusttemplates import RustProject +from mesonbuild.templates.javatemplates import JavaProject +from mesonbuild.templates.cudatemplates import CudaProject +from mesonbuild.templates.objctemplates import ObjCProject +from mesonbuild.templates.cpptemplates import CppProject +from mesonbuild.templates.cstemplates import CSharpProject +from mesonbuild.templates.ctemplates import CProject +from mesonbuild.templates.sampleimpl import SampleImpl + +import argparse + +def sameple_generator(options: argparse.Namespace) -> SampleImpl: + return { + 'c': CProject, + 'cpp': CppProject, + 'cs': CSharpProject, + 'cuda': CudaProject, + 'objc': ObjCProject, + 'objcpp': ObjCppProject, + 'java': JavaProject, + 'd': DlangProject, + 'rust': RustProject, + 'fortran': FortranProject, + 'vala': ValaProject + }[options.language](options) diff --git a/devtools/meson/mesonbuild/templates/sampleimpl.py b/devtools/meson/mesonbuild/templates/sampleimpl.py new file mode 100644 index 0000000..9702ae8 --- /dev/null +++ b/devtools/meson/mesonbuild/templates/sampleimpl.py @@ -0,0 +1,22 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +class SampleImpl: + def create_executable(self) -> None: + raise NotImplementedError('Sample implementation for "executable" not implemented!') + + def create_library(self) -> None: + raise NotImplementedError('Sample implementation for "library" not implemented!') diff --git a/devtools/meson/mesonbuild/templates/valatemplates.py b/devtools/meson/mesonbuild/templates/valatemplates.py new file mode 100644 index 0000000..ef9794d --- /dev/null +++ b/devtools/meson/mesonbuild/templates/valatemplates.py @@ -0,0 +1,125 @@ +# Copyright 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from mesonbuild.templates.sampleimpl import SampleImpl +import re + + +hello_vala_template = '''void main (string[] args) {{ + stdout.printf ("Hello {project_name}!\\n"); +}} +''' + +hello_vala_meson_template = '''project('{project_name}', ['c', 'vala'], + version : '{version}') + +dependencies = [ + dependency('glib-2.0'), + dependency('gobject-2.0'), +] + +exe = executable('{exe_name}', '{source_name}', dependencies : dependencies, + install : true) + +test('basic', exe) +''' + + +lib_vala_template = '''namespace {namespace} {{ + public int sum(int a, int b) {{ + return(a + b); + }} + + public int square(int a) {{ + return(a * a); + }} +}} +''' + +lib_vala_test_template = '''using {namespace}; + +public void main() {{ + stdout.printf("\nTesting shlib"); + stdout.printf("\n\t2 + 3 is %d", sum(2, 3)); + stdout.printf("\n\t8 squared is %d\\n", square(8)); +}} +''' + +lib_vala_meson_template = '''project('{project_name}', ['c', 'vala'], + version : '{version}') + +dependencies = [ + dependency('glib-2.0'), + dependency('gobject-2.0'), +] + +# These arguments are only used to build the shared library +# not the executables that use the library. +shlib = shared_library('foo', '{source_file}', + dependencies: dependencies, + install: true, + install_dir: [true, true, true]) + +test_exe = executable('{test_exe_name}', '{test_source_file}', dependencies : dependencies, + link_with : shlib) +test('{test_name}', test_exe) + +# Make this library usable as a Meson subproject. +{ltoken}_dep = declare_dependency( + include_directories: include_directories('.'), + link_with : shlib) +''' + + +class ValaProject(SampleImpl): + def __init__(self, options): + super().__init__() + self.name = options.name + self.version = options.version + + def create_executable(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + source_name = lowercase_token + '.vala' + open(source_name, 'w', encoding='utf-8').write(hello_vala_template.format(project_name=self.name)) + open('meson.build', 'w', encoding='utf-8').write( + hello_vala_meson_template.format(project_name=self.name, + exe_name=lowercase_token, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + uppercase_token = lowercase_token.upper() + class_name = uppercase_token[0] + lowercase_token[1:] + test_exe_name = lowercase_token + '_test' + namespace = lowercase_token + lib_vala_name = lowercase_token + '.vala' + test_vala_name = lowercase_token + '_test.vala' + kwargs = {'utoken': uppercase_token, + 'ltoken': lowercase_token, + 'header_dir': lowercase_token, + 'class_name': class_name, + 'namespace': namespace, + 'source_file': lib_vala_name, + 'test_source_file': test_vala_name, + 'test_exe_name': test_exe_name, + 'project_name': self.name, + 'lib_name': lowercase_token, + 'test_name': lowercase_token, + 'version': self.version, + } + open(lib_vala_name, 'w', encoding='utf-8').write(lib_vala_template.format(**kwargs)) + open(test_vala_name, 'w', encoding='utf-8').write(lib_vala_test_template.format(**kwargs)) + open('meson.build', 'w', encoding='utf-8').write(lib_vala_meson_template.format(**kwargs)) diff --git a/devtools/meson/mesonbuild/utils/__init__.py b/devtools/meson/mesonbuild/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/devtools/meson/mesonbuild/utils/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/utils/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23bbee241e7c07b3ae6b8da2d52de1a79b44de29 GIT binary patch literal 157 zcmZ?b<>g`kf;}G&r-A6lAOZ#$feZ&AE@lA|DGb33nv8xc8Hzx{2;!HUi&acYYFSKr zeojhpQF2U1j$ur3N_ISm4HPfQ&(A52$xSWJ&x4RjrI|S?F{LG$K;iiK%)HE!_;|g7 V%3B;Zx%nxjIjMFa^FISI0|2LTDlY&4 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/utils/__pycache__/core.cpython-37.pyc b/devtools/meson/mesonbuild/utils/__pycache__/core.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..854b38c19fff22490c3411150feda9c2f48a4be0 GIT binary patch literal 6929 zcmcIp-EZ6073a5T$se-g#&+VQ>_kogc{b4~-{!S0Qp9SD!rL4r3swhmUDokZspfYs8&-GU1>iivr6C5VeBMZ+=&xW_YCbg$Fq2vMD?B%Tr_@wtv$3a> zRfC&YDKdx~I3#ETg0g<67)rGOVNIr!lB>7&eBLBpw$JoIlAeg3gwDo(#`=|to*K1! zz*8%zhdhi@(~kn&tY~AK`$>Chb@{&B#S6ZM)Yk_lAj0*Eks6-Zj0KsLDA6#E!H4xI zIxZ6zaiu_qeH}oe94Omr$M{ZBm5$m`T&<&F)H^yxgDE(Ix>7MyGj2gLsqMPZvcz?V zJ^&0O=0R;}T1?^-Bq-OFVshO-EC0NH^XeMoyK9?Kz+&OAZ3S1>Vz%QFjQJ#rf_SY# zs+f%%t$M)LT1g$#ekAyEb6=FP@7uUy8-t>as}}y+bAzm2?h{)8Qbm{4q(%r$NG-vW zmIx(dddwj$xI>JY2hdT#2z47w0ejSKXv1^;I~DBE+JCtL#Z0*4Wm4wI*hFupPDCl3 z`3OQ^dr_SgP4Me93~601u)adc7d`@FY+xV*Zl8I9#eMq)u`4STOPryd z&(c806X$3k)e*1KFj_qvEPaS8Cf1O8D5{{j0p%bMAkz%mZ9q9RVpTeM7rx3vh`OKo z;hJ-^)oAP^bjBP~MgWqri=t`fsYxXuYu|%&Keom#PJ-VDcPZX-(S#*)u}r(wmIQd*-Q>={V0#=d1;2C)fo^9kUgngRL;b{!v(PHyh zU0`SMT$EoyPR7p4pt|_nVCUHRr)IS@V&zrlU}b#7%4_U(tW5Ap_C~(fo48+iZn2B( zk_^OCBi1gnid-v?SbK}TE!U>myKITQiGANeSYKv8!FOgDx&JHa?5%LOE~2o(!{jSZ z)JZR5vSFUI7f%Fepxr~P{K^Yje09Ic*V`BJ#N_MCmw>H*ym z&%_rA0((b0(7MLn`yKVrI8tsZ>zCKGuGzH`vtuRJfhMkXtkCFKn`*bvF*;_a(9sWc zRe5~zQRY055){$`4|jJx5sQoXP-+7tw;rd3O{iRwh}1+H)`-($J?_P&)ClTvQn52f zL0(%_Xm|@lbxfYH)(U;ZXzY}l^606$du-a7%O@+niz}w|LeVVE)(o|%&Zx6$``jq$ z9D5QqV;C7c{WM&}JjpO(B~!Zy_lIEDHiAAz{fJzEw$d(M`}W=LRp;9)-H%8tGD%Ic zI3)cNr6Uzho-DN?R^h^l4^d80Q7*Zwz|MT1YP_823|A0^6)m;4kl*rLwehOf%@*zXVcDxvU~3J%jPI+FlqbZNg8D4J48f z$Q8Vj3BAWMy3-|DMuCbF-)&{bf}o+8=wdjy;x$%{TJ6v&KFE)MAr zeYUSZ*YL3S0j0grm!&nMt9A9R(KX2$4xt%RPe9|Lp5+rAvzFTUbr4Jk68Bk$!+&z_8#=>WU<;lio+bb9E^ zg94Nua|iF_9sq}$A9*Nj*!S)Kb9xJIE|}a5|2@fc#Atxzvm;5)_Wb`*ZM%8Q{85}v z3psW?K>FfH(sR^yd3E_F8Y-kjOVnH$EVF5%Vx>9{cZc*VonXA?wSvTzfh%)56praf zcOBQU)6owRh>s|zAg7ZW+fhA44!r`Tp^e3Tnj6xgpJVO`uFU+km$*XG$$o`E>P~7T zX&|ekSOEn$ju8GkI+WjJ%8o4-J6dRW%uT5N93n|Zp_c0KCE@{IgDJm^%GB^%VmR!H zPw~>XxQ?^^(Gtit^1mclBa%-LEPjDc{wIRP7lbs#TWSOS2G=pYFG(wMl}RUZg}N_D zb7Ya-Ld^;tNlQJYs5O#IB}fhEN0n>e^^!O#@iPG7n6-hxn2P zDMiYpevHCV74=(OF@;P;wc(9t)Ooc%T9kPLK)QWusEA3m2w7s&OSX{4W(C{_*in2! z!wnj4(r}Lka?FB!kN6xzI*$HEQup)dK|GVXB}ia`2s|N4DN~Bq;sOTRLsrGMs;P^m zNuz9+^+~;Ko-yce(O5JWO^JCM#;Ebf6k7W~5}B-*eh;8mFMWwTiK9h$O<{V~UGJx*=jF5T@j9Q`Dh*X(sCpn|%t&`iSQbEz%tou6wXVs~Ar`~kyHJ9-? z!FQ^~xU~UpQO_2ovDkOfJjXYuvGWN9mANE(Tfpj-BGMDSeHFXSibGU(vLY zkPZE5f^aI1Y|l{huht^@fdb+%bh_8G=dmEO5|1z-Q{3=VE7_-iC#33Xbz=2b4{o_P z?%ulb>AjUZ)dHpTL48A(Le=RE&*jj=Fh)~77AEaoXrL;Nk>Qe86^sU(=FKldAXN?W z%~^GAySc*_4++7bq_JAY+(5;ij`e$dvY{v(Ag6^-uHX0^C9Z6-NRJ^;Jc?bZeJyK! ieng#B*>E?|>l%mi#GhvMc&DA$&gs5ciggrkts^=C(X5yn5AS0}V}NJTT(|pBMf(@Do#3p@;XA zQmd+%Aw73WPizY4--&$y$KUt++asyYMpL7uv*XdRem!#XRA3DE-Wcsh4M)2-`bV`d z;d-tMKQVSTn4gDKh_WiZ5YGYCHBHfr&1H`Vi;9feE)zuUuMaeMHfRX)loeKDgm>F4XjC(?Sstet|*oR2-2)E6%JE_+2kGbc-L-H?6j}$mS5H$5WcJ H9!vN?#m4nZ literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/utils/__pycache__/universal.cpython-37.pyc b/devtools/meson/mesonbuild/utils/__pycache__/universal.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc6599bfd4da2f1d9c44f7b4382b93a9e2d15ed2 GIT binary patch literal 72554 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%0D^DNl2MF(clLP2bFOOaIQSF*>GRG}VH* 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 N#D=l=dkz-2{~xuY+RXp} literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/utils/__pycache__/vsenv.cpython-37.pyc b/devtools/meson/mesonbuild/utils/__pycache__/vsenv.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00d8af4ccca4ea41e36596f670828a49096b926c GIT binary patch literal 2799 zcmahLO^@5gl|zvfMSZNiUOVuu>ry5jI>-) zq&zd+4}~g%Y_0+JQ1sFkkdFNeMQ{BVbM47DAA_9whEx?Bg%Jt!=FOWo?{nT8epW79 z3jF@{^56YGRu$zxa`C^P2FOFDs<1x;f)$JcWrS>mB(4Ukt)_F%&ZVQp7T!6pzHx(Cg>3hw- zf>)N53eJD8+pAdZDD~`F z5|+=LQ$NJfDHH1p#KD9Uk2@gu3RY0!l;k+6n=)jdI>{~7=d7$)``zEaLa#es8 zU9K!xeVeW_t;IPS|7Br8X^y6d8?$_ZaCxpy)kK|{bA|nr7jPv}|Em05y+Gd~Zq16k zlmHItsp2bm6<>w1hOgo4_$_<`-yD=dQjV8rl_Uq4mT2rpkg=Ygmhv@x>!yO=zNx^j z&Q~rJe0!)~BKq4z$9HZiQzJ2?=1asL1LdxygzJFS{%`MBuTgMnsj;-QI=g~57TSId z8h-;CRk(2PO!Itob~Q1QJostywc~5}UHl$?A0u4ug`8_1X=swhuqZSX!f?Gr)R9$ZTunlR>WvpIy+8^+sfC6({fTy^5CaR z4Sa7}xB_zmUe^?UXK2CMZ3I>zeX-SYdY#s8 zPvXv(yF1-(tJAehz0S^Vr~ByfQ^N};SDw;n zK;2Q>4+wkz?7{uIU3!%?X*}^g8nLL)YdxREZcyv+82i!YPRKaa5TTnV?DU9GA~j7` zwxT$|HK^uVAIh^f$u|O*6UHaS#+U+EKwL&9r3NL>W1kZCC_JAOmaEA}OLfgmU8b$M z6^+JGNJ8H1Z8f`4qO1wVHqY*VJgL9o$bLkJLFD4*{&wpObTbBu#x%mQ$C*I)CVC_0 z{Rdznl={f!LOX^QGuimrgRx5)slDP}EsFU#=2UhAyXt2VNZZy^mmk@>OGjYPMsI8L zQGDhHzDv(HKa2eUZ=QH3AS~T)9=d$;?i+c)EofaJC*`~QM!p5ZF9;gp1z-7*2VD_t z4F|PeN8~*hvKI~PYm10%`)nMz=RHCh^jFAMqtSW#c&7`qK&KNewMK`4H6B1aHdx&6 z`)9%=p%-D0DGUs$<)jO(b2Sd3|AM!H6Oz-w4+*1JAz}hqKcU}K9nkt+nwJzcVj>T% z*{9Ica|6Ob@=?tFKx@2bT)z?mg9J0_S6DQD6pp$*Tz4lp@67(@ZY)H^r| zK007{=tvysT$bg*NIujVJd{`eK&F!&q%UxDd@f3$V)-QB1+nZBfPxI9p(+e3XCY06 zA@SFTdIOb^i7K#fAT|9#NryKud5jYl;%D^UUkT3Zyw2$J|oyRN79 zq}M*X#`#m1hER8O1B|Jw**!ue%~J+`2OG2i-~n4gZIBM0OUvZu0j03}r>Y57-6XiYOLO|S0%7xd>9%m4rY literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/utils/__pycache__/win32.cpython-37.pyc b/devtools/meson/mesonbuild/utils/__pycache__/win32.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..241cbd767520a4f20ef5967a8d82360be136eb0d GIT binary patch literal 1184 zcmZuwO>Y!A5VhSO(=(Zb2$moaTJ-@TO{5(OxFCd9yAvXIMVLi`<)bx{)!X(Yow(bB z?GDU{6L8&sz#%#EANIz-@Rbuc&S(!?)k9c>urxKVs_gRftLo9}YLCGB=i|HSzY!tt z(K%TmfM3Wuv10&&2&za$GfELN#WL3Z2U#cr5vr()vlw!Lh*YOavM%6wmu9`&M07;_ z8a&y36=aEE_sJmnfVT{&U&-rQyWEw!w&M?U8C<(7t**D97jlLP*w!C4r4qMFv!jax z158PQ1x{7~pryJAK$46K0`#b0Zzz&`9cDla{P+z6G70#h=mL#iTgr!HT}!wnHqtew zE|3N;{O`hV3ssl^aO4Hqr&w47e+MrJXY&g#I0_-kj-q4Yg8f*8#{ngeNWB>n*Kx^| z9rVmY3dJa%W=Gv)K&~gESM())LTdIH6a_Nz*wbf=sBzPut^=7w)`b>jy=(Awi{I|+ zN~YTFNt3qnq%)%nX>D5CG*?FEVxBe@_NQ(SLVuxPsVI#soHp}ey8XO#kR1+Ie5hx# z&iV?poR&(~c_n>v;`z9;hlO#zgAq94<93tw$<7@<9_?)1@uxGQMvZt<0tT^C^A?~zRc2eO4 zEN%OeN#jZgKP&5NSBJB??{Y3{Ck^L6LQUHTL+EMB=moGny4d)7V1{2dFQNy-U+ejR z`7k%T)^y<5mv%F7aI|h?yDtH7r+%{+s8zf;?(X60Z z1Ji2u=NL3Ir@&OEY?1u?W KSfBP;%>Dxs!7NSy literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/utils/core.py b/devtools/meson/mesonbuild/utils/core.py new file mode 100644 index 0000000..eee88b9 --- /dev/null +++ b/devtools/meson/mesonbuild/utils/core.py @@ -0,0 +1,161 @@ +# Copyright 2012-2022 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Contains the strict minimum to run scripts. + +When the backend needs to call back into Meson during compilation for running +scripts or wrapping commands, it is important to load as little python modules +as possible for performance reasons. +""" + +from __future__ import annotations +from dataclasses import dataclass +import os +import abc +import typing as T + +if T.TYPE_CHECKING: + from hashlib import _Hash + from typing_extensions import Literal + from ..mparser import BaseNode + from .. import programs + + EnvironOrDict = T.Union[T.Dict[str, str], os._Environ[str]] + + EnvInitValueType = T.Dict[str, T.Union[str, T.List[str]]] + + +class MesonException(Exception): + '''Exceptions thrown by Meson''' + + def __init__(self, *args: object, file: T.Optional[str] = None, + lineno: T.Optional[int] = None, colno: T.Optional[int] = None): + super().__init__(*args) + self.file = file + self.lineno = lineno + self.colno = colno + + @classmethod + def from_node(cls, *args: object, node: BaseNode) -> MesonException: + """Create a MesonException with location data from a BaseNode + + :param node: A BaseNode to set location data from + :return: A Meson Exception instance + """ + return cls(*args, file=node.filename, lineno=node.lineno, colno=node.colno) + +class MesonBugException(MesonException): + '''Exceptions thrown when there is a clear Meson bug that should be reported''' + + def __init__(self, msg: str, file: T.Optional[str] = None, + lineno: T.Optional[int] = None, colno: T.Optional[int] = None): + super().__init__(msg + '\n\n This is a Meson bug and should be reported!', + file=file, lineno=lineno, colno=colno) + +class HoldableObject(metaclass=abc.ABCMeta): + ''' Dummy base class for all objects that can be + held by an interpreter.baseobjects.ObjectHolder ''' + +class EnvironmentVariables(HoldableObject): + def __init__(self, values: T.Optional[EnvInitValueType] = None, + init_method: Literal['set', 'prepend', 'append'] = 'set', separator: str = os.pathsep) -> None: + self.envvars: T.List[T.Tuple[T.Callable[[T.Dict[str, str], str, T.List[str], str, T.Optional[str]], str], str, T.List[str], str]] = [] + # The set of all env vars we have operations for. Only used for self.has_name() + self.varnames: T.Set[str] = set() + + if values: + init_func = getattr(self, init_method) + for name, value in values.items(): + v = value if isinstance(value, list) else [value] + init_func(name, v, separator) + + def __repr__(self) -> str: + repr_str = "<{0}: {1}>" + return repr_str.format(self.__class__.__name__, self.envvars) + + def hash(self, hasher: _Hash) -> None: + myenv = self.get_env({}) + for key in sorted(myenv.keys()): + hasher.update(bytes(key, encoding='utf-8')) + hasher.update(b',') + hasher.update(bytes(myenv[key], encoding='utf-8')) + hasher.update(b';') + + def has_name(self, name: str) -> bool: + return name in self.varnames + + def get_names(self) -> T.Set[str]: + return self.varnames + + def merge(self, other: EnvironmentVariables) -> None: + for method, name, values, separator in other.envvars: + self.varnames.add(name) + self.envvars.append((method, name, values, separator)) + + def set(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + self.varnames.add(name) + self.envvars.append((self._set, name, values, separator)) + + def append(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + self.varnames.add(name) + self.envvars.append((self._append, name, values, separator)) + + def prepend(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + self.varnames.add(name) + self.envvars.append((self._prepend, name, values, separator)) + + @staticmethod + def _set(env: T.Dict[str, str], name: str, values: T.List[str], separator: str, default_value: T.Optional[str]) -> str: + return separator.join(values) + + @staticmethod + def _append(env: T.Dict[str, str], name: str, values: T.List[str], separator: str, default_value: T.Optional[str]) -> str: + curr = env.get(name, default_value) + return separator.join(values if curr is None else [curr] + values) + + @staticmethod + def _prepend(env: T.Dict[str, str], name: str, values: T.List[str], separator: str, default_value: T.Optional[str]) -> str: + curr = env.get(name, default_value) + return separator.join(values if curr is None else values + [curr]) + + def get_env(self, full_env: EnvironOrDict, default_fmt: T.Optional[str] = None) -> T.Dict[str, str]: + env = full_env.copy() + for method, name, values, separator in self.envvars: + default_value = default_fmt.format(name) if default_fmt else None + env[name] = method(env, name, values, separator, default_value) + return env + + +@dataclass(eq=False) +class ExecutableSerialisation: + + # XXX: should capture and feed default to False, instead of None? + + cmd_args: T.List[str] + env: T.Optional[EnvironmentVariables] = None + exe_wrapper: T.Optional['programs.ExternalProgram'] = None + workdir: T.Optional[str] = None + extra_paths: T.Optional[T.List] = None + capture: T.Optional[bool] = None + feed: T.Optional[bool] = None + tag: T.Optional[str] = None + verbose: bool = False + installdir_map: T.Optional[T.Dict[str, str]] = None + + def __post_init__(self) -> None: + self.pickled = False + self.skip_if_destdir = False + self.subproject = '' + self.dry_run = False diff --git a/devtools/meson/mesonbuild/utils/platform.py b/devtools/meson/mesonbuild/utils/platform.py new file mode 100644 index 0000000..4a3927d --- /dev/null +++ b/devtools/meson/mesonbuild/utils/platform.py @@ -0,0 +1,38 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright 2012-2021 The Meson development team +# Copyright © 2021 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""base classes providing no-op functionality..""" + +import os +import typing as T + +from .. import mlog + +__all__ = ['BuildDirLock'] + +# This needs to be inherited by the specific implementations to make type +# checking happy +class BuildDirLock: + + def __init__(self, builddir: str) -> None: + self.lockfilename = os.path.join(builddir, 'meson-private/meson.lock') + + def __enter__(self) -> None: + mlog.debug('Calling the no-op version of BuildDirLock') + + def __exit__(self, *args: T.Any) -> None: + pass diff --git a/devtools/meson/mesonbuild/utils/posix.py b/devtools/meson/mesonbuild/utils/posix.py new file mode 100644 index 0000000..51c3cd0 --- /dev/null +++ b/devtools/meson/mesonbuild/utils/posix.py @@ -0,0 +1,43 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright 2012-2021 The Meson development team +# Copyright © 2021 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Posix specific implementations of mesonlib functionality.""" + +import fcntl +import typing as T + +from .universal import MesonException +from .platform import BuildDirLock as BuildDirLockBase + +__all__ = ['BuildDirLock'] + +class BuildDirLock(BuildDirLockBase): + + def __enter__(self) -> None: + self.lockfile = open(self.lockfilename, 'w', encoding='utf-8') + try: + fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) + except (BlockingIOError, PermissionError): + self.lockfile.close() + raise MesonException('Some other Meson process is already using this build directory. Exiting.') + except OSError as e: + self.lockfile.close() + raise MesonException(f'Failed to lock the build directory: {e.strerror}') + + def __exit__(self, *args: T.Any) -> None: + fcntl.flock(self.lockfile, fcntl.LOCK_UN) + self.lockfile.close() diff --git a/devtools/meson/mesonbuild/utils/universal.py b/devtools/meson/mesonbuild/utils/universal.py new file mode 100644 index 0000000..5095658 --- /dev/null +++ b/devtools/meson/mesonbuild/utils/universal.py @@ -0,0 +1,2430 @@ +# Copyright 2012-2020 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A library of random helper functionality.""" + +from __future__ import annotations +from pathlib import Path +import argparse +import enum +import sys +import stat +import time +import abc +import platform, subprocess, operator, os, shlex, shutil, re +import collections +from functools import lru_cache, wraps, total_ordering +from itertools import tee +from tempfile import TemporaryDirectory, NamedTemporaryFile +import typing as T +import textwrap +import copy +import pickle +import errno + +from mesonbuild import mlog +from .core import MesonException, HoldableObject + +if T.TYPE_CHECKING: + from typing_extensions import Literal, Protocol + + from .._typing import ImmutableListProtocol + from ..build import ConfigurationData + from ..coredata import KeyedOptionDictType, UserOption + from ..environment import Environment + from ..compilers.compilers import Compiler + from ..interpreterbase.baseobjects import SubProject + + class _EnvPickleLoadable(Protocol): + + environment: Environment + + class _VerPickleLoadable(Protocol): + + version: str + + # A generic type for pickle_load. This allows any type that has either a + # .version or a .environment to be passed. + _PL = T.TypeVar('_PL', bound=T.Union[_EnvPickleLoadable, _VerPickleLoadable]) + +FileOrString = T.Union['File', str] + +_T = T.TypeVar('_T') +_U = T.TypeVar('_U') + +__all__ = [ + 'GIT', + 'python_command', + 'project_meson_versions', + 'SecondLevelHolder', + 'File', + 'FileMode', + 'GitException', + 'LibType', + 'MachineChoice', + 'EnvironmentException', + 'FileOrString', + 'GitException', + 'OptionKey', + 'dump_conf_header', + 'OptionOverrideProxy', + 'OptionType', + 'OrderedSet', + 'PerMachine', + 'PerMachineDefaultable', + 'PerThreeMachine', + 'PerThreeMachineDefaultable', + 'ProgressBar', + 'RealPathAction', + 'TemporaryDirectoryWinProof', + 'Version', + 'check_direntry_issues', + 'classify_unity_sources', + 'current_vs_supports_modules', + 'darwin_get_object_archs', + 'default_libdir', + 'default_libexecdir', + 'default_prefix', + 'default_datadir', + 'default_includedir', + 'default_infodir', + 'default_localedir', + 'default_mandir', + 'default_sbindir', + 'default_sysconfdir', + 'detect_subprojects', + 'detect_vcs', + 'do_conf_file', + 'do_conf_str', + 'do_replacement', + 'exe_exists', + 'expand_arguments', + 'extract_as_list', + 'first', + 'generate_list', + 'get_compiler_for_source', + 'get_filenames_templates_dict', + 'get_variable_regex', + 'get_wine_shortpath', + 'git', + 'has_path_sep', + 'is_aix', + 'is_android', + 'is_ascii_string', + 'is_cygwin', + 'is_debianlike', + 'is_dragonflybsd', + 'is_freebsd', + 'is_haiku', + 'is_hurd', + 'is_irix', + 'is_linux', + 'is_netbsd', + 'is_openbsd', + 'is_osx', + 'is_qnx', + 'is_sunos', + 'is_windows', + 'is_wsl', + 'iter_regexin_iter', + 'join_args', + 'listify', + 'partition', + 'path_is_in_root', + 'pickle_load', + 'Popen_safe', + 'Popen_safe_logged', + 'quiet_git', + 'quote_arg', + 'relative_to_if_possible', + 'relpath', + 'replace_if_different', + 'run_once', + 'get_meson_command', + 'set_meson_command', + 'split_args', + 'stringlistify', + 'substitute_values', + 'substring_is_in_list', + 'typeslistify', + 'verbose_git', + 'version_compare', + 'version_compare_condition_with_min', + 'version_compare_many', + 'search_version', + 'windows_detect_native_arch', + 'windows_proof_rm', + 'windows_proof_rmtree', +] + + +# TODO: this is such a hack, this really should be either in coredata or in the +# interpreter +# {subproject: project_meson_version} +project_meson_versions = collections.defaultdict(str) # type: T.DefaultDict[str, str] + + +from glob import glob + +if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): + # using a PyInstaller bundle, e.g. the MSI installed executable + python_command = [sys.executable, 'runpython'] +else: + python_command = [sys.executable] +_meson_command: T.Optional['ImmutableListProtocol[str]'] = None + + +class EnvironmentException(MesonException): + '''Exceptions thrown while processing and creating the build environment''' + +class GitException(MesonException): + def __init__(self, msg: str, output: T.Optional[str] = None): + super().__init__(msg) + self.output = output.strip() if output else '' + +GIT = shutil.which('git') +def git(cmd: T.List[str], workingdir: T.Union[str, bytes, os.PathLike], check: bool = False, **kwargs: T.Any) -> T.Tuple[subprocess.Popen, str, str]: + cmd = [GIT] + cmd + p, o, e = Popen_safe(cmd, cwd=workingdir, **kwargs) + if check and p.returncode != 0: + raise GitException('Git command failed: ' + str(cmd), e) + return p, o, e + +def quiet_git(cmd: T.List[str], workingdir: T.Union[str, bytes, os.PathLike], check: bool = False) -> T.Tuple[bool, str]: + if not GIT: + m = 'Git program not found.' + if check: + raise GitException(m) + return False, m + p, o, e = git(cmd, workingdir, check) + if p.returncode != 0: + return False, e + return True, o + +def verbose_git(cmd: T.List[str], workingdir: T.Union[str, bytes, os.PathLike], check: bool = False) -> bool: + if not GIT: + m = 'Git program not found.' + if check: + raise GitException(m) + return False + p, _, _ = git(cmd, workingdir, check, stdout=None, stderr=None) + return p.returncode == 0 + +def set_meson_command(mainfile: str) -> None: + global _meson_command # pylint: disable=global-statement + # On UNIX-like systems `meson` is a Python script + # On Windows `meson` and `meson.exe` are wrapper exes + if not mainfile.endswith('.py'): + _meson_command = [mainfile] + elif os.path.isabs(mainfile) and mainfile.endswith('mesonmain.py'): + # Can't actually run meson with an absolute path to mesonmain.py, it must be run as -m mesonbuild.mesonmain + _meson_command = python_command + ['-m', 'mesonbuild.mesonmain'] + else: + # Either run uninstalled, or full path to meson-script.py + _meson_command = python_command + [mainfile] + # We print this value for unit tests. + if 'MESON_COMMAND_TESTS' in os.environ: + mlog.log(f'meson_command is {_meson_command!r}') + + +def get_meson_command() -> T.Optional['ImmutableListProtocol[str]']: + return _meson_command + + +def is_ascii_string(astring: T.Union[str, bytes]) -> bool: + try: + if isinstance(astring, str): + astring.encode('ascii') + elif isinstance(astring, bytes): + astring.decode('ascii') + except UnicodeDecodeError: + return False + return True + + +def check_direntry_issues(direntry_array: T.Union[T.Iterable[T.Union[str, bytes]], str, bytes]) -> None: + import locale + # Warn if the locale is not UTF-8. This can cause various unfixable issues + # such as os.stat not being able to decode filenames with unicode in them. + # There is no way to reset both the preferred encoding and the filesystem + # encoding, so we can just warn about it. + e = locale.getpreferredencoding() + if e.upper() != 'UTF-8' and not is_windows(): + if isinstance(direntry_array, (str, bytes)): + direntry_array = [direntry_array] + for de in direntry_array: + if is_ascii_string(de): + continue + mlog.warning(textwrap.dedent(f''' + You are using {e!r} which is not a Unicode-compatible + locale but you are trying to access a file system entry called {de!r} which is + not pure ASCII. This may cause problems. + ''')) + +class SecondLevelHolder(HoldableObject, metaclass=abc.ABCMeta): + ''' A second level object holder. The primary purpose + of such objects is to hold multiple objects with one + default option. ''' + + @abc.abstractmethod + def get_default_object(self) -> HoldableObject: ... + +class FileMode: + # The first triad is for owner permissions, the second for group permissions, + # and the third for others (everyone else). + # For the 1st character: + # 'r' means can read + # '-' means not allowed + # For the 2nd character: + # 'w' means can write + # '-' means not allowed + # For the 3rd character: + # 'x' means can execute + # 's' means can execute and setuid/setgid is set (owner/group triads only) + # 'S' means cannot execute and setuid/setgid is set (owner/group triads only) + # 't' means can execute and sticky bit is set ("others" triads only) + # 'T' means cannot execute and sticky bit is set ("others" triads only) + # '-' means none of these are allowed + # + # The meanings of 'rwx' perms is not obvious for directories; see: + # https://www.hackinglinuxexposed.com/articles/20030424.html + # + # For information on this notation such as setuid/setgid/sticky bits, see: + # https://en.wikipedia.org/wiki/File_system_permissions#Symbolic_notation + symbolic_perms_regex = re.compile('[r-][w-][xsS-]' # Owner perms + '[r-][w-][xsS-]' # Group perms + '[r-][w-][xtT-]') # Others perms + + def __init__(self, perms: T.Optional[str] = None, owner: T.Union[str, int, None] = None, + group: T.Union[str, int, None] = None): + self.perms_s = perms + self.perms = self.perms_s_to_bits(perms) + self.owner = owner + self.group = group + + def __repr__(self) -> str: + ret = ' int: + ''' + Does the opposite of stat.filemode(), converts strings of the form + 'rwxr-xr-x' to st_mode enums which can be passed to os.chmod() + ''' + if perms_s is None: + # No perms specified, we will not touch the permissions + return -1 + eg = 'rwxr-xr-x' + if not isinstance(perms_s, str): + raise MesonException(f'Install perms must be a string. For example, {eg!r}') + if len(perms_s) != 9 or not cls.symbolic_perms_regex.match(perms_s): + raise MesonException(f'File perms {perms_s!r} must be exactly 9 chars. For example, {eg!r}') + perms = 0 + # Owner perms + if perms_s[0] == 'r': + perms |= stat.S_IRUSR + if perms_s[1] == 'w': + perms |= stat.S_IWUSR + if perms_s[2] == 'x': + perms |= stat.S_IXUSR + elif perms_s[2] == 'S': + perms |= stat.S_ISUID + elif perms_s[2] == 's': + perms |= stat.S_IXUSR + perms |= stat.S_ISUID + # Group perms + if perms_s[3] == 'r': + perms |= stat.S_IRGRP + if perms_s[4] == 'w': + perms |= stat.S_IWGRP + if perms_s[5] == 'x': + perms |= stat.S_IXGRP + elif perms_s[5] == 'S': + perms |= stat.S_ISGID + elif perms_s[5] == 's': + perms |= stat.S_IXGRP + perms |= stat.S_ISGID + # Others perms + if perms_s[6] == 'r': + perms |= stat.S_IROTH + if perms_s[7] == 'w': + perms |= stat.S_IWOTH + if perms_s[8] == 'x': + perms |= stat.S_IXOTH + elif perms_s[8] == 'T': + perms |= stat.S_ISVTX + elif perms_s[8] == 't': + perms |= stat.S_IXOTH + perms |= stat.S_ISVTX + return perms + +dot_C_dot_H_warning = """You are using .C or .H files in your project. This is deprecated. + Currently, Meson treats this as C++ code, but they + used to be treated as C code. + Note that the situation is a bit more complex if you are using the + Visual Studio compiler, as it treats .C files as C code, unless you add + the /TP compiler flag, but this is unreliable. + See https://github.com/mesonbuild/meson/pull/8747 for the discussions.""" +class File(HoldableObject): + def __init__(self, is_built: bool, subdir: str, fname: str): + if fname.endswith(".C") or fname.endswith(".H"): + mlog.warning(dot_C_dot_H_warning, once=True) + self.is_built = is_built + self.subdir = subdir + self.fname = fname + self.hash = hash((is_built, subdir, fname)) + + def __str__(self) -> str: + return self.relative_name() + + def __repr__(self) -> str: + ret = ' 'File': + if not os.path.isfile(os.path.join(source_root, subdir, fname)): + raise MesonException(f'File {fname} does not exist.') + return File(False, subdir, fname) + + @staticmethod + def from_built_file(subdir: str, fname: str) -> 'File': + return File(True, subdir, fname) + + @staticmethod + def from_built_relative(relative: str) -> 'File': + dirpart, fnamepart = os.path.split(relative) + return File(True, dirpart, fnamepart) + + @staticmethod + def from_absolute_file(fname: str) -> 'File': + return File(False, '', fname) + + @lru_cache(maxsize=None) + def rel_to_builddir(self, build_to_src: str) -> str: + if self.is_built: + return self.relative_name() + else: + return os.path.join(build_to_src, self.subdir, self.fname) + + @lru_cache(maxsize=None) + def absolute_path(self, srcdir: str, builddir: str) -> str: + absdir = srcdir + if self.is_built: + absdir = builddir + return os.path.join(absdir, self.relative_name()) + + @property + def suffix(self) -> str: + return os.path.splitext(self.fname)[1][1:].lower() + + def endswith(self, ending: T.Union[str, T.Tuple[str, ...]]) -> bool: + return self.fname.endswith(ending) + + def split(self, s: str, maxsplit: int = -1) -> T.List[str]: + return self.fname.split(s, maxsplit=maxsplit) + + def rsplit(self, s: str, maxsplit: int = -1) -> T.List[str]: + return self.fname.rsplit(s, maxsplit=maxsplit) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, File): + return NotImplemented + if self.hash != other.hash: + return False + return (self.fname, self.subdir, self.is_built) == (other.fname, other.subdir, other.is_built) + + def __hash__(self) -> int: + return self.hash + + @lru_cache(maxsize=None) + def relative_name(self) -> str: + return os.path.join(self.subdir, self.fname) + + +def get_compiler_for_source(compilers: T.Iterable['Compiler'], src: 'FileOrString') -> 'Compiler': + """Given a set of compilers and a source, find the compiler for that source type.""" + for comp in compilers: + if comp.can_compile(src): + return comp + raise MesonException(f'No specified compiler can handle file {src!s}') + + +def classify_unity_sources(compilers: T.Iterable['Compiler'], sources: T.Sequence['FileOrString']) -> T.Dict['Compiler', T.List['FileOrString']]: + compsrclist: T.Dict['Compiler', T.List['FileOrString']] = {} + for src in sources: + comp = get_compiler_for_source(compilers, src) + if comp not in compsrclist: + compsrclist[comp] = [src] + else: + compsrclist[comp].append(src) + return compsrclist + + +class MachineChoice(enum.IntEnum): + + """Enum class representing one of the two abstract machine names used in + most places: the build, and host, machines. + """ + + BUILD = 0 + HOST = 1 + + def get_lower_case_name(self) -> str: + return PerMachine('build', 'host')[self] + + def get_prefix(self) -> str: + return PerMachine('build.', '')[self] + + +class PerMachine(T.Generic[_T]): + def __init__(self, build: _T, host: _T) -> None: + self.build = build + self.host = host + + def __getitem__(self, machine: MachineChoice) -> _T: + return { + MachineChoice.BUILD: self.build, + MachineChoice.HOST: self.host, + }[machine] + + def __setitem__(self, machine: MachineChoice, val: _T) -> None: + setattr(self, machine.get_lower_case_name(), val) + + def miss_defaulting(self) -> "PerMachineDefaultable[T.Optional[_T]]": + """Unset definition duplicated from their previous to None + + This is the inverse of ''default_missing''. By removing defaulted + machines, we can elaborate the original and then redefault them and thus + avoid repeating the elaboration explicitly. + """ + unfreeze = PerMachineDefaultable() # type: PerMachineDefaultable[T.Optional[_T]] + unfreeze.build = self.build + unfreeze.host = self.host + if unfreeze.host == unfreeze.build: + unfreeze.host = None + return unfreeze + + def __repr__(self) -> str: + return f'PerMachine({self.build!r}, {self.host!r})' + + +class PerThreeMachine(PerMachine[_T]): + """Like `PerMachine` but includes `target` too. + + It turns out just one thing do we need track the target machine. There's no + need to computer the `target` field so we don't bother overriding the + `__getitem__`/`__setitem__` methods. + """ + def __init__(self, build: _T, host: _T, target: _T) -> None: + super().__init__(build, host) + self.target = target + + def miss_defaulting(self) -> "PerThreeMachineDefaultable[T.Optional[_T]]": + """Unset definition duplicated from their previous to None + + This is the inverse of ''default_missing''. By removing defaulted + machines, we can elaborate the original and then redefault them and thus + avoid repeating the elaboration explicitly. + """ + unfreeze = PerThreeMachineDefaultable() # type: PerThreeMachineDefaultable[T.Optional[_T]] + unfreeze.build = self.build + unfreeze.host = self.host + unfreeze.target = self.target + if unfreeze.target == unfreeze.host: + unfreeze.target = None + if unfreeze.host == unfreeze.build: + unfreeze.host = None + return unfreeze + + def matches_build_machine(self, machine: MachineChoice) -> bool: + return self.build == self[machine] + + def __repr__(self) -> str: + return f'PerThreeMachine({self.build!r}, {self.host!r}, {self.target!r})' + + +class PerMachineDefaultable(PerMachine[T.Optional[_T]]): + """Extends `PerMachine` with the ability to default from `None`s. + """ + def __init__(self, build: T.Optional[_T] = None, host: T.Optional[_T] = None) -> None: + super().__init__(build, host) + + def default_missing(self) -> "PerMachine[_T]": + """Default host to build + + This allows just specifying nothing in the native case, and just host in the + cross non-compiler case. + """ + freeze = PerMachine(self.build, self.host) + if freeze.host is None: + freeze.host = freeze.build + return freeze + + def __repr__(self) -> str: + return f'PerMachineDefaultable({self.build!r}, {self.host!r})' + + @classmethod + def default(cls, is_cross: bool, build: _T, host: _T) -> PerMachine[_T]: + """Easy way to get a defaulted value + + This allows simplifying the case where you can control whether host and + build are separate or not with a boolean. If the is_cross value is set + to true then the optional host value will be used, otherwise the host + will be set to the build value. + """ + m = cls(build) + if is_cross: + m.host = host + return m.default_missing() + + +class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[T.Optional[_T]]): + """Extends `PerThreeMachine` with the ability to default from `None`s. + """ + def __init__(self) -> None: + PerThreeMachine.__init__(self, None, None, None) + + def default_missing(self) -> "PerThreeMachine[T.Optional[_T]]": + """Default host to build and target to host. + + This allows just specifying nothing in the native case, just host in the + cross non-compiler case, and just target in the native-built + cross-compiler case. + """ + freeze = PerThreeMachine(self.build, self.host, self.target) + if freeze.host is None: + freeze.host = freeze.build + if freeze.target is None: + freeze.target = freeze.host + return freeze + + def __repr__(self) -> str: + return f'PerThreeMachineDefaultable({self.build!r}, {self.host!r}, {self.target!r})' + + +def is_sunos() -> bool: + return platform.system().lower() == 'sunos' + + +def is_osx() -> bool: + return platform.system().lower() == 'darwin' + + +def is_linux() -> bool: + return platform.system().lower() == 'linux' + + +def is_android() -> bool: + return platform.system().lower() == 'android' + + +def is_haiku() -> bool: + return platform.system().lower() == 'haiku' + + +def is_openbsd() -> bool: + return platform.system().lower() == 'openbsd' + + +def is_windows() -> bool: + platname = platform.system().lower() + return platname == 'windows' + +def is_wsl() -> bool: + return is_linux() and 'microsoft' in platform.release().lower() + +def is_cygwin() -> bool: + return sys.platform == 'cygwin' + + +def is_debianlike() -> bool: + return os.path.isfile('/etc/debian_version') + + +def is_dragonflybsd() -> bool: + return platform.system().lower() == 'dragonfly' + + +def is_netbsd() -> bool: + return platform.system().lower() == 'netbsd' + + +def is_freebsd() -> bool: + return platform.system().lower() == 'freebsd' + +def is_irix() -> bool: + return platform.system().startswith('irix') + +def is_hurd() -> bool: + return platform.system().lower() == 'gnu' + +def is_qnx() -> bool: + return platform.system().lower() == 'qnx' + +def is_aix() -> bool: + return platform.system().lower() == 'aix' + +def exe_exists(arglist: T.List[str]) -> bool: + try: + if subprocess.run(arglist, timeout=10).returncode == 0: + return True + except (FileNotFoundError, subprocess.TimeoutExpired): + pass + return False + + +@lru_cache(maxsize=None) +def darwin_get_object_archs(objpath: str) -> 'ImmutableListProtocol[str]': + ''' + For a specific object (executable, static library, dylib, etc), run `lipo` + to fetch the list of archs supported by it. Supports both thin objects and + 'fat' objects. + ''' + _, stdo, stderr = Popen_safe(['lipo', '-info', objpath]) + if not stdo: + mlog.debug(f'lipo {objpath}: {stderr}') + return None + stdo = stdo.rsplit(': ', 1)[1] + + # Convert from lipo-style archs to meson-style CPUs + map_arch = { + 'i386': 'x86', + 'arm64': 'aarch64', + 'arm64e': 'aarch64', + 'ppc7400': 'ppc', + 'ppc970': 'ppc', + } + lipo_archs = stdo.split() + meson_archs = [map_arch.get(lipo_arch, lipo_arch) for lipo_arch in lipo_archs] + + # Add generic name for armv7 and armv7s + if 'armv7' in stdo: + meson_archs.append('arm') + + return meson_archs + +def windows_detect_native_arch() -> str: + """ + The architecture of Windows itself: x86, amd64 or arm64 + """ + if sys.platform != 'win32': + return '' + try: + import ctypes + process_arch = ctypes.c_ushort() + native_arch = ctypes.c_ushort() + kernel32 = ctypes.windll.kernel32 + process = ctypes.c_void_p(kernel32.GetCurrentProcess()) + # This is the only reliable way to detect an arm system if we are an x86/x64 process being emulated + if kernel32.IsWow64Process2(process, ctypes.byref(process_arch), ctypes.byref(native_arch)): + # https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants + if native_arch.value == 0x8664: + return 'amd64' + elif native_arch.value == 0x014C: + return 'x86' + elif native_arch.value == 0xAA64: + return 'arm64' + elif native_arch.value == 0x01C4: + return 'arm' + except (OSError, AttributeError): + pass + # These env variables are always available. See: + # https://msdn.microsoft.com/en-us/library/aa384274(VS.85).aspx + # https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/ + arch = os.environ.get('PROCESSOR_ARCHITEW6432', '').lower() + if not arch: + try: + # If this doesn't exist, something is messing with the environment + arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() + except KeyError: + raise EnvironmentException('Unable to detect native OS architecture') + return arch + +def detect_vcs(source_dir: T.Union[str, Path]) -> T.Optional[T.Dict[str, str]]: + vcs_systems = [ + { + 'name': 'git', + 'cmd': 'git', + 'repo_dir': '.git', + 'get_rev': 'git describe --dirty=+ --always', + 'rev_regex': '(.*)', + 'dep': '.git/logs/HEAD' + }, + { + 'name': 'mercurial', + 'cmd': 'hg', + 'repo_dir': '.hg', + 'get_rev': 'hg id -i', + 'rev_regex': '(.*)', + 'dep': '.hg/dirstate' + }, + { + 'name': 'subversion', + 'cmd': 'svn', + 'repo_dir': '.svn', + 'get_rev': 'svn info', + 'rev_regex': 'Revision: (.*)', + 'dep': '.svn/wc.db' + }, + { + 'name': 'bazaar', + 'cmd': 'bzr', + 'repo_dir': '.bzr', + 'get_rev': 'bzr revno', + 'rev_regex': '(.*)', + 'dep': '.bzr' + }, + ] + if isinstance(source_dir, str): + source_dir = Path(source_dir) + + parent_paths_and_self = collections.deque(source_dir.parents) + # Prepend the source directory to the front so we can check it; + # source_dir.parents doesn't include source_dir + parent_paths_and_self.appendleft(source_dir) + for curdir in parent_paths_and_self: + for vcs in vcs_systems: + if Path.is_dir(curdir.joinpath(vcs['repo_dir'])) and shutil.which(vcs['cmd']): + vcs['wc_dir'] = str(curdir) + return vcs + return None + +def current_vs_supports_modules() -> bool: + vsver = os.environ.get('VSCMD_VER', '') + nums = vsver.split('.', 2) + major = int(nums[0]) + if major >= 17: + return True + if major == 16 and int(nums[1]) >= 10: + return True + return vsver.startswith('16.9.0') and '-pre.' in vsver + +# a helper class which implements the same version ordering as RPM +class Version: + def __init__(self, s: str) -> None: + self._s = s + + # split into numeric, alphabetic and non-alphanumeric sequences + sequences1 = re.finditer(r'(\d+|[a-zA-Z]+|[^a-zA-Z\d]+)', s) + + # non-alphanumeric separators are discarded + sequences2 = [m for m in sequences1 if not re.match(r'[^a-zA-Z\d]+', m.group(1))] + + # numeric sequences are converted from strings to ints + sequences3 = [int(m.group(1)) if m.group(1).isdigit() else m.group(1) for m in sequences2] + + self._v = sequences3 + + def __str__(self) -> str: + return '{} (V={})'.format(self._s, str(self._v)) + + def __repr__(self) -> str: + return f'' + + def __lt__(self, other: object) -> bool: + if isinstance(other, Version): + return self.__cmp(other, operator.lt) + return NotImplemented + + def __gt__(self, other: object) -> bool: + if isinstance(other, Version): + return self.__cmp(other, operator.gt) + return NotImplemented + + def __le__(self, other: object) -> bool: + if isinstance(other, Version): + return self.__cmp(other, operator.le) + return NotImplemented + + def __ge__(self, other: object) -> bool: + if isinstance(other, Version): + return self.__cmp(other, operator.ge) + return NotImplemented + + def __eq__(self, other: object) -> bool: + if isinstance(other, Version): + return self._v == other._v + return NotImplemented + + def __ne__(self, other: object) -> bool: + if isinstance(other, Version): + return self._v != other._v + return NotImplemented + + def __cmp(self, other: 'Version', comparator: T.Callable[[T.Any, T.Any], bool]) -> bool: + # compare each sequence in order + for ours, theirs in zip(self._v, other._v): + # sort a non-digit sequence before a digit sequence + ours_is_int = isinstance(ours, int) + theirs_is_int = isinstance(theirs, int) + if ours_is_int != theirs_is_int: + return comparator(ours_is_int, theirs_is_int) + + if ours != theirs: + return comparator(ours, theirs) + + # if equal length, all components have matched, so equal + # otherwise, the version with a suffix remaining is greater + return comparator(len(self._v), len(other._v)) + + +def _version_extract_cmpop(vstr2: str) -> T.Tuple[T.Callable[[T.Any, T.Any], bool], str]: + if vstr2.startswith('>='): + cmpop = operator.ge + vstr2 = vstr2[2:] + elif vstr2.startswith('<='): + cmpop = operator.le + vstr2 = vstr2[2:] + elif vstr2.startswith('!='): + cmpop = operator.ne + vstr2 = vstr2[2:] + elif vstr2.startswith('=='): + cmpop = operator.eq + vstr2 = vstr2[2:] + elif vstr2.startswith('='): + cmpop = operator.eq + vstr2 = vstr2[1:] + elif vstr2.startswith('>'): + cmpop = operator.gt + vstr2 = vstr2[1:] + elif vstr2.startswith('<'): + cmpop = operator.lt + vstr2 = vstr2[1:] + else: + cmpop = operator.eq + + return (cmpop, vstr2) + + +def version_compare(vstr1: str, vstr2: str) -> bool: + (cmpop, vstr2) = _version_extract_cmpop(vstr2) + return cmpop(Version(vstr1), Version(vstr2)) + + +def version_compare_many(vstr1: str, conditions: T.Union[str, T.Iterable[str]]) -> T.Tuple[bool, T.List[str], T.List[str]]: + if isinstance(conditions, str): + conditions = [conditions] + found = [] + not_found = [] + for req in conditions: + if not version_compare(vstr1, req): + not_found.append(req) + else: + found.append(req) + return not not_found, not_found, found + + +# determine if the minimum version satisfying the condition |condition| exceeds +# the minimum version for a feature |minimum| +def version_compare_condition_with_min(condition: str, minimum: str) -> bool: + if condition.startswith('>='): + cmpop = operator.le + condition = condition[2:] + elif condition.startswith('<='): + return False + elif condition.startswith('!='): + return False + elif condition.startswith('=='): + cmpop = operator.le + condition = condition[2:] + elif condition.startswith('='): + cmpop = operator.le + condition = condition[1:] + elif condition.startswith('>'): + cmpop = operator.lt + condition = condition[1:] + elif condition.startswith('<'): + return False + else: + cmpop = operator.le + + # Declaring a project(meson_version: '>=0.46') and then using features in + # 0.46.0 is valid, because (knowing the meson versioning scheme) '0.46.0' is + # the lowest version which satisfies the constraint '>=0.46'. + # + # But this will fail here, because the minimum version required by the + # version constraint ('0.46') is strictly less (in our version comparison) + # than the minimum version needed for the feature ('0.46.0'). + # + # Map versions in the constraint of the form '0.46' to '0.46.0', to embed + # this knowledge of the meson versioning scheme. + condition = condition.strip() + if re.match(r'^\d+.\d+$', condition): + condition += '.0' + + return T.cast('bool', cmpop(Version(minimum), Version(condition))) + +def search_version(text: str) -> str: + # Usually of the type 4.1.4 but compiler output may contain + # stuff like this: + # (Sourcery CodeBench Lite 2014.05-29) 4.8.3 20140320 (prerelease) + # Limiting major version number to two digits seems to work + # thus far. When we get to GCC 100, this will break, but + # if we are still relevant when that happens, it can be + # considered an achievement in itself. + # + # This regex is reaching magic levels. If it ever needs + # to be updated, do not complexify but convert to something + # saner instead. + # We'll demystify it a bit with a verbose definition. + version_regex = re.compile(r""" + (? str: + if is_debianlike(): + try: + pc = subprocess.Popen(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + (stdo, _) = pc.communicate() + if pc.returncode == 0: + archpath = stdo.decode().strip() + return 'lib/' + archpath + except Exception: + pass + if is_freebsd() or is_irix(): + return 'lib' + if os.path.isdir('/usr/lib64') and not os.path.islink('/usr/lib64'): + return 'lib64' + return 'lib' + + +def default_libexecdir() -> str: + if is_haiku(): + return 'lib' + # There is no way to auto-detect this, so it must be set at build time + return 'libexec' + + +def default_prefix() -> str: + if is_windows(): + return 'c:/' + if is_haiku(): + return '/boot/system/non-packaged' + return '/usr/local' + + +def default_datadir() -> str: + if is_haiku(): + return 'data' + return 'share' + + +def default_includedir() -> str: + if is_haiku(): + return 'develop/headers' + return 'include' + + +def default_infodir() -> str: + if is_haiku(): + return 'documentation/info' + return 'share/info' + + +def default_localedir() -> str: + if is_haiku(): + return 'data/locale' + return 'share/locale' + + +def default_mandir() -> str: + if is_haiku(): + return 'documentation/man' + return 'share/man' + + +def default_sbindir() -> str: + if is_haiku(): + return 'bin' + return 'sbin' + + +def default_sysconfdir() -> str: + if is_haiku(): + return 'settings' + return 'etc' + + +def has_path_sep(name: str, sep: str = '/\\') -> bool: + 'Checks if any of the specified @sep path separators are in @name' + for each in sep: + if each in name: + return True + return False + + +if is_windows(): + # shlex.split is not suitable for splitting command line on Window (https://bugs.python.org/issue1724822); + # shlex.quote is similarly problematic. Below are "proper" implementations of these functions according to + # https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and + # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + + _whitespace = ' \t\n\r' + _find_unsafe_char = re.compile(fr'[{_whitespace}"]').search + + def quote_arg(arg: str) -> str: + if arg and not _find_unsafe_char(arg): + return arg + + result = '"' + num_backslashes = 0 + for c in arg: + if c == '\\': + num_backslashes += 1 + else: + if c == '"': + # Escape all backslashes and the following double quotation mark + num_backslashes = num_backslashes * 2 + 1 + + result += num_backslashes * '\\' + c + num_backslashes = 0 + + # Escape all backslashes, but let the terminating double quotation + # mark we add below be interpreted as a metacharacter + result += (num_backslashes * 2) * '\\' + '"' + return result + + def split_args(cmd: str) -> T.List[str]: + result = [] + arg = '' + num_backslashes = 0 + num_quotes = 0 + in_quotes = False + for c in cmd: + if c == '\\': + num_backslashes += 1 + else: + if c == '"' and not num_backslashes % 2: + # unescaped quote, eat it + arg += (num_backslashes // 2) * '\\' + num_quotes += 1 + in_quotes = not in_quotes + elif c in _whitespace and not in_quotes: + if arg or num_quotes: + # reached the end of the argument + result.append(arg) + arg = '' + num_quotes = 0 + else: + if c == '"': + # escaped quote + num_backslashes = (num_backslashes - 1) // 2 + + arg += num_backslashes * '\\' + c + + num_backslashes = 0 + + if arg or num_quotes: + result.append(arg) + + return result +else: + def quote_arg(arg: str) -> str: + return shlex.quote(arg) + + def split_args(cmd: str) -> T.List[str]: + return shlex.split(cmd) + + +def join_args(args: T.Iterable[str]) -> str: + return ' '.join([quote_arg(x) for x in args]) + + +def do_replacement(regex: T.Pattern[str], line: str, + variable_format: Literal['meson', 'cmake', 'cmake@'], + confdata: T.Union[T.Dict[str, T.Tuple[str, T.Optional[str]]], 'ConfigurationData']) -> T.Tuple[str, T.Set[str]]: + missing_variables = set() # type: T.Set[str] + if variable_format == 'cmake': + start_tag = '${' + backslash_tag = '\\${' + else: + start_tag = '@' + backslash_tag = '\\@' + + def variable_replace(match: T.Match[str]) -> str: + # Pairs of escape characters before '@' or '\@' + if match.group(0).endswith('\\'): + num_escapes = match.end(0) - match.start(0) + return '\\' * (num_escapes // 2) + # Single escape character and '@' + elif match.group(0) == backslash_tag: + return start_tag + # Template variable to be replaced + else: + varname = match.group(1) + var_str = '' + if varname in confdata: + var, _ = confdata.get(varname) + if isinstance(var, str): + var_str = var + elif isinstance(var, int): + var_str = str(var) + else: + msg = f'Tried to replace variable {varname!r} value with ' \ + f'something other than a string or int: {var!r}' + raise MesonException(msg) + else: + missing_variables.add(varname) + return var_str + return re.sub(regex, variable_replace, line), missing_variables + +def do_define(regex: T.Pattern[str], line: str, confdata: 'ConfigurationData', + variable_format: Literal['meson', 'cmake', 'cmake@'], subproject: T.Optional[SubProject] = None) -> str: + def get_cmake_define(line: str, confdata: 'ConfigurationData') -> str: + arr = line.split() + define_value = [] + for token in arr[2:]: + try: + (v, desc) = confdata.get(token) + define_value += [str(v)] + except KeyError: + define_value += [token] + return ' '.join(define_value) + + arr = line.split() + if len(arr) != 2: + if variable_format == 'meson': + raise MesonException('#mesondefine does not contain exactly two tokens: %s' % line.strip()) + elif subproject is not None: + from ..interpreterbase.decorators import FeatureNew + FeatureNew.single_use('cmakedefine without exactly two tokens', '0.54.1', subproject) + + varname = arr[1] + try: + (v, desc) = confdata.get(varname) + except KeyError: + return '/* #undef %s */\n' % varname + if isinstance(v, bool): + if v: + return '#define %s\n' % varname + else: + return '#undef %s\n' % varname + elif isinstance(v, int): + return '#define %s %d\n' % (varname, v) + elif isinstance(v, str): + if variable_format == 'meson': + result = v + else: + result = get_cmake_define(line, confdata) + result = f'#define {varname} {result}\n' + (result, missing_variable) = do_replacement(regex, result, variable_format, confdata) + return result + else: + raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname) + +def get_variable_regex(variable_format: Literal['meson', 'cmake', 'cmake@'] = 'meson') -> T.Pattern[str]: + # Only allow (a-z, A-Z, 0-9, _, -) as valid characters for a define + # Also allow escaping '@' with '\@' + if variable_format in {'meson', 'cmake@'}: + regex = re.compile(r'(?:\\\\)+(?=\\?@)|\\@|@([-a-zA-Z0-9_]+)@') + else: + regex = re.compile(r'(?:\\\\)+(?=\\?\$)|\\\${|\${([-a-zA-Z0-9_]+)}') + return regex + +def do_conf_str(src: str, data: list, confdata: 'ConfigurationData', + variable_format: Literal['meson', 'cmake', 'cmake@'], + encoding: str = 'utf-8', subproject: T.Optional[SubProject] = None) -> T.Tuple[T.List[str], T.Set[str], bool]: + def line_is_valid(line: str, variable_format: str) -> bool: + if variable_format == 'meson': + if '#cmakedefine' in line: + return False + else: # cmake format + if '#mesondefine' in line: + return False + return True + + regex = get_variable_regex(variable_format) + + search_token = '#mesondefine' + if variable_format != 'meson': + search_token = '#cmakedefine' + + result = [] + missing_variables = set() + # Detect when the configuration data is empty and no tokens were found + # during substitution so we can warn the user to use the `copy:` kwarg. + confdata_useless = not confdata.keys() + for line in data: + if line.startswith(search_token): + confdata_useless = False + line = do_define(regex, line, confdata, variable_format, subproject) + else: + if not line_is_valid(line, variable_format): + raise MesonException(f'Format error in {src}: saw "{line.strip()}" when format set to "{variable_format}"') + line, missing = do_replacement(regex, line, variable_format, confdata) + missing_variables.update(missing) + if missing: + confdata_useless = False + result.append(line) + + return result, missing_variables, confdata_useless + +def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', + variable_format: Literal['meson', 'cmake', 'cmake@'], + encoding: str = 'utf-8', subproject: T.Optional[SubProject] = None) -> T.Tuple[T.Set[str], bool]: + try: + with open(src, encoding=encoding, newline='') as f: + data = f.readlines() + except Exception as e: + raise MesonException(f'Could not read input file {src}: {e!s}') + + (result, missing_variables, confdata_useless) = do_conf_str(src, data, confdata, variable_format, encoding, subproject) + dst_tmp = dst + '~' + try: + with open(dst_tmp, 'w', encoding=encoding, newline='') as f: + f.writelines(result) + except Exception as e: + raise MesonException(f'Could not write output file {dst}: {e!s}') + shutil.copymode(src, dst_tmp) + replace_if_different(dst, dst_tmp) + return missing_variables, confdata_useless + +CONF_C_PRELUDE = '''/* + * Autogenerated by the Meson build system. + * Do not edit, your changes will be lost. + */ + +#pragma once + +''' + +CONF_NASM_PRELUDE = '''; Autogenerated by the Meson build system. +; Do not edit, your changes will be lost. + +''' + +def dump_conf_header(ofilename: str, cdata: 'ConfigurationData', output_format: T.Literal['c', 'nasm']) -> None: + if output_format == 'c': + prelude = CONF_C_PRELUDE + prefix = '#' + else: + prelude = CONF_NASM_PRELUDE + prefix = '%' + + ofilename_tmp = ofilename + '~' + with open(ofilename_tmp, 'w', encoding='utf-8') as ofile: + ofile.write(prelude) + for k in sorted(cdata.keys()): + (v, desc) = cdata.get(k) + if desc: + if output_format == 'c': + ofile.write('/* %s */\n' % desc) + elif output_format == 'nasm': + for line in desc.split('\n'): + ofile.write('; %s\n' % line) + if isinstance(v, bool): + if v: + ofile.write(f'{prefix}define {k}\n\n') + else: + ofile.write(f'{prefix}undef {k}\n\n') + elif isinstance(v, (int, str)): + ofile.write(f'{prefix}define {k} {v}\n\n') + else: + raise MesonException('Unknown data type in configuration file entry: ' + k) + replace_if_different(ofilename, ofilename_tmp) + + +def replace_if_different(dst: str, dst_tmp: str) -> None: + # If contents are identical, don't touch the file to prevent + # unnecessary rebuilds. + different = True + try: + with open(dst, 'rb') as f1, open(dst_tmp, 'rb') as f2: + if f1.read() == f2.read(): + different = False + except FileNotFoundError: + pass + if different: + os.replace(dst_tmp, dst) + else: + os.unlink(dst_tmp) + + +def listify(item: T.Any, flatten: bool = True) -> T.List[T.Any]: + ''' + Returns a list with all args embedded in a list if they are not a list. + This function preserves order. + @flatten: Convert lists of lists to a flat list + ''' + if not isinstance(item, list): + return [item] + result = [] # type: T.List[T.Any] + for i in item: + if flatten and isinstance(i, list): + result += listify(i, flatten=True) + else: + result.append(i) + return result + + +def extract_as_list(dict_object: T.Dict[_T, _U], key: _T, pop: bool = False) -> T.List[_U]: + ''' + Extracts all values from given dict_object and listifies them. + ''' + fetch: T.Callable[[_T], _U] = dict_object.get + if pop: + fetch = dict_object.pop + # If there's only one key, we don't return a list with one element + return listify(fetch(key) or [], flatten=True) + + +def typeslistify(item: 'T.Union[_T, T.Sequence[_T]]', + types: 'T.Union[T.Type[_T], T.Tuple[T.Type[_T]]]') -> T.List[_T]: + ''' + Ensure that type(@item) is one of @types or a + list of items all of which are of type @types + ''' + if isinstance(item, types): + item = T.cast('T.List[_T]', [item]) + if not isinstance(item, list): + raise MesonException('Item must be a list or one of {!r}, not {!r}'.format(types, type(item))) + for i in item: + if i is not None and not isinstance(i, types): + raise MesonException('List item must be one of {!r}, not {!r}'.format(types, type(i))) + return item + + +def stringlistify(item: T.Union[T.Any, T.Sequence[T.Any]]) -> T.List[str]: + return typeslistify(item, str) + + +def expand_arguments(args: T.Iterable[str]) -> T.Optional[T.List[str]]: + expended_args = [] # type: T.List[str] + for arg in args: + if not arg.startswith('@'): + expended_args.append(arg) + continue + + args_file = arg[1:] + try: + with open(args_file, encoding='utf-8') as f: + extended_args = f.read().split() + expended_args += extended_args + except Exception as e: + mlog.error('Expanding command line arguments:', args_file, 'not found') + mlog.exception(e) + return None + return expended_args + + +def partition(pred: T.Callable[[_T], object], iterable: T.Iterable[_T]) -> T.Tuple[T.Iterator[_T], T.Iterator[_T]]: + """Use a predicate to partition entries into false entries and true + entries. + + >>> x, y = partition(is_odd, range(10)) + >>> (list(x), list(y)) + ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9]) + """ + t1, t2 = tee(iterable) + return (t for t in t1 if not pred(t)), (t for t in t2 if pred(t)) + + +def Popen_safe(args: T.List[str], write: T.Optional[str] = None, + stdin: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.DEVNULL, + stdout: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + stderr: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: + import locale + encoding = locale.getpreferredencoding() + # Stdin defaults to DEVNULL otherwise the command run by us here might mess + # up the console and ANSI colors will stop working on Windows. + # If write is not None, set stdin to PIPE so data can be sent. + if write is not None: + stdin = subprocess.PIPE + + try: + if not sys.stdout.encoding or encoding.upper() != 'UTF-8': + p, o, e = Popen_safe_legacy(args, write=write, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs) + else: + p = subprocess.Popen(args, universal_newlines=True, encoding=encoding, close_fds=False, + stdin=stdin, stdout=stdout, stderr=stderr, **kwargs) + o, e = p.communicate(write) + except OSError as oserr: + if oserr.errno == errno.ENOEXEC: + raise MesonException(f'Failed running {args[0]!r}, binary or interpreter not executable.\n' + 'Possibly wrong architecture or the executable bit is not set.') + raise + # Sometimes the command that we run will call another command which will be + # without the above stdin workaround, so set the console mode again just in + # case. + mlog.setup_console() + return p, o, e + + +def Popen_safe_legacy(args: T.List[str], write: T.Optional[str] = None, + stdin: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.DEVNULL, + stdout: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + stderr: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: + p = subprocess.Popen(args, universal_newlines=False, close_fds=False, + stdin=stdin, stdout=stdout, stderr=stderr, **kwargs) + input_ = None # type: T.Optional[bytes] + if write is not None: + input_ = write.encode('utf-8') + o, e = p.communicate(input_) + if o is not None: + if sys.stdout.encoding is not None: + o = o.decode(encoding=sys.stdout.encoding, errors='replace').replace('\r\n', '\n') + else: + o = o.decode(errors='replace').replace('\r\n', '\n') + if e is not None: + if sys.stderr is not None and sys.stderr.encoding: + e = e.decode(encoding=sys.stderr.encoding, errors='replace').replace('\r\n', '\n') + else: + e = e.decode(errors='replace').replace('\r\n', '\n') + return p, o, e + + +def Popen_safe_logged(args: T.List[str], msg: str = 'Called', **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: + ''' + Wrapper around Popen_safe that assumes standard piped o/e and logs this to the meson log. + ''' + p, o, e = Popen_safe(args, **kwargs) + rc, out, err = p.returncode, o.strip(), e.strip() + mlog.debug('-----------') + mlog.debug(f'{msg}: `{join_args(args)}` -> {rc}') + if out: + mlog.debug(f'stdout:\n{out}\n-----------') + if err: + mlog.debug(f'stderr:\n{err}\n-----------') + return p, o, e + + +def iter_regexin_iter(regexiter: T.Iterable[str], initer: T.Iterable[str]) -> T.Optional[str]: + ''' + Takes each regular expression in @regexiter and tries to search for it in + every item in @initer. If there is a match, returns that match. + Else returns False. + ''' + for regex in regexiter: + for ii in initer: + if not isinstance(ii, str): + continue + match = re.search(regex, ii) + if match: + return match.group() + return None + + +def _substitute_values_check_errors(command: T.List[str], values: T.Dict[str, T.Union[str, T.List[str]]]) -> None: + # Error checking + inregex = ['@INPUT([0-9]+)?@', '@PLAINNAME@', '@BASENAME@'] # type: T.List[str] + outregex = ['@OUTPUT([0-9]+)?@', '@OUTDIR@'] # type: T.List[str] + if '@INPUT@' not in values: + # Error out if any input-derived templates are present in the command + match = iter_regexin_iter(inregex, command) + if match: + raise MesonException(f'Command cannot have {match!r}, since no input files were specified') + else: + if len(values['@INPUT@']) > 1: + # Error out if @PLAINNAME@ or @BASENAME@ is present in the command + match = iter_regexin_iter(inregex[1:], command) + if match: + raise MesonException(f'Command cannot have {match!r} when there is ' + 'more than one input file') + # Error out if an invalid @INPUTnn@ template was specified + for each in command: + if not isinstance(each, str): + continue + match2 = re.search(inregex[0], each) + if match2 and match2.group() not in values: + m = 'Command cannot have {!r} since there are only {!r} inputs' + raise MesonException(m.format(match2.group(), len(values['@INPUT@']))) + if '@OUTPUT@' not in values: + # Error out if any output-derived templates are present in the command + match = iter_regexin_iter(outregex, command) + if match: + raise MesonException(f'Command cannot have {match!r} since there are no outputs') + else: + # Error out if an invalid @OUTPUTnn@ template was specified + for each in command: + if not isinstance(each, str): + continue + match2 = re.search(outregex[0], each) + if match2 and match2.group() not in values: + m = 'Command cannot have {!r} since there are only {!r} outputs' + raise MesonException(m.format(match2.group(), len(values['@OUTPUT@']))) + + +def substitute_values(command: T.List[str], values: T.Dict[str, T.Union[str, T.List[str]]]) -> T.List[str]: + ''' + Substitute the template strings in the @values dict into the list of + strings @command and return a new list. For a full list of the templates, + see get_filenames_templates_dict() + + If multiple inputs/outputs are given in the @values dictionary, we + substitute @INPUT@ and @OUTPUT@ only if they are the entire string, not + just a part of it, and in that case we substitute *all* of them. + + The typing of this function is difficult, as only @OUTPUT@ and @INPUT@ can + be lists, everything else is a string. However, TypeDict cannot represent + this, as you can have optional keys, but not extra keys. We end up just + having to us asserts to convince type checkers that this is okay. + + https://github.com/python/mypy/issues/4617 + ''' + + def replace(m: T.Match[str]) -> str: + v = values[m.group(0)] + assert isinstance(v, str), 'for mypy' + return v + + # Error checking + _substitute_values_check_errors(command, values) + + # Substitution + outcmd = [] # type: T.List[str] + rx_keys = [re.escape(key) for key in values if key not in ('@INPUT@', '@OUTPUT@')] + value_rx = re.compile('|'.join(rx_keys)) if rx_keys else None + for vv in command: + more: T.Optional[str] = None + if not isinstance(vv, str): + outcmd.append(vv) + elif '@INPUT@' in vv: + inputs = values['@INPUT@'] + if vv == '@INPUT@': + outcmd += inputs + elif len(inputs) == 1: + outcmd.append(vv.replace('@INPUT@', inputs[0])) + else: + raise MesonException("Command has '@INPUT@' as part of a " + "string and more than one input file") + elif '@OUTPUT@' in vv: + outputs = values['@OUTPUT@'] + if vv == '@OUTPUT@': + outcmd += outputs + elif len(outputs) == 1: + outcmd.append(vv.replace('@OUTPUT@', outputs[0])) + else: + raise MesonException("Command has '@OUTPUT@' as part of a " + "string and more than one output file") + + # Append values that are exactly a template string. + # This is faster than a string replace. + elif vv in values: + o = values[vv] + assert isinstance(o, str), 'for mypy' + more = o + # Substitute everything else with replacement + elif value_rx: + more = value_rx.sub(replace, vv) + else: + more = vv + + if more is not None: + outcmd.append(more) + + return outcmd + + +def get_filenames_templates_dict(inputs: T.List[str], outputs: T.List[str]) -> T.Dict[str, T.Union[str, T.List[str]]]: + ''' + Create a dictionary with template strings as keys and values as values for + the following templates: + + @INPUT@ - the full path to one or more input files, from @inputs + @OUTPUT@ - the full path to one or more output files, from @outputs + @OUTDIR@ - the full path to the directory containing the output files + + If there is only one input file, the following keys are also created: + + @PLAINNAME@ - the filename of the input file + @BASENAME@ - the filename of the input file with the extension removed + + If there is more than one input file, the following keys are also created: + + @INPUT0@, @INPUT1@, ... one for each input file + + If there is more than one output file, the following keys are also created: + + @OUTPUT0@, @OUTPUT1@, ... one for each output file + ''' + values = {} # type: T.Dict[str, T.Union[str, T.List[str]]] + # Gather values derived from the input + if inputs: + # We want to substitute all the inputs. + values['@INPUT@'] = inputs + for (ii, vv) in enumerate(inputs): + # Write out @INPUT0@, @INPUT1@, ... + values[f'@INPUT{ii}@'] = vv + if len(inputs) == 1: + # Just one value, substitute @PLAINNAME@ and @BASENAME@ + values['@PLAINNAME@'] = plain = os.path.basename(inputs[0]) + values['@BASENAME@'] = os.path.splitext(plain)[0] + if outputs: + # Gather values derived from the outputs, similar to above. + values['@OUTPUT@'] = outputs + for (ii, vv) in enumerate(outputs): + values[f'@OUTPUT{ii}@'] = vv + # Outdir should be the same for all outputs + values['@OUTDIR@'] = os.path.dirname(outputs[0]) + # Many external programs fail on empty arguments. + if values['@OUTDIR@'] == '': + values['@OUTDIR@'] = '.' + return values + + +def _make_tree_writable(topdir: str) -> None: + # Ensure all files and directories under topdir are writable + # (and readable) by owner. + for d, _, files in os.walk(topdir): + os.chmod(d, os.stat(d).st_mode | stat.S_IWRITE | stat.S_IREAD) + for fname in files: + fpath = os.path.join(d, fname) + if os.path.isfile(fpath): + os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD) + + +def windows_proof_rmtree(f: str) -> None: + # On Windows if anyone is holding a file open you can't + # delete it. As an example an anti virus scanner might + # be scanning files you are trying to delete. The only + # way to fix this is to try again and again. + delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2] + writable = False + for d in delays: + try: + # Start by making the tree writable. + if not writable: + _make_tree_writable(f) + writable = True + except PermissionError: + time.sleep(d) + continue + try: + shutil.rmtree(f) + return + except FileNotFoundError: + return + except OSError: + time.sleep(d) + # Try one last time and throw if it fails. + shutil.rmtree(f) + + +def windows_proof_rm(fpath: str) -> None: + """Like windows_proof_rmtree, but for a single file.""" + if os.path.isfile(fpath): + os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD) + delays = [0.1, 0.1, 0.2, 0.2, 0.2, 0.5, 0.5, 1, 1, 1, 1, 2] + for d in delays: + try: + os.unlink(fpath) + return + except FileNotFoundError: + return + except OSError: + time.sleep(d) + os.unlink(fpath) + + +class TemporaryDirectoryWinProof(TemporaryDirectory): + """ + Like TemporaryDirectory, but cleans things up using + windows_proof_rmtree() + """ + + def __exit__(self, exc: T.Any, value: T.Any, tb: T.Any) -> None: + try: + super().__exit__(exc, value, tb) + except OSError: + windows_proof_rmtree(self.name) + + def cleanup(self) -> None: + try: + super().cleanup() + except OSError: + windows_proof_rmtree(self.name) + + +def detect_subprojects(spdir_name: str, current_dir: str = '', + result: T.Optional[T.Dict[str, T.List[str]]] = None) -> T.Dict[str, T.List[str]]: + if result is None: + result = {} + spdir = os.path.join(current_dir, spdir_name) + if not os.path.exists(spdir): + return result + for trial in glob(os.path.join(spdir, '*')): + basename = os.path.basename(trial) + if trial == 'packagecache': + continue + append_this = True + if os.path.isdir(trial): + detect_subprojects(spdir_name, trial, result) + elif trial.endswith('.wrap') and os.path.isfile(trial): + basename = os.path.splitext(basename)[0] + else: + append_this = False + if append_this: + if basename in result: + result[basename].append(trial) + else: + result[basename] = [trial] + return result + + +def substring_is_in_list(substr: str, strlist: T.List[str]) -> bool: + for s in strlist: + if substr in s: + return True + return False + + +class OrderedSet(T.MutableSet[_T]): + """A set that preserves the order in which items are added, by first + insertion. + """ + def __init__(self, iterable: T.Optional[T.Iterable[_T]] = None): + self.__container: T.OrderedDict[_T, None] = collections.OrderedDict() + if iterable: + self.update(iterable) + + def __contains__(self, value: object) -> bool: + return value in self.__container + + def __iter__(self) -> T.Iterator[_T]: + return iter(self.__container.keys()) + + def __len__(self) -> int: + return len(self.__container) + + def __repr__(self) -> str: + # Don't print 'OrderedSet("")' for an empty set. + if self.__container: + return 'OrderedSet("{}")'.format( + '", "'.join(repr(e) for e in self.__container.keys())) + return 'OrderedSet()' + + def __reversed__(self) -> T.Iterator[_T]: + return reversed(self.__container.keys()) + + def add(self, value: _T) -> None: + self.__container[value] = None + + def discard(self, value: _T) -> None: + if value in self.__container: + del self.__container[value] + + def move_to_end(self, value: _T, last: bool = True) -> None: + self.__container.move_to_end(value, last) + + def pop(self, last: bool = True) -> _T: + item, _ = self.__container.popitem(last) + return item + + def update(self, iterable: T.Iterable[_T]) -> None: + for item in iterable: + self.__container[item] = None + + def difference(self, set_: T.Iterable[_T]) -> 'OrderedSet[_T]': + return type(self)(e for e in self if e not in set_) + + def difference_update(self, iterable: T.Iterable[_T]) -> None: + for item in iterable: + self.discard(item) + +def relpath(path: str, start: str) -> str: + # On Windows a relative path can't be evaluated for paths on two different + # drives (i.e. c:\foo and f:\bar). The only thing left to do is to use the + # original absolute path. + try: + return os.path.relpath(path, start) + except (TypeError, ValueError): + return path + +def path_is_in_root(path: Path, root: Path, resolve: bool = False) -> bool: + # Check whether a path is within the root directory root + try: + if resolve: + path.resolve().relative_to(root.resolve()) + else: + path.relative_to(root) + except ValueError: + return False + return True + +def relative_to_if_possible(path: Path, root: Path, resolve: bool = False) -> Path: + try: + if resolve: + return path.resolve().relative_to(root.resolve()) + else: + return path.relative_to(root) + except ValueError: + return path + +class LibType(enum.IntEnum): + + """Enumeration for library types.""" + + SHARED = 0 + STATIC = 1 + PREFER_SHARED = 2 + PREFER_STATIC = 3 + + +class ProgressBarFallback: # lgtm [py/iter-returns-non-self] + ''' + Fallback progress bar implementation when tqdm is not found + + Since this class is not an actual iterator, but only provides a minimal + fallback, it is safe to ignore the 'Iterator does not return self from + __iter__ method' warning. + ''' + def __init__(self, iterable: T.Optional[T.Iterable[str]] = None, total: T.Optional[int] = None, + bar_type: T.Optional[str] = None, desc: T.Optional[str] = None, + disable: T.Optional[bool] = None): + if iterable is not None: + self.iterable = iter(iterable) + return + self.total = total + self.done = 0 + self.printed_dots = 0 + self.disable = not mlog.colorize_console() if disable is None else disable + if not self.disable: + if self.total and bar_type == 'download': + print('Download size:', self.total) + if desc: + print(f'{desc}: ', end='') + + # Pretend to be an iterator when called as one and don't print any + # progress + def __iter__(self) -> T.Iterator[str]: + return self.iterable + + def __next__(self) -> str: + return next(self.iterable) + + def print_dot(self) -> None: + if not self.disable: + print('.', end='') + sys.stdout.flush() + self.printed_dots += 1 + + def update(self, progress: int) -> None: + self.done += progress + if not self.total: + # Just print one dot per call if we don't have a total length + self.print_dot() + return + ratio = int(self.done / self.total * 10) + while self.printed_dots < ratio: + self.print_dot() + + def close(self) -> None: + if not self.disable: + print() + +try: + from tqdm import tqdm +except ImportError: + # ideally we would use a typing.Protocol here, but it's part of typing_extensions until 3.8 + ProgressBar = ProgressBarFallback # type: T.Union[T.Type[ProgressBarFallback], T.Type[ProgressBarTqdm]] +else: + class ProgressBarTqdm(tqdm): + def __init__(self, *args: T.Any, bar_type: T.Optional[str] = None, **kwargs: T.Any) -> None: + if bar_type == 'download': + kwargs.update({'unit': 'B', + 'unit_scale': True, + 'unit_divisor': 1024, + 'leave': True, + 'bar_format': '{l_bar}{bar}| {n_fmt}/{total_fmt} {rate_fmt} eta {remaining}', + }) + + else: + kwargs.update({'leave': False, + 'bar_format': '{l_bar}{bar}| {n_fmt}/{total_fmt} eta {remaining}', + }) + super().__init__(*args, **kwargs) + + ProgressBar = ProgressBarTqdm + + +class RealPathAction(argparse.Action): + def __init__(self, option_strings: T.List[str], dest: str, default: str = '.', **kwargs: T.Any): + default = os.path.abspath(os.path.realpath(default)) + super().__init__(option_strings, dest, nargs=None, default=default, **kwargs) + + def __call__(self, parser: argparse.ArgumentParser, namespace: argparse.Namespace, + values: T.Union[str, T.Sequence[T.Any], None], option_string: str = None) -> None: + assert isinstance(values, str) + setattr(namespace, self.dest, os.path.abspath(os.path.realpath(values))) + + +def get_wine_shortpath(winecmd: T.List[str], wine_paths: T.List[str], + workdir: T.Optional[str] = None) -> str: + ''' + WINEPATH size is limited to 1024 bytes which can easily be exceeded when + adding the path to every dll inside build directory. See + https://bugs.winehq.org/show_bug.cgi?id=45810. + + To shorten it as much as possible we use path relative to `workdir` + where possible and convert absolute paths to Windows shortpath (e.g. + "/usr/x86_64-w64-mingw32/lib" to "Z:\\usr\\X86_~FWL\\lib"). + + This limitation reportedly has been fixed with wine >= 6.4 + ''' + + # Remove duplicates + wine_paths = list(OrderedSet(wine_paths)) + + # Check if it's already short enough + wine_path = ';'.join(wine_paths) + if len(wine_path) <= 1024: + return wine_path + + # Check if we have wine >= 6.4 + from ..programs import ExternalProgram + wine = ExternalProgram('wine', winecmd, silent=True) + if version_compare(wine.get_version(), '>=6.4'): + return wine_path + + # Check paths that can be reduced by making them relative to workdir. + rel_paths = [] + if workdir: + abs_paths = [] + for p in wine_paths: + try: + rel = Path(p).relative_to(workdir) + rel_paths.append(str(rel)) + except ValueError: + abs_paths.append(p) + wine_paths = abs_paths + + if wine_paths: + # BAT script that takes a list of paths in argv and prints semi-colon separated shortpaths + with NamedTemporaryFile('w', suffix='.bat', encoding='utf-8', delete=False) as bat_file: + bat_file.write(''' + @ECHO OFF + for %%x in (%*) do ( + echo|set /p=;%~sx + ) + ''') + try: + stdout = subprocess.check_output(winecmd + ['cmd', '/C', bat_file.name] + wine_paths, + encoding='utf-8', stderr=subprocess.DEVNULL) + stdout = stdout.strip(';') + if stdout: + wine_paths = stdout.split(';') + else: + mlog.warning('Could not shorten WINEPATH: empty stdout') + except subprocess.CalledProcessError as e: + mlog.warning(f'Could not shorten WINEPATH: {str(e)}') + finally: + os.unlink(bat_file.name) + wine_path = ';'.join(rel_paths + wine_paths) + if len(wine_path) > 1024: + mlog.warning('WINEPATH exceeds 1024 characters which could cause issues') + return wine_path + + +def run_once(func: T.Callable[..., _T]) -> T.Callable[..., _T]: + ret = [] # type: T.List[_T] + + @wraps(func) + def wrapper(*args: T.Any, **kwargs: T.Any) -> _T: + if ret: + return ret[0] + + val = func(*args, **kwargs) + ret.append(val) + return val + + return wrapper + + +def generate_list(func: T.Callable[..., T.Generator[_T, None, None]]) -> T.Callable[..., T.List[_T]]: + @wraps(func) + def wrapper(*args: T.Any, **kwargs: T.Any) -> T.List[_T]: + return list(func(*args, **kwargs)) + + return wrapper + + +class OptionOverrideProxy(collections.abc.Mapping): + '''Mimic an option list but transparently override selected option + values. + ''' + + # TODO: the typing here could be made more explicit using a TypeDict from + # python 3.8 or typing_extensions + + def __init__(self, overrides: T.Dict['OptionKey', T.Any], options: 'KeyedOptionDictType', + subproject: T.Optional[str] = None): + self.overrides = overrides + self.options = options + self.subproject = subproject + + def __getitem__(self, key: 'OptionKey') -> 'UserOption': + # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal(). + # We should try to share the code somehow. + key = key.evolve(subproject=self.subproject) + if not key.is_project(): + opt = self.options.get(key) + if opt is None or opt.yielding: + opt = self.options[key.as_root()] + else: + opt = self.options[key] + if opt.yielding: + opt = self.options.get(key.as_root(), opt) + override_value = self.overrides.get(key.as_root()) + if override_value is not None: + opt = copy.copy(opt) + opt.set_value(override_value) + return opt + + def __iter__(self) -> T.Iterator['OptionKey']: + return iter(self.options) + + def __len__(self) -> int: + return len(self.options) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, OptionOverrideProxy): + return NotImplemented + t1 = (self.overrides, self.subproject, self.options) + t2 = (other.overrides, other.subproject, other.options) + return t1 == t2 + + +class OptionType(enum.IntEnum): + + """Enum used to specify what kind of argument a thing is.""" + + BUILTIN = 0 + BACKEND = 1 + BASE = 2 + COMPILER = 3 + PROJECT = 4 + +# This is copied from coredata. There is no way to share this, because this +# is used in the OptionKey constructor, and the coredata lists are +# OptionKeys... +_BUILTIN_NAMES = { + 'prefix', + 'bindir', + 'datadir', + 'includedir', + 'infodir', + 'libdir', + 'licensedir', + 'libexecdir', + 'localedir', + 'localstatedir', + 'mandir', + 'sbindir', + 'sharedstatedir', + 'sysconfdir', + 'auto_features', + 'backend', + 'buildtype', + 'debug', + 'default_library', + 'errorlogs', + 'genvslite', + 'install_umask', + 'layout', + 'optimization', + 'prefer_static', + 'stdsplit', + 'strip', + 'unity', + 'unity_size', + 'warning_level', + 'werror', + 'wrap_mode', + 'force_fallback_for', + 'pkg_config_path', + 'cmake_prefix_path', + 'vsenv', +} + + +def _classify_argument(key: 'OptionKey') -> OptionType: + """Classify arguments into groups so we know which dict to assign them to.""" + + if key.name.startswith('b_'): + return OptionType.BASE + elif key.lang is not None: + return OptionType.COMPILER + elif key.name in _BUILTIN_NAMES or key.module: + return OptionType.BUILTIN + elif key.name.startswith('backend_'): + assert key.machine is MachineChoice.HOST, str(key) + return OptionType.BACKEND + else: + assert key.machine is MachineChoice.HOST, str(key) + return OptionType.PROJECT + + +@total_ordering +class OptionKey: + + """Represents an option key in the various option dictionaries. + + This provides a flexible, powerful way to map option names from their + external form (things like subproject:build.option) to something that + internally easier to reason about and produce. + """ + + __slots__ = ['name', 'subproject', 'machine', 'lang', '_hash', 'type', 'module'] + + name: str + subproject: str + machine: MachineChoice + lang: T.Optional[str] + _hash: int + type: OptionType + module: T.Optional[str] + + def __init__(self, name: str, subproject: str = '', + machine: MachineChoice = MachineChoice.HOST, + lang: T.Optional[str] = None, + module: T.Optional[str] = None, + _type: T.Optional[OptionType] = None): + # the _type option to the constructor is kinda private. We want to be + # able tos ave the state and avoid the lookup function when + # pickling/unpickling, but we need to be able to calculate it when + # constructing a new OptionKey + object.__setattr__(self, 'name', name) + object.__setattr__(self, 'subproject', subproject) + object.__setattr__(self, 'machine', machine) + object.__setattr__(self, 'lang', lang) + object.__setattr__(self, 'module', module) + object.__setattr__(self, '_hash', hash((name, subproject, machine, lang, module))) + if _type is None: + _type = _classify_argument(self) + object.__setattr__(self, 'type', _type) + + def __setattr__(self, key: str, value: T.Any) -> None: + raise AttributeError('OptionKey instances do not support mutation.') + + def __getstate__(self) -> T.Dict[str, T.Any]: + return { + 'name': self.name, + 'subproject': self.subproject, + 'machine': self.machine, + 'lang': self.lang, + '_type': self.type, + 'module': self.module, + } + + def __setstate__(self, state: T.Dict[str, T.Any]) -> None: + """De-serialize the state of a pickle. + + This is very clever. __init__ is not a constructor, it's an + initializer, therefore it's safe to call more than once. We create a + state in the custom __getstate__ method, which is valid to pass + splatted to the initializer. + """ + # Mypy doesn't like this, because it's so clever. + self.__init__(**state) # type: ignore + + def __hash__(self) -> int: + return self._hash + + def _to_tuple(self) -> T.Tuple[str, OptionType, str, str, MachineChoice, str]: + return (self.subproject, self.type, self.lang or '', self.module or '', self.machine, self.name) + + def __eq__(self, other: object) -> bool: + if isinstance(other, OptionKey): + return self._to_tuple() == other._to_tuple() + return NotImplemented + + def __lt__(self, other: object) -> bool: + if isinstance(other, OptionKey): + return self._to_tuple() < other._to_tuple() + return NotImplemented + + def __str__(self) -> str: + out = self.name + if self.lang: + out = f'{self.lang}_{out}' + if self.machine is MachineChoice.BUILD: + out = f'build.{out}' + if self.module: + out = f'{self.module}.{out}' + if self.subproject: + out = f'{self.subproject}:{out}' + return out + + def __repr__(self) -> str: + return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r}, {self.lang!r}, {self.module!r}, {self.type!r})' + + @classmethod + def from_string(cls, raw: str) -> 'OptionKey': + """Parse the raw command line format into a three part tuple. + + This takes strings like `mysubproject:build.myoption` and Creates an + OptionKey out of them. + """ + try: + subproject, raw2 = raw.split(':') + except ValueError: + subproject, raw2 = '', raw + + module = None + for_machine = MachineChoice.HOST + try: + prefix, raw3 = raw2.split('.') + if prefix == 'build': + for_machine = MachineChoice.BUILD + else: + module = prefix + except ValueError: + raw3 = raw2 + + from ..compilers import all_languages + if any(raw3.startswith(f'{l}_') for l in all_languages): + lang, opt = raw3.split('_', 1) + else: + lang, opt = None, raw3 + assert ':' not in opt + assert '.' not in opt + + return cls(opt, subproject, for_machine, lang, module) + + def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None, + machine: T.Optional[MachineChoice] = None, lang: T.Optional[str] = '', + module: T.Optional[str] = '') -> 'OptionKey': + """Create a new copy of this key, but with altered members. + + For example: + >>> a = OptionKey('foo', '', MachineChoice.Host) + >>> b = OptionKey('foo', 'bar', MachineChoice.Host) + >>> b == a.evolve(subproject='bar') + True + """ + # We have to be a little clever with lang here, because lang is valid + # as None, for non-compiler options + return OptionKey( + name if name is not None else self.name, + subproject if subproject is not None else self.subproject, + machine if machine is not None else self.machine, + lang if lang != '' else self.lang, + module if module != '' else self.module + ) + + def as_root(self) -> 'OptionKey': + """Convenience method for key.evolve(subproject='').""" + return self.evolve(subproject='') + + def as_build(self) -> 'OptionKey': + """Convenience method for key.evolve(machine=MachineChoice.BUILD).""" + return self.evolve(machine=MachineChoice.BUILD) + + def as_host(self) -> 'OptionKey': + """Convenience method for key.evolve(machine=MachineChoice.HOST).""" + return self.evolve(machine=MachineChoice.HOST) + + def is_backend(self) -> bool: + """Convenience method to check if this is a backend option.""" + return self.type is OptionType.BACKEND + + def is_builtin(self) -> bool: + """Convenience method to check if this is a builtin option.""" + return self.type is OptionType.BUILTIN + + def is_compiler(self) -> bool: + """Convenience method to check if this is a builtin option.""" + return self.type is OptionType.COMPILER + + def is_project(self) -> bool: + """Convenience method to check if this is a project option.""" + return self.type is OptionType.PROJECT + + def is_base(self) -> bool: + """Convenience method to check if this is a base option.""" + return self.type is OptionType.BASE + + +def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL], suggest_reconfigure: bool = True) -> _PL: + load_fail_msg = f'{object_name} file {filename!r} is corrupted.' + extra_msg = ' Consider reconfiguring the directory with "meson setup --reconfigure".' if suggest_reconfigure else '' + try: + with open(filename, 'rb') as f: + obj = pickle.load(f) + except (pickle.UnpicklingError, EOFError): + raise MesonException(load_fail_msg + extra_msg) + except (TypeError, ModuleNotFoundError, AttributeError): + raise MesonException( + f"{object_name} file {filename!r} references functions or classes that don't " + "exist. This probably means that it was generated with an old " + "version of meson." + extra_msg) + + if not isinstance(obj, object_type): + raise MesonException(load_fail_msg + extra_msg) + + # Because these Protocols are not available at runtime (and cannot be made + # available at runtime until we drop support for Python < 3.8), we have to + # do a bit of hackery so that mypy understands what's going on here + version: str + if hasattr(obj, 'version'): + version = T.cast('_VerPickleLoadable', obj).version + else: + version = T.cast('_EnvPickleLoadable', obj).environment.coredata.version + + from ..coredata import version as coredata_version + from ..coredata import major_versions_differ, MesonVersionMismatchException + if major_versions_differ(version, coredata_version): + raise MesonVersionMismatchException(version, coredata_version, extra_msg) + return obj + + +def first(iter: T.Iterable[_T], predicate: T.Callable[[_T], bool]) -> T.Optional[_T]: + """Find the first entry in an iterable where the given predicate is true + + :param iter: The iterable to search + :param predicate: A finding function that takes an element from the iterable + and returns True if found, otherwise False + :return: The first found element, or None if it is not found + """ + for i in iter: + if predicate(i): + return i + return None diff --git a/devtools/meson/mesonbuild/utils/vsenv.py b/devtools/meson/mesonbuild/utils/vsenv.py new file mode 100644 index 0000000..e9a5c10 --- /dev/null +++ b/devtools/meson/mesonbuild/utils/vsenv.py @@ -0,0 +1,125 @@ +from __future__ import annotations + +import os +import subprocess +import json +import pathlib +import shutil +import tempfile +import locale + +from .. import mlog +from .universal import MesonException, is_windows, windows_detect_native_arch + + +__all__ = [ + 'setup_vsenv', +] + + +bat_template = '''@ECHO OFF + +call "{}" + +ECHO {} +SET +''' + +# If on Windows and VS is installed but not set up in the environment, +# set it to be runnable. In this way Meson can be directly invoked +# from any shell, VS Code etc. +def _setup_vsenv(force: bool) -> bool: + if not is_windows(): + return False + if os.environ.get('OSTYPE') == 'cygwin': + return False + if 'MESON_FORCE_VSENV_FOR_UNITTEST' not in os.environ: + # VSINSTALL is set when running setvars from a Visual Studio installation + # Tested with Visual Studio 2012 and 2017 + if 'VSINSTALLDIR' in os.environ: + return False + # Check explicitly for cl when on Windows + if shutil.which('cl.exe'): + return False + if not force: + if shutil.which('cc'): + return False + if shutil.which('gcc'): + return False + if shutil.which('clang'): + return False + if shutil.which('clang-cl'): + return False + + root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles") + bat_locator_bin = pathlib.Path(root, 'Microsoft Visual Studio/Installer/vswhere.exe') + if not bat_locator_bin.exists(): + raise MesonException(f'Could not find {bat_locator_bin}') + bat_json = subprocess.check_output( + [ + str(bat_locator_bin), + '-latest', + '-prerelease', + '-requiresAny', + '-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + '-requires', 'Microsoft.VisualStudio.Workload.WDExpress', + '-products', '*', + '-utf8', + '-format', + 'json' + ] + ) + bat_info = json.loads(bat_json) + if not bat_info: + # VS installer installed but not VS itself maybe? + raise MesonException('Could not parse vswhere.exe output') + bat_root = pathlib.Path(bat_info[0]['installationPath']) + if windows_detect_native_arch() == 'arm64': + bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsarm64.bat' + if not bat_path.exists(): + bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsx86_arm64.bat' + else: + bat_path = bat_root / 'VC/Auxiliary/Build/vcvars64.bat' + # if VS is not found try VS Express + if not bat_path.exists(): + bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsx86_amd64.bat' + if not bat_path.exists(): + raise MesonException(f'Could not find {bat_path}') + + mlog.log('Activating VS', bat_info[0]['catalog']['productDisplayVersion']) + bat_separator = '---SPLIT---' + bat_contents = bat_template.format(bat_path, bat_separator) + bat_file = tempfile.NamedTemporaryFile('w', suffix='.bat', encoding='utf-8', delete=False) + bat_file.write(bat_contents) + bat_file.flush() + bat_file.close() + bat_output = subprocess.check_output(bat_file.name, universal_newlines=True, + encoding=locale.getpreferredencoding(False)) + os.unlink(bat_file.name) + bat_lines = bat_output.split('\n') + bat_separator_seen = False + for bat_line in bat_lines: + if bat_line == bat_separator: + bat_separator_seen = True + continue + if not bat_separator_seen: + continue + if not bat_line: + continue + try: + k, v = bat_line.split('=', 1) + except ValueError: + # there is no "=", ignore junk data + pass + else: + os.environ[k] = v + return True + +def setup_vsenv(force: bool = False) -> bool: + try: + return _setup_vsenv(force) + except MesonException as e: + if force: + raise + mlog.warning('Failed to activate VS environment:', str(e)) + return False diff --git a/devtools/meson/mesonbuild/utils/win32.py b/devtools/meson/mesonbuild/utils/win32.py new file mode 100644 index 0000000..2bd4cba --- /dev/null +++ b/devtools/meson/mesonbuild/utils/win32.py @@ -0,0 +1,40 @@ +# SPDX-license-identifier: Apache-2.0 +# Copyright 2012-2021 The Meson development team +# Copyright © 2021 Intel Corporation + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Windows specific implementations of mesonlib functionality.""" + +import msvcrt +import typing as T + +from .universal import MesonException +from .platform import BuildDirLock as BuildDirLockBase + +__all__ = ['BuildDirLock'] + +class BuildDirLock(BuildDirLockBase): + + def __enter__(self) -> None: + self.lockfile = open(self.lockfilename, 'w', encoding='utf-8') + try: + msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1) + except (BlockingIOError, PermissionError): + self.lockfile.close() + raise MesonException('Some other Meson process is already using this build directory. Exiting.') + + def __exit__(self, *args: T.Any) -> None: + msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1) + self.lockfile.close() diff --git a/devtools/meson/mesonbuild/wrap/__init__.py b/devtools/meson/mesonbuild/wrap/__init__.py new file mode 100644 index 0000000..653f42a --- /dev/null +++ b/devtools/meson/mesonbuild/wrap/__init__.py @@ -0,0 +1,59 @@ +from enum import Enum + +# Used for the --wrap-mode command-line argument +# +# Special wrap modes: +# nofallback: Don't download wraps for dependency() fallbacks +# nodownload: Don't download wraps for all subproject() calls +# +# subprojects are used for two purposes: +# 1. To download and build dependencies by using .wrap +# files if they are not provided by the system. This is +# usually expressed via dependency(..., fallback: ...). +# 2. To download and build 'copylibs' which are meant to be +# used by copying into your project. This is always done +# with an explicit subproject() call. +# +# --wrap-mode=nofallback will never do (1) +# --wrap-mode=nodownload will do neither (1) nor (2) +# +# If you are building from a release tarball, you should be +# able to safely use 'nodownload' since upstream is +# expected to ship all required sources with the tarball. +# +# If you are building from a git repository, you will want +# to use 'nofallback' so that any 'copylib' wraps will be +# download as subprojects. +# +# --wrap-mode=forcefallback will ignore external dependencies, +# even if they match the version requirements, and automatically +# use the fallback if one was provided. This is useful for example +# to make sure a project builds when using the fallbacks. +# +# Note that these options do not affect subprojects that +# are git submodules since those are only usable in git +# repositories, and you almost always want to download them. + +# This did _not_ work when inside the WrapMode class. +# I don't know why. If you can fix this, patches welcome. +string_to_value = {'default': 1, + 'nofallback': 2, + 'nodownload': 3, + 'forcefallback': 4, + 'nopromote': 5, + } + +class WrapMode(Enum): + default = 1 + nofallback = 2 + nodownload = 3 + forcefallback = 4 + nopromote = 5 + + def __str__(self) -> str: + return self.name + + @staticmethod + def from_string(mode_name: str) -> 'WrapMode': + g = string_to_value[mode_name] + return WrapMode(g) diff --git a/devtools/meson/mesonbuild/wrap/__pycache__/__init__.cpython-37.pyc b/devtools/meson/mesonbuild/wrap/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f181c8b4575f20c263c2f89d8b18b434d0aaa4c GIT binary patch literal 880 zcmYjP&5qMB5VoDPN&2%aun6%2NV!ySKtc$i)xwGsl@JG{D3X=!xZSc&+_jTkv06^; zWAp`h2X4HDubg`0%!!$FyXr*qd2Elz-#78eaM)vLzyAK7evTRYLzA6#F*rtdFA#tM z*R13j=L`e{5JCsK5Uo3z_{boJWW^v+d>Lc`^uDmPzrj;1$u)w`h$zybPf}mK& zfn@?X(h*q*LDqpV>p~}sR1DoUhX~?Tm?f%*bELi&(1ZReT=J|B0~9dy@mE_cJ{eG! zI9s~F5@$=Du@M5w>snPewwjPYG8)O>qdQ8xW#1T<<74VYRg{WGr}XqEvk!6q-|2@p zIjF0AW;8fE$MsB&3^J-p8Ia+-8k(92sQof># zsnd+#9PSj1?lx25lM)q4B4Q6P>7FB`7K}atpwp8;3e~FCTk#MD&SBOE-RwUV~*h*tVj{8dB@&%DM3M_pth<~K+8-1bt&>A=UbWhbTYNr_|| ztuP))dD#@2cuQ&VtumVs(EGK0f&qdL@GAS5qJgW6dOj&teQv-$r3`BK9uUEn{s;p{ xl4Bn3K5-BT-tLam(1!{iv8DFdC%aR7mD<9s-uUg7@jH40jwlVD3%>p0;6I9+$u|H1 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/wrap/__pycache__/wrap.cpython-37.pyc b/devtools/meson/mesonbuild/wrap/__pycache__/wrap.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6022c6588bb3d993222b6b488b7c6d7530b8645b GIT binary patch literal 26773 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/wrap/__pycache__/wraptool.cpython-37.pyc b/devtools/meson/mesonbuild/wrap/__pycache__/wraptool.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..022c0c8aa21f5ec655d942a5d2757cce4873d270 GIT binary patch literal 7601 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 literal 0 HcmV?d00001 diff --git a/devtools/meson/mesonbuild/wrap/wrap.py b/devtools/meson/mesonbuild/wrap/wrap.py new file mode 100644 index 0000000..1b8dd37 --- /dev/null +++ b/devtools/meson/mesonbuild/wrap/wrap.py @@ -0,0 +1,836 @@ +# Copyright 2015 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from .. import mlog +import contextlib +from dataclasses import dataclass +import urllib.request +import urllib.error +import urllib.parse +import os +import hashlib +import shutil +import tempfile +import stat +import subprocess +import sys +import configparser +import time +import typing as T +import textwrap +import json + +from base64 import b64encode +from netrc import netrc +from pathlib import Path, PurePath + +from . import WrapMode +from .. import coredata +from ..mesonlib import quiet_git, GIT, ProgressBar, MesonException, windows_proof_rmtree, Popen_safe +from ..interpreterbase import FeatureNew +from ..interpreterbase import SubProject +from .. import mesonlib + +if T.TYPE_CHECKING: + import http.client + +try: + # Importing is just done to check if SSL exists, so all warnings + # regarding 'imported but unused' can be safely ignored + import ssl # noqa + has_ssl = True +except ImportError: + has_ssl = False + +REQ_TIMEOUT = 30.0 +WHITELIST_SUBDOMAIN = 'wrapdb.mesonbuild.com' + +ALL_TYPES = ['file', 'git', 'hg', 'svn'] + +PATCH = shutil.which('patch') + +def whitelist_wrapdb(urlstr: str) -> urllib.parse.ParseResult: + """ raises WrapException if not whitelisted subdomain """ + url = urllib.parse.urlparse(urlstr) + if not url.hostname: + raise WrapException(f'{urlstr} is not a valid URL') + if not url.hostname.endswith(WHITELIST_SUBDOMAIN): + raise WrapException(f'{urlstr} is not a whitelisted WrapDB URL') + if has_ssl and not url.scheme == 'https': + raise WrapException(f'WrapDB did not have expected SSL https url, instead got {urlstr}') + return url + +def open_wrapdburl(urlstring: str, allow_insecure: bool = False, have_opt: bool = False) -> 'http.client.HTTPResponse': + if have_opt: + insecure_msg = '\n\n To allow connecting anyway, pass `--allow-insecure`.' + else: + insecure_msg = '' + + url = whitelist_wrapdb(urlstring) + if has_ssl: + try: + return T.cast('http.client.HTTPResponse', urllib.request.urlopen(urllib.parse.urlunparse(url), timeout=REQ_TIMEOUT)) + except urllib.error.URLError as excp: + msg = f'WrapDB connection failed to {urlstring} with error {excp}.' + if isinstance(excp.reason, ssl.SSLCertVerificationError): + if allow_insecure: + mlog.warning(f'{msg}\n\n Proceeding without authentication.') + else: + raise WrapException(f'{msg}{insecure_msg}') + else: + raise WrapException(msg) + elif not allow_insecure: + raise WrapException(f'SSL module not available in {sys.executable}: Cannot contact the WrapDB.{insecure_msg}') + else: + # following code is only for those without Python SSL + mlog.warning(f'SSL module not available in {sys.executable}: WrapDB traffic not authenticated.', once=True) + + # If we got this far, allow_insecure was manually passed + nossl_url = url._replace(scheme='http') + try: + return T.cast('http.client.HTTPResponse', urllib.request.urlopen(urllib.parse.urlunparse(nossl_url), timeout=REQ_TIMEOUT)) + except urllib.error.URLError as excp: + raise WrapException(f'WrapDB connection failed to {urlstring} with error {excp}') + +def get_releases_data(allow_insecure: bool) -> bytes: + url = open_wrapdburl('https://wrapdb.mesonbuild.com/v2/releases.json', allow_insecure, True) + return url.read() + +def get_releases(allow_insecure: bool) -> T.Dict[str, T.Any]: + data = get_releases_data(allow_insecure) + return T.cast('T.Dict[str, T.Any]', json.loads(data.decode())) + +def update_wrap_file(wrapfile: str, name: str, new_version: str, new_revision: str, allow_insecure: bool) -> None: + url = open_wrapdburl(f'https://wrapdb.mesonbuild.com/v2/{name}_{new_version}-{new_revision}/{name}.wrap', + allow_insecure, True) + with open(wrapfile, 'wb') as f: + f.write(url.read()) + +def parse_patch_url(patch_url: str) -> T.Tuple[str, str]: + u = urllib.parse.urlparse(patch_url) + if u.netloc != 'wrapdb.mesonbuild.com': + raise WrapException(f'URL {patch_url} does not seems to be a wrapdb patch') + arr = u.path.strip('/').split('/') + if arr[0] == 'v1': + # e.g. https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/5/get_zip + return arr[-3], arr[-2] + elif arr[0] == 'v2': + # e.g. https://wrapdb.mesonbuild.com/v2/zlib_1.2.11-5/get_patch + tag = arr[-2] + _, version = tag.rsplit('_', 1) + version, revision = version.rsplit('-', 1) + return version, revision + else: + raise WrapException(f'Invalid wrapdb URL {patch_url}') + +class WrapException(MesonException): + pass + +class WrapNotFoundException(WrapException): + pass + +class PackageDefinition: + def __init__(self, fname: str, subproject: str = ''): + self.filename = fname + self.subproject = SubProject(subproject) + self.type = None # type: T.Optional[str] + self.values = {} # type: T.Dict[str, str] + self.provided_deps = {} # type: T.Dict[str, T.Optional[str]] + self.provided_programs = [] # type: T.List[str] + self.diff_files = [] # type: T.List[Path] + self.basename = os.path.basename(fname) + self.has_wrap = self.basename.endswith('.wrap') + self.name = self.basename[:-5] if self.has_wrap else self.basename + # must be lowercase for consistency with dep=variable assignment + self.provided_deps[self.name.lower()] = None + # What the original file name was before redirection + self.original_filename = fname + self.redirected = False + if self.has_wrap: + self.parse_wrap() + with open(fname, 'r', encoding='utf-8') as file: + self.wrapfile_hash = hashlib.sha256(file.read().encode('utf-8')).hexdigest() + self.directory = self.values.get('directory', self.name) + if os.path.dirname(self.directory): + raise WrapException('Directory key must be a name and not a path') + if self.type and self.type not in ALL_TYPES: + raise WrapException(f'Unknown wrap type {self.type!r}') + self.filesdir = os.path.join(os.path.dirname(self.filename), 'packagefiles') + + def parse_wrap(self) -> None: + try: + config = configparser.ConfigParser(interpolation=None) + config.read(self.filename, encoding='utf-8') + except configparser.Error as e: + raise WrapException(f'Failed to parse {self.basename}: {e!s}') + self.parse_wrap_section(config) + if self.type == 'redirect': + # [wrap-redirect] have a `filename` value pointing to the real wrap + # file we should parse instead. It must be relative to the current + # wrap file location and must be in the form foo/subprojects/bar.wrap. + dirname = Path(self.filename).parent + fname = Path(self.values['filename']) + for i, p in enumerate(fname.parts): + if i % 2 == 0: + if p == '..': + raise WrapException('wrap-redirect filename cannot contain ".."') + else: + if p != 'subprojects': + raise WrapException('wrap-redirect filename must be in the form foo/subprojects/bar.wrap') + if fname.suffix != '.wrap': + raise WrapException('wrap-redirect filename must be a .wrap file') + fname = dirname / fname + if not fname.is_file(): + raise WrapException(f'wrap-redirect {fname} filename does not exist') + self.filename = str(fname) + self.parse_wrap() + self.redirected = True + else: + self.parse_provide_section(config) + if 'patch_directory' in self.values: + FeatureNew('Wrap files with patch_directory', '0.55.0').use(self.subproject) + for what in ['patch', 'source']: + if f'{what}_filename' in self.values and f'{what}_url' not in self.values: + FeatureNew(f'Local wrap patch files without {what}_url', '0.55.0').use(self.subproject) + + def parse_wrap_section(self, config: configparser.ConfigParser) -> None: + if len(config.sections()) < 1: + raise WrapException(f'Missing sections in {self.basename}') + self.wrap_section = config.sections()[0] + if not self.wrap_section.startswith('wrap-'): + raise WrapException(f'{self.wrap_section!r} is not a valid first section in {self.basename}') + self.type = self.wrap_section[5:] + self.values = dict(config[self.wrap_section]) + if 'diff_files' in self.values: + FeatureNew('Wrap files with diff_files', '0.63.0').use(self.subproject) + for s in self.values['diff_files'].split(','): + path = Path(s.strip()) + if path.is_absolute(): + raise WrapException('diff_files paths cannot be absolute') + if '..' in path.parts: + raise WrapException('diff_files paths cannot contain ".."') + self.diff_files.append(path) + + def parse_provide_section(self, config: configparser.ConfigParser) -> None: + if config.has_section('provides'): + raise WrapException('Unexpected "[provides]" section, did you mean "[provide]"?') + if config.has_section('provide'): + for k, v in config['provide'].items(): + if k == 'dependency_names': + # A comma separated list of dependency names that does not + # need a variable name; must be lowercase for consistency with + # dep=variable assignment + names_dict = {n.strip().lower(): None for n in v.split(',')} + self.provided_deps.update(names_dict) + continue + if k == 'program_names': + # A comma separated list of program names + names_list = [n.strip() for n in v.split(',')] + self.provided_programs += names_list + continue + if not v: + m = (f'Empty dependency variable name for {k!r} in {self.basename}. ' + 'If the subproject uses meson.override_dependency() ' + 'it can be added in the "dependency_names" special key.') + raise WrapException(m) + self.provided_deps[k] = v + + def get(self, key: str) -> str: + try: + return self.values[key] + except KeyError: + raise WrapException(f'Missing key {key!r} in {self.basename}') + + def get_hashfile(self, subproject_directory: str) -> str: + return os.path.join(subproject_directory, '.meson-subproject-wrap-hash.txt') + + def update_hash_cache(self, subproject_directory: str) -> None: + if self.has_wrap: + with open(self.get_hashfile(subproject_directory), 'w', encoding='utf-8') as file: + file.write(self.wrapfile_hash + '\n') + +def get_directory(subdir_root: str, packagename: str) -> str: + fname = os.path.join(subdir_root, packagename + '.wrap') + if os.path.isfile(fname): + wrap = PackageDefinition(fname) + return wrap.directory + return packagename + +def verbose_git(cmd: T.List[str], workingdir: str, check: bool = False) -> bool: + ''' + Wrapper to convert GitException to WrapException caught in interpreter. + ''' + try: + return mesonlib.verbose_git(cmd, workingdir, check=check) + except mesonlib.GitException as e: + raise WrapException(str(e)) + +@dataclass(eq=False) +class Resolver: + source_dir: str + subdir: str + subproject: str = '' + wrap_mode: WrapMode = WrapMode.default + wrap_frontend: bool = False + allow_insecure: bool = False + silent: bool = False + + def __post_init__(self) -> None: + self.subdir_root = os.path.join(self.source_dir, self.subdir) + self.cachedir = os.path.join(self.subdir_root, 'packagecache') + self.wraps = {} # type: T.Dict[str, PackageDefinition] + self.netrc: T.Optional[netrc] = None + self.provided_deps = {} # type: T.Dict[str, PackageDefinition] + self.provided_programs = {} # type: T.Dict[str, PackageDefinition] + self.wrapdb: T.Dict[str, T.Any] = {} + self.wrapdb_provided_deps: T.Dict[str, str] = {} + self.wrapdb_provided_programs: T.Dict[str, str] = {} + self.load_wraps() + self.load_netrc() + self.load_wrapdb() + + def load_netrc(self) -> None: + try: + self.netrc = netrc() + except FileNotFoundError: + return + except Exception as e: + mlog.warning(f'failed to process netrc file: {e}.', fatal=False) + + def load_wraps(self) -> None: + if not os.path.isdir(self.subdir_root): + return + root, dirs, files = next(os.walk(self.subdir_root)) + ignore_dirs = {'packagecache', 'packagefiles'} + for i in files: + if not i.endswith('.wrap'): + continue + fname = os.path.join(self.subdir_root, i) + wrap = PackageDefinition(fname, self.subproject) + self.wraps[wrap.name] = wrap + ignore_dirs |= {wrap.directory, wrap.name} + # Add dummy package definition for directories not associated with a wrap file. + for i in dirs: + if i in ignore_dirs: + continue + fname = os.path.join(self.subdir_root, i) + wrap = PackageDefinition(fname, self.subproject) + self.wraps[wrap.name] = wrap + + for wrap in self.wraps.values(): + self.add_wrap(wrap) + + def add_wrap(self, wrap: PackageDefinition) -> None: + for k in wrap.provided_deps.keys(): + if k in self.provided_deps: + prev_wrap = self.provided_deps[k] + m = f'Multiple wrap files provide {k!r} dependency: {wrap.basename} and {prev_wrap.basename}' + raise WrapException(m) + self.provided_deps[k] = wrap + for k in wrap.provided_programs: + if k in self.provided_programs: + prev_wrap = self.provided_programs[k] + m = f'Multiple wrap files provide {k!r} program: {wrap.basename} and {prev_wrap.basename}' + raise WrapException(m) + self.provided_programs[k] = wrap + + def load_wrapdb(self) -> None: + try: + with Path(self.subdir_root, 'wrapdb.json').open('r', encoding='utf-8') as f: + self.wrapdb = json.load(f) + except FileNotFoundError: + return + for name, info in self.wrapdb.items(): + self.wrapdb_provided_deps.update({i: name for i in info.get('dependency_names', [])}) + self.wrapdb_provided_programs.update({i: name for i in info.get('program_names', [])}) + + def get_from_wrapdb(self, subp_name: str) -> PackageDefinition: + info = self.wrapdb.get(subp_name) + if not info: + return None + self.check_can_download() + latest_version = info['versions'][0] + version, revision = latest_version.rsplit('-', 1) + url = urllib.request.urlopen(f'https://wrapdb.mesonbuild.com/v2/{subp_name}_{version}-{revision}/{subp_name}.wrap') + fname = Path(self.subdir_root, f'{subp_name}.wrap') + with fname.open('wb') as f: + f.write(url.read()) + mlog.log(f'Installed {subp_name} version {version} revision {revision}') + wrap = PackageDefinition(str(fname)) + self.wraps[wrap.name] = wrap + self.add_wrap(wrap) + return wrap + + def merge_wraps(self, other_resolver: 'Resolver') -> None: + for k, v in other_resolver.wraps.items(): + self.wraps.setdefault(k, v) + for k, v in other_resolver.provided_deps.items(): + self.provided_deps.setdefault(k, v) + for k, v in other_resolver.provided_programs.items(): + self.provided_programs.setdefault(k, v) + + def find_dep_provider(self, packagename: str) -> T.Tuple[T.Optional[str], T.Optional[str]]: + # Python's ini parser converts all key values to lowercase. + # Thus the query name must also be in lower case. + packagename = packagename.lower() + wrap = self.provided_deps.get(packagename) + if wrap: + dep_var = wrap.provided_deps.get(packagename) + return wrap.name, dep_var + wrap_name = self.wrapdb_provided_deps.get(packagename) + return wrap_name, None + + def get_varname(self, subp_name: str, depname: str) -> T.Optional[str]: + wrap = self.wraps.get(subp_name) + return wrap.provided_deps.get(depname) if wrap else None + + def find_program_provider(self, names: T.List[str]) -> T.Optional[str]: + for name in names: + wrap = self.provided_programs.get(name) + if wrap: + return wrap.name + wrap_name = self.wrapdb_provided_programs.get(name) + if wrap_name: + return wrap_name + return None + + def resolve(self, packagename: str, method: str) -> str: + self.packagename = packagename + self.directory = packagename + self.wrap = self.wraps.get(packagename) + if not self.wrap: + self.wrap = self.get_from_wrapdb(packagename) + if not self.wrap: + m = f'Neither a subproject directory nor a {self.packagename}.wrap file was found.' + raise WrapNotFoundException(m) + self.directory = self.wrap.directory + + if self.wrap.has_wrap: + # We have a .wrap file, use directory relative to the location of + # the wrap file if it exists, otherwise source code will be placed + # into main project's subproject_dir even if the wrap file comes + # from another subproject. + self.dirname = os.path.join(os.path.dirname(self.wrap.filename), self.wrap.directory) + if not os.path.exists(self.dirname): + self.dirname = os.path.join(self.subdir_root, self.directory) + # Check if the wrap comes from the main project. + main_fname = os.path.join(self.subdir_root, self.wrap.basename) + if self.wrap.filename != main_fname: + rel = os.path.relpath(self.wrap.filename, self.source_dir) + mlog.log('Using', mlog.bold(rel)) + # Write a dummy wrap file in main project that redirect to the + # wrap we picked. + with open(main_fname, 'w', encoding='utf-8') as f: + f.write(textwrap.dedent(f'''\ + [wrap-redirect] + filename = {PurePath(os.path.relpath(self.wrap.filename, self.subdir_root)).as_posix()} + ''')) + else: + # No wrap file, it's a dummy package definition for an existing + # directory. Use the source code in place. + self.dirname = self.wrap.filename + rel_path = os.path.relpath(self.dirname, self.source_dir) + + if method == 'meson': + buildfile = os.path.join(self.dirname, 'meson.build') + elif method == 'cmake': + buildfile = os.path.join(self.dirname, 'CMakeLists.txt') + else: + raise WrapException('Only the methods "meson" and "cmake" are supported') + + # The directory is there and has meson.build? Great, use it. + if os.path.exists(buildfile): + self.validate() + return rel_path + + # Check if the subproject is a git submodule + self.resolve_git_submodule() + + if os.path.exists(self.dirname): + if not os.path.isdir(self.dirname): + raise WrapException('Path already exists but is not a directory') + else: + if self.wrap.type == 'file': + self.get_file() + else: + self.check_can_download() + if self.wrap.type == 'git': + self.get_git() + elif self.wrap.type == "hg": + self.get_hg() + elif self.wrap.type == "svn": + self.get_svn() + else: + raise WrapException(f'Unknown wrap type {self.wrap.type!r}') + try: + self.apply_patch() + self.apply_diff_files() + except Exception: + windows_proof_rmtree(self.dirname) + raise + + # A meson.build or CMakeLists.txt file is required in the directory + if not os.path.exists(buildfile): + raise WrapException(f'Subproject exists but has no {os.path.basename(buildfile)} file') + + # At this point, the subproject has been successfully resolved for the + # first time so save off the hash of the entire wrap file for future + # reference. + self.wrap.update_hash_cache(self.dirname) + + return rel_path + + def check_can_download(self) -> None: + # Don't download subproject data based on wrap file if requested. + # Git submodules are ok (see above)! + if self.wrap_mode is WrapMode.nodownload: + m = 'Automatic wrap-based subproject downloading is disabled' + raise WrapException(m) + + def resolve_git_submodule(self) -> bool: + # Is git installed? If not, we're probably not in a git repository and + # definitely cannot try to conveniently set up a submodule. + if not GIT: + return False + # Does the directory exist? Even uninitialised submodules checkout an + # empty directory to work in + if not os.path.isdir(self.dirname): + return False + # Are we in a git repository? + ret, out = quiet_git(['rev-parse'], Path(self.dirname).parent) + if not ret: + return False + # Is `dirname` a submodule? + ret, out = quiet_git(['submodule', 'status', '.'], self.dirname) + if not ret: + return False + # Submodule has not been added, add it + if out.startswith('+'): + mlog.warning('git submodule might be out of date') + return True + elif out.startswith('U'): + raise WrapException('git submodule has merge conflicts') + # Submodule exists, but is deinitialized or wasn't initialized + elif out.startswith('-'): + if verbose_git(['submodule', 'update', '--init', '.'], self.dirname): + return True + raise WrapException('git submodule failed to init') + # Submodule looks fine, but maybe it wasn't populated properly. Do a checkout. + elif out.startswith(' '): + verbose_git(['submodule', 'update', '.'], self.dirname) + verbose_git(['checkout', '.'], self.dirname) + # Even if checkout failed, try building it anyway and let the user + # handle any problems manually. + return True + elif out == '': + # It is not a submodule, just a folder that exists in the main repository. + return False + raise WrapException(f'Unknown git submodule output: {out!r}') + + def get_file(self) -> None: + path = self.get_file_internal('source') + extract_dir = self.subdir_root + # Some upstreams ship packages that do not have a leading directory. + # Create one for them. + if 'lead_directory_missing' in self.wrap.values: + os.mkdir(self.dirname) + extract_dir = self.dirname + shutil.unpack_archive(path, extract_dir) + + def get_git(self) -> None: + if not GIT: + raise WrapException(f'Git program not found, cannot download {self.packagename}.wrap via git.') + revno = self.wrap.get('revision') + checkout_cmd = ['-c', 'advice.detachedHead=false', 'checkout', revno, '--'] + is_shallow = False + depth_option = [] # type: T.List[str] + if self.wrap.values.get('depth', '') != '': + is_shallow = True + depth_option = ['--depth', self.wrap.values.get('depth')] + # for some reason git only allows commit ids to be shallowly fetched by fetch not with clone + if is_shallow and self.is_git_full_commit_id(revno): + # git doesn't support directly cloning shallowly for commits, + # so we follow https://stackoverflow.com/a/43136160 + verbose_git(['-c', 'init.defaultBranch=meson-dummy-branch', 'init', self.directory], self.subdir_root, check=True) + verbose_git(['remote', 'add', 'origin', self.wrap.get('url')], self.dirname, check=True) + revno = self.wrap.get('revision') + verbose_git(['fetch', *depth_option, 'origin', revno], self.dirname, check=True) + verbose_git(checkout_cmd, self.dirname, check=True) + if self.wrap.values.get('clone-recursive', '').lower() == 'true': + verbose_git(['submodule', 'update', '--init', '--checkout', + '--recursive', *depth_option], self.dirname, check=True) + push_url = self.wrap.values.get('push-url') + if push_url: + verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True) + else: + if not is_shallow: + verbose_git(['clone', self.wrap.get('url'), self.directory], self.subdir_root, check=True) + if revno.lower() != 'head': + if not verbose_git(checkout_cmd, self.dirname): + verbose_git(['fetch', self.wrap.get('url'), revno], self.dirname, check=True) + verbose_git(checkout_cmd, self.dirname, check=True) + else: + args = ['-c', 'advice.detachedHead=false', 'clone', *depth_option] + if revno.lower() != 'head': + args += ['--branch', revno] + args += [self.wrap.get('url'), self.directory] + verbose_git(args, self.subdir_root, check=True) + if self.wrap.values.get('clone-recursive', '').lower() == 'true': + verbose_git(['submodule', 'update', '--init', '--checkout', '--recursive', *depth_option], + self.dirname, check=True) + push_url = self.wrap.values.get('push-url') + if push_url: + verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True) + + def validate(self) -> None: + # This check is only for subprojects with wraps. + if not self.wrap.has_wrap: + return + + # Retrieve original hash, if it exists. + hashfile = self.wrap.get_hashfile(self.dirname) + if os.path.isfile(hashfile): + with open(hashfile, 'r', encoding='utf-8') as file: + expected_hash = file.read().strip() + else: + # If stored hash doesn't exist then don't warn. + return + + actual_hash = self.wrap.wrapfile_hash + + # Compare hashes and warn the user if they don't match. + if expected_hash != actual_hash: + mlog.warning(f'Subproject {self.wrap.name}\'s revision may be out of date; its wrap file has changed since it was first configured') + + def is_git_full_commit_id(self, revno: str) -> bool: + result = False + if len(revno) in {40, 64}: # 40 for sha1, 64 for upcoming sha256 + result = all(ch in '0123456789AaBbCcDdEeFf' for ch in revno) + return result + + def get_hg(self) -> None: + revno = self.wrap.get('revision') + hg = shutil.which('hg') + if not hg: + raise WrapException('Mercurial program not found.') + subprocess.check_call([hg, 'clone', self.wrap.get('url'), + self.directory], cwd=self.subdir_root) + if revno.lower() != 'tip': + subprocess.check_call([hg, 'checkout', revno], + cwd=self.dirname) + + def get_svn(self) -> None: + revno = self.wrap.get('revision') + svn = shutil.which('svn') + if not svn: + raise WrapException('SVN program not found.') + subprocess.check_call([svn, 'checkout', '-r', revno, self.wrap.get('url'), + self.directory], cwd=self.subdir_root) + + def get_netrc_credentials(self, netloc: str) -> T.Optional[T.Tuple[str, str]]: + if self.netrc is None or netloc not in self.netrc.hosts: + return None + + login, account, password = self.netrc.authenticators(netloc) + if account is not None: + login = account + + return login, password + + def get_data(self, urlstring: str) -> T.Tuple[str, str]: + blocksize = 10 * 1024 + h = hashlib.sha256() + tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False) + url = urllib.parse.urlparse(urlstring) + if url.hostname and url.hostname.endswith(WHITELIST_SUBDOMAIN): + resp = open_wrapdburl(urlstring, allow_insecure=self.allow_insecure, have_opt=self.wrap_frontend) + elif WHITELIST_SUBDOMAIN in urlstring: + raise WrapException(f'{urlstring} may be a WrapDB-impersonating URL') + else: + headers = {'User-Agent': f'mesonbuild/{coredata.version}'} + creds = self.get_netrc_credentials(url.netloc) + + if creds is not None and '@' not in url.netloc: + login, password = creds + if url.scheme == 'https': + enc_creds = b64encode(f'{login}:{password}'.encode()).decode() + headers.update({'Authorization': f'Basic {enc_creds}'}) + elif url.scheme == 'ftp': + urlstring = urllib.parse.urlunparse(url._replace(netloc=f'{login}:{password}@{url.netloc}')) + else: + mlog.warning('Meson is not going to use netrc credentials for protocols other than https/ftp', + fatal=False) + + try: + req = urllib.request.Request(urlstring, headers=headers) + resp = urllib.request.urlopen(req, timeout=REQ_TIMEOUT) + except urllib.error.URLError as e: + mlog.log(str(e)) + raise WrapException(f'could not get {urlstring} is the internet available?') + with contextlib.closing(resp) as resp, tmpfile as tmpfile: + try: + dlsize = int(resp.info()['Content-Length']) + except TypeError: + dlsize = None + if dlsize is None: + print('Downloading file of unknown size.') + while True: + block = resp.read(blocksize) + if block == b'': + break + h.update(block) + tmpfile.write(block) + hashvalue = h.hexdigest() + return hashvalue, tmpfile.name + sys.stdout.flush() + progress_bar = ProgressBar(bar_type='download', total=dlsize, + desc='Downloading', + disable=(self.silent or None)) + while True: + block = resp.read(blocksize) + if block == b'': + break + h.update(block) + tmpfile.write(block) + progress_bar.update(len(block)) + progress_bar.close() + hashvalue = h.hexdigest() + return hashvalue, tmpfile.name + + def check_hash(self, what: str, path: str, hash_required: bool = True) -> None: + if what + '_hash' not in self.wrap.values and not hash_required: + return + expected = self.wrap.get(what + '_hash').lower() + h = hashlib.sha256() + with open(path, 'rb') as f: + h.update(f.read()) + dhash = h.hexdigest() + if dhash != expected: + raise WrapException(f'Incorrect hash for {what}:\n {expected} expected\n {dhash} actual.') + + def get_data_with_backoff(self, urlstring: str) -> T.Tuple[str, str]: + delays = [1, 2, 4, 8, 16] + for d in delays: + try: + return self.get_data(urlstring) + except Exception as e: + mlog.warning(f'failed to download with error: {e}. Trying after a delay...', fatal=False) + time.sleep(d) + return self.get_data(urlstring) + + def download(self, what: str, ofname: str, fallback: bool = False) -> None: + self.check_can_download() + srcurl = self.wrap.get(what + ('_fallback_url' if fallback else '_url')) + mlog.log('Downloading', mlog.bold(self.packagename), what, 'from', mlog.bold(srcurl)) + try: + dhash, tmpfile = self.get_data_with_backoff(srcurl) + expected = self.wrap.get(what + '_hash').lower() + if dhash != expected: + os.remove(tmpfile) + raise WrapException(f'Incorrect hash for {what}:\n {expected} expected\n {dhash} actual.') + except WrapException: + if not fallback: + if what + '_fallback_url' in self.wrap.values: + return self.download(what, ofname, fallback=True) + mlog.log('A fallback URL could be specified using', + mlog.bold(what + '_fallback_url'), 'key in the wrap file') + raise + os.rename(tmpfile, ofname) + + def get_file_internal(self, what: str) -> str: + filename = self.wrap.get(what + '_filename') + if what + '_url' in self.wrap.values: + cache_path = os.path.join(self.cachedir, filename) + + if os.path.exists(cache_path): + self.check_hash(what, cache_path) + mlog.log('Using', mlog.bold(self.packagename), what, 'from cache.') + return cache_path + + os.makedirs(self.cachedir, exist_ok=True) + self.download(what, cache_path) + return cache_path + else: + path = Path(self.wrap.filesdir) / filename + + if not path.exists(): + raise WrapException(f'File "{path}" does not exist') + self.check_hash(what, path.as_posix(), hash_required=False) + + return path.as_posix() + + def apply_patch(self) -> None: + if 'patch_filename' in self.wrap.values and 'patch_directory' in self.wrap.values: + m = f'Wrap file {self.wrap.basename!r} must not have both "patch_filename" and "patch_directory"' + raise WrapException(m) + if 'patch_filename' in self.wrap.values: + path = self.get_file_internal('patch') + try: + shutil.unpack_archive(path, self.subdir_root) + except Exception: + with tempfile.TemporaryDirectory() as workdir: + shutil.unpack_archive(path, workdir) + self.copy_tree(workdir, self.subdir_root) + elif 'patch_directory' in self.wrap.values: + patch_dir = self.wrap.values['patch_directory'] + src_dir = os.path.join(self.wrap.filesdir, patch_dir) + if not os.path.isdir(src_dir): + raise WrapException(f'patch directory does not exist: {patch_dir}') + self.copy_tree(src_dir, self.dirname) + + def apply_diff_files(self) -> None: + for filename in self.wrap.diff_files: + mlog.log(f'Applying diff file "{filename}"') + path = Path(self.wrap.filesdir) / filename + if not path.exists(): + raise WrapException(f'Diff file "{path}" does not exist') + relpath = os.path.relpath(str(path), self.dirname) + if GIT: + # Git is more likely to be available on Windows and more likely + # to apply correctly assuming patches are often generated by git. + # See https://github.com/mesonbuild/meson/issues/12092. + # The `--work-tree` is necessary in case we're inside a + # Git repository: by default, Git will try to apply the patch to + # the repository root. + cmd = [GIT, '--work-tree', '.', 'apply', '-p1', relpath] + elif PATCH: + # Always pass a POSIX path to patch, because on Windows it's MSYS + cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] + else: + raise WrapException('Missing "patch" or "git" commands to apply diff files') + + p, out, _ = Popen_safe(cmd, cwd=self.dirname, stderr=subprocess.STDOUT) + if p.returncode != 0: + mlog.log(out.strip()) + raise WrapException(f'Failed to apply diff file "{filename}"') + + def copy_tree(self, root_src_dir: str, root_dst_dir: str) -> None: + """ + Copy directory tree. Overwrites also read only files. + """ + for src_dir, _, files in os.walk(root_src_dir): + dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + for file_ in files: + src_file = os.path.join(src_dir, file_) + dst_file = os.path.join(dst_dir, file_) + if os.path.exists(dst_file): + try: + os.remove(dst_file) + except PermissionError: + os.chmod(dst_file, stat.S_IWUSR) + os.remove(dst_file) + shutil.copy2(src_file, dst_dir) diff --git a/devtools/meson/mesonbuild/wrap/wraptool.py b/devtools/meson/mesonbuild/wrap/wraptool.py new file mode 100644 index 0000000..c009aa1 --- /dev/null +++ b/devtools/meson/mesonbuild/wrap/wraptool.py @@ -0,0 +1,231 @@ +# Copyright 2015-2016 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import sys, os +import configparser +import shutil +import typing as T + +from glob import glob +from .wrap import (open_wrapdburl, WrapException, get_releases, get_releases_data, + update_wrap_file, parse_patch_url) +from pathlib import Path + +from .. import mesonlib, msubprojects + +if T.TYPE_CHECKING: + import argparse + +def add_arguments(parser: 'argparse.ArgumentParser') -> None: + subparsers = parser.add_subparsers(title='Commands', dest='command') + subparsers.required = True + + p = subparsers.add_parser('list', help='show all available projects') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + p.set_defaults(wrap_func=list_projects) + + p = subparsers.add_parser('search', help='search the db by name') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + p.add_argument('name') + p.set_defaults(wrap_func=search) + + p = subparsers.add_parser('install', help='install the specified project') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + p.add_argument('name') + p.set_defaults(wrap_func=install) + + p = msubprojects.add_wrap_update_parser(subparsers) + p.set_defaults(wrap_func=msubprojects.run) + + p = subparsers.add_parser('info', help='show available versions of a project') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + p.add_argument('name') + p.set_defaults(wrap_func=info) + + p = subparsers.add_parser('status', help='show installed and available versions of your projects') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + p.set_defaults(wrap_func=status) + + p = subparsers.add_parser('promote', help='bring a subsubproject up to the master project') + p.add_argument('project_path') + p.set_defaults(wrap_func=promote) + + p = subparsers.add_parser('update-db', help='Update list of projects available in WrapDB (Since 0.61.0)') + p.add_argument('--allow-insecure', default=False, action='store_true', + help='Allow insecure server connections.') + p.set_defaults(wrap_func=update_db) + +def list_projects(options: 'argparse.Namespace') -> None: + releases = get_releases(options.allow_insecure) + for p in releases.keys(): + print(p) + +def search(options: 'argparse.Namespace') -> None: + name = options.name + releases = get_releases(options.allow_insecure) + for p, info in releases.items(): + if p.find(name) != -1: + print(p) + else: + for dep in info.get('dependency_names', []): + if dep.find(name) != -1: + print(f'Dependency {dep} found in wrap {p}') + +def get_latest_version(name: str, allow_insecure: bool) -> T.Tuple[str, str]: + releases = get_releases(allow_insecure) + info = releases.get(name) + if not info: + raise WrapException(f'Wrap {name} not found in wrapdb') + latest_version = info['versions'][0] + version, revision = latest_version.rsplit('-', 1) + return version, revision + +def install(options: 'argparse.Namespace') -> None: + name = options.name + if not os.path.isdir('subprojects'): + raise SystemExit('Subprojects dir not found. Run this script in your source root directory.') + if os.path.isdir(os.path.join('subprojects', name)): + raise SystemExit('Subproject directory for this project already exists.') + wrapfile = os.path.join('subprojects', name + '.wrap') + if os.path.exists(wrapfile): + raise SystemExit('Wrap file already exists.') + (version, revision) = get_latest_version(name, options.allow_insecure) + url = open_wrapdburl(f'https://wrapdb.mesonbuild.com/v2/{name}_{version}-{revision}/{name}.wrap', options.allow_insecure, True) + with open(wrapfile, 'wb') as f: + f.write(url.read()) + print(f'Installed {name} version {version} revision {revision}') + +def get_current_version(wrapfile: str) -> T.Tuple[str, str, str, str, T.Optional[str]]: + cp = configparser.ConfigParser(interpolation=None) + cp.read(wrapfile) + try: + wrap_data = cp['wrap-file'] + except KeyError: + raise WrapException('Not a wrap-file, cannot have come from the wrapdb') + try: + patch_url = wrap_data['patch_url'] + except KeyError: + # We assume a wrap without a patch_url is probably just an pointer to upstream's + # build files. The version should be in the tarball filename, even if it isn't + # purely guaranteed. The wrapdb revision should be 1 because it just needs uploading once. + branch = mesonlib.search_version(wrap_data['source_filename']) + revision, patch_filename = '1', None + else: + branch, revision = parse_patch_url(patch_url) + patch_filename = wrap_data['patch_filename'] + return branch, revision, wrap_data['directory'], wrap_data['source_filename'], patch_filename + +def update(options: 'argparse.Namespace') -> None: + name = options.name + if not os.path.isdir('subprojects'): + raise SystemExit('Subprojects dir not found. Run this command in your source root directory.') + wrapfile = os.path.join('subprojects', name + '.wrap') + if not os.path.exists(wrapfile): + raise SystemExit('Project ' + name + ' is not in use.') + (branch, revision, subdir, src_file, patch_file) = get_current_version(wrapfile) + (new_branch, new_revision) = get_latest_version(name, options.allow_insecure) + if new_branch == branch and new_revision == revision: + print('Project ' + name + ' is already up to date.') + raise SystemExit + update_wrap_file(wrapfile, name, new_branch, new_revision, options.allow_insecure) + shutil.rmtree(os.path.join('subprojects', subdir), ignore_errors=True) + try: + os.unlink(os.path.join('subprojects/packagecache', src_file)) + except FileNotFoundError: + pass + if patch_file is not None: + try: + os.unlink(os.path.join('subprojects/packagecache', patch_file)) + except FileNotFoundError: + pass + print(f'Updated {name} version {new_branch} revision {new_revision}') + +def info(options: 'argparse.Namespace') -> None: + name = options.name + releases = get_releases(options.allow_insecure) + info = releases.get(name) + if not info: + raise WrapException(f'Wrap {name} not found in wrapdb') + print(f'Available versions of {name}:') + for v in info['versions']: + print(' ', v) + +def do_promotion(from_path: str, spdir_name: str) -> None: + if os.path.isfile(from_path): + assert from_path.endswith('.wrap') + shutil.copy(from_path, spdir_name) + elif os.path.isdir(from_path): + sproj_name = os.path.basename(from_path) + outputdir = os.path.join(spdir_name, sproj_name) + if os.path.exists(outputdir): + raise SystemExit(f'Output dir {outputdir} already exists. Will not overwrite.') + shutil.copytree(from_path, outputdir, ignore=shutil.ignore_patterns('subprojects')) + +def promote(options: 'argparse.Namespace') -> None: + argument = options.project_path + spdir_name = 'subprojects' + sprojs = mesonlib.detect_subprojects(spdir_name) + + # check if the argument is a full path to a subproject directory or wrap file + system_native_path_argument = argument.replace('/', os.sep) + for matches in sprojs.values(): + if system_native_path_argument in matches: + do_promotion(system_native_path_argument, spdir_name) + return + + # otherwise the argument is just a subproject basename which must be unambiguous + if argument not in sprojs: + raise SystemExit(f'Subproject {argument} not found in directory tree.') + matches = sprojs[argument] + if len(matches) > 1: + print(f'There is more than one version of {argument} in tree. Please specify which one to promote:\n', file=sys.stderr) + for s in matches: + print(s, file=sys.stderr) + raise SystemExit(1) + do_promotion(matches[0], spdir_name) + +def status(options: 'argparse.Namespace') -> None: + print('Subproject status') + for w in glob('subprojects/*.wrap'): + name = os.path.basename(w)[:-5] + try: + (latest_branch, latest_revision) = get_latest_version(name, options.allow_insecure) + except Exception: + print('', name, 'not available in wrapdb.', file=sys.stderr) + continue + try: + (current_branch, current_revision, _, _, _) = get_current_version(w) + except Exception: + print('', name, 'Wrap file not from wrapdb.', file=sys.stderr) + continue + if current_branch == latest_branch and current_revision == latest_revision: + print('', name, f'up to date. Branch {current_branch}, revision {current_revision}.') + else: + print('', name, f'not up to date. Have {current_branch} {current_revision}, but {latest_branch} {latest_revision} is available.') + +def update_db(options: 'argparse.Namespace') -> None: + data = get_releases_data(options.allow_insecure) + Path('subprojects').mkdir(exist_ok=True) + with Path('subprojects/wrapdb.json').open('wb') as f: + f.write(data) + +def run(options: 'argparse.Namespace') -> int: + options.wrap_func(options) + return 0 diff --git a/devtools/meson/packaging/License.rtf b/devtools/meson/packaging/License.rtf new file mode 100644 index 0000000..b3945ba --- /dev/null +++ b/devtools/meson/packaging/License.rtf @@ -0,0 +1,73 @@ +{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}} +{\colortbl ;\red0\green0\blue255;} +{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\qc\lang1033\b\f0\fs18 Apache License\par +Version 2.0, January 2004\par +{\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/"}}{\fldrslt{\ul\cf1 http://www.apache.org/licenses/}}}\f0\fs18\par +\b0\par +\pard TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\par +\par +\pard\fi-180\li180 1. Definitions.\par +\par +\pard\li180 "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.\par +\par +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.\par +\par +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.\par +\par +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.\par +\par +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.\par +\par +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.\par +\par +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).\par +\par +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\par +\par +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."\par +\par +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.\par +\pard\par +\pard\fi-180\li180 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.\par +\par +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.\par +\par +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:\par +\pard\par +\pard\fi-270\li450 (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and\par +\par +(b) You must cause any modified files to carry prominent notices stating that You changed the files; and\par +\par +(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and\par +\par +(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.\par +\pard\par +\pard\li180 You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.\par +\pard\par +\pard\fi-180\li180 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.\par +\par +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.\par +\par +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.\par +\par +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.\par +\par +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.\par +\pard\par +END OF TERMS AND CONDITIONS\par +\par +APPENDIX: How to apply the Apache License to your work.\par +\par +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.\par +\par +\pard\li180 Copyright [yyyy] [name of copyright owner]\par +\par +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\par +\par +\pard\li360{\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/LICENSE-2.0"}}{\fldrslt{\ul\cf1 http://www.apache.org/licenses/LICENSE-2.0}}}\f0\fs18\par +\pard\li180\par +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\par +\pard\par +\par +} + \ No newline at end of file diff --git a/devtools/meson/packaging/create_zipapp.py b/devtools/meson/packaging/create_zipapp.py new file mode 100644 index 0000000..9fd0f5b --- /dev/null +++ b/devtools/meson/packaging/create_zipapp.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +import argparse +from pathlib import Path +import shutil +import sys +import tempfile +import zipapp + +parser = argparse.ArgumentParser() +parser.add_argument('source', nargs='?', default='.', help='Source directory') +parser.add_argument('--outfile', default='meson.pyz', help='Output file for the zipapp') +parser.add_argument('--interpreter', default='/usr/bin/env python3', help='The name of the Python interpreter to use') +parser.add_argument('--compress', action='store_true', default=False, help='Compress files') + +options = parser.parse_args(sys.argv[1:]) + +source = Path(options.source).resolve() + +with tempfile.TemporaryDirectory() as d: + shutil.copy2(source / 'meson.py', Path(d, '__main__.py')) + shutil.copytree(source / 'mesonbuild', Path(d, 'mesonbuild')) + zipapp.create_archive(d, interpreter=options.interpreter, target=options.outfile, compressed=options.compress) diff --git a/devtools/meson/packaging/createmsi.py b/devtools/meson/packaging/createmsi.py new file mode 100644 index 0000000..6f198f3 --- /dev/null +++ b/devtools/meson/packaging/createmsi.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python3 + +# Copyright 2017-2021 The Meson development team +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +''' +This script is for generating MSI packages +for Windows users. +''' + +import subprocess +import shutil +import uuid +import sys +import os +from glob import glob +import xml.etree.ElementTree as ET + +sys.path.append(os.getcwd()) +from mesonbuild import coredata + +# Elementtree does not support CDATA. So hack it. +WINVER_CHECK = 'Installed OR (VersionNT64 > 602)>' + +def gen_guid(): + ''' + Generate guid + ''' + return str(uuid.uuid4()).upper() + +class Node: + ''' + Node to hold path and directory values + ''' + + def __init__(self, dirs, files): + self.check_dirs(dirs) + self.check_files(files) + self.dirs = dirs + self.files = files + + @staticmethod + def check_dirs(dirs): + ''' + Check to see if directory is instance of list + ''' + assert isinstance(dirs, list) + + @staticmethod + def check_files(files): + ''' + Check to see if files is instance of list + ''' + assert isinstance(files, list) + + +class PackageGenerator: + ''' + Package generator for MSI packages + ''' + + def __init__(self): + self.product_name = 'Meson Build System' + self.manufacturer = 'The Meson Development Team' + self.version = coredata.version.replace('dev', '') + self.root = None + self.guid = '*' + self.update_guid = '141527EE-E28A-4D14-97A4-92E6075D28B2' + self.main_xml = 'meson.wxs' + self.main_o = 'meson.wixobj' + self.final_output = f'meson-{self.version}-64.msi' + self.staging_dirs = ['dist', 'dist2'] + self.progfile_dir = 'ProgramFiles64Folder' + redist_globs = ['C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Redist\\MSVC\\v*\\MergeModules\\Microsoft_VC142_CRT_x64.msm', + 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Redist\\MSVC\\v*\\MergeModules\\Microsoft_VC143_CRT_x64.msm'] + redist_path = None + for g in redist_globs: + trials = glob(g) + if len(trials) > 1: + sys.exit('MSM glob matched multiple entries:' + '\n'.join(trials)) + if len(trials) == 1: + redist_path = trials[0] + break + if redist_path is None: + sys.exit('No MSMs found.') + self.redist_path = redist_path + self.component_num = 0 + self.feature_properties = { + self.staging_dirs[0]: { + 'Id': 'MainProgram', + 'Title': 'Meson', + 'Description': 'Meson executables', + 'Level': '1', + 'AllowAbsent': 'no', + }, + self.staging_dirs[1]: { + 'Id': 'NinjaProgram', + 'Title': 'Ninja', + 'Description': 'Ninja build tool', + 'Level': '1', + } + } + self.feature_components = {} + for s_d in self.staging_dirs: + self.feature_components[s_d] = [] + + def build_dist(self): + ''' + Build dist file from PyInstaller info + ''' + for sdir in self.staging_dirs: + if os.path.exists(sdir): + shutil.rmtree(sdir) + main_stage, ninja_stage = self.staging_dirs + + pyinstaller = shutil.which('pyinstaller') + if not pyinstaller: + print("ERROR: This script requires pyinstaller.") + sys.exit(1) + + pyinstaller_tmpdir = 'pyinst-tmp' + if os.path.exists(pyinstaller_tmpdir): + shutil.rmtree(pyinstaller_tmpdir) + pyinst_cmd = [pyinstaller, + '--clean', + '--additional-hooks-dir=packaging', + '--distpath', + pyinstaller_tmpdir] + pyinst_cmd += ['meson.py'] + subprocess.check_call(pyinst_cmd) + shutil.move(pyinstaller_tmpdir + '/meson', main_stage) + self.del_infodirs(main_stage) + if not os.path.exists(os.path.join(main_stage, 'meson.exe')): + sys.exit('Meson exe missing from staging dir.') + os.mkdir(ninja_stage) + shutil.copy(shutil.which('ninja'), ninja_stage) + if not os.path.exists(os.path.join(ninja_stage, 'ninja.exe')): + sys.exit('Ninja exe missing from staging dir.') + + def del_infodirs(self, dirname): + # Starting with 3.9.something there are some + # extra metadatadirs that have a hyphen in their + # file names. This is a forbidden character in WiX + # filenames so delete them. + for d in glob(os.path.join(dirname, '*-info')): + shutil.rmtree(d) + + def generate_files(self): + ''' + Generate package files for MSI installer package + ''' + self.root = ET.Element('Wix', { + 'xmlns': 'http://wixtoolset.org/schemas/v4/wxs', + 'xmlns:ui': 'http://wixtoolset.org/schemas/v4/wxs/ui' + }) + + package = ET.SubElement(self.root, 'Package', { + 'Name': self.product_name, + 'Manufacturer': 'The Meson Development Team', + 'UpgradeCode': self.update_guid, + 'Language': '1033', + 'Codepage': '1252', + 'Version': self.version, + }) + + ET.SubElement(package, 'SummaryInformation', { + 'Keywords': 'Installer', + 'Description': f'Meson {self.version} installer', + 'Manufacturer': 'The Meson Development Team', + }) + + ET.SubElement(package, + 'Launch', + {'Message': 'This application is only supported on Windows 10 or higher.', + 'Condition': 'X'*len(WINVER_CHECK)}) + + ET.SubElement(package, 'MajorUpgrade', + {'DowngradeErrorMessage': + 'A newer version of Meson is already installed.'}) + + ET.SubElement(package, 'Media', { + 'Id': '1', + 'Cabinet': 'meson.cab', + 'EmbedCab': 'yes', + }) + targetdir = ET.SubElement(package, 'StandardDirectory', { + 'Id': 'ProgramFiles64Folder', + }) + installdir = ET.SubElement(targetdir, 'Directory', { + 'Id': 'INSTALLDIR', + 'Name': 'Meson', + }) + ET.SubElement(installdir, 'Merge', { + 'Id': 'VCRedist', + 'SourceFile': self.redist_path, + 'DiskId': '1', + 'Language': '0', + }) + + ET.SubElement(package, 'ui:WixUI', { + 'Id': 'WixUI_FeatureTree', + }) + for s_d in self.staging_dirs: + assert os.path.isdir(s_d) + top_feature = ET.SubElement(package, 'Feature', { + 'Id': 'Complete', + 'Title': 'Meson ' + self.version, + 'Description': 'The complete package', + 'Display': 'expand', + 'Level': '1', + 'ConfigurableDirectory': 'INSTALLDIR', + }) + for s_d in self.staging_dirs: + nodes = {} + for root, dirs, files in os.walk(s_d): + cur_node = Node(dirs, files) + nodes[root] = cur_node + self.create_xml(nodes, s_d, installdir, s_d) + self.build_features(top_feature, s_d) + vcredist_feature = ET.SubElement(top_feature, 'Feature', { + 'Id': 'VCRedist', + 'Title': 'Visual C++ runtime', + 'AllowAdvertise': 'no', + 'Display': 'hidden', + 'Level': '1', + }) + ET.SubElement(vcredist_feature, 'MergeRef', {'Id': 'VCRedist'}) + ET.ElementTree(self.root).write(self.main_xml, encoding='utf-8', xml_declaration=True) + # ElementTree cannot do pretty-printing, so do it manually + import xml.dom.minidom + doc = xml.dom.minidom.parse(self.main_xml) + with open(self.main_xml, 'w') as open_file: + open_file.write(doc.toprettyxml()) + # One last fix, add CDATA. + with open(self.main_xml) as open_file: + data = open_file.read() + data = data.replace('X'*len(WINVER_CHECK), WINVER_CHECK) + with open(self.main_xml, 'w') as open_file: + open_file.write(data) + + def build_features(self, top_feature, staging_dir): + ''' + Generate build features + ''' + feature = ET.SubElement(top_feature, 'Feature', self.feature_properties[staging_dir]) + for component_id in self.feature_components[staging_dir]: + ET.SubElement(feature, 'ComponentRef', { + 'Id': component_id, + }) + + def create_xml(self, nodes, current_dir, parent_xml_node, staging_dir): + ''' + Create XML file + ''' + cur_node = nodes[current_dir] + if cur_node.files: + component_id = f'ApplicationFiles{self.component_num}' + comp_xml_node = ET.SubElement(parent_xml_node, 'Component', { + 'Id': component_id, + 'Bitness': 'always64', + 'Guid': gen_guid(), + }) + self.feature_components[staging_dir].append(component_id) + if self.component_num == 0: + ET.SubElement(comp_xml_node, 'Environment', { + 'Id': 'Environment', + 'Name': 'PATH', + 'Part': 'last', + 'System': 'yes', + 'Action': 'set', + 'Value': '[INSTALLDIR]', + }) + self.component_num += 1 + for f_node in cur_node.files: + file_id = os.path.join(current_dir, f_node).replace('\\', '_').replace('#', '_').replace('-', '_') + ET.SubElement(comp_xml_node, 'File', { + 'Id': file_id, + 'Name': f_node, + 'Source': os.path.join(current_dir, f_node), + }) + + for dirname in cur_node.dirs: + dir_id = os.path.join(current_dir, dirname).replace('\\', '_').replace('/', '_') + dir_node = ET.SubElement(parent_xml_node, 'Directory', { + 'Id': dir_id, + 'Name': dirname, + }) + self.create_xml(nodes, os.path.join(current_dir, dirname), dir_node, staging_dir) + + def build_package(self): + ''' + Generate the Meson build MSI package. + ''' + subprocess.check_call(['wix', + 'build', + '-bindvariable', 'WixUILicenseRtf=packaging\\License.rtf', + '-ext', 'WixToolset.UI.wixext', + '-culture', 'en-us', + '-arch', 'x64', + '-o', + self.final_output, + self.main_xml, + ]) + + +def install_wix(): + subprocess.check_call(['dotnet', + 'nuget', + 'add', + 'source', + 'https://api.nuget.org/v3/index.json']) + subprocess.check_call(['dotnet', + 'tool', + 'install', + '--global', + 'wix']) + subprocess.check_call(['wix', + 'extension', + 'add', + 'WixToolset.UI.wixext', + ]) + +if __name__ == '__main__': + if not os.path.exists('meson.py'): + sys.exit(print('Run me in the top level source dir.')) + if not shutil.which('wix'): + install_wix() + subprocess.check_call(['pip', 'install', '--upgrade', 'pyinstaller']) + + p = PackageGenerator() + p.build_dist() + p.generate_files() + p.build_package() diff --git a/devtools/meson/packaging/createpkg.py b/devtools/meson/packaging/createpkg.py new file mode 100644 index 0000000..fd022d9 --- /dev/null +++ b/devtools/meson/packaging/createpkg.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +# Copyright 2017-2021 The Meson development team +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import shutil, sys, os +from glob import glob + +import xml.etree.ElementTree as ET + +sys.path.append(os.getcwd()) +from mesonbuild import coredata + +class PkgGenerator: + + def __init__(self): + self.pkg_dir = 'macpkg' + self.sharedir = os.path.join(self.pkg_dir, 'usr/local/share') + self.bindir = os.path.join(self.pkg_dir, 'usr/local/bin') + self.product_name = 'Meson Build System' + self.identifier = 'com.mesonbuild.meson' + self.version = coredata.version.replace('dev', '') + self.mesonstashdir = os.path.join(self.sharedir, f'meson-{self.version}') + self.pkgname = 'meson.pkg' + self.productname = f'meson-{self.version}.pkg' + self.distribution_file = 'meson-distribution.xml' + self.resourcedir = 'packaging/macpages' + + def build_dist(self): + if os.path.exists(self.pkg_dir): + shutil.rmtree(self.pkg_dir) + os.mkdir(self.pkg_dir) + pyinstaller_bin = glob('/Users/jpakkane/Library/Python/*/bin/pyinstaller') + if len(pyinstaller_bin) != 1: + sys.exit('Could not determine unique installer.') + pyinstaller_bin = pyinstaller_bin[0] + pyinst_cmd = [pyinstaller_bin, + '--clean', + '--additional-hooks-dir=packaging', + '--distpath', + self.pkg_dir] + pyinst_cmd += ['meson.py'] + subprocess.check_call(pyinst_cmd) + tmpdir = os.path.join(self.pkg_dir, 'meson') + shutil.move(tmpdir, self.mesonstashdir) + os.makedirs(self.bindir) + ln_base = os.path.relpath(self.mesonstashdir, self.bindir) + ninja_bin = shutil.which('ninja') + assert ninja_bin + shutil.copy(ninja_bin, self.bindir) + subprocess.check_call(['strip', os.path.join(self.bindir, 'ninja')]) + os.symlink(os.path.join(ln_base, 'meson'), os.path.join(self.bindir, 'meson')) + + def build_package(self): + subprocess.check_call(['pkgbuild', + '--root', + self.pkg_dir, + '--identifier', + self.identifier, + self.pkgname]) + self.generate_distribution() + subprocess.check_call(['productbuild', + '--distribution', + self.distribution_file, + '--resources', + self.resourcedir, + self.productname]) + + def generate_distribution(self): + root = ET.Element('installer-gui-script', {'minSpecVersion': '1'}) + ET.SubElement(root, 'welcome', {'file': 'welcome.html', + 'mime-type': 'text/html'}) + ET.SubElement(root, 'license', {'file': 'license.html', + 'mime-type': 'text/html'}) + ET.SubElement(root, 'conclusion', {'file': 'conclusion.html', + 'mime-type': 'text/html'}) + ET.SubElement(root, 'pkg-ref', {'id': self.identifier}) + ET.SubElement(root, 'options', {'customize': 'never', + 'require-scripts': 'false', + 'hostArchitectures': 'x86_64,arm64'}) + choices_outline = ET.SubElement(root, 'choices-outline') + line = ET.SubElement(choices_outline, 'line', {'choice': 'default'}) + ET.SubElement(line, 'line', {'choice': self.identifier}) + ET.SubElement(root, 'choice', {'id': 'default'}) + choice = ET.SubElement(root, 'choice', {'id': self.identifier, 'visible': 'false'}) + ET.SubElement(choice, 'pkg-ref', {'id': self.identifier}) + ET.SubElement(root, 'pkg-ref', {'id': self.identifier, + 'version': '0', # self.version, + 'onConclusion': 'none'}).text = self.pkgname + ET.ElementTree(root).write(self.distribution_file, encoding='utf-8', xml_declaration=True) + # ElementTree cannot do pretty-printing, so do it manually + import xml.dom.minidom + doc = xml.dom.minidom.parse(self.distribution_file) + with open(self.distribution_file, 'w') as open_file: + open_file.write(doc.toprettyxml()) + + def remove_tempfiles(self): + shutil.rmtree('macpkg') + os.unlink('meson-distribution.xml') + os.unlink('meson.pkg') + os.unlink('meson.spec') + +if __name__ == '__main__': + if not os.path.exists('meson.py'): + sys.exit(print('Run me in the top level source dir.')) + subprocess.check_call(['pip3', 'install', '--user', '--upgrade', 'pyinstaller']) + + pg = PkgGenerator() + pg.build_dist() + pg.build_package() + pg.remove_tempfiles() diff --git a/devtools/meson/packaging/hook-mesonbuild.py b/devtools/meson/packaging/hook-mesonbuild.py new file mode 100644 index 0000000..d6b06cd --- /dev/null +++ b/devtools/meson/packaging/hook-mesonbuild.py @@ -0,0 +1,60 @@ +#!hint/python3 + +""" +PyInstaller hook to make mesonbuild include everything it needs to. +""" + +import os +from glob import glob + +from PyInstaller.utils.hooks import collect_data_files + +datas = [] +hiddenimports = [] + +def get_all_modules_from_dir(dirname): + ''' + Get all modules required for Meson itself from directories. + ''' + modname = os.path.basename(dirname) + modules = [os.path.splitext(os.path.split(x)[1])[0] for x in glob(os.path.join(dirname, '*'))] + modules = ['mesonbuild.' + modname + '.' + x for x in modules if not x.startswith('_')] + return modules + +datas += collect_data_files('mesonbuild.scripts', include_py_files=True, excludes=['**/__pycache__']) +datas += collect_data_files('mesonbuild.cmake.data') +datas += collect_data_files('mesonbuild.dependencies.data') + +# lazy-loaded +hiddenimports += get_all_modules_from_dir('mesonbuild/dependencies') +# imported by meson.build files +hiddenimports += get_all_modules_from_dir('mesonbuild/modules') +# executed when named on CLI +hiddenimports += get_all_modules_from_dir('mesonbuild/scripts') + +# Python packagers want to be minimal and only copy the things +# that they can see being used. They are blind to many things. +hiddenimports += [ + # we run distutils as a subprocess via INTROSPECT_COMMAND. + 'distutils.archive_util', + 'distutils.cmd', + 'distutils.config', + 'distutils.core', + 'distutils.debug', + 'distutils.dep_util', + 'distutils.dir_util', + 'distutils.dist', + 'distutils.errors', + 'distutils.extension', + 'distutils.fancy_getopt', + 'distutils.file_util', + 'distutils.spawn', + 'distutils.util', + 'distutils.version', + 'distutils.command.build_ext', + 'distutils.command.build', + 'distutils.command.install', + + # needed for gtk's find_program() scripts + 'filecmp', +] diff --git a/devtools/meson/packaging/macpages/English.lproj/conclusion.html b/devtools/meson/packaging/macpages/English.lproj/conclusion.html new file mode 100644 index 0000000..0522455 --- /dev/null +++ b/devtools/meson/packaging/macpages/English.lproj/conclusion.html @@ -0,0 +1,24 @@ + + + + + +