[infra] Initial version of mesa BUILD.gn rules

First pass at building mesa using meson via GN templates. Specifically
this includes a wrapper for meson based builds, and runs it for mesa
when the tint fuzzer is built. This has successfully built the
software drivers locally, but has not been tested wrt linking/using
these outputs.

I fully expect this will need further adjustments as part of
integrating it into the fuzzer binary.

All of this work is guarded by a build flag and a DEPS flag, so should
not be downloaded or built unless someone intentionally turns it on.

Bug: 475840954

Change-Id: If132898831627cb7a1fdab54dd57de8f59c24e63
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/286395
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/.gitignore b/.gitignore
index 4d522a4..f3705f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,8 @@
 /third_party/libprotobuf-mutator/src
 /third_party/llvm-build
 /third_party/markupsafe
+/third_party/mesa/src
+/third_party/meson/src
 /third_party/ninja
 /third_party/node
 /third_party/node-addon-api
diff --git a/.gitmodules b/.gitmodules
index 0607686..e093cce 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -74,8 +74,8 @@
 	path = third_party/mesa/src
 	url = https://chromium.googlesource.com/external/gitlab.freedesktop.org/mesa/mesa/
 	gclient-condition = dawn_standalone and checkout_mesa
-[submodule "third_party/meson"]
-	path = third_party/meson
+[submodule "third_party/meson/src"]
+	path = third_party/meson/src
 	url = https://chromium.googlesource.com/external/github.com/mesonbuild/meson
 	gclient-condition = dawn_standalone and checkout_mesa
 [submodule "third_party/jinja2"]
diff --git a/.vpython3 b/.vpython3
index 05f110a..16704c6 100644
--- a/.vpython3
+++ b/.vpython3
@@ -42,4 +42,23 @@
 wheel: <
   name: "infra/python/wheels/psutil/${vpython_platform}"
   version: "version:5.8.0.chromium.3"
+>
+
+# Needed by meson
+wheel: <
+  name: "infra/python/wheels/markupsafe/${vpython_platform}"
+  version: "version:2.0.1"
+>
+
+wheel: <
+  name: "infra/python/wheels/mako-py3"
+  version: "version:1.2.3"
+>
+
+wheel: <
+  name: "infra/python/wheels/pyyaml/${vpython_platform}"
+  version: "version:5.4.1.chromium.1"
+  match_tag: <
+    platform: "manylinux1_x86_64"
+  >
 >
\ No newline at end of file
diff --git a/DEPS b/DEPS
index a8b7cfc..3c4861e 100644
--- a/DEPS
+++ b/DEPS
@@ -279,7 +279,7 @@
     'url': '{chromium_git}/external/gitlab.freedesktop.org/mesa/mesa/@2e683eb7385c54f872acc47b371210d2282bc103',
     'condition': 'dawn_standalone and checkout_mesa',
   },
-  'third_party/meson': {
+  'third_party/meson/src': {
     'url': '{chromium_git}/external/github.com/mesonbuild/meson@d389906a136c2aac9820ded0f38d1e25ef25fb9a',
     'condition': 'dawn_standalone and checkout_mesa',
   },
diff --git a/build_overrides/mesa.gni b/build_overrides/mesa.gni
new file mode 100644
index 0000000..169c190
--- /dev/null
+++ b/build_overrides/mesa.gni
@@ -0,0 +1,31 @@
+# Copyright 2026 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+#
+# 2. 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.
+#
+# 3. Neither the name of the copyright holder 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.
+
+mesa_options = [
+  "-Dgallium-drivers=llvmpipe",
+  "-Dvulkan-drivers=swrast",
+]
diff --git a/build_overrides/tint.gni b/build_overrides/tint.gni
index e003c71..7321804 100644
--- a/build_overrides/tint.gni
+++ b/build_overrides/tint.gni
@@ -42,3 +42,4 @@
 tint_spirv_tools_dir = "//third_party/spirv-tools/src"
 tint_spirv_headers_dir = "//third_party/spirv-headers/src"
 tint_glslang_dir = "//third_party/glslang/src"
+tint_mesa_dir = "//third_party/mesa"
diff --git a/scripts/tint_overrides_with_defaults.gni b/scripts/tint_overrides_with_defaults.gni
index fb392ff..6582f03 100644
--- a/scripts/tint_overrides_with_defaults.gni
+++ b/scripts/tint_overrides_with_defaults.gni
@@ -75,6 +75,11 @@
     tint_lpm_dir = "//third_party/libprotobuf-mutator"
   }
 
+  # Path to mesa checkout
+  if (!defined(tint_mesa_dir)) {
+    tint_mesa_dir = "//third_party/mesa"
+  }
+
   if (!defined(tint_build_cmds)) {
     tint_build_cmds = tint_standalone
   }
