2017-02-20 7 views
3

私はlinux(Ubuntu 16.04)上で、私が動的にリンクしているいくつかのpocoライブラリを使って、C++アプリケーションを準備しています。 include、bin、lib、src、buildフォルダと関連するMakefileで構成されるプロジェクトフォルダがあります。これまでのところ私は今、私はLD_LIBRARY_PATHまたは編集するLDを変更せずにのみ、プロジェクトのlibフォルダ内のライブラリを検索するようにリンカーを走行中に希望

CC := g++ 

# Folders 
SRCDIR := src 
BUILDDIR := build 
TARGETDIR := bin 

# Targets 
EXECUTABLE := C++_APP 
TARGET := $(TARGETDIR)/$(EXECUTABLE) 

SRCEXT := cpp 
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) 
CFLAGS := -c -Wall 
INC := -I include -I /usr/local/include 
LIB := -L /usr/local/lib -lPocoFoundation -lPocoNet -lPocoUtil 

$(TARGET): $(OBJECTS) 
@echo " Linking..." 
@echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB) 

$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) 
@mkdir -p $(BUILDDIR) 
@echo " $(CC) $(CFLAGS) $(INC) -c -o [email protected] $<"; $(CC) $(CFLAGS) $(INC) -c -o [email protected]  $< 

clean: 
@echo " Cleaning..."; 
@echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET) 

.PHONY: clean 

libには/ usr/local /からライブラリを持って、次のMakefileを使用していました。 so.conf。そこで検索したところ、これはリンカー引数-Wl、rpath、$ ORIGINによって実現できることがわかりました。それはまだデフォルトディレクトリ(USR/local/libのからライブラリを入手ただし

LIB := -L $ORIGIN/../lib -lPocoFoundation -lPocoNet -lPocoUtil 

:だから私は、私は次の文

LDFLAGS := -Wl,-rpath,$ORIGIN/../lib 

を追加し、次のようLIBステートメントを変更する必要があることを前提としてい)、私はプロジェクトlibフォルダ上のライブラリなしでそれをテストして以来。私は何を間違えたのですか?

+0

'LIB:= -L $(ORIGIN)/../ lib -lPocoFoundation -lPocoNet -lPocoUtil'? () – skomp

+0

@skompに注意してください$(ORIGIN)と同じ結果です。デフォルトのフォルダからライブラリを取得しますが、プロジェクトのライブラリは取得しません。 – dk13

+0

-rpathリンカー・オプションは、デフォルトのライブラリー検索パスを置き換えず、別のエントリーを追加します。したがって、-rpathは、libがデフォルトの検索パスにない場合に機能します。あなたの場合ではないでしょうか?リンカのコマンドラインでlibsにフルパスを渡してみてください。 '-l $ ORIGIN /../ lib/PocoFoundation'のようなもの –

答えて

5

いいえ、誤解しています。リテラル文字列$ORIGIN/../libをリンカの引数として渡す必要があります。 $ORIGINトークンは、作成後にプログラム内に保持され、実行時リンカーがプログラムの実行を開始すると、$ORIGINが、プログラムが呼び出された現在のパスに置き換えられます。プログラムを他の場所にコピーしたとしても、これは当てはまります。したがって、プログラムを/usr/local/bin/myprogramとして実行すると、実行時リンカーは$ORIGIN/usr/local/binに置き換えます。 /opt/mystuff/libexec/myprogramにコピーすると、実行時リンカーは$ORIGIN/opt/mystuff/libexecに置き換えます。

メイクレシピによって呼び出されるコマンドにリテラル$を渡すためには、あなたはそれを2倍にすることにより、$をエスケープする必要があります:$$を。それ以外の場合は、make変数または関数の導入として$が表示されます。それはあなたが書くときに-Wl,-rpath,$ORIGIN/../libメイクとして$ORIGIN$Oを解釈する単一文字(ノート、[email protected]$<など)

場合、メイク変数等括弧を避けるためにするために、それは完全に合法だ、覚えておいてください空の変数Oを展開して、-Wl,-rpath,RIGIN/../libを与えます。

また、シェルから$をエスケープする必要があります。そうしないと、望ましくないシェル変数として$ORIGINが展開されます。あなたはこのような何かやりたい

LDFLAGS = '-Wl,-rpath,$$ORIGIN/../lib' -L/usr/local/lib 
LDLIBS = -lPocoFoundation -lPocoNet -lPocoUtil 

$(TARGET): $(OBJECTS) 
     @echo " Linking..." 
     $(CC) $^ -o [email protected] $(LDFLAGS) $(LDLIBS) 

を、コマンドを非表示にする@を使用する理由(私はちょうど@を取り出していない理由は...コマンドをエコー、その後、知りませんechoとしてmakeコマンドを表示させてください)

+0

お返事ありがとうございます。ちょうど1つの明確化私は/ home/user/project/libの中にあるプロジェクトのlibフォルダにnoneライブラリを試して、リンカがそれを見つけました。私も-L/usr/local/libを省略しました。私はまた、-L $$ ORIGIN /../ libに置き換えられましたが、運はありません。リンカが必要なライブラリの/ home/user/project/libフォルダのみをチェックすることは可能ですか? – dk13

+0

'-rpath'オプションは、RUNTIMEで共有ライブラリを見つけることを制御します。つまり、プログラムが呼び出されたときです。リンク時にライブラリを見つけることとは何の関係もありません。これは '-L'オプションによって制御されます。これらは全く重複しない2つの全く異なるものです。リンカーは '-rpath'設定を見ず、ランタイムローダーは' -L'によって提供されるディレクトリを見ません。したがって、ランタイム動作を理解しようとしている場合は、 '-L'フラグを完全に無視するだけです。これは無関係です。 – MadScientist

+0

ランタイムローダーには共有ライブラリを見つけるためのアルゴリズムがあります。このアルゴリズムについては、 'man ld.so'(' ld.so'は実行時ローダーコード)で読むことができます。 'DT_RPATH'を最初に使ってライブラリを探します(' -rpath'オプションで設定されたものです)。しかし、そこにライブラリが見つからなければ、それは他の場所を見ることで引き続き行われます。あなたのシステムは、 '/ usr/local/lib'などのライブラリを見つけるように設定されている可能性が非常に高いです。私は、ランタイムローダーにデフォルトの場所を探すのをやめさせ、ライブラリが見つからない'DT_RPATH' – MadScientist

関連する問題