Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
Merge pull request #13 from pjbgf/libgit2-1.1.1-5
Browse files Browse the repository at this point in the history
Optimise target image for cross compilation
  • Loading branch information
stefanprodan authored Feb 2, 2022
2 parents f79adb7 + c4cd5ea commit a05dea1
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 124 deletions.
43 changes: 23 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ ARG XX_VERSION=1.1.0

FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

FROM golang:${GO_VERSION}-${BASE_VARIANT} as gostable

FROM gostable AS go-linux

FROM --platform=$BUILDPLATFORM ${BASE_VARIANT} AS build-deps
FROM --platform=$BUILDPLATFORM ${BASE_VARIANT} AS build-base

RUN apk add --no-cache \
bash \
Expand All @@ -26,15 +22,10 @@ RUN apk add --no-cache \

COPY --from=xx / /

ARG TARGETPLATFORM

RUN xx-apk add --no-cache \
xx-c-essentials

RUN xx-apk add --no-cache \
xx-cxx-essentials
FROM build-base AS build-cross

ARG TARGETPLATFORM

RUN xx-apk add --no-cache \
build-base \
pkgconfig \
Expand All @@ -48,7 +39,6 @@ RUN xx-apk add --no-cache \
WORKDIR /build
COPY hack/static.sh .

ARG TARGETPLATFORM
ENV CC=xx-clang
ENV CXX=xx-clang++

Expand All @@ -68,12 +58,25 @@ RUN ./static.sh build_libssh2
RUN ./static.sh build_libgit2


FROM go-${TARGETOS} AS build
# trimmed removes all non necessary files (i.e. openssl binary).
FROM build-cross AS trimmed

# Copy cross-compilation tools
COPY --from=xx / /
# Copy compiled libraries
COPY --from=build-deps /usr/local/ /usr/local/
ARG TARGETPLATFORM
RUN mkdir -p /trimmed/usr/local/$(xx-info triple)/ && \
mkdir -p /trimmed/usr/local/$(xx-info triple)/share

RUN cp -r /usr/local/$(xx-info triple)/lib/ /trimmed/usr/local/$(xx-info triple)/ && \
cp -r /usr/local/$(xx-info triple)/lib64/ /trimmed/usr/local/$(xx-info triple)/ | true && \
cp -r /usr/local/$(xx-info triple)/include/ /trimmed/usr/local/$(xx-info triple)/ && \
cp -r /usr/local/$(xx-info triple)/share/doc/ /trimmed/usr/local/$(xx-info triple)/share/

FROM scratch as libs-arm64
COPY --from=trimmed /trimmed/ /

FROM scratch as libs-amd64
COPY --from=trimmed /trimmed/ /

FROM scratch as libs-armv7
COPY --from=trimmed /trimmed/ /

COPY ./hack/Makefile /Makefile
COPY ./hack/static.sh /static.sh
FROM libs-$TARGETARCH$TARGETVARIANT as libs
107 changes: 26 additions & 81 deletions Dockerfile.test
Original file line number Diff line number Diff line change
@@ -1,107 +1,59 @@
# This Dockerfile tests the hack/Makefile output against git2go.
ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.17.6
ARG GO_VERSION=1.17
ARG XX_VERSION=1.1.0

FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

FROM golang:${GO_VERSION}-${BASE_VARIANT} as gostable

FROM gostable AS go-linux

FROM --platform=$BUILDPLATFORM ${BASE_VARIANT} AS build-deps

RUN apk add --no-cache \
bash \
curl \
build-base \
linux-headers \
perl \
cmake \
pkgconfig \
gcc \
musl-dev \
clang \
lld

COPY --from=xx / /
ARG LIBGIT2_IMG
ARG LIBGIT2_TAG

ARG TARGETPLATFORM

RUN xx-apk add --no-cache \
xx-c-essentials

RUN xx-apk add --no-cache \
xx-cxx-essentials

ARG TARGETPLATFORM
RUN xx-apk add --no-cache \
build-base \
pkgconfig \
gcc \
musl-dev \
clang \
lld \
llvm \
linux-headers

WORKDIR /build
COPY hack/static.sh .

ARG TARGETPLATFORM
ENV CC=xx-clang
ENV CXX=xx-clang++
FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} AS build-deps

RUN CHOST=$(xx-clang --print-target-triple) \
./static.sh build_libz

RUN CHOST=$(xx-clang --print-target-triple) \
./static.sh build_openssl
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

RUN export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \
export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \
export OPENSSL_ROOT_DIR="/usr/local/$(xx-info triple)" && \
export OPENSSL_CRYPTO_LIBRARY="/usr/local/$(xx-info triple)/lib64" && \
export OPENSSL_INCLUDE_DIR="/usr/local/$(xx-info triple)/include/openssl"
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable

RUN ./static.sh build_libssh2
RUN ./static.sh build_libgit2
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

FROM go-${TARGETOS} AS build
RUN apk add clang lld pkgconfig

# Copy cross-compilation tools
COPY --from=xx / /
# Copy compiled libraries
COPY --from=build-deps /usr/local/ /usr/local/

