| # Copyright 2018 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| load( |
| "@io_bazel_rules_dart//dart/build_rules/common:context.bzl", |
| "collect_dart_context", |
| "make_dart_context", |
| ) |
| load( |
| "@io_bazel_rules_dart//dart/build_rules/internal:common.bzl", |
| "package_spec_action", |
| ) |
| |
| """Common attributes used by the `compile_kernel_action`.""" |
| COMMON_COMPILE_KERNEL_ACTION_ATTRS = { |
| "main": attr.label( |
| doc = "The main script file", |
| mandatory = True, |
| allow_files = True, |
| single_file = True, |
| ), |
| "srcs": attr.label_list( |
| doc = "Additional source files", |
| allow_files = True, |
| ), |
| "package_name": attr.string( |
| doc = "The Dart package name", |
| mandatory = True, |
| ), |
| "deps": attr.label_list( |
| doc = "The list of libraries this app depends on", |
| mandatory = False, |
| providers = ["dart"], |
| ), |
| "_dart": attr.label( |
| default = Label("//tools:dart"), |
| allow_single_file = True, |
| executable = True, |
| cfg = "host", |
| ), |
| "_kernel_compiler": attr.label( |
| default = Label("//tools/dart_prebuilts:kernel_compiler.snapshot"), |
| allow_single_file = True, |
| cfg = "host", |
| ), |
| } |
| |
| def compile_kernel_action( |
| context, |
| package_name, |
| component_name, |
| dart_exec, |
| kernel_compiler, |
| sdk_root, |
| main, |
| srcs, |
| deps, |
| kernel_snapshot_file, |
| manifest_file, |
| main_dilp_file, |
| dilp_list_file): |
| """Creates an action that generates the Dart kernel and its dependencies. |
| |
| Args: |
| context: The rule context. |
| package_name: The Dart package name. |
| component_name: The name of this component. |
| dart_exec: The Dart executable `File`. |
| kernel_compiler: The kernel compiler snapshot `File`. |
| sdk_root: The Dart SDK root `File` (Dart or Flutter's platform libs). |
| main: The main `File`. |
| srcs: Additional list of source `File`. |
| deps: A list of `Label`s this app depends on. |
| kernel_snapshot_file: The kernel snapshot `File` output. |
| manifest_file: The Fuchsia manifest `File` output. |
| main_dilp_file: The compiled main dilp `File` output. |
| dilp_list_file: The dilplist `File` output. |
| |
| Returns: |
| Mapping `dict` to be used for packaging. |
| """ |
| build_dir = context.label.name + ".build/" |
| dart_ctx = make_dart_context( |
| ctx = context, |
| package = package_name, |
| deps = deps, |
| ) |
| |
| # 1. Create the .packages file. |
| package_spec_path = context.label.name + ".packages" |
| package_spec = context.new_file(package_spec_path) |
| package_spec_action( |
| ctx = context, |
| output = package_spec, |
| dart_ctx = dart_ctx, |
| ) |
| |
| # 2. Declare *.dilp files for all dependencies. |
| data_root = "data/%s/" % component_name |
| mappings = {} |
| dart_ctxs = collect_dart_context(dart_ctx).values() |
| for dc in dart_ctxs: |
| # There's no need to declare a file for the current package as it |
| # is outputed under `main_dilp_file`. |
| if dc.package == package_name: |
| continue |
| dilp_file = context.actions.declare_file( |
| context.label.name + "_kernel.dil-" + dc.package + ".dilp", |
| ) |
| mappings[data_root + dc.package + ".dilp"] = dilp_file |
| |
| # 3. Create a wrapper script around the kernel compiler. |
| # The kernel compiler only generates .dilp files for libraries that are |
| # actually used by app. However, we declare a .dilp file for all packages |
| # in the dependency graph: not creating that file would yield a Bazel error. |
| content = "#!/bin/bash\n" |
| content += dart_exec.path |
| content += " $@ || exit $?\n" |
| for dilp in mappings.values(): |
| content += "if ! [[ -f %s ]]; then\n" % dilp.path |
| content += " echo 'Warning: %s is not needed, generating empty file.' >&2\n" % dilp.path |
| content += " touch %s\n" % dilp.path |
| content += "fi\n" |
| |
| kernel_script = context.actions.declare_file(context.label.name + "_compile_kernel.sh") |
| context.actions.write( |
| output = kernel_script, |
| content = content, |
| is_executable = True, |
| ) |
| |
| # 4. Find all possible roots for multi-root scheme |
| roots_dict = {} |
| for dc in dart_ctxs: |
| dart_srcs = list(dc.dart_srcs) |
| if len(dart_srcs) == 0: |
| continue |
| src = dart_srcs[0] |
| index = src.path.find(dc.lib_root) |
| if index > 0: |
| root = src.path[:index] |
| roots_dict[root] = True |
| |
| # Include the root for package spec file |
| roots_dict[package_spec.root.path] = True |
| |
| # And current directory as it was ignored in the previous logic |
| roots_dict["."] = True |
| |
| roots_param = [] |
| for root in roots_dict.keys(): |
| roots_param += ["--multi-root", root] |
| |
| # 5. Compile the kernel. |
| multi_root_scheme = "main-root" |
| context.actions.run( |
| executable = kernel_script, |
| arguments = [ |
| kernel_compiler.path, |
| "--component-name", |
| component_name, |
| "--target", |
| "dart_runner", |
| "--sdk-root", |
| sdk_root.dirname, |
| "--multi-root-scheme", |
| multi_root_scheme, |
| ] + roots_param + [ |
| "--packages", |
| "%s:///%s" % (multi_root_scheme, package_spec.short_path), |
| "--manifest", |
| manifest_file.path, |
| "--output", |
| kernel_snapshot_file.path, |
| "%s:///%s" % (multi_root_scheme, main.short_path), |
| ], |
| inputs = dart_ctx.transitive_srcs.files + srcs + [ |
| kernel_compiler, |
| sdk_root, |
| package_spec, |
| main, |
| dart_exec, |
| ], |
| outputs = [ |
| main_dilp_file, |
| dilp_list_file, |
| kernel_snapshot_file, |
| manifest_file, |
| ] + mappings.values(), |
| mnemonic = "DartKernelCompiler", |
| ) |
| mappings[data_root + "main.dilp"] = main_dilp_file |
| mappings[data_root + "app.dilplist"] = dilp_list_file |
| return mappings |