Skip to content

Commit d3eff07

Browse files
committed
Refine Makefile
1 parent 7f67ce8 commit d3eff07

File tree

1 file changed

+41
-29
lines changed

1 file changed

+41
-29
lines changed

Makefile

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,30 @@
44

55
.DEFAULT_GOAL := help
66

7+
# --------------------------------------------------------------------------
8+
# Python interpreter detection
9+
# --------------------------------------------------------------------------
10+
# VENV_BIN: path to local virtualenv bin directory
711
VENV_BIN := $(PWD)/venv/bin
8-
# Use dynamic (recursive) assignment so a newly created venv is picked up
9-
# Prefer explicit versions first (newest to oldest), then python3 on PATH
10-
PY_FIND := $(shell for v in 3.13 3.12 3.11 3.10; do command -v python$$v >/dev/null 2>&1 && { echo python$$v; exit 0; }; done; command -v python3 2>/dev/null || command -v python 2>/dev/null)
11-
PYTHON ?= $(if $(wildcard $(VENV_BIN)/python),$(VENV_BIN)/python,$(PY_FIND))
12-
PIP = $(PYTHON) -m pip
13-
PYTEST = $(PYTHON) -m pytest
14-
RUFF = $(PYTHON) -m ruff
15-
PRECOMMIT = $(PYTHON) -m pre_commit
12+
13+
# PY_BEST: scan for newest supported Python (used when creating new venvs)
14+
# Supports 3.9-3.13 to match CI matrix
15+
PY_BEST := $(shell for v in 3.13 3.12 3.11 3.10 3.9; do command -v python$$v >/dev/null 2>&1 && { echo python$$v; exit 0; }; done; command -v python3 2>/dev/null || command -v python 2>/dev/null)
16+
17+
# PY_PATH: active python3/python on PATH (respects CI setup-python and activated venvs)
18+
PY_PATH := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null)
19+
20+
# PYTHON: interpreter used for all commands
21+
# 1. Use local venv if present
22+
# 2. Otherwise use active python on PATH (important for CI)
23+
# 3. Fall back to best available version
24+
PYTHON ?= $(if $(wildcard $(VENV_BIN)/python),$(VENV_BIN)/python,$(if $(PY_PATH),$(PY_PATH),$(PY_BEST)))
25+
26+
# Derived tool commands (always use -m to ensure correct environment)
27+
PIP := $(PYTHON) -m pip
28+
PYTEST := $(PYTHON) -m pytest
29+
RUFF := $(PYTHON) -m ruff
30+
PRECOMMIT := $(PYTHON) -m pre_commit
1631

1732
# Detect Apple Command Line Tools compilers (prefer system toolchain on macOS)
1833
APPLE_CLANG := $(shell xcrun --find clang 2>/dev/null)
@@ -35,8 +50,8 @@ help:
3550
@echo " make clean - Clean build artifacts"
3651
@echo " make hooks - Run pre-commit on all files"
3752
@echo " make info - Show tool versions"
38-
@echo " make check-python - Check if venv Python matches system Python"
39-
@echo " make rebuild - Clean and rebuild with system Python (respects CMAKE_ARGS)"
53+
@echo " make check-python - Check if venv Python matches best available"
54+
@echo " make rebuild - Clean and rebuild (respects CMAKE_ARGS)"
4055

4156
# Allow callers to pass CMAKE_ARGS and MACOSX_DEPLOYMENT_TARGET consistently
4257
ENV_MACOS := $(if $(MACOSX_DEPLOYMENT_TARGET),MACOSX_DEPLOYMENT_TARGET=$(MACOSX_DEPLOYMENT_TARGET),MACOSX_DEPLOYMENT_TARGET=$(DEFAULT_MACOSX))
@@ -48,12 +63,12 @@ DEV_ENV := $(ENV_MACOS) $(ENV_CC) $(ENV_CXX) $(ENV_CMAKE)
4863
dev:
4964
@echo "🚀 Setting up development environment..."
5065
@if [ ! -x "$(VENV_BIN)/python" ]; then \
51-
if [ -z "$(PY_FIND)" ]; then \
66+
if [ -z "$(PY_BEST)" ]; then \
5267
echo "❌ Error: No Python interpreter found (python3 or python)"; \
5368
exit 1; \
5469
fi; \
55-
echo "🐍 Creating virtual environment with $(PY_FIND) ..."; \
56-
$(PY_FIND) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }; \
70+
echo "🐍 Creating virtual environment with $(PY_BEST) ..."; \
71+
$(PY_BEST) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }; \
5772
if [ ! -x "$(VENV_BIN)/python" ]; then \
5873
echo "❌ Error: venv creation failed - $(VENV_BIN)/python not found"; \
5974
exit 1; \
@@ -69,11 +84,11 @@ dev:
6984

7085
venv:
7186
@echo "🐍 Creating virtual environment in ./venv ..."
72-
@if [ -z "$(PY_FIND)" ]; then \
87+
@if [ -z "$(PY_BEST)" ]; then \
7388
echo "❌ Error: No Python interpreter found (python3 or python)"; \
7489
exit 1; \
7590
fi
76-
@$(PY_FIND) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }
91+
@$(PY_BEST) -m venv venv || { echo "❌ Failed to create venv"; exit 1; }
7792
@if [ ! -x "$(VENV_BIN)/python" ]; then \
7893
echo "❌ Error: venv creation failed - $(VENV_BIN)/python not found"; \
7994
exit 1; \
@@ -88,7 +103,6 @@ install:
88103
@echo "📦 Installing package (editable)"
89104
@$(DEV_ENV) $(PIP) install -e .
90105

91-
92106
check:
93107
@PYTHON=$(PYTHON) bash dev/run-checks.sh
94108
@$(MAKE) lint
@@ -134,7 +148,7 @@ clean:
134148

