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.