Here's how you build Redox from Mac in May 2025. It's so much easier to do it now than in ancient days.
The only problem you may encounter is packaging the build, since it requires FUSE and it's requires patching Mac kernel, which I don't want. I (trying) develop a way to avoid it by using Podman only for that.
I run with UTM on QEMU virtualization. It works for me.
This notes is WIP, see https://gist.github.com/willnode/a31a1265d955dbb914001aba8a576ad2 for Redox OS native bootstrapping
- Patch prefixes
- Patch libredox
- Patch relibc
- Patch essential recipes
Before you start, please install xcode and brew, then:
cd ~/Document
git clone https://gitlab.redox-os.org/redox-os/redox
cd redox
git submodule update --init --recursive
# Install necessary tooling except things that don't work
sed -i '' '/macfuse/d' ./native_bootstrap.sh
sed -i '' '/[email protected]/d' ./native_bootstrap.sh
sed -i '' '/x86_64-elf-gcc/d' ./native_bootstrap.sh
./native_bootstrap.sh -d
# Install additional things not listed
brew install help2man m4 # required by new libtool
brew install libiconv # required by binutils
Write this on .config
:
PODMAN_BUILD=0
ARCH=aarch64
CONFIG_NAME=desktop
Then build the image with ./build.sh
. At your first try it definitely gonna break so here's some patches you need to do...
This is because it's can't be done after build, so just omit it.
sed -i '' 's/ && $(PREFIX_STRIP)//g' ./mk/prefix.mk
In mk/fstools.mk
, skip fstools installation, because it's linking to libc specifically written for linux, not mac.
$(HOST_FSTOOLS): installer redoxfs
+ echo "fstools Installation is skipped"
- rm -rf $@ [email protected]
- mkdir -p [email protected]
- $(HOST_CARGO) install --root [email protected] --path installer --bin redox_installer
- $(HOST_CARGO) install --root [email protected] --path redoxfs --bin redoxfs --bin redoxfs-mkfs
- mv [email protected] $@
touch $@
TODO: (do not use this yet, need to provide prebuilt for m1)
In mk/config.mk
, delete these conditionals because building them takes a looonggg time
-ifneq ($(HOST_TARGET),x86_64-unknown-linux-gnu)
- # The binary prefix is only built for x86_64 Linux hosts
- PREFIX_BINARY=0
-endif
...
-ifneq ($(UNAME),Linux)
- PREFIX_BINARY=0
-endif
-ifneq ($(HOST_ARCH),x86_64)
- PREFIX_BINARY=0
-endif
If you do this, you can skip patch binutils and cloning rust since it's no longer necessary.
These library paths need to be added manually either in your terminal now or in ~/.zshrc
:
export LIBRARY_PATH="/opt/homebrew/opt/isl/lib:/opt/homebrew/opt/gmp/lib:/opt/homebrew/opt/mpfr/lib:/opt/homebrew/opt/libiconv/lib:$LIBRARY_PATH"
export C_INCLUDE_PATH="/opt/homebrew/opt/isl/include:/opt/homebrew/opt/gmp/include:/opt/homebrew/opt/mpfr/include:/opt/homebrew/opt/libiconv/include:$C_INCLUDE_PATH"
export CPLUS_INCLUDE_PATH="/opt/homebrew/opt/isl/include:/opt/homebrew/opt/gmp/include:/opt/homebrew/opt/mpfr/include:/opt/homebrew/opt/libiconv/include:$CPLUS_INCLUDE_PATH"
# TODO: explanations
export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:/opt/homebrew/opt/findutils/libexec/gnubin:/opt/homebrew/opt/gnu-sed/libexec/gnubin:/opt/homebrew/opt/m4/bin/:$PATH"
ln -s /opt/homebrew/opt/m4/bin/m4 /opt/homebrew/opt/m4/bin/gm4
Note: Check with clang -v
, if your Clang <17, you don't need this.
Issue: iains/gcc-14-branch#21 Fix: https://github.com/madler/zlib/commit/4bd9a71f3539b5ce47f0c67ab5e01f3196dc8ef9 File: prefix/aarch64-unknown-redox/binutils/zlib/zutil.h and prefix/aarch64-unknown-redox/gcc/zlib/zutil.h
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 7
-# ifndef Z_SOLO
-# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-# include <unix.h> /* for fdopen */
-# else
-# ifndef fdopen
-# define fdopen(fd,mode) NULL /* No fdopen() */
-# endif
-# endif
-# endif
#endif
Patch: https://patchwork.sourceware.org/project/gdb/patch/[email protected]/ File: prefix/aarch64-unknown-redox/binutils/gdb/remote-sim.c
-[[noreturn]] static void gdb_os_error (host_callback *, const char *, ...);
+static void gdb_os_error(host_callback *, const char *, ...)
+ ATTRIBUTE_NORETURN;
Issue: https://github.com/orgs/Homebrew/discussions/5273 Patch: https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/system.h;h=03ab33ac960fd1681a6cc26d05e2ec498c12c733;hp=33e9d421115005dfefed2123bb0136ee6e4b971c;hb=68057560ff1fc0fb2df38c2f9627a20c9a8da5c5;hpb=47ebdbe5bf71d9eb260359b6aceb5cb071d97acd File: prefix/aarch64-unknown-redox/gcc/gcc/system.h
-/* Include <string> before "safe-ctype.h" to avoid GCC poisoning
- the ctype macros through safe-ctype.h */
-
-#ifdef __cplusplus
-#ifdef INCLUDE_STRING
-# include <string>
-#endif
-#endif
-
-/* There are an extraordinary number of issues with <ctype.h>.
- The last straw is that it varies with the locale. Use libiberty's
- replacement instead. */
-#include "safe-ctype.h"
-
-#include <sys/types.h>
-
-#include <errno.h>
-
-#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
-extern int errno;
-#endif
+/* Include C++ standard headers before "safe-ctype.h" to avoid GCC
+ poisoning the ctype macros through safe-ctype.h */
#ifdef __cplusplus
#if defined (INCLUDE_ALGORITHM) || !defined (HAVE_SWAP_IN_UTILITY)
@@ -229,6 +210,9 @@ extern int errno;
#ifdef INCLUDE_SET
# include <set>
#endif
+#ifdef INCLUDE_STRING
+# include <string>
+#endif
#ifdef INCLUDE_VECTOR
# include <vector>
#endif
@@ -245,6 +229,19 @@ extern int errno;
# include <type_traits>
#endif
+/* There are an extraordinary number of issues with <ctype.h>.
+ The last straw is that it varies with the locale. Use libiberty's
+ replacement instead. */
+#include "safe-ctype.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+
+#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
+extern int errno;
+#endif
+
/* Some of glibc's string inlines cause warnings. Plus we'd rather
rely on (and therefore test) GCC's string builtins. */
#define __NO_STRING_INLINES
I assume you're running from fresh Ubuntu aarch64.
sudo apt-get install cbindgen just make build-essential nasm pkg-config fuse3 libfuse3-dev libmpc-dev \
texinfo bison flex cmake ninja-build autoconf autopoint libtool po4a doxygen gperf
Or if you dare directly running it on Mac.
brew install coreutils binutils findutils gnu-sed osxfuse cbindgen just make nasm pkg-config libmpc \
mpfr gmp texinfo bison flex cmake ninja autoconf automake libtool libicinv po4a doxygen gperf
Then:
- Patch ring to use https://gitlab.redox-os.org/redox-os/ring/-/tree/redox-0.16.20, put it in
./ring
- Patch pkgutils, clone https://gitlab.redox-os.org/redox-os/ring/-/tree/redox-0.16.20, put it in
./pkgutils
- Patch binutils to use https://gitlab.redox-os.org/willnode/binutils-gdb put it in
./prefix/bintutils
- Apply patch
[patch.crates-io]
toinstaller
andcookbook
. - In
mk/prefix.mk
delete all lines with$(PREFIX_STRIP)
becausestrip
doesn't work (it's optional) - Exec these before running
build.sh
(brew from libs is not detected and need exact GNU bins not from Mac)
export LIBRARY_PATH=/opt/homebrew/Cellar/gmp/6.3.0/lib:/opt/homebrew/Cellar/mpfr/4.2.1/lib:/opt/homebrew/opt/libiconv/lib
export C_INCLUDE_PATH=/opt/homebrew/Cellar/gmp/6.3.0/include:/opt/homebrew/Cellar/mpfr/4.2.1/include:/opt/homebrew/opt/libiconv/include
export CPLUS_INCLUDE_PATH=/opt/homebrew/Cellar/gmp/6.3.0/include:/opt/homebrew/Cellar/mpfr/4.2.1/include:/opt/homebrew/opt/libiconv/include
export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:/opt/homebrew/opt/findutils/libexec/gnubin:/opt/homebrew/opt/gnu-sed/libexec/gnubin:$PATH"
I recommend patch the rust (see bootloader section) before compiling anything.
When recompiling GCC or Rust, don't forget to delete relevant builds in /prefix
.
mk/prefix.mk:
"$(ROOT)/$</configure" \
--target="$(TARGET)" \
--program-prefix="$(TARGET)-" \
--prefix="" \
--with-sysroot \
--with-build-sysroot="$(ROOT)/$(PREFIX)/relibc-freestanding-install/$(TARGET)" \
--with-native-system-header-dir="/include" \
+ --without-long-double-128 \
--disable-multilib \
--disable-nls \
--disable-werror \
--enable-languages=c,c++ \
--enable-shared \
--enable-threads=posix \
Need to patch all the long double
to double
. I have this change implemented for gettext
and nano
. Reference: https://stackoverflow.com/a/49123064/3908409
cd cookbook/recipes/tools/gettext/source
grep -Rl 'long double' * | xargs -tn1 sed -i -e 's/long double/double/g'
grep -Rl 'SIZEOF_LDBL <= sizeof (double)' * | xargs -tn1 sed -i -e 's/SIZEOF_LDBL <= sizeof (double)/SIZEOF_LDBL <= sizeof (long double)/g'
cookbook/recipes/tools/gettext/recipe.toml
script = """
COOKBOOK_CONFIGURE_FLAGS+=(
+ --disable-glib
--disable-shared
+ --disable-java
+ --disable-csharp
--enable-static
+ --with-included-libunistring
ac_cv_have_decl_program_invocation_name=no
gt_cv_locale_fr=false
gt_cv_locale_fr_utf8=false
gt_cv_locale_ja=false
gt_cv_locale_tr_utf8=false
gt_cv_locale_zh_CN=false
)
cookbook_configure
"""
PS: Not sure if anything else except --with-included-libunistring
is necessary.
cookbook/recipes/tools/gettext/source/gettext-tools/gnulib-lib/asyncsafe-spin.c
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) \
|| __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 1)) \
- && !defined __ibmxl__
+ && !defined __ibmxl__ && !defined __redox__
/* Use GCC built-ins (available in GCC >= 4.7 and clang >= 3.1) that operate on
the first byte of the lock.
Documentation:
<https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/_005f_005fatomic-Builtins.html>
*/
# elif (((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) \
&& !defined __sparc__) \
|| __clang_major__ >= 3) \
- && !defined __ibmxl__
+ && !defined __ibmxl__ && !defined __redox__
/* Use GCC built-ins (available in GCC >= 4.1, except on SPARC, and
clang >= 3.0).
Documentation:
<https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html> */
- cookbook/recipes/tools/gettext/source/gettext-tools/gnulib-lib/math.in.h
- cookbook/recipes/tools/gettext/source/libtextstyle/lib/math.in.h
#if @GNULIB_FREXP@
# if @REPLACE_FREXP@
-# if !(defined __cplusplus&& defined GNULIB_NAMESPACE)
+# if !(defined __cplusplus && defined __redox__ && defined GNULIB_NAMESPACE)
# undef frexp
# define frexp rpl_frexp
# endif
cookbook/recipes/shells/bash/source/configure
if test "$GCC" = yes; then
- ac_cv_type_long_double=yes
+ ac_cv_type_long_double=no
else
cookbook/recipes/libs/openssl1/recipe.toml
COOKBOOK_CONFIGURE_FLAGS=(
no-shared
no-dgram
+ no-asm
"redox-${ARCH}"
--prefix="/"
)
cookbook/recipes/libs/openssl1/source/Configurations/10-main.conf
"redox-x86_64" => {
inherit_from => [ "BASE_common", asm("x86_64_asm") ],
cc => "gcc",
cflags => "-DL_ENDIAN -DOSSL_SSIZE_MAX=LONG_MAX -DNO_SYSLOG -O3 -static -Wall",
bn_ops => "SIXTY_FOUR_BIT_LONG",
thread_scheme => "(unknown)",
},
+ "redox-aarch64" => {
+ inherit_from => [ "linux-generic64", asm("aarch64_asm") ],
+ cc => "gcc",
+ cflags => "-DL_ENDIAN -DOSSL_SSIZE_MAX=LONG_MAX -DNO_SYSLOG -O3 -static -Wall",
+ bn_ops => "SIXTY_FOUR_BIT_LONG",
+ thread_scheme => "(unknown)",
+ perlasm_scheme => "void",
+ },
cookbook/recipes/libs/openssl1/source/crypto/armcap.c
#else
+/* Some platforms don't have the sigjmp_buf type in <setjmp.h>. */
+#if defined _MSC_VER || defined __MINGW32__ || defined(__redox__)
+/* Native Woe32 API. */
+# define sigjmp_buf jmp_buf
+# define sigsetjmp(env,savesigs) setjmp (env)
+# define siglongjmp longjmp
+#endif
static sigset_t all_masked;
Apply https://gitlab.redox-os.org/willnode/ring/-/commit/5d895ab1e
- cookbook/recipes/core/installer/source/Cargo.toml
- cookbook/recipes/core/pkgutils/source/Cargo.toml
- cookbook/recipes/gui/installer-gui/source/Cargo.toml
[patch.crates-io]
-ring = { git = "https://gitlab.redox-os.org/redox-os/ring.git", branch = "redox-unix-0.13.5" }
+ring = { git = "https://gitlab.redox-os.org/willnode/ring.git", branch = "redox-unix-0.13.5" }
cookbook/recipes/tools/git/source/compat/bswap.h
# if defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
# define GIT_BYTE_ORDER GIT_BIG_ENDIAN
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
# elif defined(__THW_BIG_ENDIAN__) && !defined(__THW_LITTLE_ENDIAN__)
# define GIT_BYTE_ORDER GIT_BIG_ENDIAN
# elif defined(__THW_LITTLE_ENDIAN__) && !defined(__THW_BIG_ENDIAN__)
# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
# else
-# error "Cannot determine endianness"
+# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN
# endif
cookbook/recipes/backends/sdl1/recipe.toml
script = """
COOKBOOK_CONFIGURE_FLAGS+=(
+ --build=aarch64-unknown-linux-gnu
+ --host=aarch64-unknown-redox
--disable-loadso
--disable-pthread-sem
--disable-pulseaudio
--disable-video-x11
--enable-clock_gettime
--enable-redoxaudio
--enable-video-orbital
)
cookbook/recipes/core/drivers-initfs/recipe.toml
aarch64_redefine_bin()
{
- BINS=(inputd lived)
case "${BOARD}" in
raspi3bp)
BINS+=(bcm2835-sdhcid)
;;
raspi3b)
BINS+=(bcm2835-sdhcid)
;;
*)
#qemu-virt
;;
esac
}
cookbook/recipes/core/drivers/recipe.toml
# Add additional drivers to the list to build, that are not in drivers-initfs
# depending on the target architecture
case "${TARGET}" in
i686-unknown-redox | x86_64-unknown-redox)
BINS+=(ac97d bgad pcid pcspkrd sb16d vboxd)
;;
+ aarch64-unknown-redox)
+ BINS+=(pcid)
+ ;;
*)
;;
esac
config/aarch64/desktop.toml (new file)
# Default desktop configuration
include = ["../desktop.toml"]
# Override the default settings here
# General settings
[general]
# Filesystem size in MiB
# filesystem_size = 1024
# Package settings
[packages]
# example = {}
This make ramfb
device available. But then you have apply my patch to get it working
mk/qemu.mk (please adjust qemu version)
else ifeq ($(ARCH),x86_64)
+ efi=yes
+ live=yes
QEMU_ARCH=x86_64
QEMU_MACHINE?=q35
- QEMU_CPU?=core2duo
- QEMU_EFI=/usr/share/OVMF/OVMF_CODE.fd
+ QEMU_CPU=qemu64
+ QEMU_EFI=/opt/homebrew/Cellar/qemu/8.2.1/share/qemu/edk2-x86_64-code.fd
QEMUFLAGS+=-smp 4 -m 2048
else ifeq ($(ARCH),aarch64)
efi=yes
live=yes
QEMU_ARCH=aarch64
QEMU_MACHINE=virt
- QEMU_CPU=max
- ifeq ($(BOARD),raspi3bp)
- QEMU_EFI=https://gitlab.redox-os.org/Ivan/redox_firmware/-/raw/main/platform/raspberry_pi/rpi3/u-boot-rpi-3-b-plus.bin
- else
- QEMU_EFI=https://gitlab.redox-os.org/Ivan/redox_firmware/-/raw/main/platform/qemu/qemu_arm64/u-boot-qemu-arm64.bin
- endif
+ QEMU_CPU=cortex-a72
+ QEMU_EFI=/opt/homebrew/Cellar/qemu/8.2.1/share/qemu/edk2-aarch64-code.fd
QEMUFLAGS+=-smp 1 -m 2048
ifneq ($(vga),no)
...
ifeq ($(efi),yes)
FIRMWARE=$(BUILD)/firmware.rom
- QEMUFLAGS+=-bios $(BUILD)/firmware.rom
+ QEMUFLAGS+= -drive if=pflash,format=raw,unit=0,file=$(FIRMWARE),readonly=on
else
...
$(BUILD)/firmware.rom:
- ifeq ($(ARCH),aarch64)
- wget -O $@ $(QEMU_EFI)
- else
cp $(QEMU_EFI) $@
- endif
Should have the disk image now and it's bootable and able to display though can't interact because ACPI drivers is yet supported.
Currently likely stuck here forever because at this time Redox has no BIOS in aarch64 for easy framebuffer access, or an ACPI support for aarch64 to get access for virtio display.