web-dev-qa-db-ja.com

特定のターゲットのメイクファイルでincludeディレクティブを使用する方法

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 $@; \
    $(CC) -I$(INCDIR) -MM $< -MT '$(@:.d=.o) $@' > $@

# 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 $@

# 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 $@

#Clean

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

わかりますので、「crypto」の「.d」ファイルを含める必要はありませんが、「core」(デフォルトの目標)を含める必要があります。

助けてくれてありがとう.

17

Makeは手続き型言語ではないので、穀物に反するものとして扱う。メイクファイルのスケーリングは難しく、微妙なバグにつながる可能性があります。

クリーンで効率的でスケーラブルな より良い方法 がTom Tromeyによって提供されています。秘訣は、オブジェクトファイルと同じ手順で依存関係ファイルを構築できることを理解することです。依存関係は、オブジェクトが再構築される時期をMakeに通知するだけです。 Makeはオブジェクトをビルドする必要があることを知っているので、最初にオブジェクトをビルドするときには必要ありません。そして、依存関係が変更された場合、それはソース内の何かまたは古い依存関係が変更されたことが原因である可能性があるため、Makeはオブジェクトを再構築する必要があることを認識しています。 (これは明白ではないので、少し熟考する必要があります。)

_$(CORE_OBJS): build/%.o: src/%.c
    $(CC) -c $(CFLAGS) $< -o $@
    $(CC) -MM -MF build/$*.d $<

-include build/*.d
_

もう1つ問題があります。依存関係を削除するようにコードを変更し、さらにそのファイルを削除すると、古い依存関係リストはまだ見つからないファイルを要求するため、再構築できません。 。洗練されたソリューションは、依存関係ファイルを処理して、各前提条件(ヘッダーなど)をコマンドなしで独自にターゲットにすることで、必要なときに再構築されると想定できるようにします。

_$(CORE_OBJS): build/%.o: src/%.c
    $(CC) -c $(CFLAGS) $< -o $@
    $(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
_

より大まかな方法​​ですが、ほぼ間違いなく、ヘッダーとソースのすべての規則を組み込むことです。

_$(CORE_OBJS): build/%.o: src/%.c
    $(CC) -c $(CFLAGS) $< -o $@
    $(CC) -MM -MF build/$*.d $<

%.cc %.h:
_

編集:

新しいコマンドを分解するには:

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

_-MF_と共に使用される_-MM_オプションは、出力ファイルを指定します。したがって、_-MM -MF build/$*.d_は、必要な場所にルールを配置します。

したがって、次の2つのコマンドは(ほとんどの場合)同等です。

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

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

-I$(...)と_-MMD_オプションを使用する可能性は省略しました。どちらも少し複雑になり、問題の本質ではないためです。)

17
Beta

MAKECMDGOALSを使用できます。

_ifeq (core,$(MAKECMDGOALS))
include $(CORE_DEPS)
endif
_

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

注:これは「迅速で汚い」ソリューションです-これを一般的な方法にしてはいけないというベータ版に同意します(多くのメイクファイルでこれを行った場合、これは面倒になる可能性があります...)。

ジョン

3
John

良い答えは何であるかについてのガイドラインを破るしかない。

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

ベータ版からの答えは合理的かつ正統的で十分ですが、それが実行できる最高のものであっても、それをクリーンと呼ぶことはできません。 makeが以前に特定のターゲットを処理しておらず、適切なbuild/*。d依存関係ファイルがそこにない場合は、機能しません。

1
Robert Durkacz