Skip to content

Instantly share code, notes, and snippets.

@marcs-feh
Last active January 6, 2024 16:12
Show Gist options
  • Save marcs-feh/d8a1b31cd2f5302a194470c96291b234 to your computer and use it in GitHub Desktop.
Save marcs-feh/d8a1b31cd2f5302a194470c96291b234 to your computer and use it in GitHub Desktop.
"Portable" Odin build
# Container file to build a "portable" odin installation across Linux
# distributions. Bundles required .so files in one folder including the
# interpreter. Keep in mind Odin still requires clang (>=11) to be installed,
# this might change in the future
#
# Step 1: Build the image
# podman build -t odin-linux . --build-arg BUILD_TYPE=release
#
# Step 2: Run the image
# podman run --name Odin localhost/odin-linux:latest
#
# Step 3: The container environment is not meant to be used, just copy the tarball
# podman cp Odin:/odin/odin-linux.tgz .
#
# Step 4: Remove the image
# podman rm --force Odin
#
# Step 5: Profit?
# You should have the odin magic tarball in your current working dir, if you
# have patchelf installed, it is highly recommended that you use the relocate
# script to the desired directory (I recommend just using `./lib`), otherwhise
# you'll only be able to run the odin executable from within the folder because
# of the hard-coded musl-loader.
#
# Step 6: OPTIONAL, cleanup the mess, only do this if you know what these commands do:
# podman container prune --force & podman container cleanup --rm --rmi --all
ENV BUILD_TYPE="release"
ENV CXX="clang++-17"
ENV LLVM_CONFIG="llvm-config-17"
FROM alpine:3.19
WORKDIR /
RUN apk add \
git make musl-dev patchelf \
llvm17 clang17 llvm17-dev
RUN git clone https://github.com/odin-lang/Odin --depth=1 odin
WORKDIR /odin
RUN ./build_odin.sh ${BUILD_TYPE}
RUN mkdir -p .dist/lib
RUN cp /lib/ld-musl-x86_64.so.1 .dist/lib \
&& cp /usr/lib/libstdc++.so.6 .dist/lib \
&& cp ./libLLVM-17.so .dist/lib \
&& cp /usr/lib/libgcc_s.so.1 .dist/lib \
&& cp /usr/lib/libffi.so.8 .dist/lib \
&& cp /lib/libz.so.1 .dist/lib \
&& cp /usr/lib/libzstd.so.1 .dist/lib \
&& cp /usr/lib/libxml2.so.2 .dist/lib \
&& cp /usr/lib/liblzma.so.5 .dist/lib \
&& cp /usr/lib/liblzma.so.5 .dist/lib \
&& cp /lib/libc.musl-x86_64.so.1 .dist/lib
RUN echo '#!/usr/bin/env sh' >> .reloc \
&& echo '' >> .reloc \
&& echo 'targetDir="$1"' >> .reloc \
&& echo '' >> .reloc \
&& echo 'test -z "$targetDir" && {' >> .reloc \
&& echo ' echo "$0 [DIR]"' >> .reloc \
&& echo ' exit 1' >> .reloc \
&& echo '}' >> .reloc \
&& echo '' >> .reloc \
&& echo 'set -e' >> .reloc \
&& echo '' >> .reloc \
&& echo 'orig="$(readlink -f ./lib/ld-musl-x86_64.so.1)"' >> .reloc \
&& echo 'targetDir="$(readlink -f "$targetDir")"' >> .reloc \
&& echo 'loader="$targetDir/ld-musl-x86_64.so.1"' >> .reloc \
&& echo '' >> .reloc \
&& echo 'test "$orig" != "$loader" \' >> .reloc \
&& echo ' && cp ./lib/ld-musl-x86_64.so.1 "$targetDir"' >> .reloc \
&& echo '' >> .reloc \
&& echo 'patchelf --set-interpreter "$loader" odin' >> .reloc \
&& echo '' >> .reloc \
&& echo 'echo "Relocated loader for odin to $loader"' >> .reloc
RUN mv .reloc .dist/relocate-odin.sh
# Just to make sure
RUN chmod +x .dist/lib/lib* .dist/relocate-odin.sh
RUN cp odin .dist \
&& cp LICENSE .dist \
&& cp -r core .dist \
&& cp -r vendor .dist
RUN patchelf --set-rpath '$ORIGIN/lib/' .dist/lib/lib*
# NOTE: This will require the odin executable to be run within the folder
# always, it is possible to relocate it later with patchelf for convenience
RUN patchelf --set-interpreter './lib/ld-musl-x86_64.so.1' .dist/odin
RUN mv .dist odin-linux \
&& tar czf odin-linux.tgz odin-linux
ENTRYPOINT /bin/sh -c 'echo "The build is already done, copy the file /odin/odin-linux.tgz out of the container."; read _ '
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment