| # Copyright 2021 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/components/fuchsia_component.gni") |
| import("//build/dist/distribution_manifest.gni") |
| import("//build/drivers/driver_manifest.gni") |
| import("//tools/cmc/build/cmc.gni") |
| |
| # Defines a Fuchsia driver component. |
| # A driver component is a normal component that launches a driver. |
| # For more information on components see: |
| # https://fuchsia.dev/fuchsia-src/development/components/build |
| # |
| # At the moment this template will generate the Component Manifest |
| # at build time. If you'd like to write your own Component Manifest, |
| # simply use the fuchsia_component build template. |
| # |
| # The component manifest is automatically generated that points to the |
| # correct driver library and bind file. If 'deps' includes more than |
| # one driver library or more than one bind file, this will cause a build-time |
| # error. |
| # |
| # Parameters |
| # |
| # manifest (optional) |
| # The component manifest. If this and `cm_label` are not present then this target will |
| # generate a component manifest for the driver. |
| # Type: path |
| # cm_label (optional) |
| # A `fuchsia_component_manifest` target label. If this and `manifest` are not present then this |
| # target will generate a component manifest for the driver. |
| # Type: GN label, e.g. `:my_manifest` |
| # is_v1_driver (optional) |
| # If this is true then the driver is a v1 driver and it will be placed in a |
| # compatibility shim when running in a DFv2 environment. |
| # Type: bool |
| # Default: true |
| # fallback (optional) |
| # If this is true then the driver is a fallback driver. |
| # Type: bool |
| # Default: false |
| # colocate (optional) |
| # If this is true, the driver will be put in the same DriverHost as its parent. |
| # This currently only affects composite drivers. |
| # Type: boolean |
| # Default: false |
| # root_resource (optional) |
| # If this is true, the driver will be given access to the root resource. |
| # This only affects drivers with automatically generated manifests. |
| # Type: bool |
| # Default: false |
| # uses_profiles (optional) |
| # If this is true, the driver will be given access to the profile provider service. |
| # Type: bool |
| # Default: false |
| # uses_sysmem (optional) |
| # If this is true, the driver will be given access to sysmem. |
| # Type: bool |
| # Default: false |
| # composite_nodes (optional) |
| # If this is set, then the driver has this list of composite |
| # nodes, and the driver's CML file will accept capabilities from each. |
| # Type: array of strings |
| # Default: [] |
| # default_dispatcher_opts (optional) |
| # If this is set, then the default dispatcher for the driver will be |
| # created with these options. |
| # Type: array of strings |
| # Default: [] |
| # info (mandatory for //src and //zircon) |
| # Name of the file containing the driver information file. |
| # Type: file |
| # deps |
| # testonly |
| # visibility |
| template("fuchsia_driver_component") { |
| if (current_toolchain == default_toolchain) { |
| generate_manifest = true |
| if (defined(invoker.manifest) || defined(invoker.cm_label)) { |
| generate_manifest = false |
| } |
| assert(!(defined(invoker.manifest) && defined(invoker.cm_label)), |
| "`manifest` and `cm_label` cannot be defined simultaneously") |
| is_v1_driver = true |
| if (defined(invoker.is_v1_driver)) { |
| is_v1_driver = invoker.is_v1_driver |
| } |
| |
| if (generate_manifest) { |
| distribution_manifest_target = "${target_name}_distribution_manifest" |
| distribution_manifest_file = |
| "${target_gen_dir}/${target_name}.distribution_manifest" |
| distribution_manifest(distribution_manifest_target) { |
| visibility = [ ":*" ] |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| outputs = [ "${distribution_manifest_file}" ] |
| } |
| |
| manifest_target = "${target_name}_manifest" |
| manifest_path = "${target_gen_dir}/meta/${target_name}.cml" |
| fallback = false |
| if (defined(invoker.fallback)) { |
| fallback = invoker.fallback |
| } |
| action(manifest_target) { |
| visibility = [ ":*" ] |
| forward_variables_from(invoker, [ "testonly" ]) |
| deps = [ ":${distribution_manifest_target}" ] |
| script = "//build/drivers/create_component_manifest.py" |
| inputs = [ distribution_manifest_file ] |
| outputs = [ manifest_path ] |
| args = [ |
| "--distribution_manifest", |
| rebase_path(distribution_manifest_file, root_build_dir), |
| "--output", |
| rebase_path(outputs[0], root_build_dir), |
| ] |
| if (is_v1_driver) { |
| args += [ "--is_v1" ] |
| } |
| if (fallback) { |
| args += [ "--fallback" ] |
| } |
| if (defined(invoker.colocate) && invoker.colocate) { |
| args += [ "--colocate" ] |
| } |
| if (defined(invoker.root_resource) && invoker.root_resource) { |
| args += [ "--root_resource" ] |
| } |
| if (defined(invoker.uses_profiles) && invoker.uses_profiles) { |
| args += [ "--profile_provider" ] |
| } |
| if (defined(invoker.uses_sysmem) && invoker.uses_sysmem) { |
| args += [ "--sysmem" ] |
| } |
| if (defined(invoker.composite_nodes)) { |
| args += [ "--composite" ] |
| args += invoker.composite_nodes |
| } |
| |
| # TODO(fxbug.dev/99310): set allow_sync_calls for v1 drivers |
| # if they did not specify any opts. |
| if (defined(invoker.default_dispatcher_opts)) { |
| args += [ "--default_dispatcher_opts" ] |
| args += invoker.default_dispatcher_opts |
| } |
| } |
| |
| full_manifest_target = "${target_name}_full_manifest" |
| cmc_merge(full_manifest_target) { |
| visibility = [ ":*" ] |
| forward_variables_from(invoker, [ "testonly" ]) |
| output_name = invoker.target_name + ".cml" |
| deps = [ ":${manifest_target}" ] |
| sources = [] |
| foreach(dep, deps) { |
| sources += get_target_outputs(dep) |
| } |
| } |
| } |
| |
| driver_path = |
| get_path_info(get_path_info(invoker.target_name, "abspath"), "dir") |
| splitted_path = string_split(driver_path, "/") |
| base_folder = splitted_path[2] # after removing "//" |
| create_driver_doc = false |
| if (base_folder == "src" || base_folder == "zircon") { |
| # Public drivers (defined as drivers in //src and //zircon) must provide an 'info' field with |
| # a driver information file. |
| assert(defined(invoker.info), "Must include driver info") |
| create_driver_doc = true |
| } else { |
| # Ignore info assignment if present, e.g. from //tools templates. |
| if (defined(invoker.info)) { |
| not_needed(invoker, [ "info" ]) |
| } |
| } |
| |
| if (create_driver_doc) { |
| doc_output = "${target_gen_dir}/${target_name}-doc.json" |
| doc_target = "${target_name}-driver-info" |
| |
| name = invoker.target_name |
| if (defined(invoker.component_name)) { |
| name = invoker.component_name |
| } |
| doc_input = invoker.info |
| action(doc_target) { |
| visibility = [ ":*" ] |
| forward_variables_from(invoker, [ "testonly" ]) |
| script = "//build/drivers/create_driver_doc.py" |
| inputs = [ |
| driver_path, |
| doc_input, |
| ] |
| outputs = [ "${doc_output}" ] |
| args = [ |
| "--name", |
| name, |
| "--driver_path", |
| driver_path, |
| "--doc_input", |
| rebase_path(doc_input, root_build_dir), |
| "--doc_output", |
| rebase_path(outputs[0], root_build_dir), |
| ] |
| } |
| } |
| |
| fuchsia_component(target_name) { |
| # TODO(fxbug.dev/80980): Remove check_includes = false. |
| if (!defined(invoker.cm_label)) { |
| check_includes = false |
| } |
| forward_variables_from(invoker, |
| [ |
| "cm_label", |
| "component_name", |
| "deps", |
| "manifest", |
| "manifest_deps", |
| "restricted_features", |
| "testonly", |
| "visibility", |
| ]) |
| if (generate_manifest) { |
| if (!defined(manifest_deps)) { |
| manifest_deps = [] |
| } |
| manifest_deps += [ ":${full_manifest_target}" ] |
| manifest = get_target_outputs(":${full_manifest_target}") |
| manifest = manifest[0] |
| } |
| if (!defined(deps)) { |
| deps = [] |
| } |
| if (create_driver_doc) { |
| deps += [ ":${doc_target}" ] |
| not_needed(invoker, [ ":${doc_target}" ]) |
| } |
| if (is_v1_driver) { |
| deps += [ "//src/devices/misc/drivers/compat:driver" ] |
| } |
| metadata = { |
| # Used by the assert_driver_components template. |
| driver_component_barrier = [] |
| |
| if (create_driver_doc) { |
| # Used by the create_all_drivers_doc template. |
| fuchsia_driver_doc_file = [ doc_output ] |
| } |
| } |
| } |
| } else { |
| group(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| deps = [ ":$target_name($default_toolchain)" ] |
| } |
| not_needed(invoker, "*") |
| } |
| } |