forked from pydantic/monty
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
263 lines (212 loc) · 10.5 KB
/
Copy pathMakefile
File metadata and controls
263 lines (212 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
.DEFAULT_GOAL := main
ifeq ($(OS),Windows_NT)
EXE_EXT := .exe
else
EXE_EXT :=
endif
.PHONY: .cargo
.cargo: ## Check that cargo is installed
@cargo --version || echo 'Please install cargo: https://github.com/rust-lang/cargo'
.PHONY: .uv
.uv: ## Check that uv is installed
@uv --version || echo 'Please install uv: https://docs.astral.sh/uv/getting-started/installation/'
.PHONY: install-py
install-py: .uv ## Install python dependencies
# --only-dev avoids building the python packages; --inexact preserves builds installed by make dev-py
uv sync --all-packages --only-dev --inexact
.PHONY: install-js
install-js: ## Install JS package dependencies
cd crates/monty-js && npm install
.PHONY: install
install: .cargo install-py install-js ## Install the package, dependencies, and prek for local development
cargo check --workspace
uvx prek install --install-hooks
.PHONY: dev-py
dev-py: install-py ## Install python packages for development
uv run maturin develop --uv -m crates/monty-runtime/Cargo.toml
uv run maturin develop --uv -m crates/monty-python/Cargo.toml
.PHONY: dev-py-release
dev-py-release: install-py ## Install python packages for development with a release build
uv run maturin develop --uv -m crates/monty-runtime/Cargo.toml --release
uv run maturin develop --uv -m crates/monty-python/Cargo.toml --release
.PHONY: build-js
build-js: install-js ## Build the JS package (napi debug build + TypeScript)
cd crates/monty-js && npm run build:debug
.PHONY: lint-js
lint-js: install-js ## Lint JS code with oxlint
cd crates/monty-js && npm run lint
.PHONY: test-js
test-js: build-js ## Test the JS package (builds the monty binary the workers run)
cargo build -p monty-runtime
cd crates/monty-js && MONTY_BIN="$${CARGO_TARGET_DIR:-../../target}/debug/monty$(EXE_EXT)" npm test
.PHONY: build-wasm
build-wasm: install-js ## Build the lean wasm worker module (requires the wasm32-wasip1 target)
cd crates/monty-js && npm run build:wasm && npm run build:ts
.PHONY: test-wasm
test-wasm: install-js ## Test the wasm worker module from node, with no browser
cd crates/monty-js && npm run build:wasm && npm run build:ts && npm run test:wasm
.PHONY: test-browser
test-browser: install-js ## Browser (Vitest) test of the wasm path in a real headless browser
cd crates/monty-js && npm run build:wasm && npm run build:ts && npx playwright install chromium && npm run test:browser
.PHONY: dev-py-pgo
dev-py-pgo: install-py ## Install the python package for development with profile-guided optimization
$(eval PROFDATA := $(shell mktemp -d))
# the profiling run below spawns `monty` workers; build the runtime outside
# the instrumented build so only the client extension is profiled
uv run maturin develop --uv -m crates/monty-runtime/Cargo.toml --release
RUSTFLAGS='-Cprofile-generate=$(PROFDATA)' uv run maturin develop --uv -m crates/monty-python/Cargo.toml --release
uv run --package pydantic-monty-client --only-dev pytest crates/monty-python/tests -k "not test_parallel_exec"
$(eval LLVM_PROFDATA := $(shell rustup run stable bash -c 'echo $$RUSTUP_HOME/toolchains/$$RUSTUP_TOOLCHAIN/lib/rustlib/$$(rustc -Vv | grep host | cut -d " " -f 2)/bin/llvm-profdata'))
$(LLVM_PROFDATA) merge -o $(PROFDATA)/merged.profdata $(PROFDATA)
RUSTFLAGS='-Cprofile-use=$(PROFDATA)/merged.profdata' $(uv-run-no-sync) maturin develop --uv -m crates/monty-python/Cargo.toml --release
@rm -rf $(PROFDATA)
.PHONY: format-rs
format-rs: ## Format Rust code with fmt
@cargo +nightly fmt --version
cargo +nightly fmt --all
.PHONY: format-py
format-py: ## Format Python code - WARNING be careful about this command as it may modify code and break tests silently!
uv run ruff format
uv run ruff check --fix --fix-only
.PHONY: format-js
format-js: install-js ## Format JS code with prettier
cd crates/monty-js && npm run format
.PHONY: format
format: format-rs format-py format-js ## Format Rust code, this does not format Python code as we have to be careful with that
.PHONY: lint-rs
lint-rs: ## Lint Rust code with clippy and import checks
@cargo clippy --version
cargo clippy --workspace --tests -p monty-bench --benches -- -D warnings
cargo clippy --workspace --tests --all-features -- -D warnings
./scripts/check_imports.py
.PHONY: clippy-fix
clippy-fix: ## Fix Rust code with clippy
cargo clippy --workspace --tests -p monty-bench --benches --all-features --fix --allow-dirty
.PHONY: generate-proto
generate-proto: ## Regenerate monty-proto's checked-in code from the .proto schema
cargo run -p monty-proto --features generate --bin generate-proto
cargo +nightly fmt -p monty-proto
.PHONY: check-proto
check-proto: generate-proto ## Verify monty-proto's checked-in code matches the .proto schema
git diff --exit-code crates/monty-proto/src/generated crates/monty-proto/tests/oracle
.PHONY: lint-py
lint-py: dev-py ## Lint Python code with ruff
uv run ruff format --check
uv run ruff check
uv run basedpyright
# mypy-stubtest requires a build of the python package, hence dev-py
uv run -m mypy.stubtest pydantic_monty._monty --ignore-disjoint-bases
.PHONY: lint
lint: lint-rs lint-py ## Lint the code with ruff and clippy
.PHONY: test-no-features
test-no-features: ## Run rust tests without any features enabled
cargo test -p monty -p monty-fs
cargo run -p monty-datatest
.PHONY: test-memory-model-checks
test-memory-model-checks: ## Run rust tests with memory-model-checks enabled - THIS IS EXTREMELY SLOW, SHOULD MOSTLY BE RUN IN CI OR IF ABSOLUTELY NECESSARY
cargo test -p monty --features "memory-model-checks test-hooks"
cargo run -p monty-datatest --features memory-model-checks
.PHONY: test-ref-count-return
test-ref-count-return: ## Run rust tests with ref-count-return enabled
cargo test -p monty --features ref-count-return
cargo run -p monty-datatest --features ref-count-return
.PHONY: test-cases
test-cases: ## Run tests cases only
cargo run -p monty-datatest
.PHONY: miri
miri: ## Run library inline tests under miri (particularly relevant for heap.rs)
cargo +nightly miri test -p monty --lib
.PHONY: miri-test-cases
miri-test-cases: ## Run library inline tests under miri (particularly relevant for heap.rs)
MIRIFLAGS=-Zmiri-disable-isolation cargo +nightly miri run -p monty-datatest -- run_test_cases_monty
.PHONY: test-type-checking
test-type-checking: ## Run rust tests on monty-type-checking
cargo test -p monty-type-checking -p monty-typeshed
.PHONY: test-subprocess
test-subprocess: ## Run subprocess protocol, child-mode, and worker-pool tests
cargo build -p monty-runtime
cargo test -p monty-proto -p monty-runtime -p monty-pool
.PHONY: pytest
pytest: ## Run Python tests with pytest
uv run --package pydantic-monty-client --only-dev pytest crates/monty-python/tests
.PHONY: test-py
test-py: dev-py pytest ## Build the python package (debug profile) and run tests
.PHONY: test-docs
test-docs: dev-py ## Test docs examples only
uv run --package pydantic-monty-client --only-dev pytest crates/monty-python/tests/test_readme_examples.py
cargo test --doc -p monty
.PHONY: test
test: test-memory-model-checks test-ref-count-return test-no-features test-type-checking test-subprocess test-py miri ## Run rust tests
.PHONY: testcov
testcov: ## Run Rust tests with coverage, print table, and generate HTML report
@cargo llvm-cov --version > /dev/null 2>&1 || echo 'Please run: `cargo install cargo-llvm-cov`'
cargo llvm-cov clean --workspace
echo "coverage for `make test-no-features`"
cargo llvm-cov --no-report -p monty
cargo llvm-cov run --no-report -p monty-datatest
echo "coverage for `make test-memory-model-checks`"
cargo llvm-cov --no-report -p monty --features memory-model-checks
cargo llvm-cov run --no-report -p monty-datatest --features memory-model-checks
echo "coverage for `make test-ref-count-return`"
cargo llvm-cov --no-report -p monty --features ref-count-return
cargo llvm-cov run --no-report -p monty-datatest --features ref-count-return
echo "coverage for `make test-type-checking`"
cargo llvm-cov --no-report -p monty-type-checking -p monty-typeshed
echo "Generating reports:"
cargo llvm-cov report --ignore-filename-regex '(tests/|test_cases/|/tests\.rs$$)'
cargo llvm-cov report --html --ignore-filename-regex '(tests/|test_cases/|/tests\.rs$$)'
@echo ""
@echo "HTML report: $${CARGO_TARGET_DIR:-target}/llvm-cov/html/index.html"
.PHONY: complete-tests
complete-tests: ## Fill in incomplete test expectations using CPython
uv run scripts/complete_tests.py
.PHONY: update-typeshed
update-typeshed: ## Update vendored typeshed from upstream
uv run crates/monty-typeshed/update.py
uv run ruff format
uv run ruff check --fix --fix-only --silent
.PHONY: check-typeshed
check-typeshed: ## Check vendored typeshed stubs are in sync with upstream
uv run crates/monty-typeshed/check.py
.PHONY: bench
bench: ## Run benchmarks
cargo bench -p monty-bench --bench main
.PHONY: bench-pool
bench-pool: ## Run subprocess pool benchmarks (spawn, checkout, wire round-trips)
cargo build -p monty-runtime --release
MONTY_TEST_BIN=$(CURDIR)/target/release/monty cargo bench -p monty-bench --bench pool
.PHONY: bench-decode
bench-decode: ## Run child-frame protobuf decode benchmarks
cargo bench -p monty-bench --bench decode
.PHONY: dev-bench
dev-bench: ## Run benchmarks to test with dev profile
cargo bench --profile dev -p monty-bench --bench main -- --test
.PHONY: profile
profile: ## Profile the code with pprof and generate flamegraphs
cargo bench -p monty-bench --bench main --profile profiling -- --profile-time=10
uv run scripts/flamegraph_to_text.py
.PHONY: type-sizes
type-sizes: ## Write type sizes for the crate to ./type-sizes.txt (requires nightly and top-type-sizes)
RUSTFLAGS="-Zprint-type-sizes" cargo +nightly build -j1 2>&1 | top-type-sizes -f '^monty.*' > type-sizes.txt
@echo "Type sizes written to ./type-sizes.txt"
.PHONY: fuzz-string_input_panic
fuzz-string_input_panic: ## Run the `string_input_panic` fuzz target
cargo +nightly fuzz run --fuzz-dir crates/fuzz string_input_panic
.PHONY: fuzz-tokens_input_panic
fuzz-tokens_input_panic: ## Run the `tokens_input_panic` fuzz target (structured token input)
cargo +nightly fuzz run --fuzz-dir crates/fuzz tokens_input_panic
.PHONY: main
main: lint test-memory-model-checks test-subprocess test-py ## run linting and the most important tests
# (must stay last!)
.PHONY: help
help: ## Show this help (usage: make help)
@echo "Usage: make [recipe]"
@echo "Recipes:"
@awk '/^[a-zA-Z0-9_-]+:.*?##/ { \
helpMessage = match($$0, /## (.*)/); \
if (helpMessage) { \
recipe = $$1; \
sub(/:/, "", recipe); \
printf " \033[36mmake %-20s\033[0m %s\n", recipe, substr($$0, RSTART + 3, RLENGTH); \
} \
}' $(MAKEFILE_LIST)