Apple Reference, Articles, and Opinions

Using a C++ Library in an Xcode project

In the beginning of my software development career, I came across many projects, tutorials, and repositories that would make use of open source libraries. Many of these tutorials assume knowledge of how to integrate libraries into your projects by simply referencing a repo or a library that is currently available through some other package manager. While there are many resources online about how to integrate a library into your project, few explain how to do it for a newcomer.

This article assumes basic knowledge of the command line and Xcode

What is a library?

A library is a lanuguage-specific collection of code implementation. That is, a library of types & functions written in a language that is abstracted in such a way that it can be used without external knowledge of the library user. A good example of this if the cstdlib or C standard library which is included by using #include preprocessor in a C program. That particular library provides functions and data types fundamental to computer systems. Functions such as malloc to allocate memory and the div_t struct to represented a quotient and remainder. In a UNIX environment, many of these essential libraries are stored in a directory labeled /lib in the filesystem hierarchy. Libraries remove the need to rewrite code that you use more than once and creating your own is very helpful and save time. It is also helpful when collaborating with the development community as we will see by incorporating spdlog, an open source logging library that developers use to create different log messages depending on the severity of the message.

There are two main types of libraries, static and dynamic (AKA shared). Static libraries are incorporated fully into our final executable by making a full copy in our final application and this application will use it at compile time. Dynamic libraries are used across applications and executables so that many different applications can use the same code, but this code is only executed at run time and not compile time. The result is that applications using static libraries tend to be bigger because the libraries are included in the application. With dynamic libraries, they must be available on whatever system is using them prior to running and shown to the application that is dependent on them.

In this example we will be using a static library and subsequently, creating our own static library. When a tutorial refers to a library as something to use, make sure it is for the language you intend to use with it. In C/C++, libraries have built for UNIX based systems. These files have a .a file extension for a static library. We will clone the repository, build it, reference it in our library, and then compile and build that library that we can then use at a later time in projects.

One last thing to mention is that spdlog is available as a compiled library and as a header only library. That means that we could simply tell Xcode where the folder is for the include directory and it will take care of the rest. This is very simple and strightforward, but I would like to demostrate how one links a project to the library without a header only version as not all libraries have this ability.

Downloading and building spdlog


  1. Go to the spdlog and clone the repo to your desired location
    1. Using the directions in that repo, I will build it using the terminal commands below
$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && make -j

After you complete the steps listed, you should have a directory in that main spdlog directory called build inside of which will be a file called libspdlog.a. This is the library!

Creating a new Xcode static library



  1. Open Xcode and create a new project as macOS Library
    1. Select STL (C++ Library) in the Framework dropdown and Static in the Type dropdown
    2. You can remove all of the files Xcode creates for you
    3. To more easily find your products folder, you can change the project settings to dump the output of your project in a different directory by going to File->Project Settings... and changing the Derived Data location to a custom location, select the folder icon to choose a directory where you will be working out of...

Editing Project Settings

Let's go ahead and delete the 3 files created by xcode labeles project-name.cpp, project-name.hpp, and project-name-priv.hpp.

Incorporating spdlog and building your own library


Let's create a new C++ source code file and we can also check the box for Xcode to create a header file with that. You should now have two (mostly empty) files in your project folder. You can arrange these in whatever order you'd prefer.

In our header file, let's go ahead and include spdlog, so your file should look like this

#include <stdio.h>
#include <memory.h> // For shared pointers
#include "spdlog/spdlog.h" // Main logging
#include "spdlog/sinks/stdout_color_sinks.h" // Some color and formatting

#ifndef mac_spdlog_
#define mac_spdlog_


namespace Solo {
	class Logger {
	public:
		static void Init();
		inline static std::shared_ptr<spdlog::logger>& GetSoloLogger() { return s_SoloLogger; }
		
	private:
		static std::shared_ptr<spdlog::logger> s_SoloLogger;
	};
}

#endif

Now we can implement this in our source file like so

#include "mac_spdlog.hpp"

namespace Solo {
	std::shared_ptr<spdlog::logger> Logger::s_SoloLogger;
	
	void Logger::Init() {
		spdlog::set_pattern("%^[%T] %n: %v%$");
		s_SoloLogger = spdlog::stdout_color_mt("SoloLogger");
		s_SoloLogger->set_level(spdlog::level::trace);
	}
}

At this point your build should fail due to not being able to find "spdlog/spdlog.h". We need to link the library and headers with our library in order for this to work!

Add the library file to your project by going to Xcode Project->Build Phases->Link Binaries with Libraries

Add Library to Build Phases

Add the search paths for the header and library in Xcode Project->Build Settings (tip: use searchbar in upper right and quickly find this by typing "search paths")

Add search paths to build settings

Your library project should now build without any issues. In your Derived Data folder, you will find a folder with your project-name concatenated with some large hex number and from there you can go to Build/Products/Debug to find your .a file. This is your library file and now, the only thing you will need are your library's headers and this .a files from here to use whatever you write in your library. This is the advantage of using static libraries, you now have one package to link into your next project without worrying how to link anything else.

Now what?

We have successfully built a C++ library that can now be used in any other Xcode or C++ projects targeting the same architecture. In my next article, I will demonstrate how to incorporate this library into a Swift Xcode project so that you can use C++ code in Swift! Until then, thanks for reading!

With gratitude,
Jav Solo