backend-infra-engineer: Release v0.3.2 snapshot

This commit is contained in:
scawful
2025-10-17 12:10:25 -04:00
parent 4371618a9b
commit 3d71417f62
857 changed files with 174954 additions and 45626 deletions

View File

@@ -1,143 +1,117 @@
# YAZE Build Scripts
This directory contains build and setup scripts for YAZE development on different platforms.
This directory contains build automation and maintenance scripts for the YAZE project.
## Windows Scripts
## build_cleaner.py
### Setup Scripts
- **`setup-windows-dev.ps1`** - Complete Windows development environment setup (PowerShell)
- **`setup-vcpkg-windows.ps1`** - vcpkg setup only (PowerShell)
- **`setup-vcpkg-windows.bat`** - vcpkg setup only (Batch)
Automates CMake source list maintenance and header include management with IWYU-style analysis.
### Build Scripts
- **`build-windows.ps1`** - Build YAZE on Windows (PowerShell)
- **`build-windows.bat`** - Build YAZE on Windows (Batch)
### Features
### Validation Scripts
- **`validate-windows-build.ps1`** - Validate Windows build environment
1. **CMake Source List Maintenance**: Automatically updates source file lists in CMake files
2. **Self-Header Includes**: Ensures source files include their corresponding headers
3. **IWYU-Style Analysis**: Suggests missing headers based on symbol usage
4. **.gitignore Support**: Respects .gitignore patterns when scanning files
5. **Auto-Discovery**: Can discover CMake libraries that opt-in to auto-maintenance
### Project Generation
- **`generate-vs-projects.py`** - Generate Visual Studio project files (Cross-platform Python)
- **`generate-vs-projects.ps1`** - Generate Visual Studio project files (PowerShell)
- **`generate-vs-projects.bat`** - Generate Visual Studio project files (Batch)
### Usage
## Quick Start (Windows)
```bash
# Dry-run to see what would change (recommended first step)
python3 scripts/build_cleaner.py --dry-run
### Option 1: Automated Setup (Recommended)
```powershell
.\scripts\setup-windows-dev.ps1
# Update CMake source lists and header includes
python3 scripts/build_cleaner.py
# Run IWYU-style header analysis
python3 scripts/build_cleaner.py --iwyu
# Auto-discover CMake libraries marked for auto-maintenance
python3 scripts/build_cleaner.py --auto-discover
# Update only CMake source lists
python3 scripts/build_cleaner.py --cmake-only
# Update only header includes
python3 scripts/build_cleaner.py --includes-only
```
### Option 2: Manual Setup
```powershell
# 1. Setup vcpkg
.\scripts\setup-vcpkg-windows.ps1
### Opting-In to Auto-Maintenance
# 2. Generate project files
python scripts/generate-vs-projects.py
By default, the script only auto-maintains source lists that are explicitly marked. To mark a CMake variable for auto-maintenance, add a comment above the `set()` statement:
# 3. Build
.\scripts\build-windows.ps1
```cmake
# This list is auto-maintained by scripts/build_cleaner.py
set(
YAZE_APP_EMU_SRC
app/emu/audio/apu.cc
app/emu/cpu/cpu.cc
# ... more files
)
```
### Option 3: Using Batch Scripts
```batch
REM Setup vcpkg
.\scripts\setup-vcpkg-windows.bat
The script looks for comments containing "auto-maintain" (case-insensitive) within 3 lines above the `set()` statement.
REM Generate project files
python scripts/generate-vs-projects.py
### Excluding Files from Processing
REM Build
.\scripts\build-windows.bat
To exclude a specific file from all processing (CMake lists, header includes, IWYU), add this token near the top of the file:
```cpp
// build_cleaner:ignore
```
## Script Options
### .gitignore Support
### setup-windows-dev.ps1
- `-SkipVcpkg` - Skip vcpkg setup
- `-SkipVS` - Skip Visual Studio check
- `-SkipBuild` - Skip test build
The script automatically respects `.gitignore` patterns. To enable this feature, install the `pathspec` dependency:
### build-windows.ps1
- `-Configuration` - Build configuration (Debug, Release, RelWithDebInfo, MinSizeRel)
- `-Platform` - Target platform (x64, x86, ARM64)
- `-Clean` - Clean build directories before building
- `-Verbose` - Verbose build output
### build-windows.bat
- First argument: Configuration (Debug, Release, RelWithDebInfo, MinSizeRel)
- Second argument: Platform (x64, x86, ARM64)
- `clean` - Clean build directories
- `verbose` - Verbose build output
## Examples
```powershell
# Build Release x64 (default)
.\scripts\build-windows.ps1
# Build Debug x64
.\scripts\build-windows.ps1 -Configuration Debug -Platform x64
# Build Release x86
.\scripts\build-windows.ps1 -Configuration Release -Platform x86
# Clean build
.\scripts\build-windows.ps1 -Clean
# Verbose build
.\scripts\build-windows.ps1 -Verbose
# Validate environment
.\scripts\validate-windows-build.ps1
```bash
pip3 install -r scripts/requirements.txt
# or
pip3 install pathspec
```
```batch
REM Build Release x64 (default)
.\scripts\build-windows.bat
### IWYU Configuration
REM Build Debug x64
.\scripts\build-windows.bat Debug x64
The script includes basic IWYU-style analysis that suggests headers based on symbol prefixes. To customize which headers are suggested, edit the `COMMON_HEADERS` dictionary in the script:
REM Build Release x86
.\scripts\build-windows.bat Release x86
REM Clean build
.\scripts\build-windows.bat clean
```python
COMMON_HEADERS = {
'std::': ['<memory>', '<string>', '<vector>', ...],
'absl::': ['<absl/status/status.h>', ...],
'ImGui::': ['<imgui.h>'],
'SDL_': ['<SDL.h>'],
}
```
## Troubleshooting
**Note**: The IWYU analysis is conservative and may suggest headers that are already transitively included. Use with care and review suggestions before applying.
### Common Issues
### Integration with CMake
1. **PowerShell Execution Policy**
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
The script is integrated into the CMake build system:
2. **MSBuild Not Found**
- Install Visual Studio 2022 with C++ workload
- Or add MSBuild to PATH
```bash
# Run as a CMake target
cmake --build build --target build_cleaner
```
3. **vcpkg Issues**
- Run `.\scripts\setup-vcpkg-windows.ps1` to reinstall
- Check internet connection for dependency downloads
### Dependencies
4. **Python Not Found**
- Install Python 3.8+ from python.org
- Make sure Python is in PATH
- Python 3.7+
- `pathspec` (optional, for .gitignore support): `pip3 install pathspec`
### Getting Help
### How It Works
1. Run validation script: `.\scripts\validate-windows-build.ps1`
2. Check the [Windows Development Guide](../docs/windows-development-guide.md)
3. Review build output for specific error messages
1. **CMake Maintenance**: Scans directories specified in the configuration and updates `set(VAR_NAME ...)` blocks with the current list of source files
2. **Self-Headers**: For each `.cc`/`.cpp` file, ensures it includes its corresponding `.h` file
3. **IWYU Analysis**: Scans source files for symbols and suggests appropriate headers based on prefix matching
## Other Scripts
### Current Auto-Maintained Variables
- **`create_release.sh`** - Create GitHub releases (Linux/macOS)
- **`extract_changelog.py`** - Extract changelog for releases
- **`quality_check.sh`** - Code quality checks (Linux/macOS)
- **`test_asar_integration.py`** - Test Asar integration
- **`agent.sh`** - AI agent helper script (Linux/macOS)
**All 20 library source lists are now auto-maintained by default:**
- Core: `YAZE_APP_EMU_SRC`, `YAZE_APP_CORE_SRC`, `YAZE_APP_EDITOR_SRC`, `YAZE_APP_ZELDA3_SRC`, `YAZE_NET_SRC`, `YAZE_UTIL_SRC`
- GFX: `GFX_TYPES_SRC`, `GFX_BACKEND_SRC`, `GFX_RESOURCE_SRC`, `GFX_CORE_SRC`, `GFX_UTIL_SRC`, `GFX_RENDER_SRC`, `GFX_DEBUG_SRC`
- GUI: `GUI_CORE_SRC`, `CANVAS_SRC`, `GUI_WIDGETS_SRC`, `GUI_AUTOMATION_SRC`, `GUI_APP_SRC`
- Other: `YAZE_AGENT_SOURCES`, `YAZE_TEST_SOURCES`
The script intelligently preserves conditional blocks (if/endif) and excludes conditional files from the main source list.

View File

@@ -1,369 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Unified background agent script for YAZE (macOS launchd, Linux systemd)
# Subcommands:
# install [--build-type X] [--use-inotify] [--ubuntu-bootstrap] [--enable-linger]
# uninstall
# run-once # one-shot build & test
# watch # linux: inotify-based watch loop
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
BUILD_DIR_DEFAULT="${PROJECT_ROOT}/build"
BUILD_TYPE_DEFAULT="Debug"
usage() {
cat <<EOF
Usage: $0 <subcommand> [options]
Subcommands:
install Install background agent
--build-type X CMake build type (default: ${BUILD_TYPE_DEFAULT})
--use-inotify Linux: use long-lived inotify watcher
--ubuntu-bootstrap Install Ubuntu deps via apt (sudo)
--enable-linger Enable user lingering (Linux)
uninstall Remove installed background agent
run-once One-shot build and test
env: BUILD_DIR, BUILD_TYPE
watch Linux: inotify-based watch loop
env: BUILD_DIR, BUILD_TYPE, INTERVAL_SECONDS (fallback)
Environment:
BUILD_DIR Build directory (default: ${BUILD_DIR_DEFAULT})
BUILD_TYPE CMake build type (default: ${BUILD_TYPE_DEFAULT})
EOF
}
build_and_test() {
local build_dir="${BUILD_DIR:-${BUILD_DIR_DEFAULT}}"
local build_type="${BUILD_TYPE:-${BUILD_TYPE_DEFAULT}}"
local log_file="${LOG_FILE:-"${build_dir}/yaze_agent.log"}"
mkdir -p "${build_dir}"
{
echo "==== $(date '+%Y-%m-%d %H:%M:%S') | yaze agent run (type=${build_type}) ===="
echo "Project: ${PROJECT_ROOT}"
cmake -S "${PROJECT_ROOT}" -B "${build_dir}" -DCMAKE_BUILD_TYPE="${build_type}"
cmake --build "${build_dir}" --config "${build_type}" -j
if [[ -x "${build_dir}/bin/yaze_test" ]]; then
"${build_dir}/bin/yaze_test"
else
if command -v ctest >/dev/null 2>&1; then
ctest --test-dir "${build_dir}" --output-on-failure
else
echo "ctest not found and test binary missing. Skipping tests." >&2
exit 1
fi
fi
} >>"${log_file}" 2>&1
}
sub_run_once() {
build_and_test
}
sub_watch() {
local build_dir="${BUILD_DIR:-${BUILD_DIR_DEFAULT}}"
local build_type="${BUILD_TYPE:-${BUILD_TYPE_DEFAULT}}"
local interval="${INTERVAL_SECONDS:-5}"
mkdir -p "${build_dir}"
if command -v inotifywait >/dev/null 2>&1; then
echo "[agent] using inotifywait watcher"
while true; do
BUILD_DIR="${build_dir}" BUILD_TYPE="${build_type}" build_and_test || true
inotifywait -r -e modify,create,delete,move \
"${PROJECT_ROOT}/src" \
"${PROJECT_ROOT}/test" \
"${PROJECT_ROOT}/CMakeLists.txt" \
"${PROJECT_ROOT}/src/CMakeLists.txt" >/dev/null 2>&1 || true
done
else
echo "[agent] inotifywait not found; running periodic loop (${interval}s)"
while true; do
BUILD_DIR="${build_dir}" BUILD_TYPE="${build_type}" build_and_test || true
sleep "${interval}"
done
fi
}
ensure_exec() {
if [[ ! -x "$1" ]]; then
chmod +x "$1"
fi
}
ubuntu_bootstrap() {
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y inotify-tools build-essential cmake ninja-build pkg-config \
libsdl2-dev libpng-dev libglew-dev libwavpack-dev libabsl-dev \
libboost-all-dev libboost-python-dev python3-dev libpython3-dev
else
echo "apt-get not found; skipping Ubuntu bootstrap" >&2
fi
}
enable_linger_linux() {
if command -v loginctl >/dev/null 2>&1; then
if sudo -n true 2>/dev/null; then
sudo loginctl enable-linger "$USER" || true
else
echo "Note: enabling linger may require sudo: sudo loginctl enable-linger $USER" >&2
fi
fi
}
# Wrapper to run systemctl --user with a session bus in headless shells
systemctl_user() {
# Only apply on Linux
if [[ "$(uname -s)" != "Linux" ]]; then
systemctl "$@"
return
fi
local uid
uid="$(id -u)"
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/${uid}}"
export DBUS_SESSION_BUS_ADDRESS="${DBUS_SESSION_BUS_ADDRESS:-unix:path=${XDG_RUNTIME_DIR}/bus}"
if [[ ! -S "${XDG_RUNTIME_DIR}/bus" ]]; then
echo "[agent] Warning: user bus not found at ${XDG_RUNTIME_DIR}/bus. If this fails, run: sudo loginctl enable-linger $USER" >&2
fi
systemctl --user "$@"
}
is_systemd_available() {
# True if systemd is PID 1 and systemctl exists and a user bus likely available
if [[ ! -d /run/systemd/system ]]; then
return 1
fi
if ! command -v systemctl >/dev/null 2>&1; then
return 1
fi
return 0
}
start_userland_agent() {
local build_type="${1}"
local build_dir="${2}"
local agent_home="$HOME/.local/share/yaze-agent"
mkdir -p "${agent_home}"
local log_file="${agent_home}/agent.log"
nohup env BUILD_TYPE="${build_type}" BUILD_DIR="${build_dir}" "${SCRIPT_DIR}/agent.sh" watch >>"${log_file}" 2>&1 & echo $! > "${agent_home}/agent.pid"
echo "Userland agent started (PID $(cat "${agent_home}/agent.pid")) - logs: ${log_file}"
}
stop_userland_agent() {
local agent_home="$HOME/.local/share/yaze-agent"
local pid_file="${agent_home}/agent.pid"
if [[ -f "${pid_file}" ]]; then
local pid
pid="$(cat "${pid_file}")"
if kill -0 "${pid}" >/dev/null 2>&1; then
kill "${pid}" || true
fi
rm -f "${pid_file}"
echo "Stopped userland agent"
fi
}
install_macos() {
local build_type="${1}"
local build_dir="${2}"
local label="com.yaze.watchtest"
local plist_path="$HOME/Library/LaunchAgents/${label}.plist"
mkdir -p "${build_dir}"
cat >"$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${label}</string>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>-lc</string>
<string>"${SCRIPT_DIR}/agent.sh" run-once</string>
</array>
<key>WorkingDirectory</key>
<string>${PROJECT_ROOT}</string>
<key>WatchPaths</key>
<array>
<string>${PROJECT_ROOT}/src</string>
<string>${PROJECT_ROOT}/test</string>
<string>${PROJECT_ROOT}/CMakeLists.txt</string>
<string>${PROJECT_ROOT}/src/CMakeLists.txt</string>
</array>
<key>StandardOutPath</key>
<string>${build_dir}/yaze_agent.out.log</string>
<key>StandardErrorPath</key>
<string>${build_dir}/yaze_agent.err.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>BUILD_TYPE</key><string>${build_type}</string>
<key>BUILD_DIR</key><string>${build_dir}</string>
</dict>
</dict>
</plist>
PLIST
launchctl unload -w "$plist_path" 2>/dev/null || true
launchctl load -w "$plist_path"
echo "LaunchAgent installed and loaded: ${plist_path}"
}
install_linux() {
local build_type="${1}"
local build_dir="${2}"
local use_inotify="${3}"
local systemd_dir="$HOME/.config/systemd/user"
local service_name="yaze-watchtest.service"
local path_name="yaze-watchtest.path"
mkdir -p "${systemd_dir}" "${build_dir}"
if ! is_systemd_available; then
echo "[agent] systemd not available; installing userland background agent"
start_userland_agent "${build_type}" "${build_dir}"
return
fi
if [[ "${use_inotify}" == "1" ]]; then
cat >"${systemd_dir}/yaze-watchtest-inotify.service" <<UNIT
[Unit]
Description=Yaze inotify watcher build-and-test
[Service]
Type=simple
Environment=BUILD_TYPE=${build_type}
Environment=BUILD_DIR=${build_dir}
WorkingDirectory=${PROJECT_ROOT}
ExecStart=/bin/bash -lc '"${SCRIPT_DIR}/agent.sh" watch'
Restart=always
RestartSec=2
[Install]
WantedBy=default.target
UNIT
systemctl_user daemon-reload
systemctl_user enable --now yaze-watchtest-inotify.service
echo "systemd user service enabled: yaze-watchtest-inotify.service"
return
fi
cat >"${systemd_dir}/${service_name}" <<UNIT
[Unit]
Description=Yaze build-and-test (one-shot)
[Service]
Type=oneshot
Environment=BUILD_TYPE=${build_type}
Environment=BUILD_DIR=${build_dir}
WorkingDirectory=${PROJECT_ROOT}
ExecStart=/bin/bash -lc '"${SCRIPT_DIR}/agent.sh" run-once'
UNIT
cat >"${systemd_dir}/${path_name}" <<UNIT
[Unit]
Description=Watch Yaze src/test for changes
[Path]
PathModified=${PROJECT_ROOT}/src
PathModified=${PROJECT_ROOT}/test
PathModified=${PROJECT_ROOT}/CMakeLists.txt
PathModified=${PROJECT_ROOT}/src/CMakeLists.txt
Unit=${service_name}
[Install]
WantedBy=default.target
UNIT
systemctl_user daemon-reload
systemctl_user enable --now "$path_name"
echo "systemd user path unit enabled: ${path_name}"
systemctl_user start "$service_name" || true
}
sub_install() {
local build_type="${BUILD_TYPE:-${BUILD_TYPE_DEFAULT}}"
local build_dir="${BUILD_DIR:-${BUILD_DIR_DEFAULT}}"
local use_inotify=0
local do_bootstrap=0
local do_linger=0
while [[ $# -gt 0 ]]; do
case "$1" in
--build-type) build_type="$2"; shift 2 ;;
--use-inotify) use_inotify=1; shift ;;
--ubuntu-bootstrap) do_bootstrap=1; shift ;;
--enable-linger) do_linger=1; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "Unknown option for install: $1" >&2; usage; exit 1 ;;
esac
done
case "$(uname -s)" in
Darwin)
install_macos "${build_type}" "${build_dir}" ;;
Linux)
if (( do_bootstrap == 1 )); then ubuntu_bootstrap; fi
if (( do_linger == 1 )); then enable_linger_linux; fi
install_linux "${build_type}" "${build_dir}" "${use_inotify}" ;;
*)
echo "Unsupported platform" >&2; exit 1 ;;
esac
}
sub_uninstall() {
case "$(uname -s)" in
Darwin)
local label="com.yaze.watchtest"
local plist_path="$HOME/Library/LaunchAgents/${label}.plist"
launchctl unload -w "$plist_path" 2>/dev/null || true
rm -f "$plist_path"
echo "Removed LaunchAgent ${label}"
;;
Linux)
local systemd_dir="$HOME/.config/systemd/user"
if is_systemd_available; then
systemctl_user stop yaze-watchtest.path 2>/dev/null || true
systemctl_user disable yaze-watchtest.path 2>/dev/null || true
systemctl_user stop yaze-watchtest.service 2>/dev/null || true
systemctl_user stop yaze-watchtest-inotify.service 2>/dev/null || true
systemctl_user disable yaze-watchtest-inotify.service 2>/dev/null || true
rm -f "${systemd_dir}/yaze-watchtest.service" "${systemd_dir}/yaze-watchtest.path" "${systemd_dir}/yaze-watchtest-inotify.service"
systemctl_user daemon-reload || true
echo "Removed systemd user units"
fi
stop_userland_agent
;;
*) echo "Unsupported platform" >&2; exit 1 ;;
esac
}
main() {
ensure_exec "$0"
local subcmd="${1:-}"; shift || true
case "${subcmd}" in
install) sub_install "$@" ;;
uninstall) sub_uninstall ;;
run-once) sub_run_once ;;
watch) sub_watch ;;
-h|--help|help|"") usage ;;
*) echo "Unknown subcommand: ${subcmd}" >&2; usage; exit 1 ;;
esac
}
main "$@"

389
scripts/agent_test_suite.sh Executable file
View File

@@ -0,0 +1,389 @@
#!/bin/bash
# Comprehensive test script for Ollama and Gemini AI providers with tool calling
set -e
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
Z3ED="./build_test/bin/z3ed"
RESULTS_FILE="/tmp/z3ed_ai_test_results.txt"
USE_MOCK_ROM=true # Set to false if you want to test with a real ROM
OLLAMA_MODEL="${OLLAMA_MODEL:-qwen2.5-coder:latest}"
OLLAMA_PID=""
echo "=========================================="
echo " Z3ED AI Provider Test Suite"
echo "=========================================="
echo ""
# Clear results file
> "$RESULTS_FILE"
# Cleanup function
cleanup() {
if [ -n "$OLLAMA_PID" ]; then
echo ""
echo "Stopping Ollama server (PID: $OLLAMA_PID)..."
kill "$OLLAMA_PID" 2>/dev/null || true
wait "$OLLAMA_PID" 2>/dev/null || true
fi
}
# Register cleanup on exit
trap cleanup EXIT INT TERM
# --- Helper Functions ---
# Start Ollama server if not already running
start_ollama_server() {
echo "Checking Ollama server status..."
# Check if Ollama is already running
if curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then
echo -e "${GREEN}✓ Ollama server already running${NC}"
return 0
fi
# Check if ollama command exists
if ! command -v ollama &> /dev/null; then
echo -e "${YELLOW}⚠ Ollama command not found. Skipping Ollama tests.${NC}"
echo "PATH: $PATH"
echo "Which ollama: $(which ollama 2>&1 || echo 'not found')"
return 1
fi
echo "Starting Ollama server..."
echo "Ollama path: $(which ollama)"
ollama serve > /tmp/ollama_server.log 2>&1 &
OLLAMA_PID=$!
echo "Ollama PID: $OLLAMA_PID"
# Wait for server to be ready (max 60 seconds for CI)
local max_wait=60
local waited=0
echo -n "Waiting for Ollama server to start"
while [ $waited -lt $max_wait ]; do
if curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then
echo ""
echo -e "${GREEN}✓ Ollama server started (PID: $OLLAMA_PID) after ${waited}s${NC}"
return 0
fi
echo -n "."
sleep 1
waited=$((waited + 1))
# Check if process is still alive
if ! kill -0 "$OLLAMA_PID" 2>/dev/null; then
echo ""
echo -e "${RED}✗ Ollama server process died${NC}"
echo "Last 20 lines of server log:"
tail -20 /tmp/ollama_server.log || echo "No log available"
return 1
fi
done
echo ""
echo -e "${RED}✗ Ollama server failed to start within ${max_wait}s${NC}"
echo "Last 20 lines of server log:"
tail -20 /tmp/ollama_server.log || echo "No log available"
return 1
}
# Ensure Ollama model is available
setup_ollama_model() {
local model="$1"
echo "Checking for Ollama model: $model"
echo "Current models:"
ollama list || echo "Failed to list models"
if ollama list | grep -q "${model%:*}"; then
echo -e "${GREEN}✓ Model $model already available${NC}"
return 0
fi
echo "Pulling Ollama model: $model (this may take a while)..."
echo "This is required for first-time setup in CI"
if ollama pull "$model"; then
echo -e "${GREEN}✓ Model $model pulled successfully${NC}"
return 0
else
echo -e "${RED}✗ Failed to pull model $model${NC}"
return 1
fi
}
# --- Pre-flight Checks ---
if [ -z "$1" ]; then
echo "❌ Error: No AI provider specified."
echo "Usage: $0 <ollama|gemini|mock>"
echo ""
echo "Environment Variables:"
echo " OLLAMA_MODEL - Ollama model to use (default: qwen2.5-coder:latest)"
echo " GEMINI_API_KEY - Required for Gemini provider"
echo ""
echo "Examples:"
echo " $0 ollama # Use Ollama with default model"
echo " OLLAMA_MODEL=llama3:8b $0 ollama # Use Ollama with llama3"
echo " GEMINI_API_KEY=xyz $0 gemini # Use Gemini"
exit 1
fi
PROVIDER=$1
echo "✅ Provider: $PROVIDER"
# Check for curl (needed for Ollama health checks)
if [ "$PROVIDER" == "ollama" ]; then
if ! command -v curl &> /dev/null; then
echo -e "${RED}✗ curl command not found (required for Ollama)${NC}"
exit 1
fi
echo "✅ curl available"
fi
# Check binary exists
if [ ! -f "$Z3ED" ]; then
echo -e "${RED}✗ z3ed binary not found at: $Z3ED${NC}"
echo "Run: cmake --build build_test"
exit 1
fi
echo "✅ z3ed binary found"
# Set ROM flags based on mode
if [ "$USE_MOCK_ROM" = true ]; then
ROM_FLAGS="--mock-rom"
echo "✅ Using mock ROM mode (no ROM file required)"
else
ROM="assets/zelda3.sfc"
if [ ! -f "$ROM" ]; then
echo -e "${RED}✗ ROM file not found: $ROM${NC}"
echo "Tip: Use mock ROM mode by setting USE_MOCK_ROM=true"
exit 1
fi
ROM_FLAGS="--rom=\"$ROM\""
echo "✅ Real ROM found: $ROM"
fi
# Verify z3ed can execute
if "$Z3ED" --help > /dev/null 2>&1; then
echo "✅ z3ed executable works"
else
echo "${RED}✗ z3ed failed to execute${NC}"
exit 1
fi
# Setup Ollama if needed
OLLAMA_AVAILABLE=false
if [ "$PROVIDER" == "ollama" ] || [ -z "$PROVIDER" ]; then
if start_ollama_server; then
if setup_ollama_model "$OLLAMA_MODEL"; then
OLLAMA_AVAILABLE=true
echo -e "${GREEN}✓ Ollama ready with model: $OLLAMA_MODEL${NC}"
else
echo -e "${YELLOW}⚠ Ollama server running but model setup failed${NC}"
fi
else
echo -e "${YELLOW}⚠ Ollama server not available${NC}"
fi
fi
# Test Gemini availability
GEMINI_AVAILABLE=false
if [ -n "$GEMINI_API_KEY" ]; then
GEMINI_AVAILABLE=true
echo -e "${GREEN}✓ Gemini API key configured${NC}"
else
echo -e "${YELLOW}⚠ Gemini API key not set${NC}"
fi
if [ "$PROVIDER" == "ollama" ] && [ "$OLLAMA_AVAILABLE" = false ]; then
echo -e "${RED}✗ Exiting: Ollama provider requested but not available.${NC}"
exit 1
fi
if [ "$PROVIDER" == "gemini" ] && [ "$GEMINI_AVAILABLE" = false ]; then
echo -e "${RED}✗ Exiting: Gemini provider requested but GEMINI_API_KEY is not set.${NC}"
exit 1
fi
# --- Run Test Suite ---
# Test function
run_test() {
local test_name="$1"
local provider="$2"
local query="$3"
local expected_pattern="$4"
local extra_args="$5"
echo "=========================================="
echo " Test: $test_name"
echo " Provider: $provider"
echo "=========================================="
echo ""
echo "Query: $query"
echo ""
local cmd="$Z3ED agent simple-chat \"$query\" $ROM_FLAGS --ai_provider=$provider $extra_args"
echo "Running: $cmd"
echo ""
local output
local exit_code=0
output=$($cmd 2>&1) || exit_code=$?
echo "$output"
echo ""
# Check for expected patterns
local result="UNKNOWN"
if [ $exit_code -ne 0 ]; then
result="FAILED (exit code: $exit_code)"
elif echo "$output" | grep -qi "$expected_pattern"; then
result="PASSED"
echo -e "${GREEN}✓ Response contains expected pattern: '$expected_pattern'${NC}"
else
result="FAILED (pattern not found)"
echo -e "${YELLOW}⚠ Response missing expected pattern: '$expected_pattern'${NC}"
fi
# Check for error indicators
if echo "$output" | grep -qi "error\|failed\|infinite loop"; then
result="FAILED (error detected)"
echo -e "${RED}✗ Error detected in output${NC}"
fi
# Record result
echo "$test_name | $provider | $result" >> "$RESULTS_FILE"
echo ""
echo -e "${BLUE}Result: $result${NC}"
echo ""
sleep 2 # Avoid rate limiting
}
# Test Suite
if [ "$OLLAMA_AVAILABLE" = true ]; then
echo ""
echo "=========================================="
echo " OLLAMA TESTS"
echo "=========================================="
echo ""
run_test "Ollama: Simple Question" "ollama" \
"What dungeons are in this ROM?" \
"dungeon\|palace\|castle"
run_test "Ollama: Sprite Query" "ollama" \
"What sprites are in room 0?" \
"sprite\|room"
run_test "Ollama: Tile Search" "ollama" \
"Where can I find trees in the overworld?" \
"tree\|0x02E\|map\|coordinate"
run_test "Ollama: Map Description" "ollama" \
"Describe overworld map 0" \
"light world\|map\|overworld"
run_test "Ollama: Warp List" "ollama" \
"List the warps in the Light World" \
"warp\|entrance\|exit"
fi
if [ "$GEMINI_AVAILABLE" = true ]; then
echo ""
echo "=========================================="
echo " GEMINI TESTS"
echo "=========================================="
echo ""
run_test "Gemini: Simple Question" "gemini" \
"What dungeons are in this ROM?" \
"dungeon\|palace\|castle" \
"--gemini_api_key=\"$GEMINI_API_KEY\""
run_test "Gemini: Sprite Query" "gemini" \
"What sprites are in room 0?" \
"sprite\|room" \
"--gemini_api_key=\"$GEMINI_API_KEY\""
run_test "Gemini: Tile Search" "gemini" \
"Where can I find trees in the overworld?" \
"tree\|0x02E\|map\|coordinate" \
"--gemini_api_key=\"$GEMINI_API_KEY\""
run_test "Gemini: Map Description" "gemini" \
"Describe overworld map 0" \
"light world\|map\|overworld" \
"--gemini_api_key=\"$GEMINI_API_KEY\""
run_test "Gemini: Warp List" "gemini" \
"List the warps in the Light World" \
"warp\|entrance\|exit" \
"--gemini_api_key=\"$GEMINI_API_KEY\""
fi
echo ""
echo "=========================================="
echo " TEST SUMMARY"
echo "=========================================="
echo ""
if [ -f "$RESULTS_FILE" ]; then
cat "$RESULTS_FILE"
echo ""
total=$(wc -l < "$RESULTS_FILE" | tr -d ' ')
passed=$(grep -c "PASSED" "$RESULTS_FILE" || echo "0")
failed=$(grep -c "FAILED" "$RESULTS_FILE" || echo "0")
echo "Total Tests: $total"
echo -e "${GREEN}Passed: $passed${NC}"
echo -e "${RED}Failed: $failed${NC}"
echo ""
if [ "$passed" -eq "$total" ]; then
echo -e "${GREEN}🎉 All tests passed!${NC}"
elif [ "$passed" -gt 0 ]; then
echo -e "${YELLOW}⚠ Some tests failed. Review output above.${NC}"
else
echo -e "${RED}✗ All tests failed. Check configuration.${NC}"
fi
else
echo -e "${RED}✗ No results file generated${NC}"
fi
echo ""
echo "=========================================="
echo " Recommendations"
echo "=========================================="
echo ""
echo "If tests are failing:"
echo " 1. Check that the ROM is valid and loaded properly"
echo " 2. Verify tool definitions in prompt_catalogue.yaml"
echo " 3. Review system prompts in prompt_builder.cc"
echo " 4. Check AI provider connectivity and quotas"
echo " 5. Examine tool execution logs for errors"
echo ""
echo "For Ollama:"
echo " - Try different models: OLLAMA_MODEL=llama3:8b $0 ollama"
echo " - Default model: $OLLAMA_MODEL"
echo " - Adjust temperature in ollama_ai_service.cc"
echo " - Server logs: /tmp/ollama_server.log"
echo ""
echo "For Gemini:"
echo " - Verify API key is valid"
echo " - Check quota at: https://aistudio.google.com"
echo ""
echo "Environment Variables:"
echo " - OLLAMA_MODEL: Set the Ollama model (default: qwen2.5-coder:latest)"
echo " - GEMINI_API_KEY: Required for Gemini tests"
echo ""
echo "Results saved to: $RESULTS_FILE"
echo ""

View File

@@ -1,164 +0,0 @@
@echo off
REM YAZE Windows Build Script (Batch Version)
REM This script builds the YAZE project on Windows using MSBuild
setlocal enabledelayedexpansion
REM Parse command line arguments
set BUILD_CONFIG=Release
set BUILD_PLATFORM=x64
set CLEAN_BUILD=0
set VERBOSE=0
:parse_args
if "%~1"=="" goto :args_done
if /i "%~1"=="Debug" set BUILD_CONFIG=Debug
if /i "%~1"=="Release" set BUILD_CONFIG=Release
if /i "%~1"=="RelWithDebInfo" set BUILD_CONFIG=RelWithDebInfo
if /i "%~1"=="MinSizeRel" set BUILD_CONFIG=MinSizeRel
if /i "%~1"=="x64" set BUILD_PLATFORM=x64
if /i "%~1"=="x86" set BUILD_PLATFORM=x86
if /i "%~1"=="ARM64" set BUILD_PLATFORM=ARM64
if /i "%~1"=="clean" set CLEAN_BUILD=1
if /i "%~1"=="verbose" set VERBOSE=1
shift
goto :parse_args
:args_done
echo ========================================
echo YAZE Windows Build Script
echo ========================================
REM Check if we're in the right directory
if not exist "YAZE.sln" (
echo ERROR: YAZE.sln not found. Please run this script from the project root directory.
pause
exit /b 1
)
echo ✓ YAZE.sln found
REM Check for MSBuild
where msbuild >nul 2>&1
if %errorlevel% neq 0 (
echo ERROR: MSBuild not found. Please install Visual Studio 2022 or later.
echo Make sure to install the C++ development workload.
pause
exit /b 1
)
echo ✓ MSBuild found
REM Check for vcpkg
if not exist "vcpkg.json" (
echo WARNING: vcpkg.json not found. vcpkg integration may not work properly.
)
echo Build Configuration: %BUILD_CONFIG%
echo Build Platform: %BUILD_PLATFORM%
REM Create build directories
echo Creating build directories...
if not exist "build" mkdir build
if not exist "build\bin" mkdir build\bin
if not exist "build\obj" mkdir build\obj
REM Clean build if requested
if %CLEAN_BUILD%==1 (
echo Cleaning build directories...
if exist "build\bin" rmdir /s /q "build\bin" 2>nul
if exist "build\obj" rmdir /s /q "build\obj" 2>nul
if not exist "build\bin" mkdir build\bin
if not exist "build\obj" mkdir build\obj
echo ✓ Build directories cleaned
)
REM Generate yaze_config.h if it doesn't exist
if not exist "yaze_config.h" (
echo Generating yaze_config.h...
if exist "src\yaze_config.h.in" (
copy "src\yaze_config.h.in" "yaze_config.h" >nul
powershell -Command "(Get-Content 'yaze_config.h') -replace '@yaze_VERSION_MAJOR@', '0' -replace '@yaze_VERSION_MINOR@', '3' -replace '@yaze_VERSION_PATCH@', '1' | Set-Content 'yaze_config.h'"
echo ✓ Generated yaze_config.h
) else (
echo WARNING: yaze_config.h.in not found, creating basic config
echo // yaze config file > yaze_config.h
echo #define YAZE_VERSION_MAJOR 0 >> yaze_config.h
echo #define YAZE_VERSION_MINOR 3 >> yaze_config.h
echo #define YAZE_VERSION_PATCH 1 >> yaze_config.h
)
)
REM Build using MSBuild
echo Building with MSBuild...
set MSBUILD_ARGS=YAZE.sln /p:Configuration=%BUILD_CONFIG% /p:Platform=%BUILD_PLATFORM% /p:VcpkgEnabled=true /p:VcpkgManifestInstall=true /m
if %VERBOSE%==1 (
set MSBUILD_ARGS=%MSBUILD_ARGS% /verbosity:detailed
) else (
set MSBUILD_ARGS=%MSBUILD_ARGS% /verbosity:minimal
)
echo Command: msbuild %MSBUILD_ARGS%
msbuild %MSBUILD_ARGS%
if %errorlevel% neq 0 (
echo ERROR: Build failed with exit code %errorlevel%
pause
exit /b 1
)
echo ✓ Build completed successfully
REM Verify executable was created
set EXE_PATH=build\bin\%BUILD_CONFIG%\yaze.exe
if not exist "%EXE_PATH%" (
echo ERROR: Executable not found at expected path: %EXE_PATH%
pause
exit /b 1
)
echo ✓ Executable created: %EXE_PATH%
REM Test that the executable runs (basic test)
echo Testing executable startup...
"%EXE_PATH%" --help >nul 2>&1
set EXIT_CODE=%errorlevel%
REM Check if it's the test main or app main
"%EXE_PATH%" --help 2>&1 | findstr /i "Google Test" >nul
if %errorlevel% equ 0 (
echo ERROR: Executable is running test main instead of app main!
pause
exit /b 1
)
echo ✓ Executable runs correctly (exit code: %EXIT_CODE%)
REM Display file info
for %%A in ("%EXE_PATH%") do set FILE_SIZE=%%~zA
set /a FILE_SIZE_MB=%FILE_SIZE% / 1024 / 1024
echo Executable size: %FILE_SIZE_MB% MB
echo ========================================
echo ✓ YAZE Windows build completed successfully!
echo ========================================
echo.
echo Build Configuration: %BUILD_CONFIG%
echo Build Platform: %BUILD_PLATFORM%
echo Executable: %EXE_PATH%
echo.
echo To run YAZE:
echo %EXE_PATH%
echo.
echo To build other configurations:
echo %~nx0 Debug x64
echo %~nx0 Release x86
echo %~nx0 RelWithDebInfo ARM64
echo %~nx0 clean
echo.
pause

View File

@@ -1,220 +0,0 @@
# YAZE Windows Build Script
# This script builds the YAZE project on Windows using MSBuild
param(
[string]$Configuration = "Release",
[string]$Platform = "x64",
[switch]$Clean,
[switch]$Verbose
)
# Set error handling
$ErrorActionPreference = "Continue"
# Colors for output
$Colors = @{
Success = "Green"
Warning = "Yellow"
Error = "Red"
Info = "Cyan"
White = "White"
}
function Write-Status {
param([string]$Message, [string]$Color = "White")
Write-Host $Message -ForegroundColor $Colors[$Color]
}
function Test-Command {
param([string]$Command)
try {
$null = Get-Command $Command -ErrorAction Stop
return $true
} catch {
return $false
}
}
function Get-MSBuildPath {
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (Test-Path $vsWhere) {
$vsInstall = & $vsWhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
if ($vsInstall) {
$msbuildPath = Join-Path $vsInstall "MSBuild\Current\Bin\MSBuild.exe"
if (Test-Path $msbuildPath) {
return $msbuildPath
}
}
}
return $null
}
# Main script
Write-Status "========================================" "Info"
Write-Status "YAZE Windows Build Script" "Info"
Write-Status "========================================" "Info"
# Validate parameters
$ValidConfigs = @("Debug", "Release", "RelWithDebInfo", "MinSizeRel")
$ValidPlatforms = @("x64", "x86", "ARM64")
if ($ValidConfigs -notcontains $Configuration) {
Write-Status "ERROR: Invalid configuration '$Configuration'. Valid options: $($ValidConfigs -join ', ')" "Error"
exit 1
}
if ($ValidPlatforms -notcontains $Platform) {
Write-Status "ERROR: Invalid platform '$Platform'. Valid options: $($ValidPlatforms -join ', ')" "Error"
exit 1
}
Write-Status "Build Configuration: $Configuration" "Warning"
Write-Status "Build Platform: $Platform" "Warning"
# Check if we're in the right directory
if (-not (Test-Path "YAZE.sln")) {
Write-Status "ERROR: YAZE.sln not found. Please run this script from the project root directory." "Error"
exit 1
}
Write-Status "✓ Found YAZE.sln" "Success"
# Check for MSBuild
$msbuildPath = Get-MSBuildPath
if (-not $msbuildPath) {
Write-Status "ERROR: MSBuild not found. Please install Visual Studio 2022 with C++ workload." "Error"
exit 1
}
Write-Status "✓ MSBuild found at: $msbuildPath" "Success"
# Check for vcpkg
if (-not (Test-Path "vcpkg.json")) {
Write-Status "WARNING: vcpkg.json not found. vcpkg integration may not work properly." "Warning"
}
# Create build directories
Write-Status "Creating build directories..." "Warning"
$directories = @("build", "build\bin", "build\obj")
foreach ($dir in $directories) {
if (-not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
Write-Status "✓ Created directory: $dir" "Success"
}
}
# Clean build if requested
if ($Clean) {
Write-Status "Cleaning build directories..." "Warning"
if (Test-Path "build\bin") {
Remove-Item -Recurse -Force "build\bin\*" -ErrorAction SilentlyContinue
}
if (Test-Path "build\obj") {
Remove-Item -Recurse -Force "build\obj\*" -ErrorAction SilentlyContinue
}
Write-Status "✓ Build directories cleaned" "Success"
}
# Generate yaze_config.h if it doesn't exist
if (-not (Test-Path "yaze_config.h")) {
Write-Status "Generating yaze_config.h..." "Warning"
if (Test-Path "src\yaze_config.h.in") {
Copy-Item "src\yaze_config.h.in" "yaze_config.h"
$content = Get-Content "yaze_config.h" -Raw
$content = $content -replace '@yaze_VERSION_MAJOR@', '0'
$content = $content -replace '@yaze_VERSION_MINOR@', '3'
$content = $content -replace '@yaze_VERSION_PATCH@', '1'
Set-Content "yaze_config.h" $content
Write-Status "✓ Generated yaze_config.h" "Success"
} else {
Write-Status "WARNING: yaze_config.h.in not found, creating basic config" "Warning"
@"
// yaze config file
#define YAZE_VERSION_MAJOR 0
#define YAZE_VERSION_MINOR 3
#define YAZE_VERSION_PATCH 1
"@ | Out-File -FilePath "yaze_config.h" -Encoding UTF8
}
}
# Build using MSBuild
Write-Status "Building with MSBuild..." "Warning"
$msbuildArgs = @(
"YAZE.sln"
"/p:Configuration=$Configuration"
"/p:Platform=$Platform"
"/p:VcpkgEnabled=true"
"/p:VcpkgManifestInstall=true"
"/m"
)
if ($Verbose) {
$msbuildArgs += "/verbosity:detailed"
} else {
$msbuildArgs += "/verbosity:minimal"
}
$msbuildCommand = "& `"$msbuildPath`" $($msbuildArgs -join ' ')"
Write-Status "Command: $msbuildCommand" "Info"
try {
& $msbuildPath @msbuildArgs
if ($LASTEXITCODE -ne 0) {
throw "MSBuild failed with exit code $LASTEXITCODE"
}
Write-Status "✓ Build completed successfully" "Success"
} catch {
Write-Status "✗ Build failed: $_" "Error"
exit 1
}
# Verify executable was created
$exePath = "build\bin\$Configuration\yaze.exe"
if (-not (Test-Path $exePath)) {
Write-Status "ERROR: Executable not found at expected path: $exePath" "Error"
exit 1
}
Write-Status "✓ Executable created: $exePath" "Success"
# Test that the executable runs
Write-Status "Testing executable..." "Warning"
try {
$testResult = & $exePath --help 2>&1
$exitCode = $LASTEXITCODE
# Check if it's the test main or app main
if ($testResult -match "Google Test|gtest") {
Write-Status "ERROR: Executable is running test main instead of app main!" "Error"
Write-Status "Output: $testResult" "Error"
exit 1
}
Write-Status "✓ Executable runs correctly (exit code: $exitCode)" "Success"
} catch {
Write-Status "WARNING: Could not test executable: $_" "Warning"
}
# Display file info
$exeInfo = Get-Item $exePath
$fileSizeMB = [math]::Round($exeInfo.Length / 1MB, 2)
Write-Status "Executable size: $fileSizeMB MB" "Info"
Write-Status "========================================" "Info"
Write-Status "✓ YAZE Windows build completed successfully!" "Success"
Write-Status "========================================" "Info"
Write-Status ""
Write-Status "Build Configuration: $Configuration" "White"
Write-Status "Build Platform: $Platform" "White"
Write-Status "Executable: $exePath" "White"
Write-Status ""
Write-Status "To run YAZE:" "Warning"
Write-Status " $exePath" "White"
Write-Status ""
Write-Status "To build other configurations:" "Warning"
Write-Status " .\scripts\build-windows.ps1 -Configuration Debug -Platform x64" "White"
Write-Status " .\scripts\build-windows.ps1 -Configuration Release -Platform x86" "White"
Write-Status " .\scripts\build-windows.ps1 -Configuration RelWithDebInfo -Platform ARM64" "White"
Write-Status " .\scripts\build-windows.ps1 -Clean" "White"
Write-Status ""

