Releasing ManaPlus for Mac OSX

This is a beginner’s guide to help new OSX developers quickly grasp the Xcode project included with ManaPlus. If you are experienced with Xcode, please feel free to skip directly to the end (improving the workflow). If you wish to help with the releases of ManaPlus, you are reading the right thing. I will try my best to be thorough and make sure I cover most of what I did, what needs to be done and what could be improved. I am no expert on building software for the Mac, so please be patient and point out anything stupid I did.

The Xcode Project

First you will need to clone the git repository. The project is located inside the Xcode folder. There are two targets, which you can select using the Scheme menu on the top of the Xcode interface. The build for Snow Leopard is different because there were crashes with gettext, so it doesn’t have translations enabled (Build Settings > Other C++ Flags > -DENABLE_NLS). Before doing anything, you will probably want to check if there are new c++ files added or removed. Unfortunately, the project has “hard links” to files, so you have to manually add new files. This could be improved I guess, but it isn’t very complicated.

Updating the sources

The easiest way to check for new/removed files is to diff the src/CMakeList.txt. Inside Xcode, there is a handy diff viewer for git. Go to File > Source Control > Repositories… Here you will see a list of local repositories you have. Select the manaplus folder (blue icon) and in the browser, expand src and click on CMakeList.txt. In the bottom area you will see a bunch of commits over time. You have to analyse when was the last update of the Xcode project, and if there where changes since then. If so, expand the commit messages that have changed. Here you will see a list modifications. What you want is the A and D lines (Added and Deleted files).

Now you can right click on the ManaPlus Folder in the Project Browser and select ‘add files to “ManaPlus” …’ You can navigate to the src folder and add the needed files. You will see that they are darker, since Xcode keeps track of the files in your project. It is a good indicator you are doing the right thing!

Updating localization

Unfortunately, since ManaPlus has certain problems in compiling through the usual CMake, I wasn’t able to setup a nice workflow for the translations (see things to improve). So, you will have to download a nightly build (for example the windows one) and overwrite the Xcode > locale folder with the one from the nightly build. This should ensure you have the latest translations.

Now that everything is up to date, you can try to hit Run to test out the build. If it fails, it is probably because you didn’t add everything needed, or that a new library has been added (I will cover libraries later).

Your app is located inside the Derived Data folder Xcode creates. To find it, go to Xcode > Preferences… > Locations and click the little arrow beside the Derived Data path. You can also change the path, and I highly recommend adding to your finder favorites. Navigate to the Build > Products > Debug and there is your app.

Working with libraries

Libraries are probably one of the trickiest part of releasing a build. I have included all the modified dynamic libraries (.dylib) and static ones (.a) inside the Xcode > libs folder. You will need to download the SDL, SDL_mixer, SDL_image, SDL_net and SDL_ttf frameworks separately and add these in your /Library/Frameworks folder.

If for some reason, the ManaPlus project adds a new dependency, you will have many options to choose from. You can find the source code of the library and compile it inside a framework using Xcode. Then add this framework to your project and also add it to the Build Phases > Copy Files area (the framework one).

I personnally used MacPorts to compile the desired libraries. You can do

sudo port install libname

and the library will be located inside your /opt/local/lib folder. There may be both a dynamic library and a static one (.dylib and .a respectively). If you don’t want headaches, use the static library. Still, I will explain the issues of dynamic libraries in case a static version is not available.

Dynamic libraries

So here is the problem, which I learned the hard way. Dynamic libraries have a fixed path. Simply put, inside of them, they have a location to tell OSX where to find them. To see this, in the terminal do

otool -L libraryname.dylib

For example, from the manaplus directory:

cd Xcode/libs
otool -L libcurl.4.dylib

will output:

	@executable_path/../SharedSupport/libcurl.4.dylib (compatibility version 7.0.0, current version 7.0.0)
	/usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 47.0.0)
	/usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 47.0.0)
	/System/Library/Frameworks/LDAP.framework/Versions/A/LDAP (compatibility version 1.0.0, current version 2.4.0)
	/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

As you can see from the first line, this library was edited by myself. What I did here, using the install_name_tool is change the location where are application will look for the file. Since the files are packaged inside the ManaPlus.app/Contents/SharedSupport, I need to tell OSX to look for them there (and not /opt/local/lib).

To do so:

install_name_tool -id @executable_path/../SharedSupport/YourNewLibrary.dylib YourNewLibrary.dylib

Inside the Xcode project, you will also have to add a line to the Build Phases > Run Scripts area. Here, you will see that every library needed by the project is processed when you build ManaPlus. Basically, without going into to much details, you can copy/past one of the existing lines and simply change the values you need. For example change:

install_name_tool -change /usr/lib/libcurl.4.dylib @executable_path/../SharedSupport/libcurl.4.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"

to:

install_name_tool -change /usr/lib/YourNewLibrary.dylib @executable_path/../SharedSupport/YourNewLibrary.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"

Be sure to change /usr/lib to /opt/local/lib if that is where your library was pointing to (if you installed the lib using MacPorts for example). Now things may get a bit complicated (if it wasn’t already). First of all, libraries in /usr/lib are libraries included by default on OSX. You need to analyse the compatibility version of the libraries included with older versions of OS X.

Print/export
Languages