| # Copyright 2017 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. |
| |
| import("//build/toolchain/clang_toolchain.gni") |
| |
| # TODO(raggi): discuss how we want to handle the keys and then re-organize. |
| # This value is shared with //build/gn/BUILD.gn. |
| declare_args() { |
| package_signing_key = "//build/development.key" |
| } |
| |
| # Defines a package |
| # |
| # The package template is used to define a unit of related code and data. |
| # A package always has a name (defaulting to the target name) and lists of |
| # scopes describing the components of the package. |
| # |
| # Parameters |
| # |
| # app (bool, optional) |
| # If true, changes the default location of binaries from |
| # |"bin/" + binary.name| to |"apps/" + binary.name|. |
| # |
| # fuchsia_package (bool, optional) |
| # If true, the package is constructed and signed ready for distribution and |
| # inclusion in /pkgfs. system_image supersedes fuchsia_package. Eventually all |
| # packages should be fuchsia_package. |
| # |
| # Defaults to false. |
| # |
| # system_image (bool, optional) |
| # If true, the package is stored in the system boot image rather than in a |
| # Fuchsia Archive. |
| # |
| # If this package uses the |drivers| parameter, the system_image must be set |
| # to true because we are not yet sophisticated enough to load drivers out of |
| # archives. |
| # |
| # Defaults to false. |
| # |
| # meta (optional) |
| # List of scopes defining the metadata entries in the package. A metadata |
| # entry is typically a source file and is placed in the "meta/" directory of |
| # the assembled package. |
| # |
| # Requires |system_image| to be false. |
| # |
| # Entries in a scope in the meta list: |
| # |
| # path (path, required) |
| # Location of entry in source or build directory. If the resource is |
| # checked in, this will typically be specified as a path relative to the |
| # BUILD.gn file containing the package() rule. If the resource is |
| # generated, this will typically be specified relative to |
| # $target_gen_dir |
| # |
| # dest (path, required) |
| # Location the resource will be placed within "meta/" |
| # |
| # binary (optional) |
| # The path to the the primary binary for the package, relative to |
| # $root_build_dir. The binary will be placed in the assembled package at |
| # "bin/app" and will be executed by default when running the package. |
| # |
| # Requires |system_image| to be false. |
| # |
| # binaries (optional) |
| # List of scopes defining the binaries in the package. A binary is typically |
| # produced by the build system and is placed in the "bin/" directory of the |
| # assembled package. |
| # |
| # Entries in a scope in the binaries list: |
| # |
| # name (string, required) |
| # Name of the binary |
| # |
| # source (path, optional) |
| # Location of the binary in the build directory if it is not at |
| # $root_build_dir/$name |
| # |
| # dest (path, optional) |
| # Location the binary will be placed within "bin/" |
| # |
| # tests (optional) |
| # List of scopes defining the test binaries in the package. A test is |
| # typically produced by the build system and is placed in the "test/" |
| # directory of the assembled package. |
| # |
| # Entries in a scope in the tests list: |
| # |
| # name (string, required) |
| # Name of the test |
| # |
| # dest (path, optional) |
| # Location the binary will be placed within "test/" |
| # |
| # disabled (bool, optional) |
| # Whether to disable the test on continuous integration jobs. This can |
| # be used when a test is temporarily broken, or if it is too flaky or |
| # slow for CI. The test will also be skipped by the "runtests" command. |
| # |
| # drivers (optional) |
| # List of scopes defining the drivers in the package. A driver is typically |
| # produced by the build system and is placed in the "driver" directory |
| # of the assembled package. |
| # |
| # Requires |system_image| to be true. |
| # |
| # Entries in a scope in the drivers list: |
| # |
| # name (string, required) |
| # Name of the driver |
| # |
| # libraries (optional) |
| # List of scopes defining the (shared) libraries in the package. A library |
| # is placed in the "lib/" directory of the assembled package. |
| # |
| # Entries in a scope in the libraries list: |
| # |
| # name (string, required) |
| # Name of the library |
| # |
| # source (path, optional) |
| # Location of the binary in the build directory if it is not at |
| # $root_build_dir/$name |
| # |
| # dest (path, optional) |
| # Location the binary will be placed within "lib/" |
| # |
| # resources (optional) |
| # List of scopes defining the resources in the package. A resource is a |
| # data file that may be produced by the build system, checked in to a |
| # source repository, or produced by another system that runs before the |
| # build. Resources are placed in the "data/" directory of the assembled |
| # package. |
| # |
| # Entries in a scope in the resources list: |
| # |
| # path (path, required) |
| # Location of resource in source or build directory. If the resource is |
| # checked in, this will typically be specified as a path relative to the |
| # BUILD.gn file containing the package() rule. If the resource is |
| # generated, this will typically be specified relative to |
| # $target_gen_dir |
| # |
| # dest (path, required) |
| # Location the resource will be placed within "data/" |
| # |
| template("package") { |
| if (current_toolchain == target_toolchain) { |
| pkg = { |
| app = false |
| fuchsia_package = false |
| system_image = false |
| binaries = [] |
| drivers = [] |
| libraries = [] |
| meta = [] |
| package_name = target_name |
| package_version = 0 # placeholder |
| resources = [] |
| tests = [] |
| forward_variables_from(invoker, "*") |
| } |
| pkg_out_dir = "$root_build_dir/package/${pkg.package_name}" |
| |
| shared_toolchain_out_dir = |
| get_label_info("//lib($shlib_toolchain)", "root_out_dir") |
| not_needed([ "shared_toolchain_out_dir" ]) |
| |
| assert(pkg.drivers == [] || pkg.system_image) |
| |
| mkfs_target = target_name + "_mkfs" |
| |
| # This action assembles an image containing all binaries, tests, drivers, |
| # libraries, and resources defined in the package. |
| action(mkfs_target) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| |
| package_manifest_contents = [] |
| |
| sources = [] |
| |
| foreach(entry, pkg.meta) { |
| assert(!pkg.system_image, "Metadata cannot be used in system packages.") |
| source = entry.path |
| sources += [ entry.path ] |
| dest = "meta/${entry.dest}" |
| package_manifest_contents += [ "$dest=$source" ] |
| } |
| if (defined(pkg.binary)) { |
| assert( |
| !pkg.system_image, |
| "Binary requires the package to be archived. Consider using 'binaries' for system packages.") |
| source = rebase_path("$root_build_dir/${pkg.binary}") |
| sources += [ "$root_build_dir/${pkg.binary}" ] |
| package_manifest_contents += [ "bin/app=$source" ] |
| } |
| foreach(binary, pkg.binaries) { |
| assert( |
| pkg.system_image, |
| "Binaries cannot be used in archived packages. Consider using 'binary'.") |
| |
| # Binary paths are relative to the root of the build dir. |
| if (defined(binary.source)) { |
| source = rebase_path("$root_build_dir/${binary.source}") |
| sources += [ "$root_build_dir/${binary.source}" ] |
| } else { |
| source = rebase_path("$root_build_dir/${binary.name}") |
| sources += [ "$root_build_dir/${binary.name}" ] |
| } |
| dirname = "bin" |
| if (pkg.app) { |
| dirname = "apps" |
| } |
| basename = binary.name |
| if (defined(binary.dest)) { |
| basename = binary.dest |
| } |
| package_manifest_contents += [ "$dirname/$basename=$source" ] |
| } |
| foreach(test, pkg.tests) { |
| source = rebase_path("$root_build_dir/${test.name}") |
| sources += [ "$root_build_dir/${test.name}" ] |
| basename = test.name |
| if (defined(test.dest)) { |
| basename = test.dest |
| } |
| if (defined(test.disabled) && test.disabled) { |
| dest = "test/disabled/" + basename |
| } else { |
| dest = "test/" + basename |
| } |
| package_manifest_contents += [ "$dest=$source" ] |
| } |
| foreach(driver, pkg.drivers) { |
| # Driver paths are relative to the root of the build dir. |
| source = rebase_path("$root_build_dir/${driver.name}") |
| sources += [ "$root_build_dir/${driver.name}" ] |
| dest = "driver/" + driver.name |
| |
| package_manifest_contents += [ "$dest=$source" ] |
| } |
| foreach(library, pkg.libraries) { |
| # Library paths are relative to the root of the build dir. |
| if (defined(library.source)) { |
| library_path = rebase_path(library.source) |
| } else { |
| library_path = "$shared_toolchain_out_dir/${library.name}" |
| } |
| source = rebase_path(library_path) |
| sources += [ library_path ] |
| if (defined(library.dest)) { |
| dest = "lib/" + library.dest |
| } else { |
| dest = "lib/" + library.name |
| } |
| package_manifest_contents += [ "$dest=$source" ] |
| } |
| foreach(resource, pkg.resources) { |
| # Resource path are absolute. |
| source = resource.path |
| sources += [ resource.path ] |
| dest = "data/" + resource.dest |
| package_manifest_contents += [ "$dest=$source" ] |
| } |
| |
| system_manifest = "$pkg_out_dir/system_manifest" |
| archive_manifest = "$pkg_out_dir/archive_manifest" |
| package_manifest = "$pkg_out_dir/package_manifest" |
| |
| if (pkg.system_image) { |
| write_file(system_manifest, package_manifest_contents) |
| write_file(archive_manifest, []) |
| write_file(package_manifest, []) |
| |
| # We have to do something in our action |
| script = "/usr/bin/touch" |
| output = "$pkg_out_dir/.stamp" |
| outputs = [ |
| output, |
| ] |
| args = [ rebase_path(output) ] |
| } else if (pkg.fuchsia_package) { |
| # If the caller doesn't supply a package.json, we'll generate one |
| need_package_json = true |
| foreach(meta, pkg.meta) { |
| if (meta == "package.json") { |
| need_package_json = false |
| } |
| } |
| |
| if (need_package_json) { |
| package_json_file = rebase_path("$pkg_out_dir/package.json") |
| write_file(package_json_file, "{\"name\": \"${pkg.package_name}\", \"version\": \"${pkg.package_version}\"}") |
| package_manifest_contents += [ "meta/package.json=${package_json_file}" ] |
| } |
| |
| write_file(package_manifest, package_manifest_contents) |
| write_file(archive_manifest, []) |
| write_file(system_manifest, []) |
| |
| pm_label = "//garnet/go/src/pm:pm_bin($host_toolchain)" |
| deps += [ pm_label ] |
| |
| pm_out_dir = get_label_info(pm_label, "root_out_dir") |
| pm_path = "$pm_out_dir/pm" |
| |
| output = "$pkg_out_dir/meta.far" |
| |
| script = "//build/gn_run_binary.sh" |
| inputs = [ |
| pm_path, |
| package_signing_key, |
| ] |
| outputs = [ |
| output, |
| ] |
| args = [ |
| clang_prefix, |
| rebase_path(pm_path, root_build_dir), |
| "-k", |
| rebase_path(package_signing_key), |
| "-m", |
| rebase_path(package_manifest), |
| "-o", |
| rebase_path(pkg_out_dir), |
| "build", |
| ] |
| |
| # Add the meta.far to the list of fuchsia packages |
| } else { |
| assert(package_manifest_contents != []) |
| write_file(package_manifest, []) |
| |
| write_file(archive_manifest, package_manifest_contents) |
| |
| archiver_label = "//garnet/bin/far:bin($host_toolchain)" |
| deps += [ archiver_label ] |
| |
| archiver_out_dir = get_label_info(archiver_label, "root_out_dir") |
| far_path = "$archiver_out_dir/far" |
| |
| output = "$pkg_out_dir/${pkg.package_name}.far" |
| |
| script = "//build/gn_run_binary.sh" |
| inputs = [ |
| far_path, |
| ] |
| outputs = [ |
| output, |
| ] |
| args = [ |
| clang_prefix, |
| rebase_path(far_path, root_build_dir), |
| "create", |
| "--archive=" + rebase_path(output), |
| "--manifest=" + rebase_path(archive_manifest), |
| ] |
| |
| write_file(system_manifest, |
| [ "pkgs/${pkg.package_name}=" + rebase_path(output) ]) |
| } |
| } |
| group(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| deps = [ |
| ":" + mkfs_target, |
| ] |
| } |
| } else { |
| group(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "deps", |
| ]) |
| } |
| |
| # Suppress unused variable warnings. |
| not_needed(invoker, "*") |
| } |
| } |