@@ -148,6 +153,11 @@
   if (!defined(tint_enable_ir_validation)) {
     tint_enable_ir_validation = is_debug
   }
+
+  # Enable building Mesa as part of Tint fuzzers
+  if (!defined(tint_build_mesa)) {
+    tint_build_mesa = false
+  }
 }
 
 declare_args() {
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.bazel b/src/tint/cmd/fuzz/wgsl/BUILD.bazel
index 2b19c04..bdf7e7d 100644
--- a/src/tint/cmd/fuzz/wgsl/BUILD.bazel
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.bazel
@@ -53,6 +53,11 @@
 )
 
 alias(
+  name = "tint_build_mesa",
+  actual = "//src/tint:tint_build_mesa_true",
+)
+
+alias(
   name = "tint_build_msl_writer",
   actual = "//src/tint:tint_build_msl_writer_true",
 )
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.cfg b/src/tint/cmd/fuzz/wgsl/BUILD.cfg
index 2e2d939..b17eada 100644
--- a/src/tint/cmd/fuzz/wgsl/BUILD.cfg
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.cfg
@@ -6,7 +6,10 @@
         "AdditionalDependencies": {
             /* Depend on all the fuzz targets to pull them all together. */
             "Internal": [ "**:fuzz" ],
-            "External": ["dxcompiler-for-fuzzer"],
+            "External": [
+                "dxcompiler-for-fuzzer",
+                "mesa"
+            ],
         }
     }
 }
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.cmake b/src/tint/cmd/fuzz/wgsl/BUILD.cmake
index 7145d4b..dab87fb 100644
--- a/src/tint/cmd/fuzz/wgsl/BUILD.cmake
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.cmake
@@ -99,6 +99,12 @@
   )
 endif(TINT_BUILD_IR_BINARY)
 
+if(TINT_BUILD_MESA)
+  tint_target_add_external_dependencies(tint_cmd_fuzz_wgsl_fuzz_cmd fuzz_cmd
+    "mesa"
+  )
+endif(TINT_BUILD_MESA)
+
 if(TINT_BUILD_MSL_WRITER)
   tint_target_add_dependencies(tint_cmd_fuzz_wgsl_fuzz_cmd fuzz_cmd
     tint_lang_msl_writer_fuzz
diff --git a/src/tint/cmd/fuzz/wgsl/BUILD.gn b/src/tint/cmd/fuzz/wgsl/BUILD.gn
index 9acd390..1838e59 100644
--- a/src/tint/cmd/fuzz/wgsl/BUILD.gn
+++ b/src/tint/cmd/fuzz/wgsl/BUILD.gn
@@ -129,6 +129,10 @@
       deps += [ "${tint_src_dir}/lang/core/ir/binary:fuzz" ]
     }
 
+    if (tint_build_mesa) {
+      deps += [ "${tint_mesa_dir}:mesa" ]
+    }
+
     if (tint_build_msl_writer) {
       deps += [ "${tint_src_dir}/lang/msl/writer:fuzz" ]
     }
diff --git a/src/tint/externals.json b/src/tint/externals.json
index 38b0034..36ce6e7 100644
--- a/src/tint/externals.json
+++ b/src/tint/externals.json
@@ -40,6 +40,9 @@
         ],
         "Condition": "tint_build_tintd"
     },
