Macでbuildしたopencvのlibファイル使おうとするとLibrary not loadedと出たので解決法を忘れずに書いたった


# 問題


macの環境でopencvをbuildしてlibファイルを作成して実行しようと思ったのですが、
makefileでlibファイルのパスをしているはずなのに下記のエラーが出てしまいます。

```
dyld: Library not loaded: @rpath/libopencv_core.4.5.dylib
  Referenced from: /Users/satoukazuo/workspace/API/django_twitter/workspace/opencv_doc/barcode/./main
  Reason: image not found
```

Homebrewを使って `brew install opencv` で出来上がったlibファイルを使えばいいのですが、versionが少し古かったりします。シンプルに画像の輪郭抽出したい！、特徴点を抽出したい！、ヒストグラムを取りたい！などであればそれでいいのですが、数日前に最新リリースされたコードを使いたい場合はgitからコードをbuildしたlibファイルでないといかんす。

今回は `Library not loaded: @rpath/libopencv_core.4.5.dylib` となった場合の解決法を書いていきます。

# 開発コード

```makefile:GNUmakefile
CXX = c++
CXXFLAGS =  -I/usr/local/lib/opencv4.5.3/include/opencv4/
LDFLAGS = -L/usr/local/lib/opencv4.5.3/lib/
LDLIBS =  -lopencv_core -lopencv_imgcodecs  -lopencv_highgui -lopencv_imgproc
CXXVERSION = -std=c++14

main: main.cpp
	$(CXX) $< -o $@ $(CXXFLAGS) $(CXXVERSION) $(LDFLAGS) $(LDLIBS)

clean :
	rm main
```

```c++:main.cpp
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>


int main(int argc, const char* argv[])
{
    cv::String keys = "{src||}";
    cv::CommandLineParser parser(argc, argv, keys);
    cv::String src_path = parser.get<cv::String>("src");


    std::string name = "Effect";
    cv::Mat srcMat = cv::imread(src_path, cv::IMREAD_COLOR);

    cv::Mat dst;
    cv::cvtColor(srcMat, dst, cv::COLOR_BGR2GRAY);
    cv::namedWindow(name, cv::WINDOW_AUTOSIZE);

    while(true){

        cv::imshow(name, dst);
        int key = cv::waitKey(0);
        if (key == 27){
            break;
        } else if(key == 's'){
            cv::imwrite("output.png", dst);
        }
    }

    cv::destroyAllWindows();    
    return 0;
}

```

これで`make`すると実行ファイルの`main`が出来上がります。
ですが、 `./main -src=src_barcode.png` と実行すると上記のエラーが出ます。


# ファイル構成

```
barcode
 | main.cpp
 | GNUmakefile
 | src_barcode.png
 | main (実行ファイル)
```

# 解決方法

まず、otoolを使って実行ファイルで使われているlibファイルを表示します。

```sh
$ otool -L main
main:
	@rpath/libopencv_core.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	@rpath/libopencv_imgcodecs.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	@rpath/libopencv_highgui.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	@rpath/libopencv_imgproc.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
```

それで、 `install_name_tool -change` を使ってパスを変えます

```
install_name_tool -change @rpath/libopencv_core.4.5.dylib /usr/local/lib/opencv4.5.3/lib/libopencv_core.4.5.dylib main
install_name_tool -change @rpath/libopencv_imgcodecs.4.5.dylib /usr/local/lib/opencv4.5.3/lib/libopencv_imgcodecs.4.5.dylib main
install_name_tool -change @rpath/libopencv_highgui.4.5.dylib /usr/local/lib/opencv4.5.3/lib/libopencv_highgui.4.5.dylib main
install_name_tool -change @rpath/libopencv_imgproc.4.5.dylib /usr/local/lib/opencv4.5.3/lib/libopencv_imgproc.4.5.dylib main
```

これで 再度 `otool` を使うとパスが変わったことがわかります。

```sh
$ otool -L main
main:
	/usr/local/lib/opencv4.5.3/lib/libopencv_core.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	/usr/local/lib/opencv4.5.3/lib/libopencv_imgcodecs.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	/usr/local/lib/opencv4.5.3/lib/libopencv_highgui.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	/usr/local/lib/opencv4.5.3/lib/libopencv_imgproc.4.5.dylib (compatibility version 4.5.0, current version 4.5.3)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
```

 `./main -src=src_barcode.png` と実行すると、、、

![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/02f9ecd5-3ecd-6d42-b1e3-d02f7faecfa1.png)

無事白黒になりました:tada:

# PostScript
問題は解決しましたが、makeで生成したファイルをコマンドでlibファイルのパスを変換するのは面倒です。
どうにかならないですかね。