Files
nextcloud-share/.plans/DockerForDevkitARM.md

41 KiB

Docker Build Environment Plan for devkitARM

Issue: #5 - Create Docker build environment for devkitARM
Branch: docker-for-devkitarm
Status: IMPLEMENTED (Phase 1 Complete)
Completed: 2026-01-27
Last Updated: 2026-01-27


Implementation Summary

Successfully implemented complete 3DS development container with full CIA file creation capability.

What Was Delivered:

  • 3DS Container (docker/3ds.Dockerfile)

    • Based on devkitpro/devkitarm:20251231
    • All 47 available 3DS portlibs installed
    • bannertool (banner/icon creation)
    • makerom and ctrtool (CIA assembly and validation)
    • 3dstools (3dsxtool, smdhtool, mkromfs3ds)
    • ccache, ninja, python3, and build tools
    • Container size: ~1.6 GB
  • Build Scripts

    • scripts/build-container.sh - Build and tag containers
    • scripts/container-shell.sh - Interactive development shell
  • Documentation

    • docker/README.md - Comprehensive container usage guide
    • Updated main README.md with Quick Start section
  • Testing & Validation

    • Tested with 60/61 official 3ds-examples (98.4% success rate)
    • Validated with Checkpoint (real-world save manager)
    • Complete CIA workflow verified (creates all files: .3dsx, .elf, .smdh, banner.bnr, icon.icn, .cia)
    • CIA validation with ctrtool confirms proper structure

Completion Date: January 27, 2026

Phase 2 (Future): Extract to separate container repo and publish to DockerHub Phase 3 (Future): Additional platforms (Switch, Wii U, Wii, GameCube, NDS, GBA, PS Vita)


Overview

We need containerized build environments for multiple game console platforms (3DS, Switch, Wii U, etc.). Each container will extend the official devkitPro base image and install ALL available platform-specific libraries and tools from dkp-pacman. This ensures developers have a complete, batteries-included build environment without local toolchain installation.

Container Philosophy: Install everything available for a platform (e.g., all 3ds-* packages), not just what we need right now. This makes containers useful for other projects and ensures we don't need to rebuild when we need a new library.

