Compiling Hyne on OSX using QT library from Homebrew

Reading time ~4 minutes

Hyne (forum/GitHub) is a cross-platform Final Fantasy 8 save game editor. It can import/export/convert game saves from the PSX/PC/Emulator versions of Final Fantasy 8, and it runs on Windows/OSX/Linux! The last binary release for OSX however was back in 2013 and there’s been several version updates since. Although the developer will release future versions automatically using Travis on GitHub, I figured this would be a good chance to experiment with compiling a QT app!

TL;DR to just get Hyne installed on OSX

QT is a well known cross-platform GUI library. I’ve experimented a bit, so this was a chance to learn a bit more about it. The key challenge here was to try and get the app built using the Homebrew-provided QT library. I’m a big fan of Homebrew on OSX and like to keep as much software as possible managed by it.

Step 1: install QT via Homebrew - Hyne uses QT5 specifically

brew install qt5

QT5 is keg-only. This explains what that means and has some guidance on what to do (hint: DON’T brew link --force as is commonly suggested on the Internet! It’s best to keep the QT5 installation segregated from the rest of the system to prevent future conflicts).

Step 2: extend system path to include the QT binaries location

export PATH=$(brew --prefix)/opt/qt5/bin:$PATH

(FYI $(brew --prefix) evaluates to /usr/local on my system.)

Now commands like qmake will work for the current shell only.

Next step is to run qmake. Now here’s where things get tricky. When I did step 1, Homebrew said this:

If you build your own software and it requires this
formula, you'll need to add to your build variables:

    LDFLAGS:  -L/usr/local/opt/qt5/lib
    CPPFLAGS: -I/usr/local/opt/qt5/include

Makes sense. But how do I pass these variables to the compiler since I’m not actually invoking the compiler directly? Like most C++ projects, Hyne uses a Makefile. But actually I’m not even writing my own Makefile, I’m using qmake to generate one for me! The Homebrew wiki I linked to earlier has an example of what to do if using a configure script, but what about when using qmake?

Well I could use qmake and then edit the Makefile and add the extra flags wherever needed. That’s a dirty hack though and it’s not going to be pretty in the long run as every time I run qmake, I’ll have to edit the Makefile manually again. What about editing the Hyne.pro file? (QT project file that qmake reads from). That could work, except then I’ve changed a file in the repository, meaning every time I pull from upstream I’ll have to fiddle around with merges and potential conflicts.

Turns out qmake does have variables that it can use to pass to the Makefile. But now another problem comes - the instructions tell me to use LDFLAGS and CPPFLAGS, and qmake doesn’t have either of those!

…or does it? QT docs says I can use QMAKE_LFLAGS for LDFLAGS (why they excluded the D is beyond me). CPPFLAGS was more tricky; turns out CPPFLAGS are usually passed to both the C and C++ compiler. So essentially, CPPFLAGS = CFLAGS + CXXFLAGS (C compiler and C++ compiler), which qmake has via QMAKE_CFLAGS and QMAKE_CXXFLAGS.

Step 3: run qmake, supplying the compiler flags to it, which will be passed to the Makefile

qmake "QMAKE_CFLAGS+=-I$(brew --prefix)/opt/qt5/include" "QMAKE_CXXFLAGS+=-I$(brew --prefix)/opt/qt5/include" "QMAKE_LFLAGS+=-L$(brew --prefix)/opt/qt5/lib"

Note the += to append the flags to whatever else may be in use, and no spaces. Finally now I have the Makefile.

Step 4: run make (j flag for multi-threading)

make -j5

In the case of the Hyne project, this will result in an OSX .app bundle. Now Hyne was developed in French, but luckily the translations have already been done and put in the QT language format, .ts files. However, just because they’re included in the TRANSLATIONS variable in the .pro file, doesn’t mean qmake and make include them in the final app. In the same shell (still need that path from step 2):

Step 5: create binary format for the English and Japanese translations

lrelease Hyne.pro

This will spit out 2 .qm files, which for Hyne, just have to copied to Hyne.app/Contents/MacOS/

I could have stopped here, but I also wanted to distribute the binary and be able to use it on a Mac without QT (specifically without QT5 via Homebrew) so I had to package the app to include a copy of the required QT frameworks, and modify the binaries to reference the local copies. This link explains it in full detail, but I’ll be honest, I followed the install_name_tool steps but couldn’t get it to work. At the end of that page though, it describes the Mac Deploy Tool which is honestly so much easier.

Step 6: package QT frameworks with .app bundle

macdeployqt Hyne.app

Voilà! So to summarise the steps:

brew install qt5
export PATH=$(brew --prefix)/opt/qt5/bin:$PATH
qmake "QMAKE_CFLAGS+=-I$(brew --prefix)/opt/qt5/include" "QMAKE_CXXFLAGS+=-I$(brew --prefix)/opt/qt5/include" "QMAKE_LFLAGS+=-L$(brew --prefix)/opt/qt5/lib"
make -j5
lrelease Hyne.pro
macdeployqt Hyne.app

TL;DR

The current version of Hyne is 1.9.1; to make it easier for people who just want the .app file, I added the release to Homebrew Cask. So just get Homebrew Cask set up, then:

brew cask install hyne

Binaries to OSX App Bundle

Steps on how to get some executables into an OSX .app file Continue reading

The Story of Signature Extensions Limited

Published on May 20, 2016

First Post - Creating a Website

Published on March 31, 2016