backend-infra-engineer: Release v0.3.2 snapshot
This commit is contained in:
@@ -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.
|
||||
|
||||
369
scripts/agent.sh
369
scripts/agent.sh
@@ -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
389
scripts/agent_test_suite.sh
Executable 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 ""
|
||||
@@ -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
|
||||
@@ -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
946
scripts/build_cleaner.py
Executable 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())
|
||||
@@ -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"
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
6
scripts/requirements.txt
Normal 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
419
scripts/run_overworld_tests.sh
Executable 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 "$@"
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
57
scripts/start_collab_server.sh
Executable 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
|
||||
282
scripts/test_ai_features.ps1
Normal file
282
scripts/test_ai_features.ps1
Normal 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
277
scripts/test_ai_features.sh
Executable 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 ""
|
||||
@@ -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
172
scripts/test_dungeon_loading.sh
Executable 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
101
scripts/test_gui_tools.sh
Executable 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 ""
|
||||
|
||||
@@ -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"
|
||||
462
scripts/verify-build-environment.ps1
Normal file
462
scripts/verify-build-environment.ps1
Normal 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
|
||||
}
|
||||
458
scripts/verify-build-environment.sh
Executable file
458
scripts/verify-build-environment.sh
Executable 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
|
||||
Reference in New Issue
Block a user