From 319fcf52fc5eaa3a83c4a152405910a5b516f89a Mon Sep 17 00:00:00 2001
From: Chris Evich <cevich@redhat.com>
Date: Thu, 9 Sep 2021 13:46:21 -0400
Subject: Cross-build release-archives w/ arch in filename

Fixes #11417

Cross-building the podman-remote documentation requires a functional
native architecture executable.  However `make` only deals with
files/timestamps, it doesn't understand if an existing binary will
function on the system or not.  This makes building cross-platform
releases incredibly accident-prone and fragile.

A practical way to deal with this, is via multiple conditional (nested)
`make` calls along with careful manipulation of `$GOOS` and `$GOARCH`.
Also, when cross-building releases be kind to humans and cleanup
any non-native binaries left behind.

Update the `Alt Arch. Cross` Cirrus-CI task to build release archives
for all Linux architectures supported by golang and podman.  Update
the `OSX Cross` task to additionally build for the M1 (arm64)
architecture.

Finally, update the release process documentation to reflect the
new locations (Cirrus-CI task names) for the release archives.  Include
a note about additional manual work being required to produce the
signed `.dmg` file for MacOS.

Signed-off-by: Chris Evich <cevich@redhat.com>
---
 .cirrus.yml              | 10 +++--
 Makefile                 | 98 +++++++++++++++++++++++++++++++++---------------
 RELEASE_PROCESS.md       | 18 ++++++---
 contrib/cirrus/runner.sh | 22 +++++++++--
 4 files changed, 107 insertions(+), 41 deletions(-)

diff --git a/.cirrus.yml b/.cirrus.yml
index 581aaaa7b..968854771 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -359,11 +359,15 @@ osx_alt_build_task:
         TEST_FLAVOR: "altbuild"
         ALT_NAME: 'OSX Cross'
     osx_instance:
-        image: 'catalina-base'
-    script:
+        image: 'big-sur-base'
+    setup_script:
         - brew install go
         - brew install go-md2man
-        - make podman-remote-release-darwin.zip
+        - go version
+    build_amd64_script:
+        - make podman-remote-release-darwin_amd64.zip
+    build_arm64_script:
+        - make podman-remote-release-darwin_arm64.zip GOARCH=arm64
     always: *binary_artifacts
 
 
diff --git a/Makefile b/Makefile
index 12889c1c5..37396a4a6 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,7 @@
 export GOPROXY=https://proxy.golang.org
 
 GO ?= go
+GOCMD = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO)
 COVERAGE_PATH ?= .coverage
 DESTDIR ?=
 EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-main} HEAD)
