簡體   English   中英

Makefile依賴項修改檢測

[英]Makefile dependency modification detection

我正在編寫一個用於處理構建單元ONE和TWO->構建單元LIB的依賴關系的makefile。

“構建單元”是指包含目錄src,lib,include和bin的目錄,以及用於在src中編譯源代碼的makefile。 庫位於“ lib”中,而庫頭文件位於“ include”中。 編譯后的二進制文件放在“ bin”中。 構建單元接受“ make”,“ make all”,“ make lint”和“ make clean”。

當對LIB中的頭文件進行更改時,此makefile可以檢測到該文件並在編譯前重新編譯+安裝(將.a + .h文件復制到ONE和2)新版本的LIB。

.PHONY: ONE TWO CLEAN LINT

ALL: ONE TWO

%.a %.h:
    @echo ---------- Compiling LIB ----------
    @cd LIB && gmake.exe LIB

LIB_HEADERS := $(wildcard LIB/src/*.h)

ONE: ONE/lib/libLIB.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

TWO: TWO/lib/libLIB.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

CLEAN LINT:
    @cd ONE && gmake.exe $@
    @cd TWO && gmake.exe $@
    @cd LIB && gmake.exe $@

(假設LIB的makefile處理復制到一個和兩個)

  1. 當我更改LIB / src中的頭文件之一時,make為什么不運行規則“%.a%.h:”?
  2. 如何將一個和兩個概括為一個規則? 我想這樣做(但是至少不能以這種方式在依賴項中使用目標):

     ONE TWO: $@/lib/libLIB.a $(subst LIB/src/,$@/include/,$(LIB_HEADERS)) @echo ---------- Compiling $@ ---------- @cd $@ && gmake.exe 

更新:

我通過退后一步,繪制有向非循環圖並考慮單個文件而不是某個類型的所有文件來找到解決方案。

為了完整性,這是(不是很優雅的)解決方案:

.PHONY: ONE TWO CLEAN LINT

ALL: ONE TWO

LIB_HEADERS := $(sort $(subst name.h,,$(wildcard LIB/src/*.h)))

# ------------------------------------------------------------
ONE/include/%.h: LIB/src/%.h
    @echo Copying $< to $@
    @mkdir ONE\\include 2> NUL || :)
    @copy $(subst /,\,$<) ONE\\include\\ 1> NUL

TWO/include/%.h: LIB/src/%.h
    @echo Copying $< to $@
    @mkdir TWO\\include 2> NUL || :)
    @copy $(subst /,\,$<) TWO\\include\\ 1> NUL
# ------------------------------------------------------------
ONE/lib/liblib.a: LIB/bin/liblib.a
    @echo Copying $< to $@
    @mkdir ONE\\lib 2> NUL || :)
    @copy $(subst /,\,$<) ONE\\lib\\ 1> NUL

TWO/lib/liblib.a: LIB/bin/liblib.a
    @echo Copying $< to $@
    @mkdir TWO\\lib 2> NUL || :)
# Windows-equivalent of touch (discarding any output to stdout):
    @copy $(subst /,\,$<) TWO\\lib\\ 1> NUL
# ------------------------------------------------------------
LIB/bin/liblib.a: $(LIB_HEADERS) $(wildcard LIB/src/*.cpp)
    @echo ---------- Looking for changes to liblib ----------
    @cd LIB && gmake.exe LIB
    @copy /b $(subst /,\,$@) +,, 1> NUL || :)
# ------------------------------------------------------------
ONE: ONE/lib/liblib.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling ONE ----------
    @cd ONE && gmake.exe

TWO: TWO/lib/liblib.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling TWO ----------
    @cd TWO && gmake.exe
# ------------------------------------------------------------
CLEAN LINT:
    @cd ONE && gmake.exe $@
    @cd TWO && gmake.exe $@
    @cd LIB && gmake.exe $@

我非常歡迎有關如何進一步概括一和二的技巧。

對於問題1:也許您需要向上移動LIB_HEADERS定義並將規則更改為
%.a%.h:$(LIB_HEADERS)嗎?

很抱歉不得不告訴您這一點,但是您的構建系統是一個怪物。 您正試圖通過大量使用遞歸Make來進行復雜的依賴關系處理; 遞歸Make有其用途,但其缺點之一是它使Make的固有能力無法處理依賴項。 還有其他問題表明該系統的作者並沒有真正理解Make的工作原理或良好的makefile的外觀。

當您在LIB/src/更改頭文件時,Make不運行此%.a %.h:規則的原因是該規則沒有依賴性,並且該makefile中的任何內容都不依賴於不存在的頭文件。 如果這對您沒有意義,則您不了解Make規則的工作原理。

這些規則:

ONE: ONE/lib/libLIB.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

TWO: TWO/lib/libLIB.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

可以組合為一個規則:

ONE TWO: % : %/lib/libLIB.a $(addprefix %/include/,$(notdir $(LIB_HEADERS)))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

但是不要這樣做。 相反,請消除ONE/include/TWO/include/ ,因為它們只會帶來麻煩。 那么這里的規則可以是

ONE TWO: % : %/lib/libLIB.a $(LIB_HEADERS)
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

ONE/TWO/的makefile可以參考LIB/src/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM