From be33de1086b2ff8a4ff523b569bbaac8fd34f209 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 9 Sep 2025 11:56:26 +0200 Subject: [PATCH] GNUmakefile: shrink TinyGo binaries on Linux With these flags, the TinyGo binary gets 18.8MB (11.6%) smaller. That seems like a quite useful win for such a small change! This is only for Linux for now. MacOS and Windows can be tested later, the flags for those probably need to be modified. Originally inspired by: https://discourse.llvm.org/t/state-of-the-art-for-reducing-executable-size-with-heavily-optimized-program/87952/18 There are some other flags like -Wl,--pack-dyn-relocs=relr that did not shrink binary size in my testing, so I've left them out. This also switches the linker to prefer mold or lld over the default linker, since the system linker is usually ld.bfd which is very slow. (Also, for some reason mold produces smaller binaries than lld). --- .github/workflows/linux.yml | 8 ++++---- GNUmakefile | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index b44962db1..1ceb1b413 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -26,7 +26,7 @@ jobs: # tar: needed for actions/cache@v4 # git+openssh: needed for checkout (I think?) # ruby: needed to install fpm - run: apk add tar git openssh make g++ ruby-dev + run: apk add tar git openssh make g++ ruby-dev mold - name: Work around CVE-2022-24765 # We're not on a multi-user machine, so this is safe. run: git config --global --add safe.directory "$GITHUB_WORKSPACE" @@ -73,7 +73,7 @@ jobs: uses: actions/cache/restore@v4 id: cache-llvm-build with: - key: llvm-build-19-linux-alpine-v1 + key: llvm-build-19-linux-alpine-v2 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -222,7 +222,7 @@ jobs: uses: actions/cache/restore@v4 id: cache-llvm-build with: - key: llvm-build-19-linux-asserts-v1 + key: llvm-build-19-linux-asserts-v2 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -329,7 +329,7 @@ jobs: uses: actions/cache/restore@v4 id: cache-llvm-build with: - key: llvm-build-19-linux-${{ matrix.goarch }}-v3 + key: llvm-build-19-linux-${{ matrix.goarch }}-v4 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' diff --git a/GNUmakefile b/GNUmakefile index 163d8ef88..7fea90406 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -79,6 +79,26 @@ ifeq (1, $(STATIC)) BINARYEN_OPTION += -DCMAKE_CXX_FLAGS="-static" -DCMAKE_C_FLAGS="-static" endif +# Optimize the binary size for Linux. +# These flags may work on other platforms, but have only been tested on Linux. +ifeq ($(uname),Linux) + HAS_MOLD := $(shell command -v ld.mold 2> /dev/null) + HAS_LLD := $(shell command -v ld.lld 2> /dev/null) + LLVM_CFLAGS := -ffunction-sections -fdata-sections -fvisibility=hidden + LLVM_LDFLAGS := -Wl,--gc-sections + ifneq ($(HAS_MOLD),) + # Mold might be slightly faster. + LLVM_LDFLAGS += -fuse-ld=mold -Wl,--icf=all + else ifneq ($(HAS_LLD),) + # LLD is more commonly available. + LLVM_LDFLAGS += -fuse-ld=lld -Wl,--icf=all + endif + LLVM_OPTION += \ + -DCMAKE_C_FLAGS="$(LLVM_CFLAGS)" \ + -DCMAKE_CXX_FLAGS="$(LLVM_CFLAGS)" + CGO_LDFLAGS += $(LLVM_LDFLAGS) +endif + # Cross compiling support. ifneq ($(CROSS),) CC = $(CROSS)-gcc