Skip to content

Commit

Permalink
Add Crystal 1.10.1
Browse files Browse the repository at this point in the history
- Alpine Linux 3.18.4
- LLVM 16
  • Loading branch information
luislavena committed Nov 1, 2023
1 parent dea2a58 commit 063b06b
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ jobs:
fail-fast: false
matrix:
include:
- crystal_major_minor: 1.10
crystal_full: 1.10.1
target_platforms: linux/amd64,linux/arm64
concurrency_group: compile-crystal

- crystal_major_minor: 1.9
crystal_full: 1.9.2
target_platforms: linux/amd64,linux/arm64
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION ?= 1.9
VERSION ?= 1.10
REGISTRY ?= ghcr.io

DOCKERFILE := docker/${VERSION}/Dockerfile
Expand Down
295 changes: 295 additions & 0 deletions docker/1.10/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
# syntax=docker/dockerfile:1.4

# ---
# Stages:
#
# stage0: use build platform and existing compiler to cross-compile for target
# stage1: link cross-compiled objects into executables on the target platform
# stage2: prepare directory structure, source code and final executables
# stage3: copy over artifacts and development utilities and dependencies

# ---
# stage0: bootstrap Crystal using Alpine's build of Crystal
FROM --platform=$BUILDPLATFORM alpine:3.18.4 AS stage0

# expose the target architecture to be used in cross-compilation
ARG TARGETARCH

# install dependencies needed for cross-compilation of Crystal and Shards
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
set -eux; \
apk add \
crystal \
curl \
g++ \
git \
llvm16-dev \
make \
shards \
yaml-dev \
;

