Filesystem Paths
Many of our build processes are made up of a mix of Cygwin tools (makepkg/bash forstarters) and native Windows tools. When building things the paths of input andoutput files and directories are often communicated between them via processarguments or environment variables. The problem here is that those are in manycases not compatible:
C:\nopeis not a valid Unix path and\nmight make problems when being interpreted as an escape sequence.C:/nopeis slightly better, because, while it's not a valid Unix path, if it's just forwarded to some other Windows tools things might work out fine./foois both a valid Windows path (drive relative path evaluating toC:\foofor example) and a valid Unix path, but resolves to a different path. Again, if it's just forwarded to some other Unix tool then things might work out fine.foo/bar.txtjust works, relative to the current working directory, whilefoo\bar.txtis only OK with native tools.- Path lists, commonly used in environment variables like
FOO=/foo:/baralso will never work, since paths are separated by;on Windows and not:, similarlyc:/foocould be interpreted as a Unix path list containingcand/foowhen a path list is expected.
The only solution here is to avoid mixing Unix/Cygwin and native tools outsideof makepkg (preferred) or convert them when they get passed between thedifferent programs. For the latter, MSYS2 provides an automatic conversion thatjust works automatically in many cases.
Manual Unix ⟷ Windows Path Conversion
MSYS2 ships the Cygwin toolcygpath by default which allows converting pathsbetween the Unix format, Windows format, and mixed format, seecygpath --helpfor details.
$cygpath-uC:\\foo/c/foo$cygpath-m/mingw64/binC:/msys64/mingw64/bin$cygpath-w/mingw64/binC:\msys64\mingw64\binAutomatic Unix ⟶ Windows Path Conversion
Process Arguments
When calling native executables from the context of Cygwin, then all thearguments that look like Unix paths will get auto converted to Windows. Forexample, when calling native Python from the context of bash:
$python3-c"import sys; print(sys.argv)"--dir=/foo['-c','--dir=C:/msys64/foo']$python3-c"import sys; print(sys.argv)"--dir=/foo:/bla['-c','--dir=C:\\msys64\\foo;C:\\msys64\\bla']While this is helpful in many cases, it's also not perfect and in corner casesconverts arguments that look like Unix paths while they are not, or detectslists of Unix paths where there are none. For these cases, you can excludecertain arguments via theMSYS2_ARG_CONV_EXCL environment variable:
$MSYS2_ARG_CONV_EXCL='--dir='python3-c"import sys; print(sys.argv)"--dir=/foo['-c','--dir=/foo']MSYS2_ARG_CONV_EXCL can either be* to mean exclude everything, or a list ofone or more arguments prefixes separated by;, likeMSYS2_ARG_CONV_EXCL=--dir=;--bla=;/test. It matches the prefix against thewhole argument string.
Environment Variables
Similar to process arguments, paths in environment variables get converted too:
$MYVAR=/foopython3-c"import os; print(os.environ['MYVAR'])"C:/msys64/foo$MYVAR=/foo:/barpython3-c"import os; print(os.environ['MYVAR'])"C:\msys64\foo;C:\msys64\barYou can disable the conversion withMSYS2_ENV_CONV_EXCL:
$ MSYS2_ENV_CONV_EXCL='MYVAR' MYVAR=/foo python3 -c "import os; print(os.environ['MYVAR'])"/fooMSYS2_ENV_CONV_EXCL can either be* to mean exclude everything, or a list ofone or more environment variable prefixes separated by;, likeMSYS2_ENV_CONV_EXCL=FOO;BAR;/test. It matches the prefix against the followingstringKEY=VALUE.
Cygwin treats certain environment variables that are known to be paths or path lists as special cases and does less guessing with them. For example,HOME will never be interpreted as a path list even if it contains:.
Windows ⟶ Unix Path Conversion
You might wonder why calling things likels C:/ might work and suspect thatagain auto conversion is used, but that's not the case:
$/usr/bin/python3-c"import sys, os; print(sys.argv, os.listdir(sys.argv[1]))"C:/['-c','C:/']['$Recycle.Bin','$SysReset',...]Cygwin which provides the POSIX API will just forward the paths to the WindowsAPI as is. This works as long as the tool does not try to interpret the path toomuch and just forwards it to the system API. If that doesn't work in your caseyou can usecygpath:
$/usr/bin/python3-c"import sys, os; print(sys.argv, os.listdir(sys.argv[1]))""$(cygpath-uC:/)"['-c','/c/']['$Recycle.Bin','$SysReset',...]