@@ -150,7 +151,11 @@ err_if_empty = $(if $(strip $($(1))),$(strip $($(1))),$(error Required variable
 # Podman does not work w/o CGO_ENABLED, except in some very specific cases
 CGO_ENABLED ?= 1
 # Default to the native OS type and architecture unless otherwise specified
-GOOS ?= $(shell $(GO) env GOOS)
+NATIVE_GOOS := $(shell env -u GOOS $(GO) env GOOS)
+GOOS ?= $(NATIVE_GOOS)
+# Default to the native architecture type
+NATIVE_GOARCH := $(shell env -u GOARCH $(GO) env GOARCH)
+GOARCH ?= $(NATIVE_GOARCH)
 ifeq ($(call err_if_empty,GOOS),windows)
 BINSFX := .exe
 SRCBINDIR := bin/windows
@@ -162,7 +167,7 @@ BINSFX := -remote
 SRCBINDIR := bin
 endif
 # Necessary for nested-$(MAKE) calls and docs/remote-docs.sh
-export GOOS CGO_ENABLED BINSFX SRCBINDIR
+export GOOS GOARCH CGO_ENABLED BINSFX SRCBINDIR
 
 define go-get
 	env GO111MODULE=off \
@@ -239,11 +244,11 @@ gofmt: ## Verify the source code gofmt
 
 .PHONY: test/checkseccomp/checkseccomp
 test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
-	$(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
+	$(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
 
 .PHONY: test/testvol/testvol
 test/testvol/testvol: .gopathok $(wildcard test/testvol/*.go)
-	$(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol
+	$(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol
 
 .PHONY: volume-plugin-test-image
 volume-plugin-test-img:
@@ -251,7 +256,7 @@ volume-plugin-test-img:
 
 .PHONY: test/goecho/goecho
 test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go)
-	$(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
+	$(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
 
 test/version/version: .gopathok version/version.go
 	$(GO) build -o $@ ./test/version/
@@ -292,8 +297,7 @@ ifeq (,$(findstring systemd,$(BUILDTAGS)))
 		Install libsystemd on Ubuntu or systemd-devel on rpm based \
 		distro for journald support."
 endif
-	CGO_ENABLED=$(CGO_ENABLED) \
-		$(GO) build \
+	$(GOCMD) build \
 		$(BUILDFLAGS) \
 		-ldflags '$(LDFLAGS_PODMAN)' \
 		-tags "$(BUILDTAGS)" \
@@ -304,18 +308,14 @@ $(SRCBINDIR):
 	mkdir -p $(SRCBINDIR)
 
 $(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum
-	CGO_ENABLED=$(CGO_ENABLED) \
-		GOOS=$(GOOS) \
-		$(GO) build \
+	$(GOCMD) build \
 		$(BUILDFLAGS) \
 		-ldflags '$(LDFLAGS_PODMAN)' \
 		-tags "${REMOTETAGS}" \
 		-o $@ ./cmd/podman
 
 $(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum
-	CGO_ENABLED=0 \
-		GOOS=$(GOOS) \
-		$(GO) build \
+	$(GOCMD) build \
 		$(BUILDFLAGS) \
 		-ldflags '$(LDFLAGS_PODMAN_STATIC)' \
 		-tags "${REMOTETAGS}" \
@@ -333,6 +333,7 @@ podman-remote-linux: ## Build podman-remote for Linux
 	$(MAKE) \
 		CGO_ENABLED=0 \
 		GOOS=linux \
+		GOARCH=$(GOARCH) \
 		bin/podman-remote
 
 PHONY: podman-remote-static
@@ -350,6 +351,7 @@ podman-remote-darwin: ## Build podman-remote for macOS
 	$(MAKE) \
 		CGO_ENABLED=0 \
 		GOOS=darwin \
+		GOARCH=$(GOARCH) \
 		bin/darwin/podman
 
 ###
@@ -359,7 +361,7 @@ podman-remote-darwin: ## Build podman-remote for macOS
 .PHONY: generate-bindings
 generate-bindings:
 ifneq ($(GOOS),darwin)
-	GO111MODULE=off $(GO) generate ./pkg/bindings/... ;
+	GO111MODULE=off $(GOCMD) generate ./pkg/bindings/... ;
 endif
 
 # DO NOT USE: use local-cross instead
@@ -444,12 +446,14 @@ docs: $(MANPAGES) ## Generate documentation
 
 # docs/remote-docs.sh requires a locally executable 'podman-remote' binary
 # in addition to the target-archetecture binary (if any).
-install-podman-remote-%-docs: podman-remote-$(shell env -i HOME=$$HOME PATH=$$PATH go env GOOS) docs $(MANPAGES)
+podman-remote-%-docs: podman-remote-$(NATIVE_GOOS)
+	$(eval GOOS := $*)
+	$(MAKE) docs $(MANPAGES)
 	rm -rf docs/build/remote
 	mkdir -p docs/build/remote
 	ln -sf $(CURDIR)/docs/source/markdown/links docs/build/man/
 	docs/remote-docs.sh \
-		$* \
+		$(GOOS) \
 		docs/build/remote/$* \
 		$(if $(findstring windows,$*),docs/source/markdown,docs/build/man)
 
@@ -602,35 +606,65 @@ tests-expect-exit:
 ### Release/Packaging targets
 ###
 
-podman-release.tar.gz: test/version/version binaries docs  ## Build all binaries, docs., and installation tree, into a tarball.
+.PHONY: podman-release
+podman-release: podman-release-$(GOARCH).tar.gz  # Build all Linux binaries for $GOARCH, docs., and installation tree, into a tarball.
+
+# The following two targets are nuanced and complex:
+# Cross-building the podman-remote documentation requires a functional
+# native architecture executable.  However `make` only deals with
+# files/timestamps, it doesn't understand if an existing binary will
+# function on the system or not.  This makes building cross-platform
+# releases incredibly accident-prone and fragile.  The only practical
+# way to deal with this, is via multiple conditional (nested) `make`
+# calls along with careful manipulation of `$GOOS` and `$GOARCH`.
+
+podman-release-%.tar.gz: test/version/version
 	$(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX))
 	$(eval SUBDIR := podman-v$(call err_if_empty,RELEASE_NUMBER))
+	$(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr")
+	$(eval GOARCH := $*)
 	mkdir -p "$(TMPDIR)/$(SUBDIR)"
-	$(MAKE) install.bin install.remote install.man \
-		install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr"
+	$(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \
+		clean-binaries docs podman-remote-$(GOOS)-docs
+	if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \
+		$(MAKE) CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) \
+			BUILDTAGS="$(BUILDTAGS_CROSS)" clean-binaries binaries; \
+	else \
+		$(MAKE) GOOS=$(GOOS) GOARCH=$(GOARCH) binaries; \
+	fi
+	$(MAKE) $(_DSTARGS) install.bin-nobuild install.remote-nobuild install.man install.systemd
 	tar -czvf $@ --xattrs -C "$(TMPDIR)" "./$(SUBDIR)"
+	if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
 	-rm -rf "$(TMPDIR)"
 
-podman-remote-release-%.zip: test/version/version podman-remote-% install-podman-remote-%-docs  ## Build podman-remote for GOOS=%, docs., and installation zip.
+podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$GOOS_$GOARCH, and docs. into an installation zip.
 	$(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX))
 	$(eval SUBDIR := podman-$(call err_if_empty,RELEASE_NUMBER))
+	$(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr")
+	$(eval GOOS := $(firstword $(subst _, ,$*)))
+	$(eval GOARCH := $(lastword $(subst _, ,$*)))
+	$(eval _GOPLAT := GOOS=$(call err_if_empty,GOOS) GOARCH=$(call err_if_empty,GOARCH))
 	mkdir -p "$(TMPDIR)/$(SUBDIR)"
-	$(MAKE) \
-		GOOS=$* \
-		DESTDIR=$(TMPDIR)/ \
-		BINDIR=$(SUBDIR) \
-		SELINUXOPT="" \
-		install.remote-nobuild
-	cp -r ./docs/build/remote/$* "$(TMPDIR)/$(SUBDIR)/docs/"
+	$(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \
+		clean-binaries podman-remote-$(GOOS)-docs
+	if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \
+		$(MAKE) CGO_ENABLED=0 $(GOPLAT) BUILDTAGS="$(BUILDTAGS_CROSS)" \
+			clean-binaries podman-remote-$(GOOS); \
+	else \
+		$(MAKE) $(GOPLAT) podman-remote-$(GOOS); \
+	fi
+	cp -r ./docs/build/remote/$(GOOS) "$(TMPDIR)/$(SUBDIR)/docs/"
 	cp ./contrib/remote/containers.conf "$(TMPDIR)/$(SUBDIR)/"
+	$(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote-nobuild
 	cd "$(TMPDIR)" && \
 		zip --recurse-paths "$(CURDIR)/$@" "./"
+	if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
 	-rm -rf "$(TMPDIR)"
 
 .PHONY: podman.msi
 podman.msi: test/version/version  ## Build podman-remote, package for installation on Windows
 	$(MAKE) podman-v$(RELEASE_NUMBER).msi
-podman-v$(RELEASE_NUMBER).msi: podman-remote-windows install-podman-remote-windows-docs
+podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs
 	$(eval DOCFILE := docs/build/remote/windows)
 	find $(DOCFILE) -print | \
 		wixl-heat --var var.ManSourceDir --component-group ManFiles \
@@ -821,8 +855,13 @@ uninstall:
 	rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.socket
 	rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.service
 
+.PHONY: clean-binaries
+clean-binaries: ## Remove platform/architecture specific binary files
+	rm -rf \
+		bin \
+
 .PHONY: clean
-clean: ## Clean all make artifacts
+clean: clean-binaries ## Clean all make artifacts
 	rm -rf \
 		.gopathok \
 		_output \
@@ -830,7 +869,6 @@ clean: ## Clean all make artifacts
 		$(wildcard podman-remote*.zip) \
 		$(wildcard podman_tmp_*) \
 		$(wildcard podman*.tar.gz) \
-		bin \
 		build \
 		test/checkseccomp/checkseccomp \
 		test/goecho/goecho \
diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md
index bdf8aca88..32d4c039e 100644
--- a/RELEASE_PROCESS.md
+++ b/RELEASE_PROCESS.md
@@ -234,16 +234,24 @@ spelled with complete minutiae.
 
    1. Return to the Cirrus-CI Build page for the new release tag, confirm
       (or wait for) it to complete, re-running any failed tasks as appropriate.
-   1. For anything other than an RC, download the new release artifacts
-      (the binaries which were actually tested).  Visit each of the
-      "Build for ...", "Static Build", and "... Cross" tasks.
-   1. Under the "Artifacts" section of each task, click the "gosrc" item,
+   1. For anything other than an RC, download the new release artifacts from CI
+      (the binaries which were actually tested).  The items are
+      located under the *checks* tab in github for:
+
+      * `Cirrus CI / Alt Arch. Cross` - tarball for each architecture
+      * `Cirrus CI / OSX Cross` - two zip files (amd64 and arm64)
+      * `Cirrus CI / Windows Cross` - an `msi` file
+      * `Cirrus CI / Static Build` - the `bin/podman-remote` file
+
+      Under the "Artifacts" section of each task, click the "gosrc" link,
       find and download the release archive (`zip`, `tar.gz` or `.msi`).
       Save the the archive with a meaningful name, for example
       `podman-v3.0.0.msi`.
    1. For the "Static Build" task, find the compiled `podman` and `podman-remote`
-      binaries under the "binary", "bin" links.  Tar these files as
+      binaries under the "binary", then "bin" links.  Tar these files as
       `podman-static.tar.gz`.
+   1. The `podman-vX.Y.Z.dmg` file is produced manually by someone in
+      posession of a developer signing key.
    1. In the directory where you downloaded the archives, run
       `sha256sum *.tar.gz *.zip *.msi > shasums` to generate SHA sums.
    1. Go to `https://github.com/containers/podman/releases/tag/vX.Y.Z` and
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index c1972b90f..128398c38 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -205,10 +205,12 @@ function _run_build() {
     # Ensure always start from clean-slate with all vendor modules downloaded
     make clean
     make vendor
-    make podman-release.tar.gz  # includes podman, podman-remote, and docs
+    make podman-release  # includes podman, podman-remote, and docs
 }
 
 function _run_altbuild() {
+    local -a arches
+    local arch
     req_env_vars ALT_NAME
     # Defined in .cirrus.yml
     # shellcheck disable=SC2154
@@ -221,7 +223,7 @@ function _run_altbuild() {
             make build-all-new-commits GIT_BASE_BRANCH=origin/$DEST_BRANCH
             ;;
         *Windows*)
-            make podman-remote-release-windows.zip
+            make podman-remote-release-windows_amd64.zip
             make podman.msi
             ;;
         *Without*)
@@ -232,7 +234,21 @@ function _run_altbuild() {
             rpmbuild --rebuild ./podman-*.src.rpm
             ;;
         Alt*Cross)
-            make local-cross
+            arches=(\
+                amd64
+                ppc64le
+                arm
+                arm64
+                386
+                s390x
+                mips
+                mipsle
+                mips64
+                mips64le)
+            for arch in "${arches[@]}"; do
+                msg "Building release archive for $arch"
+                make podman-release-${arch}.tar.gz GOARCH=$arch
+            done
             ;;
         *Static*)
             req_env_vars CTR_FQIN
-- 
cgit v1.2.3-54-g00ecf