From 2d22a629f5494b8c032e0b56c639dd380f6202fb Mon Sep 17 00:00:00 2001 From: Jeffery To Date: Wed, 26 Aug 2020 16:17:05 +0800 Subject: [PATCH] golang: Move package scripts into golang-build.sh This also adds GO_PKG_INSTALL_BIN_PATH which determines the path where binaries are installed by GoPackage/Package/Install/Bin (this was previously hard-coded to /usr/bin). Signed-off-by: Jeffery To --- lang/golang/golang-build.sh | 156 +++++++++++++++++++++++++++++ lang/golang/golang-package.mk | 178 +++++++++------------------------- lang/golang/golang-values.mk | 4 +- 3 files changed, 206 insertions(+), 132 deletions(-) diff --git a/lang/golang/golang-build.sh b/lang/golang/golang-build.sh index d39949dca..5e40436bb 100644 --- a/lang/golang/golang-build.sh +++ b/lang/golang/golang-build.sh @@ -1,5 +1,8 @@ #!/bin/sh +nl=" +" + log() { # shellcheck disable=SC2039 local IFS=" " @@ -12,6 +15,147 @@ log_error() { 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 @@ -38,6 +182,18 @@ command="$1" shift 1 case "$command" in + configure) + configure + ;; + build) + build "$@" + ;; + install_bin) + install_bin "$@" + ;; + install_src) + install_src "$@" + ;; cache_cleanup) cache_cleanup ;; diff --git a/lang/golang/golang-package.mk b/lang/golang/golang-package.mk index b3d01857f..8c62e6399 100644 --- a/lang/golang/golang-package.mk +++ b/lang/golang/golang-package.mk @@ -111,22 +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_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) @@ -164,6 +171,21 @@ 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)" \ @@ -185,12 +207,10 @@ GO_PKG_BUILD_VARS= \ 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_LDFLAGS= \ -buildid '$(SOURCE_DATE_EPOCH)' \ -linkmode external \ @@ -212,127 +232,18 @@ GO_PKG_INSTALL_ARGS= \ $(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_BUILD_CACHE_DIR)" "$(GO_MOD_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) ; \ - if [ -f "$(PKG_BUILD_DIR)/go.mod" ] ; then \ - modargs="$(GO_MOD_ARGS)" ; \ - fi ; \ - \ - echo "Finding targets" ; \ - targets="$$$$(go list $$$$modargs $(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) $$$$modargs $(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 ; \ - \ - if [ "$$$$retval" -ne 0 ]; then \ - $(call Go/CacheCleanup) ; \ - fi ; \ - 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 @@ -340,20 +251,21 @@ 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 @@ -385,7 +297,11 @@ 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 596270caf..7429ae0de 100644 --- a/lang/golang/golang-values.mk +++ b/lang/golang/golang-values.mk @@ -231,7 +231,9 @@ GO_MOD_ARGS= \ GO_GENERAL_BUILD_CONFIG_VARS= \ CONFIG_GOLANG_MOD_CACHE_WORLD_READABLE="$(CONFIG_GOLANG_MOD_CACHE_WORLD_READABLE)" \ - GO_MOD_CACHE_DIR="$(GO_MOD_CACHE_DIR)" + 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) \