Martel
Martel

Reputation: 2734

How to set as .DELETE_ON_ERROR a list of targets built by a static pattern in a Makefile

Having a Makefile like:

list_of_targets := $(PREFIX)/target1.xv    $(PREFIX)/target2.xv ...

$(list_of_targets): | dirs

$(PREFIX)/%.xv: %.sv $(src_dependencies)
    $(CMD) -o $@ $(params) $^

.PHONY: dirs
dirs:
    @mkdir -p $(PREFIX)

How can I make all the targets in list_of_targets .DELETE_ON_ERROR?

I have tried the following:

.DELETE_ON_ERROR: $(PREFIX)/%.xv
$(PREFIX)/%.xv: %.sv $(src_dependencies)
...

and

.DELETE_ON_ERROR: $(list_of_targets)
$(list_of_targets): ...

and

.DELETE_ON_ERROR: $(PREFIX)/target1.xv

This doesn't work either:

.DELETE_ON_ERROR: $(PREFIX)/target1.xv
$(PREFIX)/target1.xv: $(src_dependencies)
    $(CMD) -o $@ $(params) $^

Note: I have double checked that my build command returns 2 as error code. I have tried .DELETE_ON_ERROR with a simple test target and it works.

EDIT 2

I have tried adding a exit 1 to the pattern I'm executing and it does delete the file. It's like if Makefile could not detect the error returned by the compilation tool. But I'm sure it returns 2.

EDIT 1: actual Makefile (long)

Here there is a summary of my actual Makefile. It uses Icarus Verilog to build some fpga test benches.

PREFIX ?= ./build

SRC := ../src
SRCRV := $(SRC)/riscv
INC := ../include

TSRCRV := ./riscv
TESTUTILS := ./test-utils
RISCV_TEST_DIR := $(PREFIX)/riscv

CC := gcc
VV := iverilog

RANDOM := $(shell bash -c 'echo $$RANDOM')


tests := $(PREFIX)/mem_tb.xv                \
         $(PREFIX)/alu_logic_tb.xv          \
         $(PREFIX)/alu_add_tb.xv            \
         $(PREFIX)/alu_subs_tb.xv           \
         $(PREFIX)/alu_cmp_tb.xv

riscv_tests := $(RISCV_TEST_DIR)/lw_tb.xv           \
               $(RISCV_TEST_DIR)/sw_tb.xv           \
               $(RISCV_TEST_DIR)/or_tb.xv           \
               $(RISCV_TEST_DIR)/and_tb.xv          \
               $(RISCV_TEST_DIR)/sub_tb.xv          \
               $(RISCV_TEST_DIR)/xor_tb.xv          \
               $(RISCV_TEST_DIR)/sll_tb.xv          \
               $(RISCV_TEST_DIR)/srl_tb.xv          \
               $(RISCV_TEST_DIR)/sra_tb.xv          \
               $(RISCV_TEST_DIR)/beq_tb.xv          \
               $(RISCV_TEST_DIR)/bne_tb.xv          \
               $(RISCV_TEST_DIR)/blt_tb.xv          \
               $(RISCV_TEST_DIR)/bge_tb.xv          \
               $(RISCV_TEST_DIR)/bltu_tb.xv         \
               $(RISCV_TEST_DIR)/bgeu_tb.xv         \
               $(RISCV_TEST_DIR)/addi_tb.xv         \
               $(RISCV_TEST_DIR)/jal_tb.xv          \
               $(RISCV_TEST_DIR)/slt_tb.xv          \
               $(RISCV_TEST_DIR)/sltu_tb.xv         \
               $(RISCV_TEST_DIR)/jalr_tb.xv         \
               $(RISCV_TEST_DIR)/auipc_tb.xv        \
               $(RISCV_TEST_DIR)/datapath_tb.xv     \
               $(RISCV_TEST_DIR)/controller_tb.xv

tests_waves := $(addsuffix .vcd,$(tests))

riscv_tests_waves := $(addsuffix .vcd,$(riscv_tests))


common_src := $(SRC)/alu.sv     \
              $(SRC)/mem.sv     \
              $(SRC)/utils.sv

riscv_src :=  $(SRCRV)/datapath.sv          \
              $(SRCRV)/riscv_single_top.sv  \
              $(SRCRV)/controller.sv


#
# Build al tests and execute them without generating wave dumps
#
.DELETE_ON_ERROR:
test: $(tests) $(riscv_tests)
    $(foreach test,$^,vvp $(test) -none;)

wavedumps: $(tests_waves) $(riscv_tests_waves)

all: test wavedumps

$(tests): | dirs

$(riscv_tests): | dirs

$(wavedumps): | dirs


$(PREFIX)/%.xv: %.sv $(common_src)
    $(VV) -o $@ -g2012 -DSEED=$(RANDOM) -I$(INC) -Wall -Wno-timescale -DVCD="\"[email protected]\"" $^

$(RISCV_TEST_DIR)/%.xv: $(TSRCRV)/%.sv $(common_src) $(riscv_src)
    $(VV) -o $@ -g2012 -DSEED=$(RANDOM) -I$(INC) -Wall -Wno-timescale -DVCD="\"[email protected]\"" $^

$(PREFIX)/%.xv.vcd: $(PREFIX)/%.xv
    $(VVP) $<

$(RISCV_TEST_DIR)/%.xv.vcd: $(RISCV_TEST_DIR)/%.xv
    $(VVP) $<

$(PREFIX)/2scomp: $(TESTUTILS)/2scomp.c dirs
    $(CC) -o $@ -std=c11 $<


.PHONY: clean
clean:
    @rm -rf $(PREFIX)/*

.PHONY: dirs
dirs:
    @mkdir -p $(PREFIX)
    @mkdir -p $(RISCV_TEST_DIR)

Let's say I execute:

make build/riscv/addi_tb.xv

The above command is successful. Then I modify riscv/addi_tb.sv (dependency of the above target) to generate an error on purpose. I get this message:

iverilog -o build/riscv/addi_tb.xv -g2012 -DSEED=5478 -I../include -Wall -Wno-timescale -DVCD="\"build/riscv/addi_tb.xv.vcd\"" riscv/addi_tb.sv ../src/alu.sv ../src/mem.sv ../src/utils.sv ../src/riscv/datapath.sv ../src/riscv/riscv_single_top.sv ../src/riscv/controller.sv
riscv/addi_tb.sv:23: syntax error
riscv/addi_tb.sv:22: error: Invalid module instantiation
make: *** [Makefile:82: build/riscv/addi_tb.xv] Error 2

However, the above doesn't delete build/riscv/addi_tb.xv, trying it with any of the combinations exposed above. I have tried adding .DELETE_ON_ERROR at the beginning of the file as well.

Upvotes: 0

Views: 158

Answers (1)

MadScientist
MadScientist

Reputation: 101041

The .DELETE_ON_ERROR: special target acts like a standalone boolean flag for the entire make process and all targets in it. It's not possible to apply it to a single target or subset of targets. The docs say:

If .DELETE_ON_ERROR is mentioned as a target anywhere in the makefile, then make will delete the target of a rule if it has changed and its recipe exits with a nonzero exit status, just as it does when it receives a signal. See Errors in Recipes.

It could be clearer, I suppose, but that's what it says.

Prerequisites are ignored, so I can't explain whatever behavior you are seeing, which you don't actually describe clearly.

Here's a test:

$ cat Makefile
.DELETE_ON_ERROR:
foo:
        touch $@
        exit 1

$ make
touch foo
exit 1
make: *** [Makefile:4: foo] Error 1
make: *** Deleting file 'foo'

What part of this doesn't work for you?

Upvotes: 1

Related Questions