forked from habedi/graphina
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
277 lines (236 loc) · 9.63 KB
/
Makefile
File metadata and controls
277 lines (236 loc) · 9.63 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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# Variables
REPO := github.com/habedi/graphina
BINARY_NAME := $(or $(PROJ_BINARY), $(notdir $(REPO)))
BINARY := target/release/$(BINARY_NAME)
PATH := /snap/bin:$(PATH)
DEBUG_GRAPHINA := 1
RUST_LOG := info
RUST_BACKTRACE := full
WHEEL_DIR := dist
PYGRAPHINA_DIR := pygraphina
PY_DEP_MNGR := uv # Use `uv sync --all-extras` to make the environment
TEST_DATA_DIR := tests/testdata
SHELL := /bin/bash
MSRV := 1.86
# Pinned versions for Rust development tools
TARPAULIN_VERSION=0.32.8
NEXTEST_VERSION=0.9.101
AUDIT_VERSION=0.21.2
CAREFUL_VERSION=0.4.8
# Find the latest built Python wheel file
WHEEL_FILE := $(shell ls $(PYGRAPHINA_DIR)/$(WHEEL_DIR)/pygraphina-*.whl 2>/dev/null | head -n 1)
# Default target
.DEFAULT_GOAL := help
.PHONY: help
help: ## Show the help message for each target
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' Makefile | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
########################################################################################
## Rust targets
########################################################################################
.PHONY: format
format: ## Format Rust files
@echo "Formatting Rust files..."
@cargo fmt
.PHONY: test
test: format doctest ## Run the tests
@echo "Running tests..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) RUST_LOG=debug RUST_BACKTRACE=$(RUST_BACKTRACE) cargo test --features all --all-targets \
--workspace -- --nocapture
.PHONY: doctest
doctest: ## Run documentation tests (Rust code examples in doc comments)
@echo "Running documentation tests..."
@cargo test --doc --features all
.PHONY: coverage
coverage: format doctest ## Generate test coverage report
@echo "Generating test coverage report..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) cargo tarpaulin --features all --out Xml --out Html
.PHONY: build
build: format ## Build the binary for the current platform
@echo "Building the project..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) cargo build --release
.PHONY: run
run: build ## Build and run the binary
@echo "Running binary: $(BINARY)"
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) ./$(BINARY)
.PHONY: clean
clean: ## Remove generated and temporary files
@echo "Cleaning up..."
@cargo clean
@rm -rf $(WHEEL_DIR) dist/ $(PYGRAPHINA_DIR)/$(WHEEL_DIR)
@rm -f $(PYGRAPHINA_DIR)/*.so
.PHONY: install-snap
install-snap: ## Install dependencies using Snapcraft
@echo "Installing snap dependencies..."
@sudo apt-get update && sudo apt-get install -y snapd
@sudo snap refresh
@sudo snap install rustup --classic
.PHONY: install-deps
install-deps: install-snap ## Install development dependencies
@echo "Installing development dependencies..."
@rustup component add rustfmt clippy
# Install each tool with a specific, pinned version
@cargo install --locked cargo-tarpaulin --version ${TARPAULIN_VERSION}
@cargo install --locked cargo-nextest --version ${NEXTEST_VERSION}
@cargo install --locked cargo-audit --version ${AUDIT_VERSION}
@cargo install --locked cargo-careful --version ${CAREFUL_VERSION}
@sudo apt-get install python3-pip libfontconfig1-dev
@pip install $(PY_DEP_MNGR)
.PHONY: lint
lint: format ## Run linters on Rust files
@echo "Linting Rust files..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) cargo clippy -- -D warnings -D clippy::unwrap_used -D clippy::expect_used
.PHONY: publish
publish: ## Publish the package to crates.io (requires CARGO_REGISTRY_TOKEN to be set)
@echo "Publishing package to Cargo registry..."
@cargo publish --token $(CARGO_REGISTRY_TOKEN)
.PHONY: bench
bench: ## Run benchmarks
@echo "Running benchmarks..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) cargo bench --features all
.PHONY: audit
audit: ## Run security audit on Rust dependencies
@echo "Running security audit..."
@cargo audit
.PHONY: check-module-deps
check-module-deps: ## Check that top-level modules only depend on core (not on each other)
@echo "Checking module dependencies..."
@ERROR=0; \
TOP_MODULES="approximation centrality community links metrics mst parallel subgraphs traversal visualization"; \
for module in $$TOP_MODULES; do \
if [ -d "src/$$module" ]; then \
for other_module in $$TOP_MODULES; do \
if [ "$$module" != "$$other_module" ]; then \
VIOLATIONS=$$(grep -r "use crate::$$other_module" src/$$module/ 2>/dev/null || true); \
if [ -n "$$VIOLATIONS" ]; then \
echo "ERROR: Module '$$module' has forbidden dependency on '$$other_module':"; \
echo "$$VIOLATIONS" | sed 's/^/ /'; \
ERROR=1; \
fi; \
fi; \
done; \
fi; \
done; \
if [ $$ERROR -eq 0 ]; then \
echo "All module dependencies are valid - only 'core' is used"; \
else \
echo "Module dependency violations found!"; \
echo ""; \
echo "Rule: Top-level modules can only depend on 'core', not on each other."; \
echo "Top-level modules: $$TOP_MODULES"; \
exit 1; \
fi
.PHONY: careful
careful: ## Run security checks on Rust code
@echo "Running security checks..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) RUST_BACKTRACE=$(RUST_BACKTRACE) cargo careful run
.PHONY: docs
docs: format ## Generate the documentation
@echo "Generating documentation..."
@cargo doc --no-deps --document-private-items
.PHONY: fix-lint
fix-lint: ## Fix the linter warnings
@echo "Fixing linter warnings..."
@cargo clippy --fix --allow-dirty --all-targets --workspace --all-features -- -D warnings -D clippy::unwrap_used -D clippy::expect_used
.PHONY: nextest
nextest: ## Run tests using nextest
@echo "Running tests using nextest..."
@DEBUG_GRAPHINA=$(DEBUG_GRAPHINA) RUST_BACKTRACE=$(RUST_BACKTRACE) cargo nextest run --features all
.PHONY: testdata
testdata: ## Download the datasets used in tests
@echo "Downloading test data..."
@$(SHELL) $(TEST_DATA_DIR)/download_datasets.sh $(TEST_DATA_DIR)
.PHONY: install-msrv
install-msrv: ## Install the minimum supported Rust version (MSRV) for development
@echo "Installing the minimum supported Rust version..."
@rustup toolchain install $(MSRV)
@rustup default $(MSRV)
.PHONY: run-examples
run-examples: ## Run all the scripts in the examples directory one by one
@echo "Running all example scripts..."
@for example in examples/*.rs; do \
example_name=$$(basename $$example .rs); \
echo "Running example: $$example_name"; \
cargo run --features all --example $$example_name; \
done
########################################################################################
## Python targets
########################################################################################
.PHONY: develop-py
develop-py: ## Build and install PyGraphina in the current Python environment
@echo "Building and installing PyGraphina..."
# Note: Maturin does not work when CONDA_PREFIX and VIRTUAL_ENV are both set
@(cd $(PYGRAPHINA_DIR) && unset CONDA_PREFIX && maturin develop)
.PHONY: wheel
wheel: ## Build the wheel file for PyGraphina
@echo "Building the PyGraphina wheel..."
@(cd $(PYGRAPHINA_DIR) && maturin build --release --out $(WHEEL_DIR) --auditwheel check)
.PHONY: wheel-manylinux
wheel-manylinux: ## Build the manylinux wheel file for PyGraphina (using Zig)
@echo "Building the manylinux PyGraphina wheel..."
@(cd $(PYGRAPHINA_DIR) && maturin build --release --out $(WHEEL_DIR) --auditwheel check --zig)
.PHONY: test-py
test-py: develop-py ## Run Python tests
@echo "Running Python tests..."
@$(PY_DEP_MNGR) run pytest
.PHONY: docs-py
docs-py: develop-py ## Generate PyGraphina MkDocs documentation
@echo "Generating MkDocs documentation..."
@$(PY_DEP_MNGR) run mkdocs build --config-file pygraphina/mkdocs.yml
.PHONY: docs-serve-py
docs-serve-py: develop-py ## Serve PyGraphina MkDocs documentation locally
@echo "Serving MkDocs documentation locally..."
@$(PY_DEP_MNGR) run mkdocs serve --config-file pygraphina/mkdocs.yml
.PHONY: rundocs
rundocs: develop-py ## Test all code examples in PyGraphina documentation using rundoc
@echo "Testing documentation code examples..."
@failed=0; \
for f in $(PYGRAPHINA_DIR)/docs/examples/*.md; do \
echo "=== Testing $$(basename $$f) ==="; \
if echo | rundoc run "$$f" 2>&1 | grep -q "Failed"; then \
echo "FAILED: $$f"; \
failed=$$((failed + 1)); \
else \
echo "PASSED: $$f"; \
fi; \
done; \
if [ $$failed -gt 0 ]; then \
echo "$$failed file(s) had failures"; \
exit 1; \
else \
echo "All documentation examples passed!"; \
fi
.PHONY: docs-serve
docs-serve: ## Serve Graphina MkDocs locally
@echo "Serving Graphina MkDocs..."
@uv run mkdocs serve
.PHONY: docs-build
docs-build: ## Generate Graphina MkDocs documentation
@echo "Building Graphina MkDocs..."
@uv run mkdocs build
.PHONY: publish-py
publish-py: wheel-manylinux ## Publish the PyGraphina wheel to PyPI (requires PYPI_TOKEN to be set)
@echo "Publishing PyGraphina to PyPI..."
@if [ -z "$(WHEEL_FILE)" ]; then \
echo "Error: No wheel file found. Please run 'make wheel' first."; \
exit 1; \
fi
@echo "Found wheel file: $(WHEEL_FILE)"
@twine upload -u __token__ -p $(PYPI_TOKEN) $(WHEEL_FILE)
.PHONY: generate-ci
generate-ci: ## Generate CI configuration files (GitHub Actions workflow)
@echo "Generating CI configuration files..."
@(cd $(PYGRAPHINA_DIR) && maturin generate-ci --zig --pytest --platform all -o ../.github/workflows/ci.yml github)
########################################################################################
## Additional targets
########################################################################################
.PHONY: setup-hooks
setup-hooks: ## Install Git hooks (pre-commit and pre-push)
@echo "Installing Git hooks..."
@pre-commit install --hook-type pre-commit
@pre-commit install --hook-type pre-push
@pre-commit install-hooks
.PHONY: test-hooks
test-hooks: ## Test Git hooks on all files
@echo "Testing Git hooks..."
@pre-commit run --all-files