我一直在開發一個Makefile來自動化C語言中的單元測驗。主要目標是對于任何一個遵循源代碼和測驗目錄結構的專案,make編譯功能,make test編譯并運行測驗。
盡管make命令可以正常作業,但make test卻不能。在下面的配置中,test的依賴關系呼叫%.exe目標,而不是test_%.exe。
我如何對任何測驗目標進行成功的呼叫,只要它以 "test_"開頭?
我試著做了一個通配符,但是沒有成功。這可能是由于我缺乏知識,但我希望能在這里找到一些幫助。
CC := gcc
CFLAGS := -Wall -Werror
CSYNTAX := -fsyntax-only -Wall
SRC = $(通配符 ./src/*.c)
DEP = $(SRC:.c=.exe)
SRCTEST = ./test/UnitTests
PATHI = ./test/UnitTests/includes
PATHU = ./test/UnitTests/Unity
INC := ./src/includes
TEST = test_$.exe
# 編譯主程式
全部:$(DEP)
語法。*.c $(SRC) $(SRCTEST)/test_*.c
$(cc) $(csyntax) $^ $(cflags) -i$(inc) -i $(pathi)
%.exe。 *.c $(SRC)
$(CC) $^ $(CFLAGS) -I$(INC) -o $@
./$@
# 編譯和執行測驗
test: $(SRCTEST)/test_*.exe
test_%.exe: $(SRCTEST)/test_%.c $(SRC) $(PATHU)/unity.c
$(CC) $(CFLAGS) $^ -I $(INC) -I $(PATHI) -I $(PATHU) -o $@
./$@
清潔。
del *.exe
我在MinGW 8.1.0上使用GNU gcc,但也可以使用Ubunutu 7.5.0的gcc(replit.com)
uj5u.com熱心網友回復:這里有一堆微妙的問題。
首先,當你的測驗目標依賴于通配符時,它的決議并不直觀,因為這并沒有被make直接展開。如果一個匹配的檔案不存在,make將試圖找到其中有字面意義的*規則:
$ cat Makefile
SRC = $(通配符 ./src/*.c)
SRCTEST = ./test/UnitTests
%.exe: $(SRC)
echo 從$^制作$@
測驗:$(SRCTEST)/test_*.exe
test_%.exe: $(SRCTEST)/test_%.c $(SRC)
echo 從$^制作$@
$ make test -dr
...
考慮到目標檔案'test'。
尋找'test'的隱式規則。
沒有發現'test'的隱式規則。
考慮目標檔案'test/UnitTests/test_*.exe'。
檔案'test/UnitTests/test_*.exe'不存在。
尋找'test/UnitTests/test_*.exe'的隱含規則。
嘗試帶有 "*"的模式規則。
嘗試隱式先決條件 'test/UnitTests/test/UnitTests/test_*.c'。
正在嘗試帶有 "test_*"字樣的模式規則。
嘗試規則前提條件'src/foo.c'。
發現'test/UnitTests/test_*.exe'的隱含規則。
正在考慮目標檔案'src/foo.c'。
為'src/foo.c'尋找一條隱式規則。
沒有發現'src/foo.c'的隱式規則。
完成了目標檔案'src/foo.c'的先決條件。
不需要重新制作目標檔案'src/foo.c'。
完成了目標檔案'test/UnitTests/test_*.exe'的先決條件。
必須重新制作目標檔案'test/UnitTests/test_*.exe'。
echo 從 src/foo.c 制作 test/UnitTests/test_*.exe。
...
假設你不想創建一個名為test_*.exe的檔案,測驗二進制檔案應該有預期的名字,即:
$ cat Makefile
SRC = $(通配符 ./src/*.c)
SRCTEST = ./test/UnitTests
%.exe: $(SRC)
echo 從$^制作$@
.PHONY:測驗
test: $(patsubst %.c,%.exe,$(通配符 $(SRCTEST)/test_*.c))
test_%.exe: $(SRCTEST)/test_%.c $(SRC)
echo 從$^制作$@
這將通過將測驗源檔案的后綴從.c轉換為.exe來匯出測驗二進制名稱。(作為附帶說明,目標檔案本身應該是假的,因為它不會創建一個真正的檔案)
用給定的檔案結構:
$ ls -R
.:
Makefile src test
./src:
foo.c
./test:
單元測驗
./test/UnitTests:
test_foo.c
這導致了試圖創建test_foo.exe而不是test_*.exe:
$ make test -dr
...
考慮到目標檔案'test'。
檔案'test'不存在。
考慮目標檔案'test/UnitTests/test_foo.exe'。
檔案'test/UnitTests/test_foo.exe'不存在。
尋找for一個隱式規則for 'test/UnitTests/test_foo.exe'。
正在嘗試帶有'foo'的模式規則。
嘗試隱式先決條件 'test/UnitTests/test/UnitTests/test_foo.c'。
試圖以'test_foo'的模式規則。
嘗試規則的前提條件'src/foo.c'。
發現一個隱式規則for 'test/UnitTests/test_foo.exe'。
考慮到目標檔案'src/foo.c'。
尋找for一個隱式規則for 'src/foo.c'。
沒有找到隱含規則 for 'src/foo.c'。
完成了目標檔案'src/foo.c'的先決條件。
不需要重新制作目標檔案'src/foo.c'。
完成了目標檔案'test/UnitTests/test_foo.exe'的先決條件。
必須重新制作目標檔案'test/UnitTests/test_foo.exe'。
echo 從 src/foo.c 制作 test/UnitTests/test_foo.exe。
...
盡管如此,它并沒有遵循測驗規則,而是遵循一般的源規則。為什么會這樣呢?嗯,這是因為在匹配莖(%部分)時,目錄是prepended到搜索的目標中。你可以在上面的輸出中看到,當make在考慮目標檔案'test/UnitTests/test_foo.exe'時,它將尋找一個檔案test/UnitTests/test/UnitTests/test_foo。 c,它來自$(SRCTEST)/test_%.c,明確提到了$(SRCTEST),同時它也被自動從莖中預輸入。當然,這樣的檔案并不存在,因此該規則被拒絕。
正確的修復方法很簡單:
$ cat Makefile
SRC = $(通配符 ./src/*.c)
SRCTEST = ./test/UnitTests
%.exe: $(SRC)
echo 從$^制作$@
.PHONY:測驗
test: $(patsubst %.c,%.exe,$(通配符$(SRCTEST)/test_*.c))
test_%.exe: test_%.c $(SRC)
echo 從$^制作$@
$ make -s test
從test/UnitTests/test_foo.c src/foo.c制作test/UnitTests/test_foo.exe。
注意,現在它已經按照預期從測驗源構建了測驗二進制檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/310312.html
標籤:
