[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: False positive "doesn't match the target pattern" error

From: Ingo Schwarze
Subject: Re: False positive "doesn't match the target pattern" error
Date: Wed, 24 Aug 2022 13:36:12 +0200


Masahiro Yamada wrote in his original bug report:

> ./foo.x: %/foo.x: %/foo.z
>       cp $< $@

This is not make(1) syntax.  POSIX does not define "%", nor multiple
colons on the same line, and i fail to see right now how any similar
problem might occur with POSIX make(1) - of course, i might be overlooking
something.  I'm not a specialist for make(1), just an ordinary OpenBSD
userland and GNU roff developer and an ordinary user of make(1).
I'm answering because Alejandro directly asked for my opinion.

On Aug 22, 2022, at 12:02 AM, Alejandro Colomar wrote:

> Do other make(1) implementations trim this leading ./?

That question is imprecisely worded.  In which context?

When actually creating the file, for example via "touch $@" or something
similar, obviously yes.  Then again, you might argue that in that case,
it isn't really make(1) resolving the "./" but rather the kernel on
behalf of the open(2) system call.

So, in which context?  As a target?  As a dependency?  Or even in yet
some other context, like variable expansion, conditional testing,
or substitution?

Alejandro Colomar wrote on Mon, Aug 22, 2022 at 08:08:13PM +0200:

> I tried on OpenBSD, and it seems to do that and more; it seems to be 
> resolving symlinks and .. (physically, although I'm not yet sure of what 
> it does to .. after segments of the path that don't exist).  It doesn't 
> seem to be documented, and also doesn't seem to be obvious in the source 
> code (I can't find any realpath(3) calls, nor '..').

You don't say what exactly you tested.  I did this quick test
right now:

   $ uname -a
  OpenBSD isnote.usta.de 7.2 GENERIC.MP#662 amd64
   $ cat Makefile                                                 
        @echo no leading dot
        @echo leading dot
  bar: foo
  baz: ./foo
   $ make foo
  no leading dot
   $ make ./foo
  leading dot
   $ make bar
  no leading dot
   $ make baz
  leading dot

So, at least in simple situations, it seems to me that OpenBSD make(1)
treats both target and destination names as strings and does not attempt
to resolve "./".

Then again, i do not doubt that, if you look hard enough, you may well
be able to find edge cases that may surprise you - in OpenBSD make 
just like in GNU make.

I believe it may well be intentional that the OpenBSD make(1) manual,
https://man.openbsd.org/make.1 , does not discuss whether targets
"foo:" and "./foo:" are the same or distinct, because you should
not rely on it.  Instead, it says:

  "For maximum portability, target names should only consist of
   periods, underscores, digits and alphabetic characters."

> Ingo, do you know how your make(1) behaves with respect to '..', '//', 
> '.', and symlinks?  Is that documented anywhere?

I don't see how exactly "..", "//", and symlinks are related to
the orignal bug report, and unless the question is worded with
significantly more precision, i don't feel like testing all over
the place.

> On 8/22/22 16:46, David A. Wheeler wrote:

>> No idea. However, I took a quick look at the POSIX make specification:
>> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html
>> The POSIX specification for make is notoriously underpowered.

Little doubt about that; unfortunately, improving it is very difficult
given how much different implementations of make(1) have diverged.
That can easily be witnessed when watching the Austin list for
proposals to improve the specification of POSIX make(1).

>> It doesn't say anything about whether or not ./FOO is the same as FOO.

It does!  Quoting from the above URI:

  "Applications shall select target names from the set of characters
   consisting solely of periods, underscores, digits, and alphabetics
   from the portable character set [...]"

Consequently, "/" is invalid in a target name, and in particular, "./foo"
is not a valid target name.

>> It refers to files by PRECEDING them with "./", e.g.
>> "By default, the following files shall be tried in sequence:
>> ./makefile and ./Makefile. If neither ./makefile or ./Makefile are
>> found, other implementation-defined files may also be tried.
>> [XSI] On XSI-conformant systems, the additional files ./s.makefile,
>> SCCS/s.makefile, ./s.Makefile, and SCCS/s.Makefile shall also be tried."
>> I interpret that as an expectation that adding "./" is expected to have
>> the same result if the filename starts with an alphabetic character,
>> but that's just my reading and not directly supported.

> That refers to the input file, and not to targets within the DAG, AFAICS.

Indeed, i agree that is completely unrelated to the interpretation
of "./foo" in *any* context inside a Makefile.  It is merely related
to the rules how programs *in general* treat "./" when *opening*
files - and i don't believe anyone could doubt, for example, that
the following two commands behave identically:

  make -f GNUmakefile
  make -f ./GNUmakefile

To summarize, i believe it is not a good idea for Makefile authors
to expect that targets "foo" and "./foo" are the same, nor should
you expect that they are distinct.  It is much better - more portable
and much more robust - to write your Makefile in such a way that the
question does not matter, and ideally, that you consistently refer to
the target "foo" in the POSIX-compatible way "foo:" and never in the
POSIX-violating way "./foo:".


Ingo Schwarze             <schwarze@usta.de>
http://www.openbsd.org/   <schwarze@openbsd.org>
http://mandoc.bsd.lv/     <schwarze@mandoc.bsd.lv>

reply via email to

[Prev in Thread] Current Thread [Next in Thread]