Skip to content
Merged
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
39 changes: 39 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
# is experimental, macOS has no perf branch sampling for its profile, and BOLT has no PE support.
# Linux is static musl and non-PIE, so it starts on any x86-64 or arm64 Linux, Alpine too
# (npm/README.md, "Linux libc"). Each Linux tsc builds natively on a Blacksmith runner of its arch.
# Linux PGO builds link with rustup's rust-lld and fold identical functions (--icf=all). The Linux
# and macOS tsc ship without their symbol tables (stripped after the checks); the artifact
# unstripped-tsc-<platform> keeps the unstripped tsc for perf and profiles.
# Windows (x86_64-pc-windows-msvc, aarch64-pc-windows-msvc) builds in Git Bash, with the C runtime
# linked in (+crt-static), so tsc.exe needs no Visual C++ redistributable. jemalloc does not build
# there: it uses the system allocator. Each PGO tsc builds natively, so its training runs on its
Expand Down Expand Up @@ -194,6 +197,9 @@ jobs:
run: scripts/goport/pgo-train.sh setup "$RUNNER_TEMP/train"
# The same build with -Cprofile-generate, the training set, then -Cprofile-use. PGO_LINK (from
# the Build step) gives the RUSTFLAGS of the plain build. Separate target dirs (not cached).
# Linux: both builds link with rustup's rust-lld (gcc-ld/ld.lld; GNU ld has no --icf) and fold
# identical functions: about 0.27 MB less, almost all of it cold code, and the same code runs.
# The plain tsc keeps GNU ld, so the check below compares the folded tsc with an unfolded one.
- name: PGO build
if: ${{ !matrix.no-pgo }}
env:
Expand All @@ -202,6 +208,11 @@ jobs:
PGO_CARGO: cargo
CARGO_FEATURES: --features noembed
run: |
if [[ $RUNNER_OS == Linux ]]; then
gccld="$(rustc --print sysroot)/lib/rustlib/$(rustc -vV | sed -n 's/^host: //p')/bin/gcc-ld"
[[ -x $gccld/ld.lld ]] || { echo "::error::no $gccld/ld.lld"; exit 1; }
export PGO_RUSTFLAGS="-Clink-arg=-fuse-ld=lld -Clink-arg=-B$gccld -Clink-arg=-Wl,--icf=all"
fi
PGO_TRAIN="scripts/goport/pgo-train.sh run $RUNNER_TEMP/train" crates/ts_goport/scripts/build-pgo.sh "$RUNNER_TEMP/pgo"
mkdir -p "$RUNNER_TEMP/out"
cp "$RUNNER_TEMP/pgo/target-use/goport/tsgo${{ matrix.exe }}" "$RUNNER_TEMP/out/tsc${{ matrix.exe }}"
Expand Down Expand Up @@ -256,6 +267,34 @@ jobs:
echo "::error::tsc.exe imports the Visual C++ runtime (vcruntime140.dll)"
exit 1
fi
# Strip the symbol tables after the checks (about 5 MB on Linux). The code does not change. Not
# a cargo profile strip: a profile change changes -C metadata, and a use build then matches no
# function of the profile (a no-PGO tsc, with no warning). The program headers must not move:
# Linux before 5.18 finds them from the first segment, and musl's static start reads PT_TLS
# there. macOS: strip -x (local symbols) with Apple's strip, which signs a linker-signed arm64
# tsc again. macOS stops an arm64 tsc with a bad signature, so the --version run catches it.
- name: Strip the tsc
if: runner.os != 'Windows'
run: |
out="$RUNNER_TEMP/out" dir="$RUNNER_TEMP/check"
mkdir -p "$RUNNER_TEMP/unstripped"
cp "$out/tsc" "$RUNNER_TEMP/unstripped/tsc"
if [[ $RUNNER_OS == Linux ]]; then
strip --strip-all "$out/tsc"
cmp <(readelf -lW "$RUNNER_TEMP/unstripped/tsc") <(readelf -lW "$out/tsc")
else
/usr/bin/strip -x "$out/tsc"
fi
cp "$out/tsc" "$dir/tsc"
[[ $("$dir/tsc" --version) == "Version 7."* ]]
wc -c "$RUNNER_TEMP/unstripped/tsc" "$out/tsc"
- if: runner.os != 'Windows'
uses: actions/upload-artifact@v4
with:
name: unstripped-tsc-${{ matrix.platform }}
path: ${{ runner.temp }}/unstripped/tsc
if-no-files-found: error
retention-days: 90
- uses: actions/upload-artifact@v4
with:
name: tsc-${{ matrix.platform }}
Expand Down
12 changes: 9 additions & 3 deletions crates/ts_goport/scripts/build-pgo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
# build-bolt.sh refuses static bins, so they only make the file bigger.
# The build prints the .text and .rela.text sections of tsgo
# (readelf -S). Expect .text.hot, .text.unlikely and .rela.text. GNU ld (the
# linker of the musl target) ignores keep-text-section-prefix, but its default
# script already puts the hot and the unlikely code together inside .text.
# default linker of the musl target) ignores keep-text-section-prefix, but its
# default script already puts the hot and the unlikely code together inside
# .text. release.yml links the musl tsc with lld (PGO_RUSTFLAGS), which keeps
# the sections.
# Other platforms (macOS) get neither flag.
#
# Environment:
Expand Down Expand Up @@ -80,6 +82,10 @@
# and proc macros do not get the flags. The bins are
# copied to the usual <target>/goport path. The build
# checks the ELF type and INTERP of tsgo.
# PGO_RUSTFLAGS more RUSTFLAGS for both builds. The script sets
# RUSTFLAGS itself, so the caller's RUSTFLAGS do not
# reach cargo. release.yml passes the lld link args
# here (identical code folding on Linux).
#
# Choosing PGO_LINK (integrator, once a round): build the default and
# PGO_LINK=static. On cup2 (under its lock) time 'tsgo --version' and query
Expand Down Expand Up @@ -189,7 +195,7 @@ triple="${PGO_TARGET:-}"
# Each step needs its own target (other RUSTFLAGS). sccache is off: it could
# reuse an object built with an older profile at the same path.
build() { # build <target-subdir> <rustflags>
local target="$out/$1" flags="$2 $link_flags" target_args=""
local target="$out/$1" flags="$2 $link_flags ${PGO_RUSTFLAGS:-}" target_args=""
# Both builds get the same link mode, so the profile of the generate build
# matches the code of the use build.
[[ -n $triple ]] && target_args="--target $triple"
Expand Down
Loading