blob: 48fa2326ae09089afe879b5d65a27853478a606a [file] [log] [blame]
# 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/verify_pragma_once.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 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]})
#
# 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
}
if (library_deps + [ "//zircon/public/lib/zircon" ] -
[ "//zircon/public/lib/zircon" ] != library_deps) {
library_deps -= [ "//zircon/public/lib/zircon" ]
library_libs += [ "zircon" ]
}
if (library_public_deps + [ "//zircon/public/lib/zircon" ] -
[ "//zircon/public/lib/zircon" ] != library_public_deps) {
library_public_deps -= [ "//zircon/public/lib/zircon" ]
library_libs += [ "zircon" ]
}
# 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_fuchsia) {
libs = library_libs
} else {
not_needed([ "library_libs" ])
}
if (defined(invoker.libs) && invoker.libs != []) {
assert(is_fuchsia, "Prebuilt $library used for host")
libs += rebase_path(invoker.libs, ".", zircon_root_build_dir)
}
}
if (defined(invoker.libs)) {
# 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"
} else {
# A source library is always built for static linking only.
# The invoker (i.e. the JSON) specifies `sources`.
type = "static_library"
}
target(type, library) {
forward_variables_from(invoker,
"*",
[
"debug",
"deps",
"dir",
"headers",
"include_dirs",
"install",
"lib_dirs",
"dist_dir",
"libs",
"public_deps",
"source_dir",
])
public_configs = [ ":$library.config" ]
deps = library_deps
public_deps = library_public_deps
if (!is_fuchsia) {
public_deps += [ "//zircon/system/public" ]
}
if (defined(invoker.libs)) {
# 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.
metadata = {
zircon_lib_dirs = []
foreach(file, invoker.libs) {
if (get_path_info(file, "extension") == "so" ||
get_path_info(file, "extension") == "a") {
zircon_lib_dirs += [ rebase_path(get_path_info(file, "dir"),
"",
zircon_root_build_dir) ]
} else {
file = rebase_path(file, "", zircon_root_build_dir)
write_file("$target_gen_dir/lib$library.so", [ "INPUT($file)" ])
zircon_lib_dirs += [ rebase_path(target_gen_dir) ]
}
}
if (defined(invoker.lib_dirs)) {
zircon_lib_dirs +=
rebase_path(invoker.lib_dirs, "", zircon_root_build_dir)
}
}
}
}
verify_pragma_once("$library-cpp_pragma") {
headers = library_headers
}
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 (invoker.debug != []) {
non_sdk_deps += [ ":$library-meta" ]
file_list = "$target_out_dir/$library.debug.manifest"
}
files = []
foreach(file, library_headers) {
files += [
{
source = file
dest = "$pkg/include/" + rebase_path(file, include[0])
},
]
}
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",
]
}
}
}