build/templates.mozbuild
author Serban Stanca <sstanca@mozilla.com>
Thu, 17 Jul 2025 20:21:32 +0300 (12 hours ago)
changeset 797003 7ec5a911287f51bc177058928bb102163a3b656e
parent 791144 d651a633b5dc1a272b520b0b6a913d9fba8c67bb
permissions -rw-r--r--
Revert "Bug 1977690 - Remove unused AppRequestInterceptor in androidTests r=aaronmt" for causing fenix-debug failures. This reverts commit bc9dc5f4296482e17560627acaacd2797e462211.
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.


@template
def Binary():
    """Generic template for target binaries. Meant to be used by other
    templates."""

    # Add -llog by default, since we use it all over the place.
    if CONFIG["OS_TARGET"] == "Android":
        OS_LIBS += ["log"]


@template
def MaybeAddProfiling(name):
    if (
        CONFIG["MOZ_ENABLE_FORKSERVER"]
        and CONFIG["NIGHTLY_BUILD"]
        and CONFIG["OS_TARGET"] == "Linux"
        and CONFIG["MOZ_PROFILE_GENERATE"] == "1"
    ):
        USE_LIBS += ["profiling"]


@template
def Program(name):
    """Template for program executables."""
    PROGRAM = name

    MaybeAddProfiling(name)

    Binary()


@template
def SimplePrograms(names, ext=".cpp"):
    """Template for simple program executables.

    Those have a single source with the same base name as the executable.
    """
    SIMPLE_PROGRAMS += names
    SOURCES += ["%s%s" % (name, ext) for name in names]

    Binary()


@template
def CppUnitTests(names, ext=".cpp"):
    """Template for C++ unit tests.

    Those have a single source with the same base name as the executable.
    """
    COMPILE_FLAGS["EXTRA_INCLUDES"] = [
        "-I%s/dist/include" % TOPOBJDIR,
        "-I%s/dist/include/testing" % TOPOBJDIR,
    ]
    CPP_UNIT_TESTS += names
    SOURCES += ["%s%s" % (name, ext) for name in names]

    Binary()


@template
def Library(name):
    """Template for libraries."""
    LIBRARY_NAME = name


@template
def AllowCompilerWarnings():
    COMPILE_FLAGS["WARNINGS_AS_ERRORS"] = []
    WASM_FLAGS["WARNINGS_AS_ERRORS"] = []


@template
def DisableCompilerWarnings():
    # Keep the -Wno-* flags to disable warnings that may be enabled through other means.
    def filter(flags):
        return [f for f in flags or [] if f.startswith("-Wno-")]

    COMPILE_FLAGS["WARNINGS_CFLAGS"] = filter(CONFIG["WARNINGS_CFLAGS"])
    COMPILE_FLAGS["WARNINGS_CXXFLAGS"] = filter(CONFIG["WARNINGS_CXXFLAGS"])
    HOST_COMPILE_FLAGS["WARNINGS_CFLAGS"] = filter(CONFIG["WARNINGS_HOST_CFLAGS"])
    HOST_COMPILE_FLAGS["WARNINGS_CXXFLAGS"] = filter(CONFIG["WARNINGS_HOST_CXXFLAGS"])


@template
def DisableWarningsForRust():
    """Template to disable warnings when compiling rust (rust build scripts
    compile C/C++ sources which we can't control easily). Meant to be used by
    other templates.
    """
    # Some Rust build scripts compile C/C++ sources, don't error on warnings for them.
    AllowCompilerWarnings()

    # And furthermore, don't even show warnings for them, so they don't regress
    # the Compiler Warnings build metric
    # <https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Automated_Performance_Testing_and_Sheriffing/Build_Metrics#compiler_warnings>.
    DisableCompilerWarnings()


@template
def RustLibrary(name, features=None, output_category=None, is_gkrust=False):
    """Template for Rust libraries."""
    Library(name)

    IS_RUST_LIBRARY = True

    DisableWarningsForRust()

    if features:
        RUST_LIBRARY_FEATURES = features

    if output_category:
        RUST_LIBRARY_OUTPUT_CATEGORY = output_category

    if is_gkrust:
        IS_GKRUST = True