RUN apk add clang lld pkgconfig
# build-go-mod can still be cached at build platform architecture.
FROM build-base as build-go-mod

WORKDIR /root/smoketest
COPY tests/smoketest/go.mod .
COPY tests/smoketest/go.sum .
RUN go mod download

# Build stage install per target platform
# dependency and effectively cross compile the application.
FROM build-go-mod as build

ARG TARGETPLATFORM

# Some dependencies have to installed
# for the target platform: https://github.com/tonistiigi/xx#go--cgo
RUN xx-apk add --no-cache \
musl-dev \
gcc
RUN xx-apk add musl-dev gcc clang lld

WORKDIR /root/smoketest

COPY tests/smoketest/main.go .
COPY --from=build-deps /usr/local/ /usr/local/

ENV CGO_ENABLED=1
RUN export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \
RUN 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 FLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2)" && \
export CGO_LDFLAGS="${FLAGS} -static" && \
xx-go build \
-ldflags "-s -w" \
-tags 'netgo,osusergo,static_build' \
-o static-test-runner -trimpath main.go;
-o static-test-runner -trimpath main.go


# Ensure that the generated binary is valid for the target platform
RUN xx-verify --static static-test-runner
Expand All @@ -119,11 +71,4 @@ COPY --from=build \

ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

# To do docker run instead, replace the RUN statement with:
# ENTRYPOINT [ "/root/smoketest/static-test-runner" ]

# The approach below was preferred as it provides a way to
# assert the functionality across the supported architectures
# without any extra steps.

RUN /root/smoketest/static-test-runner
61 changes: 58 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
IMG ?= hiddeco/golang-with-libgit2
IMG ?= ghcr.io/fluxcd/golang-with-libgit2
TAG ?= latest
STATIC_TEST_TAG := test

PLATFORMS ?= linux/amd64,linux/arm/v7,linux/arm64
BUILD_ARGS ?=

REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel)
TARGET_DIR ?= $(REPOSITORY_ROOT)/build/libgit2
BUILD_ROOT_DIR ?= $(REPOSITORY_ROOT)/build/libgit2-src

LIBGIT2_PATH := $(TARGET_DIR)
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


ifeq ($(shell uname -s),Linux)
export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2) -static
else
export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2) -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-allow-shlib-undefined -static
endif

ifeq ($(shell uname -s),Linux)
MUSL-PREFIX=$(REPOSITORY_ROOT)/build/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
endif

GO_STATIC_FLAGS=-tags 'netgo,osusergo,static_build'


.PHONY: build
build:
docker buildx build \
Expand All @@ -17,7 +49,9 @@ build:
test:
docker buildx build \
--platform=$(PLATFORMS) \
--tag $(IMG):$(TAG) \
--tag $(IMG):$(TAG)-test \
--build-arg LIBGIT2_IMG=$(IMG) \
--build-arg LIBGIT2_TAG=$(TAG) \
--file Dockerfile.test \
$(BUILD_ARGS) .

Expand All @@ -33,3 +67,24 @@ builder:
--use
# install qemu emulators
docker run -it --rm --privileged tonistiigi/binfmt --install all


$(LIBGIT2): $(MUSL-CC)
ifeq ($(shell uname -s),Darwin)
TARGET_DIR=$(TARGET_DIR) BUILD_ROOT_DIR=$(BUILD_ROOT_DIR) \
./hack/static.sh all
else
IMG_TAG=$(IMG):$(TAG) ./hack/extract-libraries.sh
endif

$(MUSL-CC):
ifneq ($(shell uname -s),Darwin)
./hack/download-musl.sh
endif


# dev-test is a smoke test for development environment
# consuming the libraries generated by this project.
dev-test: $(LIBGIT2)
cd tests/smoketest; go vet $(GO_STATIC_FLAGS) ./...
cd tests/smoketest; go run $(GO_STATIC_FLAGS) main.go
36 changes: 36 additions & 0 deletions hack/download-musl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/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_FILENAME="${MUSL_X86_64_FILENAME}"
MUSL_SHA512="${MUSL_X86_64_SHA512}"
if [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then
MUSL_FILENAME="${MUSL_AARCH64_FILENAME}"
MUSL_SHA512="${MUSL_AARCH64_SHA512}"
fi

MUSL_AARCH64_URL="https://more.musl.cc/11.2.1/x86_64-linux-musl/${MUSL_FILENAME}"

ROOT_DIR="$(git rev-parse --show-toplevel)"
MUSL_DIR="${ROOT_DIR}/build/musl"

if [ ! -f "${MUSL_DIR}/bin" ]; then
TARGET_FILE="${MUSL_DIR}/${MUSL_FILENAME}"
mkdir -p "${MUSL_DIR}"

echo "${MUSL_SHA512} ${TARGET_FILE}"
curl -o "${TARGET_FILE}" -LO "${MUSL_AARCH64_URL}"
if ! echo "${MUSL_SHA512} ${TARGET_FILE}" | sha512sum --check; 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
Loading

0 comments on commit a05dea1

Please sign in to comment.