0

I am attempting to build a target file (with GNU make) if any of its surrounding files (files of the same type in the same directory) have changed. It seems simple enough but a solution has eluded me. Here is the key line of this makefile:

dir/%.Rd: file1 file2 dir/*.Rd
    ...

where there are 40-50 *.Rd files in /dir (including %.Rd). Although make will automatically remove circular dependencies (the above code does work), I would like to remove the circularity of %.Rd depending on itself. I have tried:

1)

dir/%.Rd: file1 file2 $(filter-out %, dir/*.Rd)   # doesn't work; likely because % doesn't have meaning at this point -- second expansion
    ...

2)

dir/%.Rd: file1 file2 $(filter-out $@, dir/*.Rd)  # doesn't appear to work: circular dependency warning
    ...

3)

dir/%.Rd: file1 file2 $$(filter-out $$@, dir/*.Rd)  # same
    ...

4)

.SECONDEXPANSION:
dir/%.Rd: file1 file2 $$(filter-out $$@, dir/*.Rd)  # same
    ...

This seems like a relatively simple problem and I'm sure I'm close. Any solutions/suggestions/workarounds are greatly appreciated.

Thanks in advance ...

Stu Field
  • 255
  • 2
  • 10
  • You want to rebuild the target file if it is not the newest? So that no more than one of them can be "up to date" at a time? That's a strange design that goes against the grain of Make. – Beta Jul 22 '14 at 04:38
  • No. I want to update the target if any of the files in the same directory have changed. However if I just use `*.Rd` to define the prerequisites, the target file will be included in the '*', creating a circular dependence. I want to avoid this. I don't believe this design goes against Make dogma. – Stu Field Jul 23 '14 at 18:00
  • If any of them has changed? Has changed *since when?* You may have a simple, logically self-consistent goal in mind, but I can't see it. – Beta Jul 24 '14 at 04:17
  • Hmm..."has changed" should probably have been written as "is more recent (newer) than the target file. So to reword the problem: I have a directory with ~40 files, all with the `.Rd` extension. One of them is my target file (say `myfile.Rd`). I want to update `myfile.Rd` of ANY of the OTHER `*.Rd` files in the same directory are more recent than `myfile.Rd`. I cannot simply use `*.Rd` in defining prerequisites, because `myfile.Rd` is one of them, which will create a circular dependency issue. I want to remove `myfile.Rd` from `*.Rd` in the target definition. – Stu Field Jul 24 '14 at 15:51

1 Answers1

0

This is perhaps the least horrible way to do what you want:

RD := $(wildcard *.Rd)

ifneq ($(TARG),)
RD := $(filter-out $(TARG),$(RD))
$(TARG): $(RD)
    do something to update $@
endif

rebuild_%:
    @$(MAKE) $*.rd TARG=$*.Rd

Now make rebuild_myfile will update myfile.Rd if and only if it is not the newest Rd file in the directory, and there will be no circular dependency.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • Nice...thank you very much. I'll try this. In the meantime I did find a workaround >>>> `dir/%.Rd: file1 file2 $$(filter-out $$@, $(wildcard dir/*.Rd))` which exhibits the behaviour I'm looking for (I think) so I'll have to see if there is a fault with either solution that would raise it as preferable over the other. This solution is of course preceded by a `.SECONDEXPANSION` line. – Stu Field Jul 30 '14 at 17:22
  • @StuField: I thought of that, but it still has circular dependency, since `foo.Rd` depends on `bar.Rd` and vice versa. – Beta Jul 30 '14 at 22:45
  • then it must be something strange with Make's dependency tree build, because the circular dependency warning disappeared with this solution. Using the -debug option, there is no sign of circular dependency anywhere. – Stu Field Aug 04 '14 at 17:58