help-make
[Top][All Lists]
Advanced

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

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


From: Alejandro Colomar
Subject: Re: Handling '=' in a filename together with $(eval )
Date: Thu, 13 Feb 2025 16:24:17 +0100

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 <alx@kernel.org>
        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 <bug-make@gnu.org>
            Signed-off-by: Alejandro Colomar <alx@kernel.org>

> 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/>

Attachment: signature.asc
Description: PGP signature


reply via email to

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