135149
info:
136150
@echo "Python (active): $$($(PYTHON) --version)"
137-
@echo "Python (system): $$($(PY_FIND) --version 2>/dev/null || echo 'missing')"
151+
@echo "Python (best): $$($(PY_BEST) --version 2>/dev/null || echo 'missing')"
138152
@$(MAKE) check-python
139153
@echo "Ruff: $$($(RUFF) --version 2>/dev/null || echo 'missing')"
140154
@echo "Pyright: $$($(PYTHON) -m pyright --version 2>/dev/null | head -1 || echo 'missing')"
@@ -145,10 +159,10 @@ info:
145159
check-python:
146160
@if [ -x "$(VENV_BIN)/python" ]; then \
147161
VENV_VER=$$($(VENV_BIN)/python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \
148-
SYS_VER=$$($(PY_FIND) -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \
149-
if [ -n "$$VENV_VER" ] && [ -n "$$SYS_VER" ] && [ "$$VENV_VER" != "$$SYS_VER" ]; then \
150-
echo "⚠️ WARNING: venv Python ($$VENV_VER) != system Python ($$SYS_VER)"; \
151-
echo " Run 'make clean-venv && make dev' to recreate venv with system Python"; \
162+
BEST_VER=$$($(PY_BEST) -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "unknown"); \
163+
if [ -n "$$VENV_VER" ] && [ -n "$$BEST_VER" ] && [ "$$VENV_VER" != "$$BEST_VER" ]; then \
164+
echo "⚠️ WARNING: venv Python ($$VENV_VER) != best available Python ($$BEST_VER)"; \
165+
echo " Run 'make clean-venv && make dev' to recreate venv if desired"; \
152166
fi; \
153167
fi
154168

@@ -163,7 +177,6 @@ cpp-test:
163177
if command -v ninja >/dev/null 2>&1; then GEN_ARGS="-G Ninja"; fi; \
164178
cmake -S . -B "$$BUILD_DIR" -DNETGRAPH_CORE_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release $$GEN_ARGS; \
165179
cmake --build "$$BUILD_DIR" --config Release -j; \
166-
# Determine parallelism
167180
if command -v sysctl >/dev/null 2>&1; then \
168181
NPROC=$$(sysctl -n hw.ncpu 2>/dev/null || echo 2); \
169182
elif command -v nproc >/dev/null 2>&1; then \
@@ -175,7 +188,7 @@ cpp-test:
175188

176189
cov:
177190
@echo "📦 Reinstalling with C++ coverage instrumentation..."
178-
@$(PIP) install -U scikit-build-core "pybind11>=3"
191+
@$(PIP) install -U scikit-build-core "pybind11>=2.11"
179192
@PIP_NO_BUILD_ISOLATION=1 CMAKE_ARGS="-DNETGRAPH_CORE_COVERAGE=ON" $(PIP) install -e .'[dev]'
180193
@echo "🧪 Running Python tests with coverage..."
181194
@mkdir -p build/coverage
@@ -187,7 +200,7 @@ cov:
187200
if command -v ninja >/dev/null 2>&1; then GEN_ARGS="-G Ninja"; fi; \
188201
cmake -S . -B "$$BUILD_DIR" -DNETGRAPH_CORE_BUILD_TESTS=ON -DNETGRAPH_CORE_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug $$GEN_ARGS; \
189202
cmake --build "$$BUILD_DIR" --config Debug -j; \
190-
ctest --test-dir "$$BUILD_DIR" --output-on-failure || true
203+
ctest --test-dir "$$BUILD_DIR" --output-on-failure || echo "⚠️ Some C++ tests failed (continuing for coverage)"
191204
@echo "📈 Generating C++ coverage XML (gcovr)..."
192205
@$(PYTHON) -m gcovr --root . \
193206
--object-directory build \
@@ -201,7 +214,6 @@ cov:
201214
@echo ""
202215
@echo "✅ Coverage ready in build/coverage/: coverage-python.xml, coverage-cpp.xml, coverage-combined.html"
203216

204-
.PHONY: sanitize-test
205217
sanitize-test:
206218
@echo "🧪 Building and running C++ tests with sanitizers..."
207219
@BUILD_DIR="build/cpp-sanitize"; \
@@ -210,10 +222,10 @@ sanitize-test:
210222
if command -v ninja >/dev/null 2>&1; then GEN_ARGS="-G Ninja"; fi; \
211223
cmake -S . -B "$$BUILD_DIR" -DNETGRAPH_CORE_BUILD_TESTS=ON -DNETGRAPH_CORE_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug $$GEN_ARGS; \
212224
cmake --build "$$BUILD_DIR" --config Debug -j; \
213-
ASAN_OPTIONS=detect_leaks=1 ctest --test-dir "$$BUILD_DIR" --output-on-failure || true
225+
ASAN_OPTIONS=detect_leaks=1 ctest --test-dir "$$BUILD_DIR" --output-on-failure || echo "⚠️ Some sanitizer tests failed"
214226

215227
# Clean + reinstall in dev mode (respects CMAKE_ARGS and MACOSX_DEPLOYMENT_TARGET)
216-
# Always uses system Python to avoid venv version mismatches
228+
# Uses active PYTHON (venv or PATH) to avoid environment mismatches
217229
rebuild: clean
218-
@echo "🔨 Rebuilding with system Python: $(PY_FIND)"
219-
@$(DEV_ENV) $(PY_FIND) -m pip install -e .'[dev]'
230+
@echo "🔨 Rebuilding with: $(PYTHON)"
231+
@$(DEV_ENV) $(PIP) install -e .'[dev]'

0 commit comments

Comments
 (0)