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