third_party.pigweed.src/pw_build/go.gni
Michael Spang da057f7f3c pw_build: Remove instancing of pools across toolchains
The build system uses pools for mutual exclusion. Currently multiple
instances of these pools exist which defeats their purpose.

For example, it can cause concurrent instances of "pip install" which is
not safe.

Bug: 390
No-Docs-Update-Reason: bug fix
Change-Id: I114d2428d747a6d5a68a024a0177343ee82cad76
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/48520
Commit-Queue: Michael Spang <spang@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
2021-06-10 05:57:15 +00:00

184 lines
5.5 KiB
Plaintext

# 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" ]
}
}