MAKECMDGOALS and spaces

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

MAKECMDGOALS and spaces

Christof Warlich
Hi,

please consider this Maklefile:

$(MAKECMDGOALS):; echo "Goals: $(MAKECMDGOALS)"

For each goal being passed, it prints the list of all goals, e.g.:

$ make hi ho
echo "Goals: hi ho"
Goals: hi ho
echo "Goals: hi ho"
Goals: hi ho

But it fails when goals contain spaces:

$ make "hi ho"

make "hi ho"
make: *** No rule to make target 'hi ho'.  Stop.

Obviously, make knows that it is supposed to build a target with a
space, but this information got lost within the variable MAKECMDGOALS.
Can I fix my simple example to handle this case in a generic way?  As
much as I could figure so far, it seems to be impossible, right?

Thanks,

Chris


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Kaz Kylheku (gmake)
On 2021-02-13 10:35, Christof Warlich wrote:

> Hi,
>
> please consider this Maklefile:
>
> $(MAKECMDGOALS):; echo "Goals: $(MAKECMDGOALS)"
>
> For each goal being passed, it prints the list of all goals, e.g.:
>
> $ make hi ho
> echo "Goals: hi ho"
> Goals: hi ho
> echo "Goals: hi ho"
> Goals: hi ho
>
> But it fails when goals contain spaces:
>
> $ make "hi ho"
>
> make "hi ho"
> make: *** No rule to make target 'hi ho'.  Stop.

I think to make use of this, you need to define a target that has
a space. It seems this is possible as follows


   hi\ ho:
   [tab]echo yes

Then make "hi ho" runs the recipe and "yes" is echoed.

In order to do this with a generated rule from $(MAKECMDGOALS),
you would need some way to do the expansion such that the
spaces are similarly escaped.

There is no obvious way to refer to the value $(MAKECMDGOALS)
without that expanding to a word list.

Maybe Guile scripting needs to be involved?

Pardon the pontificating, but 've never worked with or seen
a Makefile that had spaces in a target name; that kind of
thing is best avoided.

The cultural assumption is that stuff will break if you
allow spaces in the build system.

Build systems exploit breaking into spaces. For instance,
environment variables like CC and CFLAGS contain multiple
items that need to turn into separate arguments.

The use cases for taking every target mentioned on the command
line and materializing it with a generated rule are also
not many.  I've seen that done in byzantine build systems to
do things like redirecting a command to another Makefile in
a different directory:

    $(MAKECMDGOALS):
          $(MAKE) -C $(SOMEWHERE_ELSE) $@

or something like that.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Christof Warlich
Kaz Kylheku wrote:

> I think to make use of this, you need to define a target that has
> a space. It seems this is possible as follows
>
>
>   hi\ ho:
>   [tab]echo yes
>
> Then make "hi ho" runs the recipe and "yes" is echoed.
>
> In order to do this with a generated rule from $(MAKECMDGOALS),
> you would need some way to do the expansion such that the
> spaces are similarly escaped.
>
The problem is that replacing every space with an escaped space only
works as long as MAKECMDGOALS consists of one goal only: If more goals
are given on the command line, their separating space would be replaced
as well, as the distinction between target separating spaces and
in-target spaces obviously get lost in MAKECMDGOALS.

Thus, I'm pretty sure that there is no generic way to do what I was
asking for, but I just want to double-check in case I'm missing something.



Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Kaz Kylheku (gmake)
On 2021-02-13 13:13, Christof Warlich wrote:

> Kaz Kylheku wrote:
>
>> I think to make use of this, you need to define a target that has
>> a space. It seems this is possible as follows
>>
>>
>>   hi\ ho:
>>   [tab]echo yes
>>
>> Then make "hi ho" runs the recipe and "yes" is echoed.
>>
>> In order to do this with a generated rule from $(MAKECMDGOALS),
>> you would need some way to do the expansion such that the
>> spaces are similarly escaped.
>>
> The problem is that replacing every space with an escaped space only
> works as long as MAKECMDGOALS consists of one goal only: If more goals
> are given on the command line, their separating space would be replaced
> as well, as the distinction between target separating spaces and
> in-target spaces obviously get lost in MAKECMDGOALS.
>
> Thus, I'm pretty sure that there is no generic way to do what I was
> asking for, but I just want to double-check in case I'm missing
> something.

The problem is that the value of a GNU  Make variable is just a "char *"
string.

