3

次のディレクトリ構造があります。

./
 |- obj/
 |--- debug/
 |--- release/
 |- bin/
 |--- debug/
 |--- release/
 |- src/
 |--- main.c
 |--- libb/
 |----- foo.c
 |- include/
 |--- libb/
 |----- foo.h

Makefileさらに、次の形式 (例)で my の個々のオブジェクトの依存関係を手動で指定します。

 main_DEPS = libb/foo

と入力できるようになりmake bin/debug/main、必要な依存関係とターゲット ファイルが生成されます。

  • obj/debug/libb/foo.o
  • obj/debug/main.o
  • bin/debug/main

それ、どうやったら出来るの?私の現在のアプローチは非常に複雑で不完全です。

  • 以下はオブジェクトファイルを作成します。ただし、必要なサブフォルダー ( libb) がまだ存在しない場合、作成に失敗します。また、変更されたヘッダー ファイルも追跡しません。前提条件を自動的に生成する Makefile チュートリアルのトリックは、おそらく適応できますか?

    CFLAGS+=-I include
    
    obj/*/%.o: src/%.cpp
        $(CC) $(CFLAGS) $< -c -o $@
    
  • 以下は、バイナリの依存関係を解決し、必要なすべてのオブジェクト ファイルからビルドしようとします。*_DEPSしかし、変数からそれらのオブジェクト ファイルを取得する方法がわかりません。

    .SECONDEXPANSION:
    
    bin/debug/%: obj/debug/%.o $(patsubst %,obj/debug/%.o,$($(patsubst bin/debug/%,%,$@)_DEPS))
        $(LD) $(LDFLAGS) $< $(patsubst %,obj/debug/%.o,$($(patsubst bin/debug/%,%,$@)_DEPS)) -o $@
    
    bin/release/%: obj/release/%.o $(patsubst %,obj/release/%.o,$($(patsubst bin/release/%,%,$@)_DEPS))
        $(CXX) $(LDFLAGS) $< $(patsubst %,obj/release/%.o,$($(patsubst bin/release/%,%,$@)_DEPS)) -o $@
    

    残念ながら、これは依存関係を自動的に構築しません。「obj/debug/libb/foo.o: そのようなファイルやディレクトリはありません」と文句を言うだけですmkdir obj/debug/libb; make obj/debug/libb/foo.o

    また、これはどうしようもなく複雑であり、不要なコードの重複を使用しています (これは、さらに複雑にしない限り取り除くことはできません)。

これに対する最も複雑でない解決策は何ですか? make原則として、広く利用可能なもの (autoconf など)以外のものを使用することに反対しているわけではありませんが、労力 (および必要な新しい学習) を最小限に抑えることを好みます。よりもはるかに複雑ですmake

4

1 に答える 1

2

チャットメッセージに応じて更新する

@sehe少し簡単になります、はい…しかし、重複はまだあり、依存関係を構築しないという問題もあります

(単一のMakefileで) submake呼び出しで機能させるための冗長で効果的な(複雑ではない)方法を見つけました。

単一のルールと依存関係の定義のみを含む「outermake」があります

A_DEPS=dep1 dep2
C_DEPS=dep2

##########################
# "outer" Make
bin/%/A bin/%/B bin/%/C:
    $(MAKE) BUILD="$*" TARGET=$(@F) DEPS="$($(@F)_DEPS)" GENRULE

事実上、「推定された」情報をサブコールで明示的な変数に変換して作成します。Makefileの残りの部分には、「汎用ターゲットルール」の定義が含まれていGENRULEます。

##########################
# "inner" Make

%/*.o:
    mkdir -p "$(@D)" && touch "$@"

GENRULE: obj/$(BUILD)/$(TARGET).o $(DEPS:%=obj/$(BUILD)/%.o) 
    echo gcc -o "bin/$(BUILD)/$(TARGET)" $^
    mkdir -p "bin/$(BUILD)" && touch "bin/$(BUILD)/$(TARGET)"
.PHONY: GENRULE

繰り返しますが、テスト実行:

$ for target in bin/{debug,release}/{A,B,C}; do make -Bs "$target"; done

gcc -o bin/debug/A obj/debug/A.o obj/debug/dep1.o obj/debug/dep2.o
gcc -o bin/debug/B obj/debug/B.o
gcc -o bin/debug/C obj/debug/C.o obj/debug/dep2.o
gcc -o bin/release/A obj/release/A.o obj/release/dep1.o obj/release/dep2.o
gcc -o bin/release/B obj/release/B.o
gcc -o bin/release/C obj/release/C.o obj/release/dep2.o

オブジェクトはすべて作成されました:

$ find bin obj

bin
bin/debug
bin/debug/A
bin/debug/B
bin/debug/C
bin/release
bin/release/A
bin/release/B
bin/release/C
obj
obj/debug
obj/debug/A.o
obj/debug/B.o
obj/debug/C.o
obj/debug/dep1.o
obj/debug/dep2.o
obj/release
obj/release/A.o
obj/release/B.o
obj/release/C.o
obj/release/dep1.o
obj/release/dep2.o

単純な変数(非依存関係)の場合、$ @および$(@ F)自動変数を使用した簡単な例を次に示します。

EXTRA="--standardopts"
A_FLAGS="--a-opts"
B_FLAGS="--b-opts"

.SECONDEXPANSION:
    
debug/% release/%: EXTRA+=$($(@F)_FLAGS)

%/A %/B %/C:
    echo building $@ with $(EXTRA)
于 2012-05-07T15:10:49.417 に答える