Closed jmaglic closed 3 years ago
After my original solution stopped working, I came back to this issue and finally found a proper solution. The solution comes from this 2014 blog post on the wxWidgets website.
This is the relevant quote:
[...] sometimes you may want to avoid using the system libraries, e.g. because you want to build a statically linked version of your program with as few dependencies as possible. This was always possible by explicitly disabling the use of each and every library with -with-libfoo=builtin, but this was relatively tiresome and it was easy to forget a library or two.
To remedy this, I’ve just added a new --disable-sys-libs configure option which does exactly what it says: when it is specified on configure command line, only the built-in versions of the third party libraries will be used.
So the solution is simply to use the option --disable-sys-libs
when configuring wxWidgets. No more dependencies on local dylibs.
Problem
For our 0.1.0 release I built a universal binary and bundled it into an appbundle for distribution. I then discovered that the application didn't run on Macs with x86_64 architecture. The error report suggested that the issue was with a dynamic library that was not installed on the machine.
Using
otool
on my executable I was getting this output:I discovered that installing libtiff using Homebrew fixed the app crashing. However, it would be unreasonable to expect users to install unrelated libraries for the app to work.
I was confused about why I was encountering the issue in the first place. I had built wxWidgets specifically as static library, so I wasn't expecting dylib dependencies to pop up.
Solution
Eventually I discovered a solution on this web page (I've archived a snap shot of the page with the Wayback Machine if the link ever breaks). I had to change the relevant section a little, but I added the following code to my Makefile:
This section statically links my executable against libtiff. All that was left to do was add
$(LDFLAGS)
to the linking line in my Makefile in place of`wx-config --libs`
. Inspecting the resulting executable withotool
confirms that the executable no longer asks for the dylib. Opening the app on the x86_64 machine works as desired.Alternative Solution
Before I discovered how to statically link libtiff, I constructed a whole working solution by bundling the libtiff with the appbundle. I believe this is even explained in the resource I've linked above.
In essence, the idea is to place all required dylibs inside the bundle directory. Most places I found created a
Frameworks
directory inside theContents
directory. In my case I needed two dylibs in this directory:libtiff.5.dylib
andlibjpeg.9.dylib
because the latter was a dependency of the former.As part of the appbundle creation I needed to copy the dylibs into the Frameworks folder, then inform the executable to look for the libtiff library there, instead of the usual place. The relevant make file section looked something like this:
In order to make the executable look in the right place for the dylib, I had to use
install_name_tool
with the-change
switch as seen above. The first argument is the original dylib path, the second argument is the new path relative to the executable and the last argument is the executable path. Since libtiff also had a dependency (libjpeg), I needed to do this twice, but the second time with libtiff as executable. Usingotool -L path/to/executable
I could check whether the dylib path was successfully changed.There are many places that explain how to do this, but I did find parts of this guide to be most useful.
Ultimately, the problem with this approach is that now we're distributing not only our code, but also third-party binaries. This leads to all kinds of licensing requirements that are best left untouched.
Failed Attempts
Before I got to any solution, I tried to create fat/universal binaries of the dylibs so I could include them in the appbundle. However, this ended up not being necessary, since I could just use the binaries already installed on my system. For whatever reason, only the x86_64 build requires the dylib, whereas the arm64 build manages to ignore it when linking. That means no universal libraries are required.