C++ lib, Cmake, Obj-C++

A quick note for something that I couldn’t find anywhere else, and that cost me a few hours (and a bunch of white hair).

I’m currently trying to setup a MacOS graphical app to test my current thesis algorithms. The GUI is developed using the native Mac tools, namely the latest Xcode in Objective-C.

Some standard, ugly hacks first

Since the algorithms are developed in C++ with OpenCV, I first had to switch the project compilation language setting from According to the file extension to Obj-C++ and I had to modify the pre-compiled include file to ensure that the file opencv.hpp was included before any Cocoa related file. These tricks are well known:

• the first one forces Xcode to link the resulting binary against the standard C++ library. It’s not possible to use the file-type setting because of trick #2;
• the second trick aims at solving a collision in the definition of the MAX(a,b) function/macro. Both OpenCV and Cocoa define it but in slightly different ways, resulting in errors at compile-time.

By including OpenCV first in the .pch file, the MAX(a,b) symbol is already defined via a macro and the complier gets quiet. The drawback to this ugly hack is that it leads to the inclusion of opencv.hpp inside all the files of a project including pure Objective-C ones, hence you have to force the compiler to Obj-C++.

Now, the big problem

My algorithms are developed in C++ with OpenCV, and compiled to a static library from the command line, using Cmake to generate the compiling infrastructure.

In spite of the previously mentioned precautions, I kept having undefined symbol errors at link time when trying to use my code inside the graphical app. These errors were typically bound to the C++ standard part, since the missing functions were part of the std C++ namespace. However, I checked and checked again (and banged my head against the walls) and the linker invocation seemed perfectly fine…

And the solution!

Exploring the various linker settings in Xcode, I came across one called C++ standard library. Yes ! In Xcode, you can choose between 2 C++ standard libraries. The first one (used by default) is clang’s C++11 standard library libc++. The second one (used by the command line process) is the GNU’s libstdc++.

And things became clear:

Since I was not linking agains the same standard C++ library, the linker couldn’t find standard C++ symbols!

So, I switched to GNU’s libstdc++, and it did the trick.