target override only if there is a recipe for it?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

target override only if there is a recipe for it?

Brian J. Murrell
I am trying to override a target that has a general definition in an
included Makefile with a more specific one.  But it seems that the
override only happens if the overriding target has a recipe?

I.e:

Makefile.mk:
 1 foo.gz:
 2    echo "foo" | gzip > $@

Makefile:
 1 include Makefile.mk
 2
 3 %.gz: %
 4     rm -f $@
 5     gzip $<
 6
 7 foo:
 8     echo "better foo" > $@
 9
10 foo.gz: foo

My expectation is that the foo.gz target on line 10 of Makefile
overrides the one on line 1 of Makefile.mk, but it doesn't unless I
make it:

foo.gz: foo
    rm -f $@
    gzip $<

by redundantly adding the %.gz: % recipe to it.

Is this intended behaviour?

Also, is there a way to suppores of the "warning: overriding recipe for
target" messages that make emits?  I realize they can be useful when
you inadvertently override a target, but it would be nice to indicate
in the Makefile that you understand you are overriding a target and
don't want the warning.

Cheers,
b.


_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: target override only if there is a recipe for it?

David Boyce-3
Yes, this is documented behavior. A target can be mentioned multiple times
but only one mention can provide a recipe. Others simply add to the prereq
list. Thus:

foo.gz: abc
foo.gz: def
foo.gz: ghi
        <recipe>

Has 3 prerequisite files. This behavior is documented, baked in, and is not
going to change. And is considered a feature.

There's no way to suppress the warning AFAIK but there are various
workarounds such as putting the recipe in a variable:

recipe = echo Building $@

foo.gz:
        @$(recipe)

Changing the value of the variable will not trigger a warning. You could
also look into double-colon rules, and if you really want to go for it
almost anything can be done with $(eval ...).

David

On Fri, Aug 30, 2019 at 8:08 AM Brian J. Murrell <[hidden email]>
wrote:

> I am trying to override a target that has a general definition in an
> included Makefile with a more specific one.  But it seems that the
> override only happens if the overriding target has a recipe?
>
> I.e:
>
> Makefile.mk:
>  1 foo.gz:
>  2    echo "foo" | gzip > $@
>
> Makefile:
>  1 include Makefile.mk
>  2
>  3 %.gz: %
>  4     rm -f $@
>  5     gzip $<
>  6
>  7 foo:
>  8     echo "better foo" > $@
>  9
> 10 foo.gz: foo
>
> My expectation is that the foo.gz target on line 10 of Makefile
> overrides the one on line 1 of Makefile.mk, but it doesn't unless I
> make it:
>
> foo.gz: foo
>     rm -f $@
>     gzip $<
>
> by redundantly adding the %.gz: % recipe to it.
>
> Is this intended behaviour?
>
> Also, is there a way to suppores of the "warning: overriding recipe for
> target" messages that make emits?  I realize they can be useful when
> you inadvertently override a target, but it would be nice to indicate
> in the Makefile that you understand you are overriding a target and
> don't want the warning.
>
> Cheers,
> b.
>
> _______________________________________________
> Help-make mailing list
> [hidden email]
> https://lists.gnu.org/mailman/listinfo/help-make
>
_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: target override only if there is a recipe for it?

Kaz Kylheku (gmake)
In reply to this post by Brian J. Murrell
On 2019-08-30 06:24, Brian J. Murrell wrote:
> I am trying to override a target that has a general definition in an
> included Makefile with a more specific one.  But it seems that the
> override only happens if the overriding target has a recipe?

Overriding targets isn't a concept in make; it can happen by mistake
and is diagnosed as such.

> I.e:
>
> Makefile.mk:
>  1 foo.gz:
>  2    echo "foo" | gzip > $@
>
> Makefile:
>  1 include Makefile.mk
>  2
>  3 %.gz: %
>  4     rm -f $@
>  5     gzip $<
>  6
>  7 foo:
>  8     echo "better foo" > $@
>  9
> 10 foo.gz: foo

This rule without a recipe is a make feature; what it does
is specify that foo.gz depends on foo. This can add additional
dependencies to an existing target.

> My expectation is that the foo.gz target on line 10 of Makefile
> overrides the one on line 1 of Makefile.mk, but it doesn't unless I
> make it:

There is in fact a form of overriding going on, just not
the one you want.

Your build system specifies two conflicting rules: a pattern rule
that converts any % to %.gz, and a diect rule for
updating the specific file foo.gz.

That specific rule for foo.gz is, effectively, an override
for the general pattern rule.

Thus if we want foo.gz to be updated using the pattern rule,
then what we need is for the direct rule not to exist at all.

We need a mechanism for deleting a rule (no such feature) or else
we must structure the code so that we can conditionally prevent
a rule from being defined.

For instance:

   # Makefile.mk
   ifeq ($(DEFINED_foo.gz),)
   foo.gz:
          [..commands..]
   DEFINED_foo.gz = y
   endif

Now in Makefile we can suppress the definition by defining
that variable:

   # Makefile
   DEFINED_foo.gz := y
   include Makefile.mk



_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make