From 3b495bab794a07011ccd0285c12bf33300487826 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 12 Mar 2022 14:11:34 -0600 Subject: [PATCH] Fixed spurious CI failure caused by multiple writers to .o files GCC is a bit frustrating here, it really wants to generate every file in a single command, which _is_ more efficient if our build system could leverage this. But -fcallgraph-info is a rather novel flag, so we can't really rely on it for generally compiling and testing littlefs. The multi-file output gets in the way when we want an explicitly separate rule for callgraph-info generation. We can't generate the callgraph-info without generating the objects files. This becomes a surprsing issue when parallel building (make -j) is used! Suddenly we might end up with both the .o and .ci rules writing to .o files, which creates a really difficult to track down issue of corrupted .o files. The temporary solution is to use an order-only prerequisite. This still ends up building the .o files twice, but it's an acceptable tradeoff for not requiring the -fcallgraph-info for all builds. --- Makefile | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index ca0254d..05142cd 100644 --- a/Makefile +++ b/Makefile @@ -124,16 +124,8 @@ coverage: ./scripts/coverage.py $(BUILDDIR)tests/*.toml.info -s $(COVERAGEFLAGS) .PHONY: summary -summary: $(OBJ) $(CGI) - $(strip \ - ./scripts/code.py $(OBJ) -q -o - $(CODEFLAGS) \ - | ./scripts/data.py $(OBJ) -q -m - -o - $(DATAFLAGS) \ - | ./scripts/stack.py $(CGI) -q -m - -o - $(STACKFLAGS) \ - | ./scripts/structs.py $(OBJ) -q -m - -o - $(STRUCTFLAGS) \ - $(if $(COVERAGE),\ - | ./scripts/coverage.py $(BUILDDIR)tests/*.toml.info \ - -q -m - -o - $(COVERAGEFLAGS)) \ - | ./scripts/summary.py -Y $(SUMMARYFLAGS)) +summary: $(BUILDDIR)lfs.csv + ./scripts/summary.py -Y $^ $(SUMMARYFLAGS) # rules @@ -147,15 +139,13 @@ $(BUILDDIR)lfs.a: $(OBJ) $(AR) rcs $@ $^ $(BUILDDIR)lfs.csv: $(OBJ) $(CGI) - $(strip \ - ./scripts/code.py $(OBJ) -q -o - $(CODEFLAGS) \ - | ./scripts/data.py $(OBJ) -q -m - -o - $(DATAFLAGS) \ - | ./scripts/stack.py $(CGI) -q -m - -o - $(STACKFLAGS) \ - | ./scripts/structs.py $(OBJ) -q -m - -o - $(STRUCTFLAGS) \ - $(if $(COVERAGE),\ - | ./scripts/coverage.py $(BUILDDIR)tests/*.toml.info \ - -q -m - -o - $(COVERAGEFLAGS)) \ - > $@) + ./scripts/code.py $(OBJ) -q $(CODEFLAGS) -o $@ + ./scripts/data.py $(OBJ) -q -m $@ $(DATAFLAGS) -o $@ + ./scripts/stack.py $(CGI) -q -m $@ $(STACKFLAGS) -o $@ + ./scripts/structs.py $(OBJ) -q -m $@ $(STRUCTSFLAGS) -o $@ + $(if $(COVERAGE),\ + ./scripts/coverage.py $(BUILDDIR)tests/*.toml.info \ + -q -m $@ $(COVERAGEFLAGS) -o $@) $(BUILDDIR)%.o: %.c $(CC) -c -MMD $(CFLAGS) $< -o $@ @@ -163,8 +153,12 @@ $(BUILDDIR)%.o: %.c $(BUILDDIR)%.s: %.c $(CC) -S $(CFLAGS) $< -o $@ -$(BUILDDIR)%.ci: %.c - $(CC) -c -MMD -fcallgraph-info=su $(CFLAGS) $< -o $(@:.ci=.o) +# gcc depends on the output file for intermediate file names, so +# we can't omit to .o output. We also need to serialize with the +# normal .o rule because otherwise we can end up with multiprocess +# problems with two instances of gcc modifying the same .o +$(BUILDDIR)%.ci: %.c | $(BUILDDIR)%.o + $(CC) -c -MMD -fcallgraph-info=su $(CFLAGS) $< -o $| # clean everything .PHONY: clean