Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
macosxrelease [2012/12/23 06:04]
socapex
macosxrelease [2013/04/02 03:00] (current)
socapex [Problems and Improving the Workflow]
Line 1: Line 1:
-====== Releasing ManaPlus for Mac OSX ======+====== ​Compiling and 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.+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 ([[#Problems and 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 ===== ===== The Xcode Project =====
Line 13: Line 13:
  
 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! 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!
 +
 +If files were removed, they will be red inside your ManaPlus folder. Simply delete them.
  
 == Updating localization == == 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 buildThis should ensure ​you have the latest translations.+No need to do anything special here, I have include an automatic script ​to automagically compile ​the localizationsMake sure you have gettext installed through macports.
  
-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).+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 (see [[#Working with libraries]]).
  
-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.+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/Debugand there is your debug app. 
 + 
 +===== Building a Release ===== 
 + 
 +If all went well and the app works fine, use Product > Build For > Archive to create a release build. It will be located in the release folder next to your debug app. Do this for both ManaPlus and ManaPlus-10.6. 
 + 
 +I used [[http://​www.araelium.com/​dmgcanvas/​|DMGCanvas]] to create the .dmg image. You can use the software free, with limited functionality. It is quite enough for what we need. Open both release.dmgcanvas and release 10.6.dmgcanvas. The file is probably not pointing to the correct application location. Select the ManaPlus.app and in the file info panel, point it to the correct release path (do the same for the 10.6 version). What is nice with DMGCanvas is that from now on, you wont need to do anything else. It will always include the latest version of your built app. 
 + 
 +Click build and save your dmg files somewhere. Upload and hopefully all should work. Congratulations,​ you have built a release for ManaPlus on OS X!
  
  
 ===== Working with libraries ===== ===== 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.+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). 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).
Line 31: Line 41:
 I personnally used [[http://​www.macports.org|MacPorts]] to compile the desired libraries. You can do I personnally used [[http://​www.macports.org|MacPorts]] to compile the desired libraries. You can do
 <​code>​sudo port install libname</​code>​ <​code>​sudo port install libname</​code>​
-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.+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 ​for both, and the issues of dynamic libraries in case a static version is not available
 + 
 +If you are using a dynamic library (for whatever crazy reason), read on. If you have a static library and are mentally sane, skip to the [[#Static Libraries]] section.
  
 == Dynamic libraries == == Dynamic libraries ==
 +
 +Before diving in the fun stuff, once your library is installed through macports, you need to copy it from its /​opt/​local/​lib location to the Xcode/libs folder. Now you can simply drag the library inside your Xcode Project in the Frameworks section (you will see there are already many there). It should automatically be added to the Summary > Linked Libraries section and also the Build Phases > Link Binary With Libraries area. You will now have to add it to the Build Phases > Copy Files section that copies the files to Shared Support (not the Frameworks one).
 +
 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 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
 <​code>​otool -L libraryname.dylib</​code>​ <​code>​otool -L libraryname.dylib</​code>​
Line 50: Line 65:
 </​code>​ </​code>​
  
-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).+As you can see from the first line, this library was edited by myself. What I did here, using the install_name_toolis to change the location where our 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:+To do so, simply run this command on YourNewLibrary.dylib:
 <​code>​install_name_tool -id @executable_path/​../​SharedSupport/​YourNewLibrary.dylib YourNewLibrary.dylib</​code>​ <​code>​install_name_tool -id @executable_path/​../​SharedSupport/​YourNewLibrary.dylib YourNewLibrary.dylib</​code>​
  
Line 61: Line 76:
 <​code>​install_name_tool -change /​usr/​lib/​YourNewLibrary.dylib @executable_path/​../​SharedSupport/​YourNewLibrary.dylib "​$TARGET_BUILD_DIR/​$PRODUCT_NAME.app/​Contents/​MacOS/​$PRODUCT_NAME"</​code>​ <​code>​install_name_tool -change /​usr/​lib/​YourNewLibrary.dylib @executable_path/​../​SharedSupport/​YourNewLibrary.dylib "​$TARGET_BUILD_DIR/​$PRODUCT_NAME.app/​Contents/​MacOS/​$PRODUCT_NAME"</​code>​
  
-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.+**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
 + 
 +If we take libcurl.4 for example, I had to include it because OS X 10.6 doesn'​t provide the compatibility version 7.0.0. Now this is all good, but the library itself has dependencies. Fortunately,​ Snow Leopard provided all the dependencies at the correct compatibility vesions, so I didn't have to include libcurl'​s dependencies inside the application bundle. Lets look at some other scenario... 
 + 
 +Still in the Xcode/libs folder, run: 
 +<​code>​otool -L libSDL_gfx.14.dylib</​code>​ 
 + 
 +Which will output: 
 +<​code>​ @executable_path/​../​SharedSupport/​libSDL_gfx.14.dylib (compatibility version 24.0.0, current version 24.1.0) 
 + @executable_path/​../​SharedSupport/​libSDL-1.2.0.dylib (compatibility version 12.0.0, current version 12.4.0) 
 + @executable_path/​../​SharedSupport/​libXrandr.2.dylib (compatibility version 5.0.0, current version 5.0.0) 
 + @executable_path/​../​SharedSupport/​libXext.6.dylib (compatibility version 11.0.0, current version 11.0.0) 
 + @executable_path/​../​SharedSupport/​libXrender.1.dylib (compatibility version 5.0.0, current version 5.0.0) 
 + @executable_path/​../​SharedSupport/​libX11.6.dylib (compatibility version 10.0.0, current version 10.0.0) 
 + @executable_path/​../​SharedSupport/​libxcb.1.dylib (compatibility version 3.0.0, current version 3.0.0) 
 + @executable_path/​../​SharedSupport/​libXau.6.dylib (compatibility version 7.0.0, current version 7.0.0) 
 + @executable_path/​../​SharedSupport/​libXdmcp.6.dylib (compatibility version 7.0.0, current version 7.0.0) 
 + /​System/​Library/​Frameworks/​Cocoa.framework/​Versions/​A/​Cocoa (compatibility version 1.0.0, current version 19.0.0) 
 + /​usr/​lib/​libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0) 
 +</​code>​ 
 + 
 +I had to add all the necessary dependencies to the project, because they where all pointing to /​opt/​local/​lib,​ which means they were installed through macports, and a user  wont have these libraries available. As a rule of thumb, if the lib or dependency is in /usr/lib, then it should be fine. If the library is pointing too /​opt/​local/​lib you will have to include its dependencies **that are also pointing to /​opt/​local/​lib**. You can do it all manually, or use shell scripts provided in the libs folder (libs-change.sh and libs-id.sh). I found these on the internet but can't recover the source... 
 + 
 +So first, add your library .dylib and all its dependencies to a temporary folder, and make sure they don't have more dependencies. Also copy the shell scripts inside this folder. 
 + 
 +To change all the ids of your dylibs inside the folder to @executable_path/​../​SharedSupport/,​ run the libs-id.sh script: 
 +<​code>​./​libs-id.sh</​code>​ 
 + 
 +For the other script, first **uncomment the first part** and comment the second, and run it the same way you did with libs-id. This will create a text file called changes. You can review the changes that are to be made to make sure all is working. Then, comment the first part of the script, uncomment the second and run it again (./​libs-change.sh). Now all your /​opt/​local/​lib dependencies should be changed to @executable_path/​../​SharedSupport/​. Hurray! 
 + 
 +To view the result, you can run 
 +<​code>​otool -L *</​code>​ 
 +inside your folder, you will see all your libraries information. If all is well, add these to the Xcode/lib folder and also drag the dependencies inside your Xcode project in Frameworks/​dependencies. You **do not** need to add a script line to Build Phases > Run Scripts for dependencies. Only for the one library ManaPlus now requires (which you did earlier). 
 + 
 +Whew! What a ride. Now you can check out the length of my Static Library section... To see how all of this isn't require when you use a .a library. 
 + 
 +== Static Libraries == 
 + 
 +So you are sane and have decided to use Static Libraries. I learned about these after going through the pain of linking all my macports dynamic libraries [sigh]. So lets get started. You have a NewLibrary.a inside your /​opt/​local/​lib directory. Copy that file to the Xcode/lib folder inside the manaplus directory. Take the file and drag it into your Xcode project in the Frameworks section. It should automatically be added to the Summary > Linked Libraries section and also the Build Phases > Link Binary With Libraries area. You need to **remove it** from the Build Phases > Link Binary With Libraries section. This is because Xcode is broken, and if you leave it there, Xcode will point to a .dylib if it can find one (for more information on this, you can google '​perian-and-xcode-dylib-f.e.t.i.s.h'​ and remove the dots, the wiki doesn'​t like that word). 
 + 
 +You will also have to add the full path to the library in the Build Settings > Other Linker Flags section as so: 
 +<​code>​$(SRCROOT)/​libs/​NewLibrary.a</​code>​ 
 + 
 +Just add it before or after the existing ones. The $(SRCROOT) will transform to the correct path to your project. 
 + 
 +Et voila! You are done. The library will get included inside the application bundle, along with everything it needs (I don't think you even need to add its dependencies...). Now your glad you didn't use a dynamic library, aren't you. 
 + 
 +== Conclusion == 
 + 
 +Use static libraries. 
 + 
 +Oh, and finally, to make sure all went well, compile the application,​ navigate to its location. Right click and select Show Package Content. Navigate to the executable (Contents/​MacOS/​ManaPlus). In terminal, type 'otool -L ' with the space, and drag the ManaPlus executable onto the terminal to get its full path. Now press enter, you should not see any library that points to /​opt/​local/​lib,​ and if you used a static library, you shouldn'​t see it either. 
 + 
 +===== Problems and Improving the Workflow ===== 
 + 
 +If you wish to improve the building experience, here are some good places to start.
  
 +  * Find a way to reference the src directory, instead of hard-linking to the source files. This would let us skip the "​finding and removing files" phase.
 +<​del> ​ * Create a bash script in the Build Phases to compile the localization files and copy them inside the app bundle. This would allow us to forget about dragging new translations inside the locale folder. It would also ensure everything is always up to date.</​del>​ //done//
  
 +That's pretty much it for now!
Print/export
Languages