From 925e670b550a6d8038a414a631c9d63847fe5222 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Mon, 1 May 2023 17:39:19 -0600 Subject: [PATCH 1/4] darling: init at unstable-2023-05-02 --- .../emulators/darling/default.nix | 197 ++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 + 2 files changed, 199 insertions(+) create mode 100644 pkgs/applications/emulators/darling/default.nix diff --git a/pkgs/applications/emulators/darling/default.nix b/pkgs/applications/emulators/darling/default.nix new file mode 100644 index 000000000000..053b82cfedee --- /dev/null +++ b/pkgs/applications/emulators/darling/default.nix @@ -0,0 +1,197 @@ +{ clangStdenv +, lib +, runCommandWith +, writeShellScript +, fetchFromGitHub +, fetchpatch + +, freetype +, libjpeg +, libpng +, libtiff +, giflib +, libX11 +, libXext +, libXrandr +, libXcursor +, libxkbfile +, cairo +, libglvnd +, fontconfig +, dbus +, libGLU +, fuse +, ffmpeg +, pulseaudio + +, makeWrapper +, python2 +, python3 +, cmake +, ninja +, pkg-config +, bison +, flex + +, libbsd +, openssl + +, xdg-user-dirs + +, addOpenGLRunpath + +# Whether to pre-compile Python 2 bytecode for performance. +, compilePy2Bytecode ? false +}: +let + stdenv = clangStdenv; + + # The build system invokes clang to compile Darwin executables. + # In this case, our cc-wrapper must not be used. + ccWrapperBypass = runCommandWith { + inherit stdenv; + name = "cc-wrapper-bypass"; + runLocal = false; + derivationArgs = { + template = writeShellScript "template" '' + for (( i=1; i<=$#; i++)); do + j=$((i+1)) + if [[ "''${!i}" == "-target" && "''${!j}" == *"darwin"* ]]; then + # their flags must take precedence + exec @unwrapped@ "$@" $NIX_CFLAGS_COMPILE + fi + done + exec @wrapped@ "$@" + ''; + }; + } '' + unwrapped_bin=${stdenv.cc.cc}/bin + wrapped_bin=${stdenv.cc}/bin + + mkdir -p $out/bin + + unwrapped=$unwrapped_bin/$CC wrapped=$wrapped_bin/$CC \ + substituteAll $template $out/bin/$CC + unwrapped=$unwrapped_bin/$CXX wrapped=$wrapped_bin/$CXX \ + substituteAll $template $out/bin/$CXX + + chmod +x $out/bin/$CC $out/bin/$CXX + ''; + + wrappedLibs = [ + # To find all of them: rg -w wrap_elf + + # src/native/CMakeLists.txt + freetype + libjpeg + libpng + libtiff + giflib + libX11 + libXext + libXrandr + libXcursor + libxkbfile + cairo + libglvnd + fontconfig + dbus + libGLU + + # src/external/darling-dmg/CMakeLists.txt + fuse + + # src/CoreAudio/CMakeLists.txt + ffmpeg + pulseaudio + ]; +in stdenv.mkDerivation { + pname = "darling"; + version = "unstable-2023-05-02"; + + src = fetchFromGitHub { + owner = "darlinghq"; + repo = "darling"; + rev = "557e7e9dece394a3f623825679474457e5b64fd0"; + fetchSubmodules = true; + hash = "sha256-SOoLaV7wg33qRHPQXkdMvrY++CvoG85kwd6IU6DkYa0="; + }; + + + postPatch = '' + # We have to be careful - Patching everything indiscriminately + # would affect Darwin scripts as well + chmod +x src/external/bootstrap_cmds/migcom.tproj/mig.sh + patchShebangs \ + src/external/bootstrap_cmds/migcom.tproj/mig.sh \ + src/external/darlingserver/scripts \ + src/external/openssl_certificates/scripts + + substituteInPlace src/startup/CMakeLists.txt --replace SETUID "" + substituteInPlace src/external/basic_cmds/CMakeLists.txt --replace SETGID "" + ''; + + nativeBuildInputs = [ + bison + ccWrapperBypass + cmake + flex + makeWrapper + ninja + pkg-config + python3 + ] + ++ lib.optional compilePy2Bytecode python2; + buildInputs = wrappedLibs ++ [ + libbsd + openssl + stdenv.cc.libc.linuxHeaders + ]; + + # Breaks valid paths like + # Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include + dontFixCmake = true; + + # src/external/objc4 forces OBJC_IS_DEBUG_BUILD=1, which conflicts with NDEBUG + # TODO: Fix in a better way + cmakeBuildType = " "; + + cmakeFlags = [ + "-DTARGET_i386=OFF" + "-DCOMPILE_PY2_BYTECODE=${if compilePy2Bytecode then "ON" else "OFF"}" + "-DDARLINGSERVER_XDG_USER_DIR_CMD=${xdg-user-dirs}/bin/xdg-user-dir" + ]; + + env.NIX_CFLAGS_COMPILE = "-Wno-macro-redefined -Wno-unused-command-line-argument"; + + # Linux .so's are dlopen'd by wrapgen during the build + env.LD_LIBRARY_PATH = lib.makeLibraryPath wrappedLibs; + + # Breaks shebangs of Darwin scripts + dontPatchShebangs = true; + + postFixup = '' + echo "Checking for references to $NIX_STORE in Darling root..." + + set +e + grep -r --exclude=mldr "$NIX_STORE" $out/libexec/darling + ret=$? + set -e + + if [[ $ret == 0 ]]; then + echo "Found references to $NIX_STORE in Darling root (see above)" + exit 1 + fi + + patchelf --add-rpath "${lib.makeLibraryPath wrappedLibs}:${addOpenGLRunpath.driverLink}/lib" \ + $out/libexec/darling/usr/libexec/darling/mldr + ''; + + meta = with lib; { + description = "Open-source Darwin/macOS emulation layer for Linux"; + homepage = "https://www.darlinghq.org"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ zhaofengli ]; + platforms = [ "x86_64-linux" ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index b71f0c6f1da8..7a18e54c02d2 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -493,6 +493,8 @@ with pkgs; dae = callPackage ../tools/networking/dae { }; + darling = callPackage ../applications/emulators/darling { }; + databricks-sql-cli = python3Packages.callPackage ../applications/misc/databricks-sql-cli { }; dhallDirectoryToNix = callPackage ../build-support/dhall/directory-to-nix.nix { }; From 29bca808c17023197030181e2d064ae1a49d97b1 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Mon, 1 May 2023 17:39:19 -0600 Subject: [PATCH 2/4] darling: Install source-built SDK --- .../emulators/darling/default.nix | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/pkgs/applications/emulators/darling/default.nix b/pkgs/applications/emulators/darling/default.nix index 053b82cfedee..988ca7964794 100644 --- a/pkgs/applications/emulators/darling/default.nix +++ b/pkgs/applications/emulators/darling/default.nix @@ -117,6 +117,7 @@ in stdenv.mkDerivation { hash = "sha256-SOoLaV7wg33qRHPQXkdMvrY++CvoG85kwd6IU6DkYa0="; }; + outputs = [ "out" "sdk" ]; postPatch = '' # We have to be careful - Patching everything indiscriminately @@ -170,6 +171,39 @@ in stdenv.mkDerivation { # Breaks shebangs of Darwin scripts dontPatchShebangs = true; + postInstall = '' + # Install the SDK as a separate output + mkdir -p $sdk + + sdkDir=$(readlink -f ../Developer) + + while read -r path; do + dst="$sdk/Developer/''${path#$sdkDir}" + + if [[ -L "$path" ]]; then + target=$(readlink -m "$path") + if [[ -e "$target" && "$target" == "$NIX_BUILD_TOP"* && "$target" != "$sdkDir"* ]]; then + # dereference + cp -r -L "$path" "$dst" + elif [[ -e "$target" ]]; then + # preserve symlink + cp -d "$path" "$dst" + else + # ignore symlink + >&2 echo "Ignoring symlink $path -> $target" + fi + elif [[ -f $path ]]; then + cp "$path" "$dst" + elif [[ -d $path ]]; then + mkdir -p "$dst" + fi + done < <(find $sdkDir) + + mkdir -p $sdk/bin + cp src/external/cctools-port/cctools/ld64/src/*-ld $sdk/bin + cp src/external/cctools-port/cctools/ar/*-{ar,ranlib} $sdk/bin + ''; + postFixup = '' echo "Checking for references to $NIX_STORE in Darling root..." From 1e39c977f7328e016c8a96cd14a15e5c1759dac1 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Mon, 1 May 2023 17:39:19 -0600 Subject: [PATCH 3/4] nixos/darling: init --- nixos/modules/module-list.nix | 1 + nixos/modules/programs/darling.nix | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 nixos/modules/programs/darling.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index d933199cf60b..0cfd37d2b6d0 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -153,6 +153,7 @@ ./programs/cnping.nix ./programs/command-not-found/command-not-found.nix ./programs/criu.nix + ./programs/darling.nix ./programs/dconf.nix ./programs/digitalbitbox/default.nix ./programs/dmrconfig.nix diff --git a/nixos/modules/programs/darling.nix b/nixos/modules/programs/darling.nix new file mode 100644 index 000000000000..c4e1c73b5c29 --- /dev/null +++ b/nixos/modules/programs/darling.nix @@ -0,0 +1,21 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.darling; +in { + options = { + programs.darling = { + enable = lib.mkEnableOption (lib.mdDoc "Darling, a Darwin/macOS compatibility layer for Linux"); + package = lib.mkPackageOptionMD pkgs "darling" {}; + }; + }; + + config = lib.mkIf cfg.enable { + security.wrappers.darling = { + source = lib.getExe cfg.package; + owner = "root"; + group = "root"; + setuid = true; + }; + }; +} From 4b8e0601672d7a9b4ae70d99e1eac1587a22f217 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Mon, 1 May 2023 17:39:19 -0600 Subject: [PATCH 4/4] nixos/tests/darling: init --- nixos/tests/all-tests.nix | 1 + nixos/tests/darling.nix | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 nixos/tests/darling.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e10395f0b2cd..9e22edfb5456 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -171,6 +171,7 @@ in { cups-pdf = handleTest ./cups-pdf.nix {}; custom-ca = handleTest ./custom-ca.nix {}; croc = handleTest ./croc.nix {}; + darling = handleTest ./darling.nix {}; deepin = handleTest ./deepin.nix {}; deluge = handleTest ./deluge.nix {}; dendrite = handleTest ./matrix/dendrite.nix {}; diff --git a/nixos/tests/darling.nix b/nixos/tests/darling.nix new file mode 100644 index 000000000000..bc7b189372d6 --- /dev/null +++ b/nixos/tests/darling.nix @@ -0,0 +1,44 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: + +let + # Well, we _can_ cross-compile from Linux :) + hello = pkgs.runCommand "hello" { + sdk = "${pkgs.darling.sdk}/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"; + nativeBuildInputs = with pkgs.llvmPackages_latest; [ clang-unwrapped lld ]; + src = pkgs.writeText "hello.c" '' + #include + int main() { + printf("Hello, Darling!\n"); + return 0; + } + ''; + } '' + clang \ + -target x86_64-apple-darwin \ + -fuse-ld=lld \ + -nostdinc -nostdlib \ + -mmacosx-version-min=10.15 \ + --sysroot $sdk \ + -isystem $sdk/usr/include \ + -L $sdk/usr/lib -lSystem \ + $src -o $out + ''; +in +{ + name = "darling"; + + meta.maintainers = with lib.maintainers; [ zhaofengli ]; + + nodes.machine = { + programs.darling.enable = true; + }; + + testScript = '' + start_all() + + # Darling holds stdout until the server is shutdown + machine.succeed("darling ${hello} >hello.out") + machine.succeed("grep Hello hello.out") + machine.succeed("darling shutdown") + ''; +})