lmi
[Top][All Lists]
Advanced

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

Re: [lmi] Copying compiler run-time files in the makefiles


From: Greg Chicares
Subject: Re: [lmi] Copying compiler run-time files in the makefiles
Date: Thu, 21 Jul 2022 15:02:27 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.0

[...I've very slowly popping a stack of half-written replies...]

On 6/28/22 13:47, Vadim Zeitlin wrote:
> On Tue, 28 Jun 2022 00:23:15 +0000 Greg Chicares <gchicares@sbcglobal.net> 
> wrote:
> 
> GC> On 6/27/22 20:45, Vadim Zeitlin wrote:
> GC> [...]
> GC> > I am not sure I
> GC> > understand why should build_dir depend on $(gpl_files)
> GC> 
> GC> $(build_dir) is a prerequisite for everything:
> GC> 
> GC> % :: $(build_dir) ; @:
> 
>  Ah, I've missed this, sorry. But it's still not totally clear to me how
> does this work because, quoting GNU make manual[1]:
> 
>       One choice is to mark the match-anything rule as terminal by
>       defining it with a double colon. When a rule is terminal, it does
>       not apply unless its prerequisites actually exist. Prerequisites
>       that could be made with other implicit rules are not good enough.
>       In other words, no further chaining is allowed beyond a terminal
>       rule. 
> 
> Doesn't this mean that $(build_dir) must already exist for this to work?

I was going to respond claiming that $(build_dir) is a target here,
rather than a prerequisite, but that would have been incorrect.

Applying the terminological example from section 2.1:

  target … : prerequisites …
          recipe

to the rule at hand:

  % :: $(build_dir) ; @:

the 'target' is "%"; "$(build_dir)" is a prerequisite; and the recipe
is apparently "; @:", which I don't quite understand, though I'm pretty
sure it does nothing. Normally, ";" would suffice for doing nothing.
The "@:" looks like it might mean something special to 'make', but I
can't find it in the manual, so I think the recipe is the shell command
':', and the "@" prefix tells make not to print that shell command.

So your question is deep, at least from my perspective. Stepping back
to include more context...

.PHONY: $(build_dir)
$(build_dir): $(gpl_files)
        +@[ -d $@                 ] || $(MKDIR) --parents $@
[...]
% :: $(build_dir) ; @:

I believe the resolution is that the .PHONYness of $(build_dir)
creates an implicit exception to the paragraph quoted from the
manual, which might be amended thus:

   One choice is to mark the match-anything rule as terminal by
   defining it with a double colon. When a rule is terminal, it does
-  not apply unless its prerequisites actually exist. Prerequisites
+  not apply unless its prerequisites actually exist (or are .PHONY,
+  in which case they are deemed not to name a real file). Prerequisites
   that could be made with other implicit rules are not good enough.
   In other words, no further chaining is allowed beyond a terminal
   rule.

But I think it's clear that the answer to your question is "No":
the build directory needn't already exist. Indeed, 'make clean'
removes the build directory, and it always gets recreated.

> GC> I'll try to specify the desired behavior here, in case you can see a
> GC> better way to accomplish it. To run any msw binary, the compiler runtime
> GC> libraries must be on $WINEPATH; specifically, $localbindir must contain
> GC> copies of them.
> 
>  Sorry but I have to point that the implication indicated by the use of
> semicolon here is not correct. You could also just add the directory
> containing the files to WINEPATH, which is what I typically do and which
> seems both simpler and more robust to me.

Okay, so you'd add something like this to $WINEPATH:
  /usr/lib/gcc/x86_64-w64-mingw32/10-win32/
(not tested, but that's what 'mlocate' suggests)--i.e., the place
where 'apt' put it. The canonical way to get that is:

  $ dirname $(x86_64-w64-mingw32-g++ -print-libgcc-file-name)
  /usr/lib/gcc/x86_64-w64-mingw32/10-win32
And
 "/usr/lib/gcc/x86_64-w64-mingw32/10-win32//libgcc_s_seh-1.dll \
  /usr/lib/gcc/x86_64-w64-mingw32/10-win32//libstdc++-6.dll "
is the makefile variable $(compiler_runtime_files). [It's all one
line; I split it here to make the compiler sysroot part line up.]

Yes, we could do that instead. If the goal is to make msw binaries
run on the machine where they're built, then that is indeed simpler.
But what's even more important is:
  https://en.wikipedia.org/wiki/Eating_your_own_dog_food
in order to be sure the binaries we test correspond closely to the
files we distribute. Otherwise, we might get an unnoticed dependency
on some file in the compiler sysroot other than the two named above,
and that could cause breakage for end users only.

>  Of course, you still need to include these DLLs in the binary distribution
> of lmi, but this is something different.

Okay, $(compiler_runtime_files) remains necessary for making fardels,
but fardels are made only in submakefile 'workhorse.make', and a
command like 'install -m $(compiler_runtime_files)" could be specified
as just another rule in the recipe. Then commit ceb0ac3bb13 would be
unnecessary, and the makefiles could be less ugly.

But I still think it's more important for us to eat our own dogfood.

> On Tue, 28 Jun 2022 11:32:58 +0000 Greg Chicares <gchicares@sbcglobal.net> 
> wrote:
[...]
> GC> AFAICS, the strategy now in HEAD is optimal despite its ugliness.
> 
>  It's fine, I guess, but it still seems unnecessarily complicated compared
> to just setting WINEPATH to me.

Okay, then it's not optimal, at least not in all ways.

> GC> Let me mention the reasons for a couple of particulars:
> GC>  - The 'install' command uses a shell for-loop, because
> GC>    $(compiler_runtime_files) might be empty, and I see no
> GC>    better way to deal with that possibility.
> 
>  The old (removed in the above-mentioned 19c09468c8) idea of simply using
> 
>       @[ -z "$(compiler_runtime_files)" ] || cp ...
> 
> seems better to me because it's both more clear (i.e. you can see at a
> glance that the possibility of compiler_runtime_files being empty has been
> considered and handled, instead of wondering whether it's normal for it to
> be empty) and uses one cp command instead of N calls to it. But it's hardly
> critically important, of course.

Yet commit f760e3df2823 says:

    running `make -n fardel` through shellcheck elicits:
      SC2157: Argument to -z is always false due to literal strings.
    for the controlling condition here:
      [ -z "$(compiler_runtime_files)" ]
    because of a trailing blank.

There's a trailing blank because of this definition:
  compiler_runtime_files := \
    $(wildcard $(compiler_sysroot)/libgcc*.dll) \
    $(wildcard $(compiler_sysroot)/libstdc++*.dll) \
That's how I like to define 'make' variables, and I don't want to
change it in a special case that I might break later. I could use
'sed' to remove extraneous leading or trailing spaces, but that
seems worse than the for-loop. I could try '${param// }', but
that's a ksh-ism that's not POSIX, and $(compiler_runtime_files)
is a 'make' variable anyway. Maybe
      [ -z "$(strip $(compiler_runtime_files))" ]
would work (although I'm not sure I can do that in a recipe), but
then I'd want to explain why the $(strip ...) function is used.

I think I'll just leave well enough alone.


reply via email to

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