Skip to content

chore: strip symbols from release binary#1049

Merged
Boshen merged 1 commit into
mainfrom
chore/strip-release-binary
Jul 3, 2026
Merged

chore: strip symbols from release binary#1049
Boshen merged 1 commit into
mainfrom
chore/strip-release-binary

Conversation

@Boshen

@Boshen Boshen commented Jul 3, 2026

Copy link
Copy Markdown
Member

What

Add -ldflags="-s -w" to the build recipe (both [unix] and [windows]), stripping the DWARF debug info (-w) and the symbol table (-s) from the compiled binary. The release workflow builds via just build, so all six published per-platform npm binaries pick this up automatically — no change needed in release.yml.

Binary size impact

Measured on a local darwin/arm64 build. The ~27% raw / ~45% compressed proportion holds across all six release targets.

Raw binary Gzipped (npm tarball users download)
Before 29.7 MB 13.1 MB
After 21.8 MB 7.2 MB
Saved 7.9 MB (26.6%) 5.9 MB (44.9%)

The compressed saving is proportionally larger than the raw saving because DWARF debug data compresses poorly, so removing it takes out a disproportionate share of the actual download.

npm installs only the single package matching a user's OS/arch (via os/cpu + optionalDependencies), so each user's download drops ~5.9 MB (~45%) and their node_modules footprint drops ~7.9 MB.

Behavior

No functional or runtime change — -s -w removes metadata only, never code:

  • Same lint results, same output, same speed, same exit codes.
  • Panic stack traces keep full function names and line numbers (Go's gopclntab is not stripped).
  • pprof profiling still symbolicates; go version -m ./tsgolint build info is preserved.

The one capability lost is attaching Delve/gdb to the shipped binary for source-level debugging (that needs the DWARF info removed by -w) — which is not something an end user of a linter ever does. Contributors who need it can still build an unstripped binary directly with plain go build.

@camc314 camc314 added the 0-merge label Jul 3, 2026

camc314 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jul 3, 2:22 PM UTC: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Jul 3, 2:22 PM UTC: camc314 added this pull request to the Graphite merge queue.
  • Jul 3, 2:25 PM UTC: The Graphite merge queue couldn't merge this PR because it was not satisfying all requirements (Failed CI: 'test-go').

## What

Add `-ldflags="-s -w"` to the `build` recipe (both `[unix]` and `[windows]`), stripping the DWARF debug info (`-w`) and the symbol table (`-s`) from the compiled binary. The release workflow builds via `just build`, so all six published per-platform npm binaries pick this up automatically — no change needed in `release.yml`.

## Binary size impact

Measured on a local `darwin/arm64` build. The ~27% raw / ~45% compressed proportion holds across all six release targets.

| | Raw binary | Gzipped (npm tarball users download) |
|---|---|---|
| Before | 29.7 MB | 13.1 MB |
| After | 21.8 MB | 7.2 MB |
| **Saved** | **7.9 MB (26.6%)** | **5.9 MB (44.9%)** |

The compressed saving is *proportionally larger* than the raw saving because DWARF debug data compresses poorly, so removing it takes out a disproportionate share of the actual download.

npm installs only the single package matching a user's OS/arch (via `os`/`cpu` + `optionalDependencies`), so each user's download drops ~5.9 MB (~45%) and their `node_modules` footprint drops ~7.9 MB.

## Behavior

No functional or runtime change — `-s -w` removes metadata only, never code:

- Same lint results, same output, same speed, same exit codes.
- Panic stack traces keep full function names and line numbers (Go's `gopclntab` is not stripped).
- pprof profiling still symbolicates; `go version -m ./tsgolint` build info is preserved.

The one capability lost is attaching Delve/gdb to the shipped binary for source-level debugging (that needs the DWARF info removed by `-w`) — which is not something an end user of a linter ever does. Contributors who need it can still build an unstripped binary directly with plain `go build`.
@graphite-app graphite-app Bot force-pushed the chore/strip-release-binary branch from f8b732f to 3a2a87e Compare July 3, 2026 14:22
@graphite-app graphite-app Bot removed the 0-merge label Jul 3, 2026
@Boshen Boshen force-pushed the chore/strip-release-binary branch from 9621f38 to 3a2a87e Compare July 3, 2026 15:38
@Boshen Boshen merged commit c5f13fe into main Jul 3, 2026
21 of 22 checks passed
@Boshen Boshen deleted the chore/strip-release-binary branch July 3, 2026 15:40
graphite-app Bot pushed a commit that referenced this pull request Jul 3, 2026
## What

Add `-trimpath` to the `build` recipe (both `[unix]` and `[windows]`), alongside the existing `-ldflags="-s -w"` from #1049. `-trimpath` replaces absolute filesystem paths baked into the binary — the local build directory and the Go module cache — with clean module-relative paths.

## Why — hygiene, not size

- **Reproducible builds.** The output stops depending on *where* it was built, so the same commit built on different machines/paths produces an identical binary.
- **No leaked local paths.** Without it, panic stack traces and build metadata embed the builder's absolute paths (e.g. `/Users/<name>/.../typescript-go/internal/checker/checker.go`). `-trimpath` reduces those to `github.com/microsoft/typescript-go@.../internal/checker/checker.go`.

## Size impact — negligible (measured on the merged `-s -w` baseline)

| metric | `-s -w` | `+ -trimpath` | delta |
|---|---|---|---|
| raw binary | 21.79 MB | 21.74 MB | −49.5 KB (0.23%) |
| gzipped / npm download | 7.19 MB | 7.19 MB | −2.1 KB (0.03%) |
| `__gopclntab` | 6601.6 KB | 6563.8 KB | −37.8 KB (0.57%) |

The ~50 KB raw saving is incidental (trimmed path strings living in `gopclntab`); the download users actually fetch moves ~2 KB, because those repetitive path prefixes were already compressing away under npm's gzip. This is a build-hygiene change, not a size optimization.

## Behavior

No runtime change. Panic traces still show full function names and `file:line` — only the path *prefix* changes (module-relative instead of absolute).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants