HOW-TO Build and Install Darling (MacOS Emulator for Linux) on OpenSUSE Leap 15.4 Beta

24th of March 2022
**
Introduction**

This document describes how to build and install Darling, a MacOS emulator for Linux, on OpenSUSE Leap 15.4 Beta. Darling can be considered to be the ‘Wine’ for MacOS applications. The current build instructions are only for OpenSUSE Tumbleweed, but I wanted to try it for a different version. Ideally, I would have liked to use the current stable version of Leap, which is 15.3, but I ran into some build issues that I could not resolve, and that did not occur after I switched over to Leap 15.4. I decided that Leap 15.4 was the best compromise I could make at this point, because I wanted to avoid the frequent, large, and usually daily updates one has with Tumbleweed, on the machine I am using for this.

These instructions could potentially be useful for other RPM-based Linux distros as well.

Note that this is a long exercise, and even though at the end of it I did manage to get a successful build and install, and was able to run the Darling shell and load the Darling kernel module, I ran into a known bug that prevented me from installing any MacOS applications. (More information about this later in this document.) This for me was a blocker, and I hope that it gets fixed soon. This kind of thing is only to be expected of Alpha software that is still at version 0.1.

Regardless, the advice I have seen online is that previous versions of Darling were working, and one should just build an older version. I would need some guidance as to which branch I should check out to do that. I initially just followed the build instructions and cloned the latest version of the master branch.**

What Doesn’t Work**

The first thing I would advise you not to do, and the first thing I tried, is to try building Darling from source on Leap 15.3. After I had resolved and installed the dependencies, I ran into a linker error where the linker was finding a 64-bit library instead of the 32-bit version, even though both were present. I am not sure what was wrong, but fixing this would probably require modifications to the Makefile, which is tricky to do, and I didn’t have the time to do it. As I was doing this on a relatively fresh install of Leap 15.3, I decided to switch over to Leap 15.4 and try again, and if that still didn’t work, I would just revert back to 15.3. Fortunately, this problem didn’t appear under 15.4, and I had a lot more success with that version.

The next thing I tried was to install Darling from the .deb files, even though OpenSUSE is an RPM-based distro. To do that, I needed to install two tools:

sudo zypper in dpkg dkms

You can download these here, if you wish:

https://github.com/darlinghq/darling/releases

Then I tried:

sudo dpkg --force-all -i darling-dkms_0.1.20220125.focal_amd64.deb

And got the following build error:

In file included from /var/lib/dkms/darling-mach/0.1/build/lkm/osfmk/mach/vm_param.h:79:0,
                 from /var/lib/dkms/darling-mach/0.1/build/lkm/osfmk/mach/mach_types.h:115,
                 from /var/lib/dkms/darling-mach/0.1/build/lkm/osfmk/kern/clock.h:38,
                 from /var/lib/dkms/darling-mach/0.1/build/lkm/osfmk/kern/sched_prim.h:72,
                 from /var/lib/dkms/darling-mach/0.1/build/lkm/osfmk/ipc/ipc_entry.c:76:
/var/lib/dkms/darling-mach/0.1/build/lkm/libkern/os/overflow.h:66:3: error: #error os_overflow expects type-generic builtins
 # error os_overflow expects type-generic builtins
   ^~~~~

This error is apparently caused by an incorrect version (too old) of glibc. (I actually tried running this again after I had the correct version installed – see the next section - but I still got the same error message.)

Then I tried this:

sudo dpkg --force-all -i darling_0.1.20220125.focal_amd64.deb

And I got this:

(Reading database ... 46105 files and directories currently installed.)
Preparing to unpack darling_0.1.20220125.focal_amd64.deb ...
>>> Shutting down old instances of Darling
Seeing if Darling is currently running
No instances running now
Unpacking darling (0.1.20220125~focal) over (0.1.20220125~focal) ...
dpkg: darling: dependency problems, but configuring anyway as you requested:
 darling depends on libc6 (>= 2.14); however:
  Package libc6 is not installed.
 darling depends on libc6-i386 (>= 2.3); however:
  Package libc6-i386 is not installed.
 darling depends on libavcodec58; however:
  Package libavcodec58 is not installed.
 darling depends on libavformat58; however:
  Package libavformat58 is not installed.
 darling depends on libavutil56; however:
  Package libavutil56 is not installed.
 darling depends on libcairo2 (>= 1.2.4); however:
  Package libcairo2 is not installed.
 darling depends on libdbus-1-3 (>= 1.9.14); however:
  Package libdbus-1-3 is not installed.
 darling depends on libegl1; however:
  Package libegl1 is not installed.
 darling depends on libfontconfig1 (>= 2.12.6); however:
  Package libfontconfig1 is not installed.
 darling depends on libfreetype6 (>= 2.2.1); however:
  Package libfreetype6 is not installed.
 darling depends on libfuse2 (>= 2.2); however:
  Package libfuse2 is not installed.
 darling depends on libgif7 (>= 5.1); however:
  Package libgif7 is not installed.
 darling depends on libgl1; however:
  Package libgl1 is not installed.
 darling depends on libglu1-mesa | libglu1; however:
  Package libglu1-mesa is not installed.
  Package libglu1 is not installed.
 darling depends on libjpeg8 (>= 2.0); however:
  Package libjpeg8 is not installed.
 darling depends on libpng16-16 (>= 1.6.2-1); however:
  Package libpng16-16 is not installed.
 darling depends on libpulse0 (>= 0.99.1); however:
  Package libpulse0 is not installed.
 darling depends on libswresample3 (>= 7:4.0); however:
  Package libswresample3 is not installed.
 darling depends on libtiff5 (>= 4.0.3); however:
  Package libtiff5 is not installed.
 darling depends on libx11-6; however:
  Package libx11-6 is not installed.
 darling depends on libxcursor1 (>> 1.1.2); however:
  Package libxcursor1 is not installed.
 darling depends on libxext6; however:
  Package libxext6 is not installed.
 darling depends on libxkbfile1 (>= 1:1.1.0); however:
  Package libxkbfile1 is not installed.
 darling depends on libxrandr2; however:
  Package libxrandr2 is not installed.
 darling depends on fuse; however:
  Package fuse is not installed.
 darling depends on darling-dkms; however:
  Package darling-dkms is not configured yet.
 
Setting up darling (0.1.20220125~focal) ...
>>> Shutting down old instances of Darling
Seeing if Darling is currently running
No instances running now

But I couldn’t run ‘darling’, it didn’t install. This was highly useful information though; it gave me a list of all of the dependencies!

You can also run:

dpkg -I darling_0.1.20220125.focal_amd64.deb

Which gives:

Depends: libc6 (>= 2.14), libc6-i386 (>= 2.3), libavcodec58, libavformat58, libavutil56, libcairo2 (>= 1.2.4), libdbus-1-3 (>= 1.9.14), libegl1, libfontconfig1 (>= 2.12.6), libfreetype6 (>= 2.2.1), libfuse2 (>= 2.2), libgif7 (>= 5.1), libgl1, libglu1-mesa | libglu1, libjpeg8 (>= 2.0), libpng16-16 (>= 1.6.2-1), libpulse0 (>= 0.99.1), libswresample3 (>= 7:4.0), libtiff5 (>= 4.0.3), libx11-6, libxcursor1 (>> 1.1.2), libxext6, libxkbfile1 (>= 1:1.1.0), libxrandr2, fuse, darling-dkms

Just a note about the dpkg –force-all switch, from the man page:

Warning: These options are mostly intended to be used by experts only. Using them without fully understanding their effects may break your whole system.

So, be warned about that! I had no problems, but, before trying that, as this was a relatively fresh installation of OpenSUSE, I thought that if the worst came to the worst, I would just reinstall the OS from my boot stick.

Prerequisites

On OpenSUSE, first ensure that you have the following patterns installed: Base Development Pattern, C++ Development Pattern, as well as the Linux Kernel Development Pattern, the latter is mostly for the kernel-source package, which you will need to build the Linux kernel module. Probably the easiest way to do this is from the Patterns section of the YaST Software manager.

You can find some of the prerequisites here:

https://docs.darlinghq.org/build-instructions.html

Install all of the Tumbleweed dependencies.

There are more here:

https://forums.opensuse.org/showthread.php/537415-BUG-compiling-Darling-crtbeginS-o-No-such-file-or-directory

But note that, even if you use both of these, you still won’t get all of the dependencies. Darling emulates both 64-bit and 32-bit MacOS applications, and so, you need to install both the 64-bit and the 32-bit versions of all of the libraries. I used the list of dependencies in the previous section, together with the YaST Software manager, to search for and manually check that all of the dependencies were installed, and install the ones that weren’t. A complication is that Debian packages have different naming conventions than RPM-based ones; for example, ‘libc6’ is ‘glibc’ in OpenSUSE. You will also find packages with ‘i386’ in the name which means you need to install the 32-bit package.

The final dependency you need to build manually. Leap 15.4 ships with version 2.13 of glibc, (and that’s not likely to change), but the minimum requirement for the Linux kernel module is version 2.14. It is possible to have more than one version of glibc installed and working on the same operating system at the same time.

So, from:

https://www.gnu.org/software/libc/sources.html

https://www.gnu.org/software/libc/manual/html_node/Configuring-and-compiling.html

Do the following:

git clone https://sourceware.org/git/glibc.git
cd glibc
git checkout release/2.32/master

Make a new directory to install this version of glibc, for example:

sudo mkdir /usr/local/libcompat

Then:

mkdir build
cd build
../configure --prefix=/usr/local/libcompat
make
sudo make install

Then, create a new file in etc/ld.so.conf.d/, for example:

sudo vi /etc/ld.so.conf.d/glibc.conf

Containing the path to the new directory above, like so:

/usr/local/libcompat

Save the file, then run:

sudo ldconfig

This tells the linker where to find your new glibc library.

Build and Install Procedure

The entire build and install process is a long one. On an Intel Core i5 processor with four cores running at 2.4Ghz, it took longer than twenty-four hours. So, be prepared for that!

Cloning the Repo

According to the build instructions, you should do it this way:

git clone --recursive https://github.com/darlinghq/darling.git

However, be aware that this is a very large repo, and your clone process may time out because of that. If a git clone operation times out, there is no way to resume it from where it left off. You have to run the whole clone process again. So, before you do that, I advise you to first set the following environment variables:

export GIT_HTTP_LOW_SPEED_LIMIT=0
export GIT_HTTP_LOW_SPEED_TIME=1000

If you frequently clone very large repos, it might be a good idea to set these in your .bash_rc as well.

Source Code Changes

In the file: darling/src/external/lkm/libkern/os/overflow.h

Locate the following code:

#if __has_builtin(__builtin_add_overflow) && \
         __has_builtin(__builtin_sub_overflow) && \
         __has_builtin(__builtin_mul_overflow)

Delete it, and replace it with:

#if true

This issue was reported here:

https://github.com/darlinghq/darling/issues/1012

Then, in the file darling/src/external/lkm/osfmk/duct/duct_kern_thread_call.c

Locate the following code:

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
if (atomic_long_read(&call->tc_work.work.data) & (WORK_STRUCT_PENDING | WORK_STRUCT_INACTIVE))
#else
        if (atomic_long_read(&call->tc_work.work.data) & (WORK_STRUCT_PENDING | WORK_STRUCT_DELAYED))
#endif

Delete the first line, and replace it with:

#if true

There is something funny with this kernel version check, because WORK_STRUCT_DELAYED is not defined in my kernel headers.

The kernel I am running at the moment is:

uname -a
Linux localhost.localdomain 5.14.21-150400.11-default #1 SMP PREEMPT_DYNAMIC Wed Mar 2 08:27:22 UTC 2022 (0cc030f) x86_64 x86_64 x86_64 GNU/Linux

The Build and Install

Then, assuming that I have documented this correctly, and also that I haven’t missed any necessary steps, and you have followed all of my instructions correctly; you should now be ready for a problem-free build and installation process.

According to the build instructions:

# Move into the cloned sources
$ cd darling
 
# Make a build directory
$ mkdir build && cd build
 
# Configure the build
$ cmake ..
 
# Build and install Darling
$ make
$ sudo make install

And then, to build and install the Linux kernel module:

$ make lkm
$ sudo make lkm_install

A problem I encountered is that after every kernel upgrade, you will have to run the:

$ sudo make lkm_install

step again. So, be aware of that!

You should now be able to play around a bit, according to these instructions:

https://docs.darlinghq.org/darling-shell.html

https://docs.darlinghq.org/what-to-try.html

Problem Encountered

I tried to install some software according to these instructions:

https://docs.darlinghq.org/installing-software.html

Just to show you my process, this is what I did first:

steven@localhost:~/darling/build> darling shell
Loaded the kernel module
Bootstrapping the container with launchd...
 
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Darling [/Volumes/SystemRoot/home/steven/darling/build]$
Darling ~/Downloads]$ hdiutil attach vlc-3.0.16-intel64.dmg

I got this:

Darling [/Volumes/SystemRoot/home/steven/Downloads]$ cp -r /Volumes//vlc-3.0.16-intel64/VLC.app/ /Applications
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Breakpad.framework/Breakpad: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Breakpad.framework/Headers: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Breakpad.framework/Resources: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Breakpad.framework/Versions: Socket is not connected
cp:  /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Growl.framework:  unable to copy extended attributes to  /Applications/Contents/Frameworks/Growl.framework: Socket is not  connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Growl.framework: Socket is not connected
cp:  /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Sparkle.framework:  unable to copy extended attributes to  /Applications/Contents/Frameworks/Sparkle.framework: Socket is not  connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Frameworks/Sparkle.framework: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Info.plist: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/MacOS: unable to copy  extended attributes to /Applications/Contents/MacOS: Socket is not  connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/MacOS: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/PkgInfo: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Resources: unable to  copy extended attributes to /Applications/Contents/Resources: Socket is  not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/Resources: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/_CodeSignature:  unable to copy extended attributes to  /Applications/Contents/_CodeSignature: Socket is not connected
cp: /Volumes//vlc-3.0.16-intel64/VLC.app//Contents/_CodeSignature: Socket is not connected

Running:

sudo dmesg

I got this:

  755.865286] Darling TID 8660 (PID 8660) says: sigexc:   gregs 0x0
 
  755.865290] Darling TID 8660 (PID 8660) says: sigexc: emulating default signal effects
 
  755.865298] Darling TID 8660 (PID 8660) says: sigexc: handler (6) returning
 
  755.903584] not implemented: lck_mtx_destroy()
  755.903587] not implemented: lck_mtx_destroy()
  755.903596] not implemented: lck_mtx_destroy()
  755.903597] not implemented: lck_mtx_destroy()
  755.937293] not implemented: thread_get_requested_qos()
  755.947861] not implemented: thread_get_requested_qos()
  756.003619] not implemented: lck_mtx_destroy()
  756.003624] not implemented: lck_mtx_destroy()
  756.003632] not implemented: lck_mtx_destroy()
  756.003633] not implemented: lck_mtx_destroy()
  756.039708] Darling TID 8521 (PID 8521) says: dtype for fd 255 -> /dev/pts/4
 
  756.039942] Darling TID 8521 (PID 8521) says: dtype for fd 255 -> /dev/pts/4

This is a known issue, it was reported here:

https://github.com/darlinghq/darling/issues/311

So, based on that, I believe that this is not a problem with my build, install, operating system, or kernel, because others are having the same problem. To me, this is a blocker bug, because it stops me from doing anything really useful with the emulator.

How Do I Build a Working Version?

The advice I have seen online about this issue is just to check out an earlier version of the code, and rebuild with that instead. However, it’s not clear to me which branch or version of the code would be a good candidate for this exercise. Preferably, I would like to try the most recent working version before this bug was introduced.

At this stage, I am not planning to do anything serious with Darling, but I do have a few MacOS apps that I want to test out and see if and how well they work. The main reason I started on this exercise was just to play around a bit. I am a big fan of software emulation, and a MacOS emulator for Linux would be way cool and a lot of fun to play with!

So, if anyone can give me some guidance or advice in this regard, I would greatly appreciate it!

Also posted to:

https://github.com/darlinghq/darling/issues/1124