Add 3DS Docker Development Environment with CIA Support #23
177
scripts/build-container.sh
Executable file
177
scripts/build-container.sh
Executable file
@@ -0,0 +1,177 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Build development containers for various platforms
|
||||||
|
# Usage: ./scripts/build-container.sh <platform> [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 <platform> [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 "$@"
|
||||||
136
scripts/container-shell.sh
Executable file
136
scripts/container-shell.sh
Executable file
@@ -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 "$@"
|
||||||
Reference in New Issue
Block a user