diff --git a/ports/gcc/changes/gcc_gcc_config_host_darwin.c b/ports/gcc/changes/gcc_gcc_config_host_darwin.c
new file mode 100644
index 0000000..3f8e442
--- /dev/null
+++ b/ports/gcc/changes/gcc_gcc_config_host_darwin.c
@@ -0,0 +1,85 @@
+/* Darwin host-specific hook definitions.
+   Copyright (C) 2003-2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "config/host-darwin.h"
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+
+const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
+
+/* Yes, this is really supposed to work.  */
+/* This allows for a pagesize of 16384, which we have on Darwin20, but should
+   continue to work OK for pagesize 4096 which we have on earlier versions.
+   The size is 1 (binary) Gb.  */
+static char pch_address_space[65536*16384] __attribute__((aligned (16384)));
+
+/* Return the address of the PCH address space, if the PCH will fit in it.  */
+
+void *
+darwin_gt_pch_get_address (size_t sz, int fd ATTRIBUTE_UNUSED)
+{
+  if (sz <= sizeof (pch_address_space))
+    return pch_address_space;
+  else
+    return NULL;
+}
+
+/* Check ADDR and SZ for validity, and deallocate (using munmap) that part of
+   pch_address_space beyond SZ.  */
+
+int
+darwin_gt_pch_use_address (void *addr, size_t sz, int fd, size_t off)
+{
+  const size_t pagesize = getpagesize();
+  void *mmap_result;
+  int ret;
+
+  gcc_assert ((size_t)pch_address_space % pagesize == 0
+	      && sizeof (pch_address_space) % pagesize == 0);
+  
+  ret = (addr == pch_address_space && sz <= sizeof (pch_address_space));
+  if (! ret)
+    sz = 0;
+
+  /* Round the size to a whole page size.  Normally this is a no-op.  */
+  sz = (sz + pagesize - 1) / pagesize * pagesize;
+
+  if (munmap (pch_address_space + sz, sizeof (pch_address_space) - sz) != 0)
+    fatal_error (input_location,
+		 "could not unmap %<pch_address_space%>: %m");
+
+  if (ret)
+    {
+      mmap_result = mmap (addr, sz,
+			  PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
+			  fd, off);
+
+      /* The file might not be mmap-able.  */
+      ret = mmap_result != (void *) MAP_FAILED;
+
+      /* Sanity check for broken MAP_FIXED.  */
+      gcc_assert (!ret || mmap_result == addr);
+    }
+
+  return ret;
+}
diff --git a/ports/gcc/port.sh b/ports/gcc/port.sh
index 295e4dd..da5d278 100755
--- a/ports/gcc/port.sh
+++ b/ports/gcc/port.sh
@@ -30,6 +30,7 @@ cp ports/gcc/changes/gcc_fixincludes_mkfixinc.sh bin/gcc-src/fixincludes/mkfixin
 cp ports/gcc/changes/gcc_gcc_config_essence.h bin/gcc-src/gcc/config/essence.h
 cp ports/gcc/changes/gcc_gcc_config_i386_t-x86_64-essence bin/gcc-src/gcc/config/i386/t-x86_64-essence
 cp ports/gcc/changes/gcc_gcc_config.gcc bin/gcc-src/gcc/config.gcc
+cp ports/gcc/changes/gcc_gcc_config_host_darwin.c bin/gcc-src/gcc/config/host-darwin.c
 cp ports/gcc/changes/gcc_libgcc_config.host bin/gcc-src/libgcc/config.host
 cp ports/gcc/changes/gcc_libstdc++-v3_configure bin/gcc-src/libstdc++-v3/configure
 
diff --git a/ports/harfbuzz/build.sh b/ports/harfbuzz/build.sh
index 59e62bc..cbb5501 100755
--- a/ports/harfbuzz/build.sh
+++ b/ports/harfbuzz/build.sh
@@ -18,17 +18,23 @@ if [ ! -d "bin/harfbuzz" ]; then
 
 	cd bin/harfbuzz/src
 
