$(wildcard ...*/) and symlinks

2023-02-24 Thread Frank Heckenbach
GNU Make 4.4.0.91

Run from an otherwise empty directory:

% cat Makefile
all: prepare
echo $(wildcard */)
echo $(wildcard l*/)
echo $(wildcard */*/)

prepare:
mkdir -p d/d
touch f d/f
ln -sf f l
ln -sf f d/l
% make -s
d/
l
d/d/ d/l
%

So "*/" ignores the symlink to a file as expected, but "l*/" does
return it, likewise "*/*/" which doesn't make much sense to me.

Maybe related to the issues discussed on
https://stackoverflow.com/questions/66271761/gnu-make-wildcard-function-and-terminating-slashes-on-directory-names

The workaround given there, adding a dot (and removing it from the
results), seems to help, i.e.:

  $(patsubst %/., %, $(wildcard ...*/.))



Re: VPATH question

2023-02-24 Thread Paul Smith
On Fri, 2023-02-24 at 08:44 +0100, Gisle Vanem wrote:
> So I want to create a './lib' directory in
> 'Current Directory', but gnumake won't do it
> since there is a 'lib' under 'apps'. Output:
>    gnumake: Nothing to be done for 'default'.
> 
> Why doesn't it understand the meaning of '.'?

It does.  Make adds the prerequisite to every VPATH entry.  Your VPATH
entry is "apps" and the prerequisite is "./lib", and so the combination
is "apps/./lib" which is a perfectly legal pathname, that is found.

> It also drops the '.' in the --debug' output.

This is due to a special rule in GNU make that allows "." to be ignored
for the purposes of target matching.  It's a little obscure, but it's
not related to the issue you're having with VPATH.  Even if it kept the
"./", "apps/./lib" would still exist and be matched.

> Besides I feel it's not very helpful explaining why
> it won't do "Nothing..". E.g. if I make a typo:
>default all: $(GEN_DIRS2)
> 
> it's the same bleeding message.

Well, I'm not sure it's useful for make to generate one message for
situations where a target is not rebuilt because all of its N
prerequisites are up to date and N > 0, and a different message for the
special case where N == 0.

> Adding a '--debug=w',
> would be nice with a 'why not' message.

If you use "-d" you'll get the info you want:

   No implicit rule found for 'default'.
   Considering target file 'lib'.
   Finished prerequisites of target file 'lib'.
   No need to remake target 'lib'; using VPATH name 'apps/lib'.
  Finished prerequisites of target file 'default'.

> Only adding 'MAKEFLAGS += --warn-undefined-variables' is somewhat
> helpful.

You should feel free to do that, if your makefiles are written such
that it doesn't give spurious warnings.  Make has silently expanded
empty variables to the empty string for 40 years and changing that as
the default behavior is not an option.



Re: Regression on Cygwin: Problems with parallel make in 4.4

2023-02-24 Thread Paul Smith
On Thu, 2023-02-23 at 16:17 -0500, Ken Brown wrote:
> I'm attaching that script so you can see exactly how "make" is
> invoked in a subshell.  I'm also attaching my build log up to the
> point of the warning and the Makefile in the ft-build directory in
> which the warning occurred.  I've previously sent you the top-level
> Makefile.
> 
> Let me know if you need anything else.

The ft-build/Makefile is not the interesting one: by the time make is
invoked here it already has the bad arguments.

The makefile we want is the one that invoked this make, with the bad
arguments; from your build:

  make[3]: Entering directory 
'/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2'
  rm -rf ft-build
  /usr/bin/mkdir -p ft-build
  cd ft-build && \
CC='gcc' CONFIG_SITE=/dev/null CONFIG_SHELL='/bin/sh' \
/bin/sh 
/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/../../../libs/freetype2/freetype-src/configure
 \
   --disable-shared \
  --without-bzip2 \
  --without-brotli \
  --without-harfbuzz \
  --without-png \
  --without-zlib \
  
--prefix=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/ft-install \
  --libdir=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2 \
  --includedir=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2

so, the makefile we want is the makefile in freetype2 that contains the
recipe that invokes the make command in the ft-build subdirectory.



Re: $(wildcard ...*/) and symlinks

2023-02-24 Thread Dmitry Goncharov
On Fri, Feb 24, 2023 at 6:55 AM Frank Heckenbach
 wrote:
...
> So "*/" ignores the symlink to a file as expected, but "l*/" does
> return it, likewise "*/*/" which doesn't make much sense to me.

There is a known bug in glibc glob impl.

$ ls
makefile
$ cat makefile
all:; $(info $(wildcard hell*/))
$ touch hello
$ ls hell*/
ls: cannot access 'hell*/': No such file or directory
$ make
hello
make: 'all' is up to date.

The current impl of glob handles trailing slashes correctly on certain
filesystems and fails on others.
See https://lists.gnu.org/archive/html/bug-gnulib/2019-11/msg6.html

regards, Dmitry



Re: Regression on Cygwin: Problems with parallel make in 4.4

2023-02-24 Thread Ken Brown

On 2/24/2023 9:54 AM, Paul Smith wrote:

On Thu, 2023-02-23 at 16:17 -0500, Ken Brown wrote:

I'm attaching that script so you can see exactly how "make" is
invoked in a subshell.  I'm also attaching my build log up to the
point of the warning and the Makefile in the ft-build directory in
which the warning occurred.  I've previously sent you the top-level
Makefile.

Let me know if you need anything else.


The ft-build/Makefile is not the interesting one: by the time make is
invoked here it already has the bad arguments.

The makefile we want is the one that invoked this make, with the bad
arguments; from your build:

   make[3]: Entering directory 
'/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2'
   rm -rf ft-build
   /usr/bin/mkdir -p ft-build
   cd ft-build && \
 CC='gcc' CONFIG_SITE=/dev/null CONFIG_SHELL='/bin/sh' \
 /bin/sh 
/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/../../../libs/freetype2/freetype-src/configure
 \
--disable-shared \
   --without-bzip2 \
   --without-brotli \
   --without-harfbuzz \
   --without-png \
   --without-zlib \
   
--prefix=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/ft-install \
   --libdir=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2 \
   --includedir=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2

so, the makefile we want is the makefile in freetype2 that contains the
recipe that invokes the make command in the ft-build subdirectory.


OK, I hope I'm attaching the right one now.

I thought it might also help for me to send a complete recipe for 
reproducing the problem rather than just sending bits and pieces.  The 
recipe is adapted from


  https://www.tug.org/texlive/build.html

1. git clone https://github.com/TeX-Live/texlive-source.git

2. cd texlive-source

3. TL_MAKE_FLAGS="-j13" ./Build

The build is then done in texlive-source/Work, which also contains a log 
file "build.log".  On my system the jobserver warning appears after 
about 10 minutes and is in line 2074 of build.log.  I'm using make 
4.4.0.91 patched with commit 8b8cc3a825b0e9e176db5d90084c814e3744a300.


Ken

# Makefile.in generated by automake 1.16.5 from Makefile.am.
# Makefile.  Generated from Makefile.in by configure.

# Copyright (C) 1994-2021 Free Software Foundation, Inc.

# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.



VPATH = ../../../libs/freetype2
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
false; \
  elif test -n '$(MAKE_HOST)'; then \
true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
  else \
false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
  ?) ;; \
  *) echo "am__make_running_with_option: internal error: invalid" \
  "target option '$${target_option-}' specified" >&2; \
 exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
  else \
