Skip to content

Commit b4620f4

Browse files
authored
perf: build the sqb binary and the extension from one set of compiled dependencies (#1179)
* perf: build the crates sqb shares with the extension once The sqb build resolved several dependency features differently from the extension build, so Cargo compiled polyglot-sql, sqlbuild-analysis, sqlbuild-rules and their dependencies twice in every wheel and uv sync. A new code-free sqlbuild-build-features crate enables the missing features in the sqb build, and make check-build-features fails when the two builds drift apart again. * fix: read cargo tree without colour in the build features check * ci: let the macOS sqb wheel build reuse the extension's crates
1 parent f21d774 commit b4620f4

27 files changed

Lines changed: 564 additions & 3 deletions

File tree

‎.github/workflows/build-distributions.yml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ jobs:
135135
manylinux: auto
136136
- uses: PyO3/maturin-action@v1
137137
if: inputs.prebuilt-run-id == ''
138+
# On macOS maturin links the extension with these flags for every crate, which changes
139+
# their build hash. Passing the same flags here lets sqb reuse the crates the extension
140+
# build just compiled instead of compiling them again; sqb has no undefined symbols, and
141+
# the smoke test below runs it.
142+
env:
143+
RUSTFLAGS: >-
144+
${{ runner.os == 'macOS' && '-C link-arg=-undefined -C link-arg=dynamic_lookup' || '' }}
138145
with:
139146
command: build
140147
args: >-

‎Cargo.lock‎

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[workspace]
22
members = [
3+
"crates/sqlbuild-build-features",
34
"crates/sqlbuild-core",
45
"crates/sqlbuild-cursor",
56
"crates/sqlbuild-state",
@@ -27,6 +28,7 @@ resolver = "2"
2728
# out of every crate below the polyglot floor. See crates/README.md.
2829
[workspace.metadata.native-layers]
2930
order = [
31+
"sqlbuild-build-features",
3032
"sqlbuild-core",
3133
"sqlbuild-cursor",
3234
"sqlbuild-state",
@@ -79,6 +81,17 @@ polyglot-sql-function-catalogs = { git = "https://github.com/chio-labs/polyglot.
7981
"dialect-duckdb",
8082
] }
8183
blake3 = { version = "1", features = ["rayon"] }
84+
# Only sqlbuild-build-features uses these: each enables in the sqb build exactly the features the
85+
# extension build resolves for that crate, so both builds share one compile of every common crate.
86+
arrayvec = "0.7"
87+
bstr = "1"
88+
either = { version = "1", default-features = false, features = ["use_std"] }
89+
memchr = "2"
90+
once_cell = "1"
91+
regex-automata = { version = "0.4", default-features = false, features = ["dfa-search"] }
92+
syn-v2-macro-features = { package = "syn", version = "2", default-features = false, features = ["extra-traits", "fold", "visit-mut"] }
93+
syn-v3-macro-features = { package = "syn", version = "3", default-features = false, features = ["extra-traits", "full"] }
94+
thiserror = "2"
8295
# Windows only: `sqb` ignores Ctrl+C while the Python CLI it started handles it.
8396
ctrlc = "3"
8497
quote = "1"
@@ -101,6 +114,7 @@ serde_json = { version = "1", features = ["preserve_order"] }
101114
sha2 = "0.10"
102115
sqlbuild-analysis = { path = "crates/sqlbuild-analysis" }
103116
sqlbuild-attachments = { path = "crates/sqlbuild-attachments" }
117+
sqlbuild-build-features = { path = "crates/sqlbuild-build-features" }
104118
sqlbuild-cache = { path = "crates/sqlbuild-cache" }
105119
sqlbuild-cli = { path = "crates/sqlbuild-cli" }
106120
sqlbuild-config = { path = "crates/sqlbuild-config" }

‎Makefile‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
SHELL := /bin/bash
22

3-
.PHONY: verify verify-quick verify-pg coverage cli-preview rust-check check-native-layering check-python-boundary check-release-gate check-docs-skill \
3+
.PHONY: verify verify-quick verify-pg coverage cli-preview rust-check check-native-layering check-build-features check-python-boundary check-release-gate check-docs-skill \
44
check-e2e-shards test-e2e-duckdb test-e2e-duckdb-build-core \
55
test-e2e-duckdb-build-incremental \
66
test-e2e-duckdb-cli-data test-e2e-duckdb-cli test-e2e-duckdb-inspection \
@@ -641,7 +641,7 @@ verify-quick:
641641
exit $$status
642642

643643

644-
check-ci: check-e2e-shards check-native-layering check-python-boundary check-release-gate check-docs-skill rust-lint
644+
check-ci: check-e2e-shards check-native-layering check-build-features check-python-boundary check-release-gate check-docs-skill rust-lint
645645
uv run ruff format --check .
646646
uv run ruff check .
647647
uv run ty check src tests
@@ -653,6 +653,10 @@ check-native-layering:
653653
uv run python -m scripts.check_native_layering
654654

655655

656+
check-build-features:
657+
uv run python -m scripts.check_build_features
658+
659+
656660
check-python-boundary:
657661
uv run python -m scripts.check_python_boundary
658662

‎crates/README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ that can be tested and benchmarked with `cargo test` alone.
66

77
| Crate | Responsibility |
88
|---|---|
9+
| `sqlbuild-build-features` | No code. Enables, in the `sqb` build, the dependency features the extension build resolves, so Cargo compiles the crates both builds share (polyglot-sql, `sqlbuild-analysis`, `sqlbuild-rules` and the rest) once. `make check-build-features` (part of `make check-ci`) fails when the two builds resolve a shared crate differently and names the features to add. |
910
| `sqlbuild-core` | Constants shared by several crates, the panic boundary that turns an unwinding native failure into a named compiler error, passive identity, diagnostic and SQL value types, text positions, a JSON emitter whose output matches Python's `json.dumps` and `orjson` byte for byte, and run-cost allocation with exact Python `decimal` default-context arithmetic and Snowflake query-history SQL. |
1011
| `sqlbuild-cursor` | Microbatch cursor algebra: typed cursor values, grain flooring and stepping, half-open interval clamping, merging and batch splitting, timestamp text normalization and calendar durations, with Python `datetime` results and errors. Zones other than fixed offsets are resolved through a caller-supplied lookup. |
1112
| `sqlbuild-state` | Append-only warehouse state rows: content-addressed migration event IDs, typed event SQL literals and statements, and source freshness data-version normalization, hashing, equivalence, age policy and latest-state read SQL, byte-compatible with the rows Python wrote. It also owns execution history: lifecycle event batch digests and conflicts, run projection, event and run cursors, filter and page validation, and the SQLite and PostgreSQL statements the native history backends run. |
@@ -34,7 +35,7 @@ sqlbuild-python
3435
-> sqlbuild-refactor -> sqlbuild-rules -> sqlbuild-analysis -> sqlbuild-attachments
3536
-> sqlbuild-model-config -> sqlbuild-scopes -> sqlbuild-render -> sqlbuild-discovery -> sqlbuild-host
3637
-> sqlbuild-config -> sqlbuild-sqltext -> sqlbuild-cache -> sqlbuild-pysource -> sqlbuild-state -> sqlbuild-cursor -> sqlbuild-core
37-
sqlbuild-cli -> sqlbuild-cache, sqlbuild-core
38+
sqlbuild-cli -> sqlbuild-cache, sqlbuild-core, sqlbuild-build-features
3839
```
3940

4041
`sqlbuild-scopes` reuses the macro scanner in `sqlbuild-render`; render itself depends only on
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "sqlbuild-build-features"
3+
version.workspace = true
4+
description = "No code: makes the sqb build resolve dependency features exactly as the extension build does, so both builds share one compile of every common crate."
5+
edition.workspace = true
6+
license.workspace = true
7+
publish.workspace = true
8+
rust-version.workspace = true
9+
10+
# Cargo resolves features separately for each build, so without these entries the sqb build
11+
# hashes the crates it shares with the extension differently and compiles polyglot-sql,
12+
# sqlbuild-analysis and sqlbuild-rules a second time. The workspace entries enable in the sqb
13+
# build exactly the features the extension build already resolves; sqlbuild-cli depends on this
14+
# crate, so the extension build sees them too and stays unchanged. `make check-build-features`
15+
# fails when the two builds resolve a shared crate differently.
16+
[dependencies]
17+
arrayvec.workspace = true
18+
bstr.workspace = true
19+
either.workspace = true
20+
memchr.workspace = true
21+
once_cell.workspace = true
22+
regex-automata.workspace = true
23+
thiserror.workspace = true
24+
25+
# Proc-macro dependencies resolve with build dependencies, so the syn features PyO3's macros use
26+
# are enabled here. The empty build script makes Cargo resolve them.
27+
[build-dependencies]
28+
syn-v2-macro-features.workspace = true
29+
syn-v3-macro-features.workspace = true
30+
31+
[lints]
32+
workspace = true
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//! Empty: its presence makes Cargo resolve the build dependencies that align proc-macro features.
2+
3+
fn main() {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//! No code: aligns dependency features between the sqb and extension builds (see Cargo.toml).
2+
3+
#![forbid(unsafe_code)]

‎crates/sqlbuild-cli/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ blake3.workspace = true
2020
getrandom.workspace = true
2121
serde.workspace = true
2222
serde_json.workspace = true
23+
sqlbuild-build-features.workspace = true
2324
sqlbuild-cache.workspace = true
2425
sqlbuild-config.workspace = true
2526
sqlbuild-core.workspace = true

‎fensu.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,7 @@ remediation = "consume SQLBuild-owned SQL fact rows instead of raw parser types"
15671567
crate_names = [
15681568
"sqlbuild-analysis",
15691569
"sqlbuild-attachments",
1570+
"sqlbuild-build-features",
15701571
"sqlbuild-cache",
15711572
"sqlbuild-cli",
15721573
"sqlbuild-config",

0 commit comments

Comments
 (0)