When main.c adds targets to the MAKECMDGOALS variable, it's just this:

       {
         /* Add this target name to the MAKECMDGOALS variable. */
         struct variable *gv;
         const char *value;

         gv = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS"));
         if (gv == 0)
           value = f->name;
         else
           {
             /* Paste the old and new values together */
             size_t oldlen, newlen;
             char *vp;

             oldlen = strlen (gv->value);
             newlen = strlen (f->name);
             vp = alloca (oldlen + 1 + newlen + 1);
             memcpy (vp, gv->value, oldlen);
             vp[oldlen] = ' ';
             memcpy (&vp[oldlen + 1], f->name, newlen + 1);
             value = vp;
           }
         define_variable_cname ("MAKECMDGOALS", value, o_default, 0);
       }
     }


"Add a space followed by the datum to a stack-allocated copy of the
variable,
then install the result as a replacement of the variable."

MAKECMDGOALS does not have the information required to recover targets
with spaces.


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Paul Smith-20
In reply to this post by Christof Warlich
On Sat, 2021-02-13 at 19:35 +0100, Christof Warlich wrote:
> Obviously, make knows that it is supposed to build a target with a
> space, but this information got lost within the variable
> MAKECMDGOALS.
>
> Can I fix my simple example to handle this case in a generic way?  As
> much as I could figure so far, it seems to be impossible, right?

It's basically impossible for make to handle target names with
whitespace in them.  This has been true ever since make was invented
back in the 1970's and is still true today (for all modern versions of
POSIX-based make, including GNU make).

Issues with MAKECMDGOALS are just the tip of the iceberg.

There have been various proposals made to try to resolve this; there
was one I made in a really long thread a number of years ago that
relied on (a) makefiles being UTF8 and (b) making some UTF8 characters
illegal in makefiles (for example some of the low control characters).
 But providing a syntax that works is not easy.


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Sébastien Hinderer
In reply to this post by Kaz Kylheku (gmake)
Hello,

Kaz Kylheku (gmake) (2021/02/13 11:44 -0800):
> Pardon the pontificating, but 've never worked with or seen
> a Makefile that had spaces in a target name; that kind of
> thing is best avoided.

I don't like spaces especially, either. But it seems it's not really
possible to claim one fully supports building on Windows if not
supporting directories with spaces in their names. For instance, one may
want to install to a subdirectory of "C:\Program files". In such a
scenario, one thing that would seem natural to do, at least to me, is to
have targets to creat the required directories.

I am suspecting make would have a hard time handlign this properly, but
if there is any recommendation I'd be very interested.

Sébastien.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

David
On Thu, 18 Feb 2021 at 04:36, Sébastien Hinderer
<[hidden email]> wrote:
> Kaz Kylheku (gmake) (2021/02/13 11:44 -0800):

> > Pardon the pontificating, but 've never worked with or seen
> > a Makefile that had spaces in a target name; that kind of
> > thing is best avoided.

> I don't like spaces especially, either. But it seems it's not really
> possible to claim one fully supports building on Windows if not
> supporting directories with spaces in their names.

That line of thinking is not limited to one operating system.
If that logic is correct, then apparently it's not possible
"to claim one fully supports building on" any operating system.
I think reality disagrees.

> For instance, one may
> want to install to a subdirectory of "C:\Program files".

That seems like a reasonable thing to want.

> In such a
> scenario, one thing that would seem natural to do, at least to me, is to
> have targets to creat the required directories.

Also reasonable.

> I am suspecting make would have a hard time handlign this properly, but
> if there is any recommendation I'd be very interested.

These comments are more my reactions or possible ideas than recommendations:
1) Don't use stupid operating systems.
2) I haven't used any Microsoft OS since Windows 2000. But from a
few seconds of research it appears that a few versions of Windows might
support symbolic or even hard links. Perhaps there could be a recipe in
the makefile that creates a link (without spaces in its name) to
"C:\Program files",
and then the path to the install target directory could be specified
using the link.
Perhaps the link could even be removed after installation.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Kaz Kylheku (gmake)
In reply to this post by Sébastien Hinderer
On 2021-02-17 09:35, Sébastien Hinderer wrote:

> Hello,
>
> Kaz Kylheku (gmake) (2021/02/13 11:44 -0800):
>> Pardon the pontificating, but 've never worked with or seen
>> a Makefile that had spaces in a target name; that kind of
>> thing is best avoided.
>
> I don't like spaces especially, either. But it seems it's not really
> possible to claim one fully supports building on Windows if not
> supporting directories with spaces in their names. For instance, one
> may
> want to install to a subdirectory of "C:\Program files". In such a
> scenario, one thing that would seem natural to do, at least to me, is
> to
> have targets to creat the required directories.
> I am suspecting make would have a hard time handlign this properly, but
> if there is any recommendation I'd be very interested.

There is a recommendation.

Don't even think about using make for installing programs on
Microsoft Windows.

Use a proper installer, like Nullsoft's NSIS or whatever.

Firstly, Make doesn't have the installer wizard GUI support
that users expect.

Secondly, what are the deliverables then? A .zip file that the
user extracts, to a folder full of files and a Makefile? How
does the user run that: there is no make utility installed.
To be able to click on the Makefile to run it, it needs an
extension like Install.mak. That has to be associated, by
the Explorer shell, with the make program.

Third, never mind all that Let's examine what is installation.
Installation is not building; it consist mostly of unconditionally
copying some materials into certain destinations, and possibly
tweaking some system configuration settings (something in the
Registry, or environment variables). What is make? A tool for
incrementally updating out-of-date dependencies. Installation
cannot do that; even if the already installed foo.exe has a newer
modification timestamp, a repetition of the installation steps
must overwrite it.

On Unix, we often have an install: target, because, why not?
There are sophisticated users who build from source and have
all the tools involved.

Most users of GNU/Linux distros don't install programs using
anything resembling "make install".

The convention is that "make install" targets must obey the
DESTDIR convention: if a DESTDIR variable is defined, it
gives the prefix for installation. Distro builds use this
to install to a temporary directory, from which they create
a package (or multiple packages: devel package, run-time
package, doc package. ...)

A distro build will not pull a crazy stunt on you, like
hand you a DESTDIR that expands to a path with spaces.


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Sébastien Hinderer
In reply to this post by David
Hello David,

David (2021/02/18 13:07 +1100):
> These comments are more my reactions or possible ideas than recommendations:
> 1) Don't use stupid operating systems.

To be honest I foudn this comment rather useless and improductive. I am
not in a position where I can choose which operating systems we are
supporting or not. But I liked your other idea about the symlinks!
Thanks!

Best wishes,

Sébastien.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Sébastien Hinderer
In reply to this post by Kaz Kylheku (gmake)
Dear Kaz,

Many thanks for the feedback, which raises interesting questions IMO!

We use a Cygwin environment under Windows so we are perhaps too much
with the Unix way of thinking, even when working under Windows.

I'll keep the question about whether the install target is actually
relevant or not under Windows in mind and try to find a satisfactory
response to it before trying to solve the apparently unsolvable problem
of having make handle names with spaces properly.

Thanks again to all for your enlightening contributions!

Sébastien.

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

David
In reply to this post by Sébastien Hinderer
On Fri, 19 Feb 2021 at 21:23, Sébastien Hinderer
<[hidden email]> wrote:
> David (2021/02/18 13:07 +1100):

> > These comments are more my reactions or possible ideas than recommendations:
> > 1) Don't use stupid operating systems.

> To be honest I foudn this comment rather useless and improductive. I am
> not in a position where I can choose which operating systems we are
> supporting or not.

Hi, yes certainly, it wasn't meant to be advice and I probably could
have chosen better words but sometimes I can't be bothered to polish
such emails. It was my genuine reaction and I included it not to convey
a harsh message but rather to set the context I was writing from.
As hinted by my first sentence above.

Namely that I don't care about Windows or know it in any
useful detail, but I wanted to share the other idea in case it
turned out to be actually useful even though I had no means
to test it or any experience to judge if it was a stupid idea or not.

I think that Kaz's suggestion to use an installer is probably a
better one, even though that horrifies me even further. An
OS where one is compelled use some non-open installer
to write entries into an opaque registry, ugh, I don't like it :)

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Eli Zaretskii
> From: David <[hidden email]>
> Date: Sat, 20 Feb 2021 11:05:36 +1100
>
> Namely that I don't care about Windows or know it in any
> useful detail, but I wanted to share the other idea in case it
> turned out to be actually useful even though I had no means
> to test it or any experience to judge if it was a stupid idea or not.

