From abc753c9c9044f196084b0edb46d28edbf5d29b0 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Wed, 6 Mar 2019 23:17:39 +0000 Subject: [PATCH] BUILD.gn: Split dawn_component/generator in their own files This will allow follow up commits to use them from the different parts of the split-off BUILD.gn file. BUG=dawn:61 Change-Id: I767f6c97c06ee73290d3df482880d1a2df92e187 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/5301 Reviewed-by: Kai Ninomiya Commit-Queue: Corentin Wallez --- BUILD.gn | 217 +---------------------------------- generator/dawn_generator.gni | 123 ++++++++++++++++++++ scripts/dawn_component.gni | 123 ++++++++++++++++++++ 3 files changed, 248 insertions(+), 215 deletions(-) create mode 100644 generator/dawn_generator.gni create mode 100644 scripts/dawn_component.gni diff --git a/BUILD.gn b/BUILD.gn index 13c130e8ae..f8b4a713d7 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -13,8 +13,10 @@ # limitations under the License. import("//build_overrides/build.gni") +import("scripts/dawn_component.gni") import("scripts/dawn_features.gni") import("scripts/dawn_overrides_with_defaults.gni") +import("generator/dawn_generator.gni") import("//testing/test.gni") @@ -26,221 +28,6 @@ if (build_with_chromium) { dcheck_always_on = false } -############################################################################### -# Template to wrap the Dawn code generator -############################################################################### - -# Template to help with invocation of the Dawn code generator, looks like this: -# -# dawn_generator("my_target_gen") { -# # Which generator target to output -# target = "my_target" -# # The list of expected outputs, generation fails if there's a mismatch -# outputs = [ -# "MyTarget.cpp", -# "MyTarget.h", -# ] -# } -# -# Using the generated files is done like so: -# -# shared_library("my_target") { -# deps = [ ":my_target_gen "] -# sources = get_target_outputs(":my_target_gen") -# } -# -template("dawn_generator") { - # The base arguments for the generator: from this dawn.json, generate this - # target using templates in this directory. - generator_args = [ - rebase_path("dawn.json", root_build_dir), - "--wire-json", - rebase_path("dawn_wire.json", root_build_dir), - "--template-dir", - rebase_path("generator/templates", root_build_dir), - "--targets", - invoker.target, - ] - - # Use the Jinja2 version pulled from the DEPS file. We do it so we don't - # have version problems, and users don't have to install Jinja2. - jinja2_python_path = rebase_path("${dawn_jinja2_dir}/..") - generator_args += [ - "--extra-python-path", - jinja2_python_path, - ] - - # For build parallelism GN wants to know the exact inputs and outputs of - # action targets like we use for our code generator. We avoid asking the - # generator about its inputs by using the "depfile" feature of GN/Ninja. - # - # A ninja limitation is that the depfile is a subset of Makefile that can - # contain a single target, so we output a single "JSON-tarball" instead. - json_tarball = "${target_gen_dir}/${target_name}.json_tarball" - json_tarball_depfile = "${json_tarball}.d" - - generator_args += [ - "--output-json-tarball", - rebase_path(json_tarball, root_build_dir), - "--depfile", - rebase_path(json_tarball_depfile, root_build_dir), - ] - - # After the JSON tarball is created we need an action target to extract it - # with a list of its outputs. The invoker provided a list of expected - # outputs. To make sure the list is in sync between the generator and the - # build files, we write it to a file and ask the generator to assert it is - # correct. - expected_outputs_file = "${target_gen_dir}/${target_name}.expected_outputs" - write_file(expected_outputs_file, invoker.outputs) - - generator_args += [ - "--expected-outputs-file", - rebase_path(expected_outputs_file, root_build_dir), - ] - - # The code generator invocation that will write the JSON tarball, check the - # outputs are what's expected and write a depfile for Ninja. - action("${target_name}_json_tarball") { - script = "generator/main.py" - outputs = [ - json_tarball, - ] - depfile = json_tarball_depfile - args = generator_args - } - - # Extract the JSON tarball into the target_gen_dir - action("${target_name}") { - script = "generator/extract_json.py" - args = [ - rebase_path(json_tarball, root_build_dir), - rebase_path(target_gen_dir, root_build_dir), - ] - - deps = [ - ":${target_name}_json_tarball", - ] - inputs = [ - json_tarball, - ] - - # The expected output list is relative to the target_gen_dir but action - # target outputs are from the root dir so we need to rebase them. - outputs = [] - foreach(source, invoker.outputs) { - outputs += [ "${target_gen_dir}/${source}" ] - } - } -} - -############################################################################### -# Template to produce a component for one of Dawn's libraries. -############################################################################### - -# Template that produces static and shared versions of the same library as well -# as a target similar to Chromium's component targets. -# - The shared version exports symbols and has dependent import the symbols -# as libname.so with target name libname_shared -# - The static library doesn't export symbols nor make dependents import them -# - The libname target is similar to a Chromium component and is an alias for -# either the static or the shared library. -# -# The DEFINE_PREFIX must be provided and must match the respective "_export.h" -# file. -# -# Example usage: -# -# dawn_component("my_library") { -# // my_library_export.h must use the MY_LIBRARY_IMPLEMENTATION and -# // MY_LIBRARY_SHARED_LIBRARY macros. -# DEFINE_PREFIX = "MY_LIBRARY" -# -# sources = [...] -# deps = [...] -# configs = [...] -# } -# -# executable("foo") { -# deps = [ ":my_library_shared" ] // or :my_library for the same effect -# } -template("dawn_component") { - # Copy the target_name in the local scope so it doesn't get shadowed in the - # definition of targets. - libname = target_name - - # The config that will apply to dependents of the shared library so they know - # they should "import" the symbols - config("${libname}_shared_public_config") { - defines = [ "${invoker.DEFINE_PREFIX}_SHARED_LIBRARY" ] - - # Executable needs an rpath to find our shared libraries on OSX and Linux - if (is_mac) { - ldflags = [ - "-rpath", - "@executable_path/", - ] - } - if (is_linux) { - configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } - } - - shared_library("${libname}_shared") { - output_name = libname - - # Copy all variables except "configs", which has a default value - forward_variables_from(invoker, "*", [ "configs" ]) - if (defined(invoker.configs)) { - configs += invoker.configs - } - - # Tell dependents where to find this shared library - if (is_mac) { - ldflags = [ - "-install_name", - "@rpath/${libname}.dylib", - ] - } - - # Use the config that makes the ${DEFINE_PREFIX}_EXPORT macro do something - if (!defined(public_configs)) { - public_configs = [] - } - public_configs += [ ":${libname}_shared_public_config" ] - - # Tell sources of this library to export the symbols (and not import) - if (!defined(defines)) { - defines = [] - } - defines += [ "${invoker.DEFINE_PREFIX}_IMPLEMENTATION" ] - } - - static_library("${libname}_static") { - output_name = libname - - complete_static_lib = dawn_complete_static_libs - - # Copy all variables except "configs", which has a default value - forward_variables_from(invoker, "*", [ "configs" ]) - if (defined(invoker.configs)) { - configs += invoker.configs - } - } - - group(libname) { - if (is_component_build) { - public_deps = [ - ":${libname}_shared", - ] - } else { - public_deps = [ - ":${libname}_static", - ] - } - } -} - ############################################################################### # Common dawn libraries and configs ############################################################################### diff --git a/generator/dawn_generator.gni b/generator/dawn_generator.gni new file mode 100644 index 0000000000..f9fa1f997d --- /dev/null +++ b/generator/dawn_generator.gni @@ -0,0 +1,123 @@ +# Copyright 2019 The Dawn Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("../scripts/dawn_overrides_with_defaults.gni") + +############################################################################### +# Template to wrap the Dawn code generator +############################################################################### + +# Template to help with invocation of the Dawn code generator, looks like this: +# +# dawn_generator("my_target_gen") { +# # Which generator target to output +# target = "my_target" +# # The list of expected outputs, generation fails if there's a mismatch +# outputs = [ +# "MyTarget.cpp", +# "MyTarget.h", +# ] +# } +# +# Using the generated files is done like so: +# +# shared_library("my_target") { +# deps = [ ":my_target_gen "] +# sources = get_target_outputs(":my_target_gen") +# } +# +template("dawn_generator") { + # The base arguments for the generator: from this dawn.json, generate this + # target using templates in this directory. + generator_args = [ + rebase_path("dawn.json", root_build_dir), + "--wire-json", + rebase_path("dawn_wire.json", root_build_dir), + "--template-dir", + rebase_path("generator/templates", root_build_dir), + "--targets", + invoker.target, + ] + + # Use the Jinja2 version pulled from the DEPS file. We do it so we don't + # have version problems, and users don't have to install Jinja2. + jinja2_python_path = rebase_path("${dawn_jinja2_dir}/..") + generator_args += [ + "--extra-python-path", + jinja2_python_path, + ] + + # For build parallelism GN wants to know the exact inputs and outputs of + # action targets like we use for our code generator. We avoid asking the + # generator about its inputs by using the "depfile" feature of GN/Ninja. + # + # A ninja limitation is that the depfile is a subset of Makefile that can + # contain a single target, so we output a single "JSON-tarball" instead. + json_tarball = "${target_gen_dir}/${target_name}.json_tarball" + json_tarball_depfile = "${json_tarball}.d" + + generator_args += [ + "--output-json-tarball", + rebase_path(json_tarball, root_build_dir), + "--depfile", + rebase_path(json_tarball_depfile, root_build_dir), + ] + + # After the JSON tarball is created we need an action target to extract it + # with a list of its outputs. The invoker provided a list of expected + # outputs. To make sure the list is in sync between the generator and the + # build files, we write it to a file and ask the generator to assert it is + # correct. + expected_outputs_file = "${target_gen_dir}/${target_name}.expected_outputs" + write_file(expected_outputs_file, invoker.outputs) + + generator_args += [ + "--expected-outputs-file", + rebase_path(expected_outputs_file, root_build_dir), + ] + + # The code generator invocation that will write the JSON tarball, check the + # outputs are what's expected and write a depfile for Ninja. + action("${target_name}_json_tarball") { + script = "generator/main.py" + outputs = [ + json_tarball, + ] + depfile = json_tarball_depfile + args = generator_args + } + + # Extract the JSON tarball into the target_gen_dir + action("${target_name}") { + script = "generator/extract_json.py" + args = [ + rebase_path(json_tarball, root_build_dir), + rebase_path(target_gen_dir, root_build_dir), + ] + + deps = [ + ":${target_name}_json_tarball", + ] + inputs = [ + json_tarball, + ] + + # The expected output list is relative to the target_gen_dir but action + # target outputs are from the root dir so we need to rebase them. + outputs = [] + foreach(source, invoker.outputs) { + outputs += [ "${target_gen_dir}/${source}" ] + } + } +} diff --git a/scripts/dawn_component.gni b/scripts/dawn_component.gni new file mode 100644 index 0000000000..3e854dae61 --- /dev/null +++ b/scripts/dawn_component.gni @@ -0,0 +1,123 @@ +# Copyright 2019 The Dawn Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("dawn_overrides_with_defaults.gni") +import("dawn_features.gni") + +############################################################################### +# Template to produce a component for one of Dawn's libraries. +############################################################################### + +# Template that produces static and shared versions of the same library as well +# as a target similar to Chromium's component targets. +# - The shared version exports symbols and has dependent import the symbols +# as libname.so with target name libname_shared +# - The static library doesn't export symbols nor make dependents import them +# - The libname target is similar to a Chromium component and is an alias for +# either the static or the shared library. +# +# The DEFINE_PREFIX must be provided and must match the respective "_export.h" +# file. +# +# Example usage: +# +# dawn_component("my_library") { +# // my_library_export.h must use the MY_LIBRARY_IMPLEMENTATION and +# // MY_LIBRARY_SHARED_LIBRARY macros. +# DEFINE_PREFIX = "MY_LIBRARY" +# +# sources = [...] +# deps = [...] +# configs = [...] +# } +# +# executable("foo") { +# deps = [ ":my_library_shared" ] // or :my_library for the same effect +# } +template("dawn_component") { + # Copy the target_name in the local scope so it doesn't get shadowed in the + # definition of targets. + libname = target_name + + # The config that will apply to dependents of the shared library so they know + # they should "import" the symbols + config("${libname}_shared_public_config") { + defines = [ "${invoker.DEFINE_PREFIX}_SHARED_LIBRARY" ] + + # Executable needs an rpath to find our shared libraries on OSX and Linux + if (is_mac) { + ldflags = [ + "-rpath", + "@executable_path/", + ] + } + if (is_linux) { + configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } + } + + shared_library("${libname}_shared") { + output_name = libname + + # Copy all variables except "configs", which has a default value + forward_variables_from(invoker, "*", [ "configs" ]) + if (defined(invoker.configs)) { + configs += invoker.configs + } + + # Tell dependents where to find this shared library + if (is_mac) { + ldflags = [ + "-install_name", + "@rpath/${libname}.dylib", + ] + } + + # Use the config that makes the ${DEFINE_PREFIX}_EXPORT macro do something + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":${libname}_shared_public_config" ] + + # Tell sources of this library to export the symbols (and not import) + if (!defined(defines)) { + defines = [] + } + defines += [ "${invoker.DEFINE_PREFIX}_IMPLEMENTATION" ] + } + + static_library("${libname}_static") { + output_name = libname + + complete_static_lib = dawn_complete_static_libs + + # Copy all variables except "configs", which has a default value + forward_variables_from(invoker, "*", [ "configs" ]) + if (defined(invoker.configs)) { + configs += invoker.configs + } + } + + group(libname) { + if (is_component_build) { + public_deps = [ + ":${libname}_shared", + ] + } else { + public_deps = [ + ":${libname}_static", + ] + } + } +}