[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: feature request - order only deps

From: Sebastian Pipping
Subject: Re: feature request - order only deps
Date: Sat, 02 Feb 2013 00:22:16 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130113 Thunderbird/17.0.2

On 01.02.2013 16:18, Matěj Týč wrote:
> Hi,
> I have noticed that if we have a target that has prerequisities, if
> those prerequisities are missing and I want to make the target, then
> even if the target file exists, prerequisities are remade if possible
> and then, consequently, the target has to be remade, too, since its
> prerequisity is now more up-to-date. Which, of course, makes perfect sense.
> However, if a prerequisity is order-only, it is also going to be remade
> despite the target file existis already, but unlike the case above, the
> target won't be remade because it is allowed to be older than its
> order-only prerequisity. This is normally not an issue, since order-only
> prereqs are probably often cheap commands lke mkdir etc., but my case is
> different:
> Consider a server process that can execute commands and that can load
> (huge) data into cache to spped the execution up. Loading the data is a
> make task and a target file cache-foo is created to expose that the data
> has been succesfully loaded into the server cache. Then cache-foo is an
> order-only dependency of foo1, foo2 and foo3 targets that take advantage
> of it (rules to make them call the server process that uses the foo
> cache). Therefore those targets are not made before setting the cache up
> and also the cache is loaded once, not concurently even if like -j4 is
> used as a make argument.
> As you might guess, if I have a target 'bar' that depends on 'foo1' and
> 'foo2', then even if 'foo1' and 'foo2' exist, if 'cache-foo' is missing,
> it is remade and data are loaded into the cache without being of any
> use, which is quite annoying. In other words, the whole server might
> have to start, load the cache and then do nothing.

This is what I understand to be our current Makefile:

  bar_deps = foo1 foo2

  bar: $(bar_deps)

  $(bar_deps): | cache-foo

        touch $@

Now you want that cache-foo is not built if all of $(bar_deps) exist.
We can achieve that by only adding cache-foo as a dependency, if former
is not the case.  So let's replace the line

  $(bar_deps): | cache-foo


  $(bar_deps): | $(if $(call any_file_missing,$(bar_deps)),cache-foo,)

using two custom functions:

  # $(call file_missing,file_1)
  # returns:
  #   true (actually $(file_1)) if the file is missing
  #   false (empty string) if the file exists
  define file_missing
  $(if $(wildcard $1),,$1)

  # $(call any_file_missing,file_1 file_2 ..)
  # returns:
  #   true (a non-empty string) if any file is missing
  #   false (empty string) if all file exist
  define any_file_missing
  $(strip $(foreach filename,$(1),$(call file_missing,$(filename))))

I hereby put that into the public domain.

This session confirms it working:

  $ touch foo1 foo2 bar

  $ make
  make: `bar' is up to date.    # cache-foo not built!

  $ rm foo1

  $ make
  touch cache-foo  # cache-foo built, since foo1 is missing
  touch foo1
  touch bar

I'm curious, if that helps.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]