Project Soon

Mac Support

Many years ago I tried to build a version of PixelMap for Mac 1. Sadly, only the CLI was able, due to dependency issues and lack of knowledge. Just a couple of months ago I came thinking about thinking of this again, and after I released the source, I figured I should at least compile it on a Mac and see what happens. The result was promising, as I only needed to fix some small compilation issues to make it compile properly. Both CLI and GUI compiled, but only CLI managed to start. By now I felt this as promising, so I ditched the required OpenGL frontend and settled with SDL2 handling it for me 2, and it launched, with minor issues regarding certain situations that made it crash. Later on I tried the internal testing, and was faced with crashes. After investigating further, I located the problem 3, and began fixing all warnings that the compiler spew out, and that solved the issue and testing finished with no errors.

But this was not the end. Now was the time to automate the building, and the problem was that the runner was only supporting Linux, and it was not desired to host a Mac instance just to build a package to be released for Mac. Time to bring out cross compilation again.

Dockerfile

First off, I tried to locate if there was anyone that had already made anything that I could use, which they had 4. Then I tried to find some tutorial to make things a bit easier and understandable, which existed 5. I even found a complete docker image from previously mentioned solution, but sadly it did not work as expected 6. Other solutions included prepared packages and multi-cross build mega projects, but none worked 78.

With all this gathered, I started creating a Dockerfile that would build an image for me, similar to previously built Windows and Linux images. Sadly, it became clear pretty fast that this was not to become an easy task. The first thing to do was to install all necessary dependencies.

1
2
3
4
# syntax=docker/dockerfile:1
FROM node:20-bookworm AS osx-cross
# Install necessary binaries
RUN apt-get update && apt-get install -y autoconf cmake clang llvm-dev uuid-dev libssl-dev libbz2-dev

Then it was time to retrieve the osxcross repository and start building the binaries that would make it possible for us to . Be aware that we require the SDK to compile at all, and there are some repositories out there that provides them, but I did stumble upon one or two that was improperly packaged, so it made the build process impossible 9.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Download build and SDK
RUN git clone https://github.com/tpoechtrager/osxcross.git ~/osxcross
RUN wget -P ~/osxcross/tarballs https://github.com/joseluisq/macosx-sdks/releases/download/10.15/MacOSX10.15.sdk.tar.xz
RUN mkdir -p /osxcross
# Necessary variables
ENV TARGET_DIR=/osxcross
ENV UNATTENDED=1
# Build compilers
RUN cd ~/osxcross && ./build.sh
ENV PATH="$PATH:/osxcross/bin"

Toolchain

While this should suffice to get us going, we also need to add a toolchain 10, as we need to set up the environment and tell CMake where to locate alternative binaries in order to build at all. Normally each platform comes with their respective toolchain built in, but in this case we have to set it up ourselves. The general idea is to first load osxcross-conf environment and use that as a base to what we need to tell CMake. Then we set up the target system. Some paths are set, along with the executables that will be used to build, and finally some additional linking flags and other flags which helps with making the whole process as clean as possible.

Then we put in our toolchain in our Dockerfile:

1
2
3
4
5
6
# Clean up and add toolchain
RUN rm -rf ~/osxcross
COPY osx/toolchain-x86_64.cmake /opt/
ENV MACOSX_DEPLOYMENT_TARGET=10.15
ENV OSXCROSS_MP_INC=1
ENV OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1

Custom packaging

The same goes for packaging. I tried to find some solution to this, and sadly the closest I found, that worked, was to do it myself. Luckily there was some information about how Apple packaged, and I picked DMG 11, because it was pretty straightforward to integrate.

First off, download genisoimage which contains mkisofs, to initially create an ISO.

1
RUN apt-get install -y genisoimage

Then download, build and install libdmg 12, which will be used to convert ISO to DMG.

1
2
3
RUN git clone https://github.com/checkra1n/libdmg-hfsplus.git ~/libdmg-hfsplus
RUN cd ~/libdmg-hfsplus && cmake . && make -C dmg && make install -C dmg
RUN rm -rf ~/libdmg-hfsplus

And finally we add the external package script which will combine these tools 13. This script is also added into the toolchain.

1
COPY osx/osxcross-pack.cmake /opt/

Conclusions

Cross compiling for Mac is hard. What have been mentioned above was only the result to over 20 hours of time spent researching, testing and re-doing everything. Note that in all other images I use g++, but for Mac I now use Clang. The reason for this was that when building g++ I found out that the binary provided did not support some features that was required for Objective-C. It is kind of odd, as the g++ provided in OSX had this feature, but not the one I compiled. It does work, and that is all that matters in this case.

In addition, due to this, I located several bugs and issues that popped up, including undefined behavior and crashes, so in the end this was more than worth it to make the program more stable.


  1. I tried this a couple of times, so the one posted is not the only attempt. ↩︎

  2. https://martin-fieber.de/blog/gui-development-with-cpp-sdl2-and-dear-imgui/ ↩︎

  3. http://blog.davidwolinsky.com/2015/03/gcc-and-ud2-instructions.html ↩︎

  4. https://github.com/tpoechtrager/osxcross ↩︎

  5. https://www.epeters.io/osxcross-setup ↩︎

  6. https://github.com/crazy-max/docker-osxcross ↩︎

  7. https://launchpad.net/~flosoft/+archive/ubuntu/cross-apple ↩︎

  8. https://github.com/multiarch/crossbuild ↩︎

  9. https://github.com/joseluisq/macosx-sdks ↩︎

  10. https://git.aposoc.net/McTwist/docker-files/src/branch/main/osx/toolchain-x86_64.cmake ↩︎

  11. https://en.wikipedia.org/wiki/Apple_Disk_Image ↩︎

  12. https://github.com/checkra1n/libdmg-hfsplus ↩︎

  13. https://git.aposoc.net/McTwist/docker-files/src/branch/main/osx/osxcross-pack.cmake ↩︎