Repository Strategy:

  1. Phase 1 (This PR - Issue #5): Dockerfiles live in this repo, build locally only
    • No DockerHub account needed
    • No credentials to manage
    • Build containers once, use many times
    • Fast, reproducible local development
  2. Phase 2 (Before CI/Releases): Extract to separate repo, publish to DockerHub
    • After containers are tested and stable
    • Before setting up Gitea CI
    • Before first release and merge to main
  3. Phase 3 (Production): CI uses published images, local dev can use either
    • CI pulls pre-built images (fast)
    • Developers can pull OR build locally
    • Separate repo allows community contributions

Local Container Building: Containers are built separately from project builds. Build once, use many times:

# Build the 3DS container locally (one-time, or when Dockerfile changes)
podman build -f docker/3ds.Dockerfile -t tomusan/devkitarm-3ds:20251231 .

# Now use it for all project builds (fast)
podman run --rm -v .:/project:z tomusan/devkitarm-3ds:20251231 make -C 3ds

The build scripts will check for local images first, then try DockerHub (Phase 2). This means:

  • Early development: Everyone builds containers locally
  • After publishing: New contributors can pull pre-built images
  • No DockerHub account needed until we're ready to publish

Why Delay Publishing?:

  • Test containers thoroughly before making public
  • No rush to manage DockerHub accounts/credentials
  • Can iterate freely without versioning concerns
  • Extract to separate repo when containers are mature
  • Easier to set up CI with pre-published containers

Goals

  1. Developer Convenience: Zero local toolchain installation required
  2. Build Consistency: Same environment everywhere (dev, CI, production)
  3. Maintainability: Easy to update dependencies and toolchain versions
  4. Documentation: Clear usage instructions for both podman and docker
  5. CI Integration: Container works seamlessly in Gitea Actions

Requirements

Must Have

  • devkitARM toolchain (arm-none-eabi-gcc)
  • libctru (3DS system library)
  • citro3d and citro2d (3DS graphics libraries)
  • makerom (CIA package generation)
  • tex3ds (texture conversion)
  • bannertool (banner/icon creation)
  • CMake 3.15+ (for shared library builds)
  • git (for version control operations)

Nice to Have

  • ccache (for faster rebuilds)
  • ninja (faster build system than make)
  • pkg-config (for library discovery)
  • Python 3 (for build scripts)
  • Debugging tools (gdb-multiarch)

Build Outputs

  • .3dsx files (Homebrew Launcher format)
  • .cia files (installable format)
  • .elf files (debugging symbols)

Approach Options

Option 1: Use Official devkitPro Containers As-Is

Description: Use devkitpro/devkitarm:latest directly without modification.

Pros:

  • Officially maintained by devkitPro team
  • Always up-to-date with latest toolchain releases
  • Pre-configured with correct environment variables
  • Includes all standard libraries (libctru, citro3d, citro2d)
  • Zero maintenance burden on our part
  • Community support and documentation
  • Guaranteed compatibility with devkitARM ecosystem

Cons:

  • Less control over installed packages
  • May include unnecessary tools (slight bloat)
  • Potential breaking changes with :latest tag
  • Limited customization options

When to Use:

  • When you want the simplest, most maintainable solution
  • When you trust the devkitPro team's container decisions
  • For quick prototyping and initial development
  • When you don't need special tools or configurations

Implementation:

# In build scripts or CI
podman run --rm \
  -v $PWD:/project:z \
  devkitpro/devkitarm:latest \
  make -C /project/3ds

Docker Commands:

# No Dockerfile needed - just pull and use
podman pull devkitpro/devkitarm:latest

# Build 3DS app
podman run --rm -v ./:/project:z devkitpro/devkitarm:latest \
  make -C /project/3ds

# Interactive shell
podman run --rm -it -v ./:/project:z devkitpro/devkitarm:latest bash

Option 2: Extend Official Container with FROM CHOSEN

Description: Create our own Dockerfile that extends devkitpro/devkitarm with additional tools and configuration.

Pros:

  • Inherits all benefits of official image
  • Can add project-specific tools (ccache, ninja, etc.)
  • Can pre-install dependencies (curl, python, etc.)
  • Can set custom environment variables
  • Can create helper scripts and aliases
  • Version-controllable configuration
  • Still receives upstream updates (if we rebuild regularly)

Cons:

  • Requires maintaining a Dockerfile
  • Needs periodic rebuilds to get upstream updates
  • Slightly slower CI (build time for our layer)
  • Can break if devkitPro changes base image significantly

When to Use:

  • When you need additional tools beyond what devkitPro provides
  • When you want to optimize build times (ccache, pre-downloaded deps)
  • When you need custom scripts or configuration
  • When you want more control but still leverage official base

Implementation:

# docker/devkitarm.Dockerfile
FROM devkitpro/devkitarm:20240202

# Install additional build tools
RUN dkp-pacman -Syu --noconfirm && \
    dkp-pacman -S --needed --noconfirm \
        devkitARM-cmake \
        general-tools \
        3ds-dev && \
    dkp-pacman -Scc --noconfirm

# Install system tools
RUN apt-get update && apt-get install -y --no-install-recommends \
    ccache \
    ninja-build \
    python3 \
    curl \
    jq \
    && rm -rf /var/lib/apt/lists/*

# Configure ccache
ENV CCACHE_DIR=/project/.ccache
ENV PATH="/usr/lib/ccache:${PATH}"

# Add helper scripts
COPY scripts/container-helpers.sh /usr/local/bin/

WORKDIR /project

Usage:

# Build our custom image
podman build -f docker/devkitarm.Dockerfile -t nextcloud-share-3ds:latest .

# Use it
podman run --rm -v ./:/project:z nextcloud-share-3ds:latest \
  make -C /project/3ds

Option 3: Build From Scratch

Description: Create a completely custom Dockerfile starting from a base Linux image (Debian/Ubuntu) and manually install devkitARM.

Pros:

  • Complete control over everything
  • Minimal image size (only what we need)
  • Deep understanding of all dependencies
  • Can optimize for CI performance
  • No surprises from upstream changes

Cons:

  • EXTREMELY HIGH MAINTENANCE - we own all toolchain issues
  • Must manually track devkitARM releases and updates
  • Complex installation procedure (dkp-pacman setup)
  • Need to debug toolchain issues ourselves
  • Risk of misconfiguration breaking builds
  • Time-consuming initial setup
  • No community support for custom setup

When to Use:

  • When you have very specific requirements the official image can't meet
  • When image size is absolutely critical
  • When you have deep expertise with devkitARM setup
  • RARELY RECOMMENDED - too much work for minimal benefit

Implementation Sketch:

FROM debian:bookworm-slim

# Install prerequisites
RUN apt-get update && apt-get install -y \
    wget curl gnupg2 bzip2 xz-utils make

# Add devkitPro repository
RUN wget https://apt.devkitpro.org/install-devkitpro-pacman && \
    chmod +x install-devkitpro-pacman && \
    ./install-devkitpro-pacman

# Install devkitARM and libraries
RUN dkp-pacman -Syu --noconfirm && \
    dkp-pacman -S --needed --noconfirm \
        devkitARM general-tools 3ds-dev

# Set environment variables
ENV DEVKITPRO=/opt/devkitpro
ENV DEVKITARM=/opt/devkitpro/devkitARM
# ... many more env vars needed ...

# This approach is NOT RECOMMENDED unless you have very specific needs

Option 4: Fork Official Dockerfile Repository

Description: Fork the devkitPro Docker repository and maintain our own version of their Dockerfiles.

Pros:

  • Full source control
  • Can submit improvements upstream
  • Can cherry-pick updates from upstream
  • Complete flexibility

Cons:

  • HIGHEST MAINTENANCE BURDEN - must track and merge upstream changes
  • Need to rebuild entire image on updates
  • Can diverge significantly from official builds
  • Requires git submodule or regular sync process
  • CI needs to build base image first (very slow)
  • Other developers need to understand fork workflow

When to Use:

  • When you plan to contribute major improvements back to devkitPro
  • When you need significant changes that won't be accepted upstream
  • When you're building a commercial product needing LTS support
  • NOT RECOMMENDED for typical open-source homebrew projects

Implementation:

# Fork https://github.com/devkitPro/docker to our repo
git clone https://github.com/devkitPro/docker.git devkitpro-docker
cd devkitpro-docker

# Make our changes
vim devkitarm/Dockerfile

# Build our forked version
podman build -f devkitarm/Dockerfile -t nextcloud-share-devkitarm:latest .

# Need to periodically merge upstream:
git remote add upstream https://github.com/devkitPro/docker.git
git fetch upstream
git merge upstream/main

Comparison Matrix

Criteria Option 1: Use Official Option 2: Extend Official Option 3: From Scratch Option 4: Fork Official
Setup Time Instant Minutes Hours Days
Maintenance None Low Very High Very High
Customization Limited High Complete Complete
Reliability Official Excellent Self-support Self-support
CI Build Time Fast (pull) Fast (cache) Slow (build all) Very Slow
Community Support Full Good None Limited
Update Frequency Automatic Manual rebuild Manual upgrade Manual merge

Recommendation

🏆 Option 2: Extend Official Containers (Multi-Platform Strategy)

Decision: We will use Option 2 (extend official containers) from the start because:

  1. Required 3rd Party Libraries: We need libraries like libpng that are NOT included in the base devkitPro containers
  2. Multi-Platform Support: We'll build containers for multiple platforms (3DS, Switch, Wii U, etc.) that other projects can reuse
  3. DockerHub Publishing: We'll publish our containers to DockerHub for easy consumption
  4. Optimization Opportunities: Can add ccache, build tools, and platform-specific dependencies
  5. Version Control: Maintain Dockerfiles in our repo for reproducibility

Options 3 & 4 Rejected: Both "from scratch" and "fork official" are too much work for too little benefit. We inherit upstream goodness with Option 2.

Version Pinning Strategy: Pin to specific devkitPro image tags for stability:

# Use date-based tags, not :latest
devkitpro/devkitarm:20251231   # Latest stable as of Jan 2026
devkitpro/devkita64:20251231   # For Switch
devkitpro/devkitppc:20251231   # For Wii/Wii U/GameCube

Available Official Tags (as of January 2026):

  • devkitpro/devkitarm: 20251231, 20251117, 20250728, 20250527, 20250512 (GBA/NDS/3DS)
  • devkitpro/devkita64: Available with similar date tags (Switch)
  • devkitpro/devkitppc: Available with similar date tags (Cube/Wii/Wii U)
  • All images support both linux/amd64 and linux/arm64 architectures

Implementation Plan

Phase 1: Local Container Development (This PR)

Goal: Build and use containers locally for reproducible development. No DockerHub publishing yet.

Timeline: Immediate - part of Issue #5

Deliverables:

  • Dockerfile for 3DS with ALL portlibs
  • Build scripts for container management
  • Build scripts for project compilation
  • Documentation for local workflow

Steps:

  1. Create Dockerfile: docker/3ds.Dockerfile

    FROM devkitpro/devkitarm:20251231
    
    LABEL maintainer="Tom Hicks"
    LABEL description="Complete Nintendo 3DS development environment with all available portlibs"
    LABEL base-image="devkitpro/devkitarm:20251231"
    
    # Update package database
    RUN dkp-pacman -Sy --noconfirm
    
    # Install 3DS development group (includes devkitARM, libctru, citro3d, citro2d, tools)
    RUN dkp-pacman -S --needed --noconfirm 3ds-dev
    
    # Install ALL available 3DS portlibs (alphabetical for clarity)
    # List verified from devkitpro/devkitarm:20251231 on 2026-01-27
    RUN dkp-pacman -S --needed --noconfirm \
        3ds-box2d \
        3ds-bulletphysics \
        3ds-bzip2 \
        3ds-curl \
        3ds-flac \
        3ds-flite \
        3ds-freetype \
        3ds-giflib \
        3ds-jansson \
        3ds-libarchive \
        3ds-libconfig \
        3ds-libfribidi \
        3ds-libiconv \
        3ds-libid3tag \
        3ds-libjpeg-turbo \
        3ds-libjson-c \
        3ds-liblua51 \
        3ds-liblzma \
        3ds-libmad \
        3ds-libmodplug \
        3ds-libogg \
        3ds-libopus \
        3ds-libpng \
        3ds-libsidplay \
        3ds-libtheora \
        3ds-libvorbisidec \
        3ds-libxmp \
        3ds-libzstd \
        3ds-lz4 \
        3ds-mbedtls \
        3ds-mikmod \
        3ds-mpg123 \
        3ds-opusfile \
        3ds-physfs \
        3ds-sdl \
        3ds-sdl_gfx \
        3ds-sdl_image \
        3ds-sdl_mixer \
        3ds-sdl_ttf \
        3ds-tinyxml2 \
        3ds-wildmidi \
        3ds-wslay \
        3ds-yaml_cpp \
        3ds-zlib && \
        dkp-pacman -Scc --noconfirm
    
    # Install CMake support for devkitARM
    RUN dkp-pacman -S --needed --noconfirm devkitARM-cmake
    
    # Install system build tools for development
    RUN apt-get update && apt-get install -y --no-install-recommends \
        ccache \
        ninja-build \
        python3 \
        python3-pip \
        curl \
        wget \
        jq \
        git \
        zip \
        unzip && \
        rm -rf /var/lib/apt/lists/*
    
    # Configure ccache for faster rebuilds
    ENV CCACHE_DIR=/project/.ccache
    ENV CCACHE_MAXSIZE=2G
    ENV PATH="/usr/lib/ccache:${PATH}"
    
    # Set working directory
    WORKDIR /project
    
    # Verify installation
    RUN arm-none-eabi-gcc --version && \
        make --version && \
        cmake --version
    

    Note: This installs EVERYTHING available for 3DS. Remove packages as needed if image size becomes an issue, but aim for completeness. The list above may need updating as devkitPro adds new portlibs.

  2. Verify package list: Query official container for complete list

    # Test with official container to see all available 3ds packages
    podman run --rm devkitpro/devkitarm:20251231 \
        dkp-pacman -Sl dkp-libs | grep '^dkp-libs 3ds-'
    
  3. Create container build script: scripts/build-container.sh

    • Accepts platform argument (3ds, switch, wiiu, etc.)
    • Builds container with appropriate tag
    • Shows success message with usage instructions
  4. Create project build wrapper: scripts/build-3ds.sh

    • Checks if container exists locally
    • Shows helpful error if not built yet
    • Runs make inside container with volume mounts
    • Handles SELinux (:z flag) for Fedora/RHEL
  5. Create interactive shell script: scripts/container-shell.sh

    • Launches bash inside container for debugging
    • Same volume mounts as build script
  6. Document workflow: docker/README.md

    • Building containers locally
    • Using containers for development
    • Container contents and architecture
    • Troubleshooting common issues
  7. Update main README: Add "Quick Start" section

    • Step 1: Build container (one-time)
    • Step 2: Build project (fast, repeatable)
    • Note about build times
  8. Test complete workflow:

    • Build 3DS container locally (~10-15 min first time)
    • Verify all portlibs installed
    • Create minimal 3DS project structure
    • Test compilation works
    • Test incremental builds are fast

Key Benefits of Phase 1:

  • No DockerHub account needed
  • No credentials to manage
  • Reproducible builds immediately
  • Fast iteration after initial build
  • Can test containers thoroughly before publishing

Phase 2: Extract and Publish (Before CI/Release)

Goal: Separate containers into independent repo and publish to DockerHub.

Timeline: Before setting up CI and before first release/merge to main

Prerequisites:

  • Containers tested and working locally
  • At least 3DS container fully functional
  • Documentation complete and accurate

Steps:

  1. Create new repository: tomusan/homebrew-devkit-containers

    • Move entire docker/ directory
    • Move container-related scripts
    • Add README for the containers project
    • Add LICENSE (MIT, same as this project)
  2. Set up DockerHub repositories:

    • Create tomusan/devkitarm-3ds
    • Create repos for other platforms as they're ready
    • Configure automated builds (optional)
  3. Add CI to containers repo:

    • GitHub Actions or Gitea Actions
    • Build on Dockerfile changes
    • Tag with base image date and semver
    • Push to DockerHub on tags
  4. Update this project:

    • Update build scripts to try DockerHub first
    • Fallback to local build if pull fails
    • Update documentation to reference published images
    • Add note about building locally as alternative
  5. Publish initial versions:

    • Tag containers as 20251231-v1.0.0
    • Push to DockerHub
    • Verify pulls work

Updated Build Script Logic (Phase 2):

# Try to use existing local image
if $CONTAINER_RUNTIME image exists "$CONTAINER_IMAGE"; then
    echo "Using local container image"
# Try to pull from DockerHub
elif $CONTAINER_RUNTIME pull "$CONTAINER_IMAGE" 2>/dev/null; then
    echo "✅ Pulled container from DockerHub"
# Give helpful error
else
    echo "❌ Container not found locally or on DockerHub"
    echo "Build it locally: ./scripts/build-container.sh 3ds"
    exit 1
fi

Migration Path:

  • Old workflow (Phase 1): Works exactly as before with local builds
  • New workflow (Phase 2): Pull pre-built images or build locally
  • CI: Always pulls from DockerHub for speed

Phase 3: Additional Platforms (Parallel to Phase 2)

Goal: Create containers for all planned platforms.

Timeline: Can be done alongside Phase 2, per-platform as needed

Create similar Dockerfiles for other platforms. Each installs ALL available portlibs for that platform:

  1. docker/switch.Dockerfile - Based on devkitpro/devkita64:20251231

    • Install switch-dev group
    • Install ALL switch-* portlibs (switch-libpng, switch-curl, etc.)
    • Build locally, optionally publish to: tomusan/devkita64-switch
  2. docker/wiiu.Dockerfile - Based on devkitpro/devkitppc:20251231

    • Install wiiu-dev group
    • Install ALL wiiu-* and wut-* portlibs
    • Build locally, optionally publish to: tomusan/devkitppc-wiiu
  3. docker/wii.Dockerfile - Based on devkitpro/devkitppc:20251231

    • Install wii-dev group
    • Install ALL wii-* and ppc-* portlibs
    • Build locally, optionally publish to: tomusan/devkitppc-wii
  4. docker/nds.Dockerfile - Based on devkitpro/devkitarm:20251231

    • Install nds-dev group
    • Install ALL nds-* portlibs
    • Build locally, optionally publish to: tomusan/devkitarm-nds
  5. docker/gba.Dockerfile - Based on devkitpro/devkitarm:20251231

    • Install gba-dev group
    • Install ALL gba-* portlibs
    • Build locally, optionally publish to: tomusan/devkitarm-gba

Note: Other projects can use these Dockerfiles even before publishing to DockerHub. Just copy the Dockerfile and build locally!


Testing Strategy

Local Testing Checklist

  • Pull/build container successfully
  • Create minimal 3DS project structure
  • Compile a "Hello World" 3DS app
  • Generate .3dsx file
  • Generate .cia file
  • Verify files work on hardware/emulator
  • Test volume mounting (source accessible inside container)
  • Test with both podman and docker
  • Verify on Linux (primary development platform)
  • Test on macOS (if available)
  • Document any platform-specific quirks

CI Testing Checklist

  • Container pulls successfully in Gitea Actions
  • Builds complete without errors
  • Build artifacts uploaded correctly
  • Build time is reasonable (< 5 minutes for clean build)
  • Cached builds are faster (< 1 minute for incremental)

Environment Variables

The devkitPro official container sets these automatically:

DEVKITPRO=/opt/devkitpro
DEVKITARM=/opt/devkitpro/devkitARM
PATH=$DEVKITARM/bin:$DEVKITPRO/tools/bin:$PATH

Our scripts should not override these unless necessary.


File Structure

nextcloud-share/
├── docker/
│   ├── README.md                    # Container usage and publishing docs
│   ├── 3ds.Dockerfile               # 3DS build container (devkitARM)
│   ├── switch.Dockerfile            # (Phase 2) Switch container (devkitA64)
│   ├── wiiu.Dockerfile              # (Phase 2) Wii U container (devkitPPC)
│   ├── wii.Dockerfile               # (Phase 2) Wii container (devkitPPC)
│   ├── nds.Dockerfile               # (Phase 2) NDS container (devkitARM)
│   ├── gba.Dockerfile               # (Phase 2) GBA container (devkitARM)
│   └── .dockerignore                # Files to exclude from build context
├── scripts/
│   ├── build-3ds.sh                 # Wrapper for 3DS builds
│   ├── build-image.sh               # Build and optionally push container
│   ├── container-shell.sh           # Launch interactive dev shell
│   └── publish-images.sh            # Push containers to DockerHub
└── 3ds/
    ├── Makefile                      # devkitARM build configuration
    └── src/                          # 3DS source code


DockerHub Naming Strategy

Name containers after the platform, not the project:

  • tomusan/devkitarm-3ds - Nintendo 3DS
  • tomusan/devkita64-switch - Nintendo Switch
  • tomusan/devkitppc-wiiu - Wii U
  • tomusan/devkitppc-wii - Wii
  • tomusan/devkitarm-nds - Nintendo DS
  • tomusan/devkitarm-gba - Game Boy Advance

Pros:

  • Reusable by other projects
  • Clear what toolchain and platform
  • Easy to migrate to separate repo later
  • Follows naming pattern: <user>/<toolchain>-<platform>

Option B: Project-Specific Names

  • tomusan/nextcloud-share-3ds
  • tomusan/nextcloud-share-switch

Pros:

  • Clear ownership
  • Can add project-specific customization

Cons:

  • Less discoverable for other projects
  • Suggests containers are project-specific

Option C: Organization Account

  • homebrew-containers/3ds
  • homebrew-containers/switch

Pros:

  • Professional appearance
  • Shared ownership
  • Best for community adoption

Cons:

  • Requires creating organization
  • Overkill for initial version

DECISION: Start with Option A (tomusan/devkitarm-3ds), migrate to Option C when we extract to separate repo.


Image Tagging Strategy

Use semantic versioning with base image date for traceability:

Tag Format: <base-date> and <base-date>-v<semver>

Primary Tags:

  • 20251231 - Based on devkitpro/devkitarm:20251231, latest rebuild
  • 20251231-v1.0.0 - Specific container version with that base
  • latest - Always points to newest base with latest rebuild

Examples:

# User wants latest everything
podman pull tomusan/devkitarm-3ds:latest

# User wants specific base for reproducibility  
podman pull tomusan/devkitarm-3ds:20251231

# User wants exact container version (most reproducible)
podman pull tomusan/devkitarm-3ds:20251231-v1.0.0

Version Bumping:

  • Patch (v1.0.1): Add/update documentation, minor script fixes
  • Minor (v1.1.0): Add new packages, optimization improvements
  • Major (v2.0.0): Change base image date, breaking changes

When Base Image Updates:

# Old stable version remains available
tomusan/devkitarm-3ds:20251231-v1.2.0

# New major version with updated base
tomusan/devkitarm-3ds:20260315-v2.0.0
tomusan/devkitarm-3ds:20260315  # Points to v2.0.0
tomusan/devkitarm-3ds:latest    # Points to v2.0.0

Open Questions

  1. Container Runtime: Prefer podman or docker in documentation?

    • Recommendation: Document podman first (rootless), mention docker compatibility
    • Decision: Detect with ${CONTAINER_RUNTIME:-podman} in scripts
  2. Separate Repo Name: What to call the extracted containers repo?

    • Options: homebrew-devkit-containers, devkitpro-extended, console-dev-containers
    • Recommendation: homebrew-devkit-containers - clear and descriptive
  3. DockerHub Organization: Create organization or use personal account?

    • Phase 1: Use personal account (tomusan/devkitarm-3ds)
    • Phase 2: Optionally migrate to organization (homebrew-containers/3ds)
    • Decision: Start personal, evaluate if organization needed later
  4. CI Platform for Containers Repo: GitHub Actions or Gitea Actions?

    • Recommendation: GitHub Actions (better DockerHub integration, free for public repos)
    • Alternative: Gitea Actions if staying fully self-hosted
  5. Windows Support: Should we test with Docker Desktop on Windows?

    • Recommendation: Best-effort support, primarily target Linux/macOS
    • Recommendation: Yes, on release tags. Manual push for development builds.
  6. Windows Support: Should we test with Docker Desktop on Windows?

    • Recommendation: Best-effort support, primarily target Linux

Success Criteria

Phase 1 Complete (Issue #5) When:

  • docker/3ds.Dockerfile created with ALL 3DS portlibs
  • scripts/build-container.sh can build containers locally
  • scripts/build-3ds.sh builds project using container
  • scripts/container-shell.sh provides interactive debugging
  • docker/README.md documents local workflow
  • Main README has "Quick Start" section
  • Can build 3DS apps without local devkitARM install
  • Works with both podman and docker
  • SELinux volume mounting (:z) handled correctly
  • Build artifacts (.3dsx, .cia) generate correctly
  • Incremental builds are fast (< 2 minutes)

Phase 2 Complete When:

  • Separate homebrew-devkit-containers repository created
  • Containers published to DockerHub
  • CI in containers repo builds and publishes automatically
  • This project's build scripts try DockerHub first
  • Documentation updated with published image references
  • Version tags follow semver + base image date

Phase 3 Complete When:

  • All planned platform containers created (Switch, Wii U, Wii, NDS, GBA)
  • Each platform has comprehensive portlib installation
  • Build scripts support all platforms
  • Documentation covers all platforms

DevkitPro Portlibs Research

The devkitPro ecosystem uses pacman to distribute "portlibs" - pre-compiled libraries for each platform.

Available via dkp-pacman:

  • Search packages: dkp-pacman -Ss <keyword>
  • List all packages: dkp-pacman -Sl dkp-libs
  • Install package: dkp-pacman -S 3ds-libpng

Nintendo 3DS Portlibs (devkitARM)

Total: 46 portlibs (verified from devkitpro/devkitarm:20251231)

3DS Portlibs (Verified list from devkitpro/devkitarm:20251231):

  • 3ds-box2d, 3ds-bulletphysics, 3ds-bzip2, 3ds-curl
  • 3ds-flac, 3ds-flite, 3ds-freetype, 3ds-giflib
  • 3ds-jansson, 3ds-libarchive, 3ds-libconfig, 3ds-libfribidi
  • 3ds-libiconv, 3ds-libid3tag, 3ds-libjpeg-turbo, 3ds-libjson-c
  • 3ds-liblua51, 3ds-liblzma, 3ds-libmad, 3ds-libmodplug
  • 3ds-libogg, 3ds-libopus, 3ds-libpng, 3ds-libsidplay
  • 3ds-libtheora, 3ds-libvorbisidec, 3ds-libxmp, 3ds-libzstd
  • 3ds-lz4, 3ds-mbedtls, 3ds-mikmod, 3ds-mpg123
  • 3ds-opusfile, 3ds-physfs, 3ds-sdl, 3ds-sdl_gfx
  • 3ds-sdl_image, 3ds-sdl_mixer, 3ds-sdl_ttf, 3ds-tinyxml2
  • 3ds-wildmidi, 3ds-wslay, 3ds-yaml_cpp, 3ds-zlib

Notable packages:

  • 3ds-cmake - CMake toolchain files (installed separately with devkitARM-cmake)
  • 3ds-examples - Example projects (optional, not installed in container)
  • 3ds-pkg-config - pkg-config tool (optional)

For Our Project:

  • 3ds-curl - HTTP/HTTPS client for WebDAV
  • 3ds-mbedtls - TLS/SSL support
  • 3ds-tinyxml2 - XML parsing for PROPFIND responses
  • 3ds-libpng - Image support (icons, UI)
  • 3ds-zlib - Compression (dependency of many libs)
  • 3ds-libjson-c or 3ds-jansson - JSON parsing (alternative to nlohmann header-only)
  • nlohmann/json - Can still use header-only version if preferred

Note: We install ALL available portlibs (46 packages), not just what we need. This makes the container useful for any 3DS project.


Nintendo Switch Portlibs (devkitA64)

Total: 77 portlibs (verified from devkitpro/devkita64:20251231)

Complete list:

  • switch-box2d, switch-bulletphysics, switch-bzip2, switch-curl
  • switch-dav1d, switch-enet, switch-ffmpeg, switch-flac
  • switch-freetype, switch-giflib, switch-glad, switch-glfw
  • switch-glm, switch-harfbuzz, switch-jansson, switch-libarchive
  • switch-libass, switch-libavif, switch-libconfig, switch-libdrm_nouveau
  • switch-libexpat, switch-libfribidi, switch-libgd, switch-libjpeg-turbo
  • switch-libjson-c, switch-liblua51, switch-liblzma, switch-liblzo2
  • switch-libmad, switch-libmikmod, switch-libmodplug, switch-libmpv
  • switch-libogg, switch-libopus, switch-libpcre2, switch-libplacebo
  • switch-libpng, switch-libsamplerate, switch-libsodium, switch-libssh2
  • switch-libtheora, switch-libtimidity, switch-libvorbis, switch-libvorbisidec
  • switch-libvpx, switch-libwebp, switch-libxml2, switch-libzstd
  • switch-lwext4, switch-lz4, switch-mbedtls, switch-mesa
  • switch-miniupnpc, switch-mpg123, switch-mupdf, switch-ntfs-3g
  • switch-ode, switch-oniguruma, switch-openal-soft, switch-opusfile
  • switch-physfs, switch-sdl2, switch-sdl2_gfx, switch-sdl2_image
  • switch-sdl2_mixer, switch-sdl2_net, switch-sdl2_ttf, switch-smpeg2
  • switch-tinyxml2, switch-wslay, switch-xxhash, switch-zlib, switch-zziplib

Notable packages:

  • switch-cmake - CMake toolchain files (installed separately)
  • switch-examples - Example projects (optional)
  • switch-pkg-config - pkg-config tool
  • switch-mesa - OpenGL/graphics (Switch has better GPU support than 3DS)
  • switch-ffmpeg - Full video codec support
  • switch-glfw, switch-glad - Modern OpenGL support
  • switch-ntfs-3g - NTFS filesystem support

For Our Project:

  • switch-curl - HTTP/HTTPS client
  • switch-mbedtls - TLS/SSL
  • switch-tinyxml2 or switch-libxml2 - XML parsing
  • switch-libpng - Image support
  • switch-zlib - Compression
  • switch-libjson-c or switch-jansson - JSON parsing

Wii U Portlibs (devkitPPC)

Total: 10 portlibs (verified from devkitpro/devkitppc:20251231)

Complete list:

  • wiiu-curl - HTTP/HTTPS client
  • wiiu-mbedtls - TLS/SSL support
  • wiiu-physfs - Filesystem abstraction
  • wiiu-sdl2 - SDL2 library
  • wiiu-sdl2_gfx - SDL2 graphics primitives
  • wiiu-sdl2_image - SDL2 image loading
  • wiiu-sdl2_mixer - SDL2 audio mixing
  • wiiu-sdl2_ttf - SDL2 TrueType fonts

Notable packages:

  • wiiu-cmake - CMake toolchain files
  • wiiu-pkg-config - pkg-config tool

For Our Project:

  • wiiu-curl - HTTP/HTTPS client
  • wiiu-mbedtls - TLS/SSL
  • ⚠️ wiiu-sdl2_image - Can load PNG via SDL2
  • No XML library available (need to investigate alternatives)
  • No JSON library (need to add or use header-only)

Note: Wii U has significantly fewer portlibs than 3DS or Switch. May need to add more libraries to our container or use alternatives.


Wii Portlibs (devkitPPC)

Total: 17 portlibs (verified from devkitpro/devkitppc:20251231)

Complete list:

  • wii-freeglut - OpenGL utility toolkit
  • wii-glu - OpenGL utility library
  • wii-opengx - OpenGL implementation for Wii
  • wii-physfs - Filesystem abstraction
  • wii-sdl - SDL 1.2 library
  • wii-sdl2 - SDL2 library
  • wii-sdl2_gfx - SDL2 graphics primitives
  • wii-sdl2_image - SDL2 image loading
  • wii-sdl2_mixer - SDL2 audio mixing
  • wii-sdl2_ttf - SDL2 TrueType fonts
  • wii-sdl_gfx - SDL 1.2 graphics primitives
  • wii-sdl_image - SDL 1.2 image loading
  • wii-sdl_mixer - SDL 1.2 audio mixing
  • wii-sdl_ttf - SDL 1.2 TrueType fonts

Notable packages:

  • wii-cmake - CMake toolchain files
  • wii-examples - Example projects
  • wii-pkg-config - pkg-config tool

For Our Project:

  • No curl or HTTP library
  • No mbedtls or TLS support
  • ⚠️ wii-sdl2_image - Can load PNG via SDL2
  • No XML library
  • No JSON library

Note: Wii has even fewer networking/utility libraries than Wii U. Will likely need significant additional library building for network functionality.


GameCube Portlibs (devkitPPC)

Total: 17 portlibs (verified from devkitpro/devkitppc:20251231)

Complete list:

  • gamecube-freeglut - OpenGL utility toolkit
  • gamecube-glu - OpenGL utility library
  • gamecube-opengx - OpenGL implementation for GameCube
  • gamecube-physfs - Filesystem abstraction
  • gamecube-sdl - SDL 1.2 library
  • gamecube-sdl2 - SDL2 library
  • gamecube-sdl2_gfx - SDL2 graphics primitives
  • gamecube-sdl2_image - SDL2 image loading
  • gamecube-sdl2_mixer - SDL2 audio mixing
  • gamecube-sdl2_ttf - SDL2 TrueType fonts
  • gamecube-sdl_gfx - SDL 1.2 graphics primitives
  • gamecube-sdl_image - SDL 1.2 image loading
  • gamecube-sdl_mixer - SDL 1.2 audio mixing
  • gamecube-sdl_ttf - SDL 1.2 TrueType fonts

Notable packages:

  • gamecube-cmake - CMake toolchain files
  • gamecube-examples - Example projects
  • gamecube-pkg-config - pkg-config tool
  • ogc-cmake - Legacy OGC (libogc) CMake support

For Our Project:

  • No curl or HTTP library (no network adapter support in most GameCubes)
  • No mbedtls or TLS support
  • ⚠️ gamecube-sdl2_image - Can load PNG via SDL2
  • No XML library
  • No JSON library

Note: GameCube has identical library support to Wii (both use libogc). Networking was rare on GameCube (broadband adapter required), so no network libraries.


NDS (Nintendo DS) Portlibs (devkitARM)

Total: 9 portlibs (verified from devkitpro/devkitarm:20251231)

Complete list:

  • nds-bzip2 - Compression library
  • nds-freetype - TrueType font rendering
  • nds-libexpat - XML parser
  • nds-libmad - MP3 audio decoder
  • nds-libpng - PNG image support
  • nds-zlib - Compression library

Notable packages:

  • nds-cmake - CMake toolchain files
  • nds-examples - Example projects
  • nds-pkg-config - pkg-config tool

For Our Project:

  • No curl or HTTP library
  • No mbedtls or TLS support
  • nds-libexpat - XML parsing
  • nds-libpng - Image support
  • nds-zlib - Compression
  • No JSON library (need to add or use header-only)

Note: NDS has basic library support. No networking libraries (Wi-Fi support was limited on original DS hardware).


GBA (Game Boy Advance) Portlibs (devkitARM)

Total: 0 portlibs (verified from devkitpro/devkitarm:20251231)

Notable packages:

  • gba-cmake - CMake toolchain files
  • gba-examples - Example projects
  • gba-pkg-config - pkg-config tool

For Our Project:

  • No portlibs available at all
  • Will need to compile all libraries from source

Note: GBA has NO portlibs. This is expected - GBA has very limited hardware (16 MHz ARM7TDMI, 256 KB RAM). Most GBA projects use custom/embedded libraries optimized for the hardware constraints.


Platform Summary

Platform Toolchain Container Portlibs Network Graphics Priority
3DS devkitARM devkitpro/devkitarm 46 curl, mbedtls SDL, citro3d HIGH
Switch devkitA64 devkitpro/devkita64 77 curl, mbedtls SDL2, OpenGL HIGH
Wii U devkitPPC devkitpro/devkitppc 10 curl, mbedtls SDL2 HIGH
Wii devkitPPC devkitpro/devkitppc 17 None SDL 1.2/2.0, OpenGL MEDIUM
GameCube devkitPPC devkitpro/devkitppc 17 None SDL 1.2/2.0, OpenGL LOW
NDS devkitARM devkitpro/devkitarm 9 ⚠️ Wi-Fi only Basic 2D/3D UNSUPPORTED
GBA devkitARM devkitpro/devkitarm 0 None Basic 2D UNSUPPORTED

Notes:

  • Wii U: Has plugins available for screenshots and camera photos. Priority platform for this project.
  • NDS/NDSi: Could theoretically upload photos or files from SD card (NDSi has cameras), but no native screenshot support. Containers will be built for potential future use, but not supported in this project.
  • GBA: No network connectivity and no screenshot capability. Container will be built for completeness, but not supported in this project.
  • Wii/GameCube: No networking capabilities in most units. May consider for local file transfer in future.

Recommendations:

  • Phase 1 (Issue #5): Focus on 3DS only (our current project target - has networking and screenshot capability)
  • Phase 3a: Add Switch (best library ecosystem, modern platform, network + screenshots)
  • Phase 3b: Add Wii U (has plugins for screenshots and camera, network capable)
  • Unsupported in this project: NDS/NDSi (could upload SD card files/photos but no game screenshots), GBA (no network)
  • Future consideration: Wii/GameCube (no networking, but may support local file transfer later)

Container Build Strategy:

  • All platforms will have Dockerfiles and build scripts in the extracted repo
  • This allows community members to use containers for any devkitPro platform
  • This project (nextcloud-share) only officially supports 3DS, Switch, and Wii U

References


Notes

  • SELinux systems (like Fedora) require :z flag on volume mounts: -v ./:/project:z
  • Container runs as root by default, but files are created with host UID due to volume mount
  • podman is rootless by default, docker typically requires sudo (unless in docker group)
  • Official containers are multi-arch (amd64, arm64) - works on both x86 and ARM host