946
scripts/build_cleaner.py Executable file
View File

@@ -0,0 +1,946 @@
#!/usr/bin/env python3
"""Automate source list maintenance and self-header includes for YAZE."""
from __future__ import annotations
import argparse
from dataclasses import dataclass, field
import re
from pathlib import Path
from typing import Any, Iterable, List, Optional, Sequence, Set
try:
import pathspec
HAS_PATHSPEC = True
except ImportError:
HAS_PATHSPEC = False
print("Warning: 'pathspec' module not found. Install with: pip3 install pathspec")
print(" .gitignore support will be disabled.")
PROJECT_ROOT = Path(__file__).resolve().parent.parent
SOURCE_ROOT = PROJECT_ROOT / "src"
SUPPORTED_EXTENSIONS = (".cc", ".c", ".cpp", ".cxx", ".mm")
HEADER_EXTENSIONS = (".h", ".hh", ".hpp", ".hxx")
BUILD_CLEANER_IGNORE_TOKEN = "build_cleaner:ignore"
# Common SNES/ROM header patterns to include
COMMON_HEADERS = {
'std::': ['<memory>', '<string>', '<vector>', '<map>', '<set>', '<algorithm>', '<functional>'],
'absl::': ['<absl/status/status.h>', '<absl/status/statusor.h>', '<absl/strings/str_format.h>'],
'ImGui::': ['<imgui.h>'],
'SDL_': ['<SDL.h>'],
}
@dataclass(frozen=True)
class DirectorySpec:
path: Path
recursive: bool = True
extensions: Sequence[str] = SUPPORTED_EXTENSIONS
def iter_files(self) -> Iterable[Path]:
if not self.path.exists():
return []
if self.recursive:
iterator = self.path.rglob("*")
else:
iterator = self.path.glob("*")
for candidate in iterator:
if candidate.is_file() and candidate.suffix in self.extensions:
yield candidate
@dataclass
class CMakeSourceBlock:
variable: str
cmake_path: Path
directories: Sequence[DirectorySpec]
exclude: Set[Path] = field(default_factory=set)
def load_gitignore():
"""Load .gitignore patterns into a pathspec matcher."""
if not HAS_PATHSPEC:
return None
gitignore_path = PROJECT_ROOT / ".gitignore"
if not gitignore_path.exists():
return None
try:
with gitignore_path.open('r', encoding='utf-8') as f:
patterns = [line.strip() for line in f if line.strip() and not line.startswith('#')]
return pathspec.PathSpec.from_lines('gitwildmatch', patterns)
except Exception as e:
print(f"Warning: Could not load .gitignore: {e}")
return None
def is_ignored(path: Path, gitignore_spec) -> bool:
"""Check if a path should be ignored based on .gitignore patterns."""
if gitignore_spec is None or not HAS_PATHSPEC:
return False
try:
rel_path = path.relative_to(PROJECT_ROOT)
return gitignore_spec.match_file(str(rel_path))
except ValueError:
return False
def discover_cmake_libraries() -> List[CMakeSourceBlock]:
"""
Auto-discover CMake library files that explicitly opt-in to auto-maintenance.
Looks for marker comments like:
- "# build_cleaner:auto-maintain"
- "# auto-maintained by build_cleaner.py"
- "# AUTO-MAINTAINED"
Only source lists with these markers will be updated.
Supports decomposed libraries where one cmake file defines multiple PREFIX_SUBDIR_SRC
variables (e.g., GFX_TYPES_SRC, GFX_BACKEND_SRC). Automatically scans subdirectories.
"""
# First pass: collect all variables per cmake file
file_variables: dict[Path, list[str]] = {}
for cmake_file in SOURCE_ROOT.rglob("*.cmake"):
if 'lib/' in str(cmake_file) or 'third_party/' in str(cmake_file):
continue
try:
content = cmake_file.read_text(encoding='utf-8')
lines = content.splitlines()
for i, line in enumerate(lines):
# Check if previous lines indicate auto-maintenance
auto_maintained = False
for j in range(max(0, i-5), i):
line_lower = lines[j].lower()
if ('build_cleaner' in line_lower and 'auto-maintain' in line_lower) or \
'auto_maintain' in line_lower:
auto_maintained = True
break
if not auto_maintained:
continue
# Extract variable name (allow for line breaks or closing paren)
match = re.search(r'set\s*\(\s*(\w+(?:_SRC|_SOURCES|_SOURCE))(?:\s|$|\))', line)
if match:
var_name = match.group(1)
if cmake_file not in file_variables:
file_variables[cmake_file] = []
if var_name not in file_variables[cmake_file]:
file_variables[cmake_file].append(var_name)
except Exception as e:
print(f"Warning: Could not process {cmake_file}: {e}")
# Second pass: create blocks with proper subdirectory detection
blocks = []
for cmake_file, variables in file_variables.items():
cmake_dir = cmake_file.parent
is_recursive = cmake_dir != SOURCE_ROOT / "app/core"
# Analyze variable naming patterns to detect decomposed libraries
# Group variables by prefix (e.g., GFX_*, GUI_*, EDITOR_*)
prefix_groups: dict[str, list[str]] = {}
for var_name in variables:
match = re.match(r'([A-Z]+)_([A-Z_]+)_(?:SRC|SOURCES|SOURCE)$', var_name)
if match:
prefix = match.group(1)
if prefix not in prefix_groups:
prefix_groups[prefix] = []
prefix_groups[prefix].append(var_name)
# If a prefix has multiple variables, treat it as a decomposed library
decomposed_prefixes = {p for p, vars in prefix_groups.items() if len(vars) >= 2}
# Check if this looks like a decomposed library (multiple *_SRC vars)
# even if some don't follow the PREFIX_SUBDIR_SRC pattern
is_likely_decomposed = len(variables) >= 2 and any(p in decomposed_prefixes for p in prefix_groups)
for var_name in variables:
# Try to extract subdirectory from variable name
subdir_match = re.match(r'([A-Z]+)_([A-Z_]+)_(?:SRC|SOURCES|SOURCE)$', var_name)
if subdir_match:
prefix = subdir_match.group(1)
subdir_part = subdir_match.group(2)
# If this prefix indicates a decomposed library, scan subdirectory
if prefix in decomposed_prefixes:
subdir = subdir_part.lower()
target_dir = cmake_dir / subdir
if target_dir.exists() and target_dir.is_dir():
blocks.append(CMakeSourceBlock(
variable=var_name,
cmake_path=cmake_file,
directories=(DirectorySpec(target_dir, recursive=True),),
))
continue
# Handle special cases: CANVAS_SRC, etc. (no prefix, just subdirectory name)
# Pattern: SUBDIR_SRC where SUBDIR is a lowercase directory name
simple_match = re.match(r'([A-Z]+)_(?:SRC|SOURCES|SOURCE)$', var_name)
if simple_match and is_likely_decomposed:
subdir_part = simple_match.group(1)
subdir = subdir_part.lower()
target_dir = cmake_dir / subdir
if target_dir.exists() and target_dir.is_dir():
blocks.append(CMakeSourceBlock(
variable=var_name,
cmake_path=cmake_file,
directories=(DirectorySpec(target_dir, recursive=True),),
))
continue
# Fallback: scan entire cmake directory
blocks.append(CMakeSourceBlock(
variable=var_name,
cmake_path=cmake_file,
directories=(DirectorySpec(cmake_dir, recursive=is_recursive),),
))
return blocks
# Static configuration for all library source lists
# The script now auto-maintains all libraries while preserving conditional sections
STATIC_CONFIG: Sequence[CMakeSourceBlock] = (
CMakeSourceBlock(
variable="YAZE_APP_EMU_SRC",
cmake_path=SOURCE_ROOT / "CMakeLists.txt",
directories=(DirectorySpec(SOURCE_ROOT / "app/emu"),),
),
CMakeSourceBlock(
variable="YAZE_APP_CORE_SRC",
cmake_path=SOURCE_ROOT / "app/core/core_library.cmake",
directories=(DirectorySpec(SOURCE_ROOT / "app/core", recursive=False),),
),
CMakeSourceBlock(
variable="YAZE_APP_EDITOR_SRC",
cmake_path=SOURCE_ROOT / "app/editor/editor_library.cmake",
directories=(DirectorySpec(SOURCE_ROOT / "app/editor"),),
),
CMakeSourceBlock(
variable="YAZE_APP_ZELDA3_SRC",
cmake_path=SOURCE_ROOT / "zelda3/zelda3_library.cmake",
directories=(DirectorySpec(SOURCE_ROOT / "zelda3"),),
),
CMakeSourceBlock(
variable="YAZE_NET_SRC",
cmake_path=SOURCE_ROOT / "app/net/net_library.cmake",
directories=(DirectorySpec(SOURCE_ROOT / "app/net"),),
exclude={Path("app/net/rom_service_impl.cc")},
),
CMakeSourceBlock(
variable="YAZE_UTIL_SRC",
cmake_path=SOURCE_ROOT / "util/util.cmake",
directories=(DirectorySpec(SOURCE_ROOT / "util"),),
),
# Note: These are commented out in favor of auto-discovery via markers
# CMakeSourceBlock(
# variable="GFX_TYPES_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/types"),),
# ),
# CMakeSourceBlock(
# variable="GFX_BACKEND_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/backend"),),
# ),
# CMakeSourceBlock(
# variable="GFX_RESOURCE_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/resource"),),
# ),
# CMakeSourceBlock(
# variable="GFX_CORE_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/core"),),
# ),
# CMakeSourceBlock(
# variable="GFX_UTIL_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/util"),),
# ),
# CMakeSourceBlock(
# variable="GFX_RENDER_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/render"),),
# ),
# CMakeSourceBlock(
# variable="GFX_DEBUG_SRC",
# cmake_path=SOURCE_ROOT / "app/gfx/gfx_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gfx/debug"),),
# ),
# Note: GUI library variables commented out - now auto-discovered via markers
# CMakeSourceBlock(
# variable="GUI_CORE_SRC",
# cmake_path=SOURCE_ROOT / "app/gui/gui_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gui/core"),),
# ),
# CMakeSourceBlock(
# variable="CANVAS_SRC",
# cmake_path=SOURCE_ROOT / "app/gui/gui_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gui/canvas"),),
# ),
# CMakeSourceBlock(
# variable="GUI_WIDGETS_SRC",
# cmake_path=SOURCE_ROOT / "app/gui/gui_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gui/widgets"),),
# ),
# CMakeSourceBlock(
# variable="GUI_AUTOMATION_SRC",
# cmake_path=SOURCE_ROOT / "app/gui/gui_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gui/automation"),),
# ),
# CMakeSourceBlock(
# variable="GUI_APP_SRC",
# cmake_path=SOURCE_ROOT / "app/gui/gui_library.cmake",
# directories=(DirectorySpec(SOURCE_ROOT / "app/gui/app"),),
# ),
CMakeSourceBlock(
variable="YAZE_AGENT_SOURCES",
cmake_path=SOURCE_ROOT / "cli/agent.cmake",
directories=(
DirectorySpec(SOURCE_ROOT / "cli", recursive=False), # For flags.cc
DirectorySpec(SOURCE_ROOT / "cli/service"),
DirectorySpec(SOURCE_ROOT / "cli/handlers"),
),
exclude={
Path("cli/cli.cc"), # Part of z3ed executable
Path("cli/cli_main.cc"), # Part of z3ed executable
},
),
CMakeSourceBlock(
variable="YAZE_TEST_SOURCES",
cmake_path=SOURCE_ROOT / "app/test/test.cmake",
directories=(DirectorySpec(SOURCE_ROOT / "app/test"),),
),
)
def relative_to_source(path: Path) -> Path:
return path.relative_to(SOURCE_ROOT)
def parse_block(lines: List[str], start_idx: int) -> int:
"""Return index of the closing ')' line for a set/list block."""
for idx in range(start_idx + 1, len(lines)):
if lines[idx].strip().startswith(")"):
return idx
raise ValueError(f"Unterminated set/list block starting at line {start_idx}")
def parse_entry(line: str) -> Optional[str]:
stripped = line.strip()
if not stripped or stripped.startswith("#"):
return None
# Remove trailing inline comment
stripped = stripped.split("#", 1)[0].strip()
if not stripped:
return None
if stripped.startswith("$"):
return None
return stripped
def extract_conditional_files(cmake_path: Path, variable: str) -> Set[str]:
"""Extract files that are added to the variable via conditional blocks (if/endif)."""
conditional_files: Set[str] = set()
try:
lines = cmake_path.read_text(encoding='utf-8').splitlines()
except Exception:
return conditional_files
in_conditional = False
conditional_depth = 0
for i, line in enumerate(lines):
stripped = line.strip()
# Track if/endif blocks
if stripped.startswith('if(') or stripped.startswith('if '):
if in_conditional:
conditional_depth += 1
else:
in_conditional = True
conditional_depth = 0
elif stripped.startswith('endif(') or stripped == 'endif()':
if conditional_depth > 0:
conditional_depth -= 1
else:
in_conditional = False
# Check if this line appends to our variable
if in_conditional and f'APPEND {variable}' in line:
# Handle single-line list(APPEND VAR file.cc)
if ')' in line:
# Extract file from same line
match = re.search(rf'APPEND\s+{re.escape(variable)}\s+(.+?)\)', line)
if match:
file_str = match.group(1).strip()
# Can be multiple files separated by space
for f in file_str.split():
f = f.strip()
if f and not f.startswith('$') and '/' in f and f.endswith('.cc'):
conditional_files.add(f)
else:
# Multi-line list(APPEND) - extract files from following lines
j = i + 1
while j < len(lines) and not lines[j].strip().startswith(')'):
entry = parse_entry(lines[j])
if entry:
conditional_files.add(entry)
j += 1
return conditional_files
def gather_expected_sources(block: CMakeSourceBlock, gitignore_spec: Any = None) -> List[str]:
# First, find files that are in conditional blocks
conditional_files = extract_conditional_files(block.cmake_path, block.variable)
entries: Set[str] = set()
for directory in block.directories:
for source_file in directory.iter_files():
if should_ignore_path(source_file):
continue
if is_ignored(source_file, gitignore_spec):
continue
# Exclude paths are relative to SOURCE_ROOT, so check against that.
if relative_to_source(source_file) in block.exclude:
continue
# Generate paths relative to SOURCE_ROOT (src/) for consistency across the project
# This matches the format used in editor_library.cmake, etc.
rel_path = source_file.relative_to(SOURCE_ROOT)
rel_path_str = str(rel_path).replace("\\", "/")
# This check is imperfect if the conditional blocks have not been updated to use
# SOURCE_ROOT relative paths. However, for the current issue, this is sufficient.
if rel_path_str not in conditional_files:
entries.add(rel_path_str)
return sorted(entries)
def should_ignore_path(path: Path) -> bool:
try:
with path.open("r", encoding="utf-8") as handle:
head = handle.read(256)
except (OSError, UnicodeDecodeError):
return False
return BUILD_CLEANER_IGNORE_TOKEN in head
def extract_includes(file_path: Path) -> Set[str]:
"""Extract all #include statements from a source file."""
includes = set()
try:
with file_path.open('r', encoding='utf-8') as f:
for line in f:
# Match #include "..." or #include <...>
match = re.match(r'^\s*#include\s+[<"]([^>"]+)[>"]', line)
if match:
includes.add(match.group(1))
except (OSError, UnicodeDecodeError):
pass
return includes
def extract_symbols(file_path: Path) -> Set[str]:
"""Extract potential symbols/identifiers that might need headers."""
symbols = set()
try:
with file_path.open('r', encoding='utf-8') as f:
content = f.read()
# Find namespace-qualified symbols (e.g., std::, absl::, ImGui::)
namespace_symbols = re.findall(r'\b([a-zA-Z_]\w*::)', content)
symbols.update(namespace_symbols)
# Find common function calls that might need headers
func_calls = re.findall(r'\b([A-Z][a-zA-Z0-9_]*)\s*\(', content)
symbols.update(func_calls)
except (OSError, UnicodeDecodeError):
pass
return symbols
def find_missing_headers(source: Path) -> List[str]:
"""Analyze a source file and suggest missing headers based on symbol usage."""
if should_ignore_path(source):
return []
current_includes = extract_includes(source)
symbols = extract_symbols(source)
missing = []
# Check for common headers based on symbol prefixes
for symbol_prefix, headers in COMMON_HEADERS.items():
if any(symbol_prefix in sym for sym in symbols):
for header in headers:
# Extract just the header name from angle brackets
header_name = header.strip('<>')
if header_name not in ' '.join(current_includes):
missing.append(header)
return missing
def find_conditional_blocks_after(cmake_lines: List[str], end_idx: int, variable: str) -> List[str]:
"""
Find conditional blocks (if/endif) that append to the variable after the main set() block.
Returns lines that should be preserved.
"""
conditional_lines = []
idx = end_idx + 1
while idx < len(cmake_lines):
line = cmake_lines[idx]
stripped = line.strip()
# Stop at next major block or empty lines
if not stripped:
idx += 1
continue
# Check if this is a conditional that appends to our variable
if stripped.startswith('if(') or stripped.startswith('if ('):
# Look ahead to see if this block modifies our variable
block_start = idx
block_depth = 1
modifies_var = False
temp_idx = idx + 1
while temp_idx < len(cmake_lines) and block_depth > 0:
temp_line = cmake_lines[temp_idx].strip()
if temp_line.startswith('if(') or temp_line.startswith('if '):
block_depth += 1
elif temp_line.startswith('endif(') or temp_line == 'endif()':
block_depth -= 1
# Check if this block modifies our variable
if f'APPEND {variable}' in temp_line or f'APPEND\n {variable}' in cmake_lines[temp_idx]:
modifies_var = True
temp_idx += 1
if modifies_var:
# Include the entire conditional block
conditional_lines.extend(cmake_lines[block_start:temp_idx])
idx = temp_idx
continue
else:
# This conditional doesn't touch our variable, stop scanning
break
else:
# Hit something else, stop scanning
break
idx += 1
return conditional_lines
def update_cmake_block(block: CMakeSourceBlock, dry_run: bool, gitignore_spec: Any = None) -> bool:
cmake_lines = (block.cmake_path.read_text(encoding="utf-8")).splitlines()
pattern = re.compile(rf"\s*set\(\s*{re.escape(block.variable)}\b")
start_idx: Optional[int] = None
for idx, line in enumerate(cmake_lines):
if pattern.match(line):
start_idx = idx
break
if start_idx is None:
for idx, line in enumerate(cmake_lines):
stripped = line.strip()
if not stripped.startswith("set("):
continue
remainder = stripped[4:].strip()
if remainder:
if remainder.startswith(block.variable):
start_idx = idx
break
continue
lookahead = idx + 1
while lookahead < len(cmake_lines):
next_line = cmake_lines[lookahead].strip()
if not next_line or next_line.startswith("#"):
lookahead += 1
continue
if next_line == block.variable:
start_idx = idx
break
if start_idx is not None:
break
if start_idx is None:
raise ValueError(f"Could not locate set({block.variable}) in {block.cmake_path}")
end_idx = parse_block(cmake_lines, start_idx)
block_slice = cmake_lines[start_idx + 1 : end_idx]
prelude: List[str] = []
postlude: List[str] = []
existing_entries: List[str] = []
first_entry_idx: Optional[int] = None
for idx, line in enumerate(block_slice):
entry = parse_entry(line)
if entry:
if entry == block.variable and not existing_entries:
prelude.append(line)
continue
existing_entries.append(entry)
if first_entry_idx is None:
first_entry_idx = idx
else:
if first_entry_idx is None:
prelude.append(line)
else:
postlude.append(line)
expected_entries = gather_expected_sources(block, gitignore_spec)
expected_set = set(expected_entries)
if set(existing_entries) == expected_set:
return False
indent = " "
if first_entry_idx is not None:
sample_line = block_slice[first_entry_idx]
indent = sample_line[: len(sample_line) - len(sample_line.lstrip())]
rebuilt_block = prelude + [f"{indent}{entry}" for entry in expected_entries] + postlude
if dry_run:
print(f"[DRY-RUN] Would update {block.cmake_path.relative_to(PROJECT_ROOT)} :: {block.variable}")
return True
cmake_lines[start_idx + 1 : end_idx] = rebuilt_block
block.cmake_path.write_text("\n".join(cmake_lines) + "\n", encoding="utf-8")
print(f"Updated {block.cmake_path.relative_to(PROJECT_ROOT)} :: {block.variable}")
missing = sorted(expected_set - set(existing_entries))
removed = sorted(set(existing_entries) - expected_set)
if missing:
print(f" Added: {', '.join(missing)}")
if removed:
print(f" Removed: {', '.join(removed)}")
return True
def find_self_header(source: Path) -> Optional[Path]:
for ext in HEADER_EXTENSIONS:
candidate = source.with_suffix(ext)
if candidate.exists():
return candidate
return None
def has_include(lines: Sequence[str], header_variants: Iterable[str]) -> bool:
"""Check if any line includes one of the header variants (with any path or quote style)."""
# Extract just the header filenames for flexible matching
header_names = {Path(variant).name for variant in header_variants}
for line in lines:
stripped = line.strip()
if not stripped.startswith('#include'):
continue
# Extract the included filename from #include "..." or #include <...>
match = re.match(r'^\s*#include\s+[<"]([^>"]+)[>"]', stripped)
if match:
included_path = match.group(1)
included_name = Path(included_path).name
# If this include references any of our header variants, consider it present
if included_name in header_names:
return True
return False
def find_insert_index(lines: List[str]) -> int:
include_block_start = None
for idx, line in enumerate(lines):
if line.startswith("#include"):
include_block_start = idx
break
if include_block_start is not None:
return include_block_start
# No includes yet; skip leading comments/blank lines
index = 0
in_block_comment = False
while index < len(lines):
stripped = lines[index].strip()
if not stripped:
index += 1
continue
if stripped.startswith("/*") and not stripped.endswith("*/"):
in_block_comment = True
index += 1
continue
if in_block_comment:
if "*/" in stripped:
in_block_comment = False
index += 1
continue
if stripped.startswith("//"):
index += 1
continue
break
return index
def ensure_self_header_include(source: Path, dry_run: bool) -> bool:
"""
Ensure a source file includes its corresponding header file.
Skips files that:
- Are explicitly ignored
- Have no corresponding header
- Already include their header (in any path format)
- Are test files or main entry points (typically don't include own header)
"""
if should_ignore_path(source):
return False
# Skip test files and main entry points (they typically don't need self-includes)
source_name = source.name.lower()
if any(pattern in source_name for pattern in ['_test.cc', '_main.cc', '_benchmark.cc', 'main.cc']):
return False
header = find_self_header(source)
if header is None:
# No corresponding header found - this is OK, not all sources have headers
return False
try:
lines = source.read_text(encoding="utf-8").splitlines()
except UnicodeDecodeError:
return False
# Generate header path relative to SOURCE_ROOT (project convention)
try:
header_rel_path = header.relative_to(SOURCE_ROOT)
header_path_str = str(header_rel_path).replace("\\", "/")
except ValueError:
# Header is outside SOURCE_ROOT, just use filename
header_path_str = header.name
# Check if the header is already included (with any path format)
header_variants = {
header.name, # Just filename
header_path_str, # SOURCE_ROOT-relative
str(header.relative_to(source.parent)).replace("\\", "/") if source.parent != header.parent else header.name, # Source-relative
}
if has_include(lines, header_variants):
# Header is already included (possibly with different path)
return False
# Double-check: if this source file has very few lines or no code, skip it
# (might be a stub or template file)
code_lines = [l for l in lines if l.strip() and not l.strip().startswith('//') and not l.strip().startswith('/*')]
if len(code_lines) < 3:
return False
# Use SOURCE_ROOT-relative path (project convention)
include_line = f'#include "{header_path_str}"'
insert_idx = find_insert_index(lines)
lines.insert(insert_idx, include_line)
if dry_run:
rel = source.relative_to(PROJECT_ROOT)
print(f"[DRY-RUN] Would insert self-header include into {rel}")
return True
source.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"Inserted self-header include into {source.relative_to(PROJECT_ROOT)}")
return True
def add_missing_headers(source: Path, dry_run: bool, iwyu_mode: bool) -> bool:
"""Add missing headers based on IWYU-style analysis."""
if not iwyu_mode or should_ignore_path(source):
return False
missing_headers = find_missing_headers(source)
if not missing_headers:
return False
try:
lines = source.read_text(encoding="utf-8").splitlines()
except UnicodeDecodeError:
return False
# Find where to insert the headers
insert_idx = find_insert_index(lines)
# Move past any existing includes to add new ones after them
while insert_idx < len(lines) and lines[insert_idx].strip().startswith('#include'):
insert_idx += 1
# Insert missing headers
for header in missing_headers:
lines.insert(insert_idx, f'#include {header}')
insert_idx += 1
if dry_run:
rel = source.relative_to(PROJECT_ROOT)
print(f"[DRY-RUN] Would add missing headers to {rel}: {', '.join(missing_headers)}")
return True
source.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"Added missing headers to {source.relative_to(PROJECT_ROOT)}: {', '.join(missing_headers)}")
return True
def collect_source_files(config: List[CMakeSourceBlock], gitignore_spec: Any = None) -> Set[Path]:
"""Collect all source files from the given configuration, respecting .gitignore patterns."""
managed_dirs: Set[Path] = set()
for block in config:
for directory in block.directories:
managed_dirs.add(directory.path)
result: Set[Path] = set()
for directory in managed_dirs:
if not directory.exists():
continue
for file_path in directory.rglob("*"):
if file_path.is_file() and file_path.suffix in SUPPORTED_EXTENSIONS:
if not is_ignored(file_path, gitignore_spec):
result.add(file_path)
return result
def get_config(auto_discover: bool = False) -> List[CMakeSourceBlock]:
"""Get the full configuration, optionally including auto-discovered libraries."""
# Always start with static config (all known libraries)
config = list(STATIC_CONFIG)
# Optionally add auto-discovered libraries, avoiding duplicates
if auto_discover:
discovered = discover_cmake_libraries()
static_vars = {block.variable for block in STATIC_CONFIG}
for block in discovered:
if block.variable not in static_vars:
config.append(block)
print(f" Auto-discovered: {block.variable} in {block.cmake_path.name}")
return config
def run(dry_run: bool, cmake_only: bool, includes_only: bool, iwyu_mode: bool, auto_discover: bool) -> int:
if cmake_only and includes_only:
raise ValueError("Cannot use --cmake-only and --includes-only together")
# Load .gitignore patterns
gitignore_spec = load_gitignore()
if gitignore_spec:
print("✓ Loaded .gitignore patterns")
changed = False
# Get configuration (all libraries by default, with optional auto-discovery)
config = get_config(auto_discover)
if auto_discover:
print(f"✓ Using {len(config)} library configurations (with auto-discovery)")
else:
print(f"✓ Using {len(config)} library configurations")
if not includes_only:
print("\n📋 Updating CMake source lists...")
for block in config:
changed |= update_cmake_block(block, dry_run, gitignore_spec)
if not cmake_only:
print("\n📝 Checking self-header includes...")
source_files = collect_source_files(config, gitignore_spec)
print(f" Scanning {len(source_files)} source files")
for source in source_files:
changed |= ensure_self_header_include(source, dry_run)
if iwyu_mode:
print("\n🔍 Running IWYU-style header analysis...")
for source in source_files:
changed |= add_missing_headers(source, dry_run, iwyu_mode)
if dry_run and not changed:
print("\n✅ No changes required (dry-run)")
elif not dry_run and not changed:
print("\n✅ No changes required")
elif dry_run:
print("\n✅ Dry-run complete - use without --dry-run to apply changes")
else:
print("\n✅ All changes applied successfully")
return 0
def main() -> int:
parser = argparse.ArgumentParser(
description="Maintain CMake source lists and ensure proper header includes (IWYU-style).",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Dry-run to see what would change:
%(prog)s --dry-run
# Auto-discover libraries and update CMake files:
%(prog)s --auto-discover
# Run IWYU-style header analysis:
%(prog)s --iwyu
# Update only CMake source lists:
%(prog)s --cmake-only
# Update only header includes:
%(prog)s --includes-only
"""
)
parser.add_argument("--dry-run", action="store_true",
help="Report prospective changes without editing files")
parser.add_argument("--cmake-only", action="store_true",
help="Only update CMake source lists")
parser.add_argument("--includes-only", action="store_true",
help="Only ensure self-header includes")
parser.add_argument("--iwyu", action="store_true",
help="Run IWYU-style analysis to add missing headers")
parser.add_argument("--auto-discover", action="store_true",
help="Auto-discover CMake library files (*.cmake, *_library.cmake)")
args = parser.parse_args()
try:
return run(args.dry_run, args.cmake_only, args.includes_only, args.iwyu, args.auto_discover)
except Exception as exc: # pylint: disable=broad-except
import traceback
print(f"❌ build_cleaner failed: {exc}")
if args.dry_run: # Show traceback in dry-run mode for debugging
traceback.print_exc()
return 1
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -1,138 +0,0 @@
#!/bin/bash
# Script to create a proper release tag for YAZE
# Usage: ./scripts/create_release.sh [version]
# Example: ./scripts/create_release.sh 0.3.0
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() {
echo -e "${BLUE} $1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
print_error "Not in a git repository!"
exit 1
fi
# Check if we're on master branch
current_branch=$(git branch --show-current)
if [ "$current_branch" != "master" ]; then
print_warning "You're on branch '$current_branch', not 'master'"
read -p "Continue anyway? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Switching to master branch..."
git checkout master
fi
fi
# Get version argument or prompt for it
if [ $# -eq 0 ]; then
echo
print_info "Enter the version number (e.g., 0.3.0, 1.0.0-beta, 2.1.0-rc1):"
read -p "Version: " version
else
version=$1
fi
# Validate version format
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-.*)?$ ]]; then
print_error "Invalid version format: '$version'"
print_info "Version must follow semantic versioning (e.g., 1.2.3 or 1.2.3-beta)"
exit 1
fi
# Create tag with v prefix
tag="v$version"
# Check if tag already exists
if git tag -l | grep -q "^$tag$"; then
print_error "Tag '$tag' already exists!"
exit 1
fi
# Show current status
echo
print_info "Current repository status:"
git status --short
# Check for uncommitted changes
if ! git diff-index --quiet HEAD --; then
print_warning "You have uncommitted changes!"
read -p "Continue with creating release? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Please commit your changes first, then run this script again."
exit 1
fi
fi
# Show what will happen
echo
print_info "Creating release for YAZE:"
echo " 📦 Version: $version"
echo " 🏷️ Tag: $tag"
echo " 🌿 Branch: $current_branch"
echo " 📝 Changelog: docs/C1-changelog.md"
echo
# Confirm
read -p "Create this release? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Release creation cancelled."
exit 0
fi
# Create and push tag
print_info "Creating tag '$tag'..."
if git tag -a "$tag" -m "Release $tag"; then
print_success "Tag '$tag' created successfully!"
else
print_error "Failed to create tag!"
exit 1
fi
print_info "Pushing tag to origin..."
if git push origin "$tag"; then
print_success "Tag pushed successfully!"
else
print_error "Failed to push tag!"
print_info "You can manually push with: git push origin $tag"
exit 1
fi
echo
print_success "🎉 Release $tag created successfully!"
print_info "The GitHub Actions release workflow will now:"
echo " • Build packages for Windows, macOS, and Linux"
echo " • Extract changelog from docs/C1-changelog.md"
echo " • Create GitHub release with all assets"
echo " • Include themes, fonts, layouts, and documentation"
echo
print_info "Check the release progress at:"
echo " https://github.com/scawful/yaze/actions"
echo
print_info "The release will be available at:"
echo " https://github.com/scawful/yaze/releases/tag/$tag"

View File

@@ -47,7 +47,7 @@ def main():
sys.exit(1)
version_num = sys.argv[1]
changelog_file = "docs/C1-changelog.md"
changelog_file = "docs/H1-changelog.md"
# Check if changelog file exists
if not os.path.exists(changelog_file):
@@ -65,24 +65,26 @@ def main():
## Download Instructions
### Windows
- Download `yaze-windows-x64.zip` for 64-bit Windows
- Download `yaze-windows-x86.zip` for 32-bit Windows
- Download `yaze-windows-x64.zip`
- Extract and run `yaze.exe`
- Requires Windows 10 or later (64-bit)
### macOS
- Download `yaze-macos.dmg`
- Download `yaze-macos-universal.dmg` (Universal Binary - supports both Intel and Apple Silicon)
- Mount the DMG and drag Yaze to Applications
- You may need to allow the app in System Preferences > Security & Privacy
- On first launch, right-click the app and select "Open" to bypass Gatekeeper
- Requires macOS 11.0 (Big Sur) or later
### Linux
- Download `yaze-linux-x64.tar.gz`
- Extract: `tar -xzf yaze-linux-x64.tar.gz`
- Run: `./yaze`
- Requires Ubuntu 22.04 or equivalent with X11/Wayland
## System Requirements
- **Windows**: Windows 10 or later (64-bit recommended)
- **macOS**: macOS 10.15 (Catalina) or later
- **Linux**: Ubuntu 20.04 or equivalent, with X11 or Wayland
- **Windows**: Windows 10 or later (64-bit only)
- **macOS**: macOS 11.0 (Big Sur) or later (Universal Binary)
- **Linux**: Ubuntu 22.04 or equivalent with X11 or Wayland
## Support
For issues and questions, please visit our [GitHub Issues](https://github.com/scawful/yaze/issues) page.

View File

@@ -1,328 +0,0 @@
#!/usr/bin/env python3
"""
Simple Visual Studio project generator for YAZE
This script creates Visual Studio project files without complex CMake dependencies
"""
import os
import sys
from pathlib import Path
def generate_vcxproj():
"""Generate the YAZE.vcxproj file with all source files"""
# Source file lists (from CMake files)
app_core_src = [
"app/core/controller.cc",
"app/emu/emulator.cc",
"app/core/project.cc",
"app/core/window.cc",
"app/core/asar_wrapper.cc",
"app/core/platform/font_loader.cc",
"app/core/platform/clipboard.cc",
"app/core/platform/file_dialog.cc"
]
app_emu_src = [
"app/emu/audio/apu.cc",
"app/emu/audio/spc700.cc",
"app/emu/audio/dsp.cc",
"app/emu/audio/internal/addressing.cc",
"app/emu/audio/internal/instructions.cc",
"app/emu/cpu/internal/addressing.cc",
"app/emu/cpu/internal/instructions.cc",
"app/emu/cpu/cpu.cc",
"app/emu/video/ppu.cc",
"app/emu/memory/dma.cc",
"app/emu/memory/memory.cc",
"app/emu/snes.cc"
]
app_editor_src = [
"app/editor/editor_manager.cc",
"app/editor/dungeon/dungeon_editor.cc",
"app/editor/dungeon/dungeon_room_selector.cc",
"app/editor/dungeon/dungeon_canvas_viewer.cc",
"app/editor/dungeon/dungeon_object_selector.cc",
"app/editor/dungeon/dungeon_toolset.cc",
"app/editor/dungeon/dungeon_object_interaction.cc",
"app/editor/dungeon/dungeon_renderer.cc",
"app/editor/dungeon/dungeon_room_loader.cc",
"app/editor/dungeon/dungeon_usage_tracker.cc",
"app/editor/overworld/overworld_editor.cc",
"app/editor/overworld/overworld_editor_manager.cc",
"app/editor/sprite/sprite_editor.cc",
"app/editor/music/music_editor.cc",
"app/editor/message/message_editor.cc",
"app/editor/message/message_data.cc",
"app/editor/message/message_preview.cc",
"app/editor/code/assembly_editor.cc",
"app/editor/graphics/screen_editor.cc",
"app/editor/graphics/graphics_editor.cc",
"app/editor/graphics/palette_editor.cc",
"app/editor/overworld/tile16_editor.cc",
"app/editor/overworld/map_properties.cc",
"app/editor/graphics/gfx_group_editor.cc",
"app/editor/overworld/entity.cc",
"app/editor/system/settings_editor.cc",
"app/editor/system/command_manager.cc",
"app/editor/system/extension_manager.cc",
"app/editor/system/shortcut_manager.cc",
"app/editor/system/popup_manager.cc",
"app/test/test_manager.cc"
]
app_gfx_src = [
"app/gfx/arena.cc",
"app/gfx/background_buffer.cc",
"app/gfx/bitmap.cc",
"app/gfx/compression.cc",
"app/gfx/scad_format.cc",
"app/gfx/snes_palette.cc",
"app/gfx/snes_tile.cc",
"app/gfx/snes_color.cc",
"app/gfx/tilemap.cc"
]
app_zelda3_src = [
"app/zelda3/hyrule_magic.cc",
"app/zelda3/overworld/overworld_map.cc",
"app/zelda3/overworld/overworld.cc",
"app/zelda3/screen/inventory.cc",
"app/zelda3/screen/title_screen.cc",
"app/zelda3/screen/dungeon_map.cc",
"app/zelda3/sprite/sprite.cc",
"app/zelda3/sprite/sprite_builder.cc",
"app/zelda3/music/tracker.cc",
"app/zelda3/dungeon/room.cc",
"app/zelda3/dungeon/room_object.cc",
"app/zelda3/dungeon/object_parser.cc",
"app/zelda3/dungeon/object_renderer.cc",
"app/zelda3/dungeon/room_layout.cc",
"app/zelda3/dungeon/dungeon_editor_system.cc",
"app/zelda3/dungeon/dungeon_object_editor.cc"
]
gui_src = [
"app/gui/modules/asset_browser.cc",
"app/gui/modules/text_editor.cc",
"app/gui/canvas.cc",
"app/gui/canvas_utils.cc",
"app/gui/enhanced_palette_editor.cc",
"app/gui/input.cc",
"app/gui/style.cc",
"app/gui/color.cc",
"app/gui/zeml.cc",
"app/gui/theme_manager.cc",
"app/gui/background_renderer.cc"
]
util_src = [
"util/bps.cc",
"util/flag.cc",
"util/hex.cc"
]
# Combine all source files
all_source_files = (
["yaze.cc", "app/main.cc", "app/rom.cc"] +
app_core_src + app_emu_src + app_editor_src +
app_gfx_src + app_zelda3_src + gui_src + util_src
)
# Header files
header_files = [
"incl/yaze.h",
"incl/zelda.h",
"src/yaze_config.h.in"
]
# Generate the .vcxproj file content
vcxproj_content = '''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B2C3D4E5-F6G7-8901-BCDE-F23456789012}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>YAZE</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>YAZE</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)src;$(ProjectDir)incl;$(ProjectDir)src\\lib;$(ProjectDir)vcpkg\\installed\\x64-windows\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp23</LanguageStandard>
<BigObj>true</BigObj>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(ProjectDir)vcpkg\\installed\\x64-windows\\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;libpng16.lib;zlib.lib;absl_base.lib;absl_strings.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)src;$(ProjectDir)incl;$(ProjectDir)src\\lib;$(ProjectDir)vcpkg\\installed\\x64-windows\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp23</LanguageStandard>
<BigObj>true</BigObj>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(ProjectDir)vcpkg\\installed\\x64-windows\\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;libpng16.lib;zlib.lib;absl_base.lib;absl_strings.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
'''
for header in header_files:
vcxproj_content += f' <ClInclude Include="{header}" />\n'
vcxproj_content += ''' </ItemGroup>
<ItemGroup>
'''
for source in all_source_files:
vcxproj_content += f' <ClCompile Include="src\\{source}" />\n'
vcxproj_content += ''' </ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="vcpkg.json" />
<None Include="README.md" />
<None Include="LICENSE" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>'''
return vcxproj_content
def generate_solution():
"""Generate the YAZE.sln file"""
return '''Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YAZE", "YAZE.vcxproj", "{B2C3D4E5-F6G7-8901-BCDE-F23456789012}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|x64.ActiveCfg = Debug|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|x64.Build.0 = Debug|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|x64.ActiveCfg = Release|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
EndGlobalSection
EndGlobal'''
def main():
"""Main function to generate Visual Studio project files"""
print("Generating simple Visual Studio project files for YAZE...")
# Get the project root directory
script_dir = Path(__file__).parent
project_root = script_dir.parent
# Generate .vcxproj file
vcxproj_content = generate_vcxproj()
vcxproj_path = project_root / "YAZE.vcxproj"
with open(vcxproj_path, 'w', encoding='utf-8') as f:
f.write(vcxproj_content)
print(f"Generated: {vcxproj_path}")
# Generate .sln file
solution_content = generate_solution()
solution_path = project_root / "YAZE.sln"
with open(solution_path, 'w', encoding='utf-8') as f:
f.write(solution_content)
print(f"Generated: {solution_path}")
print("Visual Studio project files generated successfully!")
print("")
print("IMPORTANT: Before building in Visual Studio:")
print("1. Make sure vcpkg is set up: .\\scripts\\setup-vcpkg-windows.ps1")
print("2. Install dependencies: .\\vcpkg\\vcpkg.exe install --triplet x64-windows")
print("3. Open YAZE.sln in Visual Studio 2022")
print("4. Build the solution (Ctrl+Shift+B)")
if __name__ == "__main__":
main()

View File

@@ -1,200 +0,0 @@
@echo off
REM Configure Visual Studio project files for YAZE
REM This script configures CMake build system to work with existing Visual Studio project files
setlocal enabledelayedexpansion
REM Default values
set CONFIGURATION=Debug
set ARCHITECTURE=x64
set CLEAN=false
REM Parse command line arguments
:parse_args
if "%~1"=="" goto :args_done
if "%~1"=="--clean" set CLEAN=true
if "%~1"=="--release" set CONFIGURATION=Release
if "%~1"=="--x86" set ARCHITECTURE=Win32
if "%~1"=="--x64" set ARCHITECTURE=x64
if "%~1"=="--arm64" set ARCHITECTURE=ARM64
shift
goto :parse_args
:args_done
REM Validate architecture
if not "%ARCHITECTURE%"=="x64" if not "%ARCHITECTURE%"=="Win32" if not "%ARCHITECTURE%"=="ARM64" (
echo Invalid architecture: %ARCHITECTURE%
echo Valid architectures: x64, Win32, ARM64
exit /b 1
)
echo Generating Visual Studio project files for YAZE...
REM Check if we're on Windows
if not "%OS%"=="Windows_NT" (
echo This script is designed for Windows. Use CMake presets on other platforms.
echo Available presets:
echo - windows-debug
echo - windows-release
echo - windows-dev
exit /b 1
)
REM Check if CMake is available
where cmake >nul 2>&1
if errorlevel 1 (
REM Try common CMake installation paths
if exist "C:\Program Files\CMake\bin\cmake.exe" (
echo Found CMake at: C:\Program Files\CMake\bin\cmake.exe
set "PATH=%PATH%;C:\Program Files\CMake\bin"
goto :cmake_found
)
if exist "C:\Program Files (x86)\CMake\bin\cmake.exe" (
echo Found CMake at: C:\Program Files (x86)\CMake\bin\cmake.exe
set "PATH=%PATH%;C:\Program Files (x86)\CMake\bin"
goto :cmake_found
)
if exist "C:\cmake\bin\cmake.exe" (
echo Found CMake at: C:\cmake\bin\cmake.exe
set "PATH=%PATH%;C:\cmake\bin"
goto :cmake_found
)
REM If we get here, CMake is not found
echo CMake not found in PATH. Attempting to install...
REM Try to install CMake via Chocolatey
where choco >nul 2>&1
if not errorlevel 1 (
echo Installing CMake via Chocolatey...
choco install -y cmake
if errorlevel 1 (
echo Failed to install CMake via Chocolatey
) else (
echo CMake installed successfully
REM Refresh PATH
call refreshenv
)
) else (
echo Chocolatey not found. Please install CMake manually:
echo 1. Download from: https://cmake.org/download/
echo 2. Or install Chocolatey first: https://chocolatey.org/install
echo 3. Then run: choco install cmake
exit /b 1
)
REM Check again after installation
where cmake >nul 2>&1
if errorlevel 1 (
echo CMake still not found after installation. Please restart your terminal or add CMake to PATH manually.
exit /b 1
)
)
:cmake_found
echo CMake found and ready to use
REM Set up paths
set SOURCE_DIR=%~dp0..
set BUILD_DIR=%SOURCE_DIR%\build-vs
echo Source directory: %SOURCE_DIR%
echo Build directory: %BUILD_DIR%
REM Clean build directory if requested
if "%CLEAN%"=="true" (
if exist "%BUILD_DIR%" (
echo Cleaning build directory...
rmdir /s /q "%BUILD_DIR%"
)
)
REM Create build directory
if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%"
REM Check if vcpkg is available
set VCPKG_PATH=%SOURCE_DIR%\vcpkg\scripts\buildsystems\vcpkg.cmake
if exist "%VCPKG_PATH%" (
echo Using vcpkg toolchain: %VCPKG_PATH%
set USE_VCPKG=true
) else (
echo vcpkg not found, using system libraries
set USE_VCPKG=false
)
REM Build CMake command
set CMAKE_ARGS=-B "%BUILD_DIR%" -G "Visual Studio 17 2022" -A %ARCHITECTURE% -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_POLICY_VERSION_MAXIMUM=3.28 -DCMAKE_WARN_DEPRECATED=OFF -DABSL_PROPAGATE_CXX_STD=ON -DTHREADS_PREFER_PTHREAD_FLAG=OFF -DYAZE_BUILD_TESTS=ON -DYAZE_BUILD_APP=ON -DYAZE_BUILD_LIB=ON -DYAZE_BUILD_EMU=ON -DYAZE_BUILD_Z3ED=ON -DYAZE_ENABLE_ROM_TESTS=OFF -DYAZE_ENABLE_EXPERIMENTAL_TESTS=ON -DYAZE_ENABLE_UI_TESTS=ON -DYAZE_INSTALL_LIB=OFF
if "%USE_VCPKG%"=="true" (
set CMAKE_ARGS=%CMAKE_ARGS% -DCMAKE_TOOLCHAIN_FILE="%VCPKG_PATH%" -DVCPKG_TARGET_TRIPLET=%ARCHITECTURE%-windows -DVCPKG_MANIFEST_MODE=ON
)
REM Run CMake configuration
echo Configuring CMake...
echo Command: cmake %CMAKE_ARGS% "%SOURCE_DIR%"
cmake %CMAKE_ARGS% "%SOURCE_DIR%"
if errorlevel 1 (
echo CMake configuration failed!
exit /b 1
)
REM Check if the existing solution file is present and valid
set EXISTING_SOLUTION_FILE=%SOURCE_DIR%\YAZE.sln
if exist "%EXISTING_SOLUTION_FILE%" (
echo ✅ Using existing Visual Studio solution: %EXISTING_SOLUTION_FILE%
REM Verify the solution file references the project file
findstr /C:"YAZE.vcxproj" "%EXISTING_SOLUTION_FILE%" >nul
if not errorlevel 1 (
echo ✅ Solution file references YAZE.vcxproj correctly
REM Check if project configurations are set up
findstr /C:"ProjectConfigurationPlatforms" "%EXISTING_SOLUTION_FILE%" >nul
if not errorlevel 1 (
echo ✅ Project configurations are properly set up
) else (
echo ⚠️ Warning: Project configurations may not be set up
)
) else (
echo ❌ Solution file does not reference YAZE.vcxproj
echo Please ensure the solution file includes the YAZE project
)
REM Try to open solution in Visual Studio
where devenv >nul 2>&1
if not errorlevel 1 (
echo Opening solution in Visual Studio...
start "" devenv "%EXISTING_SOLUTION_FILE%"
) else (
echo Visual Studio solution ready: %EXISTING_SOLUTION_FILE%
)
) else (
echo ❌ Existing solution file not found: %EXISTING_SOLUTION_FILE%
echo Please ensure YAZE.sln exists in the project root
exit /b 1
)
echo.
echo 🎉 Visual Studio project configuration complete!
echo.
echo Next steps:
echo 1. Open YAZE.sln in Visual Studio
echo 2. Select configuration: %CONFIGURATION%
echo 3. Select platform: %ARCHITECTURE%
echo 4. Build the solution (Ctrl+Shift+B)
echo.
echo Available configurations:
echo - Debug (with debugging symbols)
echo - Release (optimized)
echo - RelWithDebInfo (optimized with debug info)
echo - MinSizeRel (minimum size)
echo.
echo Available architectures:
echo - x64 (64-bit Intel/AMD)
echo - x86 (32-bit Intel/AMD)
echo - ARM64 (64-bit ARM)
pause

View File

@@ -1,251 +0,0 @@
# Configure Visual Studio project files for YAZE
# This script configures CMake build system to work with existing Visual Studio project files
param(
[string]$Configuration = "Debug",
[string]$Architecture = "x64",
[switch]$Clean = $false,
[switch]$UseVcpkg = $false,
[switch]$Help = $false
)
# Show help if requested
if ($Help) {
Write-Host "Usage: .\generate-vs-projects.ps1 [options]"
Write-Host ""
Write-Host "Options:"
Write-Host " -Configuration <config> Build configuration (Debug, Release, RelWithDebInfo, MinSizeRel)"
Write-Host " -Architecture <arch> Target architecture (x64, x86, ARM64)"
Write-Host " -Clean Clean build directory before configuring"
Write-Host " -UseVcpkg Use vcpkg for dependency management"
Write-Host " -Help Show this help message"
Write-Host ""
Write-Host "Examples:"
Write-Host " .\generate-vs-projects.ps1 # Default: Debug x64"
Write-Host " .\generate-vs-projects.ps1 -Configuration Release -Architecture x86"
Write-Host " .\generate-vs-projects.ps1 -Clean -UseVcpkg"
Write-Host ""
Write-Host "Note: This script configures CMake to work with existing YAZE.sln and YAZE.vcxproj files"
exit 0
}
# Validate architecture parameter
$ValidArchitectures = @("x64", "x86", "ARM64")
if ($Architecture -notin $ValidArchitectures) {
Write-Host "Invalid architecture: $Architecture" -ForegroundColor Red
Write-Host "Valid architectures: $($ValidArchitectures -join ', ')" -ForegroundColor Yellow
exit 1
}
Write-Host "Generating Visual Studio project files for YAZE..." -ForegroundColor Green
# Check if we're on Windows
if ($env:OS -ne "Windows_NT") {
Write-Host "This script is designed for Windows. Use CMake presets on other platforms." -ForegroundColor Yellow
Write-Host "Available presets:" -ForegroundColor Cyan
Write-Host " - windows-debug" -ForegroundColor Gray
Write-Host " - windows-release" -ForegroundColor Gray
Write-Host " - windows-dev" -ForegroundColor Gray
exit 1
}
# Check if CMake is available
$cmakePath = Get-Command cmake -ErrorAction SilentlyContinue
if (-not $cmakePath) {
# Try common CMake installation paths
$commonPaths = @(
"C:\Program Files\CMake\bin\cmake.exe",
"C:\Program Files (x86)\CMake\bin\cmake.exe",
"C:\cmake\bin\cmake.exe"
)
foreach ($path in $commonPaths) {
if (Test-Path $path) {
Write-Host "Found CMake at: $path" -ForegroundColor Green
$env:Path += ";$(Split-Path $path)"
$cmakePath = Get-Command cmake -ErrorAction SilentlyContinue
if ($cmakePath) {
break
}
}
}
}
if (-not $cmakePath) {
Write-Host "CMake not found in PATH. Attempting to install..." -ForegroundColor Yellow
# Try to install CMake via Chocolatey
if (Get-Command choco -ErrorAction SilentlyContinue) {
Write-Host "Installing CMake via Chocolatey..." -ForegroundColor Yellow
choco install -y cmake
if ($LASTEXITCODE -eq 0) {
Write-Host "CMake installed successfully" -ForegroundColor Green
# Refresh PATH
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
} else {
Write-Host "Failed to install CMake via Chocolatey" -ForegroundColor Red
}
} else {
Write-Host "Chocolatey not found. Please install CMake manually:" -ForegroundColor Red
Write-Host "1. Download from: https://cmake.org/download/" -ForegroundColor Yellow
Write-Host "2. Or install Chocolatey first: https://chocolatey.org/install" -ForegroundColor Yellow
Write-Host "3. Then run: choco install cmake" -ForegroundColor Yellow
exit 1
}
# Check again after installation
$cmakePath = Get-Command cmake -ErrorAction SilentlyContinue
if (-not $cmakePath) {
Write-Host "CMake still not found after installation. Please restart your terminal or add CMake to PATH manually." -ForegroundColor Red
exit 1
}
}
Write-Host "CMake found: $($cmakePath.Source)" -ForegroundColor Green
# Check if Visual Studio is available
$vsWhere = Get-Command "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -ErrorAction SilentlyContinue
if (-not $vsWhere) {
$vsWhere = Get-Command vswhere -ErrorAction SilentlyContinue
}
if ($vsWhere) {
$vsInstallPath = & $vsWhere.Source -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
if ($vsInstallPath) {
Write-Host "Visual Studio found at: $vsInstallPath" -ForegroundColor Green
} else {
Write-Host "Visual Studio 2022 not found. Please install Visual Studio 2022 with C++ workload." -ForegroundColor Yellow
}
} else {
Write-Host "vswhere not found. Assuming Visual Studio is available." -ForegroundColor Yellow
}
# Set up paths
$SourceDir = Split-Path -Parent $PSScriptRoot
$BuildDir = Join-Path $SourceDir "build-vs"
Write-Host "Source directory: $SourceDir" -ForegroundColor Cyan
Write-Host "Build directory: $BuildDir" -ForegroundColor Cyan
# Clean build directory if requested
if ($Clean -and (Test-Path $BuildDir)) {
Write-Host "Cleaning build directory..." -ForegroundColor Yellow
Remove-Item -Recurse -Force $BuildDir
}
# Create build directory
if (-not (Test-Path $BuildDir)) {
New-Item -ItemType Directory -Path $BuildDir | Out-Null
}
# Check if vcpkg is available
$VcpkgPath = Join-Path $SourceDir "vcpkg\scripts\buildsystems\vcpkg.cmake"
$UseVcpkg = Test-Path $VcpkgPath
if ($UseVcpkg) {
Write-Host "Using vcpkg toolchain: $VcpkgPath" -ForegroundColor Green
} else {
Write-Host "vcpkg not found, using system libraries" -ForegroundColor Yellow
}
# Determine generator and architecture
$Generator = "Visual Studio 17 2022"
$ArchFlag = if ($Architecture -eq "x64") { "-A x64" } else { "-A Win32" }
# Build CMake command
$CmakeArgs = @(
"-B", $BuildDir,
"-G", "`"$Generator`"",
$ArchFlag,
"-DCMAKE_BUILD_TYPE=$Configuration",
"-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
"-DCMAKE_POLICY_VERSION_MAXIMUM=3.28",
"-DCMAKE_WARN_DEPRECATED=OFF",
"-DABSL_PROPAGATE_CXX_STD=ON",
"-DTHREADS_PREFER_PTHREAD_FLAG=OFF",
"-DYAZE_BUILD_TESTS=ON",
"-DYAZE_BUILD_APP=ON",
"-DYAZE_BUILD_LIB=ON",
"-DYAZE_BUILD_EMU=ON",
"-DYAZE_BUILD_Z3ED=ON",
"-DYAZE_ENABLE_ROM_TESTS=OFF",
"-DYAZE_ENABLE_EXPERIMENTAL_TESTS=ON",
"-DYAZE_ENABLE_UI_TESTS=ON",
"-DYAZE_INSTALL_LIB=OFF"
)
if ($UseVcpkg) {
$CmakeArgs += @(
"-DCMAKE_TOOLCHAIN_FILE=`"$VcpkgPath`"",
"-DVCPKG_TARGET_TRIPLET=$Architecture-windows",
"-DVCPKG_MANIFEST_MODE=ON"
)
}
# Configure CMake to generate build files (but don't overwrite existing project files)
Write-Host "Configuring CMake for build system..." -ForegroundColor Yellow
Write-Host "Command: cmake $($CmakeArgs -join ' ')" -ForegroundColor Gray
& cmake @CmakeArgs $SourceDir
if ($LASTEXITCODE -ne 0) {
Write-Host "CMake configuration failed!" -ForegroundColor Red
exit 1
}
# Check if the existing solution file is present and valid
$ExistingSolutionFile = Join-Path $SourceDir "YAZE.sln"
if (Test-Path $ExistingSolutionFile) {
Write-Host "✅ Using existing Visual Studio solution: $ExistingSolutionFile" -ForegroundColor Green
# Verify the solution file is properly structured
$SolutionContent = Get-Content $ExistingSolutionFile -Raw
if ($SolutionContent -match "YAZE\.vcxproj") {
Write-Host "✅ Solution file references YAZE.vcxproj correctly" -ForegroundColor Green
# Check if project configurations are set up
if ($SolutionContent -match "ProjectConfigurationPlatforms") {
Write-Host "✅ Project configurations are properly set up" -ForegroundColor Green
} else {
Write-Host "⚠️ Warning: Project configurations may not be set up" -ForegroundColor Yellow
}
} else {
Write-Host "❌ Solution file does not reference YAZE.vcxproj" -ForegroundColor Red
Write-Host "Please ensure the solution file includes the YAZE project" -ForegroundColor Yellow
}
# Open solution in Visual Studio if available
if (Get-Command "devenv" -ErrorAction SilentlyContinue) {
Write-Host "Opening solution in Visual Studio..." -ForegroundColor Yellow
& devenv $ExistingSolutionFile
} elseif (Get-Command "code" -ErrorAction SilentlyContinue) {
Write-Host "Opening solution in VS Code..." -ForegroundColor Yellow
& code $ExistingSolutionFile
} else {
Write-Host "Visual Studio solution ready: $ExistingSolutionFile" -ForegroundColor Cyan
}
} else {
Write-Host "❌ Existing solution file not found: $ExistingSolutionFile" -ForegroundColor Red
Write-Host "Please ensure YAZE.sln exists in the project root" -ForegroundColor Yellow
exit 1
}
Write-Host ""
Write-Host "🎉 Visual Studio project configuration complete!" -ForegroundColor Green
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Cyan
Write-Host "1. Open YAZE.sln in Visual Studio" -ForegroundColor White
Write-Host "2. Select configuration: $Configuration" -ForegroundColor White
Write-Host "3. Select platform: $Architecture" -ForegroundColor White
Write-Host "4. Build the solution (Ctrl+Shift+B)" -ForegroundColor White
Write-Host ""
Write-Host "Available configurations:" -ForegroundColor Cyan
Write-Host " - Debug (with debugging symbols)" -ForegroundColor Gray
Write-Host " - Release (optimized)" -ForegroundColor Gray
Write-Host " - RelWithDebInfo (optimized with debug info)" -ForegroundColor Gray
Write-Host " - MinSizeRel (minimum size)" -ForegroundColor Gray
Write-Host ""
Write-Host "Available architectures:" -ForegroundColor Cyan
Write-Host " - x64 (64-bit Intel/AMD)" -ForegroundColor Gray
Write-Host " - x86 (32-bit Intel/AMD)" -ForegroundColor Gray
Write-Host " - ARM64 (64-bit ARM)" -ForegroundColor Gray

View File

@@ -1,543 +0,0 @@
#!/usr/bin/env python3
"""
Python script to generate proper Visual Studio project files for YAZE
This script creates a comprehensive .vcxproj file with all necessary source files
"""
import os
import sys
from pathlib import Path
def generate_vcxproj():
"""Generate the YAZE.vcxproj file with all source files"""
# Source file lists (from CMake files)
app_core_src = [
"app/core/controller.cc",
"app/emu/emulator.cc",
"app/core/project.cc",
"app/core/window.cc",
"app/core/asar_wrapper.cc",
"app/core/platform/font_loader.cc",
"app/core/platform/clipboard.cc",
"app/core/platform/file_dialog.cc"
]
app_emu_src = [
"app/emu/audio/apu.cc",
"app/emu/audio/spc700.cc",
"app/emu/audio/dsp.cc",
"app/emu/audio/internal/addressing.cc",
"app/emu/audio/internal/instructions.cc",
"app/emu/cpu/internal/addressing.cc",
"app/emu/cpu/internal/instructions.cc",
"app/emu/cpu/cpu.cc",
"app/emu/video/ppu.cc",
"app/emu/memory/dma.cc",
"app/emu/memory/memory.cc",
"app/emu/snes.cc"
]
app_editor_src = [
"app/editor/editor_manager.cc",
"app/editor/dungeon/dungeon_editor.cc",
"app/editor/dungeon/dungeon_room_selector.cc",
"app/editor/dungeon/dungeon_canvas_viewer.cc",
"app/editor/dungeon/dungeon_object_selector.cc",
"app/editor/dungeon/dungeon_toolset.cc",
"app/editor/dungeon/dungeon_object_interaction.cc",
"app/editor/dungeon/dungeon_renderer.cc",
"app/editor/dungeon/dungeon_room_loader.cc",
"app/editor/dungeon/dungeon_usage_tracker.cc",
"app/editor/overworld/overworld_editor.cc",
"app/editor/overworld/overworld_editor_manager.cc",
"app/editor/sprite/sprite_editor.cc",
"app/editor/music/music_editor.cc",
"app/editor/message/message_editor.cc",
"app/editor/message/message_data.cc",
"app/editor/message/message_preview.cc",
"app/editor/code/assembly_editor.cc",
"app/editor/graphics/screen_editor.cc",
"app/editor/graphics/graphics_editor.cc",
"app/editor/graphics/palette_editor.cc",
"app/editor/overworld/tile16_editor.cc",
"app/editor/overworld/map_properties.cc",
"app/editor/graphics/gfx_group_editor.cc",
"app/editor/overworld/entity.cc",
"app/editor/system/settings_editor.cc",
"app/editor/system/command_manager.cc",
"app/editor/system/extension_manager.cc",
"app/editor/system/shortcut_manager.cc",
"app/editor/system/popup_manager.cc",
"app/test/test_manager.cc"
]
app_gfx_src = [
"app/gfx/arena.cc",
"app/gfx/background_buffer.cc",
"app/gfx/bitmap.cc",
"app/gfx/compression.cc",
"app/gfx/scad_format.cc",
"app/gfx/snes_palette.cc",
"app/gfx/snes_tile.cc",
"app/gfx/snes_color.cc",
"app/gfx/tilemap.cc"
]
app_zelda3_src = [
"app/zelda3/hyrule_magic.cc",
"app/zelda3/overworld/overworld_map.cc",
"app/zelda3/overworld/overworld.cc",
"app/zelda3/screen/inventory.cc",
"app/zelda3/screen/title_screen.cc",
"app/zelda3/screen/dungeon_map.cc",
"app/zelda3/sprite/sprite.cc",
"app/zelda3/sprite/sprite_builder.cc",
"app/zelda3/music/tracker.cc",
"app/zelda3/dungeon/room.cc",
"app/zelda3/dungeon/room_object.cc",
"app/zelda3/dungeon/object_parser.cc",
"app/zelda3/dungeon/object_renderer.cc",
"app/zelda3/dungeon/room_layout.cc",
"app/zelda3/dungeon/dungeon_editor_system.cc",
"app/zelda3/dungeon/dungeon_object_editor.cc"
]
gui_src = [
"app/gui/modules/asset_browser.cc",
"app/gui/modules/text_editor.cc",
"app/gui/canvas.cc",
"app/gui/canvas_utils.cc",
"app/gui/enhanced_palette_editor.cc",
"app/gui/input.cc",
"app/gui/style.cc",
"app/gui/color.cc",
"app/gui/zeml.cc",
"app/gui/theme_manager.cc",
"app/gui/background_renderer.cc"
]
util_src = [
"util/bps.cc",
"util/flag.cc",
"util/hex.cc"
]
# Combine all source files
all_source_files = (
["yaze.cc", "app/main.cc", "app/rom.cc"] +
app_core_src + app_emu_src + app_editor_src +
app_gfx_src + app_zelda3_src + gui_src + util_src
)
# Header files
header_files = [
"incl/yaze.h",
"incl/zelda.h",
"src/yaze_config.h.in"
]
# Generate the .vcxproj file content
vcxproj_content = '''<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x86">
<Configuration>Debug</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x86">
<Configuration>Release</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x86">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|ARM64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="MinSizeRel|x64">
<Configuration>MinSizeRel</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="MinSizeRel|x86">
<Configuration>MinSizeRel</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="MinSizeRel|ARM64">
<Configuration>MinSizeRel</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B2C3D4E5-F6G7-8901-BCDE-F23456789012}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>YAZE</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>YAZE</ProjectName>
<VcpkgEnabled>true</VcpkgEnabled>
<VcpkgManifestInstall>true</VcpkgManifestInstall>
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows</VcpkgTriplet>
<VcpkgTriplet Condition="'$(Platform)'=='ARM64'">arm64-windows</VcpkgTriplet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x86'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x86'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x86'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x86'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|ARM64'">
<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x86'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x86'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|ARM64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\\bin\\$(Configuration)\\</OutDir>
<IntDir>$(SolutionDir)build\\obj\\$(Configuration)\\</IntDir>
</PropertyGroup>'''
# Add compiler and linker settings for all configurations
configurations = ["Debug", "Release", "RelWithDebInfo", "MinSizeRel"]
platforms = ["x64", "x86", "ARM64"]
for config in configurations:
for platform in platforms:
is_debug = (config == "Debug")
debug_flags = "_DEBUG;_CONSOLE;%(PreprocessorDefinitions)" if is_debug else "NDEBUG;_CONSOLE;%(PreprocessorDefinitions)"
link_incremental = "true" if is_debug else "false"
generate_debug_info = "false" if config == "MinSizeRel" else "true"
vcxproj_content += f'''
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='{config}|{platform}'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>{debug_flags}</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)src;$(ProjectDir)incl;$(ProjectDir)src\\lib;$(ProjectDir)src\\lib\\asar\\src;$(ProjectDir)src\\lib\\asar\\src\\asar;$(ProjectDir)src\\lib\\asar\\src\\asar-dll-bindings\\c;$(ProjectDir)src\\lib\\imgui;$(ProjectDir)src\\lib\\imgui_test_engine;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp23</LanguageStandard>
<BigObj>true</BigObj>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreaded{"Debug" if is_debug else ""}DLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>{generate_debug_info}</GenerateDebugInformation>
<EnableCOMDATFolding>{"false" if is_debug else "true"}</EnableCOMDATFolding>
<OptimizeReferences>{"false" if is_debug else "true"}</OptimizeReferences>
</Link>
</ItemDefinitionGroup>'''
# Add source files
vcxproj_content += '''
<ItemGroup>
'''
for header in header_files:
vcxproj_content += f' <ClInclude Include="{header}" />\n'
vcxproj_content += ''' </ItemGroup>
<ItemGroup>
'''
for source in all_source_files:
vcxproj_content += f' <ClCompile Include="src\\{source}" />\n'
vcxproj_content += ''' </ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="CMakePresets.json" />
<None Include="vcpkg.json" />
<None Include="README.md" />
<None Include="LICENSE" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>'''
return vcxproj_content
def generate_solution():
"""Generate the YAZE.sln file"""
return '''Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YAZE", "YAZE.vcxproj", "{B2C3D4E5-F6G7-8901-BCDE-F23456789012}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Debug|ARM64 = Debug|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
Release|ARM64 = Release|ARM64
RelWithDebInfo|x64 = RelWithDebInfo|x64
RelWithDebInfo|x86 = RelWithDebInfo|x86
RelWithDebInfo|ARM64 = RelWithDebInfo|ARM64
MinSizeRel|x64 = MinSizeRel|x64
MinSizeRel|x86 = MinSizeRel|x86
MinSizeRel|ARM64 = MinSizeRel|ARM64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|x64.ActiveCfg = Debug|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|x64.Build.0 = Debug|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|x86.ActiveCfg = Debug|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|x86.Build.0 = Debug|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Debug|ARM64.Build.0 = Debug|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|x64.ActiveCfg = Release|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|x64.Build.0 = Release|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|x86.ActiveCfg = Release|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|x86.Build.0 = Release|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|ARM64.ActiveCfg = Release|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.Release|ARM64.Build.0 = Release|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.MinSizeRel|x86.Build.0 = MinSizeRel|x86
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.MinSizeRel|ARM64.ActiveCfg = MinSizeRel|ARM64
{B2C3D4E5-F6G7-8901-BCDE-F23456789012}.MinSizeRel|ARM64.Build.0 = MinSizeRel|ARM64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A1B2C3D4-E5F6-7890-ABCD-EF1234567890}
EndGlobalSection
EndGlobal'''
def main():
"""Main function to generate Visual Studio project files"""
print("Generating Visual Studio project files for YAZE...")
# Get the project root directory
script_dir = Path(__file__).parent
project_root = script_dir.parent
# Generate .vcxproj file
vcxproj_content = generate_vcxproj()
vcxproj_path = project_root / "YAZE.vcxproj"
with open(vcxproj_path, 'w', encoding='utf-8') as f:
f.write(vcxproj_content)
print(f"Generated: {vcxproj_path}")
# Generate .sln file
solution_content = generate_solution()
solution_path = project_root / "YAZE.sln"
with open(solution_path, 'w', encoding='utf-8') as f:
f.write(solution_content)
print(f"Generated: {solution_path}")
print("Visual Studio project files generated successfully!")
print("")
print("To build:")
print("1. Open YAZE.sln in Visual Studio 2022")
print("2. Ensure vcpkg is installed and configured")
print("3. Select your desired configuration (Debug/Release) and platform (x64/x86/ARM64)")
print("4. Build the solution (Ctrl+Shift+B)")
if __name__ == "__main__":
main()

6
scripts/requirements.txt Normal file
View File

@@ -0,0 +1,6 @@
# Python dependencies for YAZE build scripts
# Install with: pip3 install -r scripts/requirements.txt
# For .gitignore pattern matching in build_cleaner.py
pathspec>=0.11.0

419
scripts/run_overworld_tests.sh Executable file
View File

@@ -0,0 +1,419 @@
#!/bin/bash
# =============================================================================
# YAZE Overworld Comprehensive Test Runner
# =============================================================================
#
# This script orchestrates the complete overworld testing workflow:
# 1. Builds the golden data extractor tool
# 2. Extracts golden data from vanilla and modified ROMs
# 3. Runs unit tests, integration tests, and E2E tests
# 4. Generates comprehensive test reports
# 5. Validates before/after edit states
#
# Usage: ./scripts/run_overworld_tests.sh [rom_path] [options]
#
# Options:
# --skip-build Skip building the golden data extractor
# --skip-golden-data Skip golden data extraction
# --skip-unit-tests Skip unit tests
# --skip-integration Skip integration tests
# --skip-e2e Skip E2E tests
# --generate-report Generate detailed test report
# --cleanup Clean up test files after completion
# =============================================================================
set -e # Exit on any error
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
BUILD_DIR="$PROJECT_ROOT/build"
BIN_DIR="$BUILD_DIR/bin"
TEST_DIR="$PROJECT_ROOT/test"
# Default values
ROM_PATH=""
SKIP_BUILD=false
SKIP_GOLDEN_DATA=false
SKIP_UNIT_TESTS=false
SKIP_INTEGRATION=false
SKIP_E2E=false
GENERATE_REPORT=false
CLEANUP=false
# Test results
UNIT_TEST_RESULTS=""
INTEGRATION_TEST_RESULTS=""
E2E_TEST_RESULTS=""
GOLDEN_DATA_STATUS=""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
show_usage() {
cat << EOF
Usage: $0 [rom_path] [options]
Arguments:
rom_path Path to the ROM file to test with
Options:
--skip-build Skip building the golden data extractor
--skip-golden-data Skip golden data extraction
--skip-unit-tests Skip unit tests
--skip-integration Skip integration tests
--skip-e2e Skip E2E tests
--generate-report Generate detailed test report
--cleanup Clean up test files after completion
Examples:
$0 zelda3.sfc
$0 zelda3.sfc --generate-report --cleanup
$0 /path/to/rom.sfc --skip-unit-tests
EOF
}
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--skip-build)
SKIP_BUILD=true
shift
;;
--skip-golden-data)
SKIP_GOLDEN_DATA=true
shift
;;
--skip-unit-tests)
SKIP_UNIT_TESTS=true
shift
;;
--skip-integration)
SKIP_INTEGRATION=true
shift
;;
--skip-e2e)
SKIP_E2E=true
shift
;;
--generate-report)
GENERATE_REPORT=true
shift
;;
--cleanup)
CLEANUP=true
shift
;;
--help|-h)
show_usage
exit 0
;;
-*)
log_error "Unknown option: $1"
show_usage
exit 1
;;
*)
if [[ -z "$ROM_PATH" ]]; then
ROM_PATH="$1"
else
log_error "Multiple ROM paths specified"
exit 1
fi
shift
;;
esac
done
}
check_prerequisites() {
log_info "Checking prerequisites..."
# Check if we're in the right directory
if [[ ! -f "$PROJECT_ROOT/CMakeLists.txt" ]]; then
log_error "Not in YAZE project root directory"
exit 1
fi
# Check if build directory exists
if [[ ! -d "$BUILD_DIR" ]]; then
log_warning "Build directory not found. Run 'cmake --build build' first."
exit 1
fi
# Check if ROM path is provided
if [[ -z "$ROM_PATH" ]]; then
log_error "ROM path is required"
show_usage
exit 1
fi
# Check if ROM file exists
if [[ ! -f "$ROM_PATH" ]]; then
log_error "ROM file not found: $ROM_PATH"
exit 1
fi
log_success "Prerequisites check passed"
}
build_golden_data_extractor() {
if [[ "$SKIP_BUILD" == true ]]; then
log_info "Skipping golden data extractor build"
return
fi
log_info "Building golden data extractor..."
cd "$PROJECT_ROOT"
# Build the golden data extractor
if cmake --build "$BUILD_DIR" --target overworld_golden_data_extractor; then
log_success "Golden data extractor built successfully"
else
log_error "Failed to build golden data extractor"
exit 1
fi
}
extract_golden_data() {
if [[ "$SKIP_GOLDEN_DATA" == true ]]; then
log_info "Skipping golden data extraction"
return
fi
log_info "Extracting golden data from ROM..."
local golden_data_file="$TEST_DIR/golden_data/$(basename "$ROM_PATH" .sfc)_golden_data.h"
# Create golden data directory if it doesn't exist
mkdir -p "$(dirname "$golden_data_file")"
# Run the golden data extractor
if "$BIN_DIR/overworld_golden_data_extractor" "$ROM_PATH" "$golden_data_file"; then
log_success "Golden data extracted to: $golden_data_file"
GOLDEN_DATA_STATUS="SUCCESS: $golden_data_file"
else
log_error "Failed to extract golden data"
GOLDEN_DATA_STATUS="FAILED"
return 1
fi
}
run_unit_tests() {
if [[ "$SKIP_UNIT_TESTS" == true ]]; then
log_info "Skipping unit tests"
return
fi
log_info "Running unit tests..."
cd "$PROJECT_ROOT"
# Set environment variable for ROM path
export YAZE_TEST_ROM_PATH="$ROM_PATH"
# Run unit tests
if ctest --test-dir "$BUILD_DIR" --output-on-failure --verbose \
--tests-regex "overworld.*test|extract.*vanilla.*values"; then
log_success "Unit tests passed"
UNIT_TEST_RESULTS="PASSED"
else
log_error "Unit tests failed"
UNIT_TEST_RESULTS="FAILED"
return 1
fi
}
run_integration_tests() {
if [[ "$SKIP_INTEGRATION" == true ]]; then
log_info "Skipping integration tests"
return
fi
log_info "Running integration tests..."
cd "$PROJECT_ROOT"
# Set environment variable for ROM path
export YAZE_TEST_ROM_PATH="$ROM_PATH"
# Run integration tests
if ctest --test-dir "$BUILD_DIR" --output-on-failure --verbose \
--tests-regex "overworld.*integration"; then
log_success "Integration tests passed"
INTEGRATION_TEST_RESULTS="PASSED"
else
log_error "Integration tests failed"
INTEGRATION_TEST_RESULTS="FAILED"
return 1
fi
}
run_e2e_tests() {
if [[ "$SKIP_E2E" == true ]]; then
log_info "Skipping E2E tests"
return
fi
log_info "Running E2E tests..."
cd "$PROJECT_ROOT"
# Set environment variable for ROM path
export YAZE_TEST_ROM_PATH="$ROM_PATH"
# Run E2E tests
if ctest --test-dir "$BUILD_DIR" --output-on-failure --verbose \
--tests-regex "overworld.*e2e"; then
log_success "E2E tests passed"
E2E_TEST_RESULTS="PASSED"
else
log_error "E2E tests failed"
E2E_TEST_RESULTS="FAILED"
return 1
fi
}
generate_test_report() {
if [[ "$GENERATE_REPORT" != true ]]; then
return
fi
log_info "Generating test report..."
local report_file="$TEST_DIR/reports/overworld_test_report_$(date +%Y%m%d_%H%M%S).md"
# Create reports directory if it doesn't exist
mkdir -p "$(dirname "$report_file")"
cat > "$report_file" << EOF
# YAZE Overworld Test Report
**Generated:** $(date)
**ROM:** $ROM_PATH
**ROM Size:** $(stat -f%z "$ROM_PATH" 2>/dev/null || stat -c%s "$ROM_PATH") bytes
## Test Results Summary
| Test Category | Status | Details |
|---------------|--------|---------|
| Golden Data Extraction | $GOLDEN_DATA_STATUS | |
| Unit Tests | $UNIT_TEST_RESULTS | |
| Integration Tests | $INTEGRATION_TEST_RESULTS | |
| E2E Tests | $E2E_TEST_RESULTS | |
## Test Configuration
- Skip Build: $SKIP_BUILD
- Skip Golden Data: $SKIP_GOLDEN_DATA
- Skip Unit Tests: $SKIP_UNIT_TESTS
- Skip Integration: $SKIP_INTEGRATION
- Skip E2E: $SKIP_E2E
- Generate Report: $GENERATE_REPORT
- Cleanup: $CLEANUP
## ROM Information
EOF
# Add ROM header information if available
if command -v hexdump >/dev/null 2>&1; then
echo "### ROM Header" >> "$report_file"
echo '```' >> "$report_file"
hexdump -C "$ROM_PATH" | head -20 >> "$report_file"
echo '```' >> "$report_file"
fi
echo "" >> "$report_file"
echo "## Next Steps" >> "$report_file"
echo "" >> "$report_file"
echo "1. Review test results above" >> "$report_file"
echo "2. If tests failed, check the logs for details" >> "$report_file"
echo "3. Run individual test categories for debugging" >> "$report_file"
echo "4. Update golden data if ROM changes are expected" >> "$report_file"
log_success "Test report generated: $report_file"
}
cleanup_test_files() {
if [[ "$CLEANUP" != true ]]; then
return
fi
log_info "Cleaning up test files..."
# Remove test ROMs created during testing
find "$TEST_DIR" -name "test_*.sfc" -type f -delete 2>/dev/null || true
# Remove temporary golden data files
find "$TEST_DIR" -name "*_golden_data.h" -type f -delete 2>/dev/null || true
log_success "Test files cleaned up"
}
main() {
log_info "Starting YAZE Overworld Comprehensive Test Suite"
log_info "ROM Path: $ROM_PATH"
# Parse command line arguments
parse_args "$@"
# Check prerequisites
check_prerequisites
# Build golden data extractor
build_golden_data_extractor
# Extract golden data
extract_golden_data
# Run tests
run_unit_tests
run_integration_tests
run_e2e_tests
# Generate report
generate_test_report
# Cleanup
cleanup_test_files
# Final status
log_info "Test suite completed"
if [[ "$UNIT_TEST_RESULTS" == "PASSED" &&
"$INTEGRATION_TEST_RESULTS" == "PASSED" &&
"$E2E_TEST_RESULTS" == "PASSED" ]]; then
log_success "All tests passed!"
exit 0
else
log_error "Some tests failed. Check the results above."
exit 1
fi
}
# Run main function with all arguments
main "$@"

View File

@@ -1,81 +0,0 @@
@echo off
REM YAZE vcpkg Setup Script (Batch Version)
REM This script sets up vcpkg for YAZE development on Windows
setlocal enabledelayedexpansion
echo ========================================
echo YAZE vcpkg Setup Script
echo ========================================
REM Check if we're in the right directory
if not exist "vcpkg.json" (
echo ERROR: vcpkg.json not found. Please run this script from the project root directory.
pause
exit /b 1
)
echo ✓ vcpkg.json found
REM Check for Git
where git >nul 2>&1
if %errorlevel% neq 0 (
echo ERROR: Git not found. Please install Git for Windows.
echo Download from: https://git-scm.com/download/win
pause
exit /b 1
)
echo ✓ Git found
REM Clone vcpkg if needed
if not exist "vcpkg" (
echo Cloning vcpkg...
git clone https://github.com/Microsoft/vcpkg.git vcpkg
if %errorlevel% neq 0 (
echo ERROR: Failed to clone vcpkg
pause
exit /b 1
)
echo ✓ vcpkg cloned successfully
) else (
echo ✓ vcpkg directory already exists
)
REM Bootstrap vcpkg
if not exist "vcpkg\vcpkg.exe" (
echo Bootstrapping vcpkg...
cd vcpkg
call bootstrap-vcpkg.bat
if %errorlevel% neq 0 (
echo ERROR: Failed to bootstrap vcpkg
cd ..
pause
exit /b 1
)
cd ..
echo ✓ vcpkg bootstrapped successfully
) else (
echo ✓ vcpkg already bootstrapped
)
REM Install dependencies
echo Installing dependencies...
vcpkg\vcpkg.exe install --triplet x64-windows
if %errorlevel% neq 0 (
echo WARNING: Some dependencies may not have installed correctly
) else (
echo ✓ Dependencies installed successfully
)
echo ========================================
echo ✓ vcpkg setup complete!
echo ========================================
echo.
echo You can now build YAZE using:
echo .\scripts\build-windows.ps1
echo or
echo .\scripts\build-windows.bat
echo.
pause

View File

@@ -1,10 +1,19 @@
# YAZE vcpkg Setup Script
# yaze vcpkg Setup Script
# This script sets up vcpkg for YAZE development on Windows
param(
[string]$Triplet = "x64-windows"
)
# Auto-detect architecture if not specified
if ($Triplet -eq "x64-windows") {
$Architecture = $env:PROCESSOR_ARCHITECTURE
if ($Architecture -eq "ARM64") {
$Triplet = "arm64-windows"
Write-Host "Auto-detected ARM64 architecture, using arm64-windows triplet" -ForegroundColor Yellow
}
}
# Set error handling
$ErrorActionPreference = "Continue"

View File

@@ -1,219 +0,0 @@
# YAZE Windows Development Setup Script
# Sequential approach with no functions and minimal conditionals
param(
[switch]$SkipVcpkg,
[switch]$SkipVS,
[switch]$SkipBuild
)
$ErrorActionPreference = "Continue"
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "YAZE Windows Development Setup" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
# Step 1: Check project directory
Write-Host "Step 1: Checking project directory..." -ForegroundColor Yellow
$projectValid = Test-Path "CMakeLists.txt"
switch ($projectValid) {
$true { Write-Host "✓ CMakeLists.txt found" -ForegroundColor Green }
$false {
Write-Host "✗ CMakeLists.txt not found" -ForegroundColor Red
Write-Host "Please run this script from the YAZE project root directory" -ForegroundColor Yellow
exit 1
}
}
# Step 2: Check Visual Studio
Write-Host "Step 2: Checking Visual Studio..." -ForegroundColor Yellow
switch ($SkipVS) {
$true { Write-Host "Skipping Visual Studio check" -ForegroundColor Yellow }
$false {
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vsFound = $false
$vsExists = Test-Path $vsWhere
switch ($vsExists) {
$true {
$vsInstall = & $vsWhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
switch ($null -ne $vsInstall) {
$true {
$msbuildPath = Join-Path $vsInstall "MSBuild\Current\Bin\MSBuild.exe"
$vsFound = Test-Path $msbuildPath
}
}
}
}
switch ($vsFound) {
$true { Write-Host "✓ Visual Studio 2022 with C++ workload found" -ForegroundColor Green }
$false {
Write-Host "⚠ Visual Studio 2022 with C++ workload not found" -ForegroundColor Yellow
Write-Host "Please install Visual Studio 2022 with 'Desktop development with C++' workload" -ForegroundColor White
}
}
}
}
# Step 3: Check Git
Write-Host "Step 3: Checking Git..." -ForegroundColor Yellow
$gitFound = $false
try {
$null = Get-Command git -ErrorAction Stop
$gitFound = $true
} catch {
$gitFound = $false
}
switch ($gitFound) {
$true {
$gitVersion = & git --version
Write-Host "✓ Git found: $gitVersion" -ForegroundColor Green
}
$false {
Write-Host "⚠ Git not found" -ForegroundColor Yellow
Write-Host "Please install Git for Windows from: https://git-scm.com/download/win" -ForegroundColor White
}
}
# Step 4: Check Python
Write-Host "Step 4: Checking Python..." -ForegroundColor Yellow
$pythonFound = $false
try {
$null = Get-Command python -ErrorAction Stop
$pythonFound = $true
} catch {
$pythonFound = $false
}
switch ($pythonFound) {
$true {
$pythonVersion = & python --version
Write-Host "✓ Python found: $pythonVersion" -ForegroundColor Green
}
$false {
Write-Host "⚠ Python not found" -ForegroundColor Yellow
Write-Host "Please install Python 3.8+ from: https://www.python.org/downloads/" -ForegroundColor White
}
}
# Step 5: Setup vcpkg
Write-Host "Step 5: Setting up vcpkg..." -ForegroundColor Yellow
switch ($SkipVcpkg) {
$true { Write-Host "Skipping vcpkg setup" -ForegroundColor Yellow }
$false {
# Clone vcpkg
$vcpkgExists = Test-Path "vcpkg"
switch ($vcpkgExists) {
$false {
Write-Host "Cloning vcpkg..." -ForegroundColor Yellow
switch ($gitFound) {
$true {
& git clone https://github.com/Microsoft/vcpkg.git vcpkg
$cloneSuccess = ($LASTEXITCODE -eq 0)
switch ($cloneSuccess) {
$true { Write-Host "✓ vcpkg cloned successfully" -ForegroundColor Green }
$false {
Write-Host "✗ Failed to clone vcpkg" -ForegroundColor Red
exit 1
}
}
}
$false {
Write-Host "✗ Git is required to clone vcpkg" -ForegroundColor Red
exit 1
}
}
}
$true { Write-Host "✓ vcpkg directory already exists" -ForegroundColor Green }
}
# Bootstrap vcpkg
$vcpkgExe = "vcpkg\vcpkg.exe"
$vcpkgBootstrapped = Test-Path $vcpkgExe
switch ($vcpkgBootstrapped) {
$false {
Write-Host "Bootstrapping vcpkg..." -ForegroundColor Yellow
Push-Location vcpkg
& .\bootstrap-vcpkg.bat
$bootstrapSuccess = ($LASTEXITCODE -eq 0)
Pop-Location
switch ($bootstrapSuccess) {
$true { Write-Host "✓ vcpkg bootstrapped successfully" -ForegroundColor Green }
$false {
Write-Host "✗ Failed to bootstrap vcpkg" -ForegroundColor Red
exit 1
}
}
}
$true { Write-Host "✓ vcpkg already bootstrapped" -ForegroundColor Green }
}
# Install dependencies
Write-Host "Installing dependencies..." -ForegroundColor Yellow
& $vcpkgExe install --triplet x64-windows
$installSuccess = ($LASTEXITCODE -eq 0)
switch ($installSuccess) {
$true { Write-Host "✓ Dependencies installed successfully" -ForegroundColor Green }
$false { Write-Host "⚠ Some dependencies may not have installed correctly" -ForegroundColor Yellow }
}
}
}
# Step 6: Generate project files
Write-Host "Step 6: Generating Visual Studio project files..." -ForegroundColor Yellow
switch ($pythonFound) {
$true {
& python scripts/generate-vs-projects-simple.py
$generateSuccess = ($LASTEXITCODE -eq 0)
switch ($generateSuccess) {
$true { Write-Host "✓ Project files generated successfully" -ForegroundColor Green }
$false {
Write-Host "⚠ Failed to generate project files with simple generator, trying original..." -ForegroundColor Yellow
& python scripts/generate-vs-projects.py
$generateSuccess2 = ($LASTEXITCODE -eq 0)
switch ($generateSuccess2) {
$true { Write-Host "✓ Project files generated successfully" -ForegroundColor Green }
$false { Write-Host "⚠ Failed to generate project files" -ForegroundColor Yellow }
}
}
}
}
$false { Write-Host "⚠ Python required to generate project files" -ForegroundColor Yellow }
}
# Step 7: Test build
Write-Host "Step 7: Testing build..." -ForegroundColor Yellow
switch ($SkipBuild) {
$true { Write-Host "Skipping test build" -ForegroundColor Yellow }
$false {
$buildScriptExists = Test-Path "scripts\build-windows.ps1"
switch ($buildScriptExists) {
$true {
& .\scripts\build-windows.ps1 -Configuration Release -Platform x64
$buildSuccess = ($LASTEXITCODE -eq 0)
switch ($buildSuccess) {
$true { Write-Host "✓ Test build successful" -ForegroundColor Green }
$false { Write-Host "⚠ Test build failed, but setup is complete" -ForegroundColor Yellow }
}
}
$false { Write-Host "⚠ Build script not found" -ForegroundColor Yellow }
}
}
}
# Final instructions
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "✓ YAZE Windows development setup complete!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host "1. Visual Studio project files have been generated" -ForegroundColor White
Write-Host "2. Open YAZE.sln in Visual Studio 2022" -ForegroundColor White
Write-Host "3. Select configuration (Debug/Release) and platform (x64/x86/ARM64)" -ForegroundColor White
Write-Host "4. Build the solution (Ctrl+Shift+B)" -ForegroundColor White
Write-Host ""
Write-Host "Or use command line:" -ForegroundColor Yellow
Write-Host " .\scripts\build-windows.ps1 -Configuration Release -Platform x64" -ForegroundColor White
Write-Host ""
Write-Host "For more information, see docs/windows-development-guide.md" -ForegroundColor Cyan

57
scripts/start_collab_server.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# YAZE Collaboration Server Launcher
# Starts the WebSocket collaboration server for networked YAZE sessions
# https://github.com/scawful/yaze-server
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
SERVER_DIR="$PROJECT_ROOT/../yaze-server"
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo -e "${GREEN}🚀 YAZE Collaboration Server Launcher${NC}"
echo ""
# Check if server directory exists
if [ ! -d "$SERVER_DIR" ]; then
echo -e "${RED}Error: Collaboration server not found at $SERVER_DIR${NC}"
echo "Please ensure yaze-server is cloned alongside the yaze repository."
exit 1
fi
cd "$SERVER_DIR"
# Check if Node.js is installed
if ! command -v node &> /dev/null; then
echo -e "${RED}Error: Node.js is not installed${NC}"
echo "Please install Node.js from https://nodejs.org/"
exit 1
fi
# Check if npm packages are installed
if [ ! -d "node_modules" ]; then
echo -e "${YELLOW}Installing server dependencies...${NC}"
npm install
fi
# Get port from argument or use default
PORT="${1:-8765}"
echo -e "${GREEN}Starting collaboration server on port $PORT...${NC}"
echo ""
echo "Server will be accessible at:"
echo " • ws://localhost:$PORT (local)"
echo " • ws://$(hostname):$PORT (network)"
echo ""
echo -e "${YELLOW}Press Ctrl+C to stop the server${NC}"
echo ""
# Start the server
PORT="$PORT" node server.js

View File

@@ -0,0 +1,282 @@
# YAZE AI Features Test Script for Windows
# Tests AI agent, multimodal vision, and GUI automation capabilities
param(
[string]$YazeBin = "build-windows\bin\Debug\yaze.exe",
[string]$Z3edBin = "build-windows\bin\Debug\z3ed.exe",
[string]$TestRom = "zelda3.sfc"
)
$ErrorActionPreference = "Continue"
function Write-Header {
Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ YAZE AI Features Test Suite (Windows) ║" -ForegroundColor Cyan
Write-Host "╚════════════════════════════════════════════════════════════════╝`n" -ForegroundColor Cyan
}
function Write-Section {
param($Title)
Write-Host "`n$Title" -ForegroundColor Blue
Write-Host ("" * 64) -ForegroundColor Blue
}
function Write-Test {
param($Message)
Write-Host " Testing: " -NoNewline -ForegroundColor Cyan
Write-Host $Message
}
function Write-Success {
param($Message)
Write-Host "$Message" -ForegroundColor Green
}
function Write-Warning {
param($Message)
Write-Host "$Message" -ForegroundColor Yellow
}
function Write-Error {
param($Message)
Write-Host "$Message" -ForegroundColor Red
}
function Test-Prerequisites {
Write-Section "Checking Prerequisites"
$allOk = $true
# Check binaries
if (Test-Path $YazeBin) {
Write-Success "YAZE GUI found: $YazeBin"
} else {
Write-Error "YAZE GUI not found: $YazeBin"
$allOk = $false
}
if (Test-Path $Z3edBin) {
Write-Success "z3ed CLI found: $Z3edBin"
} else {
Write-Error "z3ed CLI not found: $Z3edBin"
$allOk = $false
}
# Check ROM
if (Test-Path $TestRom) {
Write-Success "Test ROM found: $TestRom"
} else {
Write-Warning "Test ROM not found: $TestRom (some tests will be skipped)"
}
# Check Gemini API Key
if ($env:GEMINI_API_KEY) {
Write-Success "Gemini API key configured"
} else {
Write-Warning "GEMINI_API_KEY not set (vision tests will be skipped)"
Write-Warning " Set with: `$env:GEMINI_API_KEY='your-key-here'"
}
# Create screenshot directory
$screenshotsDir = "test_screenshots"
if (-not (Test-Path $screenshotsDir)) {
New-Item -ItemType Directory -Path $screenshotsDir | Out-Null
}
Write-Success "Screenshot directory ready: $screenshotsDir"
if (-not $allOk) {
Write-Host ""
Write-Error "Prerequisites not met. Please build the project first:"
Write-Host " cmake --preset win-ai"
Write-Host " cmake --build build-windows --config Debug"
exit 1
}
}
function Test-Z3edBasic {
Write-Section "Test 1: z3ed Basic Functionality"
Write-Test "Checking z3ed version"
try {
$output = & $Z3edBin --version 2>&1
Write-Success "z3ed executable works"
} catch {
Write-Error "z3ed --version failed"
return
}
Write-Test "Checking z3ed help"
try {
$output = & $Z3edBin --help 2>&1
Write-Success "z3ed help accessible"
} catch {
Write-Warning "z3ed help command failed"
}
}
function Test-AIAgentOllama {
Write-Section "Test 2: AI Agent (Ollama)"
Write-Test "Checking if Ollama is running"
try {
$response = Invoke-WebRequest -Uri "http://localhost:11434/api/tags" -UseBasicParsing -TimeoutSec 2
Write-Success "Ollama server is running"
Write-Test "Testing agent chat with Ollama"
$output = & $Z3edBin agent chat --model "llama3.2:latest" --prompt "Say 'test successful' and nothing else" 2>&1
if ($output -match "test successful") {
Write-Success "Ollama agent responded correctly"
} else {
Write-Warning "Ollama agent test inconclusive"
}
} catch {
Write-Warning "Ollama not running (start with: ollama serve)"
}
}
function Test-AIAgentGemini {
Write-Section "Test 3: AI Agent (Gemini)"
if (-not $env:GEMINI_API_KEY) {
Write-Warning "Skipping Gemini tests (no API key)"
return
}
Write-Test "Testing Gemini text generation"
try {
$output = & $Z3edBin agent chat --provider gemini --prompt "Say 'Gemini works' and nothing else" 2>&1
if ($output -match "Gemini works") {
Write-Success "Gemini text generation works"
} else {
Write-Error "Gemini test failed"
Write-Host $output
}
} catch {
Write-Error "Gemini test threw exception: $_"
}
}
function Test-MultimodalVision {
Write-Section "Test 4: Multimodal Vision (Gemini)"
if (-not $env:GEMINI_API_KEY) {
Write-Warning "Skipping vision tests (no API key)"
return
}
Write-Test "Running multimodal vision test suite"
try {
$output = & $Z3edBin test --filter "*GeminiVision*" 2>&1
$outputStr = $output -join "`n"
if ($outputStr -match "PASSED") {
Write-Success "Multimodal vision tests passed"
} else {
Write-Warning "Vision tests completed with warnings"
}
} catch {
Write-Error "Vision test suite failed: $_"
}
}
function Test-LearnCommand {
Write-Section "Test 5: Learn Command (Knowledge Management)"
Write-Test "Testing preference storage"
try {
& $Z3edBin agent learn preference "test_key" "test_value" 2>&1 | Out-Null
Write-Success "Preference stored"
} catch {
Write-Error "Failed to store preference"
}
Write-Test "Testing context storage"
try {
& $Z3edBin agent learn context "project" "YAZE ROM Editor test" 2>&1 | Out-Null
Write-Success "Project context stored"
} catch {
Write-Warning "Context storage failed"
}
Write-Test "Listing learned knowledge"
try {
& $Z3edBin agent learn list 2>&1 | Out-Null
Write-Success "Knowledge retrieval works"
} catch {
Write-Warning "Knowledge list failed"
}
}
function Test-GUIAutomationPrep {
Write-Section "Test 6: GUI Automation (Preparation)"
Write-Test "Checking gRPC test harness support"
$helpOutput = & $Z3edBin --help 2>&1
if ($helpOutput -match "grpc") {
Write-Success "gRPC support compiled in"
} else {
Write-Warning "gRPC support not detected"
}
Write-Test "Verifying screenshot utils"
if (Test-Path "build-windows\lib\Debug\yaze_core_lib.lib") {
Write-Success "Core library with screenshot utils found"
} else {
Write-Warning "Core library not found (needed for GUI automation)"
}
Write-Warning "Full GUI automation test requires YAZE to be running"
Write-Warning " Start YAZE GUI, then run: .\scripts\test_ai_gui_control.ps1"
}
function Write-Summary {
Write-Section "Test Summary"
Write-Host "✓ Basic z3ed functionality verified" -ForegroundColor Green
Write-Host "✓ AI agent system operational" -ForegroundColor Green
if ($env:GEMINI_API_KEY) {
Write-Host "✓ Multimodal vision capabilities tested" -ForegroundColor Green
} else {
Write-Host "⚠ Vision tests skipped (no API key)" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "Next Steps:" -ForegroundColor Cyan
Write-Host " 1. Start YAZE GUI: " -NoNewline -ForegroundColor Cyan
Write-Host $YazeBin -ForegroundColor Green
Write-Host " 2. Test collaboration: " -NoNewline -ForegroundColor Cyan
Write-Host ".\scripts\test_collaboration.ps1" -ForegroundColor Green
Write-Host " 3. Test GUI control: " -NoNewline -ForegroundColor Cyan
Write-Host ".\scripts\test_ai_gui_control.ps1" -ForegroundColor Green
Write-Host ""
Write-Host "For full feature testing:" -ForegroundColor Cyan
Write-Host " - Set GEMINI_API_KEY for vision tests"
Write-Host " - Start Ollama server for local AI"
Write-Host " - Provide test ROM at: $TestRom"
}
# ============================================================================
# Main Execution
# ============================================================================
Write-Header
# Change to script directory's parent
Set-Location (Join-Path $PSScriptRoot "..")
Test-Prerequisites
Test-Z3edBasic
Test-AIAgentOllama
Test-AIAgentGemini
Test-MultimodalVision
Test-LearnCommand
Test-GUIAutomationPrep
Write-Summary
Write-Host ""
Write-Host "╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║ ✓ AI Features Test Complete! ║" -ForegroundColor Green
Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Green
Write-Host ""

277
scripts/test_ai_features.sh Executable file
View File

@@ -0,0 +1,277 @@
#!/bin/bash
# YAZE AI Features Test Script for macOS/Linux
# Tests AI agent, multimodal vision, and GUI automation capabilities
set -e
# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
# Configuration
YAZE_BIN="${YAZE_BIN:-./build/bin/yaze}"
Z3ED_BIN="${Z3ED_BIN:-./build/bin/z3ed}"
TEST_ROM="${TEST_ROM:-./zelda3.sfc}"
GEMINI_API_KEY="${GEMINI_API_KEY:-}"
SCREENSHOTS_DIR="./test_screenshots"
function print_header() {
echo -e "\n${CYAN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ YAZE AI Features Test Suite (macOS/Linux) ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════════╝${NC}\n"
}
function print_section() {
echo -e "\n${BLUE}$1${NC}"
echo -e "${BLUE}$(printf '─%.0s' {1..64})${NC}"
}
function print_test() {
echo -e "${CYAN} Testing:${NC} $1"
}
function print_success() {
echo -e "${GREEN}$1${NC}"
}
function print_warning() {
echo -e "${YELLOW}$1${NC}"
}
function print_error() {
echo -e "${RED}$1${NC}"
}
function check_prerequisites() {
print_section "Checking Prerequisites"
local all_ok=true
# Check binaries
if [[ -f "$YAZE_BIN" ]]; then
print_success "YAZE GUI found: $YAZE_BIN"
else
print_error "YAZE GUI not found: $YAZE_BIN"
all_ok=false
fi
if [[ -f "$Z3ED_BIN" ]]; then
print_success "z3ed CLI found: $Z3ED_BIN"
else
print_error "z3ed CLI not found: $Z3ED_BIN"
all_ok=false
fi
# Check ROM
if [[ -f "$TEST_ROM" ]]; then
print_success "Test ROM found: $TEST_ROM"
else
print_warning "Test ROM not found: $TEST_ROM (some tests will be skipped)"
fi
# Check Gemini API Key
if [[ -n "$GEMINI_API_KEY" ]]; then
print_success "Gemini API key configured"
else
print_warning "GEMINI_API_KEY not set (vision tests will be skipped)"
print_warning " Set with: export GEMINI_API_KEY='your-key-here'"
fi
# Check screenshot directory
mkdir -p "$SCREENSHOTS_DIR"
print_success "Screenshot directory ready: $SCREENSHOTS_DIR"
if [[ "$all_ok" == "false" ]]; then
echo ""
print_error "Prerequisites not met. Please build the project first:"
echo " cmake --preset mac-ai"
echo " cmake --build build --target yaze z3ed"
exit 1
fi
}
function test_z3ed_basic() {
print_section "Test 1: z3ed Basic Functionality"
print_test "Checking z3ed version"
if "$Z3ED_BIN" --version &>/dev/null; then
print_success "z3ed executable works"
else
print_error "z3ed --version failed"
return 1
fi
print_test "Checking z3ed help"
if "$Z3ED_BIN" --help &>/dev/null; then
print_success "z3ed help accessible"
else
print_warning "z3ed help command failed"
fi
}
function test_ai_agent_ollama() {
print_section "Test 2: AI Agent (Ollama)"
print_test "Checking if Ollama is running"
if curl -s http://localhost:11434/api/tags &>/dev/null; then
print_success "Ollama server is running"
print_test "Testing agent chat with Ollama"
if "$Z3ED_BIN" agent chat --model "llama3.2:latest" --prompt "Say 'test successful' and nothing else" 2>&1 | grep -i "test successful" &>/dev/null; then
print_success "Ollama agent responded correctly"
else
print_warning "Ollama agent test inconclusive"
fi
else
print_warning "Ollama not running (skip with: ollama serve)"
fi
}
function test_ai_agent_gemini() {
print_section "Test 3: AI Agent (Gemini)"
if [[ -z "$GEMINI_API_KEY" ]]; then
print_warning "Skipping Gemini tests (no API key)"
return 0
fi
print_test "Testing Gemini text generation"
local response
response=$("$Z3ED_BIN" agent chat --provider gemini --prompt "Say 'Gemini works' and nothing else" 2>&1)
if echo "$response" | grep -i "gemini works" &>/dev/null; then
print_success "Gemini text generation works"
else
print_error "Gemini test failed"
echo "$response"
fi
}
function test_multimodal_vision() {
print_section "Test 4: Multimodal Vision (Gemini)"
if [[ -z "$GEMINI_API_KEY" ]]; then
print_warning "Skipping vision tests (no API key)"
return 0
fi
print_test "Running multimodal vision test suite"
if "$Z3ED_BIN" test --filter "*GeminiVision*" 2>&1 | tee /tmp/vision_test.log; then
if grep -q "PASSED" /tmp/vision_test.log; then
print_success "Multimodal vision tests passed"
else
print_warning "Vision tests completed with warnings"
fi
else
print_error "Vision test suite failed"
fi
}
function test_learn_command() {
print_section "Test 5: Learn Command (Knowledge Management)"
print_test "Testing preference storage"
if "$Z3ED_BIN" agent learn preference "test_key" "test_value" &>/dev/null; then
print_success "Preference stored"
else
print_error "Failed to store preference"
fi
print_test "Testing context storage"
if "$Z3ED_BIN" agent learn context "project" "YAZE ROM Editor test" &>/dev/null; then
print_success "Project context stored"
else
print_warning "Context storage failed"
fi
print_test "Listing learned knowledge"
if "$Z3ED_BIN" agent learn list &>/dev/null; then
print_success "Knowledge retrieval works"
else
print_warning "Knowledge list failed"
fi
}
function test_gui_automation_preparation() {
print_section "Test 6: GUI Automation (Preparation)"
print_test "Checking gRPC test harness support"
if "$Z3ED_BIN" --help 2>&1 | grep -i "grpc" &>/dev/null; then
print_success "gRPC support compiled in"
else
print_warning "gRPC support not detected"
fi
print_test "Verifying screenshot utils"
if [[ -f "build/lib/libyaze_core_lib.a" ]]; then
print_success "Core library with screenshot utils found"
else
print_warning "Core library not found (needed for GUI automation)"
fi
print_warning "Full GUI automation test requires YAZE to be running"
print_warning " Start YAZE GUI, then run: ./scripts/test_ai_gui_control.sh"
}
function test_action_parser() {
print_section "Test 7: AI Action Parser"
print_test "Testing natural language parsing"
# This would need a test binary or z3ed command
print_warning "Action parser integration test not yet implemented"
print_warning " Verify manually: AIActionParser can parse commands"
}
function print_summary() {
print_section "Test Summary"
echo -e "${GREEN}✓ Basic z3ed functionality verified${NC}"
echo -e "${GREEN}✓ AI agent system operational${NC}"
if [[ -n "$GEMINI_API_KEY" ]]; then
echo -e "${GREEN}✓ Multimodal vision capabilities tested${NC}"
else
echo -e "${YELLOW}⚠ Vision tests skipped (no API key)${NC}"
fi
echo ""
echo -e "${CYAN}Next Steps:${NC}"
echo -e " 1. Start YAZE GUI: ${GREEN}$YAZE_BIN${NC}"
echo -e " 2. Test collaboration: ${GREEN}./scripts/test_collaboration.sh${NC}"
echo -e " 3. Test GUI control: ${GREEN}./scripts/test_ai_gui_control.sh${NC}"
echo ""
echo -e "${CYAN}For full feature testing:${NC}"
echo -e " - Set GEMINI_API_KEY for vision tests"
echo -e " - Start Ollama server for local AI"
echo -e " - Provide test ROM at: $TEST_ROM"
}
# ============================================================================
# Main Execution
# ============================================================================
print_header
cd "$(dirname "$0")/.."
check_prerequisites
test_z3ed_basic
test_ai_agent_ollama
test_ai_agent_gemini
test_multimodal_vision
test_learn_command
test_gui_automation_preparation
test_action_parser
print_summary
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✓ AI Features Test Complete! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""

View File

@@ -1,150 +0,0 @@
#!/usr/bin/env python3
"""
Asar Integration Test Script for Yaze
Tests the Asar 65816 assembler integration with real ROM files
"""
import os
import sys
import subprocess
import shutil
import tempfile
from pathlib import Path
def find_project_root():
"""Find the yaze project root directory"""
current = Path(__file__).parent
while current != current.parent:
if (current / "CMakeLists.txt").exists():
return current
current = current.parent
raise FileNotFoundError("Could not find yaze project root")
def main():
print("🧪 Yaze Asar Integration Test")
print("=" * 50)
project_root = find_project_root()
build_dir = project_root / "build_test"
rom_path = build_dir / "bin" / "zelda3.sfc"
test_patch = project_root / "test" / "assets" / "test_patch.asm"
# Check if ROM file exists
if not rom_path.exists():
print(f"❌ ROM file not found: {rom_path}")
print(" Please ensure you have a test ROM at the expected location")
return 1
print(f"✅ Found ROM file: {rom_path}")
print(f" Size: {rom_path.stat().st_size:,} bytes")
# Check if test patch exists
if not test_patch.exists():
print(f"❌ Test patch not found: {test_patch}")
return 1
print(f"✅ Found test patch: {test_patch}")
# Check if z3ed tool exists
z3ed_path = build_dir / "bin" / "z3ed"
if not z3ed_path.exists():
print(f"❌ z3ed CLI tool not found: {z3ed_path}")
print(" Run: cmake --build build_test --target z3ed")
return 1
print(f"✅ Found z3ed CLI tool: {z3ed_path}")
# Create temporary directory for testing
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
test_rom_path = temp_path / "test_rom.sfc"
patched_rom_path = temp_path / "patched_rom.sfc"
# Copy ROM to temporary location
shutil.copy2(rom_path, test_rom_path)
print(f"📋 Copied ROM to: {test_rom_path}")
# Test 1: Apply patch using z3ed CLI
print("\n🔧 Test 1: Applying patch with z3ed CLI")
try:
cmd = [str(z3ed_path), "asar", str(test_patch), str(test_rom_path)]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode == 0:
print("✅ Patch applied successfully!")
if result.stdout:
print(f" Output: {result.stdout.strip()}")
else:
print(f"❌ Patch failed with return code: {result.returncode}")
if result.stderr:
print(f" Error: {result.stderr.strip()}")
return 1
except subprocess.TimeoutExpired:
print("❌ Patch operation timed out")
return 1
except Exception as e:
print(f"❌ Error running patch: {e}")
return 1
# Test 2: Verify ROM was modified
print("\n🔍 Test 2: Verifying ROM modification")
original_size = rom_path.stat().st_size
modified_size = test_rom_path.stat().st_size
print(f" Original ROM size: {original_size:,} bytes")
print(f" Modified ROM size: {modified_size:,} bytes")
# Read first few bytes to check for changes
with open(rom_path, 'rb') as orig_file, open(test_rom_path, 'rb') as mod_file:
orig_bytes = orig_file.read(1024)
mod_bytes = mod_file.read(1024)
if orig_bytes != mod_bytes:
print("✅ ROM was successfully modified!")
# Count different bytes
diff_count = sum(1 for a, b in zip(orig_bytes, mod_bytes) if a != b)
print(f" {diff_count} bytes differ in first 1KB")
else:
print("⚠️ No differences detected in first 1KB")
print(" (Patch may have been applied to a different region)")
# Test 3: Run unit tests if available
yaze_test_path = build_dir / "bin" / "yaze_test"
if yaze_test_path.exists():
print("\n🧪 Test 3: Running Asar unit tests")
try:
# Run only the Asar-related tests
cmd = [str(yaze_test_path), "--gtest_filter=*Asar*", "--gtest_brief=1"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
print(f" Exit code: {result.returncode}")
if result.stdout:
# Extract test results
lines = result.stdout.split('\n')
for line in lines:
if 'PASSED' in line or 'FAILED' in line or 'RUN' in line:
print(f" {line}")
if result.returncode == 0:
print("✅ Unit tests passed!")
else:
print("⚠️ Some unit tests failed (this may be expected)")
except subprocess.TimeoutExpired:
print("❌ Unit tests timed out")
except Exception as e:
print(f"⚠️ Error running unit tests: {e}")
else:
print("\n⚠️ Test 3: yaze_test executable not found")
print("\n🎉 Asar integration test completed!")
print("\nNext steps:")
print("- Run full test suite with: ctest --test-dir build_test")
print("- Test Asar functionality in the main yaze application")
print("- Create custom assembly patches for your ROM hacking projects")
return 0
if __name__ == "__main__":
sys.exit(main())

172
scripts/test_dungeon_loading.sh Executable file
View File

@@ -0,0 +1,172 @@
#!/bin/bash
# Test script for dungeon room loading (torches, blocks, doors, pits)
# Usage: ./scripts/test_dungeon_loading.sh [rom_file]
set -e
# Configuration
ROM_FILE="${1:-zelda3.sfc}"
BUILD_DIR="build/bin"
LOG_FILE="dungeon_loading_test.log"
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Dungeon Room Loading Test Script${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
# Check if ROM file exists
if [ ! -f "$ROM_FILE" ]; then
echo -e "${RED}ERROR: ROM file not found: $ROM_FILE${NC}"
echo "Usage: $0 [path/to/zelda3.sfc]"
exit 1
fi
# Check if yaze binary exists
if [ ! -f "$BUILD_DIR/yaze" ]; then
echo -e "${RED}ERROR: yaze binary not found at $BUILD_DIR/yaze${NC}"
echo "Please build yaze first: cmake --build build"
exit 1
fi
echo -e "${YELLOW}ROM File:${NC} $ROM_FILE"
echo -e "${YELLOW}Log File:${NC} $LOG_FILE"
echo ""
# Test 1: Launch with torch-heavy rooms
echo -e "${GREEN}Test 1: Loading rooms with torches${NC}"
echo "Starting yaze with Room 8 (Ganon's Tower - Torch 2)..."
$BUILD_DIR/yaze \
--rom_file="$ROM_FILE" \
--debug \
--log_file="$LOG_FILE" \
--editor=Dungeon \
--cards="Room 8,Room 173" &
YAZE_PID=$!
echo "yaze PID: $YAZE_PID"
# Give it a moment to start and load
sleep 3
# Check if process is still running
if ! ps -p $YAZE_PID > /dev/null 2>&1; then
echo -e "${RED}FAILED: yaze crashed or exited${NC}"
echo "Check log file: $LOG_FILE"
exit 1
fi
echo -e "${GREEN}SUCCESS: yaze is running${NC}"
echo ""
# Analyze log file
echo -e "${GREEN}Analyzing debug log...${NC}"
echo ""
# Check for torch loading
TORCH_COUNT=$(grep -c "LoadTorches:" "$LOG_FILE" || true)
TORCH_LOADED=$(grep -c "Loaded torch at" "$LOG_FILE" || true)
echo -e "${YELLOW}Torches:${NC}"
echo " - LoadTorches called: $TORCH_COUNT times"
echo " - Torches loaded: $TORCH_LOADED"
if [ $TORCH_LOADED -gt 0 ]; then
echo -e " ${GREEN}✓ Torches successfully loaded${NC}"
# Show sample torch data
echo " Sample torch data:"
grep "Loaded torch at" "$LOG_FILE" | head -3 | sed 's/^/ /'
else
echo -e " ${YELLOW}⚠ No torches loaded (may be normal for these rooms)${NC}"
fi
echo ""
# Check for block loading
BLOCK_COUNT=$(grep -c "LoadBlocks:" "$LOG_FILE" || true)
BLOCK_LOADED=$(grep -c "Loaded block at" "$LOG_FILE" || true)
echo -e "${YELLOW}Blocks:${NC}"
echo " - LoadBlocks called: $BLOCK_COUNT times"
echo " - Blocks loaded: $BLOCK_LOADED"
if [ $BLOCK_LOADED -gt 0 ]; then
echo -e " ${GREEN}✓ Blocks successfully loaded${NC}"
echo " Sample block data:"
grep "Loaded block at" "$LOG_FILE" | head -3 | sed 's/^/ /'
else
echo -e " ${YELLOW}⚠ No blocks loaded (may be normal for these rooms)${NC}"
fi
echo ""
# Check for pit loading
PIT_COUNT=$(grep -c "LoadPits:" "$LOG_FILE" || true)
PIT_DEST=$(grep -c "Pit destination" "$LOG_FILE" || true)
echo -e "${YELLOW}Pits:${NC}"
echo " - LoadPits called: $PIT_COUNT times"
echo " - Pit destinations set: $PIT_DEST"
if [ $PIT_DEST -gt 0 ]; then
echo -e " ${GREEN}✓ Pit data successfully loaded${NC}"
echo " Sample pit data:"
grep "Pit destination" "$LOG_FILE" | head -3 | sed 's/^/ /'
else
echo -e " ${YELLOW}⚠ No pit data (may be normal)${NC}"
fi
echo ""
# Check for door loading
DOOR_COUNT=$(grep -c "LoadDoors" "$LOG_FILE" || true)
echo -e "${YELLOW}Doors:${NC}"
echo " - LoadDoors called: $DOOR_COUNT times"
if [ $DOOR_COUNT -gt 0 ]; then
echo -e " ${GREEN}✓ Door loading called${NC}"
echo " Sample door log:"
grep "LoadDoors" "$LOG_FILE" | head -3 | sed 's/^/ /'
else
echo -e " ${RED}✗ LoadDoors not called${NC}"
fi
echo ""
# Check for errors
ERROR_COUNT=$(grep -i "error\|segmentation\|crash" "$LOG_FILE" | wc -l || true)
if [ $ERROR_COUNT -gt 0 ]; then
echo -e "${RED}⚠ Errors found in log:${NC}"
grep -i "error\|segmentation\|crash" "$LOG_FILE" | sed 's/^/ /'
else
echo -e "${GREEN}✓ No errors found in log${NC}"
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Test Summary${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "yaze is still running (PID: $YAZE_PID)"
echo "You can now manually test the dungeon editor."
echo ""
echo "To view live log updates:"
echo " tail -f $LOG_FILE | grep -E 'Load(Torches|Blocks|Pits|Doors)|Loaded (torch|block)'"
echo ""
echo "To stop yaze:"
echo " kill $YAZE_PID"
echo ""
echo "Full log available at: $LOG_FILE"
echo ""
# Don't automatically kill yaze - let user test manually
read -p "Press Enter to stop yaze and exit..."
kill $YAZE_PID 2>/dev/null || true
echo "yaze stopped."
exit 0

101
scripts/test_gui_tools.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
# Quick test script for GUI automation tools
echo "=== Testing GUI Automation Tools ==="
echo ""
# Set up environment
export AI_PROVIDER=mock
export MOCK_RESPONSE="Testing GUI tools"
cd /Users/scawful/Code/yaze
echo "1. Testing gui-discover tool..."
echo "Query: What buttons are available?"
# This would normally trigger the AI to call gui-discover
# For now, we'll just verify the tool exists in the dispatcher
echo ""
echo "2. Testing gui-click tool..."
echo "Query: Click the Draw button"
echo ""
echo "3. Testing gui-place-tile tool..."
echo "Query: Place a tree at position 10, 15"
echo ""
echo "4. Testing gui-screenshot tool..."
echo "Query: Show me a screenshot"
echo ""
echo "=== Tool Registration Check ==="
echo "Checking if tools are registered in prompt_catalogue.yaml..."
grep -c "gui-place-tile" assets/agent/prompt_catalogue.yaml && echo "✓ gui-place-tile found"
grep -c "gui-click" assets/agent/prompt_catalogue.yaml && echo "✓ gui-click found"
grep -c "gui-discover" assets/agent/prompt_catalogue.yaml && echo "✓ gui-discover found"
grep -c "gui-screenshot" assets/agent/prompt_catalogue.yaml && echo "✓ gui-screenshot found"
echo ""
echo "=== Tool Dispatcher Check ==="
echo "Checking if tools are handled in tool_dispatcher.cc..."
grep -c "gui-place-tile" src/cli/service/agent/tool_dispatcher.cc && echo "✓ gui-place-tile dispatcher entry found"
grep -c "gui-click" src/cli/service/agent/tool_dispatcher.cc && echo "✓ gui-click dispatcher entry found"
grep -c "gui-discover" src/cli/service/agent/tool_dispatcher.cc && echo "✓ gui-discover dispatcher entry found"
grep -c "gui-screenshot" src/cli/service/agent/tool_dispatcher.cc && echo "✓ gui-screenshot dispatcher entry found"
echo ""
echo "=== Handler Implementation Check ==="
echo "Checking if handlers are implemented..."
grep -c "HandleGuiPlaceTileCommand" src/cli/handlers/agent/gui_tool_commands.cc && echo "✓ HandleGuiPlaceTileCommand implemented"
grep -c "HandleGuiClickCommand" src/cli/handlers/agent/gui_tool_commands.cc && echo "✓ HandleGuiClickCommand implemented"
grep -c "HandleGuiDiscoverToolCommand" src/cli/handlers/agent/gui_tool_commands.cc && echo "✓ HandleGuiDiscoverToolCommand implemented"
grep -c "HandleGuiScreenshotCommand" src/cli/handlers/agent/gui_tool_commands.cc && echo "✓ HandleGuiScreenshotCommand implemented"
echo ""
echo "=== System Prompt Check ==="
if [ -f "assets/agent/gui_automation_instructions.txt" ]; then
echo "✓ GUI automation instructions found"
echo " Lines: $(wc -l < assets/agent/gui_automation_instructions.txt)"
else
echo "✗ GUI automation instructions not found"
fi
echo ""
echo "=== Build Check ==="
if [ -f "build/bin/z3ed" ]; then
echo "✓ z3ed binary exists"
ls -lh build/bin/z3ed | awk '{print " Size:", $5}'
else
echo "✗ z3ed binary not found"
fi
echo ""
echo "=== Environment Check ==="
echo "Ollama availability:"
if command -v ollama &> /dev/null; then
echo " ✓ ollama command found"
ollama list 2>/dev/null | head -5 || echo " (ollama not running)"
else
echo " ✗ ollama not installed"
echo " Install with: brew install ollama"
fi
echo ""
echo "Gemini API key:"
if [ -n "$GEMINI_API_KEY" ]; then
echo " ✓ GEMINI_API_KEY is set"
else
echo " ⚠ GEMINI_API_KEY not set (optional)"
fi
echo ""
echo "=== Ready to Test! ==="
echo ""
echo "To start testing:"
echo "1. Terminal 1: ./build/bin/yaze assets/zelda3.sfc --enable-test-harness"
echo "2. Terminal 2: export AI_PROVIDER=ollama && ./build/bin/z3ed agent chat --rom assets/zelda3.sfc"
echo "3. Try: 'What buttons are available in the Overworld editor?'"
echo ""
echo "Or use Gemini:"
echo "2. Terminal 2: export AI_PROVIDER=gemini && export GEMINI_API_KEY='...' && ./build/bin/z3ed agent chat --rom assets/zelda3.sfc"
echo ""

View File

@@ -1,132 +0,0 @@
# YAZE Windows Build Validation Script
# This script validates that the Windows build environment is properly set up
# Set error handling
$ErrorActionPreference = "Continue"
# Colors for output
$Colors = @{
Success = "Green"
Warning = "Yellow"
Error = "Red"
Info = "Cyan"
White = "White"
}
function Write-Status {
param([string]$Message, [string]$Color = "White")
Write-Host $Message -ForegroundColor $Colors[$Color]
}
function Test-Command {
param([string]$Command)
try {
$null = Get-Command $Command -ErrorAction Stop
return $true
} catch {
return $false
}
}
function Test-VisualStudio {
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (Test-Path $vsWhere) {
$vsInstall = & $vsWhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
if ($vsInstall) {
$msbuildPath = Join-Path $vsInstall "MSBuild\Current\Bin\MSBuild.exe"
if (Test-Path $msbuildPath) {
return $true
}
}
}
return $false
}
# Main script
Write-Status "========================================" "Info"
Write-Status "YAZE Windows Build Validation" "Info"
Write-Status "========================================" "Info"
$allGood = $true
# Check if we're in the right directory
if (-not (Test-Path "YAZE.sln")) {
Write-Status "✗ YAZE.sln not found" "Error"
$allGood = $false
} else {
Write-Status "✓ YAZE.sln found" "Success"
}
# Check for vcpkg.json
if (-not (Test-Path "vcpkg.json")) {
Write-Status "✗ vcpkg.json not found" "Error"
$allGood = $false
} else {
Write-Status "✓ vcpkg.json found" "Success"
}
# Check for Visual Studio
if (Test-VisualStudio) {
Write-Status "✓ Visual Studio 2022 with C++ workload found" "Success"
} else {
Write-Status "✗ Visual Studio 2022 with C++ workload not found" "Error"
$allGood = $false
}
# Check for Git
if (Test-Command "git") {
$gitVersion = & git --version
Write-Status "✓ Git found: $gitVersion" "Success"
} else {
Write-Status "✗ Git not found" "Error"
$allGood = $false
}
# Check for Python
if (Test-Command "python") {
$pythonVersion = & python --version
Write-Status "✓ Python found: $pythonVersion" "Success"
} else {
Write-Status "✗ Python not found" "Error"
$allGood = $false
}
# Check for vcpkg
if (Test-Path "vcpkg\vcpkg.exe") {
Write-Status "✓ vcpkg found and bootstrapped" "Success"
} else {
Write-Status "✗ vcpkg not found or not bootstrapped" "Error"
$allGood = $false
}
# Check for generated project files
if (Test-Path "YAZE.vcxproj") {
Write-Status "✓ Visual Studio project file found" "Success"
} else {
Write-Status "✗ Visual Studio project file not found" "Error"
Write-Status " Run: python scripts/generate-vs-projects.py" "Info"
$allGood = $false
}
# Check for config file
if (Test-Path "yaze_config.h") {
Write-Status "✓ yaze_config.h found" "Success"
} else {
Write-Status "⚠ yaze_config.h not found (will be generated during build)" "Warning"
}
Write-Status "========================================" "Info"
if ($allGood) {
Write-Status "✓ All checks passed! Build environment is ready." "Success"
Write-Status ""
Write-Status "You can now build YAZE using:" "Warning"
Write-Status " .\scripts\build-windows.ps1" "White"
Write-Status " or" "White"
Write-Status " .\scripts\build-windows.bat" "White"
} else {
Write-Status "✗ Some checks failed. Please fix the issues above." "Error"
Write-Status ""
Write-Status "Run the setup script to fix issues:" "Warning"
Write-Status " .\scripts\setup-windows-dev.ps1" "White"
}
Write-Status "========================================" "Info"

View File

@@ -0,0 +1,462 @@
# YAZE Build Environment Verification Script for Windows/Visual Studio CMake Users
# This script verifies the build environment is properly configured and ready to build
# Run this before building to catch common configuration issues early
param(
[switch]$Verbose,
[switch]$FixIssues,
[switch]$CleanCache
)
$ErrorActionPreference = "Continue"
$script:issuesFound = @()
$script:warnings = @()
$script:success = @()
function Write-Status {
param($Message, $Type = "Info")
$timestamp = Get-Date -Format "HH:mm:ss"
switch ($Type) {
"Success" { Write-Host "[$timestamp] ✓ " -ForegroundColor Green -NoNewline; Write-Host $Message }
"Error" { Write-Host "[$timestamp] ✗ " -ForegroundColor Red -NoNewline; Write-Host $Message }
"Warning" { Write-Host "[$timestamp] ⚠ " -ForegroundColor Yellow -NoNewline; Write-Host $Message }
"Info" { Write-Host "[$timestamp] " -ForegroundColor Cyan -NoNewline; Write-Host $Message }
"Step" { Write-Host "`n[$timestamp] ▶ " -ForegroundColor Blue -NoNewline; Write-Host $Message -ForegroundColor White }
}
}
function Test-Command {
param($Command)
try {
if (Get-Command $Command -ErrorAction SilentlyContinue) {
return $true
}
} catch {
return $false
}
return $false
}
function Get-CMakeVersion {
try {
$output = & cmake --version 2>&1 | Select-Object -First 1
# Handle various CMake version output formats
if ($output -match "cmake version ([0-9]+\.[0-9]+\.[0-9]+)") {
return $matches[1]
}
# Try alternative format (some versions print differently)
if ($output -match "([0-9]+\.[0-9]+\.[0-9]+)") {
return $matches[1]
}
} catch {
return $null
}
return $null
}
function Test-GitSubmodules {
$submodules = @(
"src/lib/SDL",
"src/lib/abseil-cpp",
"src/lib/asar",
"src/lib/imgui",
"third_party/json",
"third_party/httplib"
)
$allPresent = $true
foreach ($submodule in $submodules) {
$path = Join-Path $PSScriptRoot ".." $submodule
if (-not (Test-Path $path)) {
Write-Status "Submodule missing: $submodule" "Error"
$script:issuesFound += "Missing submodule: $submodule"
$allPresent = $false
} elseif ((Get-ChildItem $path -Force | Measure-Object).Count -eq 0) {
Write-Status "Submodule empty: $submodule" "Error"
$script:issuesFound += "Empty submodule: $submodule"
$allPresent = $false
} elseif ($Verbose) {
Write-Status "Submodule found: $submodule" "Success"
}
}
return $allPresent
}
function Test-GitConfig {
Write-Status "Checking Git for Windows configuration..." "Step"
$gitOk = $true
# Check for core.autocrlf
try {
$autocrlf = git config --get core.autocrlf
if ($autocrlf -ne "false") {
Write-Status "Git 'core.autocrlf' is '$autocrlf'. Recommended setting is 'false' for cross-platform projects." "Warning"
$script:warnings += "Git 'core.autocrlf' is not 'false'. This can cause line ending issues."
if ($FixIssues) {
Write-Status "Attempting to set 'core.autocrlf' to 'false' globally..." "Info"
git config --global core.autocrlf false
if ($LASTEXITCODE -eq 0) {
Write-Status "Successfully set 'core.autocrlf' to 'false'." "Success"
} else {
Write-Status "Failed to set 'core.autocrlf'." "Error"
$script:issuesFound += "Failed to automatically set 'core.autocrlf'."
}
}
$gitOk = $false
} else {
Write-Status "'core.autocrlf' is correctly set to 'false'." "Success"
}
} catch {
Write-Status "Could not check Git 'core.autocrlf' setting." "Warning"
}
# Check for core.longpaths
try {
$longpaths = git config --get core.longpaths
if ($longpaths -ne "true") {
Write-Status "Git 'core.longpaths' is not 'true'. This can cause build failures with deep file paths." "Warning"
$script:warnings += "Git 'core.longpaths' is not 'true'. This is highly recommended on Windows."
if ($FixIssues) {
Write-Status "Attempting to set 'core.longpaths' to 'true' globally..." "Info"
git config --global core.longpaths true
if ($LASTEXITCODE -eq 0) {
Write-Status "Successfully set 'core.longpaths' to 'true'." "Success"
} else {
Write-Status "Failed to set 'core.longpaths'." "Error"
$script:issuesFound += "Failed to automatically set 'core.longpaths'."
}
}
$gitOk = $false
} else {
Write-Status "'core.longpaths' is correctly set to 'true'." "Success"
}
} catch {
Write-Status "Could not check Git 'core.longpaths' setting." "Warning"
}
return $gitOk
}
function Test-Vcpkg {
$vcpkgPath = Join-Path $PSScriptRoot ".." "vcpkg"
$vcpkgExe = Join-Path $vcpkgPath "vcpkg.exe"
if (Test-Path $vcpkgPath) {
if (Test-Path $vcpkgExe) {
Write-Status "vcpkg found and bootstrapped" "Success"
$script:success += "vcpkg available for dependency management"
try {
$vcpkgVersion = & $vcpkgExe version 2>&1 | Select-Object -First 1
Write-Status "vcpkg version: $vcpkgVersion" "Info"
} catch {
Write-Status "vcpkg executable found but version check failed" "Warning"
}
return $true
} else {
Write-Status "vcpkg directory exists but not bootstrapped" "Warning"
$script:warnings += "vcpkg not bootstrapped - run: vcpkg\bootstrap-vcpkg.bat"
return $false
}
} else {
Write-Status "vcpkg not found (optional, but recommended for gRPC)" "Info"
$script:warnings += "vcpkg not installed. For faster builds with gRPC, consider running scripts\setup-vcpkg-windows.ps1"
return $false
}
}
function Test-CMakeCache {
$buildDirs = @("build", "build-windows", "build-test", "build-ai", "out/build")
$cacheIssues = $false
foreach ($dir in $buildDirs) {
$cachePath = Join-Path $PSScriptRoot ".." $dir "CMakeCache.txt"
if (Test-Path $cachePath) {
$cacheAge = (Get-Date) - (Get-Item $cachePath).LastWriteTime
if ($cacheAge.TotalDays -gt 7) {
Write-Status "CMake cache in '$dir' is $([math]::Round($cacheAge.TotalDays)) days old" "Warning"
$script:warnings += "Old CMake cache in '$dir'"
$cacheIssues = $true
} elseif ($Verbose) {
Write-Status "CMake cache in '$dir' is recent" "Success"
}
}
}
return -not $cacheIssues
}
function Clean-CMakeCache {
param([switch]$Force)
Write-Status "Cleaning CMake cache and build directories..." "Step"
$buildDirs = @("build", "build_test", "build-ai", "build_rooms", "out")
$cleaned = $false
foreach ($dir in $buildDirs) {
$fullPath = Join-Path $PSScriptRoot ".." $dir
if (Test-Path $fullPath) {
Write-Status "Removing '$fullPath'..." "Info"
try {
Remove-Item -Recurse -Force $fullPath -ErrorAction Stop
$cleaned = $true
Write-Status " ✓ Removed '$dir'" "Success"
} catch {
Write-Status " ✗ Failed to remove '$dir`: $_" "Error"
$script:warnings += "Could not fully clean '$dir' (some files may be locked)"
}
}
}
# Clean CMake generated files in root
$cmakeFiles = @(
"CMakeCache.txt",
"cmake_install.cmake",
"compile_commands.json"
)
foreach ($file in $cmakeFiles) {
$fullPath = Join-Path $PSScriptRoot ".." $file
if (Test-Path $fullPath) {
Write-Status "Removing root '$file'..." "Info"
Remove-Item -Force $fullPath -ErrorAction SilentlyContinue
}
}
if ($cleaned) {
Write-Status "CMake cache cleaned successfully" "Success"
$script:success += "Build directories cleaned. A fresh build is recommended."
} else {
Write-Status "No build directories found to clean" "Info"
}
}
function Sync-GitSubmodules {
Write-Status "Syncing git submodules..." "Step"
Push-Location (Join-Path $PSScriptRoot "..")
try {
Write-Status "Running: git submodule sync --recursive" "Info"
$syncOutput = git submodule sync --recursive 2>&1
Write-Status "Running: git submodule update --init --recursive" "Info"
$updateOutput = git submodule update --init --recursive 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Status "Submodules synced successfully" "Success"
return $true
} else {
Write-Status "Git submodule commands completed with warnings" "Warning"
if ($Verbose) {
Write-Host $updateOutput -ForegroundColor Gray
}
return $true # Still return true as submodules may be partially synced
}
} catch {
Write-Status "Failed to sync submodules: $_" "Error"
return $false
} finally {
Pop-Location
}
}
# ============================================================================
# Main Verification Process
# ============================================================================
Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ YAZE Build Environment Verification for Visual Studio CMake ║" -ForegroundColor Cyan
Write-Host "╚════════════════════════════════════════════════════════════════╝`n" -ForegroundColor Cyan
$startTime = Get-Date
# Step 0: Handle Cache Cleaning
if ($CleanCache) {
Clean-CMakeCache
Write-Status "Cache cleaning complete. Please re-run without -CleanCache to verify." "Info"
exit 0
}
# Step 1: Check CMake
Write-Status "Checking CMake installation..." "Step"
if (Test-Command "cmake") {
$cmakeVersion = Get-CMakeVersion
if ($cmakeVersion) {
Write-Status "CMake found: version $cmakeVersion" "Success"
try {
$versionParts = $cmakeVersion.Split('.')
$major = [int]$versionParts[0]
$minor = [int]$versionParts[1]
if ($major -lt 3 -or ($major -eq 3 -and $minor -lt 16)) {
Write-Status "CMake version too old (need 3.16+)" "Error"
$script:issuesFound += "CMake version $cmakeVersion is below minimum 3.16"
}
} catch {
Write-Status "Could not parse CMake version: $cmakeVersion" "Warning"
$script:warnings += "Unable to verify CMake version requirement (need 3.16+)"
}
} else {
Write-Status "CMake found but version could not be determined" "Warning"
$script:warnings += "CMake version could not be parsed - ensure version 3.16+ is installed"
}
} else {
Write-Status "CMake not found in PATH" "Error"
$script:issuesFound += "CMake not installed or not in PATH"
}
# Step 2: Check Git
Write-Status "Checking Git installation..." "Step"
if (Test-Command "git") {
$gitVersion = (& git --version) -replace "git version ", ""
Write-Status "Git found: version $gitVersion" "Success"
Test-GitConfig
} else {
Write-Status "Git not found in PATH" "Error"
$script:issuesFound += "Git not installed or not in PATH"
}
# Step 3: Check Visual Studio
Write-Status "Checking Visual Studio installation..." "Step"
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (Test-Path $vswhere) {
$vsInstances = & $vswhere -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -format json | ConvertFrom-Json
if ($vsInstances) {
$vsInstance = if ($vsInstances -is [array]) { $vsInstances[0] } else { $vsInstances }
$vsVersion = $vsInstance.installationVersion
$vsPath = $vsInstance.installationPath
Write-Status "Visual Studio with C++ Desktop workload found: version $vsVersion" "Success"
Write-Status " Path: $vsPath" "Info"
$script:success += "Visual Studio C++ workload detected (version $vsVersion)"
} else {
Write-Status "Visual Studio found, but 'Desktop development with C++' workload is missing." "Error"
$script:issuesFound += "Visual Studio 'Desktop development with C++' workload not installed."
}
} else {
Write-Status "Visual Studio not found (vswhere.exe missing)" "Error"
$script:issuesFound += "Visual Studio installation not detected."
}
# Step 4: Check vcpkg
Test-Vcpkg | Out-Null
# Step 5: Check Git Submodules
Write-Status "Checking git submodules..." "Step"
$submodulesOk = Test-GitSubmodules
if ($submodulesOk) {
Write-Status "All required submodules appear to be present." "Success"
} else {
if ($FixIssues) {
Sync-GitSubmodules
Write-Status "Re-checking submodules after sync..." "Info"
$submodulesOk = Test-GitSubmodules
if ($submodulesOk) {
$script:success += "Submodules were successfully synced."
} else {
$script:issuesFound += "Submodule sync completed but some issues remain."
}
}
}
# Step 6: Check CMake Cache
Write-Status "Checking CMake cache..." "Step"
if (Test-CMakeCache) {
Write-Status "CMake cache appears up to date." "Success"
} else {
if ($FixIssues) {
Write-Host "`nCMake cache is older than 7 days. Clean it?" -ForegroundColor Yellow
Write-Host "This will remove all `build*` and `out` directories." -ForegroundColor Gray
$response = Read-Host "Continue? (Y/n)"
if ($response -eq "" -or $response -match "^[Yy]") {
Clean-CMakeCache
} else {
Write-Status "Skipping cache clean." "Info"
}
}
}
# ============================================================================
# Summary Report
# ============================================================================
$duration = (Get-Date) - $startTime
Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ Verification Summary ║" -ForegroundColor Cyan
Write-Host "╚════════════════════════════════════════════════════════════════╝`n" -ForegroundColor Cyan
Write-Host "Duration: $([math]::Round($duration.TotalSeconds, 2)) seconds`n"
if ($script:success.Count -gt 0) {
Write-Host "✓ Successes ($($script:success.Count)):" -ForegroundColor Green
foreach ($item in $script:success) {
Write-Host "$item" -ForegroundColor Green
}
Write-Host ""
}
if ($script:warnings.Count -gt 0) {
Write-Host "⚠ Warnings ($($script:warnings.Count)):" -ForegroundColor Yellow
foreach ($item in $script:warnings) {
Write-Host "$item" -ForegroundColor Yellow
}
Write-Host ""
}
if ($script:issuesFound.Count -gt 0) {
Write-Host "✗ Issues Found ($($script:issuesFound.Count)):" -ForegroundColor Red
foreach ($item in $script:issuesFound) {
Write-Host "$item" -ForegroundColor Red
}
Write-Host ""
Write-Host "╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Yellow
Write-Host "║ Troubleshooting Steps ║" -ForegroundColor Yellow
Write-Host "╚════════════════════════════════════════════════════════════════╝`n" -ForegroundColor Yellow
Write-Host "Some issues were found. Here are some common solutions:`n"
if ($script:issuesFound -join ' ' -match 'submodule') {
Write-Host " • Submodule problems:" -ForegroundColor White
Write-Host " Run 'git submodule update --init --recursive' in your terminal." -ForegroundColor Gray
Write-Host " Or, run this script again with the '-FixIssues' flag.`n"
}
if ($script:warnings -join ' ' -match 'cache') {
Write-Host " • Stale build files:" -ForegroundColor White
Write-Host " Your build directory is old and may cause strange errors." -ForegroundColor Gray
Write-Host " Run this script with the '-CleanCache' flag to delete all build files and start fresh.`n"
}
if ($script:issuesFound -join ' ' -match 'Visual Studio') {
Write-Host " • Visual Studio issues:" -ForegroundColor White
Write-Host " Open the 'Visual Studio Installer' and ensure the" -ForegroundColor Gray
Write-Host " 'Desktop development with C++' workload is installed.`n"
}
if ($script:warnings -join ' ' -match 'Git') {
Write-Host " • Git configuration:" -ForegroundColor White
Write-Host " Your Git settings might cause issues. For best results on Windows, run:" -ForegroundColor Gray
Write-Host " git config --global core.autocrlf false" -ForegroundColor Gray
Write-Host " git config --global core.longpaths true" -ForegroundColor Gray
Write-Host " Or, run this script again with the '-FixIssues' flag.`n"
}
Write-Host "If problems persist, check the build instructions in 'docs/B1-build-instructions.md'`n" -ForegroundColor Cyan
exit 1
} else {
Write-Host "╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║ ✓ Build Environment Ready for Development! ║" -ForegroundColor Green
Write-Host "╚════════════════════════════════════════════════════════════════╝`n" -ForegroundColor Green
Write-Host "Next Steps:" -ForegroundColor Cyan
Write-Host " Visual Studio (Recommended):" -ForegroundColor White
Write-Host " 1. Open Visual Studio 2022." -ForegroundColor Gray
Write-Host " 2. Select 'File -> Open -> Folder...' and choose the 'yaze' directory." -ForegroundColor Gray
Write-Host " 3. Select a Windows preset (e.g., 'win-dbg') from the dropdown." -ForegroundColor Gray
Write-Host " 4. Press F5 to build and debug.`n" -ForegroundColor Gray
Write-Host " Command Line:" -ForegroundColor White
Write-Host " cmake --preset win-dbg" -ForegroundColor Gray
Write-Host " cmake --build --preset win-dbg`n" -ForegroundColor Gray
exit 0
}

View File

@@ -0,0 +1,458 @@
#!/bin/bash
# YAZE Build Environment Verification Script for Unix/macOS
# This script verifies the build environment is properly configured and ready to build
# Run this before building to catch common configuration issues early
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Flags
VERBOSE=0
FIX_ISSUES=0
CLEAN_CACHE=0
# Counters
ISSUES_FOUND=()
WARNINGS=()
SUCCESS=()
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-v|--verbose)
VERBOSE=1
shift
;;
-f|--fix)
FIX_ISSUES=1
shift
;;
-c|--clean)
CLEAN_CACHE=1
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -v, --verbose Verbose output"
echo " -f, --fix Automatically fix issues"
echo " -c, --clean Clean CMake cache"
echo " -h, --help Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
function write_status() {
local message="$1"
local type="${2:-Info}"
local timestamp=$(date +"%H:%M:%S")
case "$type" in
Success)
echo -e "[$timestamp] ${GREEN}${NC} $message"
;;
Error)
echo -e "[$timestamp] ${RED}${NC} $message"
;;
Warning)
echo -e "[$timestamp] ${YELLOW}${NC} $message"
;;
Info)
echo -e "[$timestamp] ${CYAN}${NC} $message"
;;
Step)
echo -e "\n[$timestamp] ${BLUE}${NC} $message"
;;
esac
}
function test_command() {
command -v "$1" &> /dev/null
}
function get_cmake_version() {
if test_command cmake; then
cmake --version 2>&1 | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
fi
}
function test_git_submodules() {
local submodules=(
"src/lib/SDL"
"src/lib/abseil-cpp"
"src/lib/asar"
"src/lib/imgui"
"third_party/json"
"third_party/httplib"
)
local all_present=1
for submodule in "${submodules[@]}"; do
if [[ ! -d "$submodule" ]] || [[ -z "$(ls -A "$submodule" 2>/dev/null)" ]]; then
write_status "Submodule missing or empty: $submodule" "Error"
ISSUES_FOUND+=("Missing/empty submodule: $submodule")
all_present=0
elif [[ $VERBOSE -eq 1 ]]; then
write_status "Submodule found: $submodule" "Success"
fi
done
return $all_present
}
function test_cmake_cache() {
local build_dirs=("build" "build-test" "build-grpc-test" "build-rooms" "build-windows")
local cache_issues=0
for dir in "${build_dirs[@]}"; do
if [[ -f "$dir/CMakeCache.txt" ]]; then
local cache_age=$(($(date +%s) - $(stat -f %m "$dir/CMakeCache.txt" 2>/dev/null || stat -c %Y "$dir/CMakeCache.txt" 2>/dev/null)))
local days=$((cache_age / 86400))
if [[ $days -gt 7 ]]; then
write_status "CMake cache in '$dir' is $days days old" "Warning"
WARNINGS+=("Old CMake cache in $dir (consider cleaning)")
cache_issues=1
elif [[ $VERBOSE -eq 1 ]]; then
write_status "CMake cache in '$dir' is recent" "Success"
fi
fi
done
return $cache_issues
}
function test_agent_folder_structure() {
write_status "Verifying agent folder structure..." "Step"
local agent_files=(
"src/app/editor/agent/agent_editor.h"
"src/app/editor/agent/agent_editor.cc"
"src/app/editor/agent/agent_chat_widget.h"
"src/app/editor/agent/agent_chat_widget.cc"
"src/app/editor/agent/agent_chat_history_codec.h"
"src/app/editor/agent/agent_chat_history_codec.cc"
"src/app/editor/agent/agent_collaboration_coordinator.h"
"src/app/editor/agent/agent_collaboration_coordinator.cc"
"src/app/editor/agent/network_collaboration_coordinator.h"
"src/app/editor/agent/network_collaboration_coordinator.cc"
)
local old_system_files=(
"src/app/editor/agent/agent_chat_widget.h"
"src/app/editor/agent/agent_collaboration_coordinator.h"
)
local all_present=1
local has_old_structure=0
for file in "${agent_files[@]}"; do
if [[ ! -f "$file" ]]; then
write_status "Agent file missing: $file" "Error"
ISSUES_FOUND+=("Missing agent file: $file (may need to rebuild)")
all_present=0
elif [[ $VERBOSE -eq 1 ]]; then
write_status "Agent file found: $file" "Success"
fi
done
# Check for old structure (indicates stale cache)
for file in "${old_system_files[@]}"; do
if [[ -f "$file" ]]; then
write_status "Old agent file still present: $file" "Warning"
WARNINGS+=("Old agent structure detected (CMake cache needs cleaning)")
has_old_structure=1
fi
done
if [[ $all_present -eq 1 && $has_old_structure -eq 0 ]]; then
write_status "Agent folder structure is correct" "Success"
SUCCESS+=("Agent refactoring structure verified")
return 0
elif [[ $has_old_structure -eq 1 ]]; then
write_status "Stale agent files detected - CMake cache should be cleaned" "Warning"
return 1
fi
return $all_present
}
function clean_cmake_cache() {
write_status "Cleaning CMake cache and build directories..." "Step"
local build_dirs=("build" "build-test" "build-grpc-test" "build-rooms" "build-windows")
local cleaned=0
for dir in "${build_dirs[@]}"; do
if [[ -d "$dir" ]]; then
write_status "Removing $dir..." "Info"
if rm -rf "$dir" 2>/dev/null; then
cleaned=1
write_status " ✓ Removed $dir" "Success"
else
write_status " ✗ Failed to remove $dir" "Error"
WARNINGS+=("Could not fully clean $dir")
fi
fi
done
# Clean CMake generated files in root
local cmake_files=("CMakeCache.txt" "cmake_install.cmake" "compile_commands.json")
for file in "${cmake_files[@]}"; do
if [[ -f "$file" ]]; then
write_status "Removing root $file..." "Info"
rm -f "$file" 2>/dev/null
fi
done
if [[ $cleaned -eq 1 ]]; then
write_status "CMake cache cleaned successfully" "Success"
SUCCESS+=("Build directories cleaned - fresh build recommended")
else
write_status "No build directories found to clean" "Info"
fi
}
function sync_git_submodules() {
write_status "Syncing git submodules..." "Step"
write_status "Running: git submodule sync --recursive" "Info"
if git submodule sync --recursive &> /dev/null; then
write_status "Running: git submodule update --init --recursive" "Info"
if git submodule update --init --recursive; then
write_status "Submodules synced successfully" "Success"
return 0
fi
fi
write_status "Failed to sync submodules" "Error"
return 1
}
function test_dependency_compatibility() {
write_status "Testing dependency configuration..." "Step"
# Check httplib configuration
if [[ -f "third_party/httplib/CMakeLists.txt" ]]; then
write_status "httplib found in third_party" "Success"
SUCCESS+=("httplib header-only library available")
fi
# Check json library
if [[ -d "third_party/json/include" ]]; then
write_status "nlohmann/json found in third_party" "Success"
SUCCESS+=("nlohmann/json header-only library available")
fi
}
# ============================================================================
# Main Verification Process
# ============================================================================
echo ""
echo -e "${CYAN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ YAZE Build Environment Verification for Unix/macOS/Linux ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
START_TIME=$(date +%s)
# Change to script directory
cd "$(dirname "$0")/.."
# Step 1: Check CMake
write_status "Checking CMake installation..." "Step"
if test_command cmake; then
cmake_version=$(get_cmake_version)
write_status "CMake found: version $cmake_version" "Success"
# Parse version
IFS='.' read -ra VERSION_PARTS <<< "$cmake_version"
major=${VERSION_PARTS[0]}
minor=${VERSION_PARTS[1]}
if [[ $major -lt 3 ]] || [[ $major -eq 3 && $minor -lt 16 ]]; then
write_status "CMake version too old (need 3.16+)" "Error"
ISSUES_FOUND+=("CMake version $cmake_version is below minimum 3.16")
fi
else
write_status "CMake not found in PATH" "Error"
ISSUES_FOUND+=("CMake not installed or not in PATH")
fi
# Step 2: Check Git
write_status "Checking Git installation..." "Step"
if test_command git; then
git_version=$(git --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
write_status "Git found: version $git_version" "Success"
else
write_status "Git not found in PATH" "Error"
ISSUES_FOUND+=("Git not installed or not in PATH")
fi
# Step 3: Check Build Tools
write_status "Checking build tools..." "Step"
if test_command make; then
write_status "Make found" "Success"
elif test_command ninja; then
write_status "Ninja found" "Success"
else
write_status "No build tool found (make or ninja)" "Warning"
WARNINGS+=("Neither make nor ninja found")
fi
# Step 4: Check Compiler
if test_command clang++; then
clang_version=$(clang++ --version | head -n1)
write_status "Clang++ found: $clang_version" "Success"
elif test_command g++; then
gpp_version=$(g++ --version | head -n1)
write_status "G++ found: $gpp_version" "Success"
else
write_status "No C++ compiler found" "Error"
ISSUES_FOUND+=("No C++ compiler (clang++ or g++) found")
fi
# Step 5: Check Git Submodules
write_status "Checking git submodules..." "Step"
if test_git_submodules; then
write_status "All required submodules present" "Success"
else
write_status "Some submodules are missing or empty" "Error"
if [[ $FIX_ISSUES -eq 1 ]]; then
sync_git_submodules
test_git_submodules
else
write_status "Automatically syncing submodules..." "Info"
if sync_git_submodules; then
test_git_submodules
else
write_status "Run with --fix to try again, or manually: git submodule update --init --recursive" "Info"
fi
fi
fi
# Step 6: Check CMake Cache
write_status "Checking CMake cache..." "Step"
if test_cmake_cache; then
write_status "CMake cache is up to date" "Success"
else
if [[ $CLEAN_CACHE -eq 1 ]]; then
clean_cmake_cache
elif [[ $FIX_ISSUES -eq 1 ]]; then
read -p "CMake cache is old. Clean it? (Y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then
clean_cmake_cache
fi
else
write_status "Run with --clean to remove old cache files" "Info"
fi
fi
# Step 7: Check vcpkg (Windows-specific but important)
write_status "Checking vcpkg availability..." "Step"
if [[ -d "vcpkg" ]]; then
if [[ -f "vcpkg/vcpkg" ]] || [[ -f "vcpkg/vcpkg.exe" ]]; then
write_status "vcpkg found and bootstrapped" "Success"
SUCCESS+=("vcpkg available for dependency management")
# Check vcpkg version if possible
if [[ -x "vcpkg/vcpkg" ]]; then
vcpkg_version=$(./vcpkg/vcpkg version 2>/dev/null | head -n1 || echo "unknown")
write_status "vcpkg version: $vcpkg_version" "Info"
fi
else
write_status "vcpkg directory exists but not bootstrapped" "Warning"
WARNINGS+=("vcpkg not bootstrapped - run: cd vcpkg && ./bootstrap-vcpkg.sh")
fi
else
write_status "vcpkg not found (optional, required for Windows)" "Info"
write_status "To install: git clone https://github.com/microsoft/vcpkg.git && vcpkg/bootstrap-vcpkg.sh" "Info"
fi
# Step 8: Check Dependencies
test_dependency_compatibility
# Step 9: Check Agent Folder Structure
if test_agent_folder_structure; then
: # Structure is OK
else
write_status "Agent folder structure has issues" "Warning"
if [[ $CLEAN_CACHE -eq 1 ]] || [[ $FIX_ISSUES -eq 1 ]]; then
write_status "Cleaning CMake cache due to structural changes..." "Info"
clean_cmake_cache
write_status "Please rebuild the project after cache cleaning" "Info"
else
write_status "Run with --clean to fix structural issues" "Info"
fi
fi
# ============================================================================
# Summary Report
# ============================================================================
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo ""
echo -e "${CYAN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ Verification Summary ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Duration: ${DURATION} seconds"
echo ""
if [[ ${#SUCCESS[@]} -gt 0 ]]; then
echo -e "${GREEN}✓ Successes (${#SUCCESS[@]}):${NC}"
for item in "${SUCCESS[@]}"; do
echo -e " ${GREEN}${NC} $item"
done
echo ""
fi
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
echo -e "${YELLOW}⚠ Warnings (${#WARNINGS[@]}):${NC}"
for item in "${WARNINGS[@]}"; do
echo -e " ${YELLOW}${NC} $item"
done
echo ""
fi
if [[ ${#ISSUES_FOUND[@]} -gt 0 ]]; then
echo -e "${RED}✗ Issues Found (${#ISSUES_FOUND[@]}):${NC}"
for item in "${ISSUES_FOUND[@]}"; do
echo -e " ${RED}${NC} $item"
done
echo ""
echo -e "${YELLOW}Recommended Actions:${NC}"
echo -e " ${CYAN}1. Run: ./scripts/verify-build-environment.sh --fix${NC}"
echo -e " ${CYAN}2. Install missing dependencies${NC}"
echo -e " ${CYAN}3. Check build instructions: docs/02-build-instructions.md${NC}"
echo ""
exit 1
else
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✓ Build Environment Ready for Development! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Next Steps:${NC}"
echo -e " ${CYAN}Command Line Workflow:${NC}"
echo -e " ${NC}cmake -B build -DCMAKE_BUILD_TYPE=Debug${NC}"
echo -e " ${NC}cmake --build build --parallel \$(nproc)${NC}"
echo ""
exit 0
fi