Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6607ab3
build-toolchain: create toolchain version file
rasky Oct 20, 2025
e18d0a1
asset, kernel, toolchain: initial picolibc support
asiekierka May 2, 2024
f067627
build-toolchain: switch unzip to quiet mode
rasky Oct 15, 2025
535ead6
build-toolchain: update meson-cross to bring in ktls to patch TLS acc…
rasky Oct 15, 2025
ef08b6a
Update picolibc to latest version
rasky Oct 18, 2025
584d98d
build-toolchain: stabilize picolibc builds
rasky Oct 23, 2025
cca1d83
debug: fix debugf exception workaround for picolibc
rasky Oct 23, 2025
c077e13
Add picolibc builds to the toolchain matrix
rasky Oct 23, 2025
faed032
github: simplify toolchain matrix avoid dupes
rasky Oct 23, 2025
b15d76b
interrupt: avoid disabling TLS in exceptions if single-threaded
rasky Oct 23, 2025
51c6e66
debug: revert previous commit for stderr access in picolibc
rasky Oct 23, 2025
7affbab
CI: make sure errors actually make the CI fail
rasky Oct 25, 2025
084397a
build-toolchain: make more robust path resolution for ktls.h
rasky Oct 25, 2025
d88c025
build-toolchain: make sure include directory exists before copying kt…
rasky Oct 25, 2025
175de39
system: fix compilation with picolibc
rasky Oct 25, 2025
3291414
build-toolchain: install and auto-include ktls.h
rasky Oct 25, 2025
fd9c1b7
build-toolchain: fix invokation of GCC binary during canadian cross
rasky Oct 26, 2025
d0c56ce
build-toolchain: avoid reconfiguring since we removed the build dir
rasky Oct 26, 2025
9109858
inspector: disassembly of rdhwr
rasky Oct 26, 2025
5b3bafc
build-toolchain: modify spec also for cc1, not only cpp
rasky Oct 26, 2025
038376f
build-toolchain: resolve meson cross name with global path
rasky Oct 26, 2025
dddd499
build-toolchain: try fixing canadian-cross build
rasky Oct 26, 2025
fa224e9
build-toolchain: try fixing again canadian crosses
rasky Oct 26, 2025
bb8bd08
system: remove asm code block which doesn't seem needed anymore
rasky Oct 26, 2025
3420de8
build-toolchain: activate tinystdio by default
rasky Oct 26, 2025
9e1ee70
build-toolchain: try building both newlib and picolibc
rasky Oct 26, 2025
64e1322
build-toolchain.sh: comments
rasky Nov 5, 2025
c2317b5
build-toolchain: simplify sudo usage
rasky Nov 5, 2025
dbef10b
build-toolchain: simplify canadian cross code
rasky Nov 16, 2025
6d7a867
build-toolchain: build both newlib and picolibc, in different directo…
rasky Nov 17, 2025
447a4ea
n64.mk: remove forced include of ktls.h, as it's handled by the toolc…
rasky Nov 17, 2025
5c2f724
ci: make sure the release date of the toolchain is updated in the met…
rasky Nov 18, 2025
d8f7f1a
build-toolchain: separate picolibc and newlib using sysroots
rasky Nov 19, 2025
3aae1d6
build-toolchain: further steps to build separate sysroots
rasky Nov 22, 2025
6f31a98
Makefile: slight refactoring and cleanup
rasky Nov 22, 2025
04978e7
build-toolchain: finish sysroot support
rasky Nov 22, 2025
5e3ca9f
Dockerfile: add unzip, meson, ninja (for picolibc)
rasky Nov 22, 2025
6860801
ktls.h: remove from git (now part of the toolchain)
rasky Nov 22, 2025
79fe179
build-toolchain: try fixing canadian cross build
rasky Nov 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 57 additions & 14 deletions .github/workflows/build-toolchain-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,39 @@ jobs:
mpfr-version: ${{ steps.gcc-version-generator.outputs.MPFR_VERSION }}
gdb-version: ${{ steps.gcc-version-generator.outputs.GDB_VERSION }}
make-version: ${{ steps.gcc-version-generator.outputs.MAKE_VERSION }}
picolibc-version: ${{ steps.gcc-version-generator.outputs.PICOLIBC_VERSION }}
strategy:
fail-fast: false
matrix:
include: [
{ host-os: ubuntu-22.04, target-platform: Windows-x86_64, deb-architecture: '', rpm-architecture: '', host: x86_64-w64-mingw32, makefile-version: 4.4, zlib-version: 1.2.13 },
{ host-os: ubuntu-22.04, target-platform: Linux-x86_64, deb-architecture: amd64, rpm-architecture: x86_64, host: '', makefile-version: '', zlib-version: '' },
{ host-os: ubuntu-22.04-arm, target-platform: Linux-aarch64, deb-architecture: arm64, rpm-architecture: aarch64, host: '', makefile-version: '', zlib-version: '' }
]
include:
- host-os: ubuntu-22.04
target-platform: Windows-x86_64
deb-architecture: ''
rpm-architecture: ''
host: x86_64-w64-mingw32
makefile-version: 4.4
zlib-version: 1.2.13
- host-os: ubuntu-22.04
target-platform: Linux-x86_64
deb-architecture: amd64
rpm-architecture: x86_64
host: ''
makefile-version: ''
zlib-version: ''
- host-os: ubuntu-22.04-arm
target-platform: Linux-aarch64
deb-architecture: arm64
rpm-architecture: aarch64
host: ''
makefile-version: ''
zlib-version: ''
runs-on: ${{ matrix.host-os }}

