# 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 # . 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, features=None, output_category=None): """Template for Rust programs.""" RUST_PROGRAMS += [name] DisableWarningsForRust() if features: RUST_PROGRAM_FEATURES = features if output_category: RUST_PROGRAM_OUTPUT_CATEGORY = output_category @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 HostRustProgram(name, features=None, output_category=None): """Template for host Rust programs.""" HOST_RUST_PROGRAMS += [name] DisableWarningsForRust() if features: HOST_RUST_PROGRAM_FEATURES = features if output_category: HOST_RUST_PROGRAM_OUTPUT_CATEGORY = output_category @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", []) extra_deps = kwargs.pop("extra_deps", []) 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.extra_deps = extra_deps generated_file.flags = flags generated_file.force = force @template def MacOSBundle(output, **kwargs): """Assemble a macOS ``.app`` bundle. ``output`` is the bundle path. A ``skeleton`` directory is copied into ``Contents``. Optionally generated ``info_plist`` and ``strings`` are placed in ``Contents`` and ``Contents/Resources/``. ``binaries`` (``(source, dest_name)`` pairs) are installed into ``Contents/MacOS``. ``lproj`` names the localized resources directory under ``Contents/Resources`` (default ``English.lproj``). ``extra_files`` is a list of ``(source, dest)`` pairs installed relative to ``Contents``. ``stage`` is a directory whose entries are split between ``Contents/MacOS`` and ``Contents/Resources``: ``macos_files`` lists the entries that belong in ``MacOS`` (kept as symlinks) and ``macos_copy_files`` those that must be deep-copied there instead. ``moves`` lists ``(name, dest)`` pairs, each moving ``Contents/Resources/name`` to ``Contents/dest``. ``pkginfo``, if set, is written verbatim to ``Contents/PkgInfo``. ``copies`` lists additional paths the assembled bundle is copied to, so an identical bundle needed in several locations is only assembled once.""" skeleton = kwargs.pop("skeleton", None) info_plist = kwargs.pop("info_plist", None) strings = kwargs.pop("strings", None) lproj = kwargs.pop("lproj", "English.lproj") binaries = kwargs.pop("binaries", []) extra_files = kwargs.pop("extra_files", []) stage = kwargs.pop("stage", None) macos_files = kwargs.pop("macos_files", None) macos_copy_files = kwargs.pop("macos_copy_files", None) moves = kwargs.pop("moves", []) pkginfo = kwargs.pop("pkginfo", None) copies = kwargs.pop("copies", []) if kwargs: error(f"Unrecognized argument(s) to MacOSBundle: {', '.join(kwargs)}") MACOS_BUNDLES += [ { "bundle": output, "skeleton": skeleton, "info_plist": info_plist, "strings": strings, "lproj": lproj, "binaries": binaries, "extra_files": extra_files, "stage": stage, "macos_files": macos_files, "macos_copy_files": macos_copy_files, "moves": moves, "pkginfo": pkginfo, "copies": copies, } ] @template def LegacyTest(*args, **kwargs): """Add one test to LEGACY_RUN_TESTS with the given attributes.""" LEGACY_RUN_TESTS += [{"args": args}] test = LEGACY_RUN_TESTS[-1] test["env"] = kwargs.pop("env", None) test["description"] = kwargs.pop("description", None) test["depends"] = kwargs.pop("depends", ()) if kwargs: error("Unrecognized argument(s) to LegacyTest: %s" % ", ".join(kwargs)) @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")