vcpkg/ports/webrtc/generate_external_third_par...

1094 lines
33 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import dataclasses
import pathlib
import shutil
NASM_ASSEMBLE_GNI = """# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This provides the nasm_assemble() template which uses NASM to assemble
# assembly files.
#
# Files to be assembled with NASM should have an extension of .asm.
#
# Parameters
#
# nasm_flags (optional)
# [list of strings] Pass additional flags into NASM. These are appended
# to the command line. Note that the output format is already set up
# based on the current toolchain so you don't need to specify these
# things (see below).
#
# Example: nasm_flags = [ "-Wall" ]
#
# include_dirs (optional)
# [list of dir names] List of additional include dirs. Note that the
# source root and the root generated file dir is always added, just like
# our C++ build sets up.
#
# Example: include_dirs = [ "//some/other/path", target_gen_dir ]
#
# defines (optional)
# [list of strings] List of defines, as with the native code defines.
#
# Example: defines = [ "FOO", "BAR=1" ]
#
# inputs, deps, visibility (optional)
# These have the same meaning as in an action.
#
# Example
#
# nasm_assemble("my_nasm_target") {
# sources = [
# "ultra_optimized_awesome.asm",
# ]
# include_dirs = [ "assembly_include" ]
# }
import("//build/compiled_action.gni")
import("//build/config/ios/config.gni")
import("//build/config/ios/ios_sdk_overrides.gni")
import("//build/config/sanitizers/sanitizers.gni")
if (is_mac) {
import("//build/config/mac/mac_sdk.gni")
}
if ((is_mac || is_ios) && (current_cpu == "x86" || current_cpu == "x64")) {
if (current_cpu == "x86") {
_nasm_flags = [ "-fmacho32" ]
} else if (current_cpu == "x64") {
_nasm_flags = [ "-fmacho64" ]
}
if (is_mac) {
_nasm_flags += [ "--macho-min-os=macos$mac_deployment_target" ]
} else if (is_ios) {
if (target_environment == "device") {
_nasm_flags += [ "--macho-min-os=ios$ios_deployment_target" ]
} else {
_nasm_flags +=
[ "--macho-min-os=ios$ios_deployment_target-$target_environment" ]
}
}
} else if (is_posix || is_fuchsia) {
if (current_cpu == "x86") {
_nasm_flags = [ "-felf32" ]
} else if (current_cpu == "x64") {
_nasm_flags = [
"-DPIC",
"-felf64",
]
}
} else if (is_win) {
if (current_cpu == "x86") {
_nasm_flags = [
"-DPREFIX",
"-fwin32",
]
} else if (current_cpu == "x64") {
_nasm_flags = [ "-fwin64" ]
}
}
if (is_win) {
asm_obj_extension = "obj"
} else {
asm_obj_extension = "o"
}
template("nasm_assemble") {
assert(defined(invoker.sources), "Need sources defined for $target_name")
# Only depend on NASM on x86 systems. Force compilation of .asm files for
# ARM to fail.
assert(current_cpu == "x86" || current_cpu == "x64")
action_name = "${target_name}_action"
source_set_name = target_name
action_foreach(action_name) {
# Only the source set can depend on this.
visibility = [ ":$source_set_name" ]
forward_variables_from(invoker,
[
"sources",
"inputs",
"deps",
])
if (!defined(deps)) {
deps = []
}
if (host_toolchain_is_msan) {
deps += [ "//third_party/instrumented_libs:ld-linux($host_toolchain)" ]
configs = [
"//third_party/instrumented_libs:msan_runtime_libs($host_toolchain)",
]
}
script = "{tool_path}"
args = _nasm_flags
if (defined(invoker.nasm_flags)) {
args += invoker.nasm_flags
}
args += [ "--reproducible" ]
if (defined(invoker.include_dirs)) {
foreach(include, invoker.include_dirs) {
args += [ "-I" + rebase_path(include, root_build_dir) + "/" ]
}
}
args += [
"-I./",
"-I" + rebase_path("//", root_build_dir),
"-I" + rebase_path(root_gen_dir, root_build_dir) + "/",
]
if (defined(invoker.defines)) {
foreach(def, invoker.defines) {
args += [ "-D$def" ]
}
}
outputs = [ "$target_out_dir/$source_set_name/{{source_name_part}}.${asm_obj_extension}" ]
args += [
"-MD",
rebase_path(outputs[0] + ".d", root_build_dir),
"-o",
rebase_path(outputs[0], root_build_dir),
"{{source}}",
]
depfile = outputs[0] + ".d"
}
static_library(source_set_name) {
if (defined(invoker.visibility)) {
visibility = invoker.visibility
}
if (defined(invoker.all_dependent_configs)) {
all_dependent_configs = invoker.all_dependent_configs
}
sources = get_target_outputs(":$action_name")
public = []
deps = [ ":$action_name" ]
}
}
"""
LIBSRTP_OPTIONS_GNI = """declare_args() {
libsrtp_build_boringssl = false
libsrtp_ssl_root = ""
}
"""
TESTING_TEST_GNI = """declare_args() {
tests_have_location_tags = false
use_fuzztest_wrapper = false
}
exec_target_suffix = ""
template("test") {
group(target_name) {
forward_variables_from(invoker, [
"testonly",
"visibility",
"deps",
"public_deps",
"data_deps",
])
}
}
"""
GOOGLETEST_BUILD_GN = """config("gtest_config") {
include_dirs = [
"custom",
"src/googletest/include",
]
}
config("gmock_config") {
include_dirs = [
"custom",
"src/googletest/include",
"src/googlemock/include",
]
}
source_set("gtest") {
testonly = true
public_configs = [ ":gtest_config" ]
sources = [
"src/googletest/include/gtest/gtest.h",
"src/googletest/src/gtest.cc",
]
}
source_set("gtest_main") {
testonly = true
public_configs = [ ":gtest_config" ]
deps = [ ":gtest" ]
sources = [ "src/googletest/src/gtest_main.cc" ]
}
source_set("gmock") {
testonly = true
public_configs = [ ":gmock_config" ]
deps = [ ":gtest" ]
sources = [
"src/googlemock/include/gmock/gmock.h",
"src/googlemock/src/gmock.cc",
]
}
source_set("gmock_main") {
testonly = true
public_configs = [ ":gmock_config" ]
deps = [ ":gmock" ]
sources = [ "src/googlemock/src/gmock_main.cc" ]
}
"""
NASM_BUILD_GN = ""
GOOGLETEST_GTEST_SPI_H = """#pragma once
#define EXPECT_FATAL_FAILURE(statement, substring) do { statement; } while (0)
#define EXPECT_NONFATAL_FAILURE(statement, substring) do { statement; } while (0)
"""
GOOGLETEST_GTEST_H = """#pragma once
#define GTEST_HAS_DEATH_TEST 0
#define FRIEND_TEST(test_case_name, test_name) friend class test_case_name##_##test_name##_Test
#define TEST(test_case_name, test_name) static void test_case_name##_##test_name()
#define TEST_F(test_fixture, test_name) static void test_fixture##_##test_name()
#define EXPECT_TRUE(condition) do { (void)(condition); } while (0)
#define EXPECT_FALSE(condition) do { (void)(condition); } while (0)
#define EXPECT_EQ(expected, actual) do { (void)(expected); (void)(actual); } while (0)
#define EXPECT_NE(expected, actual) do { (void)(expected); (void)(actual); } while (0)
#define ASSERT_TRUE(condition) do { (void)(condition); } while (0)
#define ASSERT_FALSE(condition) do { (void)(condition); } while (0)
#define ASSERT_EQ(expected, actual) do { (void)(expected); (void)(actual); } while (0)
namespace testing { class Test {}; }
"""
GOOGLETEST_ASSERTION_RESULT_H = """#pragma once
namespace testing { class AssertionResult {}; }
"""
GOOGLETEST_GTEST_PROD_H = """#pragma once
#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test
"""
TEST_MAIN_CC = """int main(int argc, char** argv) {
(void)argc;
(void)argv;
return 0;
}
"""
LIBAOM_OPTIONS_GNI = """import("//build/config/cast.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/gclient_args.gni")
declare_args() {
enable_libaom = !(is_android && current_cpu != "arm64" &&
current_cpu != "x64") && !is_castos
}
"""
LIBAOM_BUILD_GN = """config("libaom_public_config") {
include_dirs = [ "{include_root}" ]
}
config("libaom_config") {
include_dirs = [ "{include_root}" ]
}
config("libaom_link") {
lib_dirs = [ "{lib_root}" ]
libs = [ "aom" ]
}
source_set("libaom") {
public_configs = [ ":libaom_public_config" ]
configs += [
":libaom_config",
":libaom_link",
]
sources = [
"source/libaom/aom/aom_codec.h",
"source/libaom/aom/aom_encoder.h",
"source/libaom/aom/aom_image.h",
"source/libaom/aom/aomcx.h",
]
}
"""
LIBAOM_AOMCX_H = """#pragma once
#include <aom/aomcx.h>
#ifndef AOM_EFLAG_FREEZE_INTERNAL_STATE
#define AOM_EFLAG_FREEZE_INTERNAL_STATE 0
#endif
"""
PROTOBUF_BUILD_GN = """config("protobuf_config") {
}
group("protobuf_lite") {
public_configs = [ ":protobuf_config" ]
}
"""
PROTOBUF_PROTO_LIBRARY_GNI = """template("proto_library") {
group(target_name) {
forward_variables_from(invoker, [
"testonly",
"visibility",
])
}
}
"""
GENERATE_STUBS_SCRIPT = """#!/usr/bin/env python3
raise SystemExit("generate_stubs shim should not execute in this build")
"""
GENERATE_STUBS_RULES_GNI = """template("generate_stubs") {
group(target_name) {
forward_variables_from(invoker, [
"testonly",
"visibility",
"deps",
"public_deps",
"data_deps",
])
}
}
"""
def make_header_forwarder(include_path: str) -> str:
return f"""#pragma once
#include <{include_path}>
"""
def make_trivial_group_build_gn(*group_names: str) -> str:
return "\n\n".join(f'group("{group_name}") {{\n}}'
for group_name in group_names) + "\n"
def make_config_only_build_gn(config_name: str,
include_dirs: list[str]) -> str:
include_lines = "\n".join(f' "{include_dir}",'
for include_dir in include_dirs)
return f"""config("{config_name}") {{
include_dirs = [
{include_lines}
]
}}
"""
def make_linked_source_set_build_gn(
target_name: str,
include_dirs: list[str],
lib_name: str,
sources: list[str],
*,
public_config_name: str | None = None,
config_name: str | None = None,
testonly: bool = False,
deps: list[str] | None = None,
extra_configs: list[str] | None = None,
) -> str:
public_config_name = public_config_name or config_name or f"{target_name}_config"
config_name = config_name or public_config_name
deps = [] if deps is None else deps
extra_configs = [] if extra_configs is None else extra_configs
link_config_name = f"{target_name}_link"
def render_include_block(name: str) -> str:
include_lines = "\n".join(f' "{include_dir}",'
for include_dir in include_dirs)
return f"""config("{name}") {{
include_dirs = [
{include_lines}
]
}}"""
config_blocks = [render_include_block(public_config_name)]
if config_name != public_config_name:
config_blocks.append(render_include_block(config_name))
config_blocks.append(f"""config("{link_config_name}") {{
lib_dirs = [ "{{lib_root}}" ]
libs = [ "{lib_name}" ]
}}""")
source_lines = "\n".join(f' "{source}",' for source in sources)
target_lines = [f'source_set("{target_name}") {{']
if testonly:
target_lines.append(" testonly = true")
target_lines.append(f' public_configs = [ ":{public_config_name}" ]')
if deps:
deps_line = ", ".join(f'"{dep}"' for dep in deps)
target_lines.append(f" deps = [ {deps_line} ]")
configs = [f'":{link_config_name}"']
if config_name != public_config_name:
configs.insert(0, f'":{config_name}"')
configs.extend(f'"{config}"' for config in extra_configs)
if len(configs) == 1:
target_lines.append(f" configs += [ {configs[0]} ]")
else:
target_lines.append(" configs += [")
target_lines.extend(f" {config}," for config in configs)
target_lines.append(" ]")
target_lines.append(" sources = [")
target_lines.append(source_lines)
target_lines.append(" ]")
target_lines.append("}")
return "\n\n".join(config_blocks + ["\n".join(target_lines)]) + "\n"
SPECS = {
"libsrtp": {
"relative_root": "third_party/libsrtp",
"dirs": ["include", "srtp"],
"files": {
"options.gni":
LIBSRTP_OPTIONS_GNI,
"BUILD.gn":
"""import("//third_party/libsrtp/options.gni")
config("libsrtp_config") {
include_dirs = [ "{include_root}" ]
}
config("libsrtp_link") {
lib_dirs = [ "{lib_root}" ]
libs = [ "srtp2" ]
}
source_set("libsrtp") {
public_configs = [ ":libsrtp_config" ]
configs += [ ":libsrtp_link" ]
sources = [ "include/srtp.h" ]
}
""",
"include/srtp.h":
"""#pragma once
#if __has_include(<srtp.h>)
#include <srtp.h>
#else
#include <srtp2/srtp.h>
#endif
""",
},
},
"opus": {
"relative_root": "third_party/opus",
"dirs": ["src/include"],
"files": {
"BUILD.gn":
make_linked_source_set_build_gn(
"opus",
["{include_root}"],
"opus",
[
"src/include/opus.h",
"src/include/opus_defines.h",
"src/include/opus_multistream.h",
"src/include/opus_types.h",
],
),
"src/include/opus.h":
make_header_forwarder("opus/opus.h"),
"src/include/opus_defines.h":
make_header_forwarder("opus/opus_defines.h"),
"src/include/opus_multistream.h":
make_header_forwarder("opus/opus_multistream.h"),
"src/include/opus_types.h":
make_header_forwarder("opus/opus_types.h"),
},
},
"libvpx": {
"relative_root": "third_party/libvpx",
"dirs": ["source/libvpx/vpx"],
"files": {
"BUILD.gn":
make_linked_source_set_build_gn(
"libvpx",
["source/libvpx"],
"vpx",
[
"source/libvpx/vpx/vp8.h",
"source/libvpx/vpx/vp8cx.h",
"source/libvpx/vpx/vp8dx.h",
"source/libvpx/vpx/vpx_codec.h",
"source/libvpx/vpx/vpx_decoder.h",
"source/libvpx/vpx/vpx_encoder.h",
"source/libvpx/vpx/vpx_ext_ratectrl.h",
"source/libvpx/vpx/vpx_frame_buffer.h",
"source/libvpx/vpx/vpx_image.h",
"source/libvpx/vpx/vpx_integer.h",
],
public_config_name="libvpx_public_config",
config_name="libvpx_config",
),
"source/libvpx/vpx/vp8.h":
make_header_forwarder("vpx/vp8.h"),
"source/libvpx/vpx/vp8cx.h":
make_header_forwarder("vpx/vp8cx.h"),
"source/libvpx/vpx/vp8dx.h":
make_header_forwarder("vpx/vp8dx.h"),
"source/libvpx/vpx/vpx_codec.h":
make_header_forwarder("vpx/vpx_codec.h"),
"source/libvpx/vpx/vpx_decoder.h":
make_header_forwarder("vpx/vpx_decoder.h"),
"source/libvpx/vpx/vpx_encoder.h":
make_header_forwarder("vpx/vpx_encoder.h"),
"source/libvpx/vpx/vpx_ext_ratectrl.h":
make_header_forwarder("vpx/vpx_ext_ratectrl.h"),
"source/libvpx/vpx/vpx_frame_buffer.h":
make_header_forwarder("vpx/vpx_frame_buffer.h"),
"source/libvpx/vpx/vpx_image.h":
make_header_forwarder("vpx/vpx_image.h"),
"source/libvpx/vpx/vpx_integer.h":
make_header_forwarder("vpx/vpx_integer.h"),
},
},
"libyuv": {
"relative_root": "third_party/libyuv",
"dirs": ["include/libyuv"],
"files": {
"BUILD.gn":
make_linked_source_set_build_gn(
"libyuv",
["include"],
"yuv",
[
"include/libyuv/compare.h",
"include/libyuv/convert.h",
"include/libyuv/convert_from.h",
"include/libyuv/planar_functions.h",
"include/libyuv/rotate.h",
"include/libyuv/rotate_argb.h",
"include/libyuv/scale.h",
"include/libyuv/video_common.h",
],
),
"include/libyuv/compare.h":
make_header_forwarder("libyuv/compare.h"),
"include/libyuv/convert.h":
make_header_forwarder("libyuv/convert.h"),
"include/libyuv/convert_from.h":
make_header_forwarder("libyuv/convert_from.h"),
"include/libyuv/planar_functions.h":
make_header_forwarder("libyuv/planar_functions.h"),
"include/libyuv/rotate.h":
make_header_forwarder("libyuv/rotate.h"),
"include/libyuv/rotate_argb.h":
make_header_forwarder("libyuv/rotate_argb.h"),
"include/libyuv/scale.h":
make_header_forwarder("libyuv/scale.h"),
"include/libyuv/video_common.h":
make_header_forwarder("libyuv/video_common.h"),
},
},
"libaom": {
"relative_root": "third_party/libaom",
"dirs": ["source/libaom/aom"],
"files": {
"options.gni":
LIBAOM_OPTIONS_GNI,
"BUILD.gn":
LIBAOM_BUILD_GN,
"source/libaom/aom/aom_codec.h":
make_header_forwarder("aom/aom_codec.h"),
"source/libaom/aom/aom_encoder.h":
make_header_forwarder("aom/aom_encoder.h"),
"source/libaom/aom/aom_image.h":
make_header_forwarder("aom/aom_image.h"),
"source/libaom/aom/aomcx.h":
LIBAOM_AOMCX_H,
},
},
"jsoncpp": {
"relative_root": "third_party/jsoncpp",
"dirs": ["source/include"],
"files": {
"BUILD.gn":
make_linked_source_set_build_gn(
"jsoncpp",
["{include_root}"],
"jsoncpp",
["source/include/jsoncpp_shim.h"],
),
"source/include/jsoncpp_shim.h":
"#pragma once\n",
},
},
"dav1d": {
"relative_root": "third_party/dav1d",
"dirs": [],
"files": {
"BUILD.gn": make_trivial_group_build_gn("dav1d"),
},
},
"llvm-libc": {
"relative_root": "third_party/llvm-libc",
"dirs": [],
"files": {
"BUILD.gn": make_trivial_group_build_gn("llvm-libc-shared"),
},
},
"protobuf": {
"relative_root": "third_party/protobuf",
"dirs": [],
"files": {
"BUILD.gn": PROTOBUF_BUILD_GN,
"proto_library.gni": PROTOBUF_PROTO_LIBRARY_GNI,
},
},
"pffft": {
"relative_root": "third_party/pffft",
"dirs": ["src"],
"files": {
"BUILD.gn":
make_linked_source_set_build_gn(
"pffft",
["{include_root}"],
"pffft",
["src/pffft.h"],
),
"src/pffft.h":
make_header_forwarder("pffft/pffft.h"),
},
},
"alsa": {
"relative_root": "third_party/alsa",
"dirs": [],
"files": {
"BUILD.gn": make_config_only_build_gn("headers",
["{include_root}"]),
},
},
"pulseaudio": {
"relative_root": "third_party/pulseaudio",
"dirs": [],
"files": {
"BUILD.gn": make_config_only_build_gn("headers",
["{include_root}"]),
},
},
"third_party_root": {
"relative_root": "third_party",
"dirs": [],
"preserve_root": True,
"files": {
"BUILD.gn": make_trivial_group_build_gn("jpeg"),
},
},
"testing": {
"relative_root": "testing",
"dirs": ["gmock", "gtest"],
"files": {
"BUILD.gn":
"""group("pytype_dependencies") {
testonly = true
}
""",
"test.gni":
TESTING_TEST_GNI,
"gtest/BUILD.gn":
"""group("gtest") {
testonly = true
}
group("gtest_main") {
testonly = true
public_deps = [ ":gtest" ]
}
""",
"gmock/BUILD.gn":
"""group("gmock") {
testonly = true
}
group("gmock_main") {
testonly = true
public_deps = [ ":gmock" ]
}
""",
},
},
"googletest": {
"relative_root":
"third_party/googletest",
"dirs": [
"custom/gtest/internal/custom",
"src/googletest/include/gtest/internal/custom",
"src/googletest/include/gtest/internal",
"src/googletest/include/gtest",
"src/googletest/src",
"src/googlemock/include/gmock/internal/custom",
"src/googlemock/include/gmock/internal",
"src/googlemock/include/gmock",
"src/googlemock/src",
],
"files": {
"BUILD.gn":
GOOGLETEST_BUILD_GN,
"custom/gtest/internal/custom/gtest.h":
"#pragma once\n",
"custom/gtest/internal/custom/stack_trace_getter.cc":
"namespace testing {}\n",
"custom/gtest/internal/custom/stack_trace_getter.h":
"#pragma once\n",
"custom/gtest/internal/custom/chrome_custom_temp_dir.cc":
"namespace testing {}\n",
"custom/gtest/internal/custom/chrome_custom_temp_dir.h":
"#pragma once\n",
"custom/gtest/internal/custom/gtest_port_wrapper.cc":
"namespace testing {}\n",
"src/googletest/include/gtest/gtest-assertion-result.h":
GOOGLETEST_ASSERTION_RESULT_H,
"src/googletest/include/gtest/gtest-death-test.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest-matchers.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest-message.h":
"#pragma once\nnamespace testing { class Message {}; }\n",
"src/googletest/include/gtest/gtest-param-test.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest-printers.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest-spi.h":
GOOGLETEST_GTEST_SPI_H,
"src/googletest/include/gtest/gtest-test-part.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest-typed-test.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest.h":
GOOGLETEST_GTEST_H,
"src/googletest/include/gtest/gtest_pred_impl.h":
"#pragma once\n",
"src/googletest/include/gtest/gtest_prod.h":
GOOGLETEST_GTEST_PROD_H,
"src/googletest/include/gtest/internal/custom/gtest-port.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/custom/gtest-printers.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-death-test-internal.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-filepath.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-internal.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-param-util.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-port-arch.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-port.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-string.h":
"#pragma once\n",
"src/googletest/include/gtest/internal/gtest-type-util.h":
"#pragma once\n",
"src/googletest/src/gtest-assertion-result.cc":
"namespace testing {}\n",
"src/googletest/src/gtest-death-test.cc":
"namespace testing {}\n",
"src/googletest/src/gtest-filepath.cc":
"namespace testing {}\n",
"src/googletest/src/gtest-internal-inl.h":
"#pragma once\n",
"src/googletest/src/gtest-matchers.cc":
"namespace testing {}\n",
"src/googletest/src/gtest-printers.cc":
"namespace testing {}\n",
"src/googletest/src/gtest-test-part.cc":
"namespace testing {}\n",
"src/googletest/src/gtest-typed-test.cc":
"namespace testing {}\n",
"src/googletest/src/gtest.cc":
"namespace testing {}\n",
"src/googletest/src/gtest_main.cc":
TEST_MAIN_CC,
"src/googlemock/include/gmock/gmock-actions.h":
"#pragma once\n",
"src/googlemock/include/gmock/gmock-cardinalities.h":
"#pragma once\n",
"src/googlemock/include/gmock/gmock-function-mocker.h":
"#pragma once\n#define MOCK_METHOD(...) \n",
"src/googlemock/include/gmock/gmock-matchers.h":
"#pragma once\n",
"src/googlemock/include/gmock/gmock-more-matchers.h":
"#pragma once\n",
"src/googlemock/include/gmock/gmock-nice-strict.h":
"#pragma once\n",
"src/googlemock/include/gmock/gmock-spec-builders.h":
"#pragma once\n",
"src/googlemock/include/gmock/gmock.h":
"#pragma once\n#include \"gmock-function-mocker.h\"\n",
"src/googlemock/include/gmock/internal/custom/gmock-generated-actions.h":
"#pragma once\n",
"src/googlemock/include/gmock/internal/custom/gmock-matchers.h":
"#pragma once\n",
"src/googlemock/include/gmock/internal/gmock-internal-utils.h":
"#pragma once\n",
"src/googlemock/include/gmock/internal/gmock-port.h":
"#pragma once\n",
"src/googlemock/include/gmock/internal/gmock-pp.h":
"#pragma once\n",
"src/googlemock/src/gmock-cardinalities.cc":
"namespace testing {}\n",
"src/googlemock/src/gmock-internal-utils.cc":
"namespace testing {}\n",
"src/googlemock/src/gmock-matchers.cc":
"namespace testing {}\n",
"src/googlemock/src/gmock-spec-builders.cc":
"namespace testing {}\n",
"src/googlemock/src/gmock.cc":
"namespace testing {}\n",
"src/googlemock/src/gmock_main.cc":
TEST_MAIN_CC,
},
},
"catapult": {
"relative_root":
"third_party/catapult",
"dirs": [
"third_party/typ",
"tracing",
"tracing/tracing",
"tracing/tracing/proto",
],
"files": {
"tracing/BUILD.gn":
"""group("tracing_common") {
}
group("convert_chart_json") {
data_deps = [ ":tracing_common" ]
}
""",
"tracing/tracing/BUILD.gn":
make_trivial_group_build_gn("histogram", "reserved_infos"),
"tracing/tracing/proto/BUILD.gn":
make_trivial_group_build_gn("histogram_proto"),
},
},
"tools": {
"relative_root": "tools",
"dirs": ["clang/scripts", "generate_stubs", "rust"],
"files": {
"clang/scripts/update.py":
"CLANG_REVISION = 'llvmorg-0-init'\nCLANG_SUB_REVISION = 0\n",
"generate_stubs/generate_stubs.py":
GENERATE_STUBS_SCRIPT,
"generate_stubs/rules.gni":
GENERATE_STUBS_RULES_GNI,
"rust/update_rust.py":
"RUST_REVISION = 'llvmorg-0-init'\nRUST_SUB_REVISION = 0\n",
},
},
"nasm": {
"relative_root": "third_party/nasm",
"dirs": [],
"files": {
"BUILD.gn": NASM_BUILD_GN,
"nasm_assemble.gni": NASM_ASSEMBLE_GNI,
},
},
}
@dataclasses.dataclass(frozen=True)
class ResolvedSpec:
dep: str
relative_root: str
dirs: tuple[str, ...]
files: dict[str, str]
copy_files: dict[str, str]
preserve_root: bool
@dataclasses.dataclass(frozen=True)
class PlannedFile:
relative_path: str
content: str
@dataclasses.dataclass(frozen=True)
class PlannedCopyFile:
relative_path: str
asset_source: pathlib.Path
@dataclasses.dataclass(frozen=True)
class GenerationPlan:
output_root: pathlib.Path
preserve_root: bool
directories: tuple[pathlib.Path, ...]
files: tuple[PlannedFile, ...]
copied_files: tuple[PlannedCopyFile, ...]
def resolve_spec(
dep: str,
specs: dict[str, dict[str, object]] | None = None) -> ResolvedSpec:
specs = SPECS if specs is None else specs
spec = specs[dep]
if "relative_root" not in spec:
raise ValueError(f"Missing required 'relative_root' for {dep}")
if "dirs" not in spec:
raise ValueError(f"Missing required 'dirs' for {dep}")
if "files" not in spec:
raise ValueError(f"Missing required 'files' for {dep}")
relative_root = spec["relative_root"]
dirs = spec["dirs"]
files = spec["files"]
copy_files = spec.get("copy_files", {})
preserve_root = spec.get("preserve_root", False)
if not isinstance(relative_root, str):
raise ValueError(f"Invalid 'relative_root' for {dep}")
if not isinstance(dirs, list):
raise ValueError(f"Invalid 'dirs' for {dep}")
if not isinstance(files, dict):
raise ValueError(f"Invalid 'files' for {dep}")
if not isinstance(copy_files, dict):
raise ValueError(f"Invalid 'copy_files' for {dep}")
if not isinstance(preserve_root, bool):
raise ValueError(f"Invalid 'preserve_root' for {dep}")
return ResolvedSpec(
dep=dep,
relative_root=relative_root,
dirs=tuple(dirs),
files=dict(files),
copy_files=dict(copy_files),
preserve_root=preserve_root,
)
def render_template(content: str, include_root: str, lib_root: str,
tool_path: str) -> str:
return (content.replace("{include_root}", include_root).replace(
"{lib_root}", lib_root).replace("{tool_path}", tool_path))
def build_generation_plan(
source_root: pathlib.Path,
include_root: str,
lib_root: str,
tool_path: str,
spec: ResolvedSpec,
) -> GenerationPlan:
output_root = source_root / spec.relative_root
directories = tuple(output_root / rel_dir for rel_dir in spec.dirs)
files = tuple(
PlannedFile(
relative_path=rel_path,
content=render_template(content, include_root, lib_root,
tool_path),
) for rel_path, content in spec.files.items())
copied_files = tuple(
PlannedCopyFile(
relative_path=rel_path,
asset_source=pathlib.Path(__file__).resolve().parent /
asset_rel_path,
) for rel_path, asset_rel_path in spec.copy_files.items())
return GenerationPlan(
output_root=output_root,
preserve_root=spec.preserve_root,
directories=directories,
files=files,
copied_files=copied_files,
)
def plan_generation(
source_root: pathlib.Path,
dep: str,
include_root: str,
lib_root: str,
tool_path: str,
) -> GenerationPlan:
spec = resolve_spec(dep)
return build_generation_plan(source_root, include_root, lib_root,
tool_path, spec)
def apply_generation_plan(plan: GenerationPlan) -> None:
output = plan.output_root
if not plan.preserve_root:
shutil.rmtree(output, ignore_errors=True)
output.mkdir(parents=True, exist_ok=True)
for directory in plan.directories:
directory.mkdir(parents=True, exist_ok=True)
for planned_file in plan.files:
path = output / planned_file.relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(planned_file.content)
for copied_file in plan.copied_files:
path = output / copied_file.relative_path
path.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(copied_file.asset_source, path)
def write_tree(source_root: pathlib.Path, dep: str, include_root: str,
lib_root: str, tool_path: str) -> None:
apply_generation_plan(
plan_generation(source_root, dep, include_root, lib_root, tool_path))
def generate_external_dep(
source_root: pathlib.Path,
dep: str,
include_root: str,
lib_root: str,
tool_path: str,
) -> None:
apply_generation_plan(
plan_generation(source_root, dep, include_root, lib_root, tool_path))
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--source-root", required=True)
parser.add_argument("--dep", choices=sorted(SPECS), required=True)
parser.add_argument("--include-root", required=True)
parser.add_argument("--lib-root", required=True)
parser.add_argument("--tool-path", default="")
args = parser.parse_args()
generate_external_dep(
pathlib.Path(args.source_root),
args.dep,
args.include_root,
args.lib_root,
args.tool_path,
)
if __name__ == "__main__":
main()