diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml new file mode 100644 index 0000000..0a88aaa --- /dev/null +++ b/.github/workflows/build-macos.yml @@ -0,0 +1,45 @@ +name: Compile GCC (macOS) +on: + push: + tags: '*' + branches: [master] + paths-ignore: + - README.md + pull_request: + branches: [master] +jobs: + build: + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + version: + - 2.7.2-psx + - 2.7.2-cdk + - 2.8.1-psx + name: Build GCC ${{ matrix.version }} (macOS) + steps: + - name: Clone repository + uses: actions/checkout@v4 + - name: Install dependencies + run: | + # byacc is required for gcc-2.7.2-cdk + brew install byacc + - name: Build GCC + run: VERSION=${{ matrix.version }} PLATFORM=macos make + - name: Create release archive + shell: bash + run: | + cd build-gcc-${{ matrix.version }} + tar -czvf ../gcc-${{ matrix.version }}-macos.tar.gz * + - name: Create artifact + uses: actions/upload-artifact@v4 + with: + name: gcc-${{ matrix.version }}-macos + path: gcc-${{ matrix.version }}-macos.tar.gz + - name: Publish release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + files: | + gcc-${{ matrix.version }}-macos.tar.gz diff --git a/Makefile b/Makefile index 10936df..b45b67e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,11 @@ +PLATFORM ?= linux + all: check-version +ifeq ($(PLATFORM),macos) + bash gcc-$(VERSION)-macos.sh +else docker build -f gcc-$(VERSION).Dockerfile --target export --output build-gcc-$(VERSION) . +endif clean: rm -rf build-gcc-*/ @@ -8,8 +14,14 @@ check-version: ifndef VERSION $(error You must specify a VERSION e.g. `make VERSION=2.8.1`) endif +ifeq ($(PLATFORM),macos) +ifeq ($(wildcard gcc-$(VERSION)-macos.sh),) + $(error Building GCC $(VERSION) for macOS is not currently supported) +endif +else ifeq ($(wildcard gcc-$(VERSION).Dockerfile),) $(error Building GCC $(VERSION) is not currently supported) endif +endif .PHONY: all check-version diff --git a/gcc-2.7.2-cdk-macos.sh b/gcc-2.7.2-cdk-macos.sh new file mode 100755 index 0000000..0709a80 --- /dev/null +++ b/gcc-2.7.2-cdk-macos.sh @@ -0,0 +1,89 @@ +#!/bin/bash +# Build gcc-2.7.2-cdk natively on macOS (x86_64 and aarch64). +# Produces Mach-O cc1 and companion binaries targeting mips-sony-psx. +# +# Requires: byacc (install via Homebrew: brew install byacc) +set -e + +if ! command -v byacc >/dev/null 2>&1; then + echo "Error: byacc is required. Install it with: brew install byacc" >&2 + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PATCHES="$SCRIPT_DIR/patches" +OUTDIR="$SCRIPT_DIR/build-gcc-2.7.2-cdk" +WORKDIR="$(mktemp -d)" +trap 'rm -rf "$WORKDIR"' EXIT + +echo "Building gcc-2.7.2-cdk for macOS in $WORKDIR" + +# Ensure we use the system compiler and tools, not any cross-compiler wrappers +# that may be in PATH (e.g. from a nix shell). +export PATH="/usr/bin:/bin:/usr/sbin:/sbin:$PATH" +unset CC CXX + +cd "$WORKDIR" +curl -fL "https://github.com/decompals/old-gcc/releases/download/0.14/b18.tar.gz" | tar xz +cd cdk-gcc-b18 + +# Apply the same patches as the Linux Dockerfile +# macOS SDKs declare sys_nerr as 'const int'; fix the conflicting declarations. +for f in gcc.c cp/g++.c; do + [ -f "$f" ] && sed -i '' 's/^extern int sys_nerr;/extern const int sys_nerr;/' "$f" +done +patch -u -p1 Makefile.in -i "$PATCHES/Makefile-2.7.2-cdk.in.patch" +patch -u -p1 obstack.h -i "$PATCHES/obstack-2.7.2-cdk.h.patch" +patch -u -p1 config/mips/mips.h -i "$PATCHES/mipsel-2.7-cdk.patch" +patch -su -p1 < "$PATCHES/psx-2.7.2-cdk.patch" + +# macOS: replace config.guess/config.sub with modern versions that know +# about aarch64-apple-darwin, then add psx* to the OS list. +# Pinned to specific commits for reproducibility. +chmod +w config.guess config.sub +curl -fsL "https://raw.githubusercontent.com/gcc-mirror/gcc/74af13c174714dd3b9f1ded4b39955f003c16361/config.guess" -o config.guess +curl -fsL "https://raw.githubusercontent.com/gcc-mirror/gcc/6fad101f3063d722e3348d07dc93cf737f8709e4/config.sub" -o config.sub +chmod +x config.guess config.sub +sed -i '' 's/| hiux\* | abug | nacl\*/| psx* \\\ +'"$(printf '\t')"' | hiux* | abug | nacl*/' config.sub + +# Add xm-darwin.h and teach configure about *-apple-darwin* hosts. +cp "$PATCHES/xm-darwin.h" config/ +chmod +w configure +awk '/^\t\*\)$/ { buf=$0; next } + buf != "" { if (!done && /echo.*Configuration.*not supported/) { + print "\t*-apple-darwin*)"; print "\t\txm_file=xm-darwin.h" + print "\t\tfixincludes=Makefile.in"; print "\t\t;;"; done=1 } + print buf; buf="" } { print }' configure > configure.tmp +mv configure.tmp configure +chmod +x configure + +./configure \ + --target=mips-sony-psx \ + --prefix=/opt/cross \ + --with-endian-little \ + --with-gnu-as \ + --disable-gprof \ + --disable-gdb \ + --disable-werror + +# Compile the __eprintf stub — this symbol was removed from macOS SDKs +# after 10.14 but is referenced by the exception-handling code. +EPRINTF_OBJ="$PWD/eprintf-darwin.o" +cc -std=gnu89 -c "$PATCHES/eprintf-darwin.c" -o "$EPRINTF_OBJ" + +# Build single-threaded: parallel yacc invocations race on y.tab.h, +# causing bi-parser.h to be generated with the wrong grammar. +make cpp cc1 xgcc cc1plus g++ \ + CFLAGS="-std=gnu89 -w -Wno-int-conversion -Wno-implicit-function-declaration -Wno-return-mismatch" \ + LDFLAGS="$EPRINTF_OBJ" + +# Run the same tests as the Dockerfile +./cc1 -quiet -O2 "$SCRIPT_DIR/tests/little_endian.c" -o little_endian.s +grep -E 'lbu\s\$2,0\(\$4\)' little_endian.s +./cc1 -quiet -O2 "$SCRIPT_DIR/tests/section_attribute.c" -o /dev/null + +mkdir -p "$OUTDIR" +cp cpp cc1 xgcc cc1plus g++ "$OUTDIR/" +mv "$OUTDIR/xgcc" "$OUTDIR/gcc" +echo "Done — $OUTDIR/ ($(file "$OUTDIR/cc1" | cut -d: -f2 | xargs))" diff --git a/gcc-2.7.2-psx-macos.sh b/gcc-2.7.2-psx-macos.sh new file mode 100755 index 0000000..31d20be --- /dev/null +++ b/gcc-2.7.2-psx-macos.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# Build gcc-2.7.2-psx natively on macOS (x86_64 and aarch64). +# Produces Mach-O cc1 and companion binaries targeting mips-sony-psx. +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PATCHES="$SCRIPT_DIR/patches" +OUTDIR="$SCRIPT_DIR/build-gcc-2.7.2-psx" +WORKDIR="$(mktemp -d)" +trap 'rm -rf "$WORKDIR"' EXIT + +echo "Building gcc-2.7.2-psx for macOS in $WORKDIR" + +# Ensure we use the system compiler and tools, not any cross-compiler wrappers +# that may be in PATH (e.g. from a nix shell). +export PATH="/usr/bin:/bin:/usr/sbin:/sbin:$PATH" +unset CC CXX + +cd "$WORKDIR" +curl -fL "https://ftp.gnu.org/old-gnu/gcc/gcc-2.7.2.tar.gz" | tar xz +cd gcc-2.7.2 + +# Apply the same patches as the Linux Dockerfile +# Replace varargs.h with stdarg.h; some files are read-only from the tarball. +grep -rl 'include ' *.c | xargs chmod u+w +sed -i '' 's/include /include /g' *.c +# macOS SDKs declare sys_nerr as 'const int'; fix the conflicting declarations. +for f in gcc.c cp/g++.c; do + [ -f "$f" ] && sed -i '' 's/^extern int sys_nerr;/extern const int sys_nerr;/' "$f" +done + +patch -u -p1 obstack.h -i "$PATCHES/obstack-2.7.2.h.patch" +patch -u -p1 configure -i "$PATCHES/configure.patch" +patch -u -p1 config/mips/mips.h -i "$PATCHES/mipsel-2.7.patch" +patch -su -p1 < "$PATCHES/psx-2.5.7.patch" + +# macOS: replace config.guess/config.sub with modern versions that know +# about aarch64-apple-darwin, then add psx* to the OS list. +# Pinned to specific commits for reproducibility. +chmod +w config.guess config.sub +curl -fsL "https://raw.githubusercontent.com/gcc-mirror/gcc/74af13c174714dd3b9f1ded4b39955f003c16361/config.guess" -o config.guess +curl -fsL "https://raw.githubusercontent.com/gcc-mirror/gcc/6fad101f3063d722e3348d07dc93cf737f8709e4/config.sub" -o config.sub +chmod +x config.guess config.sub +sed -i '' 's/| hiux\* | abug | nacl\*/| psx* \\\ +'"$(printf '\t')"' | hiux* | abug | nacl*/' config.sub + +# Add xm-darwin.h and teach configure about *-apple-darwin* hosts. +cp "$PATCHES/xm-darwin.h" config/ +chmod +w configure +awk '/^\t\*\)$/ { buf=$0; next } + buf != "" { if (!done && /echo.*Configuration.*not supported/) { + print "\t*-apple-darwin*)"; print "\t\txm_file=xm-darwin.h" + print "\t\tfixincludes=Makefile.in"; print "\t\t;;"; done=1 } + print buf; buf="" } { print }' configure > configure.tmp +mv configure.tmp configure +chmod +x configure + +./configure \ + --target=mips-sony-psx \ + --prefix=/opt/cross \ + --with-endian-little \ + --with-gnu-as \ + --disable-gprof \ + --disable-gdb \ + --disable-werror + +make --jobs "$(sysctl -n hw.ncpu)" cpp cc1 xgcc cc1plus g++ \ + CFLAGS="-std=gnu89 -w -Wno-int-conversion -Wno-implicit-function-declaration -Wno-return-mismatch" + +# Run the same tests as the Dockerfile +./cc1 -quiet -O2 "$SCRIPT_DIR/tests/little_endian.c" -o little_endian.s +grep -E 'lbu\s\$2,0\(\$4\)' little_endian.s +./cc1 -quiet -O2 "$SCRIPT_DIR/tests/section_attribute.c" -o /dev/null +./cc1 -quiet -help &1 | grep -- -msoft-float + +mkdir -p "$OUTDIR" +cp cpp cc1 xgcc cc1plus g++ "$OUTDIR/" +mv "$OUTDIR/xgcc" "$OUTDIR/gcc" +echo "Done — $OUTDIR/ ($(file "$OUTDIR/cc1" | cut -d: -f2 | xargs))" diff --git a/gcc-2.8.1-psx-macos.sh b/gcc-2.8.1-psx-macos.sh new file mode 100755 index 0000000..961eca5 --- /dev/null +++ b/gcc-2.8.1-psx-macos.sh @@ -0,0 +1,92 @@ +#!/bin/bash +# Build gcc-2.8.1-psx natively on macOS (x86_64 and aarch64). +# Produces Mach-O cc1 and companion binaries targeting mips-sony-psx. +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PATCHES="$SCRIPT_DIR/patches" +OUTDIR="$SCRIPT_DIR/build-gcc-2.8.1-psx" +WORKDIR="$(mktemp -d)" +trap 'rm -rf "$WORKDIR"' EXIT + +echo "Building gcc-2.8.1-psx for macOS in $WORKDIR" + +# Ensure we use the system compiler, not any cross-compiler wrappers that +# may be in PATH (e.g. from a nix shell). +export PATH="/usr/bin:/bin:/usr/sbin:/sbin:$PATH" +unset CC CXX + +cd "$WORKDIR" +curl -fL "https://mirrors.kernel.org/gnu/gcc/gcc-2.8.1.tar.gz" | tar xz +cd gcc-2.8.1 + +# Apply the same patches as the Linux Dockerfile +# Replace varargs.h with stdarg.h; some files are read-only from the tarball. +grep -rl 'include ' *.c | xargs chmod u+w +sed -i '' 's/include /include /g' *.c +# macOS SDKs declare sys_nerr as 'const int'; fix the conflicting declarations. +for f in gcc.c cp/g++.c; do + [ -f "$f" ] && sed -i '' 's/^extern int sys_nerr;/extern const int sys_nerr;/' "$f" +done + +patch -u -p1 obstack.h -i "$PATCHES/obstack-2.8.1.h.patch" +patch -u -p1 config/mips/mips.h -i "$PATCHES/mips.patch" +patch -su -p1 < "$PATCHES/psx.patch" + +# macOS: replace config.guess/config.sub with modern versions that know +# about aarch64-apple-darwin, then add psx* to the OS list. +# Pinned to specific commits for reproducibility. +chmod +w config.guess config.sub +curl -fsL "https://raw.githubusercontent.com/gcc-mirror/gcc/74af13c174714dd3b9f1ded4b39955f003c16361/config.guess" -o config.guess +curl -fsL "https://raw.githubusercontent.com/gcc-mirror/gcc/6fad101f3063d722e3348d07dc93cf737f8709e4/config.sub" -o config.sub +chmod +x config.guess config.sub +sed -i '' 's/| hiux\* | abug | nacl\*/| psx* \\\ +'"$(printf '\t')"' | hiux* | abug | nacl*/' config.sub + +# Add xm-darwin.h and teach configure about *-apple-darwin* hosts. +cp "$PATCHES/xm-darwin.h" config/ +chmod +w configure +awk '/^\t\*\)$/ { buf=$0; next } + buf != "" { if (!done && /echo.*Configuration.*not supported/) { + print "\t*-apple-darwin*)"; print "\t\txm_file=xm-darwin.h" + print "\t\tfixincludes=Makefile.in"; print "\t\t;;"; done=1 } + print buf; buf="" } { print }' configure > configure.tmp +mv configure.tmp configure +chmod +x configure + +# Explicitly pass --host/--build so configure uses a single-arg config.sub +# call (which modern config.sub accepts), rather than its multi-arg form. +# Export CFLAGS so configure's compiler test (main(){return(0);}) passes under +# modern clang, which rejects implicit int without -std=gnu89. +DARWIN_HOST="$(uname -m)-apple-darwin" +export CFLAGS="-std=gnu89 -w -Wno-int-conversion -Wno-implicit-function-declaration -Wno-return-mismatch" +./configure \ + --target=mips-sony-psx \ + --host="$DARWIN_HOST" \ + --build="$DARWIN_HOST" \ + --prefix=/opt/cross \ + --with-endian-little \ + --with-gnu-as \ + --disable-gprof \ + --disable-gdb \ + --disable-werror + +# insn-config.h is generated during the build but referenced early; touch +# it to prevent spurious missing-file errors on some make versions. +touch insn-config.h + +make --jobs "$(sysctl -n hw.ncpu)" cpp cc1 xgcc cc1plus g++ \ + CFLAGS="-std=gnu89 -w -Wno-int-conversion -Wno-implicit-function-declaration -Wno-return-mismatch" + +# Run the same tests as the Dockerfile +./cc1 -quiet -O2 "$SCRIPT_DIR/tests/little_endian.c" -o little_endian.s +grep -E 'lbu\s\$2,0\(\$4\)' little_endian.s +./cc1 -quiet -O2 "$SCRIPT_DIR/tests/section_attribute.c" -o /dev/null +./cc1 -version &1 | grep -- -msoft-float +./cc1 -version &1 | grep -- -msplit-addresses +./cc1 -version &1 | grep -- -mgpopt + +mkdir -p "$OUTDIR" +cp cpp cc1 xgcc cc1plus g++ "$OUTDIR/" +mv "$OUTDIR/xgcc" "$OUTDIR/gcc" +echo "Done — $OUTDIR/ ($(file "$OUTDIR/cc1" | cut -d: -f2 | xargs))" diff --git a/patches/eprintf-darwin.c b/patches/eprintf-darwin.c new file mode 100644 index 0000000..35dd16c --- /dev/null +++ b/patches/eprintf-darwin.c @@ -0,0 +1,13 @@ +/* Stub for __eprintf, removed from macOS SDKs after 10.14. + Required by gcc-2.7.2-cdk's exception-handling code. */ +#include +#include + +/* weak: if another object (e.g. tree.o in cdk) also defines __eprintf, + that strong definition takes precedence and no duplicate-symbol error occurs. */ +__attribute__((weak)) void +__eprintf (const char *fmt, const char *file, unsigned line, const char *expr) +{ + fprintf (stderr, fmt, file, line, expr); + abort (); +} diff --git a/patches/xm-darwin.h b/patches/xm-darwin.h new file mode 100644 index 0000000..8197624 --- /dev/null +++ b/patches/xm-darwin.h @@ -0,0 +1,25 @@ +/* Host machine description for GCC running on macOS (Darwin). + Works for both x86_64 and aarch64 (Apple Silicon). + + macOS uses the LP64 model: int is 32-bit, long and pointers are 64-bit. */ + +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 64 +#define HOST_BITS_PER_LONGLONG 64 + +#define FALSE 0 +#define TRUE 1 + +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +#define HAVE_VPRINTF +#define HAVE_STRERROR +#define POSIX + +/* macOS provides bcopy/bcmp/bzero via . */ +#define BSTRING + +#include "tm.h"