From 056e11d3e9ac0e8b2f1f435eb8a9e6de8c660408 Mon Sep 17 00:00:00 2001 From: Christopher Tam Date: Tue, 31 Dec 2024 13:23:43 -0500 Subject: [PATCH] build: Make `build` target cross-compile capable This change makes `make build` capable of cross-compiling. This can be useful for external libraries. --- GNUmakefile | 32 +++++++++++--- scripts/build-lib | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 7 deletions(-) create mode 100755 scripts/build-lib diff --git a/GNUmakefile b/GNUmakefile index 1f44421..177132f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -18,6 +18,9 @@ endif GO111MODULE=on export GO111MODULE +GOOS ?= $(shell go env GOOS) +export GOOS + .PHONY: help help: @echo "Usage: make [target]" @@ -31,23 +34,37 @@ format-c: ## formats all the C code format-c-check: ## checks C code formatting ./scripts/format-c-check +.PHONY: clean +clean: ## clean up builds + @rm -rf .build + .PHONY: build -build: ## builds the Linux dynamic libraries and leave them and a copy of the definitions in .build directory +build: ## builds the libraries and leave them and a copy of the definitions in .build directory ifeq (${GPL2},true) cp go.mod go-gpl2.mod cp go.sum go-gpl2.sum go mod edit -replace github.com/spacemonkeygo/monkit/v3=./internal/replacements/monkit ./scripts/check-licenses-gpl2 endif - go build -ldflags="-s -w" -buildmode c-shared -o .build/uplink.so . - go build -ldflags="-s -w" -buildmode c-archive -o .build/uplink.a . - mv .build/uplink.so .build/libuplink.so - mv .build/uplink.a .build/libuplink.a + mkdir -p .build/out/ + + ./scripts/build-lib .build/out/ + +# Move the possible build artifacts + @(mv .build/out/uplink.so .build/libuplink.so || true) + @(mv .build/out/uplink.a .build/libuplink.a || true) + @(mv .build/out/uplink.dll .build/libuplink.dll || true) + @(mv .build/out/uplink.lib .build/libuplink.lib || true) + @(mv .build/out/uplink.dylib .build/libuplink.dylib || true) + mkdir -p .build/uplink - mv .build/*.h .build/uplink + mv .build/out/*.h .build/uplink cp uplink_definitions.h .build/uplink cp uplink_compat.h .build/uplink - ./scripts/gen-pkg-config > .build/libuplink.pc + + if [ "${GOOS}" != "windows" ]; then \ + ./scripts/gen-pkg-config > .build/libuplink.pc; \ + fi .PHONY: bump-dependencies bump-dependencies: ## bumps the dependencies @@ -85,6 +102,7 @@ OS ?= $(shell uname) ZIG ?= $(shell which zig) TAG ?= $(shell git tag -l | grep -E 'v[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n 1) + .PHONY: release-files release-files: ## builds and copies release files to Github diff --git a/scripts/build-lib b/scripts/build-lib new file mode 100755 index 0000000..ecabe70 --- /dev/null +++ b/scripts/build-lib @@ -0,0 +1,110 @@ +#!/bin/sh + +_print_usage() { + echo "Usage: $0 OUT_DIR" +} + +if [ -z "$1" ]; then + _print_usage + exit 1 +fi +OUT_DIR=$1 + +GOOS=$(go env GOOS) +GOARCH=$(go env GOARCH) +ZIG=$(which zig) + +HOST_GOOS=$(uname | tr '[:upper:]' '[:lower:]') +HOST_GOARCH=$(uname -m) + +if [ "${GOOS}" = "darwin" ]; then + if [ "${HOST_GOOS}" != "darwin" ]; then + @echo "Cannot cross-compile from $HOST_GOOS to $GOOS."; + exit 1 + fi +fi + +# Normalize HOST_GOARCH +if [ "${HOST_GOARCH}" = "x86_64" ]; then + HOST_GOARCH="amd64" +elif [ "${HOST_GOARCH}" = "aarch64" ]; then + HOST_GOARCH="arm64" +elif [ "${HOST_GOARCH}" = "loongarch64" ]; then + HOST_GOARCH="loong64" +fi + +# Initialize variables +OUT_SHARED_NAME="uplink.so" +OUT_STATIC_NAME="uplink.a" +CC_TARGET="" + +if [ "$GOOS-$GOARCH" = "$HOST_GOOS-$HOST_GOARCH" ]; then + CC_TARGET="" + case "$GOOS" in + darwin) + OUT_SHARED_NAME="uplink.dylib" + ;; + windows) + OUT_SHARED_NAME="uplink.dll" + OUT_STATIC_NAME="uplink.lib" + ;; + esac +else + if [ -z "$ZIG" ]; then + echo "Zig compiler not found" + exit 1 + fi + + echo "Cross-compiling to target: $GOOS-$GOARCH (host: $HOST_GOOS-$HOST_GOARCH)" + + CC_ARCH="" + case "$GOARCH" in + amd64) CC_ARCH="x86_64" ;; + arm64) CC_ARCH="aarch64" ;; + riscv) CC_ARCH="riscv32" ;; + riscv64) CC_ARCH="riscv64" ;; + loong64) CC_ARCH="loongarch64" ;; + ppc) CC_ARCH="powerpc" ;; + ppcle) CC_ARCH="powerpcle" ;; + ppc64) CC_ARCH="powerpc64" ;; + ppc64le) CC_ARCH="powerpc64le" ;; + mips) CC_ARCH="mips" ;; + mipsle) CC_ARCH="mipsle" ;; + mips64) CC_ARCH="mips64" ;; + mips64le) CC_ARCH="mips64le" ;; + wasm) CC_ARCH="wasm" ;; + *) + echo "Unrecognized cross-compilation target: GOOS=$GOOS GOARCH=$GOARCH" >&2 + exit 1 + ;; + esac + + case "$GOOS" in + linux) CC_TARGET="${ZIG} cc -target ${CC_ARCH}-linux-gnu" ;; + darwin) + # Native compilation is required for MacOS + CC_TARGET="" + OUT_SHARED_NAME="uplink.dylib" + ;; + windows) + CC_TARGET="${ZIG} cc -target ${CC_ARCH}-windows" + OUT_SHARED_NAME="uplink.dll" + OUT_STATIC_NAME="uplink.lib" + ;; + js) CC_TARGET="${ZIG} cc -target ${CC_ARCH}-wasi" ;; + *) CC_TARGET="${ZIG} cc -target ${CC_ARCH}-${GOOS}" ;; + esac +fi + +OUT_SHARED_PATH="$OUT_DIR/$OUT_SHARED_NAME" +OUT_STATIC_PATH="$OUT_DIR/$OUT_STATIC_NAME" + +if [ -z "$CC_TARGET" ]; then + set -e -x + CGO_ENABLED=1 go build -ldflags="-s -w" -buildmode c-shared -o "$OUT_SHARED_PATH" . + CGO_ENABLED=1 go build -ldflags="-s -w" -buildmode c-archive -o "$OUT_STATIC_PATH" . +else + set -e -x + CGO_ENABLED=1 CC="$CC_TARGET" go build -ldflags="-s -w" -buildmode c-shared -o "$OUT_SHARED_PATH" . + CGO_ENABLED=1 CC="$CC_TARGET" go build -ldflags="-s -w" -buildmode c-archive -o "$OUT_STATIC_PATH" . +fi