How to use Firebase in iOS games written in C++

Patrick Martin
Firebase Developers
10 min readApr 20, 2020

--

Many games have a core thing in common when you really dig under the surface: there’s almost always a soft nougaty core of C++. Firebase offers native feeling SDKs for Android, iOS, Unity, and the Web which makes it super easy to connect your game or application to its globe spanning infrastructure. Unfortunately these SDKs are fairly difficult to integrate if you live in C++, making them very inconvenient to use for many game developers. Fret not, as Firebase has a cross platform C++ SDK that abstracts away all the platform specific constructs to get your game talking to the cloud as fast as possible!

The Firebase C++ SDK has five platform targets: Android, iOS, and the desktop (Windows, Linux, and MacOS). The APIs exposed are identical through all five platforms, but there are some platform specific nuances that need to be covered to successfully compile a game with Firebase and initialize the library. In this post, I’ll cover iOS.

C++ Build System

The Firebase SDK generally consists of two main components on iOS:

  1. A C++ layer packaged in the C++ SDK shipped both as Frameworks that you can drag and drop into your project as well as a combination of static libraries and header files that typical C++ build systems may understand better.
  2. A set of Objective-C Frameworks and their dependencies that you can either integrate with CocoaPods or by manually managing the Frameworks and their dependencies by hand.

For many games, developers will check in an XCode Project and mirror the project structure into it in parallel with the platform-specific project files for their other platforms. When you do this, the easiest way to integrate the C++ SDK would be to drag the C++ Frameworks into your XCode project and manage the rest via CocoaPods.

Other games, including those developed with Cocos2dx 4.0, will use a master build file that generates platform specific project files as part of the build process. In the case of Cocos, this master build file is a CMake project which also happens to be the build system Firebase uses behind the scenes for its C++ build.

In this post, I’ll demonstrate how to pull in Firebase using features available in the CMake build system. I’ll use its built-in rules to copy in the necessary static libraries and hook up the proper header search paths to interface Firebase with my game. Because of some incompatibilities between CMake and CocoaPods, I’ll also manually manage my native platform dependencies whilst also using features of CMake to construct an automated build pipeline that any developer on my team can use without intervention.

To follow along, now would be a great time to type cocos new:

cocos new CocosFirebase -p <com.your_company.your_game> -l cpp -d .

This basically says:

  • cocos new CocosFirebase: create a new project named CocosFirebase
  • -p <com.your_company.your_game>: the package name for your game, without the “<>” I threw in.
  • -l cpp: the language is C++
  • -d .: create the game in my current working directory

If CMake is new to you, I highly recommend that you read my brief intro article. Similarly, I’m going to use the binary Firebase SDK, but most of what I cover will work with the open sourced one.

Now is a good time to download your GoogleServices-Info.plist file as well. The instructions are to put it into the root of your Xcode project, but your generated xcodeproj just needs to know about it. I therefore chose to put it in my project’s Resources/ directory for Cocos2dx, which is automatically copied as part of its CMake build process.

Now I need to download the latest version of the Firebase C++ SDK. I chose to place this in third_party/firebase_cpp_sdk for the purposes of this tutorial. Unless you’re planning on distributing your game on Linux, I would recommend using the binary Firebase SDK for now. I do explain the pros and cons of the binary and open source SDKs here.

With this setup, open your CMakeLists.txt at the root of your project.

First you need to add_subdirectory the directory where you installed the Firebase C++ SDK. If you recall before, this is third_party/firebase_cpp_sdk in my project:

This will make CMake aware of the various Firebase targets.

Next you need to locate the executable or library that will depend on Firebase in your CMake project. By default, Cocos places this in the ${APP_NAME} variable. If you’re not using Cocos, remember that on iOS this is almost always an exectuable (via add_executable), but can be a library.

Once you know the target name of your game, you need to look up the Firebase dependencies for the Firebase products you wish to use. Since I’m using Firebase Analytics, this means that I need firebase_analytics and firebase_app. Update your game’s target_link_libraries with the Firebase dependencies you need:

After all of this, your project folder will look something like this (with the additions highlighted):

C++ Patch

A brief note: Version 6.9.0 of the binary Firebase C++ SDK and earlier have a small bug where the CMakeLists.txt does not properly link the iOS specific libraries. You should upgrade if possible or be willing to work through some linker errors.

Native Dependencies

For many games, you would typically have an XCode Project at this point to work with. In that case you can just follow the instructions under Add Firebase SDKs to your app in lieu of this section. As of right now, Cocos2dx (and other fully CMake based engines) will need a bit of extra work to get all of the iOS specific components of your game linked in. CocoaPods 1.10.0 will likely allow us to use a similar process with CMake in the future with this patch.

In lieu of my ability to integrate CocoaPods, I will use find_library to pull in some standard iOS libraries and download the rest directly. This avoids some complexities with CocoaPods integration into a current CMake project.

