Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Make - Trailing "/"s being dropped?

I'm working on a makefile that creates multiples files in output directories. In order for those files to be created, the output directory needs to already exist or else the file creation fails.

Here's a minimal example that demonstrates the issue I'm running into:

.PHONY: default
default: dir/file.dat dir/other.dat

# In order to create these files, their parent directory must exist
dir/%.dat: | dir/
    touch "$@"

# To create a directory, use mkdir -p
%/:
    mkdir -p "$@"

When I run the makefile, I get an error that no rule exists to make dir. The debug run shows that make is dropping the trailing "/" from "dir/":

root@69654136a2ae:~# make -rdf dirs.mk
GNU Make 3.81
[snipped]

Considering target file `default'.
 File `default' does not exist.
  Considering target file `dir/file.dat'.
   File `dir/file.dat' does not exist.
    Considering target file `dir'.
     File `dir' does not exist.
     Looking for an implicit rule for `dir'.
     No implicit rule found for `dir'.
     Finished prerequisites of target file `dir'.
    Must remake target `dir'.
make: *** No rule to make target `dir', needed by `dir/file.dat'.  Stop.

Incidentally, asking for a directory target on the command line works just fine:

root@69654136a2ae:~# make -rdf dirs.mk /some/dir/
GNU Make 3.81
[snipped]

Updating goal targets....
Considering target file `/some/dir/'.
 File `/some/dir/' does not exist.
 Looking for an implicit rule for `/some/dir/'.
 Trying pattern rule with stem `/some/dir'.
 Found an implicit rule for `/some/dir/'.
 Finished prerequisites of target file `/some/dir/'.
Must remake target `/some/dir/'.
mkdir -p "/some/dir/"

How can I have make do what I want?
Ideally I'm looking for a generic solution. The above example only has one subdirectory, but the actual project will have many subdirectories, so I'd like to avoid copy-pasting a solution everywhere.

like image 365
Mr. Llama Avatar asked Jun 28 '26 16:06

Mr. Llama


1 Answers

Yes, the / is dropped in dir/ target (issue can be reproduced under GNU Make 3.81).

One alternative solution is to use automatic variable $(@D) to get the directory part of the file name of the target, with the trailing slash removed. And make the directory before touch the file:

.PHONY: default
default: dir/file.dat dir/other.dat

# In order to create these files, make their parent directory first
dir/%.dat:
        mkdir -p $(@D)
        touch "$@"

Test under GNU Make 3.81 passed:

$ make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
...

$ make
mkdir -p dir
touch "dir/file.dat"
mkdir -p dir
touch "dir/other.dat"
like image 118
leiyc Avatar answered Jul 02 '26 15:07

leiyc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!