#!/usr/bin/env bash # Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # The macOS port's C compiler (make/macos.mk; the installer builds SDL with # it too): zig cc once for each architecture in MACOS_ARCHS -- by default # Apple silicon and Intel -- with the results joined into one universal file # by llvm-lipo, as Apple's own clang does when given two -arch flags. It # takes what a C compiler takes: with -c it makes a universal object, else a # universal program. The first architecture's run is exactly the call it was # given, so its dependency file (-MMD) comes out as a plain compiler's; the # other runs leave theirs out. With one architecture, or with no -o (a # preprocessing run), it is zig cc for the first architecture alone. # # Programs run on macOS MACOS_MIN or newer: Ventura, which every Apple # silicon Mac runs and the Intel ones from 2017 on. # # From the environment (toolchains/config.mk, which make exports): ZIG and # its cache folders, MACOS_SDK and MACOS_LIPO. # # Usage: cc.sh COMPILER-ARGUMENTS... # cc.sh --minimum prints MACOS_MIN (for an Info.plist) set -euo pipefail MACOS_MIN=13.0 read -r -a archs <<< "${MACOS_ARCHS:-aarch64 x86_64}" if [[ "${1:-}" == --minimum ]]; then printf '%s\n' "$MACOS_MIN" exit 0 fi if [[ -z "${ZIG:-}" || -z "${MACOS_SDK:-}" || -z "${MACOS_LIPO:-}" ]]; then echo "$0: ZIG, MACOS_SDK or MACOS_LIPO is not set; run ./install.sh install toolchain:macos" >&2 exit 1 fi out="" compile=0 preprocess=0 prev="" for arg in "$@"; do if [[ "$prev" == -o ]]; then out="$arg" fi case "$arg" in -c) compile=1 ;; -E) preprocess=1 ;; esac prev="$arg" done # zig brings the C library's headers and libSystem's stubs; the SDK the # rest, after them (so the caller's own come first): its other headers, its # frameworks, and, for a link, the stub libraries beside them. zig cc # builds for UBSan unless told not to, and would then want its runtime; and # it warns, as no other port's compiler does, at __DATE__ and __TIME__ (a # build that uses them cannot be reproduced), which -Werror would make fatal. flags=(-fno-sanitize=undefined -Wno-date-time -idirafter "$MACOS_SDK/usr/include" -F"$MACOS_SDK/System/Library/Frameworks") if [[ $compile -eq 0 && $preprocess -eq 0 ]]; then flags+=(-L"$MACOS_SDK/usr/lib") fi # zig refuses a target with a version for a run that only preprocesses (a # build system asking what the compiler defines), and the version makes no # difference to that. target() { if [[ $preprocess -eq 1 ]]; then printf '%s-macos\n' "$1" else printf '%s-macos.%s\n' "$1" "$MACOS_MIN" fi } if [[ ${#archs[@]} -eq 1 || -z "$out" ]]; then exec "$ZIG" cc -target "$(target "${archs[0]}")" "$@" "${flags[@]}" fi slices=() trap 'rm -f "${slices[@]}"' EXIT for arch in "${archs[@]}"; do slice="$out.$arch" slices+=("$slice") if [[ ${#slices[@]} -eq 1 ]]; then "$ZIG" cc -target "$(target "$arch")" "$@" "${flags[@]}" mv -f "$out" "$slice" continue fi args=() skip=0 for arg in "$@"; do if [[ $skip -eq 1 ]]; then skip=0 continue fi case "$arg" in -o) args+=(-o "$slice"); skip=1 ;; -MD|-MMD|-MP) ;; -MF|-MT|-MQ) skip=1 ;; *) args+=("$arg") ;; esac done "$ZIG" cc -target "$(target "$arch")" "${args[@]}" "${flags[@]}" done "$MACOS_LIPO" -create "${slices[@]}" -output "$out"