MAKECMDGOALS

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

MAKECMDGOALS

Sébastien Hinderer
Hello,

I am using GNU make 4.3. The manual says:

   'Make' will set the special variable 'MAKECMDGOALS' to the list of
   goals you specified on the command line.  If no goals were given on
   the command line, this variable is empty.

If I define the following Makefile:

ifeq "$(MAKECMDGOALS)" ""
MAKECMDGOALS := default
endif

all:
        @echo MAKECMDGOALS=$(MAKECMDGOALS)

and then run

make --warn-undefined-variables

I get the following warning:

Makefile:1: warning: undefined variable 'MAKECMDGOALS'

Am I correct that there is a mismatch between make's documented and real
behaviour?

Thanks,

Sébastien.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Paul Smith-20
On Mon, 2021-02-01 at 11:49 +0100, Sébastien Hinderer wrote:

>    'Make' will set the special variable 'MAKECMDGOALS' to the list of
>    goals you specified on the command line.  If no goals were given on
>    the command line, this variable is empty.
>
> If I define the following Makefile:
>
> ifeq "$(MAKECMDGOALS)" ""
>
> make --warn-undefined-variables
>
> Makefile:1: warning: undefined variable 'MAKECMDGOALS'
>
> Am I correct that there is a mismatch between make's documented and
> real behaviour?

Hm.  Well, I could use a language lawyer's response and say that "this
variable is empty" is not the same thing as "this variable is set to
the empty value".

The variable _IS_ empty, in the same way that any unset variable is
empty.

If you want to tell the difference between a variable that is not set
at all versus set to the empty string, you have to use the
$(origin ...) function.

Instead of your code you could use:

    MAKECMDGOALS ?= default

which will set MAKECMDGOALS IFF it has never been set at all (not even
to the empty string).

Probably this section of the documentation should be updated to be more
clear so that reading it doesn't require language lawyering.


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Sébastien Hinderer
Dear Paul,

Many thanks for your response.

I was not trying to debate :)

It seems I used "defined" where youu use "set" but that's what I meant.
Shouldn't make set this variable to theempty string rather than not
setting it at all?

Cheers,

Sébastien.




Paul Smith (2021/02/01 09:17 -0500):

> On Mon, 2021-02-01 at 11:49 +0100, Sébastien Hinderer wrote:
> >    'Make' will set the special variable 'MAKECMDGOALS' to the list of
> >    goals you specified on the command line.  If no goals were given on
> >    the command line, this variable is empty.
> >
> > If I define the following Makefile:
> >
> > ifeq "$(MAKECMDGOALS)" ""
> >
> > make --warn-undefined-variables
> >
> > Makefile:1: warning: undefined variable 'MAKECMDGOALS'
> >
> > Am I correct that there is a mismatch between make's documented and
> > real behaviour?
>
> Hm.  Well, I could use a language lawyer's response and say that "this
> variable is empty" is not the same thing as "this variable is set to
> the empty value".
>
> The variable _IS_ empty, in the same way that any unset variable is
> empty.
>
> If you want to tell the difference between a variable that is not set
> at all versus set to the empty string, you have to use the
> $(origin ...) function.
>
> Instead of your code you could use:
>
>     MAKECMDGOALS ?= default
>
> which will set MAKECMDGOALS IFF it has never been set at all (not even
> to the empty string).
>
> Probably this section of the documentation should be updated to be more
> clear so that reading it doesn't require language lawyering.
>

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

David Boyce-3
It would make more sense to me for --warn-undefined-variables to simply
ignore builtin variables. Surely the point of the option is to find out
about mistakes the makefile writer may have made so whether the
implementation sets $(MAKECMDGOALS) or $(MAKEFILES) or $(GNUMAKEFLAGS) is
not of interest. If the user sets it it will be set, of course, and if not
it's whatever the documentation says it should be.

David

On Mon, Feb 1, 2021 at 6:34 AM Sébastien Hinderer <
[hidden email]> wrote:

> Dear Paul,
>
> Many thanks for your response.
>
> I was not trying to debate :)
>
> It seems I used "defined" where youu use "set" but that's what I meant.
> Shouldn't make set this variable to theempty string rather than not
> setting it at all?
>
> Cheers,
>
> Sébastien.
>
>
>
>
> Paul Smith (2021/02/01 09:17 -0500):
> > On Mon, 2021-02-01 at 11:49 +0100, Sébastien Hinderer wrote:
> > >    'Make' will set the special variable 'MAKECMDGOALS' to the list of
> > >    goals you specified on the command line.  If no goals were given on
> > >    the command line, this variable is empty.
> > >
> > > If I define the following Makefile:
> > >
> > > ifeq "$(MAKECMDGOALS)" ""
> > >
> > > make --warn-undefined-variables
> > >
> > > Makefile:1: warning: undefined variable 'MAKECMDGOALS'
> > >
> > > Am I correct that there is a mismatch between make's documented and
> > > real behaviour?
> >
> > Hm.  Well, I could use a language lawyer's response and say that "this
> > variable is empty" is not the same thing as "this variable is set to
> > the empty value".
> >
> > The variable _IS_ empty, in the same way that any unset variable is
> > empty.
> >
> > If you want to tell the difference between a variable that is not set
> > at all versus set to the empty string, you have to use the
> > $(origin ...) function.
> >
> > Instead of your code you could use:
> >
> >     MAKECMDGOALS ?= default
> >
> > which will set MAKECMDGOALS IFF it has never been set at all (not even
> > to the empty string).
> >
> > Probably this section of the documentation should be updated to be more
> > clear so that reading it doesn't require language lawyering.
> >
>
>
Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Sébastien Hinderer
Yeah, ignoring builtin variables makes sense to me, too!

Many thanks for this suggesiton, David!

Sébastien.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Kaz Kylheku (gmake)
In reply to this post by Paul Smith-20
On 2021-02-01 06:17, Paul Smith wrote:

> On Mon, 2021-02-01 at 11:49 +0100, Sébastien Hinderer wrote:
>>    'Make' will set the special variable 'MAKECMDGOALS' to the list of
>>    goals you specified on the command line.  If no goals were given on
>>    the command line, this variable is empty.
>>
>> If I define the following Makefile:
>>
>> ifeq "$(MAKECMDGOALS)" ""
>>
>> make --warn-undefined-variables
>>
>> Makefile:1: warning: undefined variable 'MAKECMDGOALS'
>>
>> Am I correct that there is a mismatch between make's documented and
>> real behaviour?
>
> Hm.  Well, I could use a language lawyer's response and say that "this
> variable is empty" is not the same thing as "this variable is set to
> the empty value".
>
> The variable _IS_ empty, in the same way that any unset variable is
> empty.

But the warning says "undefined", not "empty".

Is the warning actually about empty variables? If so, its wording is
misleading, as is the name of the option which controls it.

> If you want to tell the difference between a variable that is not set
> at all versus set to the empty string, you have to use the
> $(origin ...) function.
>
> Instead of your code you could use:
>
>     MAKECMDGOALS ?= default

But that's more of a thing we use for user-overridable variables
that we want to set to default values like

       CFLAGS ?= -O2

Not for ensuring that a documented built-in actually exists.

> which will set MAKECMDGOALS IFF it has never been set at all (not even
> to the empty string).

Maybe MAKECMDGOALS *should* be set to the empty string by make?

However, that kind of change will break Makefiles.

Unknown numbers of existing Makefiles in the wild are using
$(origin MAKECMDGOALS), and relying on that to produce the word
"undefined" when no goals have been given.

GNU Make has broken things for users before, such as suddenly turning
off the lexicographic sorting behavior in $(wildcard ...).

