我試圖在我的二進制檔案中整合git describe的輸出:
// version.c.in
#include <stdio.h>
const char version[] __attribute__((used)) = "##BUILDVERSION##:@BUILDVERSION@" 。
int main() {
printf("%s
", 版本)。)
回傳0。
}
Make會生成一個version.c出來:
//Makefile
SOURCEFILES = $(通配符 *.c) version.c
PROGRAMS = $(addprefix build/,$(SOURCEFILES:.c=.out))
.PHONY: version.c
所有:$(PROGRAMS)
清潔。
rm -fR build
build/%.out:build/%.o Makefile
mkdir -p build
gcc -g $< -o $@
build/%.o: %.c 制作檔案
mkdir -p build
gcc -Wall -Werror -g -c $< -o $@
version.c: version.c.in 制作檔案
cp $< $@_temp
sed -i "s/@BUILDVERSION@/$$(git describe --always --dirty=-dirty)/g" $@_temp
@cmp -s $@_temp $@ || mv $@_temp $@
rm -f $@_temp
我想實作只有當git describe的輸出發生變化時才觸發重建。在我目前的方法中,聯結器步驟總是被呼叫,盡管version.c甚至沒有變化。但它是.PHONY,這可能會導致所有依賴它的目標的重建。如果我讓目標不再是 .PHONY,我就會錯過一次重建,例如當我提交或添加一個標簽時。
我也無法在 .git/中找到一個合適的檔案作為 version.c 的可能依賴項。
有什么方法可以解決這個問題嗎?
uj5u.com熱心網友回復:
你在
build目錄下存盤物件檔案,所以生成的version.c也應該放在那里。你可以在
build目錄下將當前提交的哈希值存盤到一個臨時檔案中,并使build/version.c依賴于它。目標
all和clean必須被標記為.PHONY。Makefile中的注釋從#開始。build/version.c在每次洗掉build/version.o時都會被重新構建。為了避免這種洗掉,可以使用Makefile無緣無故地洗掉物件檔案的解決方案
。
因此,一般來說,可能的解決方案可以是這樣的:
uj5u.com熱心網友回復: 但它是.PHONY,這可能導致所有依賴它的目標的重建。 這是正確的:一個 由于 這里有一個完整的例子: 這即使在舊版本的gmake中也應該是可行的;新版本的gmake有 (編輯補充說明:
標籤: 下一篇:將sql中的資料格式化為單行# Makefile
# Makefile
SOURCEFILES = $(通配符 *.c.in)
OBJS = $(addprefix build/,$(SOURCEFILES:.c.in=.o))
程式 = $(addprefix build/,$(SOURCEFILES:.c.in=.out))
.PHONY: all
所有:$(PROGRAMS)
.PHONY: clean
清理。
rm -fR build
build/%.out:build/%.o Makefile
mkdir -p build
gcc -g $< -o $@
build/%.o: %.c build/%.c Makeefile
mkdir -p build
gcc -Wall -Werror -g -c $< -o $@
# .次要的: build/version.o
.PRECIOUS: build/version.o
build/current_hash。
mkdir -p build
git log --pretty=%h > [email protected]
@cmp -s [email protected] $@ || mv [email protected] $@
build/version.c: version.c.in Makefile build/current_hash
cp $< $@_temp
sed -i "s/@BUILDVERSION@/$$(git describe --always --dirty=-dirty)/g" $@_temp
@cmp -s $@_temp $@ || mv $@_temp $@
rm -f $@_temp
.PHONY目標總是被重建,這意味著任何依賴于它的東西也總是被重建。
make 的檔案和時間戳方向,您需要的是一個命令,當且僅當該檔案的內容將發生變化時,更新該檔案的時間戳。 然后你可以讓輸出O依賴于輸入檔案I,其時間戳取決于git describe輸出。
version=$(shell git describe --always --dirty=-dirty)
$(shell echo ${version} > version.tmp & &
{ cmp -s version.tmp version.txt || cp version.tmp version.txt; } &&
rm -f version.tmp)
all: version.o
version.c: version.c.in version.txt
sed "s:@BUILDVERSION@:${version}:" < [email protected] > $@
version.o: version.c
$(file)函式,可以用來完成大部分作業。 也就是說,你將用$(file)讀取version.txt的內容,然后只有當這些內容與git describe輸出的內容不匹配時,才向version.txt寫入,所有這些都在讀取Makefile的程序中完成(正如這里的情況:注意$(shell)的呼叫如何在早期發生)。
所有在這里確實應該被標記為.PHONY,因為
Andrey Starodubtsev 在他的回答中提到的。 我顯然沒有理會。 是否將所有輸出隔離到build/中由你決定。)