case $$MAKEFLAGS in \
  *\\[\ \   ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
  | sed "s/$$bs$$bs[$$bs $$bs   ]*//g"`;; \
esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
  *=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
  -*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
  -*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
  -*l?*) strip_trailopt 'l';; \
  -[dEDm]) skip_next=yes;; \
  -[JT]) skip_next=yes;; \
esac; \
case $$flg in \
  *$$target_option*) has_opt=yes; break;; \
esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/freetype--tex-live-
pkgincludedir = $(includedir)/freetype--tex-live-
pkglibdir = $(libdir)/freetype--tex-live-
pkglibexecdir = $(libexecdir)/freetype--tex-live-
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
subdir = .
ACLOCAL_M4 = $(top_srcdir)/ac

Re: Regression on Cygwin: Problems with parallel make in 4.4

2023-02-24 Thread Paul Smith
On Thu, 2023-02-23 at 16:17 -0500, Ken Brown wrote:
> Sorry, I spoke too soon.  I just went back to my original use case,
> in which I used the TeX Live "Build" script instead of directly
> invoking make, and I again got the jobserver warning.

Thanks for the info.

TL;DR: this is not an error in make :)

This warning is happening because the freetype2 configure script itself
is invoking make.

So the freetype2/Makefile contains this rule:

  ft-config:
rm -rf ft-build
$(MKDIR_P) ft-build
cd ft-build && \
  CC='$(CC)' CONFIG_SITE=/dev/null CONFIG_SHELL='$(SHELL)' \
  $(SHELL) $(abs_srcdir)/$(FREETYPE_TREE)/configure \
$(config_args) --disable-shared \
--without-bzip2 \
--without-brotli \
--without-harfbuzz \
--without-png \
--without-zlib \
--prefix=$(abs_builddir)/ft-install \
--libdir=$(abs_builddir) \
--includedir=$(abs_builddir)
echo timestamp >ft-config

This rule does not appear to invoke make (doesn't contain $(MAKE) or
${MAKE}) and it does not use a "+" prefix, so make believes that this
recipe is not a recursive make invocation, and it disables the
jobserver before invoking this recipe.

But we can see from the output that the recursive make invocation
happens in the configure script:

  /usr/bin/mkdir -p ft-build
  cd ft-build && \
CC='gcc' CONFIG_SITE=/dev/null CONFIG_SHELL='/bin/sh' \
/bin/sh 
/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/../../../libs/freetype2/freetype-src/configure
 \
   --disable-shared \
  --without-bzip2 \
  --without-brotli \
  --without-harfbuzz \
  --without-png \
  --without-zlib \
  
--prefix=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/ft-install \
  --libdir=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2 \
  --includedir=/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2
  Copying documentation assets
  cp: cannot stat 
'/home/kbrown/src/texlive/test.x86_64/libs/freetype2/freetype-src/docs/markdown':
 No such file or directory
  Copying `modules.cfg'
  Generating `Makefile'
  make[4]: Entering directory 
'/home/kbrown/src/texlive/test.x86_64/Work/libs/freetype2/ft-build'
  make[4]: not recursive -2,-2
  make[4]: warning: jobserver unavailable: using -j1.  Add '+' to parent make 
rule.

So, if you go get the freetype2/configure script and investigate its
contents, you'll find this:

  CFG=$CFG $MAKE setup unix

This invokes make, and it's THIS invocation of make which is printing
that message, and the message is absolutely correct: the jobserver WAS
de-activated because the "recipe" (the thing that invoked configure)
was not a recursive invocation.

You have a number of options here:

- You can ignore the message since it doesn't make any difference.

- You can add a "+" prefix to the configure script in the ft-config
target's recipe in the freetype2/Makefile to explicitly tell make that
this recipe is a recursive make.

You can add a spurious reference to "$(MAKE)", like:

  ft-config:
rm -rf ft-build
$(MKDIR_P) ft-build
cd ft-build && : '$(MAKE)' && \
   ^^
  CC='$(CC)' CONFIG_SITE=/dev/null CONFIG_SHELL='$(SHELL)' \
  $(SHELL) $(abs_srcdir)/$(FREETYPE_TREE)/configure \
...
echo timestamp >ft-config

to implicitly tell make that this recipe is a recursive make.

- You can remove all the MAKEFLAGS before you invoke configure:

  ft-config:
rm -rf ft-build
$(MKDIR_P) ft-build
cd ft-build && : '$(MAKE)' && \
  CC='$(CC)' CONFIG_SITE=/dev/null CONFIG_SHELL='$(SHELL)' \
  MAKEFLAGS= $(SHELL) $(abs_srcdir)/$(FREETYPE_TREE)/configure \
  ^^
...
echo timestamp >ft-config

- You could also file a bug against freetype2 and suggest that they
themselves unset MAKEFLAGS in their configure script, since it's very
unusual for a configure script to invoke make:

  CFG=$CFG MAKEFLAGS= $MAKE setup unix

This issue is one of the reasons we switched to named pipes: in that
mode there's no need to pass resources (like open file descriptors) to
sub-makes, and so we don't have to disable them.  We can just assume
that only a sub-make will parse the MAKEFLAGS and open the named pipe.



Re: VPATH question

2023-02-24 Thread Gisle Vanem

Paul Smith wrote:


If you use "-d" you'll get the info you want:

No implicit rule found for 'default'.
Considering target file 'lib'.
Finished prerequisites of target file 'lib'.
No need to remake target 'lib'; using VPATH name 'apps/lib'.
   Finished prerequisites of target file 'default'.


Only adding 'MAKEFLAGS += --warn-undefined-variables' is somewhat
helpful.


You should feel free to do that, if your makefiles are written such
that it doesn't give spurious warnings.  Make has silently expanded
empty variables to the empty string for 40 years and changing that as
the default behavior is not an option.


Ok thanks for the explanation. But I tend to use 'vpath %.c dir'
more and more. It seems a lot faster too.

--
--gv



Re: Regression on Cygwin: Problems with parallel make in 4.4

2023-02-24 Thread Ken Brown

On 2/24/2023 11:29 AM, Paul Smith wrote:

On Thu, 2023-02-23 at 16:17 -0500, Ken Brown wrote:

Sorry, I spoke too soon.  I just went back to my original use case,
in which I used the TeX Live "Build" script instead of directly
invoking make, and I again got the jobserver warning.


Thanks for the info.

TL;DR: this is not an error in make :)


That's a relief.  Thanks for the detailed explanation.

Ken



Re: VPATH question

2023-02-24 Thread Paul Smith
On Fri, 2023-02-24 at 17:40 +0100, Gisle Vanem wrote:
> Paul Smith wrote:
> > If you use "-d" you'll get the info you want:
> > 
> >  No implicit rule found for 'default'.
> >  Considering target file 'lib'.
> >  Finished prerequisites of target file 'lib'.
> >  No need to remake target 'lib'; using VPATH name 'apps/lib'.
> >     Finished prerequisites of target file 'default'.
> > 
> > > Only adding 'MAKEFLAGS += --warn-undefined-variables' is somewhat
> > > helpful.
> > 
> > You should feel free to do that, if your makefiles are written such
> > that it doesn't give spurious warnings.  Make has silently expanded
> > empty variables to the empty string for 40 years and changing that
> > as the default behavior is not an option.
> 
> Ok thanks for the explanation. But I tend to use 'vpath %.c dir'
> more and more. It seems a lot faster too.

In my opinion it's just not a good idea to use directories as
prerequisites in makefile rules, period, with only very specific,
limited exceptions.

But, I realize that I'm in the distinct minority in this opinion and
that all the "hot new makefiles" tend to do this.  I'll stick to my old
fuddy-duddy opinions however.  Keep those directories off my lawn!

As for "it seems a lot faster", I have no comment since you don't say
what it seems faster than.  If you mean that "vpath %.c dir" is faster
than "VPATH = dir", then that's not surprising since the latter
searches "dir" for every single prerequisite while the former only
searches for prerequisites that match the pattern.

If you mean it's faster than listing the full pathname explicitly as a
prerequisite, then I can't believe that's the case.

Cheers!