Re: Handling '=' in a filename together with $(eval )

Alejandro Colomar <[email protected]> Thu, 13 Feb 2025 16:24:17 +0100
Newsgroups gmane.comp.gnu.make.general
Message-ID <wmdwzehboiugdyzhwq52bwpwx6m7kapbahkrrcvists7zu5p2v@o76jy46ime32>
Hi Paul,

On Thu, Feb 13, 2025 at 10:08:36AM -0500, Paul Smith wrote:
> On Thu, 2025-02-13 at 15:46 +0100, Alejandro Colomar wrote:
> > I'm trying to find a way to correctly handle files with a '=' in
> > their name with make(1).  I know I'm doing something in the edge of
> > what's possible, so the answer may very well be "you can't", but if
> > it's possible, I'd like to learn how.  The reason is that the file
> > exists in another project, and I'd like to use it with my Makefile; I
> > can't fix the filename.
> 
> The correct way to handle most special characters in makefile syntax is
> to hide them behind a make variable.

I'm aware of that trick.  However, I think it won't work for me, since
I don't hardcode the filenames in the Makefile, but get them with

	$(shell find ...)

instead.

Here's the commit that I applied when I added support for ':', so that
you see the real Makefile code I'm talking about:

<https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=8a135d7703fa82e9b442ea3c3b1e9d119b25660a>
	commit 8a135d7703fa82e9b442ea3c3b1e9d119b25660a
	Author: Alejandro Colomar <[email protected]>
	Date:   Wed Apr 26 01:39:22 2023 +0200

	    *.mk: Handle pathnames with ':'
	    
	    Since make(1) uses ':' as a special character in rules, it needs to be
	    handled carefully.  A way to make it work is to escape it with '\:'.  We
	    can use sed(1) to do that right when we get the pathnames.  The only
	    problem with ':' is in rules' targets and prerequisites: everywhere else
	    it's fine; so let's discuss what needs to be done in those places:
	    
	    -  In the targets, it's as easy as escaping.
	    
	    -  In prerequisites, we can't second-expand variables containing such
	       pathnames, as the '\' would not be used by make(1) to escape the ':',
	       but it would be interpreted as part of the pathname.  This means we
	       need to expand rules written using second expansion into several
	       rules that only expand their variables once.
	    
	    -  $(wildcard ...) also performs the escape, so after using it the
	       pathnames are not escaped.  If we used those variables in targets, we
	       would need to escape the ':'s again, but since we don't we can skip
	       that.  The trick to make this work is to second-expand these
	       variables.
	    
	    Link: <https://stackoverflow.com/a/76096683/6872717>
	    Cc: GNU Make <[email protected]>
	    Signed-off-by: Alejandro Colomar <[email protected]>

> This works:
> 
>   EQ = =
> 
>   all: foo$(EQ)bar
> 
>   foo$(EQ)bar: ; @echo $@
> 
> gives:
> 
>   foo=bar

Hmmm, it seems it doesn't work with $(eval ...).  I do need to $(eval ).

	alx@devuan:~/tmp/symbolds$ cat Makefile 
	EQ = =
	obj := obj/asd$(EQ)fgh

	all: $(obj)

	$(info $(obj) : obj/% : src/%)
	$(eval $(obj) : obj/% : src/%)

	$(obj):
		touch $@
	alx@devuan:~/tmp/symbolds$ make
	obj/asd=fgh : obj/% : src/%
	touch obj/asd=fgh
	touch: cannot touch 'obj/asd=fgh': No such file or directory
	make: *** [Makefile:10: obj/asd=fgh] Error 1

> 
> This works because make will chop up a line into sections before it
> expands variables.

Here's the exact $(eval) code I need to use:

$(foreach s, $(MANSECTIONS),                                                  \
	$(eval MAN$(s)PAGES :=                                                \
		$(filter-out $(MANINTROPAGES),                                \
			$(filter $(MAN$(s)DIR)/%,                             \
				$(filter %.$(s),                              \
					$(MANPAGES))))))

That code allows me to generate one variable per directory that I find
under man/.  That means that if I run my build system on a system with
man10/, even if I didn't anticipate that directory, it will work.

If I find out that it's impossible to make it work, I guess I'll
hard-code the subdirectories instead of this eval loop.  That would
probably make it work.

Thanks for the help!


Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEE6jqH8KTroDDkXfJAnowa+77/2zIFAmeuDqEACgkQnowa+77/
2zLmBhAAn9PeuT/Ii+Ab0A4NjEc3gnA5LccRKDcARreRVXzrlAx7p7bsJF1feVrP
z5uB8j6wRjL0eytHr+VLm8YeUFGTvb27QgOn0V73DKNM8PJMHNX1MkWWhGzjISPz
pC1dS03SRu8EzkGN+FrrnnMHydki4P+E2Y6gCHY9bpOZ2kcR/DaSbU/wPjlHmTya
3/NkH38j7FFRFagvAMm0PEx+qF8ebcZVxRFgBRs9+iOf8vyxHJjsaafg06ijvzqn
uhy2jYqqhctHHM1WsL8H0+PXa9RCXDowRHGqUiWjijEpe8gurQz6PPfiYF4BeIL/
D+OB4Z/HPY7r9iwI34exw9QrluyX0DKm9UCY7r9mv1f6NRFKy+vI3EiwDfYCWUiR
zsFgON15IhNjICPmIokxkb3YpHSdnnX9eHV3fKIz215POWOFQ2K5yeEjdxD1h2OZ
6KkwpOITkZdVX1GOsGRjajSBmrTFz3+UJVCu3rWfO7vkZLMtvtU9N/nm5XtEYi5N
2dIZupTHa6iZgta6epleRd6V+npowP8vccO1DvLNcma3KIPnVJ2qpVvibGtTS0Ig
fjA1AL/8SEysH8Mq5PbTLNJbwWElocbvuvqfIdUcUnyTb/A2tJmO3UMdTDN03qaE
Yh3NjPPkxeV5OFG5mRU3hAb3USt84k3dzRysD81fXwHjay0f2cI=
=Zs0q
-----END PGP SIGNATURE-----