env:
Install_Directory: libdragon
Build_Directory: scratch
Package_Suffix: ''
Artifact_Suffix: ''

steps:
- name: Install native system build dependencies
Expand All @@ -50,6 +70,8 @@ jobs:
sudo apt-get install texinfo
sudo apt-get install libmpc-dev
sudo apt-get install squashfs-tools
sudo apt-get install meson
sudo apt-get install ninja-build
# If there are other dependencies, we should add them here and make sure the documentation is updated!

- name: Install x-compile system build dependencies
Expand Down Expand Up @@ -94,14 +116,14 @@ jobs:
echo "BINUTILS_VERSION=$(grep -Po 'BINUTILS_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
echo "GCC_VERSION=$(grep -Po 'GCC_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
echo "NEWLIB_VERSION=$(grep -Po 'NEWLIB_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
echo "PICOLIBC_VERSION=$(grep -Po 'PICOLIBC_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
echo "GDB_VERSION=$(grep -Po 'GDB_V=\K[^"]*' ./tools/build-gdb.sh)" >> $GITHUB_OUTPUT

echo "GMP_VERSION=$(grep -Po 'GMP_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
echo "MPC_VERSION=$(grep -Po 'MPC_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
echo "MPFR_VERSION=$(grep -Po 'MPFR_V=\K[^"]*' ./tools/build-toolchain.sh)" >> $GITHUB_OUTPUT
# TODO: this version is set explicitly. We need to fix!
echo "MAKE_VERSION=4.4" >> $GITHUB_OUTPUT
continue-on-error: false

- name: Build N64 MIPS GCC toolchain for ${{ matrix.target-platform }}
run: |
Expand Down Expand Up @@ -209,26 +231,29 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Download Windows-x86_64 artifact
- name: Download Windows-x86_64 artifacts
id: download-windows-x86_64-artifact
uses: actions/download-artifact@v4
with:
name: gcc-toolchain-mips64-Windows-x86_64
pattern: gcc-toolchain-mips64*-Windows-x86_64
path: ${{ runner.temp }}/gcc-toolchain-mips64-Windows-x86_64
merge-multiple: false

- name: Download Linux-x86_64 artifact
- name: Download Linux-x86_64 artifacts
id: download-linux-x86_64-artifact
uses: actions/download-artifact@v4
with:
name: gcc-toolchain-mips64-Linux-x86_64
pattern: gcc-toolchain-mips64*-Linux-x86_64
path: ${{ runner.temp }}/gcc-toolchain-mips64-Linux-x86_64
merge-multiple: false

- name: Download Linux-aarch64 artifact
- name: Download Linux-aarch64 artifacts
id: download-linux-arm64-artifact
uses: actions/download-artifact@v4
with:
name: gcc-toolchain-mips64-Linux-aarch64
pattern: gcc-toolchain-mips64*-Linux-aarch64
path: ${{ runner.temp }}/gcc-toolchain-mips64-Linux-aarch64
merge-multiple: false

- name: Convert files for release upload
run: |
Expand All @@ -245,6 +270,7 @@ jobs:
CHANGELOG_TEXT+="Builds toolchain dependencies:</br>"
CHANGELOG_TEXT+=" * GCC: V${{ needs.build-toolchain.outputs.gcc-version }}</br>"
CHANGELOG_TEXT+=" * Newlib: V${{ needs.build-toolchain.outputs.newlib-version }}</br>"
CHANGELOG_TEXT+=" * Picolibc: V${{ needs.build-toolchain.outputs.picolibc-version }}</br>"
CHANGELOG_TEXT+=" * BinUtils: V${{ needs.build-toolchain.outputs.binutils-version }}</br>"
CHANGELOG_TEXT+=" * GDB: V${{ needs.build-toolchain.outputs.gdb-version }}</br>"
CHANGELOG_TEXT+='</br>'
Expand All @@ -263,8 +289,25 @@ jobs:
# Compress and move the windows folder ready for upload.
- name: Compress and move windows artifacts
run: |
cd ${{ steps.download-windows-x86_64-artifact.outputs.download-path }}
zip -r -q ${{ runner.temp }}/gcc-toolchain-mips64-win64.zip *
download_path="${{ steps.download-windows-x86_64-artifact.outputs.download-path }}"
if [ -d "$download_path" ]; then
shopt -s nullglob
for dir in "$download_path"/*/; do
[ -d "$dir" ] || continue
dir=${dir%/}
base=$(basename "$dir")
(cd "$dir" && zip -r -q "${{ runner.temp }}/$base.zip" .)
done
fi

- name: Mark release as draft (force republish)
if: github.ref == 'refs/heads/trunk'
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh release view toolchain-continuous-prerelease >/dev/null 2>&1; then
gh release edit toolchain-continuous-prerelease --draft
fi

- name: Generate Release
if: github.ref == 'refs/heads/trunk'
Expand Down
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ RUN --mount=target=/var/lib/apt/lists,type=cache,sharing=locked \
libmpc-dev \
libmpfr-dev \
make \
meson \
ninja-build \
texinfo \
unzip \
wget \
zlib1g-dev \
&& apt autoremove -yq
Expand Down
74 changes: 36 additions & 38 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,28 @@ V = 1 # force verbose (at least until we have converted all sub-Makefiles)
SOURCE_DIR = src
BUILD_DIR = build
include n64.mk
INSTALLDIR = $(N64_INST)

# N64_INCLUDEDIR is normally (when building roms) a path to the installed include files
# (e.g. /opt/libdragon/$(N64_TARGET)/include), set in n64.mk
# When building libdragon, override it to use the source include files instead (./include)
N64_INCLUDEDIR = $(CURDIR)/include
libdragon:N64_INCLUDEDIR=$(CURDIR)/include

# N64_BACKTRACE_FILE_PREFIX is exposed from n64.mk, so we can use it to set the
# prefix for libdragon. It is still possible to override this when running make
# for libdragon specifically via a make override.
N64_BACKTRACE_FILE_PREFIX=libdragon
libdragon:N64_BACKTRACE_FILE_PREFIX=libdragon

LIBDRAGON_CFLAGS = -I$(CURDIR)/src
LIBDRAGON_CFLAGS = -I$(CURDIR)/include -I$(CURDIR)/src

# Activate N64 toolchain for libdragon build
libdragon: CC=$(N64_CC)
libdragon: CXX=$(N64_CXX)
libdragon: AS=$(N64_AS)
libdragon: LD=$(N64_LD)
libdragon: CFLAGS+=$(N64_CFLAGS) $(LIBDRAGON_CFLAGS)
libdragon: CXXFLAGS+=$(N64_CXXFLAGS) $(LIBDRAGON_CFLAGS)
libdragon: ASFLAGS+=$(N64_ASFLAGS) $(LIBDRAGON_CFLAGS)
libdragon: RSPASFLAGS+=$(N64_RSPASFLAGS) $(LIBDRAGON_CFLAGS)
libdragon: CFLAGS+=$(LIBDRAGON_CFLAGS) $(N64_CFLAGS)
libdragon: CXXFLAGS+=$(LIBDRAGON_CFLAGS) $(N64_CXXFLAGS)
libdragon: ASFLAGS+=$(LIBDRAGON_CFLAGS) $(N64_ASFLAGS)
libdragon: RSPASFLAGS+=$(LIBDRAGON_CFLAGS) $(N64_RSPASFLAGS)
libdragon: LDFLAGS+=$(N64_LDFLAGS)
libdragon: libdragon.a libdragonsys.a gen-version

Expand Down Expand Up @@ -101,7 +100,7 @@ examples:
$(MAKE) -C examples
# We are unable to clean examples built with n64.mk unless we
# install it first
examples-clean: $(INSTALLDIR)/include/n64.mk
examples-clean: $(N64_INST)/include/n64.mk
$(MAKE) -C examples clean

doxygen-api: doxygen-public.conf
Expand All @@ -114,13 +113,13 @@ tools-install:
tools-clean:
$(MAKE) -C tools clean

install-mk: $(INSTALLDIR)/include/n64.mk
install-mk: $(N64_INST)/include/n64.mk

$(INSTALLDIR)/include/n64.mk: n64.mk
$(N64_INST)/include/n64.mk: n64.mk
# Always update timestamp of n64.mk. This make sure that further targets
# depending on install-mk won't always try to re-install it.
mkdir -p $(INSTALLDIR)/include
install -cv -m 0644 n64.mk $(INSTALLDIR)/include/n64.mk
mkdir -p $(N64_INST)/include
install -cv -m 0644 n64.mk $(N64_INST)/include/n64.mk

gen-version:
# Generate a version file for libdragon. We go through git archive so that
Expand Down Expand Up @@ -150,34 +149,33 @@ gen-version:
cp libdragon.version "$(BUILD_DIR)/libdragon.version"; \
fi;

install: install-mk libdragon
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/lib
install -Cv -m 0644 libdragon.a $(INSTALLDIR)/$(N64_TARGET)/lib/libdragon.a
install -Cv -m 0644 n64.ld $(INSTALLDIR)/$(N64_TARGET)/lib/n64.ld
install -Cv -m 0644 dso.ld $(INSTALLDIR)/$(N64_TARGET)/lib/dso.ld
install -Cv -m 0644 rsp.ld $(INSTALLDIR)/$(N64_TARGET)/lib/rsp.ld
install -Cv -m 0644 libdragonsys.a $(INSTALLDIR)/$(N64_TARGET)/lib/libdragonsys.a
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/include
install: install-mk libdragon gen-version
install -Cv -m 0644 libdragon.a $(N64_LIBDIR)/libdragon.a
install -Cv -m 0644 n64.ld $(N64_LIBDIR)/n64.ld
install -Cv -m 0644 dso.ld $(N64_LIBDIR)/dso.ld
install -Cv -m 0644 rsp.ld $(N64_LIBDIR)/rsp.ld
install -Cv -m 0644 libdragonsys.a $(N64_LIBDIR)/libdragonsys.a

if [ -f "$(BUILD_DIR)/libdragon.version" ]; then \
install -Cv -m 0644 $(BUILD_DIR)/libdragon.version $(INSTALLDIR)/$(N64_TARGET)/include/; \
install -Cv -m 0644 $(BUILD_DIR)/libdragon.version $(N64_INCLUDEDIR)/; \
else \
rm -f $(INSTALLDIR)/$(N64_TARGET)/include/libdragon.version; \
rm -f $(N64_INCLUDEDIR)/libdragon.version; \
fi;
install -Cv -m 0644 include/*.h $(INSTALLDIR)/$(N64_TARGET)/include/
install -Cv -m 0644 include/*.inc $(INSTALLDIR)/$(N64_TARGET)/include/
install -Cv -m 0644 include/ucode.S $(INSTALLDIR)/$(N64_TARGET)/include/
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/include/sys
install -Cv -m 0644 include/sys/*.h $(INSTALLDIR)/$(N64_TARGET)/include/sys/
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/include/GL
install -Cv -m 0644 include/GL/*.h $(INSTALLDIR)/$(N64_TARGET)/include/GL/
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/include/newlib_overrides
install -Cv -m 0644 include/newlib_overrides/*.h $(INSTALLDIR)/$(N64_TARGET)/include/newlib_overrides/
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/include/libcart
install -Cv -m 0644 src/libcart/cart.h $(INSTALLDIR)/$(N64_TARGET)/include/libcart/cart.h
mkdir -p $(INSTALLDIR)/$(N64_TARGET)/include/fatfs
install -Cv -m 0644 src/fatfs/diskio.h $(INSTALLDIR)/$(N64_TARGET)/include/fatfs/diskio.h
install -Cv -m 0644 src/fatfs/ff.h $(INSTALLDIR)/$(N64_TARGET)/include/fatfs/ff.h
install -Cv -m 0644 src/fatfs/ffconf.h $(INSTALLDIR)/$(N64_TARGET)/include/fatfs/ffconf.h
install -Cv -m 0644 include/*.h $(N64_INCLUDEDIR)/
install -Cv -m 0644 include/*.inc $(N64_INCLUDEDIR)/
install -Cv -m 0644 include/ucode.S $(N64_INCLUDEDIR)/
mkdir -p $(N64_INCLUDEDIR)/sys
install -Cv -m 0644 include/sys/*.h $(N64_INCLUDEDIR)/sys/
mkdir -p $(N64_INCLUDEDIR)/GL
install -Cv -m 0644 include/GL/*.h $(N64_INCLUDEDIR)/GL/
mkdir -p $(N64_INCLUDEDIR)/newlib_overrides
install -Cv -m 0644 include/newlib_overrides/*.h $(N64_INCLUDEDIR)/newlib_overrides/
mkdir -p $(N64_INCLUDEDIR)/libcart
install -Cv -m 0644 src/libcart/cart.h $(N64_INCLUDEDIR)/libcart/cart.h
mkdir -p $(N64_INCLUDEDIR)/fatfs
install -Cv -m 0644 src/fatfs/diskio.h $(N64_INCLUDEDIR)/fatfs/diskio.h
install -Cv -m 0644 src/fatfs/ff.h $(N64_INCLUDEDIR)/fatfs/ff.h
install -Cv -m 0644 src/fatfs/ffconf.h $(N64_INCLUDEDIR)/fatfs/ffconf.h

clean:
rm -f *.o *.a
Expand Down
21 changes: 0 additions & 21 deletions include/ktls.h

This file was deleted.

2 changes: 1 addition & 1 deletion n64.mk
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ N64_DSO = $(N64_BINDIR)/n64dso
N64_DSOEXTERN = $(N64_BINDIR)/n64dso-extern
N64_DSOMSYM = $(N64_BINDIR)/n64dso-msym

N64_C_AND_CXX_FLAGS = -march=vr4300 -mtune=vr4300 -mabi=o64 -I$(N64_INCLUDEDIR)/newlib_overrides -I$(N64_INCLUDEDIR) -include ktls.h
N64_C_AND_CXX_FLAGS = -march=vr4300 -mtune=vr4300 -mabi=o64 -I$(N64_INCLUDEDIR)/newlib_overrides -I$(N64_INCLUDEDIR)
N64_C_AND_CXX_FLAGS += -falign-functions=32 # NOTE: if you change this, also change backtrace() in backtrace.c
N64_C_AND_CXX_FLAGS += -ffunction-sections -fdata-sections -g -ffile-prefix-map="$(CURDIR)"=$(N64_BACKTRACE_FILE_PREFIX)
N64_C_AND_CXX_FLAGS += -ffast-math -ftrapping-math -fno-associative-math
Expand Down
8 changes: 8 additions & 0 deletions src/asset.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,11 @@ static fpos_t seekfn_none(void *c, fpos_t pos, int whence)
return -1;
}

#if defined(__PICOLIBC__)
static int readfn_none(void *c, void *buf, size_t sz)
#else
static int readfn_none(void *c, char *buf, int sz)
#endif
{
cookie_none_t *cookie = c;
assertf(!cookie->seeked, "Cannot seek in file opened via asset_fopen (it might be compressed)");
Expand All @@ -325,7 +329,11 @@ typedef struct {
uint8_t alignas(8) state[];
} cookie_cmp_t;

#if defined(__PICOLIBC__)
static int readfn_cmp(void *c, void *buf, size_t sz)
#else
static int readfn_cmp(void *c, char *buf, int sz)
#endif
{
cookie_cmp_t *cookie = (cookie_cmp_t*)c;
assertf(!cookie->seeked, "Cannot seek in file opened via asset_fopen (it might be compressed)");
Expand Down
1 change: 1 addition & 0 deletions src/inspector.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ static void mips_disasm(uint32_t *ptr, char *out, int n) {
const char *opn = ops[(op >> 26) & 0x3F];
if (op == 0) opn = "znop";
else if (((op >> 26) & 0x3F) == 9 && ((op >> 21) & 0x1F) == 0) opn = "kli";
else if (((op >> 26) & 0x3F) == 0x1F && (op & 0x3F) == 0x3B) opn = "zrdhwr";
else if ((op >> 16) == 0x1000) opn = "yb";
else if (*opn == 's') {
opn = special[(op >> 0) & 0x3F];
Expand Down
9 changes: 6 additions & 3 deletions src/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@ static uint32_t __prenmi_tick;
static void __call_callback( struct callback_link * head )
{
/* Invalidate TP Value: if TLS data is accessed under interrupt,
an exception is raised. */
an exception is raised.
Do this only if the kernel is enabled, so that we keep TLS working
in a single-thread environment. This is useful for picolibc where
TLS is pervasive. */
void *tp = __th_cur_tp;
__th_cur_tp = KERNEL_TP_INVALID;
if (__kernel) __th_cur_tp = KERNEL_TP_INVALID;
/* Call each registered callback */
while( head )
{
Expand All @@ -132,7 +135,7 @@ static void __call_callback( struct callback_link * head )
head=head->next;
}
/* Restore TP Value */
__th_cur_tp = tp;
if (__kernel) __th_cur_tp = tp;
}

/**
Expand Down
Loading
Loading