diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8bd2e8da..27677e58 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -30,3 +30,42 @@ jobs: run: make test - name: Verify run: make verify + + kind-linux-arm64: + # Hosted on Equinix + # Docs: https://github.com/fluxcd/flux2/tree/main/.github/runners + runs-on: [self-hosted, Linux, ARM64, equinix] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + - name: Run tests + run: make test + - name: Verify + run: make verify + + # Runs 'make test' on macos-10.15 to assure development environment for + # contributors using MacOS. + darwin-amd64: + runs-on: macos-10.15 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + - name: Restore Go cache + uses: actions/cache@v1 + with: + path: /home/runner/work/_temp/_github_home/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Run tests + run: make test + - name: Verify + run: make verify diff --git a/.gitignore b/.gitignore index d70c9445..1cb15be6 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,4 @@ testbin *~ # Exclude all libgit2 related files -hack/libgit2/ build/ diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index f7599bb6..20d5ada8 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -477,30 +477,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---------------------------------------------------------------------- -The regex library (deps/regex/) is licensed under the GNU LGPL -(available at the end of this file). +The bundled PCRE implementation (deps/pcre/) is licensed under the BSD +license. -Definitions for data structures and routines for the regular -expression library. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: -Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006,2008 -Free Software Foundation, Inc. -This file is part of the GNU C Library. + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. + * Neither the name of the University of Cambridge nor the name of Google + Inc. nor the names of their contributors may be used to endorse or + promote products derived from this software without specific prior + written permission. -You should have received a copy of the GNU Lesser General Public -License along with the GNU C Library; if not, write to the Free -Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- diff --git a/Dockerfile b/Dockerfile index f8ef2efe..02d61a4f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,57 +3,97 @@ ARG GO_VERSION=1.17 ARG XX_VERSION=1.1.0 ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2 -ARG LIBGIT2_TAG=libgit2-1.1.1-4 +ARG LIBGIT2_TAG=libgit2-1.1.1-6 -FROM --platform=linux/amd64 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-amd64 -FROM --platform=linux/arm64 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-arm64 -FROM --platform=linux/arm/v7 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-armv7 +FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} AS libgit2-libs -FROM --platform=$BUILDPLATFORM build-$TARGETARCH$TARGETVARIANT AS build +FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx + +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable + +FROM gostable AS go-linux + +# Build-base consists of build platform dependencies and xx. +# These will be used at current arch to yield execute the cross compilations. +FROM go-${TARGETOS} AS build-base + +RUN apk add --no-cache clang lld pkgconfig + +COPY --from=xx / / + +# build-go-mod can still be cached at build platform architecture. +FROM build-base as build-go-mod # Configure workspace WORKDIR /workspace -# This has its own go.mod, which needs to be present so go mod -# download works. +# Copy api submodule COPY api/ api/ # Copy modules manifests COPY go.mod go.mod COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer +# Cache modules RUN go mod download -RUN apk add clang lld pkgconfig ca-certificates +# The musl-tool-chain layer is an adhoc solution +# for the problem in which xx gets confused during compilation +# and a) looks for gold linker and then b) cannot find musl's dynamic linker. +FROM --platform=$BUILDPLATFORM alpine as musl-tool-chain + +COPY --from=xx / / + +RUN apk add bash curl tar + +WORKDIR /workspace +COPY hack/download-musl.sh . -ENV CGO_ENABLED=1 ARG TARGETPLATFORM +ARG TARGETARCH +RUN ROOT_DIR="$(pwd)" TARGET_ARCH="$(xx-info alpine-arch)" ENV_FILE=true \ + ./download-musl.sh -RUN xx-apk add --no-cache \ - musl-dev gcc lld binutils-gold +# Build stage install per target platform +# dependency and effectively cross compile the application. +FROM build-go-mod as build + +ARG TARGETPLATFORM + +COPY --from=libgit2-libs /usr/local/ /usr/local/ + +# Some dependencies have to installed +# for the target platform: https://github.com/tonistiigi/xx#go--cgo +RUN xx-apk add musl-dev gcc lld + +WORKDIR /workspace + +# Copy source code +COPY main.go main.go +COPY controllers/ controllers/ +COPY pkg/ pkg/ + +COPY --from=musl-tool-chain /workspace/build /workspace/build + +ARG TARGETPLATFORM +ARG TARGETARCH +ENV CGO_ENABLED=1 # Performance related changes: # - Use read-only bind instead of copying go source files. # - Cache go packages. -RUN --mount=target=. \ - --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg \ - export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \ +RUN export $(cat build/musl/$(xx-info alpine-arch).env | xargs) && \ + export LIBRARY_PATH="/usr/local/$(xx-info triple):/usr/local/$(xx-info triple)/lib64" && \ export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \ - export FLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2)" && \ - CGO_LDFLAGS="${FLAGS} -static" \ - xx-go build \ + export CGO_LDFLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2) -static" && \ + GOARCH=$TARGETARCH go build \ -ldflags "-s -w" \ -tags 'netgo,osusergo,static_build' \ - -o /image-automation-controller -trimpath \ - main.go + -o /image-automation-controller -trimpath main.go; # Ensure that the binary was cross-compiled correctly to the target platform. RUN xx-verify --static /image-automation-controller - FROM alpine:3.15 ARG TARGETPLATFORM diff --git a/Makefile b/Makefile index d1e6e1da..4d50d240 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ CRD_OPTIONS ?= crd:crdVersions=v1 # Base image used to build the Go binary LIBGIT2_IMG ?= ghcr.io/fluxcd/golang-with-libgit2 -LIBGIT2_TAG ?= libgit2-1.1.1-4 +LIBGIT2_TAG ?= libgit2-1.1.1-6 # Allows for defining additional Docker buildx arguments, # e.g. '--push'. @@ -29,30 +29,72 @@ REFLECTOR_VER ?= v0.16.0 # Repository root based on Git metadata. REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel) +BUILD_DIR := $(REPOSITORY_ROOT)/build -LIBGIT2_PATH := $(REPOSITORY_ROOT)/build/libgit2 +# Other dependency versions +ENVTEST_BIN_VERSION ?= 1.19.2 + +# Caches libgit2 versions per tag, "forcing" rebuild only when needed. +LIBGIT2_PATH := $(BUILD_DIR)/libgit2/$(LIBGIT2_TAG) LIBGIT2_LIB_PATH := $(LIBGIT2_PATH)/lib LIBGIT2_LIB64_PATH := $(LIBGIT2_PATH)/lib64 LIBGIT2 := $(LIBGIT2_LIB_PATH)/libgit2.a +MUSL-CC = export CGO_ENABLED=1 -export LIBRARY_PATH=$(LIBGIT2_LIB_PATH):$(LIBGIT2_LIB64_PATH) -export PKG_CONFIG_PATH=$(LIBGIT2_LIB_PATH)/pkgconfig:$(LIBGIT2_LIB64_PATH)/pkgconfig -export CGO_CFLAGS=-I$(LIBGIT2_PATH)/include +export PKG_CONFIG_PATH=$(LIBGIT2_LIB_PATH)/pkgconfig +export LIBRARY_PATH=$(LIBGIT2_LIB_PATH) +export CGO_CFLAGS=-I$(LIBGIT2_PATH)/include -I$(LIBGIT2_PATH)/include/openssl + +# The pkg-config command will yield warning messages until libgit2 is downloaded. ifeq ($(shell uname -s),Darwin) - export CGO_LDFLAGS=-L$(LIBGIT2_LIB_PATH) -lssh2 -lssl -lcrypto -lgit2 +export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2 2>/dev/null) +GO_STATIC_FLAGS=-ldflags "-s -w" -tags 'netgo,osusergo,static_build' +else +export PKG_CONFIG_PATH:=$(PKG_CONFIG_PATH):$(LIBGIT2_LIB64_PATH)/pkgconfig +export LIBRARY_PATH:=$(LIBRARY_PATH):$(LIBGIT2_LIB64_PATH) +export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2 2>/dev/null) +endif + +ifeq ($(shell uname -s),Linux) +ifeq ($(shell uname -m),x86_64) +# Linux x86_64 seem to be able to cope with the static libraries +# by having only musl-dev installed, without the need of using musl toolchain. + GO_STATIC_FLAGS=-ldflags "-s -w" -tags 'netgo,osusergo,static_build' else - export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2) + MUSL-PREFIX=$(BUILD_DIR)/musl/$(shell uname -m)-linux-musl-native/bin/$(shell uname -m)-linux-musl + MUSL-CC=$(MUSL-PREFIX)-gcc + export CC=$(MUSL-PREFIX)-gcc + export CXX=$(MUSL-PREFIX)-g++ + export AR=$(MUSL-PREFIX)-ar + GO_STATIC_FLAGS=-ldflags "-s -w -extldflags \"-static\"" -tags 'netgo,osusergo,static_build' endif +endif + +# API (doc) generation utilities +CONTROLLER_GEN_VERSION ?= v0.7.0 +GEN_API_REF_DOCS_VERSION ?= v0.3.0 -# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +# If gobin not set, create one on ./build and add to path. ifeq (,$(shell go env GOBIN)) -GOBIN=$(shell go env GOPATH)/bin +export GOBIN=$(BUILD_DIR)/gobin else -GOBIN=$(shell go env GOBIN) +export GOBIN=$(shell go env GOBIN) endif +export PATH:=${GOBIN}:${PATH} +# Architecture to use envtest with +ifeq ($(shell uname -m),x86_64) +ENVTEST_ARCH ?= amd64 +else +ENVTEST_ARCH ?= arm64 +endif + +ifeq ($(shell uname -s),Darwin) +# Envtest only supports darwin-amd64 +ENVTEST_ARCH=amd64 +endif TEST_CRDS := controllers/testdata/crds @@ -88,13 +130,15 @@ ${CACHE}/imagepolicies_${REFLECTOR_VER}.yaml: curl -s --fail https://raw.githubusercontent.com/fluxcd/image-reflector-controller/${REFLECTOR_VER}/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml \ -o ${CACHE}/imagepolicies_${REFLECTOR_VER}.yaml +check-deps: +ifeq ($(shell uname -s),Darwin) + if ! command -v pkg-config &> /dev/null; then echo "pkg-config is required"; exit 1; fi +endif + KUBEBUILDER_ASSETS?="$(shell $(ENVTEST) --arch=$(ENVTEST_ARCH) use -i $(ENVTEST_KUBERNETES_VERSION) --bin-dir=$(ENVTEST_ASSETS_DIR) -p path)" test: $(LIBGIT2) test-api test_deps generate fmt vet manifests api-docs install-envtest ## Run tests KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) \ - go test ./... \ - -ldflags "-s -w" \ - -coverprofile cover.out \ - -tags 'netgo,osusergo,static_build' + go test $(GO_STATIC_FLAGS) ./... -coverprofile cover.out test-api: ## Run api tests cd api; go test ./... -coverprofile cover.out @@ -104,7 +148,7 @@ manager: $(LIBGIT2) generate fmt vet ## Build manager binary run: $(LIBGIT2) generate fmt vet manifests # Run against the configured Kubernetes cluster in ~/.kube/config - go run ./main.go --log-level=${LOG_LEVEL} --log-encoding=console + go run $(GO_STATIC_FLAGS) ./main.go --log-level=${LOG_LEVEL} --log-encoding=console install: manifests ## Install CRDs into a cluster kustomize build config/crd | kubectl apply -f - @@ -159,35 +203,40 @@ docker-deploy: ## Set the Docker image in-cluster kubectl -n flux-system set image deployment/image-automation-controller manager=$(IMG):$(TAG) # Find or download controller-gen -CONTROLLER_GEN = $(shell pwd)/bin/controller-gen +CONTROLLER_GEN = $(GOBIN)/controller-gen .PHONY: controller-gen controller-gen: ## Download controller-gen locally if necessary. $(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0) libgit2: $(LIBGIT2) ## Detect or download libgit2 library -$(LIBGIT2): - IMG_TAG=$(LIBGIT2_IMG):$(LIBGIT2_TAG) ./hack/extract-libraries.sh +$(LIBGIT2): $(MUSL-CC) + IMG=$(LIBGIT2_IMG) TAG=$(LIBGIT2_TAG) ./hack/install-libraries.sh + +$(MUSL-CC): +ifneq ($(shell uname -s),Darwin) + ./hack/download-musl.sh +endif # Find or download gen-crd-api-reference-docs -GEN_CRD_API_REFERENCE_DOCS = $(shell pwd)/bin/gen-crd-api-reference-docs +GEN_CRD_API_REFERENCE_DOCS = $(GOBIN)/gen-crd-api-reference-docs .PHONY: gen-crd-api-reference-docs gen-crd-api-reference-docs: $(call go-install-tool,$(GEN_CRD_API_REFERENCE_DOCS),github.com/ahmetb/gen-crd-api-reference-docs@v0.3.0) -ENVTEST_ASSETS_DIR=$(shell pwd)/testbin +ENVTEST_ASSETS_DIR=$(BUILD_DIR)/testbin ENVTEST_KUBERNETES_VERSION?=latest install-envtest: setup-envtest mkdir -p ${ENVTEST_ASSETS_DIR} $(ENVTEST) use $(ENVTEST_KUBERNETES_VERSION) --arch=$(ENVTEST_ARCH) --bin-dir=$(ENVTEST_ASSETS_DIR) + chmod -R u+w $(BUILD_DIR)/testbin -ENVTEST = $(shell pwd)/bin/setup-envtest +ENVTEST = $(GOBIN)/setup-envtest .PHONY: envtest setup-envtest: ## Download envtest-setup locally if necessary. $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest) # go-install-tool will 'go install' any package $2 and install it to $1. -PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) define go-install-tool @[ -f $(1) ] || { \ set -e ;\ @@ -195,7 +244,7 @@ TMP_DIR=$$(mktemp -d) ;\ cd $$TMP_DIR ;\ go mod init tmp ;\ echo "Downloading $(2)" ;\ -GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\ +env -i bash -c "GOBIN=$(GOBIN) PATH=$(PATH) GOPATH=$(shell go env GOPATH) GOCACHE=$(shell go env GOCACHE) go install $(2)" ;\ rm -rf $$TMP_DIR ;\ } endef diff --git a/hack/download-musl.sh b/hack/download-musl.sh new file mode 100755 index 00000000..3f5b527d --- /dev/null +++ b/hack/download-musl.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +set -eoux pipefail + +MUSL_X86_64_FILENAME=x86_64-linux-musl-native.tgz +MUSL_X86_64_SHA512=44d441ad9aa11a06feddf3daa4c9f53ad7d9ca37af1f5a61379aca07793703d179410cea723c1b7fca94c4de19a321228bdb3656bc5cbdb5e3bea8e2d6dac6c7 +MUSL_AARCH64_FILENAME=aarch64-linux-musl-native.tgz +MUSL_AARCH64_SHA512=16d544e09845c9dbba50f29e0cb04dd661e17eb63c56acad6a67fd2a78aa7596b792477c7177d3cd56d408a27dc291a90507df882f2b099c0f25511ce08fd3b5 +MUSL_XX86_64_FILENAME=x86_64-linux-musl-cross.tgz +MUSL_XX86_64_SHA512=52abd1a56e670952116e35d1a62e048a9b6160471d988e16fa0e1611923dd108a581d2e00874af5eb04e4968b1ba32e0eb449a1f15c3e4d5240ebe09caf5a9f3 +MUSL_XAARCH64_FILENAME=aarch64-linux-musl-cross.tgz +MUSL_XAARCH64_SHA512=8695ff86979cdf30fbbcd33061711f5b1ebc3c48a87822b9ca56cde6d3a22abd4dab30fdcd1789ac27c6febbaeb9e5bde59d79d66552fae53d54cc1377a19272 +MUSL_XARMV7_FILENAME=armv7l-linux-musleabihf-cross.tgz +MUSL_XARMV7_SHA512=1bb399a61da425faac521df9b8d303e60ad101f6c7827469e0b4bc685ce1f3dedc606ac7b1e8e34d79f762a3bfe3e8ab479a97e97d9f36fbd9fc5dc9d7ed6fd1 + +TARGET_ARCH="${TARGET_ARCH:-$(uname -m)}" +ENV_FILE="${ENV_FILE:-false}" + +MUSL_FILENAME="" +MUSL_SHA512="" + +ROOT_DIR="${ROOT_DIR:-$(git rev-parse --show-toplevel)}" +MUSL_DIR="${ROOT_DIR}/build/musl" + + +if [ "${TARGET_ARCH}" = "$(uname -m)" ]; then + MUSL_FILENAME="${MUSL_X86_64_FILENAME}" + MUSL_SHA512="${MUSL_X86_64_SHA512}" + MUSL_PREFIX="${TARGET_ARCH}-linux-musl-native/bin/${TARGET_ARCH}-linux-musl" + if [ "${TARGET_ARCH}" = "arm64" ] || [ "${TARGET_ARCH}" = "aarch64" ]; then + MUSL_FILENAME="${MUSL_AARCH64_FILENAME}" + MUSL_SHA512="${MUSL_AARCH64_SHA512}" + fi +else + MUSL_FILENAME="${MUSL_XX86_64_FILENAME}" + MUSL_SHA512="${MUSL_XX86_64_SHA512}" + MUSL_PREFIX="${TARGET_ARCH}-linux-musl-cross/bin/${TARGET_ARCH}-linux-musl" + if [ "${TARGET_ARCH}" = "arm64" ] || [ "${TARGET_ARCH}" = "aarch64" ]; then + MUSL_FILENAME="${MUSL_XAARCH64_FILENAME}" + MUSL_SHA512="${MUSL_XAARCH64_SHA512}" + elif [ "${TARGET_ARCH}" = "arm" ] || [ "${TARGET_ARCH}" = "armv7" ]; then + MUSL_FILENAME="${MUSL_XARMV7_FILENAME}" + MUSL_SHA512="${MUSL_XARMV7_SHA512}" + MUSL_PREFIX=armv7l-linux-musleabihf-cross/bin/armv7l-linux-musleabihf + fi +fi + +mkdir -p "${MUSL_DIR}" + +if "${ENV_FILE}"; then + cat< "${MUSL_DIR}/${TARGET_ARCH}.env" +CC="$(pwd)/build/musl/${MUSL_PREFIX}-gcc" +CXX="$(pwd)/build/musl/${MUSL_PREFIX}-g++" +AR="$(pwd)/build/musl/${MUSL_PREFIX}-ar" +EOF +fi + +MUSL_AARCH64_URL="https://more.musl.cc/11.2.1/x86_64-linux-musl/${MUSL_FILENAME}" + +if [ ! -f "${MUSL_DIR}/bin" ]; then + TARGET_FILE="${MUSL_DIR}/${MUSL_FILENAME}" + curl -o "${TARGET_FILE}" -LO "${MUSL_AARCH64_URL}" + if ! echo "${MUSL_SHA512} ${TARGET_FILE}" | sha512sum; then + echo "Checksum failed for ${MUSL_FILENAME}." + rm -rf "${MUSL_DIR}" + exit 1 + fi + + tar xzf "${TARGET_FILE}" -C "${MUSL_DIR}" + rm "${TARGET_FILE}" +fi diff --git a/hack/install-libraries.sh b/hack/install-libraries.sh new file mode 100755 index 00000000..630ac7ac --- /dev/null +++ b/hack/install-libraries.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +IMG="${IMG:-}" +TAG="${TAG:-}" +IMG_TAG="${IMG}:${TAG}" + +function extract(){ + PLATFORM=$1 + DIR=$2 + + id=$(docker create --platform="${PLATFORM}" "${IMG_TAG}" sh) + docker cp "${id}":/usr/local - > output.tar.gz + docker rm -v "${id}" + + tar -xf output.tar.gz "local/${DIR}" + rm output.tar.gz +} + +function setup() { + PLATFORM=$1 + DIR=$2 + + extract "${PLATFORM}" "${DIR}" + + NEW_DIR="$(/bin/pwd)/build/libgit2/${TAG}" + INSTALLED_DIR="/usr/local/${DIR}" + + mv "local/${DIR}" "${TAG}" + rm -rf "local" + mv "${TAG}/" "./build/libgit2" + + # Update the prefix paths included in the .pc files. + # This will make it easier to update to the location in which they will be used. + find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} sed -i "s;${INSTALLED_DIR};${NEW_DIR};g" {} +} + +function setup_current() { + if [ -d "./build/libgit2/${TAG}" ]; then + echo "Skipping libgit2 setup as it already exists" + exit 0 + fi + + mkdir -p "./build/libgit2" + if [[ $OSTYPE == 'darwin'* ]]; then + # For MacOS development environments, download the amd64 static libraries released from from golang-with-libgit2. + + curl -o output.tar.gz -LO "https://github.com/fluxcd/golang-with-libgit2/releases/download/${TAG}/darwin-libs.tar.gz" + + DIR=libgit2-darwin + NEW_DIR="$(/bin/pwd)/build/libgit2/${TAG}" + INSTALLED_DIR="/Users/runner/work/golang-with-libgit2/golang-with-libgit2/build/${DIR}-amd64" + + tar -xf output.tar.gz + rm output.tar.gz + mv "${DIR}" "${TAG}" + mv "${TAG}/" "./build/libgit2" + + LIBGIT2_SED="s;-L/Applications/Xcode_.* ;;g" + LIBGIT2PC="$(/bin/pwd)/build/libgit2/${TAG}/lib/pkgconfig/libgit2.pc" + # Some macOS users may override their sed with gsed. If gsed is the PATH, use that instead. + if command -v gsed &> /dev/null; then + # Removes abs path from build machine, and let iconv be resolved automatically by default search paths. + gsed -i "${LIBGIT2_SED}" "${LIBGIT2PC}" + + # Update the prefix paths included in the .pc files. + # This will make it easier to update to the location in which they will be used. + # sed has a sight different behaviour in MacOS + find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} gsed -i "s;${INSTALLED_DIR};${NEW_DIR};g" {} + else + # Removes abs path from build machine, and let iconv be resolved automatically by default search paths. + sed -i "" "${LIBGIT2_SED}" "${LIBGIT2PC}" + + # Update the prefix paths included in the .pc files. + # This will make it easier to update to the location in which they will be used. + # sed has a sight different behaviour in MacOS + find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} sed -i "" "s;${INSTALLED_DIR};${NEW_DIR};g" {} + fi + else + # for linux development environments, use the static libraries from the official container images. + DIR="x86_64-alpine-linux-musl" + PLATFORM="linux/amd64" + + if [[ "$(uname -m)" == armv7* ]]; then + DIR="armv7-alpine-linux-musleabihf" + PLATFORM="linux/arm/v7" + elif [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then + DIR="aarch64-alpine-linux-musl" + PLATFORM="linux/arm64" + fi + + setup "${PLATFORM}" "${DIR}" + fi +} + +setup_current