Thursday, May 26, 2016

How to Install OPENCV on Mac OS X with libstdc++ for CUDA

Installing opencv on Mac OS X has been painful for me because the older version of CUDA toolkit does not support libc++, while the default compilation option for OS X's clang is to use libc++ instead of libstdc++. Due to this issue, I kept getting errors like
undefined symbols for architecture x86_64: "cv::imread(std::string const&, int)" referenced from ...

So, in this post, I will cover how to install opencv on Mac OS X using libstdc++ and successfully run CUDA programs.

The easiest way is to use homebrew to install opencv. If you already do not have homebrew installed on your Mac OS X system, please refer here.

First, we will need to edit the default make option. To do so, run the command
$ brew tap homebrew/science
$ brew edit opencv

You may want to replace option "32-bit" with option "64-bit" in line 15, although I am not sure if this makes any difference.

Next, add a line with -DCMAKE_CXX_FLAGS:STRING=-stdlib=libstdc++ into line 76, after which it should read something like below:
      args = std_cmake_args + %W[
        -DCMAKE_OSX_DEPLOYMENT_TARGET=
        -DBUILD_ZLIB=OFF
        -DBUILD_TIFF=OFF
        -DBUILD_PNG=OFF
        -DBUILD_OPENEXR=OFF
        -DBUILD_JASPER=OFF
        -DBUILD_JPEG=OFF
        -DCMAKE_CXX_FLAGS:STRING=-stdlib=libstdc++
        -DJPEG_INCLUDE_DIR=#{jpeg.opt_include}
        -DJPEG_LIBRARY=#{jpeg.opt_lib}/libjpeg.#{dylib}
      ]

By the way, this formula file can also be edited by the following command
$ vim /usr/local/Library/Taps/homebrew/homebrew-science/opencv.rb

To restore the file back to the original, you may run
$ cd /usr/local/Library/Taps/homebrew/homebrew-science
$ git checkout -- opencv.rb

To restore all formula files in the folder to the default, you may run
$ git reset --hard HEAD

Now, you may proceed to install opencv, but make sure to compile it from source
$ brew install --build-from-source opencv

Please note that it will take quite some time to build the library, so please be patient. After complete, you may want to verify whether it has been compiled with libstdc++
$ otools -L /usr/local/Cellar/opencv/2.4.12_2/lib/libopencv_imgproc.dylib
libopencv_imgproc.dylib:
/usr/local/opt/opencv/lib/libopencv_imgproc.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
/usr/local/Cellar/opencv/2.4.12_2/lib/libopencv_core.2.4.dylib (compatibility version 2.4.0, current version 2.4.12)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)

As you can see, opencv has been compiled against libstdc++ instead of libc++. Now, you will be able to run your CUDA programs. Note, however, that you will need to ask g++ to link against libstdc++ as well. That is, for example, compile with the option as shown below:
$ g++ your_program.cxx -stdlib=libstdc++

1 comment: