| # Copyright 2019 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/config/fuchsia/zircon.gni") |
| import("//build/cpp/extract_public_symbols.gni") |
| import("//build/cpp/verify_pragma_once.gni") |
| import("//build/cpp/verify_public_symbols.gni") |
| import("//build/fidl/wireformat.gni") |
| import("//build/sdk/sdk_atom.gni") |
| |
| # Define a library in //zircon/public/lib/$target_name/BUILD.gn. |
| # |
| # zircon_library() is invoked by files copied from lib_template.gn based on |
| # "$zircon_root_build_dir/legacy-$target_cpu.json" entries generated by |
| # Zircon library() targets with $sdk set. They provide the deps API for |
| # Fuchsia targets to depend on Zircon libraries, which are either used as |
| # binaries previously built by Zircon, or built in Fuchsia from source. |
| # |
| # Parameters |
| # |
| # deps, public_deps |
| # Optional: Dependencies for the target. $deps is only relevant for |
| # source libraries. $public_deps reflects header dependencies. |
| # Type: list(label matching "//zircon/public/lib/*") |
| # |
| # dir |
| # Required: Source-absolute path to library's source directory in //zircon. |
| # Type: dir |
| # |
| # sources |
| # Optional: If present, publish library as source with these files. |
| # Type: list(file) |
| # |
| # libs |
| # Optional: If present, publish library as prebuilt with these files. |
| # Type: list(path relative to $zircon_root_build_dir) |
| # |
| # include_dirs |
| # Required: The directory prefix where $headers are found. |
| # Type: singleton list(path relative to $zircon_root_build_dir) |
| # |
| # headers |
| # Required: List of header files to copy into the SDK. |
| # Type: list(path relative to ${include_dirs[0]}) |
| # |
| # publishable |
| # Optional: Whether the library is eligible for addition to SDKs. |
| # Type: bool |
| # Default: false |
| # |
| # Either $sources or $libs must be present. |
| # |
| template("zircon_library") { |
| library = target_name |
| |
| include = rebase_path(invoker.include_dirs, ".", zircon_root_build_dir) |
| assert(include == [ include[0] ]) |
| library_headers = rebase_path(invoker.headers, ".", include[0]) |
| |
| # Zircon targets depend explicitly on $zx/system/ulib/zircon, but in |
| # legacy Fuchsia GN there is no //zircon/public/lib/zircon and instead |
| # it's available implicitly in the sysroot via `libs = [ "zircon" ]`. |
| library_deps = [] |
| library_public_deps = [] |
| library_libs = [] |
| if (defined(invoker.deps)) { |
| library_deps = invoker.deps |
| } |
| if (defined(invoker.public_deps)) { |
| library_public_deps = invoker.public_deps |
| } |
| |
| # Remove references to a libzircon dependency, as it is provided by the |
| # sysroot in the present build. |
| if (library_deps + [ "//zircon/public/lib/zircon" ] - |
| [ "//zircon/public/lib/zircon" ] != library_deps) { |
| library_deps -= [ "//zircon/public/lib/zircon" ] |
| if (is_fuchsia) { |
| library_libs += [ "zircon" ] |
| } else { |
| library_deps += [ |
| "//zircon/public/lib/zircon-headers", |
| "//zircon/system/public", |
| ] |
| } |
| } |
| if (library_public_deps + [ "//zircon/public/lib/zircon" ] - |
| [ "//zircon/public/lib/zircon" ] != library_public_deps) { |
| library_public_deps -= [ "//zircon/public/lib/zircon" ] |
| if (is_fuchsia) { |
| library_libs += [ "zircon" ] |
| } else { |
| library_public_deps += [ |
| "//zircon/public/lib/zircon-headers", |
| "//zircon/system/public", |
| ] |
| } |
| } |
| |
| # Update dependency on libdriver, whose implementation is provided by the |
| # present build. |
| if (library_deps + [ "//zircon/public/lib/driver" ] - |
| [ "//zircon/public/lib/driver" ] != library_deps) { |
| library_deps -= [ "//zircon/public/lib/driver" ] |
| library_deps += [ "//src/devices/lib/driver" ] |
| } |
| if (library_public_deps + [ "//zircon/public/lib/driver" ] - |
| [ "//zircon/public/lib/driver" ] != library_public_deps) { |
| library_public_deps -= [ "//zircon/public/lib/driver" ] |
| library_public_deps += [ "//src/devices/lib/driver" ] |
| } |
| |
| # Update references to boringssl. |
| foreach(prefix, |
| [ |
| "", |
| "u", |
| ]) { |
| if (library_deps + [ "//zircon/public/lib/${prefix}boringssl" ] - |
| [ "//zircon/public/lib/${prefix}boringssl" ] != library_deps) { |
| library_deps -= [ "//zircon/public/lib/${prefix}boringssl" ] |
| library_deps += [ "//third_party/boringssl" ] |
| } |
| if (library_public_deps + [ "//zircon/public/lib/${prefix}boringssl" ] - |
| [ "//zircon/public/lib/${prefix}boringssl" ] != library_public_deps) { |
| library_public_deps -= [ "//zircon/public/lib/${prefix}boringssl" ] |
| library_public_deps += [ "//third_party/boringssl" ] |
| } |
| } |
| |
| # Update reference to zstd libraries, for which there exist targets under |
| # //third_party/zstd. |
| foreach(library, |
| [ |
| "zstd", |
| "zstdseek", |
| ]) { |
| if (library_deps + [ "//zircon/public/lib/$library" ] - |
| [ "//zircon/public/lib/$library" ] != library_deps) { |
| library_deps -= [ "//zircon/public/lib/$library" ] |
| library_deps += [ "//third_party/zstd:$library" ] |
| } |
| if (library_public_deps + [ "//zircon/public/lib/$library" ] - |
| [ "//zircon/public/lib/$library" ] != library_public_deps) { |
| library_public_deps -= [ "//zircon/public/lib/$library" ] |
| library_public_deps += [ "//third_party/zstd:$library" ] |
| } |
| } |
| |
| is_prebuilt = defined(invoker.libs) |
| |
| zx_lib_dirs = [] |
| zx_libs = [] |
| if (is_prebuilt) { |
| # A prebuilt binary (either static .a or shared .so, doesn't matter) |
| # has nothing to do but bring in the config() for its `libs`. |
| type = "group" |
| |
| # Rust targets use -L... -lfoo instead of explicit files. So they |
| # need to collect the -L list via metadata, and directories on that |
| # list needs to hold exact names libfoo.so or libfoo.a for -lfoo. |
| foreach(file, invoker.libs) { |
| if (get_path_info(file, "extension") == "so" || |
| get_path_info(file, "extension") == "a") { |
| zx_lib_dirs += [ rebase_path(get_path_info(file, "dir"), |
| "", |
| zircon_root_build_dir) ] |
| zx_libs += [ get_path_info(file, "name") ] |
| } else { |
| file = rebase_path(file, "", zircon_root_build_dir) |
| write_file("$target_gen_dir/lib$library.so", [ "INPUT($file)" ]) |
| zx_lib_dirs += [ rebase_path(target_gen_dir) ] |
| zx_libs += [ library ] |
| } |
| } |
| if (defined(invoker.lib_dirs)) { |
| zx_lib_dirs += rebase_path(invoker.lib_dirs, "", zircon_root_build_dir) |
| } |
| } else { |
| # A source library is always built for static linking only. |
| # The invoker (i.e. the JSON) specifies `sources`. |
| type = "static_library" |
| } |
| |
| # A library() always an include/ directory dependents must use. |
| # A prebuilt library() (`sdk != "source"`) has a library they must link in. |
| config("$library.config") { |
| include_dirs = include |
| if (!is_prebuilt) { |
| include_dirs += invoker.compilation_include_dirs |
| } else { |
| not_needed(invoker, [ "compilation_include_dirs" ]) |
| } |
| if (is_fuchsia || is_prebuilt) { |
| libs = library_libs |
| lib_dirs = zx_lib_dirs |
| not_needed([ "zx_libs" ]) |
| } else { |
| not_needed([ |
| "library_libs", |
| "zx_lib_dirs", |
| "zx_libs", |
| ]) |
| } |
| if (defined(invoker.libs) && invoker.libs != []) { |
| is_host_library = |
| string_replace(library, "-host", "") + "-host" == library |
| assert(is_fuchsia != is_host_library, |
| "Prebuilt $library used in wrong toolchain") |
| libs += rebase_path(invoker.libs, ".", zircon_root_build_dir) |
| } |
| } |
| |
| has_runtime_dep = false |
| if (is_prebuilt) { |
| foreach(file, invoker.install) { |
| if (get_path_info(file.dest, "dir") == "dist") { |
| has_runtime_dep = true |
| } |
| } |
| |
| if (has_runtime_dep) { |
| import("//build/unification/lib/zircon_runtime_library.gni") |
| |
| runtime_target = "${library}_runtime" |
| |
| zircon_runtime_library(runtime_target) { |
| library = library |
| } |
| } |
| } |
| |
| target(type, library) { |
| forward_variables_from(invoker, |
| "*", |
| [ |
| "compilation_defines", |
| "compilation_include_dirs", |
| "debug", |
| "deps", |
| "dir", |
| "disable_ubsan", |
| "disable_unused_function", |
| "headers", |
| "include_dirs", |
| "install", |
| "lib_dirs", |
| "dist_dir", |
| "libs", |
| "public_deps", |
| "publishable", |
| "source_dir", |
| ]) |
| public_configs = [ ":$library.config" ] |
| if (!is_prebuilt) { |
| configs += [ "//build/unification/config:zircon-library" ] |
| if (defined(invoker.disable_ubsan) && invoker.disable_ubsan) { |
| configs += [ "//build/config:temporarily_disable_ubsan_do_not_use" ] |
| } |
| if (defined(invoker.disable_unused_function) && |
| invoker.disable_unused_function) { |
| configs += [ "//build/config:Wno-unused-function" ] |
| } |
| defines = invoker.compilation_defines |
| } else { |
| not_needed(invoker, [ "compilation_defines" ]) |
| } |
| deps = library_deps |
| public_deps = library_public_deps |
| if (!is_fuchsia) { |
| public_deps += [ "//zircon/system/public" ] |
| } |
| metadata = { |
| } |
| if (zx_lib_dirs != []) { |
| metadata.zircon_lib_dirs = zx_lib_dirs |
| } |
| if (has_runtime_dep) { |
| if (!defined(data_deps)) { |
| data_deps = [] |
| } |
| data_deps += [ ":$runtime_target" ] |
| } |
| |
| # TODO(fxb/41298): This is a temporary change to activate writing the |
| # v1 FIDL wire-format selectively. Remove this when all bindings start |
| # writing v1 wire-format by default. |
| if (library == "fidl_base" && type == "static_library" && |
| fidl_write_v1_wireformat) { |
| if (!defined(defines)) { |
| defines = [] |
| } |
| defines += [ "FIDL_EXPERIMENTAL_WRITE_V1_WIREFORMAT" ] |
| } |
| |
| if (!is_prebuilt) { |
| if (!defined(defines)) { |
| defines = [] |
| } |
| defines += [ "_ALL_SOURCE" ] |
| } |
| |
| # Manually add data dependencies. |
| # That information is not available in the metadata provided by the ZN |
| # build, so we manually replicate it here. |
| if (!defined(data_deps)) { |
| data_deps = [] |
| } |
| if (library == "hermetic-decompressor") { |
| data_deps += [ |
| "//build/unification/data:hermetic.decompress-lz4f", |
| "//build/unification/data:hermetic.decompress-zstd", |
| ] |
| } |
| if (library == "fs-management") { |
| data_deps += [ |
| "//build/unification/data:bin.fsck-msdosfs", |
| "//zircon/third_party/uapp/mkfs-msdosfs", |
| "//zircon/system/uapp/blobfs", |
| "//zircon/system/uapp/minfs", |
| ] |
| } |
| |
| # Tests migrated from the Zircon build depend on libraries exposed in |
| # //zircon/public/lib. However, these tests cannot be marked as "testonly" |
| # for legacy reasons (in short: the -many- targets that transitively depend |
| # on them via manifests are not testonly). Rather than introduce a huge |
| # number of testonly markers everywhere, we disable it here, knowing that |
| # we can and should reintroduce it when these libraries are migrated away |
| # from the Zircon build. This seems like an acceptable compromise given that |
| # the vast majority of these libraries do not have the marker anyways. |
| testonly = false |
| } |
| |
| if (defined(invoker.publishable) && invoker.publishable) { |
| verify_pragma_once("$library-cpp_pragma") { |
| headers = library_headers |
| } |
| |
| lib_to_extract_symbols = "" |
| foreach(file, invoker.install) { |
| if (get_path_info(file.dest, "dir") == "lib") { |
| # TODO(DX-688): formulate a policy around and handle static archives |
| if (get_path_info(file.dest, "extension") != "a") { |
| assert(lib_to_extract_symbols == "", |
| "There should be only one entry under lib") |
| lib_to_extract_symbols = file.source |
| } |
| } |
| } |
| if (lib_to_extract_symbols != "") { |
| lib_name = library |
| generated_symbols_file = "$target_gen_dir/$lib_name.symbols.api" |
| reference_symbols_file = "//sdk/lib/$lib_name/$lib_name.symbols.api" |
| extract_public_symbols("$library-extract_public_symbols") { |
| library = rebase_path(lib_to_extract_symbols, "", zircon_root_build_dir) |
| |
| # No dependencies, since all of Zircon has been built |
| symbols = generated_symbols_file |
| } |
| verify_public_symbols("$library-verify_public_symbols") { |
| current = generated_symbols_file |
| reference = reference_symbols_file |
| library_name = "(zircon) ${lib_name}" |
| deps = [ ":$library-extract_public_symbols" ] |
| } |
| } |
| |
| is_shared = false |
| if (invoker.install != []) { |
| _debug = invoker.debug |
| installed_binaries = { |
| if (_debug != []) { |
| assert(_debug == [ _debug[0] ]) |
| debug = rebase_path(_debug[0], "", zircon_root_build_dir) |
| } |
| } |
| foreach(file, invoker.install) { |
| if (get_path_info(file.dest, "dir") == "dist") { |
| installed_binaries.dist = "arch/$target_cpu/${file.dest}" |
| file_name = get_path_info(file.dest, "file") |
| installed_binaries.dist_path = "lib/$file_name" |
| } else if (get_path_info(file.dest, "dir") == "lib") { |
| installed_binaries.link = "arch/$target_cpu/${file.dest}" |
| } |
| } |
| is_shared = get_path_info(installed_binaries.link, "extension") == "so" |
| } |
| |
| _sdk_deps = [] |
| if (!is_shared && defined(invoker.deps)) { |
| _sdk_deps += invoker.deps |
| } |
| if (defined(invoker.public_deps)) { |
| _sdk_deps += invoker.public_deps |
| } |
| |
| # De-duplicate. |
| sdk_deps = [] |
| foreach(label, _sdk_deps) { |
| sdk_deps += [ label ] |
| sdk_deps -= [ label ] |
| sdk_deps += [ label ] |
| } |
| |
| _lib_deps = [] |
| _fidl_deps = [] |
| _banjo_deps = [] |
| foreach(label, sdk_deps) { |
| if (get_path_info(get_path_info(label, "dir"), "name") == "fidl") { |
| _fidl_deps += [ get_path_info(get_label_info(label, "dir"), "name") ] |
| } else if (get_path_info(get_path_info(label, "dir"), "name") == |
| "banjo") { |
| _banjo_deps += [ get_path_info(get_label_info(label, "dir"), "name") ] |
| } else { |
| _lib_deps += [ get_path_info(get_label_info(label, "dir"), "name") ] |
| } |
| } |
| |
| # Zircon targets depend explicitly on $zx/system/ulib/zircon, but in |
| # legacy Fuchsia GN there is no //zircon/public/lib/zircon and instead |
| # it's available implicitly in the sysroot via `libs = [ "zircon" ]`. |
| # zircon-internal is a header-only library used by some static libraries. |
| _lib_deps += [ |
| "zircon", |
| "zircon-internal", |
| ] |
| _lib_deps -= [ |
| "zircon", |
| "zircon-internal", |
| ] |
| |
| pkg = "pkg/$library" |
| sdk_metadata = { |
| name = library |
| root = pkg |
| if (defined(invoker.sources)) { |
| type = "cc_source_library" |
| } else { |
| type = "cc_prebuilt_library" |
| } |
| |
| include_dir = "$pkg/include" |
| headers = rebase_path(invoker.headers, "//", "//$pkg/include") |
| if (defined(invoker.sources)) { |
| sources = rebase_path(rebase_path(invoker.sources, invoker.source_dir), |
| "//", |
| "//$pkg") |
| } |
| |
| deps = _lib_deps |
| if (invoker.install == []) { |
| banjo_deps = _banjo_deps |
| fidl_deps = _fidl_deps |
| } else { |
| not_needed([ |
| "_banjo_deps", |
| "_fidl_deps", |
| ]) |
| if (is_shared) { |
| format = "shared" |
| } else if (get_path_info(installed_binaries.link, "extension") == "a") { |
| format = "static" |
| } |
| binaries = { |
| if (target_cpu == "arm64") { |
| arm64 = installed_binaries |
| } else if (target_cpu == "x64") { |
| x64 = installed_binaries |
| } |
| } |
| } |
| } |
| |
| sdk_atom("${library}_sdk") { |
| id = "sdk://pkg/$library" |
| category = "partner" |
| |
| meta = { |
| dest = "$pkg/meta.json" |
| schema = sdk_metadata.type |
| if (invoker.debug == []) { |
| value = sdk_metadata |
| } else { |
| source = "$target_out_dir/$library.meta.out.json" |
| } |
| } |
| |
| non_sdk_deps = [ ":$library-cpp_pragma" ] |
| if (lib_to_extract_symbols != "") { |
| non_sdk_deps += [ ":$library-verify_public_symbols" ] |
| } |
| if (invoker.debug != []) { |
| non_sdk_deps += [ ":$library-meta" ] |
| file_list = "$target_out_dir/$library.debug.manifest" |
| } |
| |
| deps = [] |
| foreach(dep, _sdk_deps) { |
| if (dep != "//zircon/public/lib/zircon" && |
| dep != "//zircon/public/lib/zircon-internal") { |
| full_label = get_label_info(dep, "label_no_toolchain") |
| sdk_dep = "${full_label}_sdk" |
| deps += [ sdk_dep ] |
| } |
| } |
| |
| files = [] |
| |
| api_contents = [] |
| foreach(file, library_headers) { |
| api_contents += [ |
| { |
| source = file |
| dest = "$pkg/include/" + rebase_path(file, include[0]) |
| }, |
| ] |
| } |
| files += api_contents |
| |
| if (api_contents != []) { |
| api = "//sdk/lib/$library/$library.api" |
| } |
| |
| if (defined(invoker.sources)) { |
| foreach(file, invoker.sources) { |
| files += [ |
| { |
| source = file |
| dest = "$pkg/" + rebase_path(file, invoker.source_dir) |
| }, |
| ] |
| } |
| } |
| |
| foreach(file, invoker.install) { |
| files += [ |
| { |
| source = rebase_path(file.source, "", zircon_root_build_dir) |
| dest = "arch/$target_cpu/${file.dest}" |
| }, |
| ] |
| } |
| } |
| |
| if (invoker.debug != []) { |
| write_file("$target_gen_dir/$library.meta.in.json", sdk_metadata, "json") |
| action("$library-meta") { |
| visibility = [ ":*" ] |
| script = "//build/zircon/sdk_build_id.py" |
| sources = [ "$target_gen_dir/$library.meta.in.json" ] |
| outputs = [ |
| "$target_out_dir/$library.meta.out.json", |
| "$target_out_dir/$library.debug.manifest", |
| ] |
| args = [ |
| "--input=" + rebase_path(sources[0], root_build_dir), |
| "--output=" + rebase_path(outputs[0], root_build_dir), |
| "--manifest=" + rebase_path(outputs[1], root_build_dir), |
| "--location=/binaries/$target_cpu/debug", |
| ] |
| } |
| } |
| } else { |
| not_needed([ "library_headers" ]) |
| } # defined(invoker.publishable) && invoker.publishable |
| } |