web-dev-qa-db-ja.com

makefile:異なるサブディレクトリからのオブジェクトファイルをリンクし、異なる検索パスを含める方法

テストコード(tsnnls_test_DKU.c)の場所を変更したいのですが、このフォルダーの変更を正しく反映するためにmakefileを変更できません。いくつかの助けをいただければ幸いです。

2つの質問があります: 1)異なるサブディレクトリからオブジェクトファイルをリンクする方法2)異なる検索パス(私の例では3つの検索パス)を含めます。

Makefileが正常に機能する元のセットアップでは、テストコードtsnnls_test_DKU.cを次の場所(サードパーティライブラリ内)に配置します。

Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls

私がリンクしているすべてのオブジェクトファイルは、

OBJDir = /home/dkumar/libtsnnls-2.3.3/tsnnls

また、tsnnls_test_DKU.cに含まれる一部のインクルードファイルは、次の3つの場所にあります(つの検索パス):

Dir1 = /home/dkumar/libtsnnls-2.3.3/tsnnls  
Dir2 = /home/dkumar/libtsnnls-2.3.3
Dir3 = /home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic

そして私のmakefileはうまく機能します。

ただし、テストコードの場所を次のように変更したいと思います。

Dir4 = /home/dkumar/CPP_ExampleCodes_DKU/Using_tsnnls_DKU/

