2012-11-17 8 views
14

特定のターゲットに対してのみincludeディレクティブを使用したいとします。私はmakefileが不必要に生成されているので、ターゲットが必要ないときには他のmakefileを実行したくありません。特定のターゲットに対してmakefileでincludeディレクティブを使用する方法

したがって、ターゲット上で条件付きであるincludeディレクティブを条件付きで使用する方法はありますか?または、何らかの形でincludeディレクティブをターゲットの前提条件にする。ここで

は、私がこれまで持っているものです。

# Flags 

INCDIR = $(CURDIR)/include 
CFLAGS = -Wall -Wno-overflow -Wno-uninitialized -pedantic -std=c99 -I$(INCDIR) -O3 
LFLAGS = -flat_namespace -dynamiclib -undefined dynamic_lookup 

# Directory names 

# Set vpath search paths 

vpath %.h include 
vpath %.c src 
vpath %.o build 
vpath %.d build 

# Get files for the core library 

CORE_FILES = $(wildcard src/*.c) 
CORE_OBJS = $(patsubst src/%.c, build/%.o, $(CORE_FILES)) 
CORE_DEPS = $(CORE_OBJS:.o=.d) 

# Core library target linking 

core : $(CORE_OBJS) | bin 
    $(CC) $(LFLAGS) -o bin/libcbitcoin.2.0.dylib $(CORE_OBJS) 

# Include header prerequisites (How to do only for "core" target?) 

include $(CORE_DEPS) 

# Makefiles for header dependencies. 

$(CORE_DEPS): build/%.d: src/%.c | build 
    rm -f [email protected]; \ 
    $(CC) -I$(INCDIR) -MM $< -MT '$(@:.d=.o) [email protected]' > [email protected] 

# Objects depend on directory 

$(CORE_OBS) : | build 

# Create build directory 

build: 
    mkdir build 

# Create bin directory 

bin: 
    mkdir bin 

# Core Compilation 

$(CORE_OBJS): build/%.o: src/%.c 
    $(CC) -c $(CFLAGS) $< -o [email protected] 

# Depencies require include/CBDependencies.h as a prerequisite 

build/CBOpenSSLCrypto.o: include/CBDependencies.h 

# Crypto library target linking 

crypto : build/CBOpenSSLCrypto.o -lcrypto -lssl | bin 
    $(CC) $(LFLAGS) -o bin/libcbitcoin-crypto.2.0.dylib build/CBOpenSSLCrypto.o -lcrypto -lssl 

# Crypto library compile 

build/CBOpenSSLCrypto.o: dependencies/crypto/CBOpenSSLCrypto.c 
    $(CC) -c $(CFLAGS) $< -o [email protected] 

#Clean 

clean: 
    rm -f $(CORE_OBJS) $(CORE_DEPS) build/CBOpenSSLCrypto.o 

あなたは、私が 『暗号化』のための「.D」ファイルを含める必要はありませんが、私は 『コア』のために何を伝えることができるはずと(デフォルトゴール)。

ありがとうございました。

+0

これはできますが、*はできません。それはメイクの穀物に逆らって、より良い方法があります。すばやく簡単なアプローチ、あるいは高度で強力なものをご希望ですか? – Beta

+1

それから、私は質問することができます: "穀物"と "これらの"良い方法 "とは何ですか?維持しやすい限り。それが私が望むものです。私は手動でヘッダの前提条件を追加したくありません。 –

答えて

15

メイクは、1つの穀物に反するようにそれを処理し、手続き型言語ではありません。あなたのmakefileは拡大縮小が難しく、微妙なバグにつながる可能性があります。

清潔で効率的でスケーラビリティのあるTom Tromeyのbetter wayがあります。このトリックは、オブジェクトファイルと同じ手順で依存関係ファイルを構築できることを認識することです。依存関係は、オブジェクトの再構築が必要なときにMakeに通知します。最初にオブジェクトをビルドしたときは、オブジェクトをビルドする必要があることがわかっているので、それらを必要としません。また、依存関係が変更された場合は、ソースまたは古い依存関係が変更されたためである可能性があります。したがって、Makeはオブジェクトを再構築する必要があることを認識します。 (これは少し思考がかかる場合がありますので、明らかにされていません。)

​​

1つの以上ヒッチがあります:依存性を除去するために、あなたは、コードを変更した場合 - とも、そのファイルを削除 - あなたが勝ちました」古い従属リストはもはや見つからないファイルを要求するため、再構築することはできません。必要なときに再構築されると仮定することができるように洗練されたソリューションは、なしのコマンドを使用して、独自の権利で、ターゲットごとの前提条件(例えば、ヘッダ)を作成するように依存関係ファイルを処理することです。

$(CORE_OBJS): build/%.o: src/%.c 
    $(CC) -c $(CFLAGS) $< -o [email protected] 
    $(CC) -MM -MF build/$*.d $< 
    @cp build/$*.d build/$*.P 
    @sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ 
      -e '/^$$/ d' -e 's/$$/ :/' < build/$*.P >> build/$*.d; 
    @rm build/$*.P 

A cruder方法が、ほとんど誰にでもできるように、ヘッダとソースのためのキャッチオールのルールで置くことです:

$(CORE_OBJS): build/%.o: src/%.c 
    $(CC) -c $(CFLAGS) $< -o [email protected] 
    $(CC) -MM -MF build/$*.d $< 

%.cc %.h: 

EDIT:

新しいコマンドを打破するには、次の

-MMオプションは、前処理またはコンパイルではなく、オブジェクトファイルに対してmakeルールを生成するようgccに指示します。デフォルトでは、前処理された出力を送信する場所にルールを送信します(通常は標準出力になります)。

-MFオプションは、-MMで使用され、出力ファイルを指定します。だから、-MM -MF build/$*.dは私たちが望むところにルールを置きます。

したがって、次の2つのコマンドは(ほとんど常に)等価です。両方は少し複雑になり、実際にはありませんので、

$(CC) -MM -MF build/$*.d $< 

    $(CC) -MM $< > build/$*.d 

(Iは、-I$(...)-MMDオプションを使用しての可能性を残してきました質問のポイント。

+0

よろしくお願いいたします。私は '$(CC)-MM -MFビルド/ $ * .d $ <'を '$(CC)-I $(INCDIR)-MM -MFビルド/ $ * .d $ < > build/$ *に変更しなければなりませんでした。私のシステムではMFフラグはサポートされていません。 MFの機能を置き換えるにはどうすればよいですか? –

+0

@MatthewMitchell、あなたはほとんどあなた自身で質問に答えましたが、私は私の答えを編集します。 – Beta

+0

パーフェクト、明確化のためにありがとう。 –

3

MAKECMDGOALSを使用できます。

ifeq (core,$(MAKECMDGOALS)) 
include $(CORE_DEPS) 
endif 

複数のターゲットの可能性があった場合はもちろん、ifneq (,$(findstring core,$(MAKECMDGOALS)))を使用することができます。

注:これは「すばやく汚れた」解決策です - これは一般的な習慣にしてはいけないことに私はベータに同意します(これは多くのメイクファイルでやった方が乱雑になります...)。

ジョン

+0

ありがとうございます。これは私が推測する一つの方法ですが、ベータの代替方法が最も理想的です。私はautomakeを使って同様の目標を達成する一つの方法だと思います。 –

1

私は丁度良い答えのためのガイドラインを破るのを助けることができません。

元の質問に対する私の答えは、私の意見では、ターゲットに依存するルールを含めることはできません。ターゲットは、ターゲットが考慮される前に処理されます。これはmake(私が推測する)の限界です。次に、良い点は、MAKECMDGOALSがありますが、これはmakeユーティリティ自体のハックだけではありませんか?

ベータ版からの回答は、妥当かつ正統なものですが、できる限り最善のものであっても、それをきれいにすることはできません。 makeが以前に特定のターゲットを処理しておらず、適切なビルド/ * .d依存ファイルがそこに存在しない場合は動作しません。

+2

あなたは間違っています。前にターゲットをビルドしておらず、対応する '.d'ファイルが存在しない場合、私が記述したアプローチ(私が発明しなかった)は完全にうまく動作します。 – Beta

関連する問題