+    "mesa": {
+        "Condition": "tint_build_mesa"
+    },
     "metal": {
         "IncludePatterns": [
             "Metal/Metal.h"
diff --git a/third_party/mesa/BUILD.gn b/third_party/mesa/BUILD.gn
new file mode 100644
index 0000000..6ec0fdc
--- /dev/null
+++ b/third_party/mesa/BUILD.gn
@@ -0,0 +1,36 @@
+# Copyright 2026 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+#
+# 2. 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.
+#
+# 3. Neither the name of the copyright holder 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.
+
+import("mesa_overrides_with_defaults.gni")
+
+import("${mesa_meson_dir}/meson_target.gni")
+
+meson_target("mesa") {
+  source_dir = "src"
+  options = mesa_options
+  outputs = [ "${target_gen_dir}/install" ]
+}
diff --git a/third_party/mesa/mesa_overrides_with_defaults.gni b/third_party/mesa/mesa_overrides_with_defaults.gni
new file mode 100644
index 0000000..fb31701
--- /dev/null
+++ b/third_party/mesa/mesa_overrides_with_defaults.gni
@@ -0,0 +1,38 @@
+# Copyright 2026 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+#
+# 2. 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.
+#
+# 3. Neither the name of the copyright holder 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.
+
+import("//build_overrides/mesa.gni")
+
+declare_args() {
+  if (!defined(mesa_meson_dir)) {
+    mesa_meson_dir = "//third_party/meson"
+  }
+
+  if (!defined(mesa_options)) {
+    mesa_options = []
+  }
+}
diff --git a/third_party/meson/meson_overrides_with_defaults.gni b/third_party/meson/meson_overrides_with_defaults.gni
new file mode 100644
index 0000000..16a195b
--- /dev/null
+++ b/third_party/meson/meson_overrides_with_defaults.gni
@@ -0,0 +1,37 @@
+# Copyright 2026 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+#
+# 2. 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.
+#
+# 3. Neither the name of the copyright holder 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.
+
+import("//build_overrides/meson.gni")
+
+declare_args() {
+  # Path to the meson source used in meson_target and helpers. Can not
+  # be inferred in the target, because it is in a .gni, so relative
+  # paths will be to where it is being used not declared.
+  if (!defined(meson_src_dir)) {
+    meson_src_dir = "//third_party/meson"
+  }
+}
diff --git a/third_party/meson/meson_target.gni b/third_party/meson/meson_target.gni
new file mode 100644
index 0000000..295f4d5
--- /dev/null
+++ b/third_party/meson/meson_target.gni
@@ -0,0 +1,202 @@
+# Copyright 2026 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+#
+# 2. 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.
+#
+# 3. Neither the name of the copyright holder 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.
+
+# Custom templates for wrapping Meson based builds, i.e. mesa, in GN
+# rules so that they can be used as part of the Dawn and Chromium
+# builds. These rules invoke meson for actually running the build
+# process, so behave like opaque external scripts.
+#
+# The external API is 'meson_target' at the bottom of this file
+#
+# Meson builds are split into two stages from the perspective of
+# GN. There is a `meson setup` stage which generates all of the
+# dynamic bits for the builds based on flags/vars and ensures that all
+# of the dependencies are present. This is equivalent to `gn gen` or
+# `cmake ../..`, and thus the `_meson_setup` targets will run during
+# `gn gen` to catch missing dependencies and others misconfigurations.
+#
+# The other stage is `meson install` which builds the targets and
+# copies the results into the appropriate output directory. This is
+# broadly equivalent of `ninja -C out/` or `ninja -C out/ all`. The
+# `_meson_build` target should depend on an appropriate `_meson_setup`
+# target to ensure necessary meson commands are run in order.
+
+# (Technically `meson install` can be separated into compile then
+# install calls, but since GN's behaviour is to build to the output
+# directory, they are being called as one command).
+
+import("meson_overrides_with_defaults.gni")
+
+import("//build/config/clang/clang.gni")
+
+# Internal helper that sets up a meson build, i.e. runs `meson setup`
+# with appropriate args based on the environment being used by GN.
+#
+#   src
+#       Specifies the path relative to the current BUILD.gn file where
+#       the source for the meson build is.
+#
+#   options
+#       Additional options to be passed into meson, often used for
+#       controlling what components should be configured for the
+#       build.
+template("_meson_setup") {
+  assert(defined(invoker.source_dir), "source_dir must be defined")
+
+  _meson_args = [
+    "setup",
+    rebase_path("${target_gen_dir}/${target_name}", root_build_dir),
+    rebase_path(invoker.source_dir, root_build_dir),
+    "--prefix=" + rebase_path("${target_gen_dir}/install"),
+  ]
+
+  if (defined(invoker.options)) {
+    _meson_args += invoker.options
+  }
+
+  # Use the hermetic clang toolchain
+  if (is_clang) {
+    _cc_path = rebase_path("$clang_base_path/bin/clang")
+    _cxx_path = rebase_path("$clang_base_path/bin/clang++")
+    _meson_args += [
+      "-Dc_link_args=-fuse-ld=lld",
+      "-Dcpp_link_args=-fuse-ld=lld",
+    ]
+
+    # Used by meson to allow specifying the toolchain elements to use
+    _native_file_content = [
+      "[binaries]",
+      "c = '${_cc_path}'",
+      "cpp = '${_cxx_path}'",
+      "ar = '" + rebase_path("$clang_base_path/bin/llvm-ar") + "'",
+      "strip = '" + rebase_path("$clang_base_path/bin/llvm-strip") + "'",
+      "pkg-config = 'pkg-config'",
+      "python = ['vpython3', '-vpython-spec', '" + rebase_path("//.vpython3") +
+          "']",
+    ]
+
+    _native_file_path = "${target_gen_dir}/${target_name}_native.ini"
+    write_file(_native_file_path, _native_file_content)
+
+    _meson_args += [
+      "--native-file",
+      rebase_path(_native_file_path, root_build_dir),
+    ]
+  }
+
+  exec_script("${meson_src_dir}/src/meson.py", _meson_args)
+
+  group(target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "deps",
+                             "public_deps",
+                             "testonly",
+                             "visibility",
+                           ])
+  }
+}
+
+# Internal helper that executes a previously setup meson build and
+# installs the output into a directory under the GN output/gen
+# directory.
+#
+#   meson_setup_target
+#       Specifies the meson_setup target that this target depends
+#       on. This ensures that it is run before this target, and
+#       coordinates the generated output path.
+template("_meson_build") {
+  action(target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "data_deps",
+                             "deps",
+                             "public_deps",
+                             "testonly",
+                             "visibility",
+                             "outputs",
+                           ])
+
+    assert(defined(invoker.meson_setup_target),
+           "meson_setup_target must be defined")
+
+    if (!defined(deps)) {
+      deps = []
+    }
+    deps += [ invoker.meson_setup_target ]
+
+    script = "${meson_src_dir}/src/meson.py"
+
+    _setup_gen_dir =
+        get_label_info(invoker.meson_setup_target, "target_gen_dir")
+    _setup_name = get_label_info(invoker.meson_setup_target, "name")
+    _build_dir = "${_setup_gen_dir}/${_setup_name}"
+
+    args = [
+      "install",
+      "-C",
+      rebase_path(_build_dir, root_build_dir),
+    ]
+  }
+}
+
+# Setups and builds a Meson based project
+#   src
+#       Specifies the path relative to the current BUILD.gn file where
+#       the source for the meson build is.
+#
+#   options
+#       Additional options to be passed into meson, often used for
+#       controlling what components should be configured for the
+#       build.
+template("meson_target") {
+  _meson_setup_target = "${target_name}_setup"
+
+  _meson_setup(_meson_setup_target) {
+    forward_variables_from(invoker,
+                           [
+                             "source_dir",
+                             "options",
+                             "deps",
+                             "public_deps",
+                             "testonly",
+                             "visibility",
+                           ])
+  }
+
+  _meson_build(target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "data_deps",
+                             "public_deps",
+                             "testonly",
+                             "visibility",
+                             "outputs",
+                           ])
+    meson_setup_target = ":${_meson_setup_target}"
+  }
+}
diff --git a/third_party/meson b/third_party/meson/src
similarity index 100%
rename from third_party/meson
rename to third_party/meson/src
diff --git a/tools/src/cmd/gen/build/BUILD.bazel.tmpl b/tools/src/cmd/gen/build/BUILD.bazel.tmpl
index f269a82..6e1730c 100644
--- a/tools/src/cmd/gen/build/BUILD.bazel.tmpl
+++ b/tools/src/cmd/gen/build/BUILD.bazel.tmpl
@@ -151,6 +151,7 @@
 {{-   else if eq $.Name "gtest"                          -}}"@gtest",
 {{-   else if eq $.Name "jsoncpp"                        -}}{{/* unsupported */}}
 {{-   else if eq $.Name "langsvr"                        -}}{{/* unsupported */}}
