box2D for iOS made easy: make it a static library

http://box2d.org/ is a wonderful, FREE!, physics library. Without it, we probably wouldn’t have the likes of Angry Birds (since Angry Birds was built on-top of it).

But … it’s a C++ library, and the official version doesn’t play nice with iOS (iPhone/iPad). You can include the full source into your project, but then you (might) run into Apple’s bugs where C++ sometimes fails to compile correctly in Xcode. And … you get several Warnings for the box2D source, where it doesn’t quite meet Xcode’s expectations. Most teams work on a “zero warnings allowed” basis, forcing you to branch the project :(.

Solution: convert box2D into a static library!

Please note: This tutorial is the MINIMUM steps we found that workaround the Xcode bugs. They SHOULD work for all other C++ libraries too – this is a more careful, cautious approach than the “standard” way you create static libraries.

But … if you see an unecessary step, or mistake, please add a comment to this post and I’ll look into it.

1. Create a new Xcode Project

When we’re done, you’ll have two items (a file and a folder) which you can drag/drop into any xcode project, and they will Just Work ™ – every time, with no code changes needed.

To start with, create a new Xcode project, and choose a type of: “Cocoa Touch Static Library”

2. Add the Box2D source

This is where it gets slightly tricky: we are going to workaround a major bug in Xcode, and a minor nuisance in the way box2D’s source code is written.

NB: box2d’s source is correct – it’s following the standards – it’s Apple that is wrong here. But … many library authors have given up, and just follow Apple’s “customized” version of the standards, because it makes life easier.

i. Download the source

First, download the box2d source code (if it’s not there, use the links from box2d.org to find it)

ii. Find the correct set of files

Inside the zip file, you’ll find a lot of stuff:

…you want the Box2D sub-folder from the above screenshot. Copy the whole thing somewhere on your hard disk (you don’t want to change the original).

iii. Duplicate the headers

This step is critical: most libraries don’t need this, but we have to workaround a bug in Xcode

  1. Create two new folders: “src” and “headers”
  2. Copy/paste the Box2D folder into “headers”, and move the original into “src” – yes, you really DO need two copies of the source!
  3. Move both folders (“src” and “headers”) into the folder where your new Xcode project lives. DO NOT ADD THEM TO YOUR PROJECT.

Finally … open the “headers” copy of Box2D in Finder … and “move to trash” every single file that is NOT a “.h” file.

NB: you *will* end up with two copies of every header file – one in the “headers” folder, and one in the “src” folder. That sounds strange, but it’s how we force Xcode to do what it’s supposed to do.

iv. Add to project

This step is critical: most libraries don’t need this, but we have to workaround a bug in Xcode

  1. Drag/drop the “src” folder into your project
    1. CRITICAL: “Create groups for any added folders” MUST be checked
  2. Drag/drop the second Box2D folder (the one inside “headers” into your project
    1. CRITICAL: “Create folder references for any added folders” MUST be checked

When you’re finished, it MUST look like this. If not – you did it wrong, and YOUR LIBRARY WILL NOT WORK

Note that the copy from “headers” has all the folders coloured blue, whereas the copy from “src” has all the folders coloured yellow. That is very important…

3. Fix the headers (part 2)

We’ve duplicated the headers, and added them to the project.

But now we have to workaround ANOTHER bug in Xcode – one that is fatal to the box2D project.

Also … by default, Xcode does NOT make headers available to other projects. This is a bad “default” behaviour of Xcode – Xcode knows we’re making a static library, so it’s pretty obvious we’d want people to use it!

First, remove Xcode’s buggy, incorrect header-export:

  1. Open the build-settings for your new library project
  2. Select the “Build Phases” tab
  3. Open the “Copy Headers” phase
  4. …and delete all the headers in there

Next, add the headers CORRECTLY, and make them PUBLIC:

  1. Drag/drop the blue “Box2D” folder from the Project Navigator into the Public section
  2. …NB: you *must* drag the blue folder
  3. …NB: you *must* drag it – if you use the small “+” button, that is for adding headers, XCODE WILL NOT DO WHAT YOU TOLD IT TO (bug).

When you’re done, you should have exactly this:

5. Make the library “universal”

For Xcode 4.0, Apple removed a *critical* feature – their build notes said it was too confusing for developers, so they simply removed it. I think it’s more likely they decided they didn’t have time to fix all the bugs in their implementation (there were quite a few)…

Anyway, we’re going to add the feature back in.

Using this StackOverflow question and answer, convert your library from “Simulator only” / “Device only”, into a library that works on both simulators AND on devices, all in one file.

Briefly:

  1. In the Build Settings page you already have open in Xcode, click “Add Build Phase -> Run Script Phase” at bottom right
  2. Copy/paste the script from StackOverflow into the script area.

Easy!

6. Build, and add to your game / app project

Hit Build, and you get a library.

However, there’s ANOTHER bug in Xcode: it will “hide” the library somewhere semi-random on your hard disk. The StackOverflow answer has step-by-step instructions for finding it (hint: look in the Build Results window in Xcode, and the script prints the location to screen, so you can find it, because Xcode hides it from you).

Now drag/drop the file (e.g. “libBox2dStatic.a”, if you called your box2d project “Box2DStatic”) into your main app project.

In Finder, in the same folder where you found the “.a” file, you’ll see a folder “usr” – also drag/drop this one into your project. (it contains all the header files that Box2D needs)

7. Configure your project to find the header files

By default, Xcode ignores incoming header files. This is poor interface design from Apple – most IDE’s would have asked you “are you adding these files to your project – or are they part of a library that you’re importing?” – but it means we have to manually tell Xcode that we just added library headers.

  1. IN YOUR MAIN GAME/APP: go to the Build Settings page
  2. Select the TARGET you’re building (not the PROJECT), and select “Build Settings” tab
  3. in the search box, type “header”
  4. Edit the “Header Search Paths” line, and add an entry (if its not there already): “$(SRCROOT)”
  5. Hit Enter/Return key (Xcode will often delete the new entry if you don’t do this!)
  6. Check the little tickbox to the left of the new entry – this is REQUIRED

When you’re done, double-click the “Header Search Paths” and check your entry is there (c.f. note above, about how Xcode often deletes new entries for no apparent reason). It should look like this:

(NB: the libxml2 line in the screenshot probably isn’t needed in your project – in this example, I used a project that already had some Header Search Paths)

8. Import Box2D, and start coding…

YOU MUST NOT #import BOX2D – it doesn’t support that usage. Instead, you must #include it – and you MUST use angle-brackets.

Here’s an example – note how the “#import” for Foundation is an import, but the Box2D is an include:

Finally: since box2d is written in C++, you MUST make your source file into Objective-C++. This is very easy – all you have to do is rename it from “.m” to “.mm”.

(if that doesn’t work, you can open the right-hand panel in Xcode, and in the “Identity and Type” section, set the File Type setting to “C++ Source File”)

10 thoughts on “box2D for iOS made easy: make it a static library

  1. Tried several times. Wasted hours because “File not found” in Box2D. Randomly changes which file is not found every time I try to build. Why is the static library not made available for download?

  2. Hello! Thanks for sharing.
    Although I Tried, I have xCode 4.5, so I don’t know how to do some steps, like the copy headers.
    Since it’s a file, can you please zip it and share with the community? We would really appreciate this!

    Thanks!

  3. It is very easy, and you need to learn this for yourself. It takes less time to learn than it would take you to download the file.

  4. I was really hoping this would work for me. I followed all the steps and got the finished library but I’m still getting a ton of Box2d errors about “file not found”. Grrr … guess I’ll keep looking. Thanks for the write-up though, it was very insightful.

  5. the images are not showing anymore, can you fix it please? there’s something important to see there to understand this tutorial

  6. I’ve followed the instructions to the letter, but alas it’s not working. I’m getting the “File Not Found” for every Box2D #include in the source code when I try to compile the static library. I presume that you may have missed a search header step in the compiler settings? I’ll keep cracking as Box2D is such a pain to set up…

  7. In the latest Xcode, Apple secretly changed the way they compile and build, breaking a large number of projects.

    I recommend submitting bugs to them – whatever you can to annoy them – maybe in future they’ll behave a little better, and stop doing this to developers.

    This post needs rewriting from scratch to work with the “new” Apple poorly-documented build system. There are still bugs in XCode’s build flow, but they’re different ones today :(.

    Finally: Apple is about to release Xcode 5, which will almost certainly break it all over again. I would recommend waiting for Xcode 5 before figuring this out – Box2D is hard to integrate to start with, and it’s not worth the pain of figuring out the arcane combination of undocumented settings … if Apple’s about to invalidate it in a few weeks time!

Leave a Reply

Your email address will not be published. Required fields are marked *