LSI Jiu-Jitsu

電子工作とブラジリアン柔術

Makefileにサーチパスを追加

コンパイルしたexeをMakefileから実行させたい時などで、実行時に一時的にサーチパスを追加する方法です。

シェルスクリプトと同じ書き方でいけると思いきや意外と手こずりました。

やりたことは make run とした時に、ホームにあるOpenCVライブラリを $LD_LIBRARY_PATH に追加してexeを実行することです。

何種類か書いてようやく納得できる書き方が見つかりましたのでまとめてみます。

 

■ その1

シェルスクリプトのように再帰的に後ろに追加

export LD_LIBRARY_PATH = $(LD_LIBRARY_PATH):$(DIR_OPENCV_LIB)

run:
    ./exe

→ makeエラー

Makefile:xx: *** 再帰的変数 `LD_LIBRARY_PATH' が(最終的に)それ自身を参照しています. 中止.

 

■ その2

"+=" で追加

export LD_LIBRARY_PATH += $(DIR_OPENCV_LIB)

run:
    ./exe

→ 実行エラー

/usr/lib:/usr/local/lib ~/tool/opencv/lib

パスがコロンで区切られていないので見つからない。

 

■ その3

"+=" に ":" を追加

export LD_LIBRARY_PATH += :$(DIR_OPENCV_LIB)

run:
    ./exe

→ とりあえずOK

/usr/lib:/usr/local/lib :~/tool/opencv/lib

コロンが付いたことで認識できるようになったけど空白が気になる・・。

 

■ その4

echoさせてから後ろに追加

export LD_LIBRARY_PATH = $(shell echo $$LD_LIBRARY_PATH):$(DIR_OPENCV_LIB)

run:
    ./exe

→ OK!

/usr/lib:/usr/local/lib:~/tool/opencv/lib

意図した通りに追加されました。

g++でDPI-C向けライブラリを作成

g++でコンパイルしたライブラリをSystemVerilogからDPI-Cを通してコールしたところvcsがエラーを吐き出しました。

Error-[DPI-DIFNF] DPI import function not found
**********.sv, **
 The definition of DPI import function/task 'Convert' does not exist.
 Please check the stated DPI import function/task is defined, and its
 definition is either passed in a source file at compile-time, or provided in
 a shared library specified using the LRM Annex-J options at run-time.

どうやらそんな関数(Convert)が見つからないよと言っているようです。

試しにgccコンパイルして問題なくコールできているライブラリをg++でコンパイルし直してみたところ、やはり上記のようなエラーが発生しました。

 

調べてみると、どうやらg++でコンパイルすると名前修飾の影響で関数名が変わってしまうようです。

nmでシンボルリストを見てみると

$ nm refc.so
.............
00000000000093ea T _Z13ConvertiiiiiPviiiiiS_S_iiS_
.............

Convertの前後に文字列が付与されています。

 

これを回避する方法として、関数全体をextern "C"で囲って名前修飾させないようにする(C言語の名前で関数名を構築)のが一般的なようです。

#include "svdpi.h"

#ifdef __cplusplus
extern "C" {
#endif

int Convert(
 const svOpenArrayHandle in_img,
       svOpenArrayHandle out_img
){
......

 return(0);
}

#ifdef __cplusplus
}
#endif

nmでシンボルリストを見ると余計な文字列が付いていませんでした。

$ nm refc.so
00000000000093da T Convert
.............

これで無事にSystemVerilogからコールすることができるようになりました。

 

ちなみにライブラリを作る時のMakefikeはこんな感じにしています。

refc_src = refc.cpp
refc_obj = $(refc_src:%.cpp=%.o)
refc_so  = refc.so

%.o: %.cpp
	g++ -m64 -fPIC -I$(VCS_HOME)/include -I$(refc_dir) -o $@ -c $<

$(refc_so): $(refc_obj)
	g++ -m64 -shared -o $(refc_so) $(refc_obj)