-	find . -type f -exec sed -i 's/#include <assert.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <atomic.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <builtins.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <float.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <locale.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <math.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <stdio.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <stdlib.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <string.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <unistd.h>/#include <essence.h>/g' {} \;
-	find . -type f -exec sed -i 's/#include <xlocale.h>/#include <essence.h>/g' {} \;
+	SED=sed
+
+	if [[ "$OSTYPE" == "darwin"* ]]; then
+		SED=gsed
+	fi
+
+	find . -type f -exec $SED -i 's/#include <assert.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <atomic.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <builtins.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <float.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <locale.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <math.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <stdio.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <stdlib.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <string.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <unistd.h>/#include <essence.h>/g' {} \;
+	find . -type f -exec $SED -i 's/#include <xlocale.h>/#include <essence.h>/g' {} \;
 
 	CC="x86_64-essence-g++ -DHAVE_CONFIG_H -I. -I.. -ffreestanding -fno-rtti -g -O2 -DHB_TINY -fno-exceptions -fno-threadsafe-statics -fvisibility-inlines-hidden"
 
@@ -80,7 +86,7 @@ if [ ! -d "bin/harfbuzz" ]; then
 	$CC -c hb-unicode.cc -o hb-unicode.o
 	$CC -c hb-ft.cc -o hb-ft.o
 
-	ar cr libharfbuzz.a hb-aat-layout.o hb-aat-map.o hb-blob.o hb-buffer-serialize.o hb-buffer.o hb-common.o hb-face.o hb-fallback-shape.o hb-font.o hb-map.o hb-number.o hb-ot-cff1-table.o hb-ot-cff2-table.o hb-ot-color.o hb-ot-face.o hb-ot-font.o hb-ot-layout.o hb-ot-map.o hb-ot-math.o hb-ot-meta.o hb-ot-metrics.o hb-ot-name.o hb-ot-shape-complex-arabic.o hb-ot-shape-complex-default.o hb-ot-shape-complex-hangul.o hb-ot-shape-complex-hebrew.o hb-ot-shape-complex-indic-table.o hb-ot-shape-complex-indic.o hb-ot-shape-complex-khmer.o hb-ot-shape-complex-myanmar.o hb-ot-shape-complex-thai.o hb-ot-shape-complex-use-table.o hb-ot-shape-complex-use.o hb-ot-shape-complex-vowel-constraints.o hb-ot-shape-fallback.o hb-ot-shape-normalize.o hb-ot-shape.o hb-ot-tag.o hb-ot-var.o hb-set.o hb-shape-plan.o hb-shape.o hb-shaper.o hb-static.o hb-ucd.o hb-unicode.o hb-ft.o
+	x86_64-essence-ar cr libharfbuzz.a hb-aat-layout.o hb-aat-map.o hb-blob.o hb-buffer-serialize.o hb-buffer.o hb-common.o hb-face.o hb-fallback-shape.o hb-font.o hb-map.o hb-number.o hb-ot-cff1-table.o hb-ot-cff2-table.o hb-ot-color.o hb-ot-face.o hb-ot-font.o hb-ot-layout.o hb-ot-map.o hb-ot-math.o hb-ot-meta.o hb-ot-metrics.o hb-ot-name.o hb-ot-shape-complex-arabic.o hb-ot-shape-complex-default.o hb-ot-shape-complex-hangul.o hb-ot-shape-complex-hebrew.o hb-ot-shape-complex-indic-table.o hb-ot-shape-complex-indic.o hb-ot-shape-complex-khmer.o hb-ot-shape-complex-myanmar.o hb-ot-shape-complex-thai.o hb-ot-shape-complex-use-table.o hb-ot-shape-complex-use.o hb-ot-shape-complex-vowel-constraints.o hb-ot-shape-fallback.o hb-ot-shape-normalize.o hb-ot-shape.o hb-ot-tag.o hb-ot-var.o hb-set.o hb-shape-plan.o hb-shape.o hb-shaper.o hb-static.o hb-ucd.o hb-unicode.o hb-ft.o
 
 	cd ../../..
 fi
diff --git a/start.sh b/start.sh
index ebbe173..f6a3d36 100755
--- a/start.sh
+++ b/start.sh
@@ -6,11 +6,22 @@ cd "$(dirname "$0")"
 # Create the bin directory.
 mkdir -p bin
 
-# Check that we are running on a sensible platform.
-uname -o | grep Cygwin > /dev/null
-if [ $? -ne 1 ]; then
-	echo Cygwin is not supported. Please install a modern GNU/Linux distro.
-	exit
+if [[ "$OSTYPE" == "darwin"* ]]; then
+	export CC=gcc-11
+	export CXX=g++-11
+	export CPPFLAGS=-I/opt/homebrew/include
+	export LDFLAGS=-L/opt/homebrew/lib
+	alias md5sum="md5"
+	alias gcc="gcc-11"
+	alias g++="g++-11"
+	alias sed="gsed"
+else
+	# Check that we are running on a sensible platform.
+	uname -o | grep Cygwin > /dev/null
+	if [ $? -ne 1 ]; then
+		echo Cygwin is not supported. Please install a modern GNU/Linux distro.
+		exit
+	fi
 fi
 
 # Check that the source code is valid.