+{{-   else if eq $.Name "mesa"                           -}}{{/* unsupported */}}
 {{-   else if eq $.Name "metal"                          -}}{{/* unsupported */}}
 {{-   else if eq $.Name "spirv-headers"                  -}}"@spirv_headers//:spirv_cpp11_headers", "@spirv_headers//:spirv_c_headers",
 {{-   else if eq $.Name "spirv-opt-internal"             -}}"@spirv_tools//:spirv_tools_opt",
diff --git a/tools/src/cmd/gen/build/BUILD.gn.tmpl b/tools/src/cmd/gen/build/BUILD.gn.tmpl
index aa65d67..3e6b59c 100644
--- a/tools/src/cmd/gen/build/BUILD.gn.tmpl
+++ b/tools/src/cmd/gen/build/BUILD.gn.tmpl
@@ -176,6 +176,7 @@
 {{-   else if eq $.Name "jsoncpp"                        -}}"${tint_src_dir}:jsoncpp",
 {{-   else if eq $.Name "langsvr"                        -}}"${tint_src_dir}:langsvr",
 {{-   else if eq $.Name "libprotobuf-mutator"            -}}"${tint_lpm_dir}:libprotobuf-mutator",
+{{-   else if eq $.Name "mesa"                           -}}"${tint_mesa_dir}:mesa",
 {{-   else if eq $.Name "metal"                          -}}"${tint_src_dir}:metal",
 {{-   else if eq $.Name "spirv-headers"                  -}}"${tint_spirv_headers_dir}:spv_headers",
 {{-   else if eq $.Name "spirv-opt-internal"             -}}"${tint_spirv_tools_dir}:spvtools", "${tint_spirv_tools_dir}:spvtools_opt", "${tint_spirv_tools_dir}:spvtools_val",