Reputation: 35
While investigating differences between single-colon rules (:
) and double-colon rules (::
) in Makefiles, I observed some confusing behaviors:
include
directive should force the target file to be generated (regardless of rule type).include
, but single-colon rules worked as expected.include
?Content of Makefile:
test0.txt::
touch test0.txt
test.txt::
touch test.txt
include test.txt
Result:
xuanyi@Shwan:~/try/playground$ tree
.
└── Makefile
1 directory, 1 file
xuanyi@Shwan:~/try/playground$ head -n 20 Makefile
test0.txt ::
touch test0.txt
test.txt ::
touch test.txt
include test.txt
xuanyi@Shwan:~/try/playground$ make
touch test0.txt
xuanyi@Shwan:~/try/playground$ tree
.
├── Makefile
└── test0.txt
1 directory, 2 files
xuanyi@Shwan:~/try/playground$
The question is include test.txt
did not trigger the double-colon rule, yet the unrelated test0.txt
rule executed.
Content of Makefile:
test0.txt::
touch test0.txt
test.txt:
touch test.txt
include test.txt
Result:
xuanyi@Shwan:~/try/playground$ tree
.
└── Makefile
1 directory, 1 file
xuanyi@Shwan:~/try/playground$ head -n 20 Makefile
test0.txt ::
touch test0.txt
test.txt :
touch test.txt
include test.txt
xuanyi@Shwan:~/try/playground$ make
touch test.txt
touch test0.txt
xuanyi@Shwan:~/try/playground$ tree
.
├── Makefile
├── test.txt
└── test0.txt
1 directory, 3 files
xuanyi@Shwan:~/try/playground$
Key Difference:
include
, while double-colon rules with empty prerequisites (Experiment 1) fail.Content of Makefile:
test0.txt::
touch test0.txt
test.txt:: invalid_file
touch test.txt
include test.txt
Result:
xuanyi@Shwan:~/try/playground$ tree
.
└── Makefile
1 directory, 1 file
xuanyi@Shwan:~/try/playground$ head -n 20 Makefile
test0.txt ::
touch test0.txt
test.txt :: invalid_file
touch test.txt
include test.txt
xuanyi@Shwan:~/try/playground$ touch invalid_file
xuanyi@Shwan:~/try/playground$ tree
.
├── Makefile
└── invalid_file
1 directory, 2 files
xuanyi@Shwan:~/try/playground$ make
touch test.txt
touch test0.txt
xuanyi@Shwan:~/try/playground$ tree
.
├── Makefile
├── invalid_file
├── test.txt
└── test0.txt
1 directory, 4 files
xuanyi@Shwan:~/try/playground$
About my environment:
xuanyi@Shwan:~/try/playground$ make --version
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
xuanyi@Shwan:~/try/playground$ hostnamectl
Static hostname: Shwan
Icon name: computer-container
Chassis: container ☐
Machine ID: #####
Boot ID: #####
Virtualization: wsl
Operating System: Ubuntu 24.04.1 LTS
Kernel: Linux 5.15.167.4-microsoft-standard-WSL2
Architecture: x86-64
I am confused about the result that double-colon rules are triggered by include
only if prerequisites exist, but fail with empty prerequisites (Experiment 1). Why do double-colon rules with empty prerequisites conflict with include
's priority logic? Does Make apply implicit conditions to double-colon rules?
Let me know if further adjustments are needed.
Upvotes: 2
Views: 22
Reputation: 101021
First, please always mention the version of GNU Make and the type and version of the operating system you're running it on.
If you enable debugging output you will see that make informs you of what is happening:
$ make -d
...
Makefile 'test.txt' might loop; not remaking it.
...
This message should (IMO) be displayed as part of the --trace
output, but it's not unfortunately.
The GNU Make manual discusses the behavior of double-colon rules with no prerequisite:
If there are no prerequisites for that rule, its recipe is always executed (even if the target already exists).
Because of this, if GNU Make were to allow double-colon rules with no prerequisites to recreate makefiles then it would be an infinite loop of creating the makefile, re-invoking make, creating the makefile, re-invoking make, etc.
This is also discussed directly in the GNU Make manual section on re-making makefiles:
If the makefiles specify a double-colon rule to remake a file with a recipe but no prerequisites, that file will always be remade (see Double-Colon Rules). In the case of makefiles, a makefile that has a double-colon rule with a recipe but no prerequisites will be remade every time make is run, and then again after make starts over and reads the makefiles in again. This would cause an infinite loop: make would constantly remake the makefile and restart, and never do anything else. So, to avoid this, make will not attempt to remake makefiles which are specified as targets of a double-colon rule with a recipe but no prerequisites.
Upvotes: 0