| # Copyright 2020 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/cpp/sdk_shared_library.gni") |
| import("//build/cpp/sdk_source_set.gni") |
| import("//build/cpp/sdk_static_library.gni") |
| import("//build/toolchain/toolchain_environment.gni") |
| |
| # Build a zircon-specific library, possibly in several ways. |
| # |
| # This template should be used by Zircon build rules exclusively, and follows |
| # most of the conventions of the Zircon build `library()` template, which |
| # differ significantly from those of `library()` in the Fuchsia build. |
| # |
| # IMPORTANT NOTE: Due to historical reasons, its behaviour is very different, |
| # depending on the value of the `is_kernel` global variable. |
| # |
| # * When building with a Zircon-specific toolchain, it will create a source_set() |
| # if the global `is_kernel` is true (meaning building part of the kernel), or |
| # a static_library() target otherwise. Teh values of `sdk`, `sdk_publishable` |
| # and `sdk_headers` will be ignored entirely. |
| # |
| # This will also create a :headers sub-target, a group used to give access |
| # to the library's include directory from any dependent. Note that this |
| # does *not* make the library's headers, listed in `sdk_headers` public. |
| # |
| # This behaviour is needed to replicate the Zircon build's behaviour when |
| # compiling Zircon artefacts. |
| # |
| # * When not using a Zircon-specific toolchain, which means the library is built |
| # either as a Fuchsia user binary or a host binary, `sdk` must be set to determine |
| # the shape of the library, as well as `sdk_headers to list the library's public |
| # headers, relative to its `include` sub-directory. |
| # |
| # If `sdk_publishable` is true, the library will be part of the Fuchsia SDK. |
| # |
| # Any :headers sub-targets that appear in public_deps will be rewritten into |
| # a dependency to the library itself, e.g.: |
| # |
| # public_deps = [ "//zircon/system/ulib/foo:headers" ] |
| # |
| # will be replaced by: |
| # |
| # public_deps = [ "//zircon/system/ulib/foo" ] |
| # |
| # Because the Fuchsia build doesn't support :headers sub-targets in |
| # non-kernel libraries for several technical reasons. |
| # |
| # Parameters |
| # |
| # sdk |
| # Optional: A value that indicates whether to build this library as a |
| # source set, static library or shared library with the Fuchsia build. |
| # This is required, except when building with Zircon-specific toolchains. |
| # Note that this name is confusing for historical reasons, because using |
| # this parameter does not make this library exported to the Fuchsia SDK |
| # (see `sdk_publishable` below for this). |
| # Type: "static" or "shared" or "source" |
| # |
| # sdk_publishable |
| # Optional: Indicates that this library can be added to the Fuchsia SDK. |
| # When false, the library is not added to the SDK. When true, it is added |
| # to the SDK with a "partner" category. Otherwise, a string value may be |
| # used to specify another category (e.g. `sdk_publishable` = "cts"`). |
| # Type: bool, or a string indicating an SDK category. |
| # Default: false |
| # |
| # sdk_headers |
| # Optional: Required, except if the global `is_kernel` is true. |
| # This must list all the public header files in the library's `include/` |
| # directory; names should be relative to `include/`. |
| # Type: list(string) |
| # |
| # sdk_name |
| # Optional: Name under which the library is published. This can be used |
| # when $target_name is already used by another target in the Fuchsia build. |
| # Type: string |
| # Default: target_name |
| # |
| # sdk_private_headers |
| # Optional: the list of header files that are not intended for direct |
| # inclusion by users. Such header files are part of the SDK package, but |
| # emit an error if included directly. |
| # |
| # See source_set() for other parameters. |
| # |
| template("zx_library") { |
| template_params = [ |
| "sdk", |
| "sdk_headers", |
| "sdk_publishable", |
| ] |
| |
| not_needed(invoker, |
| [ |
| "sdk_name", |
| |
| # Not all template expansion paths use this variable, don't |
| # error out in those paths. |
| "sdk_private_headers", |
| ]) |
| |
| if (zircon_toolchain != false) { |
| _library_name = target_name |
| |
| if (toolchain_environment == "kernel") { |
| # In the kernel proper, zx_library() is always a source_set(). |
| # Everything goes into the kernel and anything unused gets linker GC. |
| kernel_library_target_type = "source_set" |
| } else { |
| kernel_library_target_type = "static_library" |
| } |
| |
| # If the library has the same name as its directory, just create |
| # :headers and :headers.config sub-targets. Otherwise, create |
| # :foo.headers and :foo.headers.config |
| if (get_label_info(":$_library_name", "name") == |
| get_path_info(get_label_info(":$_library_name", "dir"), "file")) { |
| _headers_target = "headers" |
| _headers_config_target = "headers.config" |
| } else { |
| _headers_target = "$_library_name.headers" |
| _headers_config_target = "$_library_name.headers.config" |
| } |
| |
| target(kernel_library_target_type, _library_name) { |
| if (kernel_library_target_type == "static_library") { |
| complete_static_lib = true |
| } |
| forward_variables_from(invoker, "*", template_params) |
| if (!defined(public_deps)) { |
| public_deps = [] |
| } |
| public_deps += [ ":$_headers_target" ] |
| } |
| |
| group(_headers_target) { |
| # Used to represent header dependencies. |
| # Direct us of public_configs should be rare but is sometimes needed. |
| forward_variables_from(invoker, |
| [ |
| "public_configs", |
| "public_deps", |
| "testonly", |
| "visibility", |
| ]) |
| if (!defined(public_configs)) { |
| public_configs = [] |
| } |
| public_configs += [ ":${_headers_config_target}" ] |
| } |
| |
| config(_headers_config_target) { |
| include_dirs = [ "include" ] |
| } |
| } else { |
| assert( |
| defined(invoker.sdk), |
| "The `sdk` argument is needed to build a zx_library() with a Fuchsia or host toolchain ($current_toolchain)") |
| shape = invoker.sdk |
| |
| sdkable = |
| defined(invoker.sdk_publishable) && invoker.sdk_publishable != false |
| if (sdkable) { |
| if (invoker.sdk_publishable == true) { |
| sdk_category = "partner" |
| } else { |
| sdk_category = invoker.sdk_publishable |
| } |
| } |
| |
| extra_target_args = { |
| } |
| if (shape == "source") { |
| if (sdkable) { |
| name = target_name |
| if (defined(invoker.sdk_name)) { |
| name = invoker.sdk_name |
| } |
| target_type = "sdk_source_set" |
| if (sdk_category == "public" || sdk_category == "partner") { |
| # API version checks are only relevant for public or partner APIs. |
| # Here, and in the similar code below. |
| extra_target_args = { |
| api = "//sdk/lib/$target_name/$target_name.api" |
| build_as_static = true |
| category = sdk_category |
| sdk_name = name |
| if (defined(invoker.sdk_private_headers)) { |
| private_headers = invoker.sdk_private_headers |
| } |
| } |
| } else { |
| extra_target_args = { |
| category = sdk_category |
| sdk_name = name |
| build_as_static = true |
| if (defined(invoker.sdk_private_headers)) { |
| private_headers = invoker.sdk_private_headers |
| } |
| } |
| } |
| } else { |
| target_type = "static_library" |
| } |
| } else if (shape == "static") { |
| if (sdkable) { |
| target_type = "sdk_static_library" |
| if (sdk_category == "public" || sdk_category == "partner") { |
| extra_target_args = { |
| api = "//sdk/lib/$target_name/$target_name.api" |
| category = sdk_category |
| libcxx_linkage = "static" |
| sdk_name = target_name |
| if (defined(invoker.sdk_private_headers)) { |
| private_headers = invoker.sdk_private_headers |
| } |
| } |
| } else { |
| extra_target_args = { |
| category = sdk_category |
| sdk_name = target_name |
| libcxx_linkage = "static" |
| if (defined(invoker.sdk_private_headers)) { |
| private_headers = invoker.sdk_private_headers |
| } |
| } |
| } |
| } else { |
| target_type = "static_library" |
| } |
| } else if (shape == "shared") { |
| if (sdkable) { |
| target_type = "sdk_shared_library" |
| if (sdk_category == "public" || sdk_category == "partner") { |
| extra_target_args = { |
| api = "//sdk/lib/$target_name/$target_name.api" |
| category = sdk_category |
| libcxx_linkage = "static" |
| sdk_name = target_name |
| symbols_api = "//sdk/lib/$target_name/$target_name.symbols.api" |
| if (defined(invoker.sdk_private_headers)) { |
| private_headers = invoker.sdk_private_headers |
| } |
| } |
| } else { |
| extra_target_args = { |
| category = sdk_category |
| sdk_name = target_name |
| libcxx_linkage = "static" |
| if (defined(invoker.sdk_private_headers)) { |
| private_headers = invoker.sdk_private_headers |
| } |
| } |
| } |
| } else { |
| target_type = "shared_library" |
| } |
| } else { |
| assert(false, "Unknown library type: $shape") |
| } |
| |
| main_target_name = target_name |
| config_target_name = "$target_name.config" |
| |
| config(config_target_name) { |
| include_dirs = [ "include" ] |
| } |
| |
| # IMPORTANT: Rewrite header dependencies in public_deps |
| # |
| # For each zx_library(), the Zircon build used to produce a 'headers' |
| # group that adds a 'headers.config' public config. This is done to allow |
| # other targets to depend on the library's headers, but not the library |
| # itself. |
| # |
| # In practice, this means it is common for targets to list these headers |
| # groups in their public_deps, as in: |
| # |
| # public_deps = [ "//sdk/lib/fit:headers" ] |
| # |
| # However, these groups do not mix well with the Fuchsia build, and |
| # especially with sdk_source_set() or sdk_static_library(). |
| # |
| # To work around this, rewrite the headers public dependencies into |
| # regular dependencies into the libraries themselves. |
| # |
| lib_deps = [] |
| if (defined(invoker.deps)) { |
| lib_deps = invoker.deps |
| } |
| lib_public_deps = [] |
| if (defined(invoker.public_deps)) { |
| foreach(dep, invoker.public_deps) { |
| if (get_label_info(dep, "name") == "headers") { |
| # Format //zircon/.../foo:headers -> //zircon/.../foo |
| dep = get_label_info(dep, "dir") |
| } else if (get_path_info(get_label_info(dep, "name"), "extension") == |
| "headers") { |
| # Format //zircon/.../foo:bar.headers -> //zircon/.../foo:bar |
| dep = get_label_info(dep, "dir") + ":" + |
| get_path_info(get_label_info(dep, "name"), "name") |
| } |
| lib_public_deps += [ dep ] |
| } |
| } |
| |
| # Remove references to a libzircon dependency, as it is provided by the |
| # sysroot in the present build. |
| |
| lib_libs = [] |
| if (defined(invoker.libs)) { |
| lib_libs = invoker.libs |
| } |
| |
| if (!is_fuchsia) { |
| lib_public_deps += [ "//zircon/system/public" ] |
| } |
| |
| _has_public_headers = |
| defined(invoker.sdk_headers) && invoker.sdk_headers != [] |
| |
| target(target_type, main_target_name) { |
| forward_variables_from(invoker, |
| "*", |
| template_params + [ |
| "deps", |
| "libs", |
| "public_deps", |
| ]) |
| |
| deps = lib_deps |
| libs = lib_libs |
| public_deps = lib_public_deps |
| |
| forward_variables_from(extra_target_args, "*") |
| |
| if (_has_public_headers) { |
| public = [] |
| foreach(header, invoker.sdk_headers) { |
| public += [ "include/$header" ] |
| } |
| } |
| |
| if (!defined(public_configs)) { |
| public_configs = [] |
| } |
| public_configs += [ ":$config_target_name" ] |
| |
| if (!defined(defines)) { |
| defines = [] |
| } |
| defines += [ "_ALL_SOURCE" ] |
| |
| if (!defined(data_deps)) { |
| data_deps = [] |
| } |
| |
| # Add allowlist to data_deps rather than deps to not trigger SDK deps logic |
| data_deps += [ "//build:deprecated_zx_wrapper_allowlist" ] |
| } |
| } |
| |
| # Uncomment the below to generate the allowlist |
| #print("\"" + get_label_info(":$target_name", "dir") + "/*\",") |
| } |
| |
| set_defaults("zx_library") { |
| configs = default_common_binary_configs |
| } |