diff --git a/util/build.c b/util/build.c
index 73cc9b2..f0d2275 100644
--- a/util/build.c
+++ b/util/build.c
@@ -41,6 +41,10 @@ char compilerPath[4096];
 int argc;
 char **argv;
 
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
 #include "build_common.h"
 
 BuildFont fonts[] = {
@@ -327,7 +331,9 @@ void BuildUtilities() {
 
 	BUILD_UTILITY("render_svg", "-lm", "");
 	BUILD_UTILITY("build_core", "-pthread -DPARALLEL_BUILD", "");
+#ifndef __APPLE__ // Luigi doesn't support macOS.
 	BUILD_UTILITY("config_editor", "-lX11 -Wno-unused-parameter", "");
+#endif
 	BUILD_UTILITY("reflect_gen", "", "designer/");
 
 	if (CheckDependencies("Utilities.DesignerHeader")) {
@@ -339,8 +345,7 @@ void BuildUtilities() {
 		}
 	}
 
-	//util/designer_luigi.c -lX11 -lm
-
+#ifndef __APPLE__ // Luigi doesn't support macOS.
 	if (CheckDependencies("Utilities.Designer1") || CheckDependencies("Utilities.Designer2")) {
 		if (!CallSystem("gcc -MMD -o bin/designer.o -c util/designer/designer.c -g -std=c2x -fsanitize=address " WARNING_FLAGS_C)
 					&& !CallSystem("gcc -MMD -o bin/designer_luigi.o -c util/designer/designer_luigi.c -g -std=c2x " WARNING_FLAGS_C)
@@ -349,6 +354,7 @@ void BuildUtilities() {
 			ParseDependencies("bin/designer_luigi.d", "Utilities.Designer2", false);
 		}
 	}
+#endif
 }
 
 void Build(int optimise, bool compile) {
@@ -559,6 +565,7 @@ bool PatchGCC() {
 	if (CallSystem("cp ports/gcc/changes/gcc_gcc_config_essence.h bin/gcc-" GCC_VERSION "/gcc/config/essence.h")) return false; 
 	if (CallSystem("cp ports/gcc/changes/gcc_gcc_config_i386_t-x86_64-essence bin/gcc-" GCC_VERSION "/gcc/config/i386/t-x86_64-essence")) return false; 
 	if (CallSystem("cp ports/gcc/changes/gcc_gcc_config.gcc bin/gcc-" GCC_VERSION "/gcc/config.gcc")) return false; 
+	if (CallSystem("cp ports/gcc/changes/gcc_gcc_config_host_darwin.c bin/gcc-" GCC_VERSION "/gcc/config/host-darwin.c")) return false;
 	if (CallSystem("cp ports/gcc/changes/gcc_libgcc_config.host bin/gcc-" GCC_VERSION "/libgcc/config.host")) return false; 
 	if (CallSystem("cp ports/gcc/changes/gcc_libstdc++-v3_configure bin/gcc-" GCC_VERSION "/libstdc++-v3/configure")) return false; 
 
@@ -582,22 +589,30 @@ void BuildCrossCompiler() {
 		printf("- You must fully update your system before building.\n\n");
 
 		bool missingPackages = false;
-		if (CallSystem("g++ --version > /dev/null 2>&1")) { printf("Error: Missing GCC/G++.\n"); missingPackages = true; }
-		if (CallSystem("make --version > /dev/null 2>&1")) { printf("Error: Missing GNU Make.\n"); missingPackages = true; }
-		if (CallSystem("bison --version > /dev/null 2>&1")) { printf("Error: Missing GNU Bison.\n"); missingPackages = true; }
-		if (CallSystem("flex --version > /dev/null 2>&1")) { printf("Error: Missing Flex.\n"); missingPackages = true; }
-		if (CallSystem("curl --version > /dev/null 2>&1")) { printf("Error: Missing curl.\n"); missingPackages = true; }
-		if (CallSystem("nasm --version > /dev/null 2>&1")) { printf("Error: Missing nasm.\n"); missingPackages = true; }
-		if (CallSystem("ctags --version > /dev/null 2>&1")) { printf("Error: Missing ctags.\n"); missingPackages = true; }
-		if (CallSystem("xz --version > /dev/null 2>&1")) { printf("Error: Missing xz.\n"); missingPackages = true; }
-		if (CallSystem("gzip --version > /dev/null 2>&1")) { printf("Error: Missing gzip.\n"); missingPackages = true; }
-		if (CallSystem("tar --version > /dev/null 2>&1")) { printf("Error: Missing tar.\n"); missingPackages = true; }
-		if (CallSystem("grep --version > /dev/null 2>&1")) { printf("Error: Missing grep.\n"); missingPackages = true; }
-		if (CallSystem("sed --version > /dev/null 2>&1")) { printf("Error: Missing sed.\n"); missingPackages = true; }
-		if (CallSystem("awk --version > /dev/null 2>&1")) { printf("Error: Missing awk.\n"); missingPackages = true; }
-		if (CallSystem("gcc -lmpc 2>&1 | grep undefined > /dev/null")) { printf("Error: Missing GNU MPC.\n"); missingPackages = true; }
-		if (CallSystem("gcc -lmpfr 2>&1 | grep undefined > /dev/null")) { printf("Error: Missing GNU MPFR.\n"); missingPackages = true; }
-		if (CallSystem("gcc -lgmp 2>&1 | grep undefined > /dev/null")) { printf("Error: Missing GNU GMP.\n"); missingPackages = true; }
+		if (CallSystem("which g++ > /dev/null 2>&1")) { printf("Error: Missing GCC/G++.\n"); missingPackages = true; }
+		if (CallSystem("which make > /dev/null 2>&1")) { printf("Error: Missing GNU Make.\n"); missingPackages = true; }
+		if (CallSystem("which bison > /dev/null 2>&1")) { printf("Error: Missing GNU Bison.\n"); missingPackages = true; }
+		if (CallSystem("which flex > /dev/null 2>&1")) { printf("Error: Missing Flex.\n"); missingPackages = true; }
+		if (CallSystem("which curl > /dev/null 2>&1")) { printf("Error: Missing curl.\n"); missingPackages = true; }
+		if (CallSystem("which nasm > /dev/null 2>&1")) { printf("Error: Missing nasm.\n"); missingPackages = true; }
+		if (CallSystem("which ctags > /dev/null 2>&1")) { printf("Error: Missing ctags.\n"); missingPackages = true; }
+		if (CallSystem("which xz > /dev/null 2>&1")) { printf("Error: Missing xz.\n"); missingPackages = true; }
+		if (CallSystem("which gzip > /dev/null 2>&1")) { printf("Error: Missing gzip.\n"); missingPackages = true; }
+		if (CallSystem("which tar > /dev/null 2>&1")) { printf("Error: Missing tar.\n"); missingPackages = true; }
+		if (CallSystem("which grep > /dev/null 2>&1")) { printf("Error: Missing grep.\n"); missingPackages = true; }
+		if (CallSystem("which sed > /dev/null 2>&1")) { printf("Error: Missing sed.\n"); missingPackages = true; }
+		if (CallSystem("which awk > /dev/null 2>&1")) { printf("Error: Missing awk.\n"); missingPackages = true; }
+
+#ifdef __APPLE__
+		if (CallSystem("gcc -L/opt/homebrew/lib -lmpc 2>&1 | grep -i undefined > /dev/null")) { printf("Error: Missing GNU MPC.\n"); missingPackages = true; }
+		if (CallSystem("gcc -L/opt/homebrew/lib -lmpfr 2>&1 | grep -i undefined > /dev/null")) { printf("Error: Missing GNU MPFR.\n"); missingPackages = true; }
+		if (CallSystem("gcc -L/opt/homebrew/lib -lgmp 2>&1 | grep -i undefined > /dev/null")) { printf("Error: Missing GNU GMP.\n"); missingPackages = true; }
+#else
+		if (CallSystem("gcc -lmpc 2>&1 | grep -i undefined > /dev/null")) { printf("Error: Missing GNU MPC.\n"); missingPackages = true; }
+		if (CallSystem("gcc -lmpfr 2>&1 | grep -i undefined > /dev/null")) { printf("Error: Missing GNU MPFR.\n"); missingPackages = true; }
+		if (CallSystem("gcc -lgmp 2>&1 | grep -i undefined > /dev/null")) { printf("Error: Missing GNU GMP.\n"); missingPackages = true; }
+#endif
+
 		if (missingPackages) exit(0);
 
 		char installationFolder[4096];