Files
pyhdwallet/Makefile

448 lines
15 KiB
Makefile
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Makefile for hdwalletpy workflow
# - Build reusable Docker image (Python 3.12)
# - Vendor multi-platform wheels for offline air-gapped use
# - Compile wheels in container (wheelhouse)
# - Create host venv and install from wheelhouse or vendor/
# - Optionally run inside a warm container
# ---------- Platform Detection ----------
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_S),Darwin)
PLATFORM := macos
ifeq ($(UNAME_M),arm64)
ARCH := arm64
else
$(error Unsupported macOS architecture: $(UNAME_M))
endif
else ifeq ($(UNAME_S),Linux)
PLATFORM := linux
ARCH := x86_64
else
$(error Unsupported OS: $(UNAME_S))
endif
VENDOR_DIR := vendor/$(PLATFORM)-$(ARCH)
# Vendor directories for air-gapped deployment
VENDOR_MACOS := vendor/macos-arm64
VENDOR_LINUX_X86 := vendor/linux-x86_64
VENDOR_LINUX_ARM := vendor/linux-aarch64
# ---------- Config ----------
IMAGE := hdwallet-build:3.12
CONTAINER := hdwallet-dev
WORKDIR := /app
VENV_HOST := .venv
VENV_CONTAINER := /opt/venv
WHEELHOUSE := wheelhouse
# Vendor directories for air-gapped deployment
VENDOR_MACOS := vendor/macos-arm64
VENDOR_LINUX := vendor/linux-x86_64
# ---------- Help ----------
.PHONY: help
help:
@echo "pyhdwallet build system (macOS + Linux compatible)"
@echo ""
help:
@echo "📦 Vendoring (for offline/air-gapped use):"
@echo " make vendor-macos - Build macOS ARM64 wheels (runtime)"
@echo " make vendor-macos-dev - Build macOS ARM64 dev wheels (pytest)"
@echo " make vendor-linux - Build Linux x86_64 wheels (Docker)"
@echo " make vendor-linux-dev - Build Linux x86_64 dev wheels (Docker)"
@echo " make vendor-linux-arm - Build Linux ARM64/aarch64 wheels (Docker)"
@echo " make vendor-linux-arm-dev - Build Linux ARM64 dev wheels (Docker)"
@echo " make vendor-all - Build runtime wheels for ALL platforms"
@echo " make vendor-all-dev - Build dev wheels for ALL platforms"
@echo " make verify-vendor - Test offline installation from vendor/"
@echo ""
@echo "🔨 Binary Distribution:"
@echo " make binary - Build standalone binary for current platform"
@echo " make binary-linux - Build Linux binary via Docker (any OS)"
@echo " make binary-all - Build binaries for all platforms"
@echo ""
@echo "🚀 Release Management:"
@echo " make release - Build complete release (binaries + vendors + checksums)"
@echo " make release-binaries - Copy binaries to releases/vX.Y.Z/"
@echo " make release-checksums - Generate SHA256SUMS for binaries"
@echo " make release-test - Test release binaries"
@echo " make clean-release - Remove all release artifacts"
@echo ""
@echo "🛠️ Development workflow (works on macOS + Linux):"
@echo " make install - Create venv and install runtime dependencies"
@echo " make install-offline - Install runtime deps from vendor/ (offline)"
@echo " make install-dev-offline - Install runtime + dev deps from vendor/ (offline)"
@echo " make test - Run test suite"
@echo " make build-image - Build Docker image (Python 3.12)"
@echo " make wheels - Build wheels into ./$(WHEELHOUSE)"
@echo " make up - Start warm dev container"
@echo " make shell - Open shell in warm container"
@echo " make down - Stop and remove dev container"
@echo ""
@echo "🧹 Cleanup:"
@echo " make clean-vendor - Remove all vendor wheels"
@echo " make clean - Remove vendor/ + .venv + cache"
@echo " make clean-release - Remove releases/ only"
@echo ""
@echo " Platform Info:"
@echo " make info - Show platform detection info"
@echo ""
@echo "Platform notes:"
@echo " • vendor-macos requires native macOS (uses .venv312 with ARM64 Python)"
@echo " • vendor-linux works on any platform with Docker"
@echo " • vendor-linux-dev includes pytest for offline development"
@echo " • binary-linux works on any platform with Docker"
@echo " • All other targets work on macOS and Linux"
# ---------- Build reusable image ----------
.PHONY: build-image
build-image:
docker build -t $(IMAGE) .
# ---------- Vendoring for Air-Gapped Use ----------
.PHONY: vendor-macos
vendor-macos: requirements.txt
@echo "Building macOS ARM64 wheels (native)..."
@if [ ! -f ".venv312/bin/pip" ]; then \
echo "ERROR: .venv312 not found. Create it first:"; \
echo " python3.12 -m venv .venv312 && source .venv312/bin/activate"; \
exit 1; \
fi
mkdir -p $(VENDOR_MACOS)
.venv312/bin/pip download --dest $(VENDOR_MACOS) -r requirements.txt
cd $(VENDOR_MACOS) && shasum -a 256 *.whl > SHA256SUMS
@echo "✓ macOS ARM64 wheels: $(VENDOR_MACOS)/"
.PHONY: vendor-linux
vendor-linux: requirements.txt
@echo "Building Linux x86_64 wheels (Docker)..."
mkdir -p $(VENDOR_LINUX)
docker run --rm \
--platform linux/amd64 \
-v "$$PWD":$(WORKDIR) \
-w $(WORKDIR) \
python:3.12-slim \
bash -c " \
set -e && \
apt-get update -qq && apt-get install -y -qq gcc g++ make libffi-dev && \
pip install --upgrade pip && \
pip download --dest $(VENDOR_LINUX) -r requirements.txt && \
pip wheel --wheel-dir $(VENDOR_LINUX) --no-deps $(VENDOR_LINUX)/*.tar.gz 2>/dev/null || true && \
rm -f $(VENDOR_LINUX)/*.tar.gz && \
cd $(VENDOR_LINUX) && sha256sum *.whl > SHA256SUMS \
"
@echo "✓ Linux x86_64 wheels: $(VENDOR_LINUX)/"
# Add after vendor-linux target:
.PHONY: vendor-linux-arm
vendor-linux-arm: requirements.txt
@echo "Building Linux ARM64/aarch64 wheels (Docker)..."
mkdir -p $(VENDOR_LINUX_ARM)
docker run --rm \
--platform linux/arm64 \
-v "$$PWD":$(WORKDIR) \
-w $(WORKDIR) \
python:3.12-slim \
bash -c " \
set -e && \
apt-get update -qq && apt-get install -y -qq gcc g++ make libffi-dev && \
pip install --upgrade pip && \
pip download --dest $(VENDOR_LINUX_ARM) -r requirements.txt && \
pip wheel --wheel-dir $(VENDOR_LINUX_ARM) --no-deps $(VENDOR_LINUX_ARM)/*.tar.gz 2>/dev/null || true && \
rm -f $(VENDOR_LINUX_ARM)/*.tar.gz && \
cd $(VENDOR_LINUX_ARM) && sha256sum *.whl > SHA256SUMS \
"
@echo "✓ Linux ARM64 wheels: $(VENDOR_LINUX_ARM)/"
.PHONY: vendor-linux-arm-dev
vendor-linux-arm-dev: requirements-dev.txt
@echo "Building Linux ARM64 dev wheels (Docker)..."
mkdir -p $(VENDOR_LINUX_ARM)-dev
docker run --rm \
--platform linux/arm64 \
-v "$$PWD":$(WORKDIR) \
-w $(WORKDIR) \
python:3.12-slim \
bash -c " \
set -e && \
apt-get update -qq && apt-get install -y -qq gcc g++ make libffi-dev && \
pip install --upgrade pip && \
pip download --dest $(VENDOR_LINUX_ARM)-dev -r requirements-dev.txt && \
pip wheel --wheel-dir $(VENDOR_LINUX_ARM)-dev --no-deps $(VENDOR_LINUX_ARM)-dev/*.tar.gz 2>/dev/null || true && \
rm -f $(VENDOR_LINUX_ARM)-dev/*.tar.gz && \
cd $(VENDOR_LINUX_ARM)-dev && sha256sum *.whl > SHA256SUMS \
"
@echo "✓ Linux ARM64 dev wheels: $(VENDOR_LINUX_ARM)-dev/"
# Update vendor-all:
.PHONY: vendor-all
vendor-all: vendor-macos vendor-linux vendor-linux-arm
@echo ""
@echo "✓ All platforms vendored (runtime only):"
@echo " macOS ARM64: $(VENDOR_MACOS)/ ($$(ls $(VENDOR_MACOS)/*.whl 2>/dev/null | wc -l | xargs) wheels)"
@echo " Linux x86_64: $(VENDOR_LINUX_X86)/ ($$(ls $(VENDOR_LINUX_X86)/*.whl 2>/dev/null | wc -l | xargs) wheels)"
@echo " Linux aarch64: $(VENDOR_LINUX_ARM)/ ($$(ls $(VENDOR_LINUX_ARM)/*.whl 2>/dev/null | wc -l | xargs) wheels)"
@echo ""
@echo "Commit with: git add vendor/ && git commit -m 'vendor: update wheels'"
.PHONY: vendor-all-dev
vendor-all-dev: vendor-linux vendor-linux-dev vendor-linux-arm vendor-linux-arm-dev
@echo ""
@echo "✓ All platform wheels (runtime + dev):"
@echo " Linux x86_64 (runtime): $(VENDOR_LINUX_X86)/"
@echo " Linux x86_64 (dev): $(VENDOR_LINUX_X86)-dev/"
@echo " Linux aarch64 (runtime): $(VENDOR_LINUX_ARM)/"
@echo " Linux aarch64 (dev): $(VENDOR_LINUX_ARM)-dev/"
@echo ""
@echo "For macOS dev wheels, run on native macOS"
.PHONY: vendor-linux-dev
vendor-linux-dev: requirements-dev.txt
@echo "Building Linux x86_64 dev wheels (Docker)..."
mkdir -p $(VENDOR_LINUX)-dev
docker run --rm \
--platform linux/amd64 \
-v "$$PWD":$(WORKDIR) \
-w $(WORKDIR) \
python:3.12-slim \
bash -c " \
set -e && \
apt-get update -qq && apt-get install -y -qq gcc g++ make libffi-dev && \
pip install --upgrade pip && \
pip download --dest $(VENDOR_LINUX)-dev -r requirements-dev.txt && \
pip wheel --wheel-dir $(VENDOR_LINUX)-dev --no-deps $(VENDOR_LINUX)-dev/*.tar.gz 2>/dev/null || true && \
rm -f $(VENDOR_LINUX)-dev/*.tar.gz && \
cd $(VENDOR_LINUX)-dev && sha256sum *.whl > SHA256SUMS \
"
@echo "✓ Linux x86_64 dev wheels: $(VENDOR_LINUX)-dev/"
.PHONY: verify-vendor
verify-vendor:
@echo "Testing offline installation from vendor/..."
@bash -c ' \
if [[ "$$OSTYPE" == "darwin"* ]]; then \
PLATFORM="macos-arm64"; \
else \
PLATFORM="linux-x86_64"; \
fi; \
echo "Platform: $$PLATFORM"; \
python3.12 -m venv .venv-verify && \
source .venv-verify/bin/activate && \
pip install --no-index --find-links=vendor/$$PLATFORM -r requirements.txt && \
python src/pyhdwallet.py test && \
echo "" && \
echo "✅ Vendor installation verified!" && \
deactivate && \
rm -rf .venv-verify \
'
# ---------- Offline Installation ----------
.PHONY: install-offline
install-offline:
@echo "Installing from vendor/ (runtime only)..."
@./install_offline.sh
.PHONY: install-dev-offline
install-dev-offline:
@echo "Installing from vendor/ (dev mode with pytest)..."
@./install_offline.sh --dev
# ---------- Binary Building ----------
.PHONY: binary
binary:
@echo "🔨 Building binary for current platform: $(PLATFORM)-$(ARCH)..."
ifeq ($(PLATFORM),macos)
@if [ ! -f "build_binary.sh" ]; then \
echo "❌ build_binary.sh not found!"; \
exit 1; \
fi
@bash build_binary.sh
else
@echo "⚠️ For Linux native builds, use build_binary.sh directly"
@echo " Or use: make binary-linux (builds via Docker)"
endif
.PHONY: binary-linux
binary-linux:
@./build_binary_linux.sh
.PHONY: binary-all
binary-all:
@echo "🏗️ Building binaries for all platforms..."
@echo ""
@echo "1⃣ Building native binary..."
@$(MAKE) binary
@echo ""
@echo "2⃣ Building Linux binary via Docker..."
@$(MAKE) binary-linux
@echo ""
@echo "✅ All binaries built:"
@ls -lh dist/pyhdwallet* 2>/dev/null | awk '{print " " $$9 " (" $$5 ")"}' || echo " No binaries found"
# ---------- Development Workflow ----------
.PHONY: wheels
wheels: requirements.txt build-image
docker run --rm \
-v "$$PWD":$(WORKDIR) \
-w $(WORKDIR) \
$(IMAGE) \
bash -c " \
pip install --upgrade pip setuptools wheel && \
mkdir -p $(WHEELHOUSE) && \
pip wheel -r requirements.txt -w $(WHEELHOUSE) \
"
.PHONY: install
install: requirements.txt
@if [ ! -d "$(VENV_HOST)" ]; then \
echo "Creating venv: $(VENV_HOST)"; \
python3.12 -m venv $(VENV_HOST); \
fi
. $(VENV_HOST)/bin/activate && \
pip install --upgrade pip && \
pip install -r requirements.txt && \
echo "✓ Virtual environment ready: $(VENV_HOST)"
.PHONY: test
test:
@if [ ! -d "$(VENV_HOST)" ]; then \
echo "ERROR: Run 'make install' first"; \
exit 1; \
fi
. $(VENV_HOST)/bin/activate && \
pytest -v tests/test_vectors.py && \
python src/pyhdwallet.py test
# ---------- Warm container lifecycle ----------
.PHONY: up
up: build-image
docker run -dit \
-v "$$PWD":$(WORKDIR) \
-w $(WORKDIR) \
--name $(CONTAINER) \
$(IMAGE) \
bash
.PHONY: shell
shell:
docker exec -it $(CONTAINER) bash
.PHONY: down
down:
- docker rm -f $(CONTAINER)
# ---------- Cleanup ----------
.PHONY: clean-vendor
clean-vendor:
rm -rf vendor/
.PHONY: clean
clean: down
rm -rf $(VENV_HOST) $(WHEELHOUSE) .venv-verify .venv-offline-test
rm -rf dist/ build/ *.spec src/pyhdwallet_frozen.py
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
# NOTE: vendor/ is kept (use 'make clean-vendor' to remove)
# ---------- Platform-Aware Operations ----------
.PHONY: info
info:
@echo "Platform Information:"
@echo " OS: $(PLATFORM)"
@echo " Architecture: $(ARCH)"
@echo " Vendor dir: $(VENDOR_DIR)"
@echo " Python: $(shell python3 --version 2>/dev/null || echo 'not found')"
@echo " Docker: $(shell docker --version 2>/dev/null || echo 'not found')"
# ---------- Release Management ----------
VERSION := v1.1.0
RELEASE_DIR := releases/$(VERSION)
.PHONY: release-prep
release-prep:
@echo "📦 Preparing release $(VERSION)..."
@mkdir -p $(RELEASE_DIR)
.PHONY: release-binaries
release-binaries: release-prep binary binary-linux
@echo "📦 Copying binaries to $(RELEASE_DIR)..."
@cp dist/pyhdwallet $(RELEASE_DIR)/pyhdwallet-macos-arm64
@cp dist/pyhdwallet-linux $(RELEASE_DIR)/pyhdwallet-linux-x86_64
@echo "✅ Binaries copied"
.PHONY: release-checksums
release-checksums: release-binaries
@echo "🔐 Generating checksums..."
@cd $(RELEASE_DIR) && shasum -a 256 pyhdwallet-* > SHA256SUMS
@echo "✅ Checksums generated:"
@cat $(RELEASE_DIR)/SHA256SUMS
.PHONY: release-vendors
release-vendors: release-prep vendor-all
@echo "📦 Copying vendor wheels to $(RELEASE_DIR)..."
@mkdir -p $(RELEASE_DIR)/vendor
@cp -r vendor/macos-arm64 $(RELEASE_DIR)/vendor/
@cp -r vendor/linux-x86_64 $(RELEASE_DIR)/vendor/
@echo "✅ Vendor wheels copied"
.PHONY: release
release: release-checksums
@echo ""
@echo "🎉 Release $(VERSION) binaries ready!"
@echo ""
@if [ -d ".venv312" ]; then \
echo "📦 Building vendor wheels..."; \
$(MAKE) release-vendors; \
else \
echo "⚠️ Skipping vendor wheels (.venv312 not found)"; \
echo " To include vendors: python3.12 -m venv .venv312 && make release-vendors"; \
fi
@echo ""
@echo "Contents:"
@ls -lh $(RELEASE_DIR)/ | tail -n +2
@echo ""
@cat $(RELEASE_DIR)/SHA256SUMS
@echo ""
@echo "Next steps:"
@echo " 1. Test: make release-test"
@echo " 2. Tag: git tag -a $(VERSION) -m 'Release $(VERSION)'"
@echo " 3. Push: git push origin $(VERSION)"
.PHONY: release-test
release-test:
@echo "🧪 Testing release binaries..."
@echo ""
@echo "Testing macOS binary:"
@$(RELEASE_DIR)/pyhdwallet-macos-arm64 test || echo "⚠️ macOS binary test skipped (wrong platform)"
@echo ""
@echo "Testing Linux binary (via Docker):"
@docker run --rm --platform linux/amd64 \
-v "$$PWD/$(RELEASE_DIR)":/binaries \
ubuntu:22.04 \
/binaries/pyhdwallet-linux-x86_64 test
.PHONY: clean-release
clean-release:
@echo "🧹 Cleaning release artifacts..."
@rm -rf releases/
@echo "✅ Release artifacts cleaned"
.PHONY: clean-vendor
clean-vendor:
@echo "Removing all vendor wheels..."
rm -rf vendor/
@echo "✓ Vendor directory cleaned"
.PHONY: clean
clean: clean-vendor
@echo "Removing virtual environments..."
rm -rf .venv
@echo "Removing Python cache..."
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
find . -type f -name "*.pyc" -delete
@echo "✓ Cleanup complete"