The impact of that kind of change, though not eliminated, could be
softened if Make had some way of emulating old behaviors. For instance,
NU Bash has the following environment variable:

        BASH_COMPAT
               The value is  used  to  set  the  shell's  compatibility
               level.   See  the description of the shopt builtin below
               under SHELL BUILTIN COMMANDS for a  description  of  the
               various  compatibility  levels  and  their effects.  The
               value may be a decimal number (e.g., 4.2) or an  integer
               (e.g.,  42)  corresponding  to the desired compatibility
               level.  If BASH_COMPAT is unset  or  set  to  the  empty
               string,  the  compatibility  level is set to the default
               for the current version.  If BASH_COMPAT  is  set  to  a
               value that is not one of the valid compatibility levels,
               the shell prints an error message and sets the  compati‐
               bility  level  to  the  default for the current version.
               The valid compatibility levels correspond to the compat‐
               ibility  options accepted by the shopt builtin described
               below (for example, compat42 means that 4.2 and  42  are
               valid  values).   The  current  version  is also a valid
               value.

The shopt documentation describes all the meaningful version values
and their specific effect:

               compat41
                       If  set, bash, when in posix mode, treats a sin‐
                       gle quote in a double-quoted parameter expansion
                       as  a special character.  The single quotes must
                       match  (an  even  number)  and  the   characters
                       between the single quotes are considered quoted.
                       This is the behavior of posix mode through  ver‐
                       sion  4.1.  The default bash behavior remains as
                       in previous versions.




Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Paul Smith-20
In reply to this post by Sébastien Hinderer
On Mon, 2021-02-01 at 15:33 +0100, Sébastien Hinderer wrote:
> Shouldn't make set this variable to theempty string rather than not
> setting it at all?

Maybe that would have been a way to do it, back when this feature was
added.  However, it has downsides as you can infer from my email; for
example if we set it to the empty string then using:

    MAKECMGOALS ?= default

would not work.  However, since setting MAKECMDGOALS is useless anyway
this may not be that important.

At this point I think it would be a backward-compat issue to change
this, as some makefiles could be relying on the difference somehow.


My suspicion is that your question is kind of an XY problem and the
real issue you care about isn't whether MAKECMDGOALS is unset or has an
empty value anyway; I think the thing you really care about is that
make gives a warning if MAKECMDGOALS is not set and you reference it,
if you set warn-undefined-variables.

I think the right way to handle that is not to change the value of
MAKECMDGOALS, but instead to declare that this variable is one of the
special-case variables that are not warned about if they are used
without being set.

You can file an enhancement request for this here:

https://savannah.gnu.org/bugs/?func=additem&group=make


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Kaz Kylheku (gmake)
In reply to this post by Sébastien Hinderer
On 2021-02-01 08:34, Sébastien Hinderer wrote:
> Yeah, ignoring builtin variables makes sense to me, too!

But the problem is that when no goals are specified at run-time,
then in that situation the variable is not built-in.

GNU Make should probably not implement a concept of "this variable
is built in, but, oh, not at the moment".

A variable that is "de-facto built-in, but not defined", should
only be one that serves as an *input* to make, not one that is
used to *output* useful information.

In other words, what is built in is not that variable /per se/
but the program's detection of and reaction to it.


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS

Paul Smith-20
In reply to this post by Kaz Kylheku (gmake)
On Mon, 2021-02-01 at 08:51 -0800, Kaz Kylheku (gmake) wrote:
> > The variable _IS_ empty, in the same way that any unset variable is
> > empty.
>
> But the warning says "undefined", not "empty".
> Is the warning actually about empty variables? If so, its wording is
> misleading, as is the name of the option which controls it.

The warning is only for undefined variables.

> Maybe MAKECMDGOALS *should* be set to the empty string by make?

I don't think so.

I see that I wrote a reply then got distracted and forgot to send it,
so I've done that now.  Basically it was the same thing David said.

> A variable that is "de-facto built-in, but not defined", should
> only be one that serves as an *input* to make, not one that is
> used to *output* useful information.

I'm not convinced we should make that restriction.  In the case of
MAKECMDGOALS it might not have mattered because there's no feasible way
that a value of that variable could be the empty string that is
materially different from being undefined.  But in other situations it
could be useful to keep the difference.