blob: 03799f5306d98f3c40eccce82c9e2ec4af76aa9f [file] [log] [blame]
# 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/config/clang/clang.gni")
import("//build/config/sysroot.gni")
import("//build/host.gni")
declare_args() {
# gocache_dir
# Directory GOCACHE environment variable will be set to. This directory
# will have build and test results cached, and is safe to be written to
# concurrently. If overridden, this directory must be a full path.
gocache_dir = rebase_path("$root_out_dir/.gocache")
# go_vet_enabled
# [bool] if false, go vet invocations are disabled for all builds.
go_vet_enabled = false
}
# A template for an action that builds a Go binary. Users should instead use the
# go_binary or go_test rules.
#
# Parameters
#
# gopackages (optional)
# List of packages to build. Exactly one of gopackages or library must be
# set.
#
# library (optional)
# Alternative to gopackages, a library GN label corresponding to the
# package to build.
#
# deps (optional)
# List of labels representing go_library targets this target depends on.
#
# non_go_deps (optional)
# List of labels this target depends on that are not Go libraries.
#
# skip_vet (optional)
# Whether to skip running go vet for this target. This flag should _only_
# be used for packages in the Go source tree itself that otherwise match
# whitelist entries in go vet all. Go vet is only run if go_vet_enabled is
# true.
#
# test (optional, default: false)
# Whether this target defines a test.
#
template("go_build") {
forward_variables_from(invoker, [ "visibility" ])
main_target_name = target_name
output_name = target_name
if (defined(invoker.output_name)) {
output_name = invoker.output_name
}
output_path = "${root_out_dir}/${output_name}"
use_strip = is_fuchsia
if (use_strip) {
unstripped_output_path = "${root_out_dir}/exe.unstripped/${output_name}"
}
action(main_target_name) {
deps = []
if (defined(invoker.non_go_deps)) {
deps += invoker.non_go_deps
}
go_deps = []
if (defined(invoker.deps)) {
go_deps += invoker.deps
}
if (defined(invoker.library)) {
# It's redundant to include the `library` label in `deps` because we'll add
# it implicitly.
assert(go_deps + [ invoker.library ] - [ invoker.library ] == go_deps,
"library should not be listed in deps")
go_deps += [ invoker.library ]
}
args = []
# TODO(https://fxbug.dev/42136747): Delete `gopackages` in favor of `library`.
if (defined(invoker.gopackages) == defined(invoker.library)) {
assert(false, "Exactly one of gopackages or library must be set")
} else if (defined(invoker.gopackages)) {
gopackages = invoker.gopackages
# Multi-package support was never implemented and is no longer planned as
# `gopackages` is slated for deletion as part of https://fxbug.dev/42136747.
assert(gopackages == [ gopackages[0] ],
"gopackages only supports one package")
foreach(gopackage, gopackages) {
args += [
"--package",
gopackage,
]
}
} else if (defined(invoker.library)) {
_gen_dir = get_label_info(invoker.library, "target_gen_dir")
_name = get_label_info(invoker.library, "name")
args += [
"--library-metadata",
rebase_path("${_gen_dir}/${_name}.go_deps", root_build_dir),
]
}
pool = "//build/go:pool($default_toolchain)"
outputs = [ output_path ]
if (use_strip) {
outputs += [ unstripped_output_path ]
}
script = "//build/go/build.py"
depfile = "${output_path}.d"
sources = [ "//build/go/gen_library_metadata.py" ]
godepfile = "//sysroot/golang/bin/godepfile"
inputs = [ godepfile ]
args += [
"--godepfile",
rebase_path(godepfile, "", root_build_dir),
"--root-out-dir",
rebase_path(root_out_dir, root_build_dir),
"--depfile",
rebase_path(depfile),
"--current-cpu",
current_cpu,
"--current-os",
current_os,
"--binname",
output_name,
"--go-cache",
gocache_dir,
"--cc",
rebase_path("$clang_prefix/clang", "", root_build_dir),
"--cxx",
rebase_path("$clang_prefix/clang++", "", root_build_dir),
"--objcopy",
rebase_path("$clang_prefix/llvm-objcopy", "", root_build_dir),
"--sysroot",
sysroot,
"--target",
clang_target,
]
if (defined(invoker.skip_vet) && !invoker.skip_vet && go_vet_enabled) {
args += [ "--vet" ]
}
if (is_fuchsia) {
deps += [
"//sdk/lib/fdio",
"//third_party/go:go_runtime",
]
args += [
# GN provides no way to propagate include paths like this, so, this
# is brittle.
"--include-dir",
rebase_path("//sdk/lib/fdio/include"),
"--include-dir",
rebase_path("//zircon/third_party/ulib/musl/include"),
"--include-dir",
rebase_path("//zircon/system/public"),
"--include-dir",
rebase_path("//zircon/system/ulib/zircon/include"),
"--go-root",
rebase_path("$host_tools_dir/goroot"),
]
foreach(target, zircon_legacy_targets) {
if (target.target_name == "zircon") {
_libs = target.libs
lib = _libs[0]
assert(_libs == [ lib ])
_libs = []
args += [
"--lib-dir",
rebase_path(get_path_info("$zircon_root_build_dir/$lib", "dir")),
]
}
}
# See //build/config/fuchsia:fdio_config.
args += [
"--lib-dir",
rebase_path(get_label_info("//build/config/fuchsia:fdio_config",
"target_gen_dir")),
]
} else {
args += [
"--go-root",
rebase_path("//sysroot/golang/"),
]
}
if (use_strip) {
args += [
"--unstripped-binname",
rebase_path("${root_out_dir}/exe.unstripped/${output_name}",
root_build_dir),
]
}
# Add needed arguments for the buildidtool. We should add the stamp file
# output by buildidtool to the list of outputs for this action but because
# Ninja (and by consequence GN) limits us to one depfile where that depfile
# has only one output and we need the depfile for other things we don't
# list it as an output.
args += [
"--buildidtool",
rebase_path("//sysroot/bin/buildidtool", root_build_dir),
"--build-id-dir",
".build-id",
]
if (defined(invoker.test) && invoker.test) {
testonly = true
args += [ "--is-test=true" ]
}
if (go_deps != []) {
deps += go_deps
args += [ "--go-dep-files" ]
foreach(dep, go_deps) {
gen_dir = get_label_info(dep, "target_gen_dir")
name = get_label_info(dep, "name")
args += [ rebase_path("$gen_dir/$name.go_deps") ]
}
}
}
}