2012-11-17 35 views
14

我想僅將include指令用於特定目標。當不需要目標時,我不想運行其他makefile,因爲這意味着makefile不必要地生成。如何在特定目標的makefile中使用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

你*可以*做到這一點,但你*不應該*。它違背Make的粒子,有更好的方法。你想快速簡單的方法,還是先進的和強大的? – Beta

+1

那我可以問一下這個問題:什麼是「製造粒」和這些「更好的方法」?只要它很容易維護。這就是我想要的。我不想手動添加標題先決條件。 –

回答

15

提出的,是不是程序語言,所以把它當作一個違背了糧食;你的makefile文件將難以擴展,並且會導致微妙的錯誤。

Tom Tromey有一個better way,它乾淨,高效且可擴展。訣竅是認識到你可以在與目標文件相同的步驟中構建依賴文件。依賴關係僅告訴Make什麼時候該對象將被重建;當您第一次構建對象時,您不需要它們,因爲Make知道該對象必須被構建。如果依賴關係發生變化,那隻能是因爲源或舊依賴關係中的某些內容發生了變化,所以Make知道該對象必須被重建。 (這不是顯而易見的,因此它可能需要一些思維。)

​​

還有一個障礙:如果你更改代碼,以便去除依賴 - 也刪除文件 - 你贏了」不能重建,因爲舊的依賴列表仍然會要求一個無法找到的文件。的複雜的解決方案是處理相關性文件,以使每個先決條件(例如,報頭)在自己的權利的目標,沒有命令,以便它可以假定在需要時重建:

$(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 

甲較粗略的方法,但幾乎萬無一失,是擺在包羅萬象的規則,標題和來源:

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

%.cc %.h: 

編輯:

打破了這種新的命令:

-MM選項告訴gcc爲目標文件生成make規則,而不是預處理或編譯。默認是將規則發送到將發送預處理輸出的地方,通常是stdout。

-MM一起使用的-MF選項指定輸出文件。所以-MM -MF build/$*.d將把規則放在我們想要的地方。

所以下面的命令是(幾乎總是)相當於:

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

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

(我已經離開了-I$(...)並使用-MMD選項,因爲兩者會有點複雜的可能性,是不是真的問題的關鍵。)

+0

好的,謝謝你。我不得不將'$(CC)-MM -MF build/$ * .d $ <'改成'$(CC)-I $(INCDIR)-MM -MF build/$ * .d $ < > build/$ * .d'來讓它工作,但在我的系統上不支持MF標誌。我應該怎麼做來取代MF的功能? –

+0

@MatthewMitchell,你幾乎自己回答了這個問題,但我會編輯我的答案。 – Beta

+0

完美,謝謝澄清。 –

3

您可以使用MAKECMDGOALS。

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

您當然可以,使用ifneq (,$(findstring core,$(MAKECMDGOALS)))如果有一個以上的目標的可能性。

注意:這是一個'快速和骯髒'的解決方案 - 我同意測試版,你不應該這樣做是一種常見的做法(如果你在很多makefile文件中做這個,這可能會變得麻煩......)。

約翰

+0

謝謝。這是我猜測的一種方式,但Beta的替代方法看起來似乎是最理想的。我想用automake是實現類似目標的一種方法。 –

1

我不禁打破了什麼是一個很好的答案的指導方針。

我對原始問題的回答是在我看來,不,你不能包括依賴於目標的規則 - 所有規則都在目標被考慮之前處理。這是一個限制(我猜)。再好的一點是,有MAKECMDGOALS,但這不僅僅是make實用程序本身的破解?

從Beta的答案是合理的和正統的,但即使它是最好的,你也不能稱之爲乾淨。如果make之前沒有處理特定的目標,並且相應的build/*。d依賴文件不在那裏,它將不起作用。

+2

你錯了。我描述的方法(我沒有發明)如果Make之前沒有構建目標並且相應的'.d'文件不存在,那麼這種方法非常完美。 – Beta