Subject: Re: setting $MSYS2_ARG_CONV_EXCL in compile script?

From: Bruno Haible <[email-masked]>
Date: Sun, 02 Feb 2025 16:10:22 +0100

Karl Berry wrote:
> Kirill (cc'd) proposed setting the MSYS2_ARG_CONV_EXCL envvar in the
> compile script which comes from Automake, to avoid a double-conversion.
> See his report in the first msg here, and the final suggestion in the last:
> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75939
> 
> I don't know anything about this. I've never done any programming under
> Windows, or msys, cygwin, wine, or any other Unix emulator under Windows.
> 
> So I wanted to ask for advice before tinkering with something as basic
> as the compile script in this way. Especially since it currently does
> not set any environment variables.
> 
> So ... I'm hoping for feedback like "yeah sure", or "no, we should do
> xyz instead", or "the problem is actually abc", or something. Since no
> feedback was forthcoming on the automake list, I'm trying here.
> 
> And if we do apply it, then where? In this branch?
> 	cygwin/* | msys/*)
> 	  file=`cygpath -m "$file" || echo "$file"`
> 
> But I fear this will cause trouble on cygwin. But if we separate the
> branches, then it seems like other trouble could ensue. Setting it
> unconditionally in all cases seems unnecessarily global to me, though
> maybe that is the simplest.

Table of contents:
* Cygwin vs. MSYS2
* Nature of the MSYS2 problem
* General recommendation
* Specific proposal

* ========== Cygwin vs. MSYS2

MSYS2_ARG_CONV_EXCL is documented in
https://www.msys2.org/docs/filesystem-paths/#process-arguments
Quote:
  "When calling native executables from the context of [MSYS] then all the
   arguments that look like Unix paths will get auto converted to Windows."

Cygwin and MSYS2 both are development environments for native Windows
programs on Windows. Cygwin passes argv[] from the caller to the callee
unmodified; MSYS2 modifies it, at every program invocation, based on
heuristics.

On Cygwin, therefore, it is the programmer's responsibility to use
'cygpath -w' at the appropriate places. Fortunately, there is a Gnulib
macro, build-to-host.m4, that makes this easy.

* ========== Nature of the MSYS2 problem

The MSYS2 problem is that it's a horrible hack that is based on a
heuristic: all arguments that "look like Unix paths" are modified.

The user can set MSYS2_ARG_CONV_EXCL to avoid this from happening
in 1, 2, 3, or 10 places. But it will never be 100% correct.

* ========== General recommendation

My general advice is:
  1) Recommend Cygwin, not MSYS2. Like I do in
     <https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob_plain;f=INSTALL.windows;hb=HEAD>
  2) Reduce the effort for GNU package upstream maintainers, by
     requesting a reasonably complete patch, not a piecemeal patch here
     and a piecemeal patch there.

* ========== Specific proposal

As for every bug report, the first action is to analyze the failure.
Here, the relevant lines of code in the 'compile' script are:

 	cygwin/* | msys/*)
 	  file=`cygpath -m "$file" || echo "$file"`

This is in function func_file_conv, which is used to produce arguments
for invocation of 'cl' (which is a native Windows program).

As documented in <https://cygwin.com/cygwin-ug-net/cygpath.html>,
"cygpath -m" produces file names like C:/Users/foobar/filename .
Some native Windows programs accept this syntax, some don't.
Therefore it is generally better to use "cygpath -w", which
produces file names like C:\Users\foobar\filename .
The *only* situation I've ever seen where "cygpath -m" is required
is when the callee is a shell script (with 'echo') that invokes
a Java program. (Example: IBM Application Server.)
Since the compiler called by 'compile' never is of this type, it is
better to use "cygpath -w".

Find attached a proposed patch. Tested on Cygwin with MSVC. Will work on
MSYS2 with MSVC as well.

Bruno
>From c0f453d1d2a52d21f24da17415de8ecbfbd19a3d Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email-masked]>
Date: Sun, 2 Feb 2025 15:40:20 +0100
Subject: [PATCH] compile: Improve support for C++ compilations on MSYS2.

Reported by Kirill Makurin <[email-masked]> in
<https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75939>.

* lib/compile (func_file_conv): Use 'cygpath -w', not 'cygpath -m'.
---
 lib/compile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/compile b/lib/compile
index 14aec5621..6f0e105a0 100755
--- a/lib/compile
+++ b/lib/compile
@@ -1,7 +1,7 @@
 #! /bin/sh
 # Wrapper for compilers which do not understand '-c -o'.
 
-scriptversion=2024-12-03.03; # UTC
+scriptversion=2025-02-02.14; # UTC
 
 # Copyright (C) 1999-2025 Free Software Foundation, Inc.
 # Written by Tom Tromey <[email-masked]>.
@@ -68,7 +68,7 @@ func_file_conv ()
 	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
 	  ;;
 	cygwin/* | msys/*)
-	  file=`cygpath -m "$file" || echo "$file"`
+	  file=`cygpath -w "$file" || echo "$file"`
 	  ;;
 	wine/*)
 	  file=`winepath -w "$file" || echo "$file"`
-- 
2.43.0