You may not care about Windows, but supporting Windows is what makes
GNU utilities such as Make more viable than if it would support only a
single OS.  It's what keeps the GNU ecosystem more diverse, and thus
less likely to become ill or die when eventually the Linux OS will
give way to something new.

Moreover, file names with spaces are found not only on Windows
nowadays.  So I guess what you regard as "stupid idea" is for some
reason picked up by GNU/Linux and other systems (perhaps because they
lack imagination, and basically copycat every UI idea they find on
Windows?).

> I think that Kaz's suggestion to use an installer is probably a
> better one, even though that horrifies me even further. An
> OS where one is compelled use some non-open installer
> to write entries into an opaque registry, ugh, I don't like it :)

No one is compelled to use installers, that idea is not the only one.
Using hard links (present on Windows filesystems since long ago) is
one way; using 8+3 file names with numeric tails is another.

But IME the best solution for this is not to put anything under
"Program Files" (or more generally anywhere on the C: drive): those
directories are watched by several OS mechanisms designed to prevent
corruption, and usually have special access control rights.  Programs
installed by the user are better off if they steer away of those
places.  My suggestion -- and what I personally use for many years --
is to create a Posix-like tree in D:\usr, and install all programs
like Make there, adding D:\usr\bin to your PATH.  This allows to solve
easily the problem discussed here and many others as well.

HTH

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Marco Atzeri
On 20.02.2021 08:12, Eli Zaretskii wrote:
>> From: David <[hidden email]>
>> Date: Sat, 20 Feb 2021 11:05:36 +1100
>>

> But IME the best solution for this is not to put anything under
> "Program Files" (or more generally anywhere on the C: drive): those
> directories are watched by several OS mechanisms designed to prevent
> corruption, and usually have special access control rights.  Programs
> installed by the user are better off if they steer away of those
> places.  My suggestion -- and what I personally use for many years --
> is to create a Posix-like tree in D:\usr, and install all programs
> like Make there, adding D:\usr\bin to your PATH.  This allows to solve
> easily the problem discussed here and many others as well.
>
> HTH
>

similar solution is implemented by Cygwin (Posix on Windows ambient)

Installation are

C:\cygwin64\ or D:\cygwin64\

with the usual structure starting there

$ ls -1 /

bin
cygdrive
dev
etc
home
lib
proc
sbin
srv
tmp
usr
var

Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Paul Smith-20
In reply to this post by Eli Zaretskii
On Sat, 2021-02-20 at 09:12 +0200, Eli Zaretskii wrote:
> Moreover, file names with spaces are found not only on Windows
> nowadays.  So I guess what you regard as "stupid idea" is for some
> reason picked up by GNU/Linux and other systems (perhaps because
> they lack imagination, and basically copycat every UI idea they find
> on Windows?).

Just to clarify: UNIX systems have supported spaces in filenames since
before the first line of DOS was written; a filename in POSIX has
always been able to contain _any_ character other than slash ("/") and
nul ('\0') and that includes whitespace of all kinds [1].

It's just that no one in the UNIX/POSIX world actually USED filenames
containing these characters because they required quoting, and that was
especially annoying when the only interfaces we had were CLI (without
completion!) and you had to get the quoting right by hand.  Certainly
they were not part of the base OS (like "Program Files") and so many
UNIX tools from that era simply ignored them; a kind of "Dr. it hurts
when I do that" / "Don't do that" situation.

make, unfortunately it turns out, falls into that category for sure.


[1] Whether this is a good thing or not is certainly open for debate.
Definitely it's been a serious, recognized problem for a long time that
some characters (like newlines!!) should really have not been allowed
in filenames, due to security reasons.



Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Stefan Monnier
> make, unfortunately it turns out, falls into that category for sure.

`make` feel very deeply in that category, to the point where it's not
just space, but several different characters and that it does not
include the necessary quoting functionality to make it *possible* to
deal with those characters.

Just try to write makefiles that build files with colons, semi colons,
etc..

Looked at through the lense of "sh vs csh", `make` is like `csh`, except
its quoting is even more lacking and there's no replacement for "make"
that could play the role of "sh" :-(


        Stefan


Reply | Threaded
Open this post in threaded view
|

Re: MAKECMDGOALS and spaces

Sébastien Hinderer
In reply to this post by Eli Zaretskii
Many thanks for your feedback, Eli. I'll definitely keep it in mind
because that's what seems the easiest to integrate given the environment
we already have.

Best wishes,

Sébastien.