windowsbashcygwinmsys

Why doesn't MSYS Bash evaluate windows exectuable commands as expected?


I've run into a weird behaviour (as usual) where I'm trying to use a Windows executable in a (MSYS) Bash alias, to execute command and handle the results.

The Windows program in question is dumpbin.exe as part of the VS tools, and can be found in the version dependent location:
'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\.

Here is what I am trying to do:

dumpbin /dependents some.exe

So I created a Bash function like this:

function show_deps () {
    local DBPATH='C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\'
    "${DBPATH}"/dumpbin.exe /dependents /nologo $1
}

# show_deps some.exe

Dump of file C:\msys64\dependents
LINK : fatal error LNK1181: cannot open input file 'C:\msys64\dependents'

So the command runs, but no matter what I try the argument always become "\dependents". So then I thought to try using the eval command:

DBPATH='/c/Program\ Files/Microsoft\ Visual\ Studio/2022/Community/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/dumpbin.exe'

EXE_ARGS="/dependents /nologo some.exe"; eval "${DBPATH} ${EXE_ARGS}"

# Again same issue: 
...
Dump of file C:\msys64\dependents
LINK : fatal error LNK1181: cannot open input file 'C:\msys64\dependents'

# So I try without the argument: 
EXE_ARGS="some.exe"; eval "${DBPATH} ${EXE_ARGS}"
...
Dump of file some.exe

File Type: EXECUTABLE IMAGE

  Summary

        3000 .bss
        1000 .buildid
        1000 .data
        3000 .debug_abbrev
...
# OK!

So the command works, but not with arguments!

Now here comes the killer... In Cygwin (with an older Bash version) the same function works!

function show_deps () {
    local DBPATH='C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\'
    "${DBPATH}"/dumpbin.exe /dependents /nologo $1
}

# show_deps some.exe

Dump of file some.exe

File Type: EXECUTABLE IMAGE

  Image has the following dependencies:

    cygconfuse-1.dll
    cygwin1.dll
    KERNEL32.dll

  Summary

        3000 .bss
        1000 .buildid
        1000 .data
        3000 .debug_abbrev
        1000 .debug_aranges
        2000 .debug_frame
       13000 .debug_info
        5000 .debug_line
        2000 .debug_line_str
        1000 .debug_loclists
        1000 .debug_rnglists
        1000 .debug_str
        1000 .idata
        1000 .pdata
        3000 .rdata
        1000 .reloc
        1000 .rsrc
        C000 .text
        1000 .xdata

How can I make this work in MSYS bash?
Can anyone explain what's going on here?

PS. This is completely different to the suggested related question about using git-bash in AWS. This is an MSYS and Cygwin implementation difference.


Solution

  • Embarrassingly, it appears that the default Bash settings in MSYS and Cygwin are interpreting / differently. Most likely because Cygwin accepts Windows paths (C:\the\path) to a certain extent, whereas MSYS does not at all, and a purely relying on POSIX paths, i.e. /the/path.

    After a lot of trial-and-error, and also suggested by Philippe, I found out that the forward slash needed to be doubled. I still don't understand exactly why, because I also tried enclosing it in single quites (') which should never be interpreted in any way after variable expansion, so it is happening somewhere else.

    This works as expected:

    DBPATH='/c/Program\ Files/Microsoft\ Visual\ Studio/2022/Community/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/dumpbin.exe' 
    EXE_ARGS=" //dependents //nologo some.exe"
    eval "${DBPATH} ${EXE_ARGS}"
    
    # This also works!
    # Notice removal of backslashes and change of quotes:
    DBPATH='/c/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/dumpbin.exe'
    "${DBPATH}" ${EXE_ARGS}
    

    PS. I'm happy to accept an alternative answer if there's some better explanation on this difference.