これが私のmakefileがどのように見えるかです(他のユーザーからの入力後に更新されました:

# A sample Makefile

VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls
INC_PATH  = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/  -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/

# Here is a simple Make Macro.
LINK_TARGET     = tsnnls_test_DKU
OBJS_LOC    = tsnnls_test_DKU.o

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS =  libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
    libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
    libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
    libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
    libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
    libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
    libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
    libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o   \
    $(OBJS_LOC)

REBUILDABLES = $(LINK_TARGET) 

all : $(LINK_TARGET)
    echo All done

clean : 
    rm -f $(REBUILDABLES)   
    echo Clean done

#Inclusion of all libraries
RANLIB = ranlib
STATICLIB= /usr/local/lib/taucs_full/lib/linux/libtaucs.a 

tsnnls_test_LDADD = $(LDADD)
LIBS = -largtable2 -llapack -lblas -lquadmath -lm

$(LINK_TARGET) : $(OBJS)   $(tsnnls_test_LDADD) $(LIBS)  $(STATICLIB)
gcc -g ${INC_PATH} -o $@ $^

「$ make」を実行しようとしたときに発生するエラー

make: *** No rule to make target `libtsnnls_la-taucs_malloc.o', needed by `tsnnls_test_DKU'.  Stop.

明らかに、私はVPATHを適切に使用することができませんでした。

PDATE:私の質問に答えてくれたMikeKinghanに感謝します。

6
Garima Singh

Q1:別のサブディレクトリからオブジェクトファイルをリンクする方法は?

プログラムprogが、サブディレクトリobjにコンパイルされるオブジェクト_file0.o_、_file1.o_からリンクされるCプログラムであるとします。これは、そのリンケージを実行するためにメイクファイルで通常必要な種類のものです。

_$(OBJS) = $(patsubst %.o,obj/%.o,file0.o file1.o)

prog: $(OBJS)
    gcc -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
_

これにより、$(OBJS) = _obj/file0.o, obj/file1.o_になり、そのようなオブジェクトファイルをlinkコマンドに渡すだけです。 patsubstのドキュメント

NBコンパイルするときにobjサブディレクトリが存在しない場合、これはcreateには不十分です。その中にオブジェクトファイル。自分で作成するか、makeに実行させる方法を学習する必要があります。

Q2:さまざまな検索パスを含める方法は?

これはあいまいな質問です-あいまいさはあなたを混乱させます-そして私たちはそれをQ2.a、Q2.b、Q2.cに分解しなければなりません:

Q2.a:プリプロセッサがソースコードで_#include_-されたヘッダーファイルを検索するさまざまな検索パスを指定するにはどうすればよいですか?

デフォルトでは、プリプロセッサは組み込みの標準検索パスのリストを使用してヘッダーファイルを検索します。プリプロセッサを冗長モードで実行すると、それらを確認できます。例:_cpp -v_(CTRL-Cで終了)。出力には次のようなものが含まれます。

_#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
_

サブディレクトリincおよび_inc/foo/bar_に独自のヘッダーファイルがいくつかあり、プリプロセッサがこれらのディレクトリも検索するようにしたいとします。次に、プリプロセッサオプションを渡す必要があります。

_-I inc -I inc/foo/bar
_

コンパイルコマンドに。プリプロセッサオプションは、通常、make変数CPPFLAGSに割り当てられます。

_CPPFLAGS = -I inc -I inc/foo/bar
_

(必要な他のプリプロセッサオプションとともに)、コンパイルコマンドレシピでこの変数を介して渡されます。

_gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
_

N.B。CPPFLAGSがC++コンパイラフラグの従来のmake変数であると考えるのはよくある間違いです。 C++コンパイラフラグの従来のmake変数はCXXFLAGSです。

以下を実行すると、_-I_オプションの効果を確認できます。

_mkdir -p inc/foo/bar # Just to create the path
cpp -v -I inc -I inc/foo/bar
_

(CTRL-Cで終了します)。これで、出力には次のようなものが含まれます。

_#include "..." search starts here:
#include <...> search starts here:
 inc
 inc/foo/bar
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
_

Q2.b:リンカーがライブラリを検索するさまざまな検索パスを指定するにはどうすればよいですか?

progとリンクする必要のあるライブラリ_libfoobar.a_があり、それがメイクファイルから2レベル上のディレクトリlibにあるとします。次に、リンカーオプションを渡す必要があります。

_-L ../../lib
_

そして

_-lfoobar
_

リンクコマンドに。これらの最初のものは、_../../lib_がライブラリを探す場所の1つであることをリンカに通知します。従来、このオプションはLDFLAGSを介してリンカーコマンドレシピで渡します。 2つ目は、_libfoobar.a_(静的ライブラリ)または_libfoobar.so_(動的ライブラリ)と呼ばれるライブラリを検索するようにリンカに指示します。従来、このオプションはLDLIBSを介してリンカーコマンドレシピで渡します。

プリプロセッサの検索パスのデフォルトリストがあるのと同じように、リンカの検索パスのデフォルトリストがあります。あなたは実行することによってそれらを見ることができます:

_gcc -v -Wl,--verbose 2>&1 | grep 'LIBRARY_PATH'
_

出力は次のようになります。

LIBRARY_PATH =/usr/lib/gcc/x86_64-linux-gnu/4.8 /:/ usr/lib/gcc/x86_64-linux-gnu/4.8 /../../../ x86_64-linux-gnu /:/ usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib /:/ lib/x86_64-linux-gnu /:/ lib /../ lib /:/ usr /lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib /

標準ライブラリの1つをリンクする必要がある場合。 libm(数学ライブラリ)。デフォルトのライブラリ検索パスの1つにあり、_-L_オプションを渡す必要はありません。 _-lm_だけで十分です。

Q2.c:makeがターゲットの前提条件を検索するさまざまな検索パスを指定する方法は?

N.B。これはmakeに関する質問であり、プリプロセッサ、コンパイラ、またはリンカに関する質問ではありません。

すべてのオブジェクトファイルがサブディレクトリobjにコンパイルされると想定しています。それらをそこでコンパイルするには、パターンルールを使用するだけで簡単です。

_obj/%.o:%.c
    gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
_

makeにそのことを伝えます。例: _obj/file0.o_は_file0.c_からレシピによって作られています:

_gcc -c -o obj/file0.o $(CPPFLAGS) $(CFLAGS) file0.c
_

同様に、任意のファイル_obj/*.o_および一致するファイル_*.c_

_file0.c_がmakefileと同じディレクトリにある限り、これは問題ありませんが、_*.c_ファイルが別の場所にあると仮定しますか?ソースファイルがサブディレクトリ_foo/file0.c_および_bar/file1.c_で編成されているとします。その場合、makeはそのパターンルールを満たすことができず、「ターゲットobj /file0.oを作成するルールがない」などと表示されます。

この問題を解決するには、特別な意味を持つVPATH変数であるmakeを使用します。 ':'で区切られたディレクトリ名のリストをVPATHに割り当てると、makeは、リストされている各ディレクトリで前提条件が見つからない場合は常に検索します。カレントディレクトリ。そう:

_VPATH = foo:bar
_

makeが現在のディレクトリを検索し、そのパターンルールに一致する_.c_ファイルを検索しようとするとfoobarが検索されます。ルールを満たすことに成功し、必要なソースファイルをコンパイルします。

N.B。投稿されたコードでVPATHを誤って使用しました:

_VPATH = -L/home/dkumar/libtsnnls-2.3.3/tsnnls
_

リンカオプション_-L_を使用して、linker検索パスを割り当てました。

結論:

  • ヘッダーファイルを検索するための先行検索パスは、プリプロセッサの_-I<dirname>_オプションで指定されます。これらのオプションをCPPFLAGSのコンパイルレシピに渡します

  • ライブラリを検索するためのリンカ検索パスは、リンカの_-L<dirname>_オプションで指定されます。これらのオプションをLDFLAGSのリンケージレシピに渡します

  • makeルールの前提条件の検索パスは、make変数VPATHで、 ':-ディレクトリ名の句読点リストとして指定されます。

19
Mike Kinghan

My answer to part of questionリンクする方法を見つけることができましたobject files from different subdirectory/ subdirectories;それでも could not figure out how to use different search path

私の現在のメイクファイルは次のとおりです。

    # A sample Makefile

OBJS_PATH = /home/dkumar/libtsnnls-2.3.3/tsnnls/
C_INCLUDE_PATH  = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/  -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/
CPATH  = -I/home/dkumar/libtsnnls-2.3.3/ -I/home/dkumar/libtsnnls-2.3.3/tsnnls/  -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/

# Here is a simple Make Macro.
LINK_TARGET     = tsnnls_test_DKU
OBJS_LOC    = tsnnls_test_DKU.o

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS =  libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
    libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
    libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
    libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
    libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
    libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
    libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
    libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o   

 ## adding "$(OBJS_PATH)" to each Word in "$(OBJS)"
# which in our case is basically to add the same folder in front of all "*.o" object files.
OBJS2 = $(addprefix $(OBJS_PATH)/, $(OBJS)) 


# OBJS_LOC is in current working directory,
OBJS_ALL = $(OBJS2) \
    $(OBJS_LOC)

## DKU IS COPING THIS FROM ORIGINAL MAKEFILE THAT ARE GENERATED USING /home/dkumar/libtsnnls-2.3.3/tsnnls/MAKEFILE.AM
RANLIB = ranlib
STATICLIB= /usr/local/lib/taucs_full/lib/linux/libtaucs.a 

tsnnls_test_LDADD = $(LDADD)
LIBS = -largtable2 -llapack -lblas -lquadmath -lm


REBUILDABLES = $(OBJS_LOC) $(LINK_TARGET) 


all : $(LINK_TARGET)
    echo All done

clean : 
    rm -f $(REBUILDABLES)   
    echo Clean done

# Here is a Rule that uses some built-in Make Macros in its command:
$(LINK_TARGET) : $(OBJS_ALL)   $(tsnnls_test_LDADD) $(LIBS)  $(STATICLIB)
    gcc -g -o $@ $^
0
Garima Singh