diff --git a/lang/golang/golang-build.sh b/lang/golang/golang-build.sh new file mode 100644 index 000000000..5e40436bb --- /dev/null +++ b/lang/golang/golang-build.sh @@ -0,0 +1,204 @@ +#!/bin/sh + +nl=" +" + +log() { + # shellcheck disable=SC2039 + local IFS=" " + printf '%s\n' "$*" +} + +log_error() { + # shellcheck disable=SC2039 + local IFS=" " + printf 'Error: %s\n' "$*" >&2 +} + +link_contents() { + # shellcheck disable=SC2039 + local src="$1" dest="$2" IFS="$nl" dirs dir base + + if [ -n "$(find "$src" -mindepth 1 -maxdepth 1 -name "*.go" -not -type d)" ]; then + log_error "$src is already a Go library" + return 1 + fi + + dirs="$(find "$src" -mindepth 1 -maxdepth 1 -type d)" + for dir in $dirs; do + base="${dir##*/}" + if [ -d "$dest/$base" ]; then + case "$dir" in + *$GO_BUILD_DEPENDS_SRC/$GO_PKG) + log "$GO_PKG is already installed. Please check for circular dependencies." + ;; + *) + link_contents "$src/$base" "$dest/$base" + ;; + esac + else + log "...${src#$GO_BUILD_DEPENDS_SRC}/$base" + ln -sf "$src/$base" "$dest/$base" + fi + done + + return 0 +} + +configure() { + # shellcheck disable=SC2039 + local files code testdata gomod pattern extra IFS file dest + + cd "$BUILD_DIR" || return 1 + + files="$(find ./ -path "*/.*" -prune -o -not -type d -print)" + + if [ "$GO_INSTALL_ALL" != 1 ]; then + code="$(printf '%s\n' "$files" | grep '\.\(c\|cc\|cpp\|go\|h\|hh\|hpp\|proto\|s\)$')" + testdata="$(printf '%s\n' "$files" | grep '/testdata/')" + gomod="$(printf '%s\n' "$files" | grep '/go\.\(mod\|sum\)$')" + + for pattern in $GO_INSTALL_EXTRA; do + extra="$(printf '%s\n' "$extra"; printf '%s\n' "$files" | grep -e "$pattern")" + done + + files="$(printf '%s\n%s\n%s\n%s\n' "$code" "$testdata" "$gomod" "$extra" | grep -v '^[[:space:]]*$' | sort -u)" + fi + + IFS="$nl" + + log "Copying files from $BUILD_DIR into $GO_BUILD_DIR/src/$GO_PKG" + mkdir -p "$GO_BUILD_DIR/src" + for file in $files; do + log "${file#./}" + dest="$GO_BUILD_DIR/src/$GO_PKG/${file#./}" + mkdir -p "${dest%/*}" + cp -fpR "$file" "$dest" + done + log + + if [ "$GO_SOURCE_ONLY" != 1 ]; then + if [ -d "$GO_BUILD_DEPENDS_SRC" ]; then + log "Symlinking directories from $GO_BUILD_DEPENDS_SRC into $GO_BUILD_DIR/src" + link_contents "$GO_BUILD_DEPENDS_SRC" "$GO_BUILD_DIR/src" + else + log "$GO_BUILD_DEPENDS_SRC does not exist, skipping symlinks" + fi + else + log "Not building binaries, skipping symlinks" + fi + log + + return 0 +} + +build() { + # shellcheck disable=SC2039 + local modargs pattern targets retval + + cd "$GO_BUILD_DIR" || return 1 + + if [ -f "$BUILD_DIR/go.mod" ] ; then + mkdir -p "$GO_MOD_CACHE_DIR" + modargs="$GO_MOD_ARGS" + fi + + log "Finding targets" + # shellcheck disable=SC2086 + targets="$(go list $modargs $GO_BUILD_PKG)" + for pattern in $GO_EXCLUDES; do + targets="$(printf '%s\n' "$targets" | grep -v "$pattern")" + done + log + + if [ "$GO_GO_GENERATE" = 1 ]; then + log "Calling go generate" + # shellcheck disable=SC2086 + GOOS='' GOARCH='' GO386='' GOARM='' GOMIPS='' GOMIPS64='' \ + go generate -v $targets + log + fi + + if [ "$GO_SOURCE_ONLY" = 1 ]; then + return 0 + fi + + log "Building targets" + mkdir -p "$GO_BUILD_DIR/bin" "$GO_BUILD_CACHE_DIR" + # shellcheck disable=SC2086 + go install $modargs "$@" $targets + retval="$?" + log + + if [ "$retval" -eq 0 ] && [ -z "$(find "$GO_BUILD_BIN_DIR" -maxdepth 0 -type d -not -empty 2>/dev/null)" ]; then + log_error "No binaries were built" + retval=1 + fi + + if [ "$retval" -ne 0 ]; then + cache_cleanup + fi + + return "$retval" +} + +install_bin() { + # shellcheck disable=SC2039 + local dest="$1" + install -d -m0755 "$dest/$GO_INSTALL_BIN_PATH" + install -m0755 "$GO_BUILD_BIN_DIR"/* "$dest/$GO_INSTALL_BIN_PATH/" +} + +install_src() { + # shellcheck disable=SC2039 + local dest="$1" dir="${GO_PKG%/*}" + install -d -m0755 "$dest/$GO_BUILD_DEPENDS_PATH/src/$dir" + cp -fpR "$GO_BUILD_DIR/src/$GO_PKG" "$dest/$GO_BUILD_DEPENDS_PATH/src/$dir/" +} + +cache_cleanup() { + if ! [ -d "$GO_MOD_CACHE_DIR" ]; then + return 0 + fi + + # in case go is called without -modcacherw + find "$GO_MOD_CACHE_DIR" -type d -not -perm -u+w -exec chmod u+w '{}' + + + if [ -n "$CONFIG_GOLANG_MOD_CACHE_WORLD_READABLE" ]; then + find "$GO_MOD_CACHE_DIR" -type d -not -perm -go+rx -exec chmod go+rx '{}' + + find "$GO_MOD_CACHE_DIR" -not -type d -not -perm -go+r -exec chmod go+r '{}' + + fi + + return 0 +} + + +if [ "$#" -lt 1 ]; then + log_error "Missing command" + exit 1 +fi + +command="$1" +shift 1 + +case "$command" in + configure) + configure + ;; + build) + build "$@" + ;; + install_bin) + install_bin "$@" + ;; + install_src) + install_src "$@" + ;; + cache_cleanup) + cache_cleanup + ;; + *) + log_error "Invalid command \"$command\"" + exit 1 + ;; +esac diff --git a/lang/golang/golang-compiler.mk b/lang/golang/golang-compiler.mk index cf350d82c..e8b4b9156 100644 --- a/lang/golang/golang-compiler.mk +++ b/lang/golang/golang-compiler.mk @@ -24,8 +24,8 @@ endef # $(4) additional environment variables (optional) define GoCompiler/Default/Make ( \ - cd $(1)/src ; \ - $(if $(2),GOROOT_FINAL=$(2)/lib/go-$(3)) \ + cd "$(1)/src" ; \ + $(if $(2),GOROOT_FINAL="$(2)/lib/go-$(3)") \ $(4) \ $(BASH) make.bash --no-banner ; \ ) @@ -34,8 +34,8 @@ endef # $(1) destination prefix # $(2) go version id define GoCompiler/Default/Install/make-dirs - $(INSTALL_DIR) $(1)/lib/go-$(2) - $(INSTALL_DIR) $(1)/share/go-$(2) + $(INSTALL_DIR) "$(1)/lib/go-$(2)" + $(INSTALL_DIR) "$(1)/share/go-$(2)" endef # $(1) source go root @@ -43,8 +43,8 @@ endef # $(3) go version id # $(4) file/directory name define GoCompiler/Default/Install/install-share-data - $(CP) $(1)/$(4) $(2)/share/go-$(3)/ - $(LN) ../../share/go-$(3)/$(4) $(2)/lib/go-$(3)/ + $(CP) "$(1)/$(4)" "$(2)/share/go-$(3)/" + $(LN) "../../share/go-$(3)/$(4)" "$(2)/lib/go-$(3)/" endef # $(1) source go root @@ -57,35 +57,35 @@ define GoCompiler/Default/Install/Bin $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),api) - $(INSTALL_DATA) -p $(1)/VERSION $(2)/lib/go-$(3)/ + $(INSTALL_DATA) -p "$(1)/VERSION" "$(2)/lib/go-$(3)/" for file in AUTHORS CONTRIBUTING.md CONTRIBUTORS LICENSE PATENTS README.md SECURITY.md; do \ - if [ -f $(1)/$$$$file ]; then \ - $(INSTALL_DATA) -p $(1)/$$$$file $(2)/share/go-$(3)/ ; \ + if [ -f "$(1)/$$$$file" ]; then \ + $(INSTALL_DATA) -p "$(1)/$$$$file" "$(2)/share/go-$(3)/" ; \ fi ; \ done - $(INSTALL_DIR) $(2)/lib/go-$(3)/bin + $(INSTALL_DIR) "$(2)/lib/go-$(3)/bin" ifeq ($(4),$(GO_HOST_OS_ARCH)) - $(INSTALL_BIN) -p $(1)/bin/* $(2)/lib/go-$(3)/bin/ + $(INSTALL_BIN) -p "$(1)/bin"/* "$(2)/lib/go-$(3)/bin/" else - $(INSTALL_BIN) -p $(1)/bin/$(4)/* $(2)/lib/go-$(3)/bin/ + $(INSTALL_BIN) -p "$(1)/bin/$(4)"/* "$(2)/lib/go-$(3)/bin/" endif - $(INSTALL_DIR) $(2)/lib/go-$(3)/pkg - $(CP) $(1)/pkg/$(4)$(if $(5),_$(5)) $(2)/lib/go-$(3)/pkg/ + $(INSTALL_DIR) "$(2)/lib/go-$(3)/pkg" + $(CP) "$(1)/pkg/$(4)$(if $(5),_$(5))" "$(2)/lib/go-$(3)/pkg/" - $(INSTALL_DIR) $(2)/lib/go-$(3)/pkg/tool/$(4) - $(INSTALL_BIN) -p $(1)/pkg/tool/$(4)/* $(2)/lib/go-$(3)/pkg/tool/$(4)/ + $(INSTALL_DIR) "$(2)/lib/go-$(3)/pkg/tool/$(4)" + $(INSTALL_BIN) -p "$(1)/pkg/tool/$(4)"/* "$(2)/lib/go-$(3)/pkg/tool/$(4)/" endef # $(1) destination prefix # $(2) go version id define GoCompiler/Default/Install/BinLinks - $(INSTALL_DIR) $(1)/bin - $(LN) ../lib/go-$(2)/bin/go $(1)/bin/go - $(LN) ../lib/go-$(2)/bin/gofmt $(1)/bin/gofmt + $(INSTALL_DIR) "$(1)/bin" + $(LN) "../lib/go-$(2)/bin/go" "$(1)/bin/go" + $(LN) "../lib/go-$(2)/bin/gofmt" "$(1)/bin/gofmt" endef # $(1) source go root @@ -111,29 +111,29 @@ define GoCompiler/Default/Install/Src $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),test) $(FIND) \ - $(2)/share/go-$(3)/src/ \ - \! -type d -a \( -name '*.bat' -o -name '*.rc' \) \ + "$(2)/share/go-$(3)/src/" \ + \! -type d -a \( -name "*.bat" -o -name "*.rc" \) \ -delete - if [ -d $(1)/pkg/include ]; then \ - $(INSTALL_DIR) $(2)/lib/go-$(3)/pkg ; \ - $(INSTALL_DIR) $(2)/share/go-$(3)/pkg ; \ - $(CP) $(1)/pkg/include $(2)/share/go-$(3)/pkg/ ; \ - $(LN) ../../../share/go-$(3)/pkg/include $(2)/lib/go-$(3)/pkg/ ; \ + if [ -d "$(1)/pkg/include" ]; then \ + $(INSTALL_DIR) "$(2)/lib/go-$(3)/pkg" ; \ + $(INSTALL_DIR) "$(2)/share/go-$(3)/pkg" ; \ + $(CP) "$(1)/pkg/include" "$(2)/share/go-$(3)/pkg/" ; \ + $(LN) "../../../share/go-$(3)/pkg/include" "$(2)/lib/go-$(3)/pkg/" ; \ fi endef # $(1) destination prefix # $(2) go version id define GoCompiler/Default/Uninstall - rm -rf $(1)/lib/go-$(2) - rm -rf $(1)/share/go-$(2) + rm -rf "$(1)/lib/go-$(2)" + rm -rf "$(1)/share/go-$(2)" endef # $(1) destination prefix define GoCompiler/Default/Uninstall/BinLinks - rm -f $(1)/bin/go - rm -f $(1)/bin/gofmt + rm -f "$(1)/bin/go" + rm -f "$(1)/bin/gofmt" endef diff --git a/lang/golang/golang-host-build.mk b/lang/golang/golang-host-build.mk new file mode 100644 index 000000000..ee4f1ea31 --- /dev/null +++ b/lang/golang/golang-host-build.mk @@ -0,0 +1,220 @@ +# +# Copyright (C) 2020 Jeffery To +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +ifeq ($(origin GO_INCLUDE_DIR),undefined) + GO_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST))) +endif + +include $(GO_INCLUDE_DIR)/golang-values.mk + + +# these variables have the same meanings as in golang-package.mk +GO_HOST_INSTALL_EXTRA?=$(GO_PKG_INSTALL_EXTRA) +GO_HOST_INSTALL_ALL?=$(GO_PKG_INSTALL_ALL) +GO_HOST_SOURCE_ONLY?=$(GO_PKG_SOURCE_ONLY) +GO_HOST_BUILD_PKG?=$(GO_PKG_BUILD_PKG) +GO_HOST_EXCLUDES?=$(GO_PKG_EXCLUDES) +GO_HOST_GO_GENERATE?=$(GO_PKG_GO_GENERATE) +GO_HOST_GCFLAGS?=$(GO_PKG_GCFLAGS) +GO_HOST_LDFLAGS?=$(GO_PKG_LDFLAGS) +GO_HOST_LDFLAGS_X?=$(GO_PKG_LDFLAGS_X) +GO_HOST_TAGS?=$(GO_PKG_TAGS) +GO_HOST_INSTALL_BIN_PATH?=/bin + + +# need to repeat this here in case golang-package.mk is not included +GO_PKG_BUILD_PKG?=$(strip $(GO_PKG))/... + +GO_HOST_WORK_DIR_NAME:=.go_work +GO_HOST_BUILD_DIR=$(HOST_BUILD_DIR)/$(GO_HOST_WORK_DIR_NAME)/build +GO_HOST_BUILD_BIN_DIR=$(GO_HOST_BUILD_DIR)/bin + +GO_HOST_BUILD_DEPENDS_PATH:=/share/gocode +GO_HOST_BUILD_DEPENDS_SRC=$(STAGING_DIR_HOSTPKG)$(GO_HOST_BUILD_DEPENDS_PATH)/src + +GO_HOST_DIR_NAME:=$(lastword $(subst /,$(space),$(CURDIR))) +GO_HOST_STAGING_DIR:=$(TMP_DIR)/host-stage-$(GO_HOST_DIR_NAME) +GO_HOST_STAGING_FILES_LIST_DIR:=$(HOST_BUILD_PREFIX)/stamp +GO_HOST_BIN_STAGING_FILES_LIST:=$(GO_HOST_STAGING_FILES_LIST_DIR)/$(GO_HOST_DIR_NAME)-bin.list +GO_HOST_SRC_STAGING_FILES_LIST:=$(GO_HOST_STAGING_FILES_LIST_DIR)/$(GO_HOST_DIR_NAME)-src.list + +ifeq ($(GO_HOST_PIE_SUPPORTED),1) + GO_HOST_ENABLE_PIE:=1 +endif + +GO_HOST_BUILD_CONFIG_VARS= \ + GO_PKG="$(strip $(GO_PKG))" \ + GO_INSTALL_EXTRA="$(strip $(GO_HOST_INSTALL_EXTRA))" \ + GO_INSTALL_ALL="$(strip $(GO_HOST_INSTALL_ALL))" \ + GO_SOURCE_ONLY="$(strip $(GO_HOST_SOURCE_ONLY))" \ + GO_BUILD_PKG="$(strip $(GO_HOST_BUILD_PKG))" \ + GO_EXCLUDES="$(strip $(GO_HOST_EXCLUDES))" \ + GO_GO_GENERATE="$(strip $(GO_HOST_GO_GENERATE))" \ + GO_INSTALL_BIN_PATH="$(strip $(GO_HOST_INSTALL_BIN_PATH))" \ + BUILD_DIR="$(HOST_BUILD_DIR)" \ + GO_BUILD_DIR="$(GO_HOST_BUILD_DIR)" \ + GO_BUILD_BIN_DIR="$(GO_HOST_BUILD_BIN_DIR)" \ + GO_BUILD_DEPENDS_PATH="$(GO_HOST_BUILD_DEPENDS_PATH)" \ + GO_BUILD_DEPENDS_SRC="$(GO_HOST_BUILD_DEPENDS_SRC)" + +GO_HOST_MORE_CFLAGS?= \ + -Wformat -Werror=format-security \ + -fstack-protector-strong \ + -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \ + -Wl,-z,now -Wl,-z,relro \ + $(if $(GO_HOST_ENABLE_PIE),$(FPIC)) + +GO_HOST_MORE_LDFLAGS?= \ + -znow -zrelro \ + $(if $(GO_HOST_ENABLE_PIE),$(FPIC) -specs=$(INCLUDE_DIR)/hardened-ld-pie.specs) + +GO_HOST_TARGET_VARS= \ + CGO_ENABLED=1 \ + CC=gcc \ + CXX=g++ \ + PKG_CONFIG=pkg-config \ + CGO_CFLAGS="$(HOST_CFLAGS) $(GO_HOST_MORE_CFLAGS)" \ + CGO_CPPFLAGS="$(HOST_CPPFLAGS) $(GO_HOST_MORE_CPPFLAGS)" \ + CGO_CXXFLAGS="$(HOST_CFLAGS) $(GO_HOST_MORE_CFLAGS)" \ + CGO_LDFLAGS="$(HOST_LDFLAGS) $(GO_HOST_MORE_LDFLAGS)" \ + GO_GCC_HELPER_CC="$(HOSTCC)" \ + GO_GCC_HELPER_CXX="$(HOSTCXX)" \ + GO_GCC_HELPER_PATH="$$$$PATH" \ + PATH="$(STAGING_DIR_HOSTPKG)/lib/go-cross/openwrt:$$$$PATH" + +GO_HOST_BUILD_VARS= \ + GOPATH="$(GO_HOST_BUILD_DIR)" \ + GOCACHE="$(GO_BUILD_CACHE_DIR)" \ + GOMODCACHE="$(GO_MOD_CACHE_DIR)" \ + GOENV=off + +GO_HOST_VARS= \ + $(GO_HOST_TARGET_VARS) \ + $(GO_HOST_BUILD_VARS) + +GO_HOST_DEFAULT_LDFLAGS= \ + -linkmode external \ + -extldflags '$(patsubst -z%,-Wl$(comma)-z$(comma)%,$(HOST_LDFLAGS) $(GO_HOST_MORE_LDFLAGS))' + +GO_HOST_CUSTOM_LDFLAGS= \ + $(GO_HOST_LDFLAGS) \ + $(patsubst %,-X %,$(GO_HOST_LDFLAGS_X)) + +GO_HOST_INSTALL_ARGS= \ + -v \ + -ldflags "all=$(GO_HOST_DEFAULT_LDFLAGS)" \ + $(if $(filter $(GO_HOST_ENABLE_PIE),1),-buildmode pie) \ + $(if $(GO_HOST_GCFLAGS),-gcflags "$(GO_HOST_GCFLAGS)") \ + $(if $(GO_HOST_CUSTOM_LDFLAGS),-ldflags "$(GO_HOST_CUSTOM_LDFLAGS) $(GO_HOST_DEFAULT_LDFLAGS)") \ + $(if $(GO_HOST_TAGS),-tags "$(GO_HOST_TAGS)") + +define GoHost/Host/Configure + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_HOST_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh configure +endef + +# $(1) additional arguments for go command line (optional) +define GoHost/Host/Compile + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_HOST_BUILD_CONFIG_VARS) \ + $(GO_HOST_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh build $(GO_HOST_INSTALL_ARGS) $(1) +endef + +define GoHost/Host/Install/Bin + rm -rf "$(GO_HOST_STAGING_DIR)" + mkdir -p "$(GO_HOST_STAGING_DIR)" "$(GO_HOST_STAGING_FILES_LIST_DIR)" + + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_HOST_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh install_bin "$(GO_HOST_STAGING_DIR)" + + if [ -f "$(GO_HOST_BIN_STAGING_FILES_LIST)" ]; then \ + "$(SCRIPT_DIR)/clean-package.sh" \ + "$(GO_HOST_BIN_STAGING_FILES_LIST)" \ + "$(1)" ; \ + fi + + cd "$(GO_HOST_STAGING_DIR)" && find ./ > "$(GO_HOST_STAGING_DIR).files" + + $(call locked, \ + mv "$(GO_HOST_STAGING_DIR).files" "$(GO_HOST_BIN_STAGING_FILES_LIST)" && \ + $(CP) "$(GO_HOST_STAGING_DIR)"/* "$(1)/", \ + host-staging-dir \ + ) + + rm -rf "$(GO_HOST_STAGING_DIR)" +endef + +define GoHost/Host/Install/Src + rm -rf "$(GO_HOST_STAGING_DIR)" + mkdir -p "$(GO_HOST_STAGING_DIR)" "$(GO_HOST_STAGING_FILES_LIST_DIR)" + + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_HOST_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh install_src "$(GO_HOST_STAGING_DIR)" + + if [ -f "$(GO_HOST_SRC_STAGING_FILES_LIST)" ]; then \ + "$(SCRIPT_DIR)/clean-package.sh" \ + "$(GO_HOST_SRC_STAGING_FILES_LIST)" \ + "$(1)" ; \ + fi + + cd "$(GO_HOST_STAGING_DIR)" && find ./ > "$(GO_HOST_STAGING_DIR).files" + + $(call locked, \ + mv "$(GO_HOST_STAGING_DIR).files" "$(GO_HOST_SRC_STAGING_FILES_LIST)" && \ + $(CP) "$(GO_HOST_STAGING_DIR)"/* "$(1)/", \ + host-staging-dir \ + ) + + rm -rf "$(GO_HOST_STAGING_DIR)" +endef + +define GoHost/Host/Install + $(if $(filter $(GO_HOST_SOURCE_ONLY),1),, \ + $(call GoHost/Host/Install/Bin,$(1)) \ + ) + $(call GoHost/Host/Install/Src,$(1)) +endef + +define GoHost/Host/Uninstall + if [ -f "$(GO_HOST_BIN_STAGING_FILES_LIST)" ]; then \ + "$(SCRIPT_DIR)/clean-package.sh" \ + "$(GO_HOST_BIN_STAGING_FILES_LIST)" \ + "$(HOST_BUILD_PREFIX)" ; \ + rm -f "$(GO_HOST_BIN_STAGING_FILES_LIST)" ; \ + fi + + if [ -f "$(GO_HOST_SRC_STAGING_FILES_LIST)" ]; then \ + "$(SCRIPT_DIR)/clean-package.sh" \ + "$(GO_HOST_SRC_STAGING_FILES_LIST)" \ + "$(HOST_BUILD_PREFIX)" ; \ + rm -f "$(GO_HOST_SRC_STAGING_FILES_LIST)" ; \ + fi +endef + + +ifneq ($(strip $(GO_PKG)),) + Host/Configure=$(call GoHost/Host/Configure) + Host/Compile=$(call GoHost/Host/Compile) + Hooks/HostCompile/Post+=Go/CacheCleanup + Host/Uninstall=$(call GoHost/Host/Uninstall,$(1)) +endif + +define GoHostBuild + Host/Install=$$(call GoHost/Host/Install,$$(1)) +endef + +define GoBinHostBuild + Host/Install=$$(call GoHost/Host/Install/Bin,$$(1)) +endef + +define GoSrcHostBuild + Host/Install=$$(call GoHost/Host/Install/Src,$$(1)) +endef diff --git a/lang/golang/golang-package.mk b/lang/golang/golang-package.mk index 1e279797b..7144a4524 100644 --- a/lang/golang/golang-package.mk +++ b/lang/golang/golang-package.mk @@ -111,26 +111,29 @@ include $(GO_INCLUDE_DIR)/golang-values.mk # parameter to the -tags option for 'go install'. # # e.g. GO_PKG_TAGS:=release,noupgrade +# +# +# GO_PKG_INSTALL_BIN_PATH - target directory path, default /usr/bin +# +# Directory path under "dest_dir" where binaries will be installed by +# '$(call GoPackage/Package/Install/Bin,dest_dir)'. +# +# e.g. GO_PKG_INSTALL_BIN_PATH:=/sbin # Credit for this package build process (GoPackage/Build/Configure and # GoPackage/Build/Compile) belong to Debian's dh-golang completely. # https://salsa.debian.org/go-team/packages/dh-golang -# for building packages, not user code -GO_PKG_PATH:=/usr/share/gocode - GO_PKG_BUILD_PKG?=$(strip $(GO_PKG))/... +GO_PKG_INSTALL_BIN_PATH?=/usr/bin GO_PKG_WORK_DIR_NAME:=.go_work -GO_PKG_WORK_DIR=$(PKG_BUILD_DIR)/$(GO_PKG_WORK_DIR_NAME) - -GO_PKG_BUILD_DIR=$(GO_PKG_WORK_DIR)/build -GO_PKG_CACHE_DIR=$(GO_PKG_WORK_DIR)/cache - +GO_PKG_BUILD_DIR=$(PKG_BUILD_DIR)/$(GO_PKG_WORK_DIR_NAME)/build GO_PKG_BUILD_BIN_DIR=$(GO_PKG_BUILD_DIR)/bin$(if $(GO_HOST_TARGET_DIFFERENT),/$(GO_OS_ARCH)) -GO_PKG_BUILD_DEPENDS_SRC=$(STAGING_DIR)$(GO_PKG_PATH)/src +GO_PKG_BUILD_DEPENDS_PATH:=/usr/share/gocode +GO_PKG_BUILD_DEPENDS_SRC=$(STAGING_DIR)$(GO_PKG_BUILD_DEPENDS_PATH)/src ifdef CONFIG_PKG_ASLR_PIE_ALL ifeq ($(strip $(PKG_ASLR_PIE)),1) @@ -152,6 +155,14 @@ ifdef CONFIG_PKG_ASLR_PIE_REGULAR endif endif +ifdef CONFIG_GOLANG_SPECTRE + ifeq ($(GO_TARGET_SPECTRE_SUPPORTED),1) + GO_PKG_ENABLE_SPECTRE:=1 + else + $(warning Spectre mitigations are not supported for $(GO_ARCH)) + endif +endif + # sstrip causes corrupted section header size ifneq ($(CONFIG_USE_SSTRIP),) ifneq ($(CONFIG_DEBUG),) @@ -168,34 +179,51 @@ define GoPackage/GoSubMenu CATEGORY:=Languages endef +GO_PKG_BUILD_CONFIG_VARS= \ + GO_PKG="$(strip $(GO_PKG))" \ + GO_INSTALL_EXTRA="$(strip $(GO_PKG_INSTALL_EXTRA))" \ + GO_INSTALL_ALL="$(strip $(GO_PKG_INSTALL_ALL))" \ + GO_SOURCE_ONLY="$(strip $(GO_PKG_SOURCE_ONLY))" \ + GO_BUILD_PKG="$(strip $(GO_PKG_BUILD_PKG))" \ + GO_EXCLUDES="$(strip $(GO_PKG_EXCLUDES))" \ + GO_GO_GENERATE="$(strip $(GO_PKG_GO_GENERATE))" \ + GO_INSTALL_BIN_PATH="$(strip $(GO_PKG_INSTALL_BIN_PATH))" \ + BUILD_DIR="$(PKG_BUILD_DIR)" \ + GO_BUILD_DIR="$(GO_PKG_BUILD_DIR)" \ + GO_BUILD_BIN_DIR="$(GO_PKG_BUILD_BIN_DIR)" \ + GO_BUILD_DEPENDS_PATH="$(GO_PKG_BUILD_DEPENDS_PATH)" \ + GO_BUILD_DEPENDS_SRC="$(GO_PKG_BUILD_DEPENDS_SRC)" + GO_PKG_TARGET_VARS= \ - GOOS=$(GO_OS) \ - GOARCH=$(GO_ARCH) \ - GO386=$(GO_386) \ - GOARM=$(GO_ARM) \ - GOMIPS=$(GO_MIPS) \ - GOMIPS64=$(GO_MIPS64) \ + GOOS="$(GO_OS)" \ + GOARCH="$(GO_ARCH)" \ + GO386="$(GO_386)" \ + GOARM="$(GO_ARM)" \ + GOMIPS="$(GO_MIPS)" \ + GOMIPS64="$(GO_MIPS64)" \ CGO_ENABLED=1 \ - CC=$(TARGET_CC) \ - CXX=$(TARGET_CXX) \ + CC="$(TARGET_CC)" \ + CXX="$(TARGET_CXX)" \ CGO_CFLAGS="$(filter-out $(GO_CFLAGS_TO_REMOVE),$(TARGET_CFLAGS))" \ CGO_CPPFLAGS="$(TARGET_CPPFLAGS)" \ CGO_CXXFLAGS="$(filter-out $(GO_CFLAGS_TO_REMOVE),$(TARGET_CXXFLAGS))" \ CGO_LDFLAGS="$(TARGET_LDFLAGS)" GO_PKG_BUILD_VARS= \ - GOPATH=$(GO_PKG_BUILD_DIR) \ - GOCACHE=$(GO_PKG_CACHE_DIR) \ + GOPATH="$(GO_PKG_BUILD_DIR)" \ + GOCACHE="$(GO_BUILD_CACHE_DIR)" \ + GOMODCACHE="$(GO_MOD_CACHE_DIR)" \ GOENV=off -GO_PKG_DEFAULT_VARS= \ +GO_PKG_VARS= \ $(GO_PKG_TARGET_VARS) \ $(GO_PKG_BUILD_VARS) -GO_PKG_VARS=$(GO_PKG_DEFAULT_VARS) +GO_PKG_DEFAULT_GCFLAGS= \ + $(if $(GO_PKG_ENABLE_SPECTRE),-spectre all) -# do not use for new code; this will be removed after the next OpenWrt release -GoPackage/Environment=$(GO_PKG_VARS) +GO_PKG_DEFAULT_ASMFLAGS= \ + $(if $(GO_PKG_ENABLE_SPECTRE),-spectre all) GO_PKG_DEFAULT_LDFLAGS= \ -buildid '$(SOURCE_DATE_EPOCH)' \ @@ -210,130 +238,28 @@ GO_PKG_INSTALL_ARGS= \ -v \ -trimpath \ -ldflags "all=$(GO_PKG_DEFAULT_LDFLAGS)" \ + $(if $(GO_PKG_DEFAULT_GCFLAGS),-gcflags "all=$(GO_PKG_DEFAULT_GCFLAGS)") \ + $(if $(GO_PKG_DEFAULT_ASMFLAGS),-asmflags "all=$(GO_PKG_DEFAULT_ASMFLAGS)") \ $(if $(filter $(GO_PKG_ENABLE_PIE),1),-buildmode pie) \ $(if $(filter $(GO_ARCH),arm),-installsuffix "v$(GO_ARM)") \ $(if $(filter $(GO_ARCH),mips mipsle),-installsuffix "$(GO_MIPS)") \ $(if $(filter $(GO_ARCH),mips64 mips64le),-installsuffix "$(GO_MIPS64)") \ - $(if $(GO_PKG_GCFLAGS),-gcflags "$(GO_PKG_GCFLAGS)") \ + $(if $(GO_PKG_GCFLAGS),-gcflags "$(GO_PKG_GCFLAGS) $(GO_PKG_DEFAULT_GCFLAGS)") \ $(if $(GO_PKG_CUSTOM_LDFLAGS),-ldflags "$(GO_PKG_CUSTOM_LDFLAGS) $(GO_PKG_DEFAULT_LDFLAGS)") \ $(if $(GO_PKG_TAGS),-tags "$(GO_PKG_TAGS)") -# false if directory does not exist -GoPackage/is_dir_not_empty=$$$$($(FIND) $(1) -maxdepth 0 -type d \! -empty 2>/dev/null) - -GoPackage/has_binaries=$(call GoPackage/is_dir_not_empty,$(GO_PKG_BUILD_BIN_DIR)) - define GoPackage/Build/Configure - ( \ - cd $(PKG_BUILD_DIR) ; \ - mkdir -p $(GO_PKG_BUILD_DIR)/bin $(GO_PKG_BUILD_DIR)/src $(GO_PKG_CACHE_DIR) ; \ - \ - files=$$$$($(FIND) ./ \ - -type d -a \( -path './.git' -o -path './$(GO_PKG_WORK_DIR_NAME)' \) -prune -o \ - \! -type d -print | \ - sed 's|^\./||') ; \ - \ - if [ "$(strip $(GO_PKG_INSTALL_ALL))" != 1 ]; then \ - code=$$$$(echo "$$$$files" | grep '\.\(c\|cc\|cpp\|go\|h\|hh\|hpp\|proto\|s\)$$$$') ; \ - testdata=$$$$(echo "$$$$files" | grep '\(^\|/\)testdata/') ; \ - gomod=$$$$(echo "$$$$files" | grep '\(^\|/\)go\.\(mod\|sum\)$$$$') ; \ - \ - for pattern in $(GO_PKG_INSTALL_EXTRA); do \ - extra=$$$$(echo "$$$$extra"; echo "$$$$files" | grep "$$$$pattern") ; \ - done ; \ - \ - files=$$$$(echo "$$$$code"; echo "$$$$testdata"; echo "$$$$gomod"; echo "$$$$extra") ; \ - files=$$$$(echo "$$$$files" | grep -v '^[[:space:]]*$$$$' | sort -u) ; \ - fi ; \ - \ - IFS=$$$$'\n' ; \ - \ - echo "Copying files from $(PKG_BUILD_DIR) into $(GO_PKG_BUILD_DIR)/src/$(strip $(GO_PKG))" ; \ - for file in $$$$files; do \ - echo $$$$file ; \ - dest=$(GO_PKG_BUILD_DIR)/src/$(strip $(GO_PKG))/$$$$file ; \ - mkdir -p $$$$(dirname $$$$dest) ; \ - $(CP) $$$$file $$$$dest ; \ - done ; \ - echo ; \ - \ - link_contents() { \ - local src=$$$$1 ; \ - local dest=$$$$2 ; \ - local dirs dir base ; \ - \ - if [ -n "$$$$($(FIND) $$$$src -mindepth 1 -maxdepth 1 -name '*.go' \! -type d)" ]; then \ - echo "$$$$src is already a Go library" ; \ - return 1 ; \ - fi ; \ - \ - dirs=$$$$($(FIND) $$$$src -mindepth 1 -maxdepth 1 -type d) ; \ - for dir in $$$$dirs; do \ - base=$$$$(basename $$$$dir) ; \ - if [ -d $$$$dest/$$$$base ]; then \ - case $$$$dir in \ - *$(GO_PKG_PATH)/src/$(strip $(GO_PKG))) \ - echo "$(strip $(GO_PKG)) is already installed. Please check for circular dependencies." ;; \ - *) \ - link_contents $$$$src/$$$$base $$$$dest/$$$$base ;; \ - esac ; \ - else \ - echo "...$$$${src#$(GO_PKG_BUILD_DEPENDS_SRC)}/$$$$base" ; \ - $(LN) $$$$src/$$$$base $$$$dest/$$$$base ; \ - fi ; \ - done ; \ - } ; \ - \ - if [ "$(strip $(GO_PKG_SOURCE_ONLY))" != 1 ]; then \ - if [ -d $(GO_PKG_BUILD_DEPENDS_SRC) ]; then \ - echo "Symlinking directories from $(GO_PKG_BUILD_DEPENDS_SRC) into $(GO_PKG_BUILD_DIR)/src" ; \ - link_contents $(GO_PKG_BUILD_DEPENDS_SRC) $(GO_PKG_BUILD_DIR)/src ; \ - else \ - echo "$(GO_PKG_BUILD_DEPENDS_SRC) does not exist, skipping symlinks" ; \ - fi ; \ - else \ - echo "Not building binaries, skipping symlinks" ; \ - fi ; \ - echo ; \ - ) + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_PKG_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh configure endef # $(1) additional arguments for go command line (optional) define GoPackage/Build/Compile - ( \ - cd $(GO_PKG_BUILD_DIR) ; \ - export $(GO_PKG_VARS) ; \ - \ - echo "Finding targets" ; \ - targets=$$$$(go list $(GO_PKG_BUILD_PKG)) ; \ - for pattern in $(GO_PKG_EXCLUDES); do \ - targets=$$$$(echo "$$$$targets" | grep -v "$$$$pattern") ; \ - done ; \ - echo ; \ - \ - if [ "$(strip $(GO_PKG_GO_GENERATE))" = 1 ]; then \ - echo "Calling go generate" ; \ - go generate -v $(1) $$$$targets ; \ - echo ; \ - fi ; \ - \ - if [ "$(strip $(GO_PKG_SOURCE_ONLY))" != 1 ]; then \ - echo "Building targets" ; \ - go install $(GO_PKG_INSTALL_ARGS) $(1) $$$$targets ; \ - retval=$$$$? ; \ - echo ; \ - \ - if [ "$$$$retval" -eq 0 ] && [ -z "$(call GoPackage/has_binaries)" ]; then \ - echo "No binaries were generated, consider adding GO_PKG_SOURCE_ONLY:=1 to Makefile" ; \ - echo ; \ - fi ; \ - \ - echo "Cleaning module download cache (golang/go#27455)" ; \ - go clean -modcache ; \ - echo ; \ - fi ; \ - exit $$$$retval ; \ - ) + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_PKG_BUILD_CONFIG_VARS) \ + $(GO_PKG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh build $(GO_PKG_INSTALL_ARGS) $(1) endef define GoPackage/Build/InstallDev @@ -341,27 +267,33 @@ define GoPackage/Build/InstallDev endef define GoPackage/Package/Install/Bin - if [ -n "$(call GoPackage/has_binaries)" ]; then \ - $(INSTALL_DIR) $(1)/usr/bin ; \ - $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/* $(1)/usr/bin/ ; \ - fi + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_PKG_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh install_bin "$(1)" endef define GoPackage/Package/Install/Src - dir=$$$$(dirname $(GO_PKG)) ; \ - $(INSTALL_DIR) $(1)$(GO_PKG_PATH)/src/$$$$dir ; \ - $(CP) $(GO_PKG_BUILD_DIR)/src/$(strip $(GO_PKG)) $(1)$(GO_PKG_PATH)/src/$$$$dir/ + $(GO_GENERAL_BUILD_CONFIG_VARS) \ + $(GO_PKG_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh install_src "$(1)" endef define GoPackage/Package/Install - $(call GoPackage/Package/Install/Bin,$(1)) + $(if $(filter $(GO_PKG_SOURCE_ONLY),1),, \ + $(call GoPackage/Package/Install/Bin,$(1)) \ + ) $(call GoPackage/Package/Install/Src,$(1)) endef ifneq ($(strip $(GO_PKG)),) + ifeq ($(GO_TARGET_SPECTRE_SUPPORTED),1) + PKG_CONFIG_DEPENDS+=CONFIG_GOLANG_SPECTRE + endif + Build/Configure=$(call GoPackage/Build/Configure) Build/Compile=$(call GoPackage/Build/Compile) + Hooks/Compile/Post+=Go/CacheCleanup Build/InstallDev=$(call GoPackage/Build/InstallDev,$(1)) endif @@ -382,3 +314,14 @@ define GoSrcPackage Package/$(1)/install=$$(call GoPackage/Package/Install/Src,$$(1)) endif endef + + +# Deprecated variables - these will be removed after the next OpenWrt release +GO_PKG_PATH=$(GO_PKG_BUILD_DEPENDS_PATH) +GO_PKG_WORK_DIR=$(PKG_BUILD_DIR)/$(GO_PKG_WORK_DIR_NAME) +GO_PKG_CACHE_DIR=$(GO_BUILD_CACHE_DIR) +GO_PKG_DEFAULT_VARS=$(GO_PKG_VARS) +GoPackage/Environment=$(GO_PKG_VARS) +GoPackage/is_dir_not_empty=$$$$($(FIND) "$(1)" -maxdepth 0 -type d \! -empty 2>/dev/null) +GoPackage/has_binaries=$(call GoPackage/is_dir_not_empty,$(GO_PKG_BUILD_BIN_DIR)) +# End of deprecated variables diff --git a/lang/golang/golang-values.mk b/lang/golang/golang-values.mk index d52ad481f..69126a1ed 100644 --- a/lang/golang/golang-values.mk +++ b/lang/golang/golang-values.mk @@ -21,6 +21,7 @@ unexport \ GOARCH \ GOBIN \ GOCACHE \ + GOMODCACHE \ GODEBUG \ GOENV \ GOFLAGS \ @@ -110,13 +111,13 @@ unexport \ BOOT_GO_GCFLAGS \ BOOT_GO_LDFLAGS -# From https://golang.org/src/cmd/dist/buildtool.go +# From https://golang.org/src/cmd/dist/buildruntime.go unexport \ - GOBOOTSTRAP_TOOLEXEC + GOEXPERIMENT -# From https://golang.org/src/cmd/internal/objabi/util.go +# From https://golang.org/src/cmd/dist/buildtool.go unexport \ - GOEXPERIMENT + GOBOOTSTRAP_TOOLEXEC # GOOS / GOARCH @@ -198,6 +199,8 @@ GO_PIE_SUPPORTED_OS_ARCH:= \ android_386 android_amd64 android_arm android_arm64 \ linux_386 linux_amd64 linux_arm linux_arm64 \ \ + windows_386 windows_amd64 windows_arm \ + \ darwin_amd64 \ freebsd_amd64 \ \ @@ -205,7 +208,7 @@ GO_PIE_SUPPORTED_OS_ARCH:= \ \ linux_ppc64le linux_s390x -go_pie_install_suffix=$(if $(filter $(1),aix_ppc64),,shared) +go_pie_install_suffix=$(if $(filter $(1),aix_ppc64 windows_386 windows_amd64 windows_arm),,shared) ifneq ($(filter $(GO_HOST_OS_ARCH),$(GO_PIE_SUPPORTED_OS_ARCH)),) GO_HOST_PIE_SUPPORTED:=1 @@ -216,3 +219,36 @@ ifneq ($(filter $(GO_OS_ARCH),$(GO_PIE_SUPPORTED_OS_ARCH)),) GO_TARGET_PIE_SUPPORTED:=1 GO_TARGET_PIE_INSTALL_SUFFIX:=$(call go_pie_install_suffix,$(GO_OS_ARCH)) endif + + +# Spectre mitigations + +GO_SPECTRE_SUPPORTED_ARCH:=amd64 + +ifneq ($(filter $(GO_HOST_ARCH),$(GO_SPECTRE_SUPPORTED_ARCH)),) + GO_HOST_SPECTRE_SUPPORTED:=1 +endif + +ifneq ($(filter $(GO_ARCH),$(GO_SPECTRE_SUPPORTED_ARCH)),) + GO_TARGET_SPECTRE_SUPPORTED:=1 +endif + + +# General build info + +GO_BUILD_CACHE_DIR:=$(or $(call qstrip,$(CONFIG_GOLANG_BUILD_CACHE_DIR)),$(TOPDIR)/.go-build) +GO_MOD_CACHE_DIR:=$(DL_DIR)/go-mod-cache + +GO_MOD_ARGS= \ + -modcacherw + +GO_GENERAL_BUILD_CONFIG_VARS= \ + CONFIG_GOLANG_MOD_CACHE_WORLD_READABLE="$(CONFIG_GOLANG_MOD_CACHE_WORLD_READABLE)" \ + GO_BUILD_CACHE_DIR="$(GO_BUILD_CACHE_DIR)" \ + GO_MOD_CACHE_DIR="$(GO_MOD_CACHE_DIR)" \ + GO_MOD_ARGS="$(GO_MOD_ARGS)" + +define Go/CacheCleanup + $(GENERAL_BUILD_CONFIG_VARS) \ + $(SHELL) $(GO_INCLUDE_DIR)/golang-build.sh cache_cleanup +endef diff --git a/lang/golang/golang/Config.in b/lang/golang/golang/Config.in new file mode 100644 index 000000000..714bf01fd --- /dev/null +++ b/lang/golang/golang/Config.in @@ -0,0 +1,33 @@ +menu "Configuration" + +config GOLANG_EXTERNAL_BOOTSTRAP_ROOT + string "External bootstrap Go root directory" + default "" + help + Path to a working Go tree (>= Go 1.4), with bin, pkg, and src + subdirectories and the Go compiler at bin/go. + + If specified, the existing Go installation will be used to + compile host (buildroot) Go. + + Leave blank to compile the default bootstrap Go. + +config GOLANG_BUILD_CACHE_DIR + string "Go build cache directory" + default "" + help + Store the Go build cache in this directory. + If not set, uses './.go-build'. + +config GOLANG_MOD_CACHE_WORLD_READABLE + bool "Ensure Go module cache is world-readable" + default n + +config GOLANG_SPECTRE + bool "Enable Spectre mitigations" + default n + depends on x86_64 + help + Currently only available for x86-64 (amd64). + +endmenu diff --git a/lang/golang/golang/Makefile b/lang/golang/golang/Makefile index 320ed7812..2016dfb8c 100644 --- a/lang/golang/golang/Makefile +++ b/lang/golang/golang/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk -GO_VERSION_MAJOR_MINOR:=1.14 -GO_VERSION_PATCH:=7 +GO_VERSION_MAJOR_MINOR:=1.15 +GO_VERSION_PATCH:=2 PKG_NAME:=golang PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) @@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \ PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz PKG_SOURCE_URL:=$(GO_SOURCE_URLS) -PKG_HASH:=064392433563660c73186991c0a315787688e7c38a561e26647686f89b6c30e3 +PKG_HASH:=28bf9d0bcde251011caae230a4a05d917b172ea203f2a62f2c2f9533589d4b4d PKG_MAINTAINER:=Jeffery To PKG_LICENSE:=BSD-3-Clause @@ -32,10 +32,6 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/go-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 PKG_USE_MIPS16:=0 -PKG_GO_WORK_DIR:=$(PKG_BUILD_DIR)/.go_work -PKG_GO_HOST_CACHE_DIR:=$(PKG_GO_WORK_DIR)/host_cache -PKG_GO_TARGET_CACHE_DIR:=$(PKG_GO_WORK_DIR)/target_cache - PKG_GO_PREFIX:=/usr PKG_GO_VERSION_ID:=$(GO_VERSION_MAJOR_MINOR) PKG_GO_ROOT:=$(PKG_GO_PREFIX)/lib/go-$(PKG_GO_VERSION_ID) @@ -43,24 +39,21 @@ PKG_GO_ROOT:=$(PKG_GO_PREFIX)/lib/go-$(PKG_GO_VERSION_ID) HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/go-$(PKG_VERSION) HOST_BUILD_PARALLEL:=1 -HOST_GO_WORK_DIR:=$(HOST_BUILD_DIR)/.go_work -HOST_GO_CACHE_DIR:=$(HOST_GO_WORK_DIR)/cache - HOST_GO_PREFIX:=$(STAGING_DIR_HOSTPKG) HOST_GO_VERSION_ID:=cross HOST_GO_ROOT:=$(HOST_GO_PREFIX)/lib/go-$(HOST_GO_VERSION_ID) HOST_GO_VALID_OS_ARCH:= \ android_386 android_amd64 android_arm android_arm64 \ - darwin_386 darwin_amd64 darwin_arm darwin_arm64 \ freebsd_386 freebsd_amd64 freebsd_arm freebsd_arm64 \ linux_386 linux_amd64 linux_arm linux_arm64 \ + openbsd_386 openbsd_amd64 openbsd_arm openbsd_arm64 \ \ - openbsd_386 openbsd_amd64 openbsd_arm \ netbsd_386 netbsd_amd64 netbsd_arm \ plan9_386 plan9_amd64 plan9_arm \ + windows_386 windows_amd64 windows_arm \ \ - windows_386 windows_amd64 \ + darwin_amd64 darwin_arm64 \ \ dragonfly_amd64 \ illumos_amd64 \ @@ -78,8 +71,6 @@ BOOTSTRAP_SOURCE_URL:=$(GO_SOURCE_URLS) BOOTSTRAP_HASH:=f4ff5b5eb3a3cae1c993723f3eab519c5bae18866b5e5f96fe1102f0cb5c3e52 BOOTSTRAP_BUILD_DIR:=$(HOST_BUILD_DIR)/.go_bootstrap -BOOTSTRAP_WORK_DIR:=$(BOOTSTRAP_BUILD_DIR)/.go_work -BOOTSTRAP_CACHE_DIR:=$(BOOTSTRAP_WORK_DIR)/cache BOOTSTRAP_GO_VALID_OS_ARCH:= \ darwin_386 darwin_amd64 \ @@ -97,26 +88,16 @@ include $(INCLUDE_DIR)/package.mk include ../golang-compiler.mk include ../golang-package.mk -PKG_UNPACK:=$(HOST_TAR) -C $(PKG_BUILD_DIR) --strip-components=1 -xzf $(DL_DIR)/$(PKG_SOURCE) -HOST_UNPACK:=$(HOST_TAR) -C $(HOST_BUILD_DIR) --strip-components=1 -xzf $(DL_DIR)/$(PKG_SOURCE) -BOOTSTRAP_UNPACK:=$(HOST_TAR) -C $(BOOTSTRAP_BUILD_DIR) --strip-components=1 -xzf $(DL_DIR)/$(BOOTSTRAP_SOURCE) +PKG_UNPACK:=$(HOST_TAR) -C "$(PKG_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" +HOST_UNPACK:=$(HOST_TAR) -C "$(HOST_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(PKG_SOURCE)" +BOOTSTRAP_UNPACK:=$(HOST_TAR) -C "$(BOOTSTRAP_BUILD_DIR)" --strip-components=1 -xzf "$(DL_DIR)/$(BOOTSTRAP_SOURCE)" # don't strip ELF executables in test data RSTRIP:=: STRIP:=: -ifdef CONFIG_PKG_ASLR_PIE_ALL - ifeq ($(GO_TARGET_PIE_SUPPORTED),1) - PKG_GO_ENABLE_PIE:=1 - PKG_GO_INSTALL_SUFFIX:=$(GO_TARGET_PIE_INSTALL_SUFFIX) - else - $(warning PIE buildmode is not supported for $(GO_OS)/$(GO_ARCH)) - endif -endif - -ifeq ($(GO_HOST_PIE_SUPPORTED),1) - HOST_GO_ENABLE_PIE:=1 - HOST_GO_INSTALL_SUFFIX:=$(GO_HOST_PIE_INSTALL_SUFFIX) +ifeq ($(GO_TARGET_SPECTRE_SUPPORTED),1) + PKG_CONFIG_DEPENDS+=CONFIG_GOLANG_SPECTRE endif define Package/golang/Default @@ -155,20 +136,7 @@ libraries for the Go programming language. endef define Package/golang/config -menu "Configuration" - -config GOLANG_EXTERNAL_BOOTSTRAP_ROOT - string "External bootstrap Go root directory" - help - Path to a working Go tree (>= Go 1.4), with bin, pkg, and src - subdirectories and the Go compiler at bin/go. - - If specified, the existing Go installation will be used to - compile host (buildroot) Go. - - Leave blank to compile the default bootstrap Go. - -endmenu + source "$(SOURCE)/Config.in" endef define Package/golang-doc @@ -194,94 +162,63 @@ This package provides the Go programming language source files needed for cross-compilation. endef -EXTERNAL_BOOTSTRAP_DIR:=$(call qstrip,$(CONFIG_GOLANG_EXTERNAL_BOOTSTRAP_ROOT)) -USE_DEFAULT_BOOTSTRAP:=$(if $(EXTERNAL_BOOTSTRAP_DIR),,1) -PKG_GO_ZBOOTSTRAP_MODS:= \ - s/defaultGO386 = `[^`]*`/defaultGO386 = `$(if $(GO_386),$(GO_386),387)`/; \ - s/defaultGOARM = `[^`]*`/defaultGOARM = `$(if $(GO_ARM),$(GO_ARM),5)`/; \ - s/defaultGOMIPS = `[^`]*`/defaultGOMIPS = `$(if $(GO_MIPS),$(GO_MIPS),hardfloat)`/; \ - s/defaultGOMIPS64 = `[^`]*`/defaultGOMIPS64 = `$(if $(GO_MIPS64),$(GO_MIPS64),hardfloat)`/; \ - s/defaultGOPPC64 = `[^`]*`/defaultGOPPC64 = `power8`/; +# Bootstrap -PKG_GO_LDFLAGS= \ - -buildid '$(SOURCE_DATE_EPOCH)' +BOOTSTRAP_ROOT_DIR:=$(call qstrip,$(CONFIG_GOLANG_EXTERNAL_BOOTSTRAP_ROOT)) -ifeq ($(CONFIG_NO_STRIP)$(CONFIG_DEBUG),) - PKG_GO_LDFLAGS+= -s -w -endif +ifeq ($(BOOTSTRAP_ROOT_DIR),) + BOOTSTRAP_ROOT_DIR:=$(BOOTSTRAP_BUILD_DIR) -# setting -trimpath is not necessary here because the paths inside the -# compiler binary are relative to GOROOT_FINAL (PKG_GO_ROOT), which is -# static / not dependent on the build environment -PKG_GO_INSTALL_ARGS= \ - -ldflags "all=$(PKG_GO_LDFLAGS)" + define Download/golang-bootstrap + FILE:=$(BOOTSTRAP_SOURCE) + URL:=$(BOOTSTRAP_SOURCE_URL) + HASH:=$(BOOTSTRAP_HASH) + endef + $(eval $(call Download,golang-bootstrap)) -ifeq ($(PKG_GO_ENABLE_PIE),1) - PKG_GO_INSTALL_ARGS+= -buildmode pie + define Bootstrap/Prepare + mkdir -p "$(BOOTSTRAP_BUILD_DIR)" + $(BOOTSTRAP_UNPACK) + endef + Hooks/HostPrepare/Post+=Bootstrap/Prepare + + $(eval $(call GoCompiler/AddProfile,Bootstrap,$(BOOTSTRAP_BUILD_DIR),,bootstrap,$(GO_HOST_OS_ARCH))) endif -define Download/golang-bootstrap - FILE:=$(BOOTSTRAP_SOURCE) - URL:=$(BOOTSTRAP_SOURCE_URL) - HASH:=$(BOOTSTRAP_HASH) -endef -$(eval $(call GoCompiler/AddProfile,Host,$(HOST_BUILD_DIR),$(HOST_GO_PREFIX),$(HOST_GO_VERSION_ID),$(GO_HOST_OS_ARCH),$(HOST_GO_INSTALL_SUFFIX))) -$(eval $(call GoCompiler/AddProfile,Package,$(PKG_BUILD_DIR),$(PKG_GO_PREFIX),$(PKG_GO_VERSION_ID),$(GO_OS_ARCH),$(PKG_GO_INSTALL_SUFFIX))) +# Host -ifeq ($(USE_DEFAULT_BOOTSTRAP),1) - $(eval $(call GoCompiler/AddProfile,Bootstrap,$(BOOTSTRAP_BUILD_DIR),,bootstrap,$(GO_HOST_OS_ARCH))) +ifeq ($(GO_HOST_PIE_SUPPORTED),1) + HOST_GO_ENABLE_PIE:=1 +endif - $(eval $(call Download,golang-bootstrap)) +# when using GO_LDFLAGS to set buildmode=pie, the PIE install suffix +# does not apply (we also delete the std lib during Host/Install) - define Host/Prepare - $(call Host/Prepare/Default) - mkdir -p $(BOOTSTRAP_BUILD_DIR) - $(BOOTSTRAP_UNPACK) - endef -endif +$(eval $(call GoCompiler/AddProfile,Host,$(HOST_BUILD_DIR),$(HOST_GO_PREFIX),$(HOST_GO_VERSION_ID),$(GO_HOST_OS_ARCH),$(HOST_GO_INSTALL_SUFFIX))) + +HOST_GO_VARS= \ + GOCACHE="$(GO_BUILD_CACHE_DIR)" \ + GOENV=off \ + CC="$(HOSTCC_NOCACHE)" \ + CXX="$(HOSTCXX_NOCACHE)" -# when https://github.com/golang/go/issues/31544 is fixed, -# we should be able to set GO_LDFLAGS=-buildmode=pie for host make -# instead of doing a rebuild for pie define Host/Compile $(call GoCompiler/Bootstrap/CheckHost,$(BOOTSTRAP_GO_VALID_OS_ARCH)) $(call GoCompiler/Host/CheckHost,$(HOST_GO_VALID_OS_ARCH)) - mkdir -p \ - $(BOOTSTRAP_CACHE_DIR) \ - $(HOST_GO_CACHE_DIR) + mkdir -p "$(GO_BUILD_CACHE_DIR)" $(call GoCompiler/Bootstrap/Make, \ - GOCACHE=$(BOOTSTRAP_CACHE_DIR) \ - CC=$(HOSTCC_NOCACHE) \ - CXX=$(HOSTCXX_NOCACHE) \ + $(HOST_GO_VARS) \ ) $(call GoCompiler/Host/Make, \ - GOROOT_BOOTSTRAP=$(if $(USE_DEFAULT_BOOTSTRAP),$(BOOTSTRAP_BUILD_DIR),$(EXTERNAL_BOOTSTRAP_DIR)) \ - GOCACHE=$(HOST_GO_CACHE_DIR) \ - CC=$(HOSTCC_NOCACHE) \ - CXX=$(HOSTCXX_NOCACHE) \ + GOROOT_BOOTSTRAP="$(BOOTSTRAP_ROOT_DIR)" \ + $(if $(HOST_GO_ENABLE_PIE),GO_LDFLAGS="-buildmode pie") \ + $(HOST_GO_VARS) \ ) - - ifneq ($(HOST_GO_ENABLE_PIE),) - @echo "Rebuilding host Go with PIE" - - ( \ - cd $(HOST_BUILD_DIR)/bin ; \ - $(CP) go go-nopie ; \ - GOCACHE=$(HOST_GO_CACHE_DIR) \ - GOENV=off \ - CC=$(HOSTCC_NOCACHE) \ - CXX=$(HOSTCXX_NOCACHE) \ - ./go-nopie install -a -buildmode=pie std cmd ; \ - retval=$$$$? ; \ - rm -f go-nopie ; \ - exit $$$$retval ; \ - ) - endif endef # if host and target os/arch are the same, @@ -295,64 +232,97 @@ define Host/Install $(call GoCompiler/Host/Install/BinLinks,) - rm -rf $(HOST_GO_ROOT)/pkg/$(GO_HOST_OS_ARCH)$(if $(HOST_GO_INSTALL_SUFFIX),_$(HOST_GO_INSTALL_SUFFIX)) + rm -rf "$(HOST_GO_ROOT)/pkg/$(GO_HOST_OS_ARCH)$(if $(HOST_GO_INSTALL_SUFFIX),_$(HOST_GO_INSTALL_SUFFIX))" - $(INSTALL_DIR) $(HOST_GO_ROOT)/openwrt - $(INSTALL_BIN) ./files/go-gcc-helper $(HOST_GO_ROOT)/openwrt/ - $(LN) go-gcc-helper $(HOST_GO_ROOT)/openwrt/gcc - $(LN) go-gcc-helper $(HOST_GO_ROOT)/openwrt/g++ + $(INSTALL_DIR) "$(HOST_GO_ROOT)/openwrt" + $(INSTALL_BIN) ./files/go-gcc-helper "$(HOST_GO_ROOT)/openwrt/" + $(LN) go-gcc-helper "$(HOST_GO_ROOT)/openwrt/gcc" + $(LN) go-gcc-helper "$(HOST_GO_ROOT)/openwrt/g++" endef define Host/Uninstall - rm -rf $(HOST_GO_ROOT)/openwrt + rm -rf "$(HOST_GO_ROOT)/openwrt" $(call GoCompiler/Host/Uninstall/BinLinks,) $(call GoCompiler/Host/Uninstall,) endef + +# Target + +ifeq ($(GO_PKG_ENABLE_PIE),1) + PKG_GO_INSTALL_SUFFIX:=$(GO_TARGET_PIE_INSTALL_SUFFIX) +endif + +$(eval $(call GoCompiler/AddProfile,Package,$(PKG_BUILD_DIR),$(PKG_GO_PREFIX),$(PKG_GO_VERSION_ID),$(GO_OS_ARCH),$(PKG_GO_INSTALL_SUFFIX))) + +PKG_GO_ZBOOTSTRAP_MODS:= \ + s/defaultGO386 = `[^`]*`/defaultGO386 = `$(or $(GO_386),387)`/; \ + s/defaultGOARM = `[^`]*`/defaultGOARM = `$(or $(GO_ARM),5)`/; \ + s/defaultGOMIPS = `[^`]*`/defaultGOMIPS = `$(or $(GO_MIPS),hardfloat)`/; \ + s/defaultGOMIPS64 = `[^`]*`/defaultGOMIPS64 = `$(or $(GO_MIPS64),hardfloat)`/; \ + s/defaultGOPPC64 = `[^`]*`/defaultGOPPC64 = `power8`/; + +PKG_GO_VARS= \ + GOCACHE="$(GO_BUILD_CACHE_DIR)" \ + GOENV=off \ + GO_GCC_HELPER_PATH="$$$$PATH" \ + CC=gcc \ + CXX=g++ \ + PKG_CONFIG=pkg-config \ + PATH="$(HOST_GO_ROOT)/openwrt:$$$$PATH" + +PKG_GO_GCFLAGS= \ + $(if $(GO_PKG_ENABLE_SPECTRE),-spectre all) + +PKG_GO_ASMFLAGS= \ + $(if $(GO_PKG_ENABLE_SPECTRE),-spectre all) + +PKG_GO_LDFLAGS= \ + -buildid '$(SOURCE_DATE_EPOCH)' \ + -linkmode external \ + -extldflags '$(patsubst -z%,-Wl$(comma)-z$(comma)%,$(TARGET_LDFLAGS))' \ + $(if $(CONFIG_NO_STRIP)$(CONFIG_DEBUG),,-s -w) + +# setting -trimpath is not necessary here because the paths inside the +# compiler binary are relative to GOROOT_FINAL (PKG_GO_ROOT), which is +# static / not dependent on the build environment +PKG_GO_INSTALL_ARGS= \ + -ldflags "all=$(PKG_GO_LDFLAGS)" \ + $(if $(PKG_GO_GCFLAGS),-gcflags "all=$(PKG_GO_GCFLAGS)") \ + $(if $(PKG_GO_ASMFLAGS),-asmflags "all=$(PKG_GO_ASMFLAGS)") \ + $(if $(filter $(GO_PKG_ENABLE_PIE),1),-buildmode pie) + define Build/Compile - mkdir -p \ - $(PKG_GO_HOST_CACHE_DIR) \ - $(PKG_GO_TARGET_CACHE_DIR) + mkdir -p "$(GO_BUILD_CACHE_DIR)" @echo "Building target Go first stage" $(call GoCompiler/Package/Make, \ - GOROOT_BOOTSTRAP=$(HOST_GO_ROOT) \ - GOCACHE=$(PKG_GO_HOST_CACHE_DIR) \ + GOROOT_BOOTSTRAP="$(HOST_GO_ROOT)" \ GO_GCC_HELPER_CC="$(HOSTCC)" \ GO_GCC_HELPER_CXX="$(HOSTCXX)" \ - GO_GCC_HELPER_PATH=$$$$PATH \ - CC=gcc \ - CXX=g++ \ - PKG_CONFIG=pkg-config \ - PATH=$(HOST_GO_ROOT)/openwrt:$$$$PATH \ + $(PKG_GO_VARS) \ ) $(SED) '$(PKG_GO_ZBOOTSTRAP_MODS)' \ - $(PKG_BUILD_DIR)/src/cmd/internal/objabi/zbootstrap.go + "$(PKG_BUILD_DIR)/src/cmd/internal/objabi/zbootstrap.go" @echo "Building target Go second stage" ( \ - cd $(PKG_BUILD_DIR)/bin ; \ + cd "$(PKG_BUILD_DIR)/bin" ; \ export $(GO_PKG_TARGET_VARS) ; \ $(CP) go go-host ; \ - GOROOT_FINAL=$(PKG_GO_ROOT) \ - GOCACHE=$(PKG_GO_TARGET_CACHE_DIR) \ - GOENV=off \ + GOROOT_FINAL="$(PKG_GO_ROOT)" \ GO_GCC_HELPER_CC="$(TARGET_CC)" \ GO_GCC_HELPER_CXX="$(TARGET_CXX)" \ - GO_GCC_HELPER_PATH=$$$$PATH \ - CC=gcc \ - CXX=g++ \ - PKG_CONFIG=pkg-config \ - PATH=$(HOST_GO_ROOT)/openwrt:$$$$PATH \ + $(PKG_GO_VARS) \ ./go-host install -a $(PKG_GO_INSTALL_ARGS) std cmd ; \ - retval=$$$$? ; \ + retval="$$$$?" ; \ rm -f go-host ; \ - exit $$$$retval ; \ + exit "$$$$retval" ; \ ) endef @@ -377,6 +347,7 @@ define Package/golang-src/extra_provides echo 'libc.so.6' endef + $(eval $(call HostBuild)) $(eval $(call BuildPackage,golang)) $(eval $(call BuildPackage,golang-doc)) diff --git a/lang/golang/golang/files/go-gcc-helper b/lang/golang/golang/files/go-gcc-helper index 3d3f8935d..b396e302c 100644 --- a/lang/golang/golang/files/go-gcc-helper +++ b/lang/golang/golang/files/go-gcc-helper @@ -1,23 +1,41 @@ #!/bin/sh me=go-gcc-helper -name=$(basename $0) +name="${0##*/}" -case $name in +log() { + # shellcheck disable=SC2039 + local IFS=" " + printf '%s\n' "$me: $*" +} + +case "$name" in gcc) - cmd=$GO_GCC_HELPER_CC + if [ -z "$GO_GCC_HELPER_CC" ]; then + log "missing GO_GCC_HELPER_CC" + exit 1 + fi + cmd="$GO_GCC_HELPER_CC" ;; g++) - cmd=$GO_GCC_HELPER_CXX + if [ -z "$GO_GCC_HELPER_CXX" ]; then + log "missing GO_GCC_HELPER_CXX" + exit 1 + fi + cmd="$GO_GCC_HELPER_CXX" ;; *) - echo "$me: unknown command \"$name\"" + log "unknown command \"$name\"" exit 1 ;; esac -export PATH="$GO_GCC_HELPER_PATH" +if [ -n "$GO_GCC_HELPER_PATH" ]; then + export PATH="$GO_GCC_HELPER_PATH" +else + log "missing GO_GCC_HELPER_PATH" +fi -echo "$me: running $cmd $@" +log "running $cmd $*" $cmd "$@" diff --git a/utils/ctop/Makefile b/utils/ctop/Makefile index aae82f010..85242dbe5 100644 --- a/utils/ctop/Makefile +++ b/utils/ctop/Makefile @@ -35,12 +35,11 @@ endef MAKE_PATH:=$(GO_PKG_WORK_DIR_NAME)/build/src/$(GO_PKG) MAKE_VARS += \ GOPATH=$(GO_PKG_BUILD_DIR) \ - GOCACHE=$(GO_PKG_CACHE_DIR) \ - GOTMPDIR=$(GO_PKG_TMP_DIR) \ + GOCACHE=$(GO_BUILD_CACHE_DIR) \ GOROOT_FINAL=$(GO_TARGET_ROOT) \ CC=$(TARGET_CC) \ CXX=$(TARGET_CXX) \ - $(call GoPackage/Environment) + $(GO_PKG_VARS) MAKE_FLAGS += \ COMMIT=$(PKG_SOURCE_VERSION) diff --git a/utils/docker-ce/Makefile b/utils/docker-ce/Makefile index 1f6c1ee79..fe072902e 100644 --- a/utils/docker-ce/Makefile +++ b/utils/docker-ce/Makefile @@ -77,8 +77,7 @@ define Build/Configure mkdir -p $(GO_PKG_BUILD_DIR)/bin \ $(GO_PKG_BUILD_DIR)/src \ $(GO_PKG_BUILD_DIR)/src/$(GO_PKG)/ \ - $(GO_PKG_CACHE_DIR) \ - $(GO_PKG_TMP_DIR) + $(GO_BUILD_CACHE_DIR) $(LN) $(PKG_BUILD_DIR)/cli $(GO_PKG_BUILD_DIR)/src/$(GO_PKG)/cli $(LN) $(PKG_BUILD_DIR)/engine $(GO_PKG_BUILD_DIR)/src/$(GO_PKG)/docker endef