Mac build is now universal.

This commit is contained in:
Scott Duensing 2026-09-05 00:37:42 -05:00
parent b8b934c271
commit 43b53de960
8 changed files with 80 additions and 33 deletions

View file

@ -229,6 +229,16 @@ Fixes
version header, and the manual are generated by CMake. The manual is
embedded again and extracted as Singe/Manual.pdf.
- One command builds Singe from a clean checkout on a Debian based
system: ./build-all.sh <platform> <arch> installs the host packages,
then CMake fetches zig (the compiler for every target), the Pi's
platform packages and the macOS SDK into .builddir/toolchains and
builds every library and Singe itself. The results are a Linux binary
that runs on glibc 2.28 or newer, a Windows 10 or newer binary, a
64-bit Raspberry Pi OS (bullseye or newer) binary and a macOS 13 or
newer Apple silicon binary. The toolchains repository is no longer
needed. See INSTALL.
SINGE 2.10
==========

View file

@ -505,6 +505,7 @@ elseif(KANGAROO_OS STREQUAL "macos")
-Wl,-weak_framework,Metal
-Wl,-weak_framework,QuartzCore
-Wl,-weak_framework,CoreHaptics
-Wl,-weak_framework,UniformTypeIdentifiers
-liconv
-lc++
)
@ -552,17 +553,24 @@ else()
message(FATAL_ERROR "Unknown KANGAROO_OS: ${KANGAROO_OS}")
endif()
# FFmpeg's hardware decoding backends (VA-API, VDPAU, DRM, V4L2) are whatever the superbuild
# configured; its pkg-config files name the system libraries they need, so read them back.
if(KANGAROO_OS STREQUAL "linux" OR KANGAROO_OS STREQUAL "pi")
# FFmpeg's hardware decoding backends (VA-API, VDPAU, DRM, V4L2, VideoToolbox) are whatever the
# superbuild configured; its pkg-config files name the system libraries and frameworks they need, so
# read them back.
if(NOT KANGAROO_OS STREQUAL "windows")
foreach(pc libavutil libavcodec)
set(pcFile ${BUILD_DIR}/lib/pkgconfig/${pc}.pc)
if(EXISTS ${pcFile})
file(STRINGS ${pcFile} pcLibs REGEX "^Libs:")
string(REGEX REPLACE "^Libs: *" "" pcLibs "${pcLibs}")
separate_arguments(pcLibs)
set(framework FALSE)
foreach(token ${pcLibs})
if(token MATCHES "^-l" AND NOT token MATCHES "^-l(avutil|avcodec|z|m|atomic|pthread)$")
if(framework)
list(APPEND SYSTEM_LIBS -Wl,-framework,${token})
set(framework FALSE)
elseif(token STREQUAL "-framework")
set(framework TRUE)
elseif(token MATCHES "^-l" AND NOT token MATCHES "^-l(avutil|avcodec|z|m|atomic|pthread|iconv)$")
list(APPEND SYSTEM_LIBS ${token})
endif()
endforeach()
@ -600,12 +608,13 @@ set(STATIC_LIBS
${BUILD_DIR}/lib/libcrypto.a
${BUILD_DIR}/lib/libssl.a
)
if(NOT KANGAROO_OS STREQUAL "macos")
list(APPEND STATIC_LIBS
${BUILD_DIR}/lib/libjpeg.a
${BUILD_DIR}/lib/libpng16.a
)
# SDL3_image builds its own jpeg and png decoders where the platform has none (macOS uses ImageIO
# for jpeg); link whichever archives it produced.
foreach(imageLib libjpeg.a libpng16.a)
if(EXISTS ${BUILD_DIR}/lib/${imageLib})
list(APPEND STATIC_LIBS ${BUILD_DIR}/lib/${imageLib})
endif()
endforeach()
# System libraries follow the static ones so their symbols resolve for everything above.
# Apple's linker has no --start-group, so the list is repeated there instead.

21
INSTALL
View file

