OpenCV with C++11 on OS X 10.8

The new C++11 standard includes many language and library features that make programming in C++ more enjoyable, such as lambdas, the auto keyword and smart pointers (in the STL). Visual Studio 2010 already supports some of these features out of the box, and Visual Studio 2012 implements even more (detailed list of features implemented by different compilers).

Here is how it works with Xcode 4.5 under OS X 10.8 Mountain Lion. All one needs to do in Xcode is:

  1. Enable the C++11 language features in the “build settings” pane. Under “Apple LLVM compiler 4.1 – Language” (select “All” instead of “Basic” settings first), set “C++ Language Dialect” to “C++11 [-std=c++11]”.
  2. Select ‘libc++’ as the standard library by setting “C++ Standard Library” to “libc++ (LLVM C++ standard library with C++11 support)” in the same section.

This second step is necessary because the new C++11 features depend on library support in the standard library, and the default standard library ‘libstdc++’ does not implement them, but ‘libc++’ does.

For a standalone project, all is well now. However, real projects have external dependencies, which is where it gets complicated. When libraries such as OpenCV are compiled from scratch with default settings, they link to the default standard library ‘libstdc++’. This causes linking errors when one wants to use it in a project that uses the new C++11 features and links to ‘libc++’.

Compiling OpenCV with libc++

The solution is to compile OpenCV with the same standard library (that is ‘libc++’). To do this, first download the latest version of OpenCV from opencv.org (I used OpenCV 2.4.2) and uncompress it.

Next, one could run CMake as usual to create Xcode projects, and then change the project settings mentioned above manually. However, one would need to redo this every time CMake is run, because it overwrites the Xcode project files.

A better approach is thus to apply these settings inside of the root CMakeLists.txt file of OpenCV. Find the following line (at line 348 in OpenCV 2.4.2):

add_definitions(-DHAVE_ALLOCA -DHAVE_ALLOCA_H -DHAVE_LIBPTHREAD -DHAVE_UNISTD_H)

and insert the following after it:

 message("Setting up Xcode for C++11 with libc++.")
 set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x")
 set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")

This sets up the projects for C++11 with the libc++ standard library.

Now configure OpenCV using CMake: choose the “Xcode” generator with the default native compilers.

Unfortunately, building the projects in Xcode fails in project “opencv_ts” (related OpenCV bug):

OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:1657:13: 'tr1/tuple' file not found
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:9801:34: No member named 'tr1' in namespace 'std'
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:9801:44: Expected ')'
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:9802:16: Use of undeclared identifier 't'
[...]

It turns out that these problems are caused by Google Test which is not compatible with C++11 yet. Sylvain Pointeau has a simple workaround for that (adding the line #define GTEST_USE_OWN_TR1_TUPLE 1 to the top of ts_gtest.h). However, this doesn’t help with subsequent problems in “opencv_perf_imgproc” and “opencv_perf_video”, which confuse C++11’s std::tuple with the built-in std::tr1::tuple:

OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:10847:24: No matching conversion for static_cast from 'const std::__1::tuple<double, double>' to 'std::tr1::tuple<double, double, void, void, void, void, void, void, void, void>'
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:10847:45: No matching conversion for static_cast from 'const std::__1::tuple<double, double>' to 'std::tr1::tuple<double, double, void, void, void, void, void, void, void, void>'
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:10848:9: No matching conversion for static_cast from 'const std::__1::tuple<double, double>' to 'std::tr1::tuple<double, double, void, void, void, void, void, void, void, void>'
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:10828:24: No matching conversion for static_cast from 'const std::__1::tuple<int, int>' to 'std::tr1::tuple<int, int, void, void, void, void, void, void, void, void>'
OpenCV-2.4.2/modules/ts/include/opencv2/ts/ts_gtest.h:10828:45: No matching conversion for static_cast from 'const std::__1::tuple<int, int>' to 'std::tr1::tuple<int, int, void, void, void, void, void, void, void, void>'

Instead, it is better to patch Google Test for libc++-compatibility. A simplified version of this patch is to replace the following line (in line 1657 in OpenCV 2.4.2):

#   include <tr1/tuple>  // NOLINT

with

// C++11 puts its tuple into the ::std namespace rather than ::std::tr1.
// gtest expects tuple to live in ::std::tr1, so put it there.
#include <tuple>  // NOLINT
namespace std {
    namespace tr1 {
        using ::std::get;
        using ::std::make_tuple;
        using ::std::tuple;
        using ::std::tuple_element;
        using ::std::tuple_size;
    }
}

This leaves one more compilation error:

OpenCV-2.4.2/modules/flann/include/opencv2/flann/lsh_table.h:196:14: Use of undeclared identifier 'use_speed_'

The suggested solution is to just delete the if (!use_speed_), which works fine.

Everything else should now compile and link cleanly.

7 Responses to “OpenCV with C++11 on OS X 10.8”

    • Christian Richardt

      I think you’re right. I didn’t compile with CUDA, so I don’t know what happens. But as CUDA doesn’t appear to support C++11 anyway, you can probably leave out that flag. However, I have no idea if it will link in the end.

      Reply
  1. Dan Kegel

    Looks like OpenCV-2.4.7 has this sorted, yay. No special options needed for building with XCode 5, which defaults to libc++.

    Reply

Leave a Reply