This will go a little beyond my intro to CMake tutorial, but it should still be relatively easy to follow.

To link Firebase Analytics, I will need two additional system libraries: sqlite3 and StoreKit. I’ll also need to pass the -ObjC linker flag. I can accomplish this by typing:

find_library has a special implementation for iOS that helps it locate built in Frameworks. I use this to find StoreKit and store it as ${STOREKIT_LIB} and to find sqlite3 and store it as ${SQLITE_LIB}.

target_link_options lets you pass in additional linker flags, including the -ObjC that the Firebase SDKs need. PUBLIC ensures that these changes are applied transitively to any dependent targets.

Finally, I use target_link_libraries to include the libraries I discovered via find_library.

Now I need to link in the iOS specific dependencies. I’ll extract the framework SDK zip file into third_party/iOS.

If you read the accompanying README.md, you’ll see this instruction:

Drag each framework from the “FirebaseAnalytics” directory into the Project Navigator pane. In the dialog box that appears, make sure the target you want the framework to be added to has a checkmark next to it, and that you’ve selected “Copy items if needed”. If you already have Firebase frameworks in your project, make sure that you replace them with the new versions.

The rough CMake equivalent of this instruction is:

First I create a variable named ${FIREBASE_FRAMEWORK_PATH} using the set command pointing to where I’ve downloaded the framework SDK.

Then I use file(GLOB to look for every *.framework file under FirebaseAnalytics/ and store them as a list in the variable ${firebase_dependencies}. This is roughly the equivalent of the instruction “Drag each framework from the FirebaseAnalytics directory into the Project Navigator pane” (although you’ll never actually see these Frameworks in the project navigator of the generated XCode project).

I then use foreach to take each dependency out of ${firebase_dependencies} individually (as ${dep}), and link it with my app using the line target_link_libraries(${APP_NAME} ${dep}). This is roughly equivalent to “make sure the target you want the framework to be added to has a checkmark next to it.”

To test this, you should invoke cmake from some build directory (I named mine ios-build):

cmake .. tells CMake to look one directory up for the CMakeLists.txt file. Replace .. with the path to your CMakeLists.txt file if you placed it elsewhere.

-GXcode tells CMake to generate an XCode project

-D passes a variable into CMake, this is equivalent to using set with the flag CACHE set.

-DCMAKE_SYSTEM_NAME=iOS indicates that we’re building for iOS.

-DCMAKE_OSX_SYSROOT=iphoneos indicates that we’re building for a physical device. The simulator would be iphonesimulator.

If you open your generated xcodeproj now, you should see these framework files under “Other Linker Flags”:

A word of warning: this only works for dependencies that only depend on framework files. In particular, Firestore, FirebaseMLVisionFaceModel, and FirebaseMLVisionTextModel all have additional resources that need to be added to Copy Bundle Resources. None of these have games-focused SDKs right now, so I’ll ignore these for the time being.

If you’re using this CMakeLists.txt to work with multiple operating systems, you can move all this optional iOS logic into a block defined by:

All of this may open you up to some linker errors if some of these frameworks are included in your project multiple times or at multiple versions. If you run into issues either integrating Firebase or another third party library, it’s really important that you reread this section and fully understand what’s happening and how to check it. If you do run into errors, check out the “Ask the Firebase community” section of the firebase support page for some great resources to help you get unstuck.

Calling Firebase from C++

I chose Analytics as it’s the simplest Firebase product to get working, and is the best way to test your Firebase integration with Android. To start getting analytics events, you just have to call ::firebase::App::Create.

To initialize Firebase in my Cocos project, I first add a ::firebase::App to my AppDelegate.h:

then I initialize it with:

If you’ve done everything right, you should see a user appear in your Analytics Dashboard:

What next?

Now would be a perfect time to start adding a few custom events for your game. I would also recommend Crashlytics as your next Firebase integration. It supports C++ in addition to ObjectiveC to really help you narrow in on those strange native call stacks you’ll see in many games.

If you’re like me, one of the biggest pain points of native C++ game development is just interfacing with web backends. Since most games now have some sort of service component, I recommend checking out Firebase Cloud Functions, Realtime Database, and Authentication to really start feeling Firebase’s power.

What if I don’t use Cocos or CMake?

All of the C++ frameworks are individually available via the binary Firebase C++ SDK. Rather than writing:

you can just look under the frameworks/universal directory of the Firebase SDK and drag firebase.framework and firebase_analytics.framework into your XCode project. It would then be much easier to add the native dependencies via CocoaPods rather than manually adding them in and playing dependency resolver yourself.

Resources

--

--

Patrick Martin
Firebase Developers

I’ve been a software engineer on everything from games to connected toys. I’m now a developer advocate for Google’s Firebase.