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