Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ WORKDIR /workspace/bun

ENV BUN_NO_CORE_DUMP=1

# Bootstrap development environment and prepare build directories
RUN sh -c "git pull && scripts/bootstrap.sh"

# Put the LLVM that bootstrap.sh just installed on PATH, unversioned.
# bootstrap.sh does this itself with `append_to_path /usr/lib/llvm-N/bin`,
# but that only writes shell profiles, which Docker RUN/exec shells never
# source, and its /usr/bin/llvm-symbolizer symlink lives in the Ubuntu-only
# install_gcc path, so on this Debian image `clang`, `ld.lld`,
# `llvm-symbolizer` etc. resolve only as `-N` names. A stable
# /usr/lib/llvm-current -> the newest llvm-N tracks whatever version bun
# main pins without editing this file on every LLVM bump.
# Install the toolchain: the script that oven-sh/bun generates for its CI
# machines, up to its prefetch section. install-toolchain.sh has the details.
COPY install-toolchain.sh /tmp/install-toolchain.sh
RUN git pull && sh /tmp/install-toolchain.sh && rm /tmp/install-toolchain.sh

# Put the LLVM that the script just installed on PATH, unversioned.
# The script does this itself, but in /etc/profile.d/bun-ci.sh, which only
# login shells read. Docker RUN/exec shells never do, so on this Debian image
# `clang`, `ld.lld`, `llvm-symbolizer` etc. resolve only as `-N` names. A
# stable /usr/lib/llvm-current -> the newest llvm-N tracks whatever version
# bun main pins without editing this file on every LLVM bump.
RUN set -eu; \
llvm_dir="$(ls -d /usr/lib/llvm-[0-9]* | sort -V | tail -n1)"; \
test -x "$llvm_dir/bin/clang"; \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This image contains:
- Debian bookworm slim as the base OS
- Bun repository cloned to `/workspace/bun`
- Development dependencies installed
- Bootstrap script already executed
- The toolchain of Bun's CI machines, installed by the script that oven-sh/bun generates for them (see `install-toolchain.sh`)
- Modern GCC/G++ 12 with full C++20 support (including constexpr std::array<std::string>)

### Pre-built Image
Expand Down
61 changes: 61 additions & 0 deletions install-toolchain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/sh
# Installs the toolchain that builds and tests Bun, inside `docker build`.
#
# oven-sh/bun generates the script that its CI machines are baked with, from
# scripts/build/ci-images/spec.ts (`bun run ci:images`). It replaced
# scripts/bootstrap.sh in oven-sh/bun#43608. This file generates that script
# for Debian 13 on this architecture and runs it, with two differences from a
# CI bake:
#
# - `role: "test"` leaves out the cross-compile SDKs and sysroots. Only the
# one CI machine that compiles every target needs them.
# - The script is cut before its `prefetch` section. That section and the ones
# after it need a Docker daemon and an init system. The documentation in
# scripts/build/ci-images/ ("Testing a change before CI does") says to cut
# there.
#
# Run it as root, from the root of a checkout of oven-sh/bun. It needs `bun`
# on PATH to run the generator. The generated script cannot run twice.
set -eu

spec=scripts/build/ci-images/spec.ts
if ! [ -f "$spec" ]; then
echo "install-toolchain: $(pwd) has no $spec. A ref older than oven-sh/bun#43608 cannot be built." >&2
exit 1
fi

bake_root=$(mktemp -d -p /var/tmp)
bake=$(BAKE_ROOT="$bake_root" bun -e '
import { generateImage, images } from "./scripts/build/ci-images/spec.ts";
const arch = process.arch === "arm64" ? "aarch64" : "x64";
const image = images.find(i => i.os === "linux" && i.distro === "debian" && i.arch === arch);
if (!image) throw new Error("spec.ts has no Debian image for " + arch);
console.log(generateImage({ ...image, role: "test" }, process.env.BAKE_ROOT).directory);
')

if ! grep -q '^# ---- prefetch$' "$bake/bootstrap.sh"; then
echo "install-toolchain: the generated script has no \"# ---- prefetch\" section to cut at." >&2
exit 1
fi
sed '/^# ---- prefetch$/,$d' "$bake/bootstrap.sh" > "$bake/toolchain.sh"
echo "install-toolchain: sections: $(grep '^# ---- ' "$bake/toolchain.sh" | cut -c8- | tr '\n' ' ')"

# Some lookups of apt.llvm.org return one IPv6 address and nothing else. A
# build container has no IPv6 route, so curl and wget fail at once ("Network
# is unreachable", and llvm.sh then says the distribution "is not supported").
# Their retries reuse the failed lookup. These files make both tools ask for
# IPv4 only and look the name up again for each retry. CURL_HOME and WGETRC
# apply them to the generated script and to nothing else.
printf 'ipv4\nretry-all-errors\n' > "$bake_root/.curlrc"
printf 'inet4_only = on\nretry_on_host_error = on\nretry_connrefused = on\n' > "$bake_root/wgetrc"

CURL_HOME="$bake_root" WGETRC="$bake_root/wgetrc" \
sh "$bake/toolchain.sh" "$(git rev-parse HEAD)" bun-development-docker-image
rm -rf "$bake_root"

# The script writes the node-gyp header cache for CI's agent user alone. Root
# gets a copy, as bootstrap.sh gave it, so that a native addon builds without
# a download of the headers.
agent_home=$(getent passwd buildkite-agent | cut -d: -f6)
mkdir -p /root/.cache
cp -R "$agent_home/.cache/node-gyp" /root/.cache/