diff --git a/scripts/build-container.sh b/scripts/build-container.sh new file mode 100755 index 0000000..47b6570 --- /dev/null +++ b/scripts/build-container.sh @@ -0,0 +1,177 @@ +#!/bin/bash +# Build development containers for various platforms +# Usage: ./scripts/build-container.sh [version] +# +# Platforms: 3ds, switch, wiiu, wii, gamecube, nds, gba +# Version: Semantic version (default: 0.1.0) + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Print colored message +print_msg() { + local color=$1 + shift + echo -e "${color}$*${NC}" +} + +# Print usage +usage() { + cat << EOF +Usage: $0 [version] + +Build development container for specified platform. + +Platforms: + 3ds Nintendo 3DS (devkitARM) + switch Nintendo Switch (devkitA64) - Not yet implemented + wiiu Nintendo Wii U (devkitPPC) - Not yet implemented + wii Nintendo Wii (devkitPPC) - Not yet implemented + gamecube Nintendo GameCube (devkitPPC) - Not yet implemented + nds Nintendo DS (devkitARM) - Not yet implemented + gba Game Boy Advance (devkitARM) - Not yet implemented + +Version: + Semantic version tag (default: 0.1.0) + Example: 0.1.0, 1.0.0, 0.2.0-beta + +Examples: + $0 3ds # Build 3DS container with version 0.1.0 + $0 3ds 0.2.0 # Build 3DS container with version 0.2.0 + $0 switch # Build Switch container (when implemented) + +Environment Variables: + CONTAINER_RUNTIME Container runtime to use (podman or docker, default: auto-detect) + +EOF + exit 1 +} + +# Detect container runtime +detect_runtime() { + if [ -n "$CONTAINER_RUNTIME" ]; then + echo "$CONTAINER_RUNTIME" + return + fi + + if command -v podman &> /dev/null; then + echo "podman" + elif command -v docker &> /dev/null; then + echo "docker" + else + print_msg "$RED" "Error: Neither podman nor docker found in PATH" + print_msg "$YELLOW" "Please install podman (recommended) or docker" + exit 1 + fi +} + +# Build container +build_container() { + local platform=$1 + local version=$2 + local dockerfile="docker/${platform}.Dockerfile" + local image_name="tomusan/devkitarm-${platform}" + + if [ ! -f "$PROJECT_ROOT/$dockerfile" ]; then + print_msg "$RED" "Error: Dockerfile not found: $dockerfile" + print_msg "$YELLOW" "This platform may not be implemented yet." + exit 1 + fi + + local runtime + runtime=$(detect_runtime) + + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_msg "$GREEN" "Building ${platform} container" + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo + print_msg "$YELLOW" "Platform: $platform" + print_msg "$YELLOW" "Version: $version" + print_msg "$YELLOW" "Runtime: $runtime" + print_msg "$YELLOW" "Dockerfile: $dockerfile" + print_msg "$YELLOW" "Image: ${image_name}:${version}" + print_msg "$YELLOW" " ${image_name}:latest" + echo + + cd "$PROJECT_ROOT" + + # Build with both version and latest tags + print_msg "$GREEN" "Starting build..." + echo + + "$runtime" build \ + -t "${image_name}:${version}" \ + -t "${image_name}:latest" \ + -f "$dockerfile" \ + . + + local exit_code=$? + + if [ $exit_code -eq 0 ]; then + echo + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_msg "$GREEN" "✓ Build successful!" + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo + print_msg "$GREEN" "Tagged images:" + print_msg "$YELLOW" " ${image_name}:${version}" + print_msg "$YELLOW" " ${image_name}:latest" + echo + print_msg "$GREEN" "To use this container:" + print_msg "$YELLOW" " $runtime run --rm -v ./your-project:/project:z ${image_name}:latest make" + echo + print_msg "$GREEN" "For interactive shell:" + print_msg "$YELLOW" " $runtime run -it --rm -v ./your-project:/project:z ${image_name}:latest bash" + echo + else + echo + print_msg "$RED" "✗ Build failed with exit code $exit_code" + exit $exit_code + fi +} + +# Main +main() { + if [ $# -lt 1 ]; then + usage + fi + + local platform=$1 + local version=${2:-0.1.0} + + # Validate platform + case "$platform" in + 3ds) + ;; + switch|wiiu|wii|gamecube|nds|gba) + print_msg "$RED" "Error: Platform '$platform' is not yet implemented" + print_msg "$YELLOW" "Currently only '3ds' is available" + exit 1 + ;; + *) + print_msg "$RED" "Error: Unknown platform '$platform'" + echo + usage + ;; + esac + + # Validate version format (basic semantic versioning) + if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then + print_msg "$RED" "Error: Invalid version format '$version'" + print_msg "$YELLOW" "Expected format: X.Y.Z or X.Y.Z-label (e.g., 0.1.0, 1.0.0, 0.2.0-beta)" + exit 1 + fi + + build_container "$platform" "$version" +} + +main "$@" diff --git a/scripts/container-shell.sh b/scripts/container-shell.sh new file mode 100755 index 0000000..afd4bd6 --- /dev/null +++ b/scripts/container-shell.sh @@ -0,0 +1,136 @@ +#!/bin/bash +# Open interactive shell in 3DS development container +# Usage: ./scripts/container-shell.sh [project-path] [podman-args...] +# +# All arguments after project-path are passed to podman/docker run before the container name +# This allows mounting additional volumes, setting environment variables, etc. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Print colored message +print_msg() { + local color=$1 + shift + echo -e "${color}$*${NC}" +} + +# Print usage +usage() { + cat << 'EOF' +Usage: ./scripts/container-shell.sh [project-path] [podman-args...] + +Open interactive bash shell in 3DS development container with project mounted. + +Arguments: + project-path Path to project directory (default: current directory) + podman-args Additional arguments passed to podman/docker run + +Examples: + # Shell in current directory + ./scripts/container-shell.sh + + # Shell in specific project + ./scripts/container-shell.sh ~/my-3ds-game + + # With additional volume mount + ./scripts/container-shell.sh ~/my-game -v /data:/data:z + + # With environment variable + ./scripts/container-shell.sh ~/my-game -e DEBUG=1 + + # Multiple extra arguments + ./scripts/container-shell.sh ~/my-game -v /data:/data:z -e DEBUG=1 --network=host + +Inside the container: + - Project is mounted at /project + - Working directory is /project + - All devkitARM tools are in PATH + - Run 'make' to build your project + - Run 'exit' or Ctrl+D to leave + +Environment Variables: + CONTAINER_RUNTIME Container runtime to use (podman or docker, default: auto-detect) + +EOF + exit 1 +} + +# Detect container runtime +detect_runtime() { + if [ -n "$CONTAINER_RUNTIME" ]; then + echo "$CONTAINER_RUNTIME" + return + fi + + if command -v podman &> /dev/null; then + echo "podman" + elif command -v docker &> /dev/null; then + echo "docker" + else + print_msg "$RED" "Error: Neither podman nor docker found in PATH" + print_msg "$YELLOW" "Please install podman (recommended) or docker" + exit 1 + fi +} + +# Main +main() { + # Show help + if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then + usage + fi + + # Determine project path + local project_path="${1:-.}" + shift || true # Remove first arg if present, don't fail if no args + + # Resolve absolute path + project_path=$(cd "$project_path" 2>/dev/null && pwd) || { + print_msg "$RED" "Error: Project path does not exist: ${1:-.}" + exit 1 + } + + # Collect remaining arguments for podman/docker run + local extra_args=("$@") + + local runtime + runtime=$(detect_runtime) + + local image_name="tomusan/devkitarm-3ds:latest" + + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_msg "$GREEN" "3DS Development Container Shell" + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo + print_msg "$YELLOW" "Project: $project_path" + print_msg "$YELLOW" "Runtime: $runtime" + print_msg "$YELLOW" "Image: $image_name" + if [ ${#extra_args[@]} -gt 0 ]; then + print_msg "$YELLOW" "Extra: ${extra_args[*]}" + fi + echo + print_msg "$GREEN" "Type 'exit' or press Ctrl+D to leave the container" + echo + print_msg "$BLUE" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo + + # Run container with interactive shell + # Project mounted to /project, any extra args passed to podman/docker run + "$runtime" run -it --rm \ + -v "$project_path:/project:z" \ + "${extra_args[@]}" \ + "$image_name" \ + bash +} + +main "$@"