tt_pre
tt_pre

Reputation: 147

How to build make dependency when the target name is not the file name

I am trying to write a very simple Makefile which I can't make it to work as I expect.

target_a : file.txt
       echo "this is target_a"
       touch 0_$@
target_b : 0_target_a
       echo "executing target_b"
       touch 0_$@

Whenever I run make taget_b it gives out an error:

make: *** No rule to make target '0_target_a', needed by 'target_b'.  Stop.

I can just change touch 0_$@ to touch $@. But I really want a solution for touch 0_$@ (a free choice of filename).

From GNU-man page ftp://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_2.html

A target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out

I want to know how to build the Make dependency when the target name is an:

Action

Upvotes: 1

Views: 2170

Answers (2)

igagis
igagis

Reputation: 2079

The dependency of target_b should be a valid target itself, or a file which already exists

target_a : file.txt
       echo "this is target_a"
       touch 0_$@
target_b : target_a
       echo "executing target_b"
       touch 0_$@

if you want to "alias" creation of 0_target_a file to the target_a "action" you can add intermediate rule:

0_target_a : file.txt
       echo "creating 0_target_a"
       touch 0_$@

target_a : 0_target_a

target_b : target_a
       echo "executing target_b"
       touch 0_$@

Upvotes: 0

Ondrej K.
Ondrej K.

Reputation: 9679

I am afraid you cannot directly do just that and you'd have to help yourself with an intermediate target that makes the connection between target and its output clear (and hence gives make a chance to decide when it does or does not need to be remade:

0_target_a: file.txt
        echo "this is target_a"
        touch $@

target_b: 0_target_a
        echo "executing target_b"
        touch 0_$@

I.e. defining rule for target 0_target_a and updating touch accordingly will give you the behavior you wanted as make now understand the rule the connection between target and file 0_target_a and know when it does not need to be remade as a dependency of target_b. Now if you still want to also have a standalone target_a that would generate file 0_target_a, you can define it as follows:

target_a: 0_target_a

Since we know this target is not really creating a file itself, we can spare make a little effort looking for its result (target_a) and also prevent clashes should such file be created by declaring it as phony.

As a matter of fact you may want to give your target_b the same treatment, as otherwise (again make does not have enough information to understand the relation between target_b and 0_target_b) make target_b is always remade even though the file has already been generated.

The whole make file would look like this:

.PHONY: target_a target_b
target_a: 0_target_a
target_b: 0_target_b

0_target_a: file.txt
    echo "this is target_a"
    touch $@

0_target_b: 0_target_a
    echo "executing target_b"
    touch $@

If that is a reoccurring theme throughout the file, you could also express the relation on second and third line by defining a static pattern rule:

target_a target_b: %:  0_%

This defines a rule that a any target (first '%' without anything else) has a prerequisite of 0_ prefix followed by that target name (0_%, 0_ plus stem which in this case is a target name in its entirety as matched by previous %). and makes this rule applicable to targets target_a and target_a. This rule has no recipe and hence only describe target/prerequisite relation between the two.

In other words it means the same thing as the full example lines 2 and 3 combined.

Upvotes: 1

Related Questions