All of lore.kernel.org
 help / color / mirror / Atom feed
From: "SZEDER Gábor" <szeder.dev@gmail.com>
To: Jeff King <peff@peff.net>
Cc: git@vger.kernel.org, Phillip Wood <phillip.wood@dunelm.org.uk>
Subject: Re: [PATCH 1/2] Makefile: use order-only prereq for UNIT_TEST_BIN
Date: Mon, 29 Jan 2024 21:22:01 +0100	[thread overview]
Message-ID: <20240129202201.GA9612@szeder.dev> (raw)
In-Reply-To: <20240129031816.GA2433899@coredump.intra.peff.net>

On Sun, Jan 28, 2024 at 10:18:16PM -0500, Jeff King wrote:
> We build the UNIT_TEST_BIN directory (t/unit-tests/bin) on the fly with
> "mkdir -p". And so the recipe for UNIT_TEST_PROGS, which put their
> output in that directory, depend on UNIT_TEST_BIN to make sure it's
> there.
> 
> But using a normal dependency leads to weird outcomes, because the
> timestamp of the directory is important. For example, try this:
> 
>   $ make
>   [...builds everything...]
> 
>   [now re-build one unit test]
>   $ touch t/unit-tests/t-ctype.c
>   $ make
>       SUBDIR templates
>       CC t/unit-tests/t-ctype.o
>       LINK t/unit-tests/bin/t-ctype
> 
> So far so good. Now running make again should build nothing. But it
> doesn't!
> 
>   $ make
>       SUBDIR templates
>       LINK t/unit-tests/bin/t-basic
>       LINK t/unit-tests/bin/t-mem-pool
>       LINK t/unit-tests/bin/t-strbuf
> 
> Er, what? Let's rebuild again:
> 
>   $ make
>       SUBDIR templates
>       LINK t/unit-tests/bin/t-ctype
> 
> Weird. And now we ping-pong back and forth forever:
> 
>   $ make
>       SUBDIR templates
>       LINK t/unit-tests/bin/t-basic
>       LINK t/unit-tests/bin/t-mem-pool
>       LINK t/unit-tests/bin/t-strbuf
>   $ make
>       SUBDIR templates
>       LINK t/unit-tests/bin/t-ctype
> 
> What happens is that writing t/unit-tests/bin/t-ctype updates the mtime
> of the directory t/unit-tests/bin. And then on the next invocation of
> make, all of those other tests are now older and so get rebuilt. And
> back and forth forever.
> 
> We can fix this by using an order-only prereq. This is a GNU-ism that
> tells make to only care that the dependency exists at all, and to ignore
> its mtime. It was designed for exactly this sort of situation (the
> documentation example even uses "mkdir").
> 
> We already rely on GNU make, so that's not a problem. This particular
> feature was added in GNU make 3.80, released in October 2002. This is
> obviously quite old by date, but it's also worth thinking about macOS,
> as Apple stopped updating packages that switched to GPLv3 tools. In this
> their dev tools ship GNU make 3.81, which is recent enough.
> 
> If it is a problem, there are two alternatives:
> 
>   - we can just "mkdir -p" in the recipe to build the individual
>     binaries. This will mean some redundant "mkdir" calls, but only when
>     actually invoking the compiler.
> 
>   - we could stop making the directory on the fly, and just add it with
>     a .gitignore of "*". This would work fine, but might be awkward when
>     moving back and forth in history.

A third alternative is to use $(call mkdir_p_parent_template) in the
recipe and get rid of the thus unnecessary UNIT_TEST_BIN dependency
and target.  It will only run mkdir when needed, and it's a well
established pattern in our Makefile, so you won't have to spend a
paragraph or two arguing about potential problems with GNU-isms :)

On a related note, 'make clean' doesn't remove this 't/unit-tests/bin'
directory.

> Signed-off-by: Jeff King <peff@peff.net>
> ---
> I may be overly paranoid about the ".gitignore" strategy. I feel like
> I've been bitten by this in the past by things switching from source to
> build (I think with git-remote-testgit). But that's an actual built
> file. Git would probably be OK with the "bin/" directory coming and
> going as a tracked entity, because the index really only cares about
> the file "bin/.gitignore". Still, this make fix was easy enough.
> 
>  Makefile | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Makefile b/Makefile
> index 1a62e48759..958f4cd0bf 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -3866,7 +3866,7 @@ fuzz-all: $(FUZZ_PROGRAMS)
>  $(UNIT_TEST_BIN):
>  	@mkdir -p $(UNIT_TEST_BIN)
>  
> -$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/test-lib.o $(GITLIBS) GIT-LDFLAGS $(UNIT_TEST_BIN)
> +$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/test-lib.o $(GITLIBS) GIT-LDFLAGS | $(UNIT_TEST_BIN)
>  	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
>  		$(filter %.o,$^) $(filter %.a,$^) $(LIBS)
>  
> -- 
> 2.43.0.797.g29b680fc68
> 
> 

  reply	other threads:[~2024-01-29 20:22 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-29  3:15 [PATCH 0/2] some unit-test Makefile polishing Jeff King
2024-01-29  3:18 ` [PATCH 1/2] Makefile: use order-only prereq for UNIT_TEST_BIN Jeff King
2024-01-29 20:22   ` SZEDER Gábor [this message]
2024-01-29 22:06     ` Junio C Hamano
2024-01-30  5:21     ` Jeff King
2024-01-29  3:19 ` [PATCH 2/2] t/Makefile: get UNIT_TESTS list from C sources Jeff King
2024-01-29 11:26   ` Patrick Steinhardt
2024-01-29 17:49     ` Jeff King
2024-01-29 21:31       ` Adam Dinwoodie
2024-01-30  0:27         ` Junio C Hamano
2024-01-30  5:25           ` Jeff King
2024-01-31 19:13           ` Adam Dinwoodie
2024-01-30  5:23         ` Jeff King
2024-01-29 21:51   ` Junio C Hamano
2024-01-30  5:37 ` [PATCH v2 0/3] some unit-test Makefile polishing Jeff King
2024-01-30  5:37   ` [PATCH v2 1/3] Makefile: use mkdir_p_parent_template for UNIT_TEST_BIN Jeff King
2024-01-30  5:38   ` [PATCH v2 2/3] Makefile: remove UNIT_TEST_BIN directory with "make clean" Jeff King
2024-01-30  5:40   ` [PATCH v2 3/3] t/Makefile: get UNIT_TESTS list from C sources Jeff King
2024-01-31 22:58     ` Junio C Hamano
2024-02-01 10:50     ` Phillip Wood
2024-02-02  1:20   ` [PATCH v2 0/3] some unit-test Makefile polishing Junio C Hamano
2024-02-02 23:52     ` Johannes Schindelin
2024-02-03  1:32       ` Junio C Hamano
2024-02-04  4:41         ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240129202201.GA9612@szeder.dev \
    --to=szeder.dev@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=peff@peff.net \
    --cc=phillip.wood@dunelm.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.