| # Copyright 2015-2018 The Chromium OS Authors. All rights reserved. |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| # @ECLASS: cros-go.eclass |
| # @MAINTAINER: |
| # The Chromium OS Authors <chromium-os-dev@chromium.org> |
| # @BUGREPORTS: |
| # Please report bugs via https://crbug.com/new (with component "Tools>ChromeOS-Toolchain") |
| # @VCSURL: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/eclass/@ECLASS@ |
| # @BLURB: Eclass for fetching, building, and installing Go packages. |
| # @DESCRIPTION: |
| # See http://www.chromium.org/chromium-os/developer-guide/go-in-chromium-os for details. |
| |
| # @ECLASS-VARIABLE: CROS_GO_SOURCE |
| # @PRE_INHERIT |
| # @DESCRIPTION: |
| # Path to the upstream repository and commit id. |
| # Go repositories on "github.com" and "*.googlesource.com" are supported. |
| # The source string contains the path of the git repository containing Go |
| # packages, and a commit-id (or version tag). |
| # For example: |
| # CROS_GO_SOURCE="github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed" |
| # will fetch the sources from https://github.com/golang/glog at the |
| # specified commit-id, and |
| # CROS_GO_SOURCE="github.com/pkg/errors v0.8.0" |
| # will fetch the sources from https://github.com/pkg/errors at version |
| # v0.8.0. |
| # By default, the import path for Go packages in the repository is the |
| # same as repository path. This can be overridden by appending a colon |
| # to the repository path, followed by an alternate import path. |
| # For example: |
| # CROS_GO_SOURCE="github.com/go-yaml/yaml:gopkg.in/yaml.v2 v2.2.1" |
| # will fetch the sources from https://github.com/go-yaml/yaml at version |
| # v2.2.1, and install the package under "gopkg.in/yaml.v2". |
| # CROS_GO_SOURCE can contain multiple items when defined as an array: |
| # CROS_GO_SOURCE=( |
| # "github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed" |
| # "github.com/pkg/errors v0.8.0" |
| # "github.com/go-yaml/yaml:gopkg.in/yaml.v2 v2.2.1" |
| # ) |
| |
| # @ECLASS-VARIABLE: CROS_GO_WORKSPACE |
| # @DESCRIPTION: |
| # Path to the Go workspace, default is ${S}. |
| # The Go workspace is searched for packages to build and install. |
| # If all Go packages in a repository are located under "go/src/": |
| # CROS_GO_WORKSPACE="${S}/go" |
| # CROS_GO_WORKSPACE can contain multiple items when defined as an array: |
| # CROS_GO_WORKSPACE=( |
| # "${S}" |
| # "${S}/tast-base" |
| # ) |
| |
| # @ECLASS-VARIABLE: CROS_GO_BINARIES |
| # @DESCRIPTION: |
| # Go executable binaries to build and install. |
| # Each path must contain a package "main". The last component |
| # of the package path will become the name of the executable. |
| # The executable name can be overridden by appending a colon |
| # to the package path, followed by an alternate name. |
| # The install path for an executable can be overridden by |
| # appending a colon to the package path, followed by the |
| # desired install path/name for it. |
| # For example: |
| # CROS_GO_BINARIES=( |
| # "golang.org/x/tools/cmd/godoc" |
| # "golang.org/x/tools/cmd/guru:goguru" |
| # "golang.org/x/tools/cmd/stringer:/usr/local/bin/gostringer" |
| # ) |
| # will build and install "godoc", "goguru", and "gostringer" binaries. |
| |
| # @ECLASS-VARIABLE: CROS_GO_VERSION |
| # @DESCRIPTION: |
| # Version string to embed in the executable binary. |
| # The variable main.Version is set to this value at build time. |
| # For example: |
| # CROS_GO_VERSION="${PVR}" |
| # will set main.Version string variable to package version and |
| # revision (if any) of the ebuild. |
| |
| # @ECLASS-VARIABLE: CROS_GO_PACKAGES |
| # @DESCRIPTION: |
| # Go packages to install in /usr/lib/gopath. |
| # Packages are installed in /usr/lib/gopath such that they |
| # can be imported later from Go code using the exact paths |
| # listed here. For example: |
| # CROS_GO_PACKAGES=( |
| # "github.com/golang/glog" |
| # ) |
| # will install package files to |
| # "/usr/lib/gopath/src/github.com/golang/glog" |
| # and other Go projects can use the package with |
| # import "github.com/golang/glog" |
| # If the last component of a package path is "...", it is |
| # expanded to include all Go packages under the directory. |
| |
| # @ECLASS-VARIABLE: CROS_GO_TEST |
| # @DESCRIPTION: |
| # Go packages to test. |
| # Package tests are run with "-short" flag by default. |
| # Package tests are always built and run locally on host. |
| # Default is to test all packages in CROS_GO_WORKSPACE(s). |
| : ${CROS_GO_TEST:=./...} |
| |
| inherit toolchain-funcs |
| |
| DEPEND="dev-lang/go" |
| |
| # @FUNCTION: cros-go_get |
| # @USAGE: <source> [variables to extract] |
| # @INTERNAL |
| # @DESCRIPTION: |
| # Parse source string and extract different components. |
| # This function parses the string containing upstream |
| # repository, import path, and commit id information |
| # (see description of CROS_GO_SOURCE format above). |
| # It can also be used to construct the name of the |
| # distfile and a uri for fetching it. |
| cros-go_get() { |
| local src commit repopath importpath distfile uri |
| src="$1" |
| commit="${src##* }" |
| repopath="${src%% *}" |
| importpath="${repopath#*:}" |
| repopath="${repopath%:*}" |
| distfile="${repopath//\//-}-${commit}.tar.gz" |
| uri="https://${repopath}/${commit}.tar.gz" |
| case "${repopath%%/*}" in |
| github.com) |
| uri="https://${repopath}/archive/${commit}.tar.gz" ;; |
| *.googlesource.com) |
| uri="https://${repopath}/+archive/${commit}.tar.gz" ;; |
| *) |
| die "Unsupported upstream source in ${repopath}" ;; |
| esac |
| |
| shift |
| local arg |
| for arg in "$@" ; do |
| case "${arg}" in |
| commit) printf "%s" "${commit}" ;; |
| repopath) printf "%s" "${repopath}" ;; |
| importpath) printf "%s" "${importpath}" ;; |
| distfile) printf "%s" "${distfile}" ;; |
| uri) printf "%s" "${uri}" ;; |
| *) printf "${arg}" ;; |
| esac |
| done |
| } |
| |
| # @FUNCTION: cros-go_src_uri |
| # @RETURN: a valid SRC_URI for CROS_GO_SOURCE |
| # @DESCRIPTION: |
| # Set the SRC_URI in an ebuild with: |
| # SRC_URI="$(cros-go_src_uri)" |
| cros-go_src_uri() { |
| local src |
| for src in "${CROS_GO_SOURCE[@]}" ; do |
| cros-go_get "${src}" uri " -> " distfile "\n" |
| done |
| } |
| |
| # @FUNCTION: cros-go_pkg_nofetch |
| # @DESCRIPTION: |
| # Print useful information on how to download a source tarball and |
| # add it to chromeos-localmirror. |
| cros-go_pkg_nofetch() { |
| local src |
| for src in "${CROS_GO_SOURCE[@]}" ; do |
| local uri="$(cros-go_get "${src}" uri)" |
| local distfile="$(cros-go_get "${src}" distfile)" |
| einfo "Run these commands to add ${distfile} to chromeos-localmirror:" |
| einfo " wget -O ${distfile} ${uri}" |
| einfo " gsutil cp -a public-read ${distfile} gs://chromeos-localmirror/distfiles/" |
| einfo |
| done |
| einfo "After all distfiles have been mirrored, update the 'Manifest' file with:" |
| einfo " ebuild ${EBUILD} manifest" |
| } |
| |
| # @FUNCTION: cros-go_src_unpack |
| # @DESCRIPTION: |
| # Unpack the source tarball under appropriate location based on |
| # the desired import path. |
| cros-go_src_unpack() { |
| local src |
| for src in "${CROS_GO_SOURCE[@]}" ; do |
| local commit="$(cros-go_get "${src}" commit)" |
| local repopath="$(cros-go_get "${src}" repopath)" |
| local importpath="$(cros-go_get "${src}" importpath)" |
| local distfile="$(cros-go_get "${src}" distfile)" |
| |
| local destdir="${S}/src/${importpath}" |
| case "${repopath%%/*}" in |
| github.com) |
| # Unpacking tarballs from github creates a top level |
| # directory "projectname-version", so extra logic is |
| # required to make the contents appear correctly in |
| # the desired destination directory. |
| mkdir -p "${destdir%/*}" || die |
| pushd "${destdir%/*}" >/dev/null || die |
| unpack "${distfile}" |
| mv "${repopath##*/}-${commit#v}" "${importpath##*/}" || die |
| popd >/dev/null || die |
| ;; |
| *.googlesource.com) |
| mkdir -p "${destdir}" || die |
| pushd "${destdir}" >/dev/null || die |
| unpack "${distfile}" |
| popd >/dev/null || die |
| ;; |
| esac |
| done |
| } |
| |
| # @FUNCTION: cros-go_workspace |
| # @RETURN: Go workspaces, colon separated |
| # @INTERNAL |
| # @DESCRIPTION: |
| # Return the list of workspaces in CROS_GO_WORKSPACE, |
| # properly formatted for inclusion into GOPATH. |
| cros-go_workspace() { |
| if [[ ${#CROS_GO_WORKSPACE[@]} != 0 ]] ; then |
| ( IFS=:; echo "${CROS_GO_WORKSPACE[*]}" ) |
| else |
| echo "${S}" |
| fi |
| } |
| |
| # @FUNCTION: cros-go_gopath |
| # @RETURN: a valid GOPATH for CROS_GO_WORKSPACE |
| # @DESCRIPTION: |
| # Set the GOPATH in an ebuild with: |
| # GOPATH="$(cros-go_gopath)" |
| cros-go_gopath() { |
| echo "$(cros-go_workspace):${SYSROOT}/usr/lib/gopath" |
| } |
| |
| # @FUNCTION: cros_go |
| # @DESCRIPTION: |
| # Wrapper function for invoking the Go tool from an ebuild. |
| # Sets up GOPATH, and uses the appropriate cross-compiler. |
| cros_go() { |
| GOPATH="$(cros-go_gopath)" $(tc-getGO) "$@" || die |
| } |
| |
| # @FUNCTION: go_list |
| # @DESCRIPTION: |
| # List all Go packages matching a pattern. Only looks up |
| # package names in the current workspace (does not match |
| # packages installed under /usr/lib/gopath). |
| go_list() { |
| GOPATH="$(cros-go_workspace)" $(tc-getGO) list "$@" || die |
| } |
| |
| # @FUNCTION: go_test |
| # @DESCRIPTION: |
| # Wrapper function for building and running unit tests. |
| # Package tests are always built and run locally on host. |
| go_test() { |
| GOPATH="$(cros-go_gopath)" $(tc-getBUILD_GO) test "$@" || die |
| } |
| |
| # @FUNCTION: cros-go_src_compile |
| # @DESCRIPTION: |
| # Build CROS_GO_BINARIES. |
| cros-go_src_compile() { |
| local bin |
| for bin in "${CROS_GO_BINARIES[@]}" ; do |
| einfo "Building \"${bin}\"" |
| local path="${bin#*:}" |
| local name="${path##*/}" |
| bin="${bin%:*}" |
| cros_go build -v \ |
| ${CROS_GO_VERSION:+"-ldflags=-X main.Version=${CROS_GO_VERSION}"} \ |
| -o "${name}" \ |
| "${bin}" |
| done |
| } |
| |
| # @FUNCTION: cros-go_src_test |
| # @DESCRIPTION: |
| # Run tests for packages listed in CROS_GO_TEST. |
| cros-go_src_test() { |
| local pkglist=( $(go_list "${CROS_GO_TEST[@]}") ) |
| go_test -short "${pkglist[@]}" |
| } |
| |
| # @FUNCTION: cros-go_src_install |
| # @DESCRIPTION: |
| # Install CROS_GO_BINARIES and CROS_GO_PACKAGES. |
| cros-go_src_install() { |
| # Install the compiled binaries. |
| local bin |
| for bin in "${CROS_GO_BINARIES[@]}" ; do |
| einfo "Installing \"${bin}\"" |
| local path="${bin#*:}" |
| local name="${path##*/}" |
| if [[ "${bin}" == *:*/* ]] ; then |
| path="${path%/*}" |
| else |
| path="/usr/bin" |
| fi |
| ( |
| # Run in sub-shell so we do not modify env. |
| exeinto "${path}" |
| doexe "${name}" |
| ) |
| done |
| |
| # Install the importable packages in /usr/lib/gopath. |
| local pkglist=() |
| if [[ ${#CROS_GO_PACKAGES[@]} != 0 ]] ; then |
| pkglist=( $(go_list "${CROS_GO_PACKAGES[@]}") ) |
| fi |
| local pkg |
| for pkg in "${pkglist[@]}" ; do |
| einfo "Installing \"${pkg}\"" |
| local pkgdir="$(go_list -f "{{.Dir}}" "${pkg}")" |
| ( |
| # Run in sub-shell so we do not modify env. |
| insinto "/usr/lib/gopath/src/${pkg}" |
| local file |
| while read -d $'\0' -r file ; do |
| doins "${file}" |
| done < <(find "${pkgdir}" -maxdepth 1 ! -type d -print0) |
| ) |
| done |
| |
| # TODO(crbug.com/811542,crbug.com/749300): Disable as workaround for bug. |
| # # Check for missing dependencies of installed packages. |
| # local CROS_GO_WORKSPACE="${D}/usr/lib/gopath" |
| # for pkg in "${pkglist[@]}" ; do |
| # if [[ $(cros_go list -f "{{.Incomplete}}" "${pkg}") == "true" ]] ; then |
| # cros_go list -f "{{.DepsErrors}}" "${pkg}" |
| # die "Package has missing dependency: \"${pkg}\"" |
| # fi |
| # done |
| } |
| |
| if [[ ${#CROS_GO_SOURCE[@]} != 0 ]] ; then |
| EXPORT_FUNCTIONS pkg_nofetch src_unpack |
| fi |
| |
| EXPORT_FUNCTIONS src_compile src_test src_install |