On Thursday, July 11th, 2024 at 7:21 PM, Eduard Zingerman <eddyz87@xxxxxxxxx> wrote: [...] > After some investigation it turned out that behaviour is specific to LLVM. > Under certain not yet clear conditions clang writes .d file after writing .o file. > For example: > > {llvm} 19:15:59 bpf$ rm ringbuf.test.o; make `pwd`/ringbuf.test.o; ls -l --time-style=full-iso `pwd`/ringbuf.test.{o,d} > TEST-OBJ [test_progs] ringbuf.test.o > -rw-rw-r-- 1 eddy eddy 1947 2024-07-11 19:16:01.059016929 -0700 /home/eddy/work/bpf-next/tools/testing/selftests/bpf/ringbuf.test.d > -rw-rw-r-- 1 eddy eddy 160544 2024-07-11 19:16:01.055016909 -0700 /home/eddy/work/bpf-next/tools/testing/selftests/bpf/ringbuf.test.o > > Note that ringbuf.test.d is newer than ringbuf.test.o. > This happens on each 10 or 20 run of the command. > Such behaviour clearly defies the reason for dependency files generation. > > The decision for now is to avoid specifying .d files as direct dependencies > of the .o files and use order-only dependencies instead. > The make feature for reloading included makefiles would take care > of correctly re-specifying dependencies. Eduard, thank you for testing. I was able to reproduce the problem you've noticed using LLVM 19. As far as I understand, direct dependency is not reliable here because it implicitly expects %.d files to always be older than %.o files. There are two possible situations when a given %.test.o must be built. If %.test.d does not exist, then the include will be empty. However, because there is a target for %.test.d and a dependency on it, all the %.bpf.o and skels will be built. And by the time CC %.test.o happens, all its dependencies are ready. This is true for %.test.d both as direct and order only dependency. If %.test.d exists, then make included it and there is an additional target for a particular %.test.o with concrete dependencies, which are built as necessary. And the explicit %.test.d doesn't trigger, because the file is up-to-date (which is exactly what we want). In the second case, if %.test.d prerequisite is not order only, and %.test.d sometimes happens to be newer than %.test.o (this is the case for clang, but not for gcc), make would run CC again, which may update %.d again and create a loop. I think making %.test.d an order only prerequisite is the right fix here, because we clearly can not expect that all compiler versions will output %.d before %.o (even though it makes sense). I will send v2 of the patch shortly.