@ -59,7 +59,7 @@ library (zlib, zstd, SDL3 and its satellites, OpenSSL, FFmpeg) into
copied to .builddir/Singe-v<version>-<Os>-<arch>.
Host packages (what build-all.sh installs): build-essential cmake
pkg-config perl nasm imagemagick lua5.4 ffmpeg asciidoctor
pkg-config perl nasm llvm imagemagick lua5.4 ffmpeg asciidoctor
ruby-asciidoctor-pdf autoconf automake libtool libasound-dev libxi-dev
libvdpau-dev libva-dev libdrm-dev libgl-dev libx11-dev.
@ -76,18 +76,19 @@ libraries itself, so nothing else is installed:
A developer build with the host's own gcc, glibc and symbols is the
linux-x86_64-gcc preset (binary Singe-v3.00-Linux-x86_64-gcc).
macOS builds with zig too, but needs an Apple SDK for the frameworks,
which Apple's licence does not allow a build script to fetch. Provide it
once as a tarball holding a single MacOSX*.sdk directory:
macOS (Apple silicon, macOS 13 or newer) builds with zig too, but needs
an Apple SDK for the frameworks.
Apple only ships it inside Xcode, so by default the build fetches the
MacOSX15.5 SDK tarball from the community mirror osxcross users share
(github.com/joseluisq/macosx-sdks), checks its SHA-256, and unpacks it to
.builddir/toolchains/MacOSX.sdk on first use. To avoid the download,
put a tarball holding a single MacOSX*.sdk directory at
.builddir/toolchains/MacOSX.sdk.tar.xz
On a Mac with Xcode installed, osxcross's tools/gen_sdk_package.sh makes
exactly that tarball from the installed SDK. The build unpacks it to
.builddir/toolchains/MacOSX.sdk on first use. Alternatively point
SINGE_MACOS_SDK at an unpacked SDK, or set SINGE_MACOS_SDK_URL (and
SINGE_MACOS_SDK_SHA256) to have the build fetch the tarball from a
location of your choosing. Then:
(on a Mac with Xcode, osxcross's tools/gen_sdk_package.sh makes exactly
that), or point SINGE_MACOS_SDK at an unpacked SDK. SINGE_MACOS_SDK_URL
and SINGE_MACOS_SDK_SHA256 pick a different mirror. Then:
./build-all.sh macos aarch64

View file

@ -61,6 +61,7 @@ sudo apt-get install -y \
pkg-config \
perl \
nasm \
llvm \
imagemagick \
lua5.4 \
ffmpeg \

View file

@ -254,10 +254,17 @@ endif()
# With a classic cross toolchain every tool is <triple>-<tool>; with zig each is named outright.
if(SINGE_ZIG_TARGET)
set(ffmpegTools --enable-cross-compile --cc=${SB_CC} --cxx=${SB_CXX} --ar=${CMAKE_AR} --ranlib=${SB_RANLIB} --windres=${CMAKE_RC_COMPILER})
# The host's binutils nm reads x86 ELF and PE objects but not aarch64 or Mach-O ones; FFmpeg only
# uses nm to learn the symbol prefix, which is empty everywhere but macOS, so the others go without.
# FFmpeg only uses nm to learn the symbol prefix. The host's binutils nm reads x86 ELF and PE
# objects but not aarch64 or Mach-O ones; the prefix is empty on Linux either way, and on macOS
# (where it is an underscore) llvm-nm from Debian's llvm package reads Mach-O.
if(KANGAROO_ARCH STREQUAL "x86_64")
list(APPEND ffmpegTools --nm=nm)
elseif(KANGAROO_OS STREQUAL "macos")
find_program(SINGE_LLVM_NM NAMES llvm-nm llvm-nm-21 llvm-nm-20 llvm-nm-19 llvm-nm-18 llvm-nm-17 llvm-nm-16 llvm-nm-15)
if(NOT SINGE_LLVM_NM)
message(FATAL_ERROR "llvm-nm is needed for the macOS FFmpeg build (apt-get install llvm).")
endif()
list(APPEND ffmpegTools --nm=${SINGE_LLVM_NM})
endif()
else()
set(ffmpegTools --cross-prefix=${SINGE_TRIPLE}- --cc=${SB_CC} --cxx=${SB_CXX} --ranlib=${SB_RANLIB})

View file

@ -23,18 +23,23 @@
# script fetch. The SDK is expected, in this order:
# 1. an unpacked SDK at SINGE_MACOS_SDK (default .builddir/toolchains/MacOSX.sdk);
# 2. a tarball at .builddir/toolchains/MacOSX.sdk.tar.xz, unpacked on first use;
# 3. SINGE_MACOS_SDK_URL (with SINGE_MACOS_SDK_SHA256), downloaded and unpacked on first use.
# See INSTALL for how to make the tarball from Xcode.
# 3. SINGE_MACOS_SDK_URL (with SINGE_MACOS_SDK_SHA256), downloaded and unpacked on first use;
# the default points at the community mirror osxcross users share (github.com/joseluisq/
# macosx-sdks), pinned to one SDK release and its published SHA-256.
# See INSTALL for how to make the tarball from Xcode instead.
include(${CMAKE_CURRENT_LIST_DIR}/zig.cmake)
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm64)
# Oldest macOS the binary runs on (Ventura: Intel Macs from 2017 and every Apple silicon Mac).
set(SINGE_MACOS_VERSION 13.0)
get_filename_component(sdkToolchains ${CMAKE_CURRENT_LIST_DIR}/../../.builddir/toolchains ABSOLUTE)
set(SINGE_MACOS_SDK ${sdkToolchains}/MacOSX.sdk CACHE PATH "Unpacked Apple SDK for the macOS build")
set(SINGE_MACOS_SDK_URL "" CACHE STRING "Where to fetch the Apple SDK tarball from, if anywhere")
set(SINGE_MACOS_SDK_SHA256 "" CACHE STRING "SHA-256 of that tarball")
set(SINGE_MACOS_SDK_URL "https://github.com/joseluisq/macosx-sdks/releases/download/15.5/MacOSX15.5.sdk.tar.xz" CACHE STRING "Where to fetch the Apple SDK tarball from; empty to never download")
set(SINGE_MACOS_SDK_SHA256 "c15cf0f3f17d714d1aa5a642da8e118db53d79429eb015771ba816aa7c6c1cbd" CACHE STRING "SHA-256 of that tarball; empty to skip the check")
set(sdkTarball ${sdkToolchains}/MacOSX.sdk.tar.xz)
if(NOT EXISTS ${SINGE_MACOS_SDK}/System/Library/Frameworks/Cocoa.framework)
if((NOT EXISTS ${sdkTarball}) AND SINGE_MACOS_SDK_URL)
@ -68,9 +73,22 @@ if(NOT EXISTS ${SINGE_MACOS_SDK}/System/Library/Frameworks/Cocoa.framework)
message(FATAL_ERROR "No Apple SDK at ${SINGE_MACOS_SDK}. Put an SDK tarball at ${sdkTarball} (see INSTALL), or set SINGE_MACOS_SDK to an unpacked SDK, or SINGE_MACOS_SDK_URL to fetch one.")
endif()
# The SDK's headers come after zig's own libc headers; frameworks and stub libraries from the SDK.
singeZigToolchain(aarch64-macos "--sysroot=${SINGE_MACOS_SDK} -idirafter ${SINGE_MACOS_SDK}/usr/include -F${SINGE_MACOS_SDK}/System/Library/Frameworks -L${SINGE_MACOS_SDK}/usr/lib")
set(CMAKE_OSX_SYSROOT ${SINGE_MACOS_SDK} CACHE PATH "Apple SDK" FORCE)
# No --sysroot: zig would then prefix every -L path with it, the superbuild's own lib directory
# included. The SDK is named outright instead: its usr/include (libDER and other non-libc pieces)
# after zig's own libc headers, its frameworks, and its stub libraries. The SDK's CMTag.h uses two
# macOS 14 types without an availability guard, and FFmpeg's configure makes that an error with
# -Werror=partial-availability; the trailing -Wno-unguarded-availability-new wins over it.
singeZigToolchain(aarch64-macos.${SINGE_MACOS_VERSION} "-idirafter ${SINGE_MACOS_SDK}/usr/include -F${SINGE_MACOS_SDK}/System/Library/Frameworks -L${SINGE_MACOS_SDK}/usr/lib -Wno-unguarded-availability-new")
# SDL3 compiles Objective-C, which the same zig wrappers handle, and CMake's Darwin support insists
# on an install_name_tool even though nothing here links dynamically; llvm's stands in.
set(CMAKE_OBJC_COMPILER ${CMAKE_C_COMPILER} CACHE FILEPATH "" FORCE)
set(CMAKE_OBJCXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE FILEPATH "" FORCE)
find_program(SINGE_INSTALL_NAME_TOOL NAMES llvm-install-name-tool llvm-install-name-tool-21 llvm-install-name-tool-20 llvm-install-name-tool-19 llvm-install-name-tool-18 llvm-install-name-tool-17 llvm-install-name-tool-16 llvm-install-name-tool-15)
if(NOT SINGE_INSTALL_NAME_TOOL)
message(FATAL_ERROR "llvm-install-name-tool is needed for the macOS build (apt-get install llvm).")
endif()
set(CMAKE_INSTALL_NAME_TOOL ${SINGE_INSTALL_NAME_TOOL} CACHE FILEPATH "" FORCE)
set(CMAKE_OSX_SYSROOT "" CACHE PATH "Left empty; the wrappers name the SDK themselves" FORCE)
set(CMAKE_OSX_ARCHITECTURES "" CACHE STRING "Left empty; the zig target names the architecture" FORCE)
set(CMAKE_FIND_ROOT_PATH ${SINGE_MACOS_SDK})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

View file

@ -50,9 +50,10 @@ endif()
function(singeZigToolchain target extra)
set(dir ${CMAKE_BINARY_DIR}/zig-${target})
file(MAKE_DIRECTORY ${dir})
# The compiler wrappers drop one flag: FFmpeg's configure adds binutils' --pic-executable ASLR
# workaround to every test link on Windows, and zig's linker driver refuses it. They also add
set(filter "for a in \"$@\"; do [[ $a == -Wl,--pic-executable* ]] || args+=(\"$a\"); done")
# The compiler wrappers drop two flags FFmpeg's configure adds to every test link and zig's linker
# driver refuses: binutils' --pic-executable ASLR workaround on Windows and Apple's
# -dynamic,-search_paths_first on macOS. They also add
set(filter "for a in \"$@\"; do [[ $a == -Wl,--pic-executable* || $a == -Wl,-dynamic* ]] || args+=(\"$a\"); done")
# -fno-sanitize=undefined: zig cc instruments for UBSan by default and expects its runtime at
# link time; a release build wants neither.
# extra goes after the caller's arguments so the caller's -L directories are searched first.

View file

@ -137,7 +137,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
#if defined(MACOS)
# define OS_CODE 7
# ifndef Z_SOLO
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os