25

Like the title says, I would like to make a dependency only if a certain file does not exist, NOT every time it updates.

I have a root directory (the one with the makefile) and in it a sub-directory called "example". In my root directory are four .h files (functions.h, parser.h, node.h, and exception.h) which I would like to copy to the "example" sub-directory if those .h files do not already exist in "examples".

Unfortunately I can not just make a standard dependency to check for the header files in "example" because each time I copy the header files from root to "example", the header files in "example" will be considered updated and will trigger that dependency each time I run make. I would like for a way to have my makefile copy the header files from the root directory to "example" only if they do not exist in "example".

Daniel
  • 1,872
  • 4
  • 17
  • 34
  • The manual is very, very clear that automatic variables (such as `$@`) are valid _only_ within the recipe. You cannot use them in targets, in prerequisites, or in make conditional statements (because those are expanded while the makefile is read in). In those cases, `$@` expands to the empty string. – MadScientist Feb 13 '14 at 05:19
  • I see, but because I append "example/" there's something for the ifeq() to still evaluate to false. Thanks for clearing that up. I've edited my post to focus on the remaining issue. – Daniel Feb 13 '14 at 05:29
  • Another solution to your problem can be `cp -p --update`: _copy only when the SOURCE file is newer than the destination file or when the destination file is missing_. – Maxim Egorushkin Feb 20 '22 at 19:47

1 Answers1

34

This is what order-only prerequisites/dependencies are for:

Occasionally, however, you have a situation where you want to impose a specific ordering on the rules to be invoked without forcing the target to be updated if one of those rules is executed. In that case, you want to define order-only prerequisites. Order-only prerequisites can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only.

In your case:

examples/%.h : | %.h
    cp $| $@

See also: Order-only prerequisites do not show up in $^ or $+.

kenorb
  • 137,499
  • 74
  • 643
  • 694
Maxim Egorushkin
  • 125,859
  • 15
  • 164
  • 254
  • 1
    If you are using GNU make (and you probably are), this is a great answer. – reinierpost Feb 13 '14 at 14:12
  • 1
    @reinierpost I am not sure why would one use any other make. – Maxim Egorushkin Feb 13 '14 at 14:17
  • In the past, I've been stuck with other `make`s but indeed, that was a long time ago. – reinierpost Feb 13 '14 at 14:24
  • Thanks, this example worked but I'm not sure I understand it. I thought order-only means that if the dependency "%.h" doesn't exist or is updated it would NOT trigger the target "examples/%.h". Furthermore, "examples/%.h" is a dependency of its own that should be triggered any time files from "root" are copied to "examples" since it updates the files "examples/%.h". This however is not the behavior meaning it does what I want it to, but not what I expect. Could you elaborate on what's happening in your solution? – Daniel Feb 13 '14 at 16:01
  • @Daniel `make` does not check the timestamp of order-only dependencies. Which means that it creates `examples/%.h` but does not update it when its prerequisite `%.h` changes. – Maxim Egorushkin Feb 13 '14 at 16:05
  • So if %.h is executed not necessarily the rule examples/%.h will be executed. Just when examples/%.h is executed, %.h is checked and if newer than, is executed. – David Kennedy Feb 11 '17 at 16:57
  • @DavidKennedy `%.h` timestamp is never checked, your summary doesn't sound right. – Maxim Egorushkin Feb 22 '22 at 01:20
  • Sorry, @MaximEgorushkin. The main difference using order-only is that it ignores updates but keeps looking at the file existence, right? – David Kennedy Feb 23 '22 at 04:55