dawn-cmake/generator/generator_lib.gni
Corentin Wallez 05623df97f BUILD.gn: Add a check generated files are in allowed dirs.
This is important so that we know that the list of allowed directories
is in sync with other parts of the build in follow-up commits.

BUG=dawn:22

Change-Id: I202bec55b510989e43acf497956e2937c9a2f60a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11360
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
2019-09-18 23:19:31 +00:00

166 lines
5.6 KiB
Plaintext

# 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.
# Template to help invoking code generators based on generator_lib.py
# Internal use only, this should only be called from templates implementing
# generator-specific actions.
#
# Variables:
# script: Path to generator script.
#
# args: List of extra command-line arguments passed to the generator.
#
# outputs: List of expected outputs, generation will fail if there is a
# mistmatch.
#
# generator_lib_dir: directory where generator_lib.py is located.
#
# custom_gen_dir: Optional custom target gen dir. Defaults to $target_gen_dir
# but allows output files to not depend on the location of the BUILD.gn
# that generates them.
#
# template_dir: Optional template root directory. Defaults to
# "${generator_lib_dir}/templates".
#
# jinja2_path: Optional Jinja2 installation path.
#
# allowed_output_dirs: Optional list of directories that are the only
# directories in which files of `outputs` are allowed to be (and not
# in children directories). Generation will fail if an output isn't
# in a directory in the list.
#
# root_dir: Optional root source dir for Python dependencies
# computation. Defaults to "${generator_lib_dir}/..". Any dependency
# outside of this directory is considered a system file and will be
# omitted.
#
template("generator_lib_action") {
_generator_args = []
if (defined(invoker.args)) {
_generator_args += invoker.args
}
assert(defined(invoker.generator_lib_dir),
"generator_lib_dir must be defined before calling this action!")
_template_dir = "${invoker.generator_lib_dir}/templates"
if (defined(invoker.template_dir)) {
_template_dir = invoker.template_dir
}
_generator_args += [
"--template-dir",
rebase_path(_template_dir),
]
if (defined(invoker.root_dir)) {
_generator_args += [
"--root-dir",
rebase_path(_root_dir, root_build_dir),
]
}
if (defined(invoker.jinja2_path)) {
_generator_args += [
"--jinja2-path",
rebase_path(invoker.jinja2_path),
]
}
# Chooses either the default gen_dir or the custom one required by the
# invoker. This allows moving the definition of code generators in different
# BUILD.gn files without changing the location of generated file. Without
# this generated headers could cause issues when old headers aren't removed.
_gen_dir = target_gen_dir
if (defined(invoker.custom_gen_dir)) {
_gen_dir = invoker.custom_gen_dir
}
# 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 = "${_gen_dir}/${target_name}.json_tarball"
_json_tarball_target = "${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 = "${_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),
]
# Check that all of the outputs are in a directory that's allowed. This is
# useful to keep the list of directories in sink with other parts of the
# build.
if (defined(invoker.allowed_output_dirs)) {
_allowed_output_dirs_file = "${_gen_dir}/${target_name}.allowed_output_dirs"
write_file(_allowed_output_dirs_file, invoker.allowed_output_dirs)
_generator_args += [
"--allowed-output-dirs-file",
rebase_path(_allowed_output_dirs_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(_json_tarball_target) {
script = invoker.script
outputs = [
_json_tarball,
]
depfile = _json_tarball_depfile
args = _generator_args
}
# Extract the JSON tarball into the gen_dir
action(target_name) {
script = "${invoker.generator_lib_dir}/extract_json.py"
args = [
rebase_path(_json_tarball, root_build_dir),
rebase_path(_gen_dir, root_build_dir),
]
deps = [
":${_json_tarball_target}",
]
inputs = [
_json_tarball,
]
# The expected output list is relative to the gen_dir but action
# target outputs are from the root dir so we need to rebase them.
outputs = []
foreach(source, invoker.outputs) {
outputs += [ "${_gen_dir}/${source}" ]
}
}
}