-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
198 lines (154 loc) · 7.51 KB
/
Makefile
File metadata and controls
198 lines (154 loc) · 7.51 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
# WASP2 Makefile
# Common development targets for building, testing, and benchmarking
.PHONY: all build install test test-quick test-sanity lint format clean help
.PHONY: download-sanity-data sanity-data-local rust-build rust-test
.PHONY: test-mapping-parity
# Configuration
PYTHON ?= python
MATURIN ?= maturin
PYTEST ?= pytest
RUFF ?= ruff
CARGO ?= cargo
# Project paths
RUST_DIR := rust
SRC_DIR := src
TESTS_DIR := tests
SANITY_DATA_DIR := tests/sanity/data
# Sanity test data configuration
SANITY_VERSION := v1
SANITY_TARBALL := wasp2-sanity-chr21-$(SANITY_VERSION).tar.xz
SANITY_RELEASE_URL := https://github.com/mcvickerlab/WASP2/releases/download/v1.3.0/$(SANITY_TARBALL)
# Local sanity data path (for development). Override by exporting
# WASP2_SANITY_DATA_DIR or passing LOCAL_SANITY_DATA=... to make.
LOCAL_SANITY_DATA ?= $(or $(WASP2_SANITY_DATA_DIR),$(CURDIR)/benchmarking/sanity_test)
# =============================================================================
# Main targets
# =============================================================================
all: build ## Build the project (default)
build: rust-build install ## Build Rust extension and install package
install: ## Install package in development mode
$(PYTHON) -m pip install -e ".[dev]" --no-build-isolation -q
# =============================================================================
# Rust build targets
# =============================================================================
rust-build: ## Build Rust extension with maturin
$(MATURIN) build --release -m $(RUST_DIR)/Cargo.toml
$(PYTHON) -m pip install $(RUST_DIR)/target/wheels/*.whl --force-reinstall -q
rust-dev: ## Build Rust extension in debug mode (faster compile)
$(MATURIN) develop -m $(RUST_DIR)/Cargo.toml
rust-test: ## Run Rust unit tests
cd $(RUST_DIR) && PYO3_PYTHON=$$($(PYTHON) -c "import sys; print(sys.executable)") $(CARGO) test
rust-bench: ## Run Rust benchmarks
cd $(RUST_DIR) && $(CARGO) bench
# =============================================================================
# Testing targets
# =============================================================================
test: ## Run all tests (excluding benchmarks)
$(PYTEST) $(TESTS_DIR) -v --tb=short \
--ignore=$(TESTS_DIR)/benchmarks \
-m "not benchmark"
test-quick: ## Run quick validation tests only
$(PYTEST) $(TESTS_DIR)/test_validation_quick.py -v --tb=short
test-rust: ## Run Rust-specific tests
$(PYTEST) $(TESTS_DIR) -v --tb=short -m "rust"
test-mapping-parity: ## Run mapping parity tests against legacy and unified paths
$(PYTEST) $(TESTS_DIR)/regression/test_mapping_stage_parity.py -v --tb=short
test-integration: ## Run integration tests
$(PYTEST) $(TESTS_DIR) -v --tb=short -m "integration"
test-sanity: ## Run sanity tests with real chr21 data
$(PYTEST) $(TESTS_DIR)/sanity -v --tb=short -x
test-all: ## Run all tests including sanity and slow tests
$(PYTEST) $(TESTS_DIR) -v --tb=short \
--ignore=$(TESTS_DIR)/benchmarks
# =============================================================================
# Sanity data management
# =============================================================================
download-sanity-data: ## Download sanity test data from GitHub release
@echo "Downloading sanity data from $(SANITY_RELEASE_URL)..."
@mkdir -p $(SANITY_DATA_DIR)
@if command -v wget > /dev/null; then \
wget -q -O $(SANITY_DATA_DIR)/$(SANITY_TARBALL) $(SANITY_RELEASE_URL); \
else \
curl -sL -o $(SANITY_DATA_DIR)/$(SANITY_TARBALL) $(SANITY_RELEASE_URL); \
fi
@echo "Extracting..."
@cd $(SANITY_DATA_DIR) && tar -xJf $(SANITY_TARBALL) --strip-components=1
@rm -f $(SANITY_DATA_DIR)/$(SANITY_TARBALL)
@echo "Sanity data ready in $(SANITY_DATA_DIR)/"
sanity-data-local: ## Link sanity data from local HPC path (development)
@if [ -d "$(LOCAL_SANITY_DATA)" ]; then \
mkdir -p $(SANITY_DATA_DIR); \
ln -sf $(LOCAL_SANITY_DATA)/chr21.bam $(SANITY_DATA_DIR)/chr21.bam; \
ln -sf $(LOCAL_SANITY_DATA)/chr21.bam.bai $(SANITY_DATA_DIR)/chr21.bam.bai; \
ln -sf $(LOCAL_SANITY_DATA)/chr21.vcf.gz $(SANITY_DATA_DIR)/chr21.vcf.gz; \
ln -sf $(LOCAL_SANITY_DATA)/chr21.vcf.gz.tbi $(SANITY_DATA_DIR)/chr21.vcf.gz.tbi; \
ln -sf $(LOCAL_SANITY_DATA)/expected_counts.tsv $(SANITY_DATA_DIR)/expected_counts.tsv; \
ln -sf $(LOCAL_SANITY_DATA)/expected_r1.fq.gz $(SANITY_DATA_DIR)/expected_r1.fq.gz; \
ln -sf $(LOCAL_SANITY_DATA)/expected_r2.fq.gz $(SANITY_DATA_DIR)/expected_r2.fq.gz; \
ln -sf $(LOCAL_SANITY_DATA)/expected_analysis.tsv $(SANITY_DATA_DIR)/expected_analysis.tsv; \
echo "Linked sanity data from $(LOCAL_SANITY_DATA)"; \
else \
echo "Local sanity data not found at $(LOCAL_SANITY_DATA)"; \
echo "Run 'make download-sanity-data' to download from GitHub"; \
exit 1; \
fi
clean-sanity-data: ## Remove downloaded sanity test data
rm -rf $(SANITY_DATA_DIR)
# =============================================================================
# Benchmarking targets
# =============================================================================
benchmark: ## Run all benchmarks
$(PYTHON) $(TESTS_DIR)/benchmarks/run_benchmarks.py
benchmark-quick: ## Run quick benchmark subset
$(PYTHON) $(TESTS_DIR)/benchmarks/run_benchmarks.py --quick
benchmark-figures: ## Regenerate benchmark figures
$(PYTHON) $(TESTS_DIR)/benchmarks/run_benchmarks.py --figures-only
benchmark-list: ## List available benchmark groups
$(PYTHON) $(TESTS_DIR)/benchmarks/run_benchmarks.py --list-groups
# =============================================================================
# Code quality targets
# =============================================================================
lint: ## Run all linters
$(RUFF) check $(SRC_DIR) $(TESTS_DIR)
cd $(RUST_DIR) && $(CARGO) clippy -- -D warnings
format: ## Format code
$(RUFF) format $(SRC_DIR) $(TESTS_DIR)
cd $(RUST_DIR) && $(CARGO) fmt
format-check: ## Check code formatting without changes
$(RUFF) format --check $(SRC_DIR) $(TESTS_DIR)
cd $(RUST_DIR) && $(CARGO) fmt --check
typecheck: ## Run type checking
mypy $(SRC_DIR) --ignore-missing-imports
security: ## Run security checks
bandit -c pyproject.toml -r $(SRC_DIR)
cd $(RUST_DIR) && cargo audit
# =============================================================================
# CLI verification
# =============================================================================
verify-cli: ## Verify CLI tools are working
wasp2-count --help > /dev/null && echo "wasp2-count: OK"
wasp2-map --help > /dev/null && echo "wasp2-map: OK"
wasp2-analyze --help > /dev/null && echo "wasp2-analyze: OK"
$(PYTHON) -c "import wasp2_rust; print('wasp2_rust: OK')"
# =============================================================================
# Cleanup targets
# =============================================================================
clean: ## Clean build artifacts
rm -rf build/ dist/ *.egg-info
rm -rf $(RUST_DIR)/target/wheels
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find . -type f -name "*.pyc" -delete
clean-all: clean clean-sanity-data ## Clean everything including sanity data
rm -rf $(RUST_DIR)/target
rm -rf .pytest_cache .mypy_cache .ruff_cache
# =============================================================================
# Help
# =============================================================================
help: ## Show this help message
@echo "WASP2 Development Makefile"
@echo ""
@echo "Usage: make [target]"
@echo ""
@echo "Targets:"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'