web-dev-qa-db-ja.com

異なるディレクトリにソースファイルがあるMakefile

ディレクトリ構造が次のようなプロジェクトがあります。

                         $projectroot
                              |
              +---------------+----------------+
              |               |                |
            part1/          part2/           part3/
              |               |                |
       +------+-----+     +---+----+       +---+-----+
       |      |     |     |        |       |         |
     data/   src/  inc/  src/     inc/   src/       inc/

一部のC/C++ソースファイルをコンパイル/リンクできるpart/src(または実際にはどこでも)にあるメイクファイルをどのように作成すればよいですか?

-I $ projectroot/part1/src -I $ projectroot/part1/inc -I $ projectroot/part2/srcのようなことはできますか?.

それが機能する場合、それを行う簡単な方法があります。対応する部分のそれぞれにメイクファイルがあるプロジェクトを見ましたか?フォルダー。 [この投稿では、bash構文のように疑問符を使用しました]

120
devin

従来の方法は、各サブディレクトリ(part1part2など)にMakefileを配置して、それらを個別に構築できるようにすることです。さらに、すべてをビルドするプロジェクトのルートディレクトリにMakefileを用意します。 「ルート」Makefileは次のようになります。

all:
    +$(MAKE) -C part1
    +$(MAKE) -C part2
    +$(MAKE) -C part3

Makeターゲットの各行は独自のシェルで実行されるため、ディレクトリツリーを逆方向に移動したり、他のディレクトリに移動したりする必要はありません。

GNU make manual section 5.7 ;をご覧になることをお勧めします。とても助かります。

99
anon

あるサブディレクトリに別のサブディレクトリのコードに依存するコードがある場合は、トップレベルで単一のメイクファイルを使用する方がよいでしょう。

完全な根拠については Recursive Make Thoughd Harmful を参照してくださいプロジェクトの3分の1だけを伝えてください。

上記のリンクに到達できないようです。同じドキュメントがここに到達できます:

83
dave4420

VPATHオプションが役立つ場合があります。これは、ソースコードを検索するディレクトリをmakeに指示します。ただし、各インクルードパスには-Iオプションが必要です。例:

CXXFLAGS=-Ipart1/inc -Ipart2/inc -Ipart3/inc
VPATH=part1/src:part2/src:part3/src

OutputExecutable: part1api.o part2api.o part3api.o

これにより、VPATHで指定されたディレクトリのいずれかで一致するpartXapi.cppファイルが自動的に検出され、コンパイルされます。ただし、srcディレクトリがサブディレクトリに分割されている場合、これはより便利です。他の人が言ったように、あなたが説明するものについては、特に各部分が独立している場合は、各部分のmakefileを使用する方がよいでしょう。

30
CodeGoat

他のディレクトリにある必要なcppファイルをコンパイルするために、ルートMakefileにルールを追加できます。以下のMakefileの例は、目的の場所に到達するための良い出発点です。

 CC = g ++ 
 TARGET = cppTest 
 OTHERDIR = ../../someotherpath/in/project/src 
 
 SOURCE = cppTest。 cpp 
 SOURCE = $(OTHERDIR)/file.cpp 
 
 ##ソース定義の終了
 INCLUDE = -I./ $(AN_INCLUDE_DIR)
 INCLUDE = -I。$(OTHERDIR)/../ inc 
 ## end more includes 
 
 VPATH = $(OTHERDIR)
 OBJ = $( join $(addsuffix ../obj/、$(dir $(SOURCE)))、$(notdir $(SOURCE:.cpp = .o)))
 
 ##依存関係の修正srcに対して相対的な../.depになるようにdir 
 DEPENDS = $(join $(addsuffix ../.dep/、$(dir $(SOURCE)))、$(notdir $(SOURCE :. cpp = .d)))
 
 ##実行されるデフォルトのルール
 all:$(TARGET)
 @true 
 
 ##クリーンルール
 clean:
 @ -rm -f $(TARGET)$(OBJ)$(DEPENDS)
 
 
 ##実際のターゲットを作成するためのルール
 $(TARGET):$(OBJ)
 @echo "=============" 
 @echo "ターゲットのリンク$ @ "
 @echo" ============= "
 @ $(CC)$(CFLAGS)-o $ @ $ ^ $(LIBS)
 @echo-リンク完了-
 
 ##一般的なコンパイル規則
