| #!/usr/bin/env python3 |
| # |
| # Copyright 2025 Google LLC |
| # |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| # |
| """Builds Tint using CMake. |
| |
| This script configures and builds Tint using CMake and Ninja. It then |
| discovers all object files for the specified libraries and combines them |
| into a static archive (.a [Linux/Mac] or .lib [Windows]). |
| """ |
| |
| import argparse |
| import os |
| import shutil |
| import subprocess |
| import sys |
| |
| from cmake_utils import ( |
| add_common_cmake_args, combine_into_library, discover_dependencies, |
| get_cmake_os_cpu, get_windows_settings, quote_if_needed, write_depfile, |
| get_third_party_locations) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description="Build Tint using CMake.") |
| add_common_cmake_args(parser) |
| args = parser.parse_args() |
| |
| target_os, target_cpu = get_cmake_os_cpu(args.target_os, args.target_cpu) |
| |
| output_path = args.output_path |
| depfile_path = args.depfile_path |
| script_dir = os.path.dirname(os.path.realpath(__file__)) |
| dawn_dir = os.path.join(script_dir, "..", "externals", "dawn") |
| |
| # The build can be invoked in parallel for different toolchains, so we use |
| # a short, unique build directory. |
| build_dir = args.build_dir |
| |
| cmake_exe = shutil.which("cmake") |
| if not cmake_exe: |
| print("Error: cmake not found in PATH.") |
| sys.exit(1) |
| |
| ninja_exe = shutil.which("ninja") |
| if not ninja_exe: |
| print("Error: ninja not found in PATH.") |
| sys.exit(1) |
| |
| # Configure the project using CMake. Tint is a part of Dawn. |
| # https://github.com/google/dawn/blob/main/docs/quickstart-cmake.md |
| configure_cmd = [ |
| cmake_exe, |
| "-S", |
| dawn_dir, |
| "-B", |
| build_dir, |
| f"-DCMAKE_C_COMPILER={args.cc.replace(os.sep, '/')}", |
| f"-DCMAKE_CXX_COMPILER={args.cxx.replace(os.sep, '/')}", |
| f"-DCMAKE_SYSTEM_NAME={target_os}", |
| f"-DCMAKE_SYSTEM_PROCESSOR={target_cpu}", |
| # This is handled by GN |
| "-DDAWN_FETCH_DEPENDENCIES=OFF", |
| "-DDAWN_ENABLE_INSTALL=OFF", |
| f"-DCMAKE_BUILD_TYPE={args.build_type}", |
| # skslc needs WGSL support. |
| "-DTINT_BUILD_WGSL_READER=ON", |
| "-DTINT_BUILD_WGSL_WRITER=ON", |
| "-DTINT_ENABLE_INSTALL=ON", |
| # Use Ninja for faster builds. |
| "-G", |
| "Ninja", |
| f"-DCMAKE_MAKE_PROGRAM={ninja_exe}", |
| "-DDAWN_ENABLE_D3D11=OFF", |
| "-DDAWN_ENABLE_D3D12=OFF", |
| "-DDAWN_ENABLE_METAL=OFF", |
| "-DDAWN_ENABLE_NULL=OFF", |
| "-DDAWN_ENABLE_DESKTOP_GL=OFF", |
| "-DDAWN_ENABLE_OPENGLES=OFF", |
| "-DDAWN_ENABLE_VULKAN=OFF", |
| ] |
| configure_cmd += get_third_party_locations() |
| if args.enable_rtti: |
| configure_cmd.append("-DDAWN_ENABLE_RTTI=ON") |
| |
| cxx_flags = args.cxx_flags or [] |
| ld_flags = args.ld_flags or [] |
| |
| if target_os == "Windows": |
| win_cfgs, win_cxx, win_ld = get_windows_settings(args) |
| configure_cmd += win_cfgs |
| cxx_flags += win_cxx |
| ld_flags += win_ld |
| |
| if cxx_flags: |
| c_cxx_flags_str = " ".join(cxx_flags) |
| configure_cmd.append(f"-DCMAKE_CXX_FLAGS={c_cxx_flags_str}") |
| |
| if ld_flags: |
| ld_flags_str = " ".join(ld_flags) |
| configure_cmd.append(f"-DCMAKE_EXE_LINKER_FLAGS={ld_flags_str}") |
| configure_cmd.append(f"-DCMAKE_SHARED_LINKER_FLAGS={ld_flags_str}") |
| configure_cmd.append(f"-DCMAKE_MODULE_LINKER_FLAGS={ld_flags_str}") |
| |
| # Set PYTHONPATH to include Dawn's third_party directory. This is needed |
| # for the generator scripts to find jinja2 and markupsafe as packages. |
| third_party_dir = os.path.abspath(os.path.join(dawn_dir, "third_party")) |
| env = os.environ.copy() |
| env["PYTHONPATH"] = third_party_dir |
| # Don't write .pyc files, which can cause race conditions when building |
| # tint and dawn in parallel. |
| env["PYTHONDONTWRITEBYTECODE"] = "1" |
| |
| subprocess.run(configure_cmd, check=True, env=env) |
| |
| # These tint targets (and their deps) are what Skia needs to build |
| tint_targets = ["tint_api", "tint_lang_wgsl_reader", "tint_lang_wgsl_writer"] |
| |
| build_cmd = [ninja_exe, "-C", build_dir, "-dkeepdepfile"] + tint_targets |
| subprocess.run(build_cmd, check=True, env=env) |
| |
| dependencies, object_files = discover_dependencies(build_dir, tint_targets) |
| # Generate the depfile. This lists all source files that the Tint library |
| # depends on. This allows GN to know when to re-run this script. |
| write_depfile(output_path, depfile_path, dependencies) |
| |
| # After building, Tint consists of many small object files. For easier |
| # consumption by GN, we combine them into a single archive using ar. |
| combine_into_library(args, output_path, build_dir, target_os, object_files) |
| |
| |
| if __name__ == "__main__": |
| main() |