From c137c382573f114902607546c5ed5b562df0b9b0 Mon Sep 17 00:00:00 2001 From: Jeffery To Date: Sun, 18 Mar 2018 00:32:35 +0800 Subject: [PATCH] golang: new packages From golang.org: The Go programming language is an open source project to make programmers more productive. This commit consists of two "parts": * golang/host: Main Go compiler for host (installed to STAGING_DIR_HOST/lib/go-cross), used to cross-compile Go programs to be packaged. * golang (and golang-src/golang-doc): Main Go compiler for on-target development. These packages are quite large, but I would expect only developers to install these. Signed-off-by: Jeffery To --- lang/golang/golang-compiler.mk | 186 ++++++++++++++++ lang/golang/golang-package.mk | 297 +++++++++++++++++++++++++ lang/golang/golang-values.mk | 72 ++++++ lang/golang/golang-version.mk | 14 ++ lang/golang/golang/Makefile | 277 +++++++++++++++++++++++ lang/golang/golang/files/go-gcc-helper | 23 ++ 6 files changed, 869 insertions(+) create mode 100644 lang/golang/golang-compiler.mk create mode 100644 lang/golang/golang-package.mk create mode 100644 lang/golang/golang-values.mk create mode 100644 lang/golang/golang-version.mk create mode 100644 lang/golang/golang/Makefile create mode 100644 lang/golang/golang/files/go-gcc-helper diff --git a/lang/golang/golang-compiler.mk b/lang/golang/golang-compiler.mk new file mode 100644 index 000000000..5e7fe689d --- /dev/null +++ b/lang/golang/golang-compiler.mk @@ -0,0 +1,186 @@ +# +# Copyright (C) 2018 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 + + +# $(1) valid GOOS_GOARCH combinations +# $(2) go version id +define GoCompiler/Default/CheckHost + $(if $(filter $(GO_HOST_OS_ARCH),$(1)),,$(error go-$(2) cannot be installed on $(GO_HOST_OS)/$(GO_HOST_ARCH))) +endef + +# $(1) source go root +# $(2) destination prefix +# $(3) go version id +# $(4) additional environment variables (optional) +define GoCompiler/Default/Make + ( \ + cd $(1)/src ; \ + $(if $(2),GOROOT_FINAL=$(2)/lib/go-$(3)) \ + $(4) \ + $(BASH) make.bash --no-banner ; \ + ) +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) +endef + +# $(1) source go root +# $(2) destination prefix +# $(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)/ +endef + +# $(1) source go root +# $(2) destination prefix +# $(3) go version id +# $(4) GOOS_GOARCH +define GoCompiler/Default/Install/Bin + $(call GoCompiler/Default/Install/make-dirs,$(2),$(3)) + + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),api) + + $(INSTALL_DATA) -p $(1)/VERSION $(2)/lib/go-$(3)/ + + for file in AUTHORS CONTRIBUTING.md CONTRIBUTORS LICENSE PATENTS README README.md; do \ + if [ -f $(1)/$$$$file ]; then \ + $(INSTALL_DATA) -p $(1)/$$$$file $(2)/share/go-$(3)/ ; \ + fi ; \ + done + + $(INSTALL_DIR) $(2)/lib/go-$(3)/bin + + ifeq ($(4),$(GO_HOST_OS_ARCH)) + $(INSTALL_BIN) -p $(1)/bin/* $(2)/lib/go-$(3)/bin/ + else + $(INSTALL_BIN) -p $(1)/bin/$(4)/* $(2)/lib/go-$(3)/bin/ + endif + + $(INSTALL_DIR) $(2)/lib/go-$(3)/pkg + $(CP) $(1)/pkg/$(4) $(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)/ +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 +endef + +# $(1) source go root +# $(2) destination prefix +# $(3) go version id +define GoCompiler/Default/Install/Doc + $(call GoCompiler/Default/Install/make-dirs,$(2),$(3)) + + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),doc) + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),favicon.ico) + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),robots.txt) +endef + +# $(1) source go root +# $(2) destination prefix +# $(3) go version id +define GoCompiler/Default/Install/Src + $(call GoCompiler/Default/Install/make-dirs,$(2),$(3)) + + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),lib) + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),misc) + $(call GoCompiler/Default/Install/install-share-data,$(1),$(2),$(3),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' \) \ + -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/ ; \ + 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) +endef + +# $(1) destination prefix +define GoCompiler/Default/Uninstall/BinLinks + rm -f $(1)/bin/go + rm -f $(1)/bin/gofmt +endef + + +# $(1) profile name +# $(2) source go root +# $(3) destination prefix +# $(4) go version id +# $(5) GOOS_GOARCH +define GoCompiler/AddProfile + + # $$(1) valid GOOS_GOARCH combinations + define GoCompiler/$(1)/CheckHost + $$(call GoCompiler/Default/CheckHost,$$(1),$(4)) + endef + + # $$(1) additional environment variables (optional) + define GoCompiler/$(1)/Make + $$(call GoCompiler/Default/Make,$(2),$(3),$(4),$$(1)) + endef + + # $$(1) override install prefix (optional) + define GoCompiler/$(1)/Install/Bin + $$(call GoCompiler/Default/Install/Bin,$(2),$$(or $$(1),$(3)),$(4),$(5)) + endef + + # $$(1) override install prefix (optional) + define GoCompiler/$(1)/Install/BinLinks + $$(call GoCompiler/Default/Install/BinLinks,$$(or $$(1),$(3)),$(4)) + endef + + # $$(1) override install prefix (optional) + define GoCompiler/$(1)/Install/Doc + $$(call GoCompiler/Default/Install/Doc,$(2),$$(or $$(1),$(3)),$(4)) + endef + + # $$(1) override install prefix (optional) + define GoCompiler/$(1)/Install/Src + $$(call GoCompiler/Default/Install/Src,$(2),$$(or $$(1),$(3)),$(4)) + endef + + # $$(1) override install prefix (optional) + define GoCompiler/$(1)/Uninstall + $$(call GoCompiler/Default/Uninstall,$$(or $$(1),$(3)),$(4)) + endef + + # $$(1) override install prefix (optional) + define GoCompiler/$(1)/Uninstall/BinLinks + $$(call GoCompiler/Default/Uninstall/BinLinks,$$(or $$(1),$(3))) + endef + +endef diff --git a/lang/golang/golang-package.mk b/lang/golang/golang-package.mk new file mode 100644 index 000000000..a42bc6417 --- /dev/null +++ b/lang/golang/golang-package.mk @@ -0,0 +1,297 @@ +# +# Copyright (C) 2018 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 + + +# Variables (all optional, except GO_PKG) to be set in package +# Makefiles: +# +# GO_PKG (required) - name of Go package +# +# Go name of the package. +# +# e.g. GO_PKG:=golang.org/x/text +# +# +# GO_PKG_INSTALL_EXTRA - list of regular expressions, default empty +# +# Additional files/directories to install. By default, only these +# files are installed: +# +# * Files with one of these extensions: +# .go, .c, .cc, .h, .hh, .proto, .s +# +# * Files in any 'testdata' directory +# +# e.g. GO_PKG_INSTALL_EXTRA:=example.toml marshal_test.toml +# +# +# GO_PKG_INSTALL_ALL - boolean (0 or 1), default false +# +# If true, install all files regardless of extension or directory. +# +# e.g. GO_PKG_INSTALL_ALL:=1 +# +# +# GO_PKG_SOURCE_ONLY - boolean (0 or 1), default false +# +# If true, 'go install' will not be called. If the package does not +# (or should not) build any binaries, then specifying this option will +# save build time. +# +# e.g. GO_PKG_SOURCE_ONLY:=1 +# +# +# GO_PKG_BUILD_PKG - list of build targets, default GO_PKG/... +# +# Build targets for compiling this Go package, i.e. arguments passed +# to 'go install' +# +# e.g. GO_PKG_BUILD_PKG:=github.com/debian/ratt/cmd/... +# +# +# GO_PKG_EXCLUDES - list of regular expressions, default empty +# +# Patterns to exclude from the build targets expanded from +# GO_PKG_BUILD_PKG. +# +# e.g. GO_PKG_EXCLUDES:=examples/ +# +# +# GO_PKG_GO_GENERATE - boolean (0 or 1), default false +# +# If true, 'go generate' will be called on all build targets (as +# determined by GO_PKG_BUILD_PKG and GO_PKG_EXCLUDES). This is usually +# not necessary. +# +# e.g. GO_PKG_GO_GENERATE:=1 + +# Credit for this package build process (GoPackage/Build/Configure and +# GoPackage/Build/Compile) belong to Debian's dh-golang completely. +# https://anonscm.debian.org/cgit/pkg-go/packages/dh-golang.git + + +# for building packages, not user code +GO_PKG_PATH:=/usr/share/gocode + +GO_PKG_BUILD_PKG?=$(GO_PKG)/... + +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_TMP_DIR:=$(GO_PKG_WORK_DIR)/tmp + +GO_PKG_BUILD_BIN_DIR:=$(GO_PKG_BUILD_DIR)/bin$(if \ + $(GO_HOST_TARGET_DIFFERENT),/$(GO_OS)_$(GO_ARCH)) + +GO_PKG_BUILD_DEPENDS_SRC:=$(STAGING_DIR)$(GO_PKG_PATH)/src + +# sstrip causes corrupted section header size +ifneq ($(CONFIG_USE_SSTRIP),) + ifneq ($(CONFIG_DEBUG),) + GO_PKG_STRIP_ARGS:=--strip-unneeded --remove-section=.comment --remove-section=.note + else + GO_PKG_STRIP_ARGS:=--strip-all + endif + STRIP:=$(TARGET_CROSS)strip $(GO_PKG_STRIP_ARGS) + RSTRIP= \ + export CROSS="$(TARGET_CROSS)" \ + $(if $(PKG_BUILD_ID),KEEP_BUILD_ID=1) \ + $(if $(CONFIG_KERNEL_KALLSYMS),NO_RENAME=1) \ + $(if $(CONFIG_KERNEL_PROFILING),KEEP_SYMBOLS=1); \ + NM="$(TARGET_CROSS)nm" \ + STRIP="$(STRIP)" \ + STRIP_KMOD="$(SCRIPT_DIR)/strip-kmod.sh" \ + PATCHELF="$(STAGING_DIR_HOST)/bin/patchelf" \ + $(SCRIPT_DIR)/rstrip.sh +endif + +define GoPackage/GoSubMenu + SUBMENU:=Go + SECTION:=lang + CATEGORY:=Languages +endef + +define GoPackage/Environment + GOOS=$(GO_OS) \ + GOARCH=$(GO_ARCH) \ + GO386=$(GO_386) \ + GOARM=$(GO_ARM) \ + GOMIPS=$(GO_MIPS) \ + CGO_ENABLED=1 \ + CGO_CFLAGS="$(filter-out $(GO_CFLAGS_TO_REMOVE),$(TARGET_CFLAGS))" \ + CGO_CPPFLAGS="$(TARGET_CPPFLAGS)" \ + CGO_CXXFLAGS="$(filter-out $(GO_CFLAGS_TO_REMOVE),$(TARGET_CXXFLAGS))" +endef + +# 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) $(GO_PKG_TMP_DIR) ; \ + \ + files=$$$$($(FIND) ./ \ + -type d -a \( -path './.git' -o -path './$(GO_PKG_WORK_DIR_NAME)' \) -prune -o \ + \! -type d -print | \ + sed 's|^\./||') ; \ + \ + if [ "$(GO_PKG_INSTALL_ALL)" != 1 ]; then \ + code=$$$$(echo "$$$$files" | grep '\.\(c\|cc\|go\|h\|hh\|proto\|s\)$$$$') ; \ + testdata=$$$$(echo "$$$$files" | grep '\(^\|/\)testdata/') ; \ + \ + for pattern in $(GO_PKG_INSTALL_EXTRA); do \ + extra=$$$$(echo "$$$$extra"; echo "$$$$files" | grep "$$$$pattern") ; \ + done ; \ + \ + files=$$$$(echo "$$$$code"; echo "$$$$testdata"; echo "$$$$extra") ; \ + files=$$$$(echo "$$$$files" | grep -v '^[[:space:]]*$$$$' | sort -u) ; \ + fi ; \ + \ + echo "Copying files from $(PKG_BUILD_DIR) into $(GO_PKG_BUILD_DIR)/src/$(GO_PKG)" ; \ + for file in $$$$files; do \ + echo $$$$file ; \ + dest=$(GO_PKG_BUILD_DIR)/src/$(GO_PKG)/$$$$file ; \ + mkdir -p $$$$(dirname $$$$dest) ; \ + $(CP) $$$$file $$$$dest ; \ + done ; \ + \ + 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/$(GO_PKG)) \ + echo "$(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 [ "$(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 ; \ + ) +endef + +define GoPackage/Build/Compile + ( \ + cd $(GO_PKG_BUILD_DIR) ; \ + export GOPATH=$(GO_PKG_BUILD_DIR) \ + GOCACHE=$(GO_PKG_CACHE_DIR) \ + GOTMPDIR=$(GO_PKG_TMP_DIR) \ + GOROOT_FINAL=$(GO_TARGET_ROOT) \ + CC=$(TARGET_CC) \ + CXX=$(TARGET_CXX) \ + $(call GoPackage/Environment) ; \ + \ + targets=$$$$(go list $(GO_PKG_BUILD_PKG)) ; \ + for pattern in $(GO_PKG_EXCLUDES); do \ + targets=$$$$(echo "$$$$targets" | grep -v "$$$$pattern") ; \ + done ; \ + \ + if [ "$(GO_PKG_GO_GENERATE)" = 1 ]; then \ + go generate -v $$$$targets ; \ + fi ; \ + \ + if [ "$(GO_PKG_SOURCE_ONLY)" != 1 ]; then \ + case $(GO_ARCH) in \ + arm) installsuffix="-installsuffix v$(GO_ARM)" ;; \ + mips|mipsle) installsuffix="-installsuffix $(GO_MIPS)" ;; \ + esac ; \ + trimpath="all=-trimpath=$(GO_PKG_BUILD_DIR)" ; \ + ldflags="all=-linkmode external -extldflags '$(TARGET_LDFLAGS)'" ; \ + go install $$$$installsuffix -gcflags "$$$$trimpath" -asmflags "$$$$trimpath" -ldflags "$$$$ldflags" -v $$$$targets ; \ + retval=$$$$? ; \ + \ + if [ "$$$$retval" -eq 0 ] && [ -z "$(call GoPackage/has_binaries)" ]; then \ + echo "No binaries were generated, consider adding GO_PKG_SOURCE_ONLY:=1 to Makefile" ; \ + fi ; \ + fi ; \ + exit $$$$retval ; \ + ) +endef + +define GoPackage/Build/InstallDev + $(call GoPackage/Package/Install/Src,$(1)) +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 +endef + +define GoPackage/Package/Install/Src + dir=$$$$(dirname $(GO_PKG)) ; \ + $(INSTALL_DIR) $(1)$(GO_PKG_PATH)/src/$$$$dir ; \ + $(CP) $(GO_PKG_BUILD_DIR)/src/$(GO_PKG) $(1)$(GO_PKG_PATH)/src/$$$$dir/ +endef + +define GoPackage/Package/Install + $(call GoPackage/Package/Install/Bin,$(1)) + $(call GoPackage/Package/Install/Src,$(1)) +endef + + +ifneq ($(GO_PKG),) + Build/Configure=$(call GoPackage/Build/Configure) + Build/Compile=$(call GoPackage/Build/Compile) + Build/InstallDev=$(call GoPackage/Build/InstallDev,$(1)) +endif + +define GoPackage + ifndef Package/$(1)/install + Package/$(1)/install=$$(call GoPackage/Package/Install,$$(1)) + endif +endef + +define GoBinPackage + ifndef Package/$(1)/install + Package/$(1)/install=$$(call GoPackage/Package/Install/Bin,$$(1)) + endif +endef + +define GoSrcPackage + ifndef Package/$(1)/install + Package/$(1)/install=$$(call GoPackage/Package/Install/Src,$$(1)) + endif +endef diff --git a/lang/golang/golang-values.mk b/lang/golang/golang-values.mk new file mode 100644 index 000000000..13763e364 --- /dev/null +++ b/lang/golang/golang-values.mk @@ -0,0 +1,72 @@ +# +# Copyright (C) 2018 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-version.mk + + +unexport \ + GOARCH GOBIN GOCACHE GODEBUG GOHOSTARCH GOOS GOPATH GORACE GOROOT GOTMPDIR GCCGO \ + CGO_ENABLED \ + CGO_CFLAGS CGO_CFLAGS_ALLOW CGO_CFLAGS_DISALLOW \ + CGO_CPPFLAGS CGO_CPPFLAGS_ALLOW CGO_CPPFLAGS_DISALLOW \ + CGO_CXXFLAGS CGO_CXXFLAGS_ALLOW CGO_CXXFLAGS_DISALLOW \ + CGO_FFLAGS CGO_FFLAGS_ALLOW CGO_FFLAGS_DISALLOW \ + CGO_LDFLAGS CGO_LDFLAGS_ALLOW CGO_LDFLAGS_DISALLOW \ + GOARM GO386 GOMIPS \ + GOROOT_FINAL GO_EXTLINK_ENABLED GIT_ALLOW_PROTOCOL \ + CC_FOR_TARGET CXX_FOR_TARGET GO_DISTFLAGS GO_GCFLAGS GO_LDFLAGS GOBUILDTIMELOGFILE GOROOT_BOOTSTRAP \ + BOOT_GO_GCFLAGS GOEXPERIMENT GOBOOTSTRAP_TOOLEXEC + # there are more magic environment variables to track down, but ain't nobody got time for that + +go_arch=$(subst \ + aarch64,arm64,$(subst \ + i386,386,$(subst \ + mipsel,mipsle,$(subst \ + mips64el,mips64le,$(subst \ + powerpc64,ppc64,$(subst \ + x86_64,amd64,$(1))))))) + +GO_OS:=linux +GO_ARCH:=$(call go_arch,$(ARCH)) +GO_OS_ARCH:=$(GO_OS)_$(GO_ARCH) + +GO_HOST_OS:=$(call tolower,$(HOST_OS)) +GO_HOST_ARCH:=$(call go_arch,$(subst \ + armv6l,arm,$(subst \ + armv7l,arm,$(subst \ + i486,i386,$(subst \ + i586,i386,$(subst \ + i686,i386,$(HOST_ARCH))))))) +GO_HOST_OS_ARCH:=$(GO_HOST_OS)_$(GO_HOST_ARCH) + +GO_HOST_TARGET_SAME:=$(if $(and $(findstring $(GO_OS_ARCH),$(GO_HOST_OS_ARCH)),$(findstring $(GO_HOST_OS_ARCH),$(GO_OS_ARCH))),1) +GO_HOST_TARGET_DIFFERENT:=$(if $(GO_HOST_TARGET_SAME),,1) + +# ensure binaries can run on older CPUs +GO_386:=387 + +GO_ARM:=$(if $(CONFIG_arm_v7),7,$(if $(CONFIG_arm_v6),6,$(if $(findstring $(GO_ARCH),arm),5,))) + +GO_MIPS:=$(if $(filter $(GO_ARCH),mips mipsle),$(if $(CONFIG_HAS_FPU),hardfloat,softfloat),) + +# -fno-plt: causes "unexpected GOT reloc for non-dynamic symbol" errors +# -mips32r2: conflicts with -march=mips32 set by go +GO_CFLAGS_TO_REMOVE:=$(if \ +$(filter $(GO_ARCH),386),-fno-plt,$(if \ +$(filter $(GO_ARCH),mips mipsle),-mips32r2,)) + +# mips64 / mips64el doesn't have softfloat support yet +# https://github.com/golang/go/issues/14635 +GO_ARCH_DEPENDS:=@(aarch64||arm||i386||i686||mips||mipsel||powerpc64||x86_64) + +GO_TARGET_PREFIX:=/usr +GO_TARGET_VERSION_ID:=$(GO_VERSION_MAJOR_MINOR) +GO_TARGET_ROOT:=$(GO_TARGET_PREFIX)/lib/go-$(GO_TARGET_VERSION_ID) diff --git a/lang/golang/golang-version.mk b/lang/golang/golang-version.mk new file mode 100644 index 000000000..01b429508 --- /dev/null +++ b/lang/golang/golang-version.mk @@ -0,0 +1,14 @@ +# +# Copyright (C) 2018 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 + + +GO_VERSION_MAJOR_MINOR:=1.10 +GO_VERSION_PATCH:= diff --git a/lang/golang/golang/Makefile b/lang/golang/golang/Makefile new file mode 100644 index 000000000..081701267 --- /dev/null +++ b/lang/golang/golang/Makefile @@ -0,0 +1,277 @@ +# +# Copyright (C) 2018 Jeffery To +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include ../golang-version.mk + +PKG_NAME:=golang +PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH)) +PKG_RELEASE:=1 + +PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz +PKG_SOURCE_URL:=https://golang.org/dl/ +PKG_HASH:=f3de49289405fda5fd1483a8fe6bd2fa5469e005fd567df64485c4fa000c7f24 + +PKG_LICENSE:=BSD-3-Clause +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Jeffery To + +PKG_BUILD_DEPENDS:=golang/host +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_TMP_DIR:=$(PKG_GO_WORK_DIR)/tmp + +HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/go-$(PKG_VERSION) +HOST_BUILD_PARALLEL:=1 + +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_arm \ + darwin_386 darwin_amd64 darwin_arm darwin_arm64 \ + dragonfly_amd64 \ + freebsd_386 freebsd_amd64 freebsd_arm \ + linux_386 linux_amd64 linux_arm linux_arm64 \ + netbsd_386 netbsd_amd64 netbsd_arm \ + openbsd_386 openbsd_amd64 openbsd_arm \ + plan9_386 plan9_amd64 \ + solaris_amd64 \ + windows_386 windows_amd64 \ + \ + linux_ppc64 linux_ppc64le linux_mips linux_mipsle linux_mips64 linux_mips64le + +BOOTSTRAP_SOURCE_PROTO:=git +BOOTSTRAP_SOURCE_URL:=https://go.googlesource.com/go +BOOTSTRAP_SOURCE_VERSION:=4d5426a570c2820c5894a61b52e3dc147e4e7925 +BOOTSTRAP_SOURCE_DATE:=20170926 +BOOTSTRAP_MIRROR_HASH:=a3e26ee7c96486c841d29cbea3bf548ce2d999b9235275091cbe60ae6efa4cb1 + +BOOTSTRAP_VERSION:=$(BOOTSTRAP_SOURCE_DATE)-$(call version_abbrev,$(BOOTSTRAP_SOURCE_VERSION)) +BOOTSTRAP_SOURCE_SUBDIR:=golang-bootstrap-$(BOOTSTRAP_VERSION) +BOOTSTRAP_SOURCE:=$(BOOTSTRAP_SOURCE_SUBDIR).tar.xz + +BOOTSTRAP_BUILD_DIR:=$(HOST_BUILD_DIR)/.go_bootstrap + +BOOTSTRAP_GO_VALID_OS_ARCH:= \ + darwin_386 darwin_amd64 \ + dragonfly_386 dragonfly_amd64 \ + freebsd_386 freebsd_amd64 freebsd_arm \ + linux_386 linux_amd64 linux_arm \ + netbsd_386 netbsd_amd64 netbsd_arm \ + openbsd_386 openbsd_amd64 \ + plan9_386 plan9_amd64 \ + solaris_amd64 \ + windows_386 windows_amd64 + +include $(INCLUDE_DIR)/host-build.mk +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 -xJf $(DL_DIR)/$(BOOTSTRAP_SOURCE) + +# don't strip ELF executables in test data (and go itself) +RSTRIP:=: +STRIP:=: + +define Package/golang/Default +$(call GoPackage/GoSubMenu) + TITLE:=Go programming language + URL:=https://golang.org/ + DEPENDS:=$(GO_ARCH_DEPENDS) +endef + +define Package/golang/Default/description +The Go programming language is an open source project to make +programmers more productive. + +Go is expressive, concise, clean, and efficient. Its concurrency +mechanisms make it easy to write programs that get the most out of +multicore and networked machines, while its novel type system enables +flexible and modular program construction. Go compiles quickly to +machine code yet has the convenience of garbage collection and the power +of run-time reflection. It's a fast, statically typed, compiled language +that feels like a dynamically typed, interpreted language. +endef + +# go tool requires source present: +# https://github.com/golang/go/issues/4635 +define Package/golang +$(call Package/golang/Default) + TITLE+= (compiler) + DEPENDS+= +golang-src +endef + +define Package/golang/description +$(call Package/golang/Default/description) + +This package provides an assembler, compiler, linker, and compiled +libraries for the Go programming language. +endef + +define Package/golang-doc +$(call Package/golang/Default) + TITLE+= (documentation) +endef + +define Package/golang-doc/description +$(call Package/golang/Default/description) + +This package provides the documentation for the Go programming language. +endef + +define Package/golang-src +$(call Package/golang/Default) + TITLE+= (source files) +endef + +define Package/golang-src/description +$(call Package/golang/Default/description) + +This package provides the Go programming language source files needed +for cross-compilation. +endef + +define Download/golang-bootstrap + FILE:=$(BOOTSTRAP_SOURCE) + URL:=$(BOOTSTRAP_SOURCE_URL) + SUBDIR:=$(BOOTSTRAP_SOURCE_SUBDIR) + PROTO:=$(BOOTSTRAP_SOURCE_PROTO) + MIRROR_HASH:=$(BOOTSTRAP_MIRROR_HASH) + VERSION:=$(BOOTSTRAP_SOURCE_VERSION) +endef +$(eval $(call Download,golang-bootstrap)) + +$(eval $(call GoCompiler/AddProfile,Bootstrap,$(BOOTSTRAP_BUILD_DIR),,bootstrap,$(GO_HOST_OS_ARCH))) +$(eval $(call GoCompiler/AddProfile,Host,$(HOST_BUILD_DIR),$(HOST_GO_PREFIX),$(HOST_GO_VERSION_ID),$(GO_HOST_OS_ARCH))) +$(eval $(call GoCompiler/AddProfile,Package,$(PKG_BUILD_DIR),$(GO_TARGET_PREFIX),$(GO_TARGET_VERSION_ID),$(GO_OS_ARCH))) + +define Host/Prepare + $(call Host/Prepare/Default) + mkdir -p $(BOOTSTRAP_BUILD_DIR) + $(BOOTSTRAP_UNPACK) +endef + +define Host/Compile + $(call GoCompiler/Bootstrap/CheckHost,$(BOOTSTRAP_GO_VALID_OS_ARCH)) + $(call GoCompiler/Host/CheckHost,$(HOST_GO_VALID_OS_ARCH)) + + $(call GoCompiler/Bootstrap/Make, \ + CC=$(HOSTCC_NOCACHE) \ + CXX=$(HOSTCXX_NOCACHE) \ + ) + + $(call GoCompiler/Host/Make, \ + GOROOT_BOOTSTRAP=$(BOOTSTRAP_BUILD_DIR) \ + CC=$(HOSTCC_NOCACHE) \ + CXX=$(HOSTCXX_NOCACHE) \ + ) +endef + +# if host and target os/arch are the same, +# when go compiles a program, it will use the host std lib +# so remove it now and force go to rebuild std for target later +define Host/Install + $(call GoCompiler/Host/Install/Bin,) + $(call GoCompiler/Host/Install/Src,) + + $(call GoCompiler/Host/Install/BinLinks,) + + rm -rf $(HOST_GO_ROOT)/pkg/$(GO_HOST_OS_ARCH) + + $(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 + + $(call GoCompiler/Host/Uninstall/BinLinks,) + + $(call GoCompiler/Host/Uninstall,) +endef + +define Build/Compile + mkdir -p \ + $(PKG_GO_HOST_CACHE_DIR) \ + $(PKG_GO_TARGET_CACHE_DIR) \ + $(PKG_GO_TMP_DIR) + + @echo "Building target Go first stage" + + $(call GoCompiler/Package/Make, \ + GOROOT_BOOTSTRAP=$(HOST_GO_ROOT) \ + GOCACHE=$(PKG_GO_HOST_CACHE_DIR) \ + GOTMPDIR=$(PKG_GO_TMP_DIR) \ + 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 \ + ) + + @echo "Building target Go second stage" + + ( \ + cd $(PKG_BUILD_DIR)/bin ; \ + $(CP) go go-host ; \ + GOROOT_FINAL=$(GO_TARGET_ROOT) \ + GOCACHE=$(PKG_GO_TARGET_CACHE_DIR) \ + GOTMPDIR=$(PKG_GO_TMP_DIR) \ + 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 \ + $(call GoPackage/Environment) \ + ./go-host install -a -v std cmd ; \ + retval=$$$$? ; \ + rm -f go-host ; \ + exit $$$$retval ; \ + ) +endef + +define Package/golang/install + $(call GoCompiler/Package/Install/Bin,$(1)$(GO_TARGET_PREFIX)) + $(call GoCompiler/Package/Install/BinLinks,$(1)$(GO_TARGET_PREFIX)) +endef + +define Package/golang-doc/install + $(call GoCompiler/Package/Install/Doc,$(1)$(GO_TARGET_PREFIX)) +endef + +define Package/golang-src/install + $(call GoCompiler/Package/Install/Src,$(1)$(GO_TARGET_PREFIX)) +endef + +# src/debug contains ELF executables as test data +# and they reference these libraries +# we need to call this in Package/$(1)/extra_provides +# to pass CheckDependencies in include/package-ipkg.mk +define Package/golang-src/extra_provides + echo 'libc.so.6' +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,golang)) +$(eval $(call BuildPackage,golang-doc)) +$(eval $(call BuildPackage,golang-src)) diff --git a/lang/golang/golang/files/go-gcc-helper b/lang/golang/golang/files/go-gcc-helper new file mode 100644 index 000000000..3d3f8935d --- /dev/null +++ b/lang/golang/golang/files/go-gcc-helper @@ -0,0 +1,23 @@ +#!/bin/sh + +me=go-gcc-helper +name=$(basename $0) + +case $name in +gcc) + cmd=$GO_GCC_HELPER_CC + ;; +g++) + cmd=$GO_GCC_HELPER_CXX + ;; +*) + echo "$me: unknown command \"$name\"" + exit 1 + ;; +esac + +export PATH="$GO_GCC_HELPER_PATH" + +echo "$me: running $cmd $@" + +$cmd "$@"