# download and compile Crystal source for target platform
RUN set -eux -o pipefail; \
cd /tmp; \
export \
CRYSTAL_VERSION=1.10.1 \
CRYSTAL_SHA256=f6449ffff519c86383f5e845455f3e6f6b10d6090effab09568f4c7414a8a51b \
; \
{ \
curl --fail -Lo crystal.tar.gz https://github.com/crystal-lang/crystal/archive/refs/tags/${CRYSTAL_VERSION}.tar.gz; \
echo "${CRYSTAL_SHA256} *crystal.tar.gz" | sha256sum -c - >/dev/null 2>&1; \
tar -xf crystal.tar.gz; \
rm crystal.tar.gz; \
mv crystal-${CRYSTAL_VERSION} crystal; \
}; \
{ \
cd /tmp/crystal; \
# prepare man page
gzip -9 man/crystal.1; \
mkdir -p /usr/local/share/man/man1; \
cp -f man/*.1.gz /usr/local/share/man/man1/; \
# build Compiler for target architecture
mkdir -p .build; \
make crystal release=1 static=1 target=$TARGETARCH-alpine-linux-musl | tail -1 | tee .build/crystal.sh; \
rm -rf src/llvm/ext/llvm_ext.o; \
}

# download and compile Shards source for target platform
RUN set -eux -o pipefail; \
cd /tmp; \
export \
SHARDS_VERSION=0.17.3 \
SHARDS_SHA256=6512ff51bd69057f4da4783eb6b14c29d9a88b97d35985356d1dc644a08424c7 \
; \
{ \
curl --fail -Lo shards.tar.gz https://github.com/crystal-lang/shards/archive/refs/tags/v${SHARDS_VERSION}.tar.gz; \
echo "${SHARDS_SHA256} *shards.tar.gz" | sha256sum -c - >/dev/null 2>&1; \
tar -xf shards.tar.gz; \
rm shards.tar.gz; \
mv shards-${SHARDS_VERSION} shards; \
}; \
{ \
cd /tmp/shards; \
# prepare man pages
gzip -9 man/shards.1 man/shard.yml.5; \
mkdir -p /usr/local/share/man/man1 /usr/local/share/man/man5; \
cp -f man/*.1.gz /usr/local/share/man/man1/; \
cp -f man/*.5.gz /usr/local/share/man/man5/; \
# build for target platform
make bin/shards release=1 static=1 FLAGS="--cross-compile --target $TARGETARCH-alpine-linux-musl" | tail -1 | tee bin/shards.sh; \
}

# ---
# stage1: link compiled objects on target platform
FROM alpine:3.18.4 AS stage1

# install dependencies needed for linking
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
set -eux; \
apk add \
g++ \
gc-dev \
gcc \
git \
libevent-static \
libxml2-static \
llvm16-dev \
llvm16-static \
make \
musl-dev \
pcre-dev \
pcre2-dev \
yaml-static \
zlib-static \
zstd-static \
;

# copy build artifacts from stage0
COPY --from=stage0 /tmp/crystal/.build /tmp/crystal/.build
COPY --from=stage0 /tmp/crystal/Makefile /tmp/crystal/Makefile
COPY --from=stage0 /tmp/crystal/src/llvm/ext /tmp/crystal/src/llvm/ext
COPY --from=stage0 /tmp/shards/bin /tmp/shards/bin

# link objects to final binaries
RUN set -eux; \
# compile LLVM extension and link the compiler
{ \
cd /tmp/crystal; \
mkdir -p spec/; \
make llvm_ext; \
sh -ex .build/crystal.sh; \
# smoke test
.build/crystal --version; \
# copy final binary
mkdir -p /tmp/usr/local/bin; \
cp -f .build/crystal /tmp/usr/local/bin/; \
}; \
# compile shards
{ \
cd /tmp/shards; \
sh -ex bin/shards.sh; \
# smoke test
bin/shards --version; \
# copy final binary
mkdir -p /tmp/usr/local/bin; \
cp -f bin/shards /tmp/usr/local/bin/; \
}

# ---
# stage2: prepare binaries and code for final image
FROM alpine:3.18.4 AS stage2

# combine source code and final binaries from previous stages
COPY --from=stage0 /tmp/crystal/src /usr/local/share/crystal/src
COPY --from=stage0 /usr/local/share/man /usr/local/share/man
COPY --from=stage1 /tmp/usr/local/bin /usr/local/bin

# ---
# stage3: final image
FROM alpine:3.18.4 AS stage3

# upgrade system and installed dependencies for security patches
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
set -eux; \
apk upgrade

# copy prepared structure from stage2
COPY --from=stage2 /usr/local /usr/local

# install dependencies and common packages
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
set -eux; \
apk add \
curl \
gc-dev \
gcc \
git \
libevent-static \
musl-dev \
openssl-dev \
openssl-libs-static \
pcre-dev \
pcre2-dev \
sqlite-static \
tzdata \
yaml-dev \
yaml-static \
zlib-dev \
zlib-static \
; \
# smoke tests
[ "$(command -v crystal)" = '/usr/local/bin/crystal' ]; \
[ "$(command -v shards)" = '/usr/local/bin/shards' ]; \
crystal --version; \
shards --version

# setup non-root user (fixuid)
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
--mount=type=tmpfs,target=/tmp \
set -eux -o pipefail; \
# create non-root user & give passwordless sudo
{ \
apk add sudo; \
addgroup -g 1000 user; \
adduser -u 1000 -G user -h /home/user -s /bin/sh -D user; \
mkdir -p /etc/sudoers.d; \
echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user; \
# cleanup backup copies
rm /etc/group- /etc/passwd- /etc/shadow-; \
}; \
# Install fixuid
{ \
cd /tmp; \
export FIXUID_VERSION=0.6.0; \
case "$(arch)" in \
x86_64) \
export \
FIXUID_ARCH=amd64 \
FIXUID_SHA256=8c47f64ec4eec60e79871796ea4097ead919f7fcdedace766da9510b78c5fa14 \
; \
;; \
aarch64) \
export \
FIXUID_ARCH=arm64 \
FIXUID_SHA256=827e0b480c38470b5defb84343be7bb4e85b9efcbf3780ac779374e8b040a969 \
; \
;; \
esac; \
wget -q -O fixuid.tar.gz https://github.com/boxboat/fixuid/releases/download/v${FIXUID_VERSION}/fixuid-${FIXUID_VERSION}-linux-${FIXUID_ARCH}.tar.gz; \
echo "${FIXUID_SHA256} *fixuid.tar.gz" | sha256sum -c - >/dev/null 2>&1; \
tar -xf fixuid.tar.gz; \
mv fixuid /usr/local/bin/; \
chmod u+s /usr/local/bin/fixuid; \
rm fixuid.tar.gz; \
}; \
# Generate fixuid config
mkdir -p /etc/fixuid; \
{ \
echo "user: user"; \
echo "group: user"; \
} | tee /etc/fixuid/config.yml

# Adjust ENTRYPOINT
ENTRYPOINT [ "/usr/local/bin/fixuid", "-q" ]
CMD [ "/bin/sh" ]

# install development utilities
RUN --mount=type=cache,sharing=private,target=/var/cache/apk \
--mount=type=tmpfs,target=/tmp \
set -eux; \
cd /tmp; \
# Overmind (needs tmux)
{ \
export OVERMIND_VERSION=2.4.0; \
case "$(arch)" in \
x86_64) \
export \
OVERMIND_ARCH=amd64 \
OVERMIND_SHA256=1f7cac289b550a71bebf4a29139e58831b39003d9831be59eed3e39a9097311c \
; \
;; \
aarch64) \
export \
OVERMIND_ARCH=arm64 \
OVERMIND_SHA256=94a3e8393bd718ae9ec1b6cc21740bffa52da20710eaf020a7aa679cdc926104 \
; \
;; \
esac; \
apk add \
tmux \
; \
curl --fail -Lo overmind.gz https://github.com/DarthSim/overmind/releases/download/v${OVERMIND_VERSION}/overmind-v${OVERMIND_VERSION}-linux-${OVERMIND_ARCH}.gz; \
echo "${OVERMIND_SHA256} *overmind.gz" | sha256sum -c - >/dev/null 2>&1; \
gunzip overmind.gz; \
chmod +x overmind; \
mv overmind /usr/local/bin/; \
}; \
# Watchexec
{ \
export WATCHEXEC_VERSION=1.23.0; \
case "$(arch)" in \
x86_64) \
export \
WATCHEXEC_ARCH=x86_64 \
WATCHEXEC_SHA256=9cab0c339ad5f6da34ce6ce00d27dc02e9ba3f5418f81c728b83c1b7feef051d \
; \
;; \
aarch64) \
export \
WATCHEXEC_ARCH=aarch64 \
WATCHEXEC_SHA256=3a977fa419d7dafe07b119a9c0b3c53311b0b624a388647ce0f0e12b254f4351 \
; \
;; \
esac; \
curl --fail -Lo watchexec.tar.xz https://github.com/watchexec/watchexec/releases/download/v${WATCHEXEC_VERSION}/watchexec-${WATCHEXEC_VERSION}-${WATCHEXEC_ARCH}-unknown-linux-musl.tar.xz; \
echo "${WATCHEXEC_SHA256} *watchexec.tar.xz" | sha256sum -c - >/dev/null 2>&1; \
tar -xf watchexec.tar.xz; \
mv watchexec-${WATCHEXEC_VERSION}-${WATCHEXEC_ARCH}-unknown-linux-musl/watchexec /usr/local/bin/; \
rm -rf watchexec.tar.xz watchexec-${WATCHEXEC_VERSION}-${WATCHEXEC_ARCH}-unknown-linux-musl; \
}; \
# smoke tests
[ "$(command -v overmind)" = '/usr/local/bin/overmind' ]; \
[ "$(command -v watchexec)" = '/usr/local/bin/watchexec' ]; \
overmind --version; \
watchexec --version

0 comments on commit 063b06b

Please sign in to comment.