%。o:%.cpp 
 @mkdir -p $(dir $ @)
 @echo "=============" 
 @echo "Compiling $ <" 
 @ $(CC)$(CFLAGS)-c $ <-o $ @ 
 
 
 ##オブジェクトのルールcppファイルからのファイル
 ##各ファイルのオブジェクトファイルは、実際のソースディレクトリから1レベル上のobjディレクトリ
 ##に配置されます。
 ../ obj /%。o :%.cpp 
 @mkdir -p $(dir $ @)
 @echo "=============" 
 @echo "コンパイル$ <"
 @ $(CC)$(CFLAGS)-c $ <-o $ @ 
 
#「その他のディレクトリ」のルール「その他」ごとに1つ必要です。 dir 
 $(OTHERDIR)/../ obj /%。o:%.cpp 
 @mkdir -p $(dir $ @)
 @echo "==== ========= "
 @echo"コンパイル$ <"
 @ $(CC)$(CFLAGS)-c $ <-o $ @ 
 
 ##依存ルールを作成します
 ../。dep /%。d:%.cpp 
 @mkdir -p $(dir $ @)
 @echo "=============" 
 @echo $ *。o [.____の依存関係ファイルの構築。] @ $(シェル)-ec '$(CC)-M $(CFLAGS)$ <| sed "s ^ $ *。o ^ ../obj/$ *。o ^"> $ @ '
 
 ##「その他」ディレクトリの依存ルール
 $( OTHERDIR)/../。dep /%。d:%.cpp 
 @mkdir -p $(dir $ @)
 @echo "=========== == "
 @echo $ *。o 
の依存ファイルの構築@ $(Shell)-ec '$(CC)-M $(CFLAGS)$ <| sed "s ^ $ *。o ^ $(OTHERDIR)/../ obj/$ *。o ^"> $ @ '
 
 ##依存関係ファイルを含める
 -include $(DEPENDS)
 
23
RC.

ソースが多数のフォルダーに分散しており、個々のMakefileを用意することが理にかなっている場合は、以前に提案したように、再帰的なmakeが適切なアプローチですが、小規模なプロジェクトではMakefileへの相対パスでMakefileこのように:

# common sources
COMMON_SRC := ./main.cpp \
              ../src1/somefile.cpp \
              ../src1/somefile2.cpp \
              ../src2/somefile3.cpp \

次に、VPATHを次のように設定できます。

VPATH := ../src1:../src2

次に、オブジェクトを作成します。

COMMON_OBJS := $(patsubst %.cpp, $(ObjDir)/%$(Arch)$(DEBUG).o, $(notdir $(COMMON_SRC)))

これでルールは簡単になりました:

# the "common" object files
$(ObjDir)/%$(Arch)$(DEBUG).o : %.cpp Makefile
    @echo creating $@ ...
    $(CXX) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<

そして、出力の構築はさらに簡単です:

# This will make the cbsdk shared library
$(BinDir)/$(OUTPUTBIN): $(COMMON_OBJS)
    @echo building output ...
    $(CXX) -o $(BinDir)/$(OUTPUTBIN) $(COMMON_OBJS) $(LFLAGS)

次の方法でVPATH生成を自動化することもできます。

VPATH := $(dir $(COMMON_SRC))

または、sortが重複を削除するという事実を使用します(重要ではありませんが)。

VPATH := $(sort  $(dir $(COMMON_SRC)))
18
dashesy

Make(再帰的または非再帰的)を使用することは、現在のツールと比較して、学習、保守、およびスケーリングが難しいため、通常は避けたいものです。

これはすばらしいツールですが、直接使用することは2010年以降廃止されると考えられます。

もちろん、特別な環境、つまりレガシープロジェクトなどで作業している場合を除きます。

IDE、 CMake を使用するか、ハードコアの場合は Autotools を使用します。

(downvotes、ty honza指摘のため編集)

9
IlDan

RCの投稿はとても役に立ちました。私は$(dir $ @)関数の使用を考えたことはありませんでしたが、必要なことを正確に行いました。

ParentDirには、ソースファイルを含むディレクトリの束があります:dirA、dirB、dirC。さまざまなファイルが他のディレクトリのオブジェクトファイルに依存しているため、1つのディレクトリ内から1つのファイルを作成し、その依存関係に関連付けられたmakefileを呼び出して依存関係を作成できるようにしたいと考えました。

基本的に、parentDirにMakefileを1つ作成しました。このファイルには、RCに似た一般的なルールがあります(他にもたくさんあります)。

%.o : %.cpp
        @mkdir -p $(dir $@)
        @echo "============="
        @echo "Compiling $<"
        @$(CC) $(CFLAGS) -c $< -o $@

この汎用ルールを継承するために、各サブディレクトリにはこの上位レベルのメイクファイルが含まれていました。各サブディレクトリのMakefileには、各ファイルに依存するすべてを追跡できるように、各ファイルにカスタムルールを記述しました。

ファイルを作成する必要があるときはいつでも、(本質的に)このルールを使用して、すべて/すべての依存関係を再帰的に作成しました。パーフェクト!

注:「makepp」と呼ばれるユーティリティがあり、このタスクをさらに直感的に実行するように見えますが、移植性のために、別のツールに依存しないため、この方法を選択しました。

お役に立てれば!

2
jvriesem

Makeの再帰的な使用

all:
    +$(MAKE) -C part1
    +$(MAKE) -C part2
    +$(MAKE) -C part3

これにより、makeがジョブに分割され、複数のコアを使用できるようになります

2
EhevuTov

私はこのようなものを探していましたが、何度か試行錯誤した後、私は独自のメイクファイルを作成しますが、それは「イディオマティックな方法」ではありませんが、メイクを理解し始めており、これは私にとってうまくいきます。

PROJ_NAME=mono

CPP_FILES=$(Shell find . -name "*.cpp")

S_OBJ=$(patsubst %.cpp, %.o, $(CPP_FILES))

CXXFLAGS=-c \
         -g \
        -Wall

all: $(PROJ_NAME)
    @echo Running application
    @echo
    @./$(PROJ_NAME)

$(PROJ_NAME): $(S_OBJ)
    @echo Linking objects...
    @g++ -o $@ $^

%.o: %.cpp %.h
    @echo Compiling and generating object $@ ...
    @g++ $< $(CXXFLAGS) -o $@

main.o: main.cpp
    @echo Compiling and generating object $@ ...
    @g++ $< $(CXXFLAGS)

clean:
    @echo Removing secondary things
    @rm -r -f objects $(S_OBJ) $(PROJ_NAME)
    @echo Done!

私はそれが簡単であり、一部の人にとっては私のフラグが間違っていることを知っていますが、私が言ったように、これは私のプロジェクトを複数のディレクトリでコンパイルし、すべてをリンクしてビンを作成する最初のMakefileです。

私はサジェスチョンを受け入れています:D

autotoolsを使用することをお勧めします。

//##生成されたオブジェクトファイル(.o)をソースファイルと同じディレクトリに配置します。これは、非再帰的なmakeが使用される場合の衝突を回避するためです。

AUTOMAKE_OPTIONS = subdir-objects

Makefile.amに他の非常に単純なものとともに含めるだけです。

チュートリアル です。

0
user2763812