Skip to content

Instantly share code, notes, and snippets.

@brabect1
Created October 14, 2016 07:25
Show Gist options
  • Save brabect1/8575fdaaabfed35b089f1157519e7dc8 to your computer and use it in GitHub Desktop.
Save brabect1/8575fdaaabfed35b089f1157519e7dc8 to your computer and use it in GitHub Desktop.
GNU Make and the effects of intermediate targets.

Intermediate files in make's terminology is a file needed somewhere on way from a source file to target file. An examples is a file.c needed to create file.o from file.y (YACC source). From that principle, an intermediate file is needed only once to generate the target after the source changed and thus can be removed after it was used. Therefore, an intermediate file which did not exist before make also does not exist after make (see gnu_rule_chains). In other words, make removes the intermediate files it needed to create (unless .SECONDARY or .PRECIOUS is used). For details refer to gnu_rule_chains.

That being said, the use of explicit intermediate files (i.e. .INTERMEDIATE) is rarely needed. Often one either really wants to see the itermediate files too (thus making explicit targets and dependencies and remove them as a part of make clean) or use them implicitly in connection to pattern rules (and thus no need to use .INTERMEDIATE, see gnu_pattern_rules).

The following Makefile example shows the effects of explicit intermediate targets. See the differences between make final and make finalx.

# This example is to show the effects of .INTERMEDIATE target.
# For targets/files marked as `intermediate` it holds that targets
# depending on them call the intermediate targets only once.
# Note that the choice of target names is only to make them
# self-explanatory.

# This is how to identify intermediate targets.
.INTERMEDIATE: intermediate

# As the target creates a file of that name, the `intermediate`
# target is called only once for the initial creation of the
# `final` file. While the `intermediate` target is not called,
# the dependency is still checked. That is, if one creates a
# new `intermediate` file herself (after the last update to
# the `final` file), then the `final` target's recipe is
# executed.
final: intermediate
	cat intermediate >> $@
	rm -rf $^

# Since this target does NOT create a file of the same name
# it will call the `intermediate` target every time.
# Also notice that the explicit `rm` is missing but still
# gets issued (and intermediate files removed). This is
# done implicitly by `make` (so the explicit `rm` in the
# `final` target is not necessary). This is the result of
# the make's nature "an intermediate file which did not exist
# before make also does not exist after make" (see GNU Make
# Manual, Sec. 10.4 Chains of Implicit Rules).
finalx: intermediate
	cat intermediate >> final
	rm -rf $^

intermediate:
	echo "intermediate file $$(date)" > $@

Here is an example taken from here and shows how trying to make wildcard targets intermediates may not work (i.e. .INTERMEDIATE: %.dep).

oncetwice: once twice
    @echo $@: $^

## Uncommenting the following line is sufficient to cause GNU make 3.81 to
## not delete the intermediate 'twice.dep', even if it didn't exist
## previously (i.e., was created by this invocation).
#another: twice.dep

%: %.dep
    @echo $^ >$@

## the following .INTERMEDIATE has no effect re: the twice: twice.dep
## dependency
## PROBLEM: `%.dep` may not work as a pattern/wildcard dependency. Discussion from
## the link says that there is a bug in GNU 3.81 related to .INTERMEDIATE. Suprisingly
## enough this example works on Red Hat 6.7.
.INTERMEDIATE: %.dep

## This is the pattern rule for the intermediate files. Even when the `.INTERMEDIATE: %.dep`
## is removed/commented, `make` will treat the .dep files as intermadiate because they
## satisfy the condition "does not exist before make".
%.dep:
    @echo $@ >$@
@DeadZay
Copy link

DeadZay commented Mar 16, 2020

Hi. Is there way to delete directory using .INTERMEDIATE ?
Maybe change flags or command that doing it (or something else?).
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment