0

I have this make target. Its intention is to rely on the output directory as well as the source. I used this for truncating the file name and leaving the directories its in.

build/%.o: src/%.cpp build/${%%/*}/
        $(CC) $(CFLAGS) -o $@ $^

Then the directory make target:

%/:
        mkdir -p $@

The problem is, ${%%/*} isn't being substituted so it only ends up making the dir build// instead of build/folder/folder/.

Jens
  • 69,818
  • 15
  • 125
  • 179
Chris Smith
  • 2,928
  • 4
  • 27
  • 59

1 Answers1

2
.SECONDEXPANSION:

build/%.o:  src/%.c | $$(dir $$@)/.dirstamp
    echo $@

%/.dirstamp:
    mkdir -p $(@D)
    touch $@

should do it.

Please note:

  • use |; only existence matters, not whether directory stamp is newer
  • using a .dirstamp is more reliable

You might want to mark the .dirstamp as .SECONDARY. Unfortunately, gnumake does not support wildcards so you have to enumerate them either all, or treat every target as .SECONDARY

ensc
  • 6,704
  • 14
  • 22
  • You really don't need `.dirstamp`. Just using `/.` should be enough (`$$(dir $$@)/.` and `%/.`) – MadScientist Jul 31 '16 at 22:24
  • You need it when `.SECONDARY` is not used. Else, make can try to `rm build/dir` which fails on directories. – ensc Aug 01 '16 at 10:25
  • True. Mentioning the directory as a target anywhere in the makefile will solve that. E.g., a new phony rule like `makedirs : somedir/. anotherdir/.` etc. – MadScientist Aug 01 '16 at 15:40