Adding modding folder with a hacked build.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Build environment for modding/hacked/ (vendored from
|
||||
# https://github.com/inkyblackness/hacked, see ../README.md). Fetches the Go
|
||||
# toolchain and this module's dependencies once, here, at image-build time, so
|
||||
# ../hacked-build-run-image.sh can compile fully offline afterward. Rebuild
|
||||
# with ../hacked-build-image.sh whenever a version below changes, or whenever
|
||||
# ../hacked/go.mod or go.sum changes (its dependencies are baked into the
|
||||
# image's module cache).
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# go.mod's own "go" directive is a minimum toolchain version, not a version to
|
||||
# fetch - pin a stable release that already satisfies it so `go build` never
|
||||
# needs to fetch a newer toolchain over the network at build time.
|
||||
ARG GO_VERSION=1.27.1
|
||||
|
||||
# build-essential/pkg-config/curl/ca-certificates/git/gosu: base toolchain.
|
||||
# mingw-w64: the Windows cross-build. libgl1-mesa-dev/xorg-dev: go-gl/glfw's
|
||||
# cgo bindings (Linux build only - the Windows cross-build talks to the Win32
|
||||
# API directly, via mingw-w64's own headers). libgtk-3-dev:
|
||||
# github.com/sqweek/dialog's Linux backend uses GTK3 via cgo (`pkg-config
|
||||
# gtk+-3.0`) for native file/message dialogs. zip: packages the Windows build
|
||||
# (see build-hacked.sh) - tar, for the Linux .tgz, is already part of the
|
||||
# base image.
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
build-essential pkg-config curl ca-certificates git gosu \
|
||||
mingw-w64 \
|
||||
libgl1-mesa-dev xorg-dev \
|
||||
libgtk-3-dev \
|
||||
zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -sSLO "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
&& tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
&& rm "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
ENV PATH=/usr/local/go/bin:${PATH}
|
||||
ENV GOTOOLCHAIN=local
|
||||
ENV GOPATH=/opt/go
|
||||
|
||||
# Populates /opt/go/pkg/mod with every dependency hacked/go.mod pins, so the
|
||||
# container never needs network access to build it. Only go.mod/go.sum are
|
||||
# copied in for this - not the rest of the source - so editing hacked's own
|
||||
# .go files doesn't invalidate this layer's cache.
|
||||
COPY hacked/go.mod hacked/go.sum /tmp/hacked-deps/
|
||||
RUN cd /tmp/hacked-deps && go mod download && rm -rf /tmp/hacked-deps
|
||||
|
||||
COPY hacked-build-image/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||
COPY hacked-build-image/build-hacked.sh /usr/local/bin/build-hacked.sh
|
||||
# 755, not +x: the entrypoint drops to a `builder` user matching the *host's*
|
||||
# UID/GID (see docker-entrypoint.sh), which is never in these root-owned
|
||||
# files' group, so it needs the image's own explicit world-read+execute here -
|
||||
# `chmod +x` alone only adds execute bits on top of whatever "other"
|
||||
# permissions the source file happened to have (host umask-dependent).
|
||||
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh /usr/local/bin/build-hacked.sh
|
||||
|
||||
WORKDIR /workspace
|
||||
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|
||||
CMD ["/usr/local/bin/build-hacked.sh"]
|
||||
|
||||
# Marks a shell as already running inside this image, same convention as the
|
||||
# main project's own build-image (see ../../build-image/Dockerfile) - lets
|
||||
# ../Makefile compile directly instead of trying to docker-run this image
|
||||
# again from inside itself (e.g. a CI job already using this image as its
|
||||
# container).
|
||||
ENV HACKED_BUILD_IMAGE=1
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# Compiles modding/hacked/ for Linux and Windows (amd64), entirely offline -
|
||||
# every Go module dependency was already fetched into the build-image at
|
||||
# image-build time (see Dockerfile). Baked into the image at
|
||||
# /usr/local/bin/build-hacked.sh (see Dockerfile's CMD) - run via
|
||||
# ../hacked-build-run-image.sh, which bind-mounts modding/ at /workspace, not
|
||||
# directly.
|
||||
#
|
||||
# Does not follow hacked/build.sh (its own upstream build script): that script
|
||||
# assumes hacked/ is its own git checkout (it derives its version from `git
|
||||
# describe --tags`), which isn't true here - hacked/ is a vendored snapshot,
|
||||
# not a git submodule, so `git describe` there would silently pick up
|
||||
# *questshock's* tags instead. Version is a plain build-date string instead.
|
||||
set -euo pipefail
|
||||
|
||||
MODDING_ROOT="$(pwd)"
|
||||
HACKED_SRC="$MODDING_ROOT/hacked"
|
||||
OUT_DIR="$MODDING_ROOT/dist"
|
||||
|
||||
VERSION="hacked-$(date -u +%Y%m%d)"
|
||||
echo "Version: $VERSION"
|
||||
|
||||
rm -rf "$OUT_DIR"
|
||||
mkdir -p "$OUT_DIR/linux/hacked" "$OUT_DIR/win/hacked"
|
||||
|
||||
cd "$HACKED_SRC"
|
||||
|
||||
echo "== Building Linux amd64 =="
|
||||
go build -gcflags "-d=checkptr=0" -ldflags "-X main.version=$VERSION" \
|
||||
-trimpath -o "$OUT_DIR/linux/hacked/hacked" .
|
||||
|
||||
echo "== Preparing the Windows icon/version-info resource =="
|
||||
# cmd/link automatically links in a *.syso file sitting in the main package
|
||||
# directory during a Windows build - no explicit flag needed, but it does mean
|
||||
# generating it (via windres, from hacked.rc/.ico/.exe.manifest) has to happen
|
||||
# right here, before go build runs, and be cleaned up after regardless of
|
||||
# outcome so it never leaks into a Linux build run from the same checkout.
|
||||
WIN_RES_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$WIN_RES_DIR"; rm -f "$HACKED_SRC/main-res.syso"' EXIT
|
||||
cp "$HACKED_SRC"/_resources/build/win/* "$WIN_RES_DIR/"
|
||||
# No git tag to derive a real version from (hacked/ is a vendored snapshot,
|
||||
# not its own checkout) - same date-based fallback hacked/build.sh itself
|
||||
# uses when `git describe` fails.
|
||||
sed -i "s/§MAJOR/$(date -u +%Y)/;s/§MINOR/$(date -u +%m)/;s/§PATCH/$(date -u +%d)/" \
|
||||
"$WIN_RES_DIR/hacked.exe.manifest"
|
||||
x86_64-w64-mingw32-windres -o "$HACKED_SRC/main-res.syso" "$WIN_RES_DIR/hacked.rc"
|
||||
|
||||
echo "== Building Windows amd64 (cross-compiled via mingw-w64) =="
|
||||
# -extldflags -static-libgcc/-static-libstdc++: statically links the mingw
|
||||
# C/C++ runtime into hacked.exe, the same technique the main project's own
|
||||
# Windows cross-build uses (see ../../build-image/Dockerfile) - avoids having
|
||||
# to locate and ship libgcc_s_seh-1.dll/libstdc++-6.dll (their exact path
|
||||
# depends on the mingw-w64 package's gcc version). libwinpthread-1.dll still
|
||||
# needs shipping alongside the .exe; it isn't part of that static link.
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 \
|
||||
CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ \
|
||||
go build -gcflags "-d=checkptr=0" \
|
||||
-ldflags "-X main.version=$VERSION -H=windowsgui -extldflags '-static-libgcc -static-libstdc++'" \
|
||||
-trimpath -o "$OUT_DIR/win/hacked/hacked.exe" .
|
||||
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll "$OUT_DIR/win/hacked/"
|
||||
|
||||
echo "== Copying distribution resources =="
|
||||
for os in linux win; do
|
||||
packageDir="$OUT_DIR/$os/hacked"
|
||||
cp "$HACKED_SRC/LICENSE" "$packageDir/"
|
||||
cp -R "$HACKED_SRC/_resources/dist/." "$packageDir/"
|
||||
done
|
||||
|
||||
echo "== Packaging =="
|
||||
# $VERSION (hacked-<date>) is already a complete, self-describing name - no
|
||||
# separate package-name prefix needed on top of it.
|
||||
(cd "$OUT_DIR/linux" && tar -czf "$OUT_DIR/$VERSION.linux64.tgz" hacked)
|
||||
(cd "$OUT_DIR/win" && zip -rq "$OUT_DIR/$VERSION.win64.zip" hacked)
|
||||
|
||||
echo "== Done =="
|
||||
echo "Linux: $OUT_DIR/$VERSION.linux64.tgz"
|
||||
echo "Windows: $OUT_DIR/$VERSION.win64.zip"
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# Drops from root (needed to read the Go toolchain and module cache under
|
||||
# /usr/local/go and /opt/go) to a user matching the host's UID/GID, so
|
||||
# anything written into the bind-mounted repo (hacked/_build/, ...) is owned
|
||||
# by the host user instead of root.
|
||||
set -euo pipefail
|
||||
|
||||
USER_UID="${HOST_UID:-1000}"
|
||||
USER_GID="${HOST_GID:-1000}"
|
||||
|
||||
groupadd -g "$USER_GID" builder 2>/dev/null || true
|
||||
useradd -u "$USER_UID" -g "$USER_GID" -m -s /bin/bash builder 2>/dev/null || true
|
||||
|
||||
# /workspace (the bind-mounted repo) may actually be owned by a group the
|
||||
# host user only has via *supplementary* membership rather than their
|
||||
# primary GID above - e.g. a VirtualBox vboxsf shared folder, which shows
|
||||
# up as root:vboxsf on the host and would otherwise be inaccessible to
|
||||
# `builder` here (falls through to "other", which vboxsf's default mode
|
||||
# leaves with no permissions at all). Join whatever group actually owns
|
||||
# /workspace too, if it differs.
|
||||
WORKSPACE_GID="$(stat -c %g /workspace 2>/dev/null || true)"
|
||||
if [ -n "$WORKSPACE_GID" ] && [ "$WORKSPACE_GID" != "$USER_GID" ]; then
|
||||
groupadd -g "$WORKSPACE_GID" workspace 2>/dev/null || true
|
||||
usermod -aG "$WORKSPACE_GID" builder 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# The Go module cache under /opt/go was populated as root at image-build
|
||||
# time (see Dockerfile) - readable by anyone, but go build also wants to
|
||||
# write GOCACHE (build cache) under there by default. Point it at a
|
||||
# per-run tmpfs-friendly location inside the builder's own home instead of
|
||||
# fighting permissions on the image's baked-in GOPATH.
|
||||
export GOCACHE=/home/builder/.cache/go-build
|
||||
export GOMODCACHE=/opt/go/pkg/mod
|
||||
|
||||
exec gosu builder "$@"
|
||||
Reference in New Issue
Block a user