Introduction

Windows上でOpenCVのstaticライブラリを作成し、自作のdllにリンクさせる方法。

.NETでP/Invokeするとよくあるエラーの一つが、Nativeのdllが見つからないというのがあります。
例えば下記のような。

1
2
3
4
5
Unhandled exception. System.DllNotFoundException: Unable to load shared library 'XXXXXXXX' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libXXXXXXXX: cannot open shared object file: No such file or directory
at XXXXXXXX.net_Net_new(IntPtr& net)
at XXXXXXXX.Net..ctor() in /home/t-takeuchi/Work/OpenSource/YYYYYYY/src/XXXXXXXX/src/XXXXXXXX/Net/Net.cs:line 15
at YYYYYYY.YYYYYYY..ctor(YYYYYYYParameter parameter) in /home/t-takeuchi/Work/OpenSource/YYYYYYY/src/YYYYYYY/YYYYYYY.cs:line 118
at Demo.Program.Main(String[] args) in /home/t-takeuchi/Work/OpenSource/YYYYYYY/examples/Demo/Program.cs:line 35

たいていは、そのdllがないのではなく、そのdllが依存しているライブラリが存在しないというパターンが多い。
Windowsの場合はDepenecyWalkerとかで割と簡単に原因がわかる。
OSXなら、otool -L、Linuxの場合は、lddを使えばわかる。

しかし、今回、Ubuntuで発生した上記エラーに対し、lddを適用したところ

1
2
3
4
5
6
7
8
9
10
11
12
$ ldd bin/Release/netcoreapp3.1/libXXXXXXXX.so 
linux-vdso.so.1 (0x00007ffdb97dd000)
libvulkan.so.1 => /usr/share/vulkan/1.1.92.1/x86_64/lib/libvulkan.so.1 (0x00007fde29b7b000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fde2995c000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fde29754000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fde29550000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fde291c7000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fde28e29000)
libmvec.so.1 => /lib/x86_64-linux-gnu/libmvec.so.1 (0x00007fde28bff000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fde289e7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fde285f6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fde2ac47000)

エラーが見当たらなかった。

という問題の解決方法。

How to?

タイトル通りLD_DEBUGを使います。
ググっても、使い方がわかりづらかったのですが、要するに

1
$ LD_DEBUG=symbols,bindings dotnet run -c Release 2> error.log

のように、問題が発生するコマンドと合わせて実行するということです。

標準エラー出力に出力されるのでリダイレクトでファイルに書き出します。
かなり巨大なので注意。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
symbol=omp_get_max_threads;  lookup in file=/home/t-takeuchi/Work/OpenSource/YYYYYYY/examples/Demo/bin/Release/netcoreapp3.1/Demo [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libpthread.so.0 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libdl.so.2 [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libm.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libgcc_s.so.1 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/lib/x86_64-linux-gnu/liblttng-ust-tracepoint.so.0 [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/lib/x86_64-linux-gnu/liburcu-bp.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.0/libcoreclrtraceptprovider.so [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/lib/x86_64-linux-gnu/liblttng-ust.so.0 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/librt.so.1 [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/lib/x86_64-linux-gnu/liburcu-cds.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/home/t-takeuchi/Work/OpenSource/YYYYYYY/examples/Demo/bin/Release/netcoreapp3.1/libXXXXXXXX.so [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/share/vulkan/1.1.92.1/x86_64/lib/libvulkan.so.1 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libpthread.so.0 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/librt.so.1 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libdl.so.2 [0]
8183: symbol=omp_get_max_threads; lookup in file=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libm.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libmvec.so.1 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libgcc_s.so.1 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
8183: symbol=omp_get_max_threads; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
8183: /home/t-takeuchi/Work/OpenSource/YYYYYYY/examples/Demo/bin/Release/netcoreapp3.1/libXXXXXXXX.so: error: symbol lookup error: undefined symbol: omp_get_max_threads (fatal)

問題のdll名をgrepしていくと怪しそうなところが。
要するに、シンボル omp_get_max_threadslookup in していったけどついに見つかりませんでした、ということでした。

今回はdllがなかったのではなくシンボルが見つからなかったというパターン。
自分で呼び出しているものならともかく依存しているライブラリだと実行時のエラーメッセージには出ませんね。