blob: d13af2ef189f4ce5ef5006dbf5dea85ad0162cb8 [file] [log] [blame]
# Copyright 2019 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
# This file provides GN build integration for Go. These templates are limited,
# supporting only legacy GOPATH-based builds.
import("exec.gni")
import("input_group.gni")
# Defines a Go package.
#
# A Go package consists of one or more Go files in a single directory. The
# package can depend on other Go packages or generated Go code.
#
# Args:
# sources: List of Go source files.
# deps: Optional list of target dependencies.
# external_deps: Optional list of Go package dependencies outside of Pigweed.
# gopath: Root of the GOPATH in which the package is located.
#
# Example:
#
# # In //my_module/go/src/example.com/foo/BUILD.gn
# pw_go_package("foo_package") {
# sources = [ "main.go" ]
# deps = [
# "//my_module:foo_proto_go"
# ]
# external_deps = [
# "github.com/golang/glog"
# ]
# gopath = "//my_module/go"
# }
#
template("pw_go_package") {
assert(defined(invoker.sources), "pw_go_source_set requires sources")
assert(defined(invoker.gopath), "pw_go_source_set requires a GOPATH root")
_gopath = rebase_path(invoker.gopath)
# List the sources in an input group with GOPATH environment metadata.
pw_input_group(target_name) {
inputs = invoker.sources
forward_variables_from(invoker,
[
"deps",
"metadata",
])
if (!defined(metadata)) {
metadata = {
}
}
metadata.gopath = [ "GOPATH+=${_gopath}" ]
if (defined(invoker.external_deps)) {
metadata.external_deps = invoker.external_deps
}
}
}
# Builds a Go executable from a Go package.
#
# The package must include only a main.go file labelled "package main". It may
# depend on other Go packages defined in the build.
#
# Args:
# deps: List of size one specifying the GN path to the Go package target.
# package: Name of the Go package as resolved by the Go compiler.
#
# Example:
#
# # In //my_module/go
# pw_go_executable("foo") {
# deps = [ "//my_module/go/src/example.com/foo:foo_package" ]
# package = "example.com/foo"
# }
#
template("pw_go_executable") {
assert(defined(invoker.deps),
"pw_go_executable requires at least one Go package as a dependency")
assert(defined(invoker.package),
"pw_go_executable requires the name of the package to build")
_metadata_target_name = "${target_name}_pw_go_metadata"
_metadata_file = "$target_gen_dir/${target_name}_pw_go_env.env"
# Collect all the GOPATH metadata from pw_go_package and _pw_go_proto_library
# targets into a plaintext file of environment variable definitions.
generated_file(_metadata_target_name) {
deps = invoker.deps
data_keys = [ "gopath" ]
outputs = [ _metadata_file ]
}
# Collect all of the external dependencies of the executable and its packages.
_deps_metadata_target_name = "${target_name}_pw_go_deps"
_deps_metadata_file = "$target_gen_dir/${target_name}_pw_go_deps.txt"
generated_file(_deps_metadata_target_name) {
deps = invoker.deps
data_keys = [ "external_deps" ]
outputs = [ _deps_metadata_file ]
}
_default_gopath = rebase_path("$root_gen_dir/go")
# Create a target to download all external dependencies into the default
# GOPATH in the out directory. This is only run once; "go get" does not
# re-download existing packages.
_download_target_name = "${target_name}_pw_go_get"
pw_exec(_download_target_name) {
program = "go"
args = [ "get" ]
deps = [ ":$_deps_metadata_target_name" ] + invoker.deps
env = [
"GO111MODULE=off",
"GOPATH=$_default_gopath",
]
if (host_os == "mac") {
# TODO(frolv): Some versions of Go for MacOS have issues finding the C
# stdlib headers. Temporarily disable CGo on Mac. The root cause of this
# issue should be investigated and fixed.
env += [ "CGO_ENABLED=0" ]
}
args_file = _deps_metadata_file
# If the args file is empty, don't run the "go get" command.
skip_empty_args = true
# Limit download parallelization to 1.
pool = "$dir_pw_build/pool:go_download($default_toolchain)"
}
# Run a "go build" command with the environment configured from metadata.
pw_exec(target_name) {
program = "go"
args = [
"build",
"-o",
rebase_path(target_out_dir, root_build_dir),
invoker.package,
]
deps = [
":$_download_target_name",
":$_metadata_target_name",
]
env = [
"GO111MODULE=off",
"GOPATH+=$_default_gopath",
]
if (host_os == "mac") {
# TODO(frolv): Some versions of Go for MacOS have issues finding the C
# stdlib headers. Temporarily disable CGo on Mac. The root cause of this
# issue should be investigated and fixed.
env += [ "CGO_ENABLED=0" ]
}
env_file = _metadata_file
_binary_name = get_path_info(invoker.package, "name")
if (host_os == "win") {
_extension = ".exe"
} else {
_extension = ""
}
outputs = [ "$target_out_dir/$_binary_name$_extension" ]
}
}