@template
def RustProgram(name):
    """Template for Rust programs."""
    RUST_PROGRAMS += [name]
    DisableWarningsForRust()


@template
def SharedLibrary(name, output_category=None):
    """Template for shared libraries."""
    Library(name)

    FORCE_SHARED_LIB = True

    if output_category:
        SHARED_LIBRARY_OUTPUT_CATEGORY = output_category

    MaybeAddProfiling(name)

    Binary()


@template
def Framework(name, output_category=None):
    """Template for OSX Frameworks."""
    SharedLibrary(name, output_category)

    IS_FRAMEWORK = True


@template
def HostProgram(name):
    """Template for build tools executables."""
    HOST_PROGRAM = name


@template
def HostSimplePrograms(names, ext=".cpp"):
    """Template for simple build tools executables.

    Those have a single source with the same base name as the executable.
    """
    HOST_SIMPLE_PROGRAMS += names
    HOST_SOURCES += ["%s%s" % (name.replace("host_", ""), ext) for name in names]


@template
def HostSharedLibrary(name):
    """Template for build tools libraries."""
    if name != "clang-plugin":
        error(
            "Please make sure host shared library support is complete "
            "before using for something else than the clang plugin"
        )

    HOST_LIBRARY_NAME = name

    FORCE_SHARED_LIB = True


@template
def HostLibrary(name):
    """Template for build tools libraries."""
    HOST_LIBRARY_NAME = name


@template
def HostRustLibrary(name, features=None):
    """Template for host Rust libraries."""
    HostLibrary(name)

    IS_RUST_LIBRARY = True
    # Some Rust build scripts compile C/C++ sources, don't error on warnings for them.
    AllowCompilerWarnings()

    if features:
        HOST_RUST_LIBRARY_FEATURES = features


@template
def DisableStlWrapping():
    COMPILE_FLAGS["STL"] = []


@template
def NoVisibilityFlags():
    COMPILE_FLAGS["VISIBILITY"] = []


@template
def ForceInclude(*headers):
    """Force includes a set of header files in C++ compilations"""
    if CONFIG["CC_TYPE"] == "clang-cl":
        include_flag = "-FI"
    else:
        include_flag = "-include"
    for header in headers:
        CXXFLAGS += [include_flag, header]


@template
def GeneratedFile(name, *names, **kwargs):
    """Add one or more GENERATED_FILES with the given attributes.

    You must pass in at least one generated file (the "name" argument). Other
    names can be included as positional arguments after "name"."""
    script = kwargs.pop("script", None)
    entry_point = kwargs.pop("entry_point", None)
    inputs = kwargs.pop("inputs", [])
    flags = kwargs.pop("flags", [])
    force = kwargs.pop("force", False)
    if kwargs:
        error("Unrecognized argument(s) to GeneratedFile: %s" % ", ".join(kwargs))
    if entry_point and not script:
        error("entry_point cannot be provided if script is not provided")
    if script and ":" in script:
        error(
            "script should not include a `:`. If you want to provide an "
            "alternative entry point for your script, use the entry_point "
            "parameter."
        )

    key = (name,) + names if names else name
    GENERATED_FILES += [key]
    generated_file = GENERATED_FILES[key]
    if script and not entry_point:
        generated_file.script = script
    if script and entry_point:
        generated_file.script = script + ":" + entry_point
    generated_file.inputs = inputs
    generated_file.flags = flags
    generated_file.force = force


@template
def CbindgenHeader(name, inputs):
    """Add one GENERATED_FILES by running RunCbindgen.py"""

    inputs = ["!/config/cbindgen-metadata.json"] + inputs
    GeneratedFile(
        name, script="/build/RunCbindgen.py", entry_point="generate", inputs=inputs
    )


include("gecko_templates.mozbuild")