Let’s XCode in Linux For Real💻🛠✌

Thomas Brillion
7 min readAug 18, 2024

Have you ever wondered that you could develop and build apple related OS apps such as iOS, macOS, etc., using your non-apple hardware?

Of course. It is the best way to buy a Mac and develop them. I bought a M1 Macbook Air and tried to build iOS apps but the 8GB ram is never enough and it is always struggling when it comes to software development.

The other option you have is using a hackintosh or OSX KVM ( kernal based virtual machine). As for me, I decided to approach the KVM method in my journey.

Disclaimer: Installing macOS on non-Apple hardware is illegal and violates Apple’s EULA. This article is for informational purposes only.

Introduction

It was kinda easy to setup an OSX-kvm thanks to this OSX-kvm project and Docker-OSX project. But passing through the USB port instead of the whole USB bus controller had been such a hustle for me. I have spent almost 72 hours to figure out how to make XCode installed in the macOS VM recognize my iPhone. I have tried every possible method found on the internet such as

  • Disabling usbmuxd and passing through the usb port along with custom “udev” rules. See here. The device shows up in “USB” sections of System Report in the Mac but XCode doesn’t recognize.
  • Using usbmuxd, sonat and usbfluxd approach with building the dyld-shared-cache hoping my XCode would recognize it. ( this method is referenced as a working method in both the OSX-KVM and Docker-OSX projects. It worked with XCode before but not now.)
  • Passing through the whole USB bus controller by unlinking it in my host which leads to all connected devices unrecognizable. I was panic at that moment and the only working thing is the mousepad. So I had to turn on on-screen keyboard and type word by word using the pad.
  • Using “virt-manager” and its “Add Hardware” feature suggested in both “Gemini” and “ChatGPT”, the device doesn’t even show up in the “USB” section of “System Report”.

I was about to give up on it but I pushed myself a little further and kept finding solution. And then I am proud to say it that I have found the solution. It works with current latest XCode ( Xcode 15.4 ) and Sonoma! ٩(˘◡˘)۶

It all thanks to this doc and feel free to skip to that article.

Let’s get started. Open your terminal.

Preparation

NOTE: the following instructions are from https://github.com/kholia/OSX-KVM/blob/master/README.md. If you use DockerOSX , please consult their doc. You can view the requirements here.

  • Install the dependencies. Use package manager depending on your distro. I use Ubuntu .
sudo apt-get install qemu-system uml-utilities virt-manager git \
wget libguestfs-tools p7zip-full make dmg2img tesseract-ocr \
tesseract-ocr-eng genisoimage vim net-tools screen -y
  • Clone or Download the repository from Github.
cd ~

git clone --depth 1 --recursive https://github.com/kholia/OSX-KVM.git

cd OSX-KVM
  • KVM may need the following tweak on the host machine to work.
sudo modprobe kvm; echo 1 | sudo tee /sys/module/kvm/parameters/ignore_msrs
  • To make this change permanent, you may use the following command.
sudo cp kvm.conf /etc/modprobe.d/kvm.conf  # for intel boxes only

sudo cp kvm_amd.conf /etc/modprobe.d/kvm.conf # for amd boxes only
  • Add user to the kvm and libvirt groups (might be needed).
sudo usermod -aG kvm $(whoami)
sudo usermod -aG libvirt $(whoami)
sudo usermod -aG input $(whoami)
  • Download your preferred Base OS
./fetch-macOS-v2.py
1. High Sierra (10.13)
2. Mojave (10.14)
3. Catalina (10.15)
4. Big Sur (11.7)
5. Monterey (12.6)
6. Ventura (13) - RECOMMENDED
7. Sonoma (14)

Choose a product to download (1-7): 7
  • Convert the downloaded BaseSystem.dmg file into the BaseSystem.img file.
dmg2img -i BaseSystem.dmg BaseSystem.img
  • Create a virtual HDD image where macOS will be installed. If you change the name of the disk image from mac_hdd_ng.img to something else, the boot scripts will need to be updated to point to the new image name.
qemu-img create -f qcow2 mac_hdd_ng.img 256G

Before you start the VM, let’s pass through your apple device connected to the host machine.

Finding your device id

lsusb

It will give you a list of connected USB devices.

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 3252:0004 Goodong USB Camera
Bus 001 Device 010: ID 05ac:12a8 Apple, Inc. iPhone 5/5C/5S/6/SE
Bus 001 Device 002: ID 0414:7a3f Giga-Byte Technology Co., Ltd USB-HID Keyboard
Bus 001 Device 006: ID 046d:c09d Logitech, Inc. G102 LIGHTSYNC Gaming Mouse
Bus 001 Device 004: ID 8087:0032 Intel Corp. AX210 Bluetooth
Bus 001 Device 005: ID 05ac:024f Apple, Inc. Aluminium Keyboard (ANSI)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Find your device. In the above result, it is

Bus 001 Device 010: ID 05ac:12a8 Apple, Inc. iPhone 5/5C/5S/6/SE

Note the string 05ac:12a8 in which the first four characters are vendor-id and the last four characters are product-id . It may be different from your result.

Adding your device to the qemu command line

Since we are gonna run the VM using OpenCore-Boot.sh , open the OpenCore-Boot.sh file in your favourite editor and then edit the following line based on your vendor-id and product-id and add it after -device usb-ehci,id=ehci . The id parameter is not mandatory.

-device usb-ehci,id=ehci
-device usb-host,vendorid=0x5ac,productid=0x12a8,id=iphone,guest-reset=false

Changing Permission in udev

Since qemu runs as a regular user, it cannot connect to hot-plug USB devices unless you change permssions on the host. Being in group plugdev might be sufficient for standard USD block devices. For others, such as an iphone, you need to manually change the /dev/bus/usb/xxx/yyy to group users or create /etc/udev/rules.d/97-iphone.rules .

For your information, Udev is a dynamic device management system in Linux that handles the creation, naming, and management of device nodes in the /dev . Udev rules are processed in numerical order, from lowest to highest and the standard format rule is {priority}.{device_name}.rules .

In terminal, create or open the file /etc/udev/rules.d/97-iphone.rules or /etc/udev/rules.d/97-ipad.rules . Then add the following rule.

# /etc/udev/rules.d/97-iphone.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="05ac", ATTRS{idProduct}=="*",GROUP="users", MODE="0660"

and restart the udev service

sudo systemctl reload systemd-udevd

Start the VM

Before you start the VM, note that you need to set the CPU type as Haswell-noTSX or host if you choose Sonoma . To do that, edit the OpenCore-Boot.sh and find the line and change it to Haswell-noTSX or host .

// Change the following line
-enable-kvm -m "$ALLOCATED_RAM" -cpu Penryn,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on,"$MY_OPTIONS"


// To this
-enable-kvm -m "$ALLOCATED_RAM" -cpu host,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on,"$MY_OPTIONS"
// Or this
-enable-kvm -m "$ALLOCATED_RAM" -cpu Haswell-noTSX,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on,"$MY_OPTIONS"

Then start the

./OpenCore-Boot.sh

If you cannot run it, try giving execute permission to that file.

chmod +x ./OpenCore-Boot.sh

You will see thata window will appear and follow the instructions below.

  • Select Disk Utility
  • Select a biggest disk and Click Erase at the top right of the window. Don’t worry. It is just a virtual disk and it will not delete your files on your drive.
  • Name the disk and erase it. Close the window.
  • Initial window will appear and click Reinstall xxxx
  • Then choose the formatted disk and install. Hold tight. It’s gonna take a while.

It will boot the OS on its own. Then the macOS setup will be loaded after the installation. Continue the steps as you wish.

Note: the background might be gray or white as shown in the image if you choose Sonoma . Don’t worry. You can change the wallpaper after completing the setup.

TADA!!!

Hold on. Plug your iOS device into your machine and see if it works by checking in Finder .

The display would be lagging since we are not using any external GPU. You can pass the GPU if you have AMD GPU or Nvidia GTX GPU. The GPU higher than GTX doesn’t work in macOS sadly. You can increase the Ram and CPU cores and threads as much as your system can provide. For more information, consult the doc or use the internet.

You can download the XCode and I suggest you to share a folder from host with macOS VM. Then open your folder in your favourite IDE in your host machine and code. Then compile the code in the VM. I haven’t tested it yet but I believe there is no way that it won’t work.

That’s all. Good Luck and Happy Developing To You. 👏👏

If you find it useful, please consider buying me a coffee. 🥺

Find me on Github: https://github.com/w99910

Find me on X: https://x.com/thomasbrillion

--

--

Thomas Brillion

Full stack professional web developer specialized in PHP Laravel and Vue Js. - Blender Enthusiast plus 3D web app hobbyist. - Open-source fonder 😎😎