Stop compiling the GPL crate GPUI drags in behind the framework
Lumbridge is Apache-2.0, and decision 0023 quietly made it link
GPL-3.0-or-later. `crates/gpui/Cargo.toml` at the pinned revision carries
`ztracing.workspace = true` -- unconditional, not optional, not behind a
feature -- and `ztracing` is GPL-3.0-or-later, as are the `zlog` and
`ztracing_macro` it pulls. `sum_tree` asks for it too. The path is the ordinary
Linux build, not an `--all-features` artefact and not a dev-dependency:
lumbridge -> gpui_platform -> gpui_linux -> gpui -> ztracing -> zlog
-> ztracing_macro
`cargo deny check licenses` failed on it, exit 4.
This is the second thing decision 0023 got wrong by reading the manifests of the
crates it added instead of resolving the graph; the first was believing there
were two Zed Git sources when there are five. Both were found by a gate that had
never been run.
There was no feature to turn off, so the choice was to relax the licence policy,
drop the framework, or stop compiling the crate. `ztracing` is now redirected by
a `[patch]` table at `crates/lumbridge-ztracing-shim`, a first-party
zero-dependency no-op under Apache-2.0. `zlog` and `ztracing_macro` were
reachable only through it and leave the lockfile with it.
The shim is small because the usage is: nine `#[instrument(skip_all)]` sites
across `gpui/src/svg_renderer.rs`, `sum_tree/src/sum_tree.rs` and
`sum_tree/src/cursor.rs`, and nothing else. Upstream's own crate compiles to
almost exactly this whenever the `ztracing` cfg is off, which is every build
that is not a Tracy profiling build, so no shipping behaviour is lost. It is a
proc-macro crate deliberately: such a crate can export nothing but proc macros,
so an upstream revision that starts using `ztracing::Span` or
`ztracing::info_span!` fails to compile and names the shim, rather than
resolving to something plausible.
`scripts/workspace-guard.sh` gained a third gate asserting, against Cargo.lock
rather than the manifest, that no `ztracing`, `zlog` or `ztracing_macro`
resolves to a Zed source and that the patch table is still present. `cargo deny`
already checks this, and the duplication is the point: `scripts/ci.sh`
downgrades a missing cargo-deny to a warning unless `LUMBRIDGE_CI_STRICT=1`, and
that is how the licence closure went ungated once already. A `[patch]` is an
unusually quiet thing to lose -- delete the table and everything still compiles,
still passes, and is GPL again.
Removing the three GPL rejections exposed a fourth that had been sitting beside
them and was never reported separately: `libbz2-rs-sys` under `bzip2-1.0.6`,
reached through async-compression <- http_client <- gpui. It is BSD-style and
permissive with no copyleft, and is allowed in `deny.toml` with that reasoning
written down. `cargo deny check licenses sources` is exit 0 for the first time.
The Git-source allowances in `deny.toml` are all still needed; the patched
crate's own source was `zed.git`, which `gpui` still requires.
Decision 0025 records the whole of it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPYebLiN2w4TqnHUYGdECq
This commit is contained in:
co-authored by
Claude Opus 5
parent
3cb5e1002c
commit
2aab0c4aab
@@ -0,0 +1,126 @@
|
||||
# 0025: GPUI's GPL dependency is patched out, not tolerated
|
||||
|
||||
Status: accepted. Amends decision 0023, which chose the pinned Zed revision
|
||||
without noticing what came with it. Does not change that revision.
|
||||
|
||||
## The decision
|
||||
|
||||
`ztracing` is redirected, by a `[patch]` table in the root manifest, at
|
||||
`crates/lumbridge-ztracing-shim` — a first-party, zero-dependency, no-op crate
|
||||
under Apache-2.0. Nothing else about decision 0023's pin changes.
|
||||
|
||||
## The problem
|
||||
|
||||
Lumbridge is Apache-2.0, and `DISTRIBUTION.md` treats the licence closure of
|
||||
everything the product links as a hard gate. Decision 0023 replaced published
|
||||
`gpui` releases with a pinned revision of Zed's monorepo, and a monorepo
|
||||
revision does not bring only the crates you named. `crates/gpui/Cargo.toml` at
|
||||
`ce48461` carries:
|
||||
|
||||
```toml
|
||||
ztracing.workspace = true
|
||||
```
|
||||
|
||||
Unconditional. Not optional. Not behind a feature. `ztracing` is
|
||||
**GPL-3.0-or-later**, and it pulls `zlog` and `ztracing_macro`, both also
|
||||
GPL-3.0-or-later. `sum_tree` asks for `ztracing` as well. The path is entirely
|
||||
inside the build that ships:
|
||||
|
||||
```text
|
||||
lumbridge -> gpui_platform -> gpui_linux -> gpui -> ztracing -> zlog
|
||||
-> ztracing_macro
|
||||
```
|
||||
|
||||
This is not an `--all-features` artefact and not a dev-dependency. It is the
|
||||
ordinary Linux build. `cargo deny check licenses` failed on it, exit 4, three
|
||||
rejections, each `license is not explicitly allowed`.
|
||||
|
||||
That is the second thing decision 0023 got wrong by reading manifests instead of
|
||||
resolving a graph. The first was believing there were two Zed Git sources when
|
||||
there are five. Both were caught by a gate that had never been run, and both
|
||||
argue the same point: the transitive closure is the only thing that answers a
|
||||
licensing question.
|
||||
|
||||
## What was rejected
|
||||
|
||||
**Relax `deny.toml`.** Adding GPL-3.0-or-later to the allow list would trade the
|
||||
product's licence for a green build. The gate exists precisely to stop that
|
||||
being done quietly.
|
||||
|
||||
**Turn the feature off.** There is no feature. `ztracing.workspace = true` has
|
||||
no `optional = true` beside it, and no `cfg` guards its use sites.
|
||||
|
||||
**Drop GPUI.** That throws away decision 0023 and, until `lumbridge-toolkit`
|
||||
exists, the product's ability to draw a window.
|
||||
|
||||
**Vendor and relicense.** Not available: GPL is GPL.
|
||||
|
||||
## What was chosen, and why it is small
|
||||
|
||||
Every use of `ztracing` and `zlog` across the eighteen Zed packages in the
|
||||
resolved graph, found by grepping the vendored checkout rather than the
|
||||
manifests:
|
||||
|
||||
- `gpui/src/svg_renderer.rs`, two sites: `#[ztracing::instrument(skip_all)]`
|
||||
- `sum_tree/src/sum_tree.rs` and `sum_tree/src/cursor.rs`:
|
||||
`use ztracing::instrument;`, then seven `#[instrument(skip_all)]` sites
|
||||
- `sum_tree/src/sum_tree.rs:1401`: `zlog::init_test()`, inside `#[cfg(test)]`,
|
||||
behind a dev-dependency Cargo never resolves for a non-workspace package —
|
||||
which is why no `zlog` shim is needed and why `zlog` leaves the lockfile
|
||||
entirely
|
||||
|
||||
Nine attribute sites, all `skip_all`, and nothing else. So the shim is one
|
||||
attribute proc-macro that returns its input unchanged. Upstream's own crate
|
||||
compiles to almost exactly that whenever the `ztracing` cfg is off — which is
|
||||
every build that is not a Tracy profiling build — so no shipping behaviour is
|
||||
lost. Lumbridge ships no telemetry by default in any case.
|
||||
|
||||
Because `zlog` and `ztracing_macro` were reachable only through `ztracing`,
|
||||
patching the one package removes all three: they no longer appear in
|
||||
`Cargo.lock`.
|
||||
|
||||
## How it is held
|
||||
|
||||
`scripts/workspace-guard.sh` gained a third gate. It asserts, against
|
||||
`Cargo.lock` rather than the manifest, that no `ztracing`, `zlog` or
|
||||
`ztracing_macro` resolves to a Zed source, and that the `[patch]` table is still
|
||||
in `Cargo.toml`.
|
||||
|
||||
`cargo deny` already checks this, so the duplication is deliberate.
|
||||
`scripts/ci.sh` downgrades a missing `cargo-deny` to a warning unless
|
||||
`LUMBRIDGE_CI_STRICT=1`, and that arrangement is how the licence closure went
|
||||
ungated once already — green on a runner that had never installed the tool. The
|
||||
guard needs no tool and runs in milliseconds. It is what makes deleting the
|
||||
patch a build failure rather than a silent relicensing of the product.
|
||||
|
||||
A `[patch]` is an unusually quiet thing to lose: delete the table and everything
|
||||
still compiles, still passes every test, and is GPL again.
|
||||
|
||||
## The unrelated failure this exposed
|
||||
|
||||
Removing the three GPL rejections left one behind that had been sitting beside
|
||||
them: `libbz2-rs-sys` under the `bzip2-1.0.6` licence, reached through
|
||||
`bzip2 -> compression-codecs -> async-compression -> http_client -> gpui`. It is
|
||||
BSD-style and permissive — retain the notice, do not misrepresent the origin, no
|
||||
warranty — with no copyleft and no source-disclosure term, and it is allowed in
|
||||
`deny.toml` with that reasoning written down. It is recorded here because it was
|
||||
never reported as a separate finding; it was simply the fourth line of a failure
|
||||
everyone read as being about GPL.
|
||||
|
||||
## What the next revision bump must check
|
||||
|
||||
Whether upstream started using a `ztracing` symbol the shim does not provide.
|
||||
The shim is a proc-macro crate, which can export nothing except proc macros, so
|
||||
`ztracing::Span`, `ztracing::info_span!`, `ztracing::init()`, `ztracing::Level`
|
||||
and `ztracing::field` all fail to resolve at compile time and name this crate in
|
||||
the error. There is no silent fallback.
|
||||
|
||||
The fix then is not to widen the shim by reflex. If the new use is another
|
||||
zero-cost annotation, add the matching no-op — which means splitting the shim
|
||||
into a library crate and a proc-macro crate, since one package cannot be both.
|
||||
If upstream has started routing real telemetry through `ztracing`, that is a
|
||||
decision record, because no telemetry is enabled by default here.
|
||||
|
||||
And run `cargo deny check licenses sources` at the new revision before anything
|
||||
else. A monorepo pin can acquire a *different* GPL crate on a different path,
|
||||
and reading the manifests of the crates you added will not find it.
|
||||
Reference in New Issue
Block a user