msys path conversion (or cygpath for msys?)

Viewed 26845

I need to pass /DEF:c:\filepath\myLib.def" command line option from a bash script to MS compiler/linker. The path is generated as part of build process by a bash script. Basically, the argument that my script passes is:

-DEF:/c/filepath/myLib.def

MSYS path conversion can't handle it properly because it doesn't understand /DEF: part. It works if I do

-DEF=/c/filepath/myLib.def

but then ms tools don't understand this parameter. In short, what's the proper way to write that parameter in MSYS bash so that it converts it to proper argument?

On cygwin I could use cygpath, but there is no equivalent, because somebody from msys thinks that it's not needed (even if there are scripts for cygwin that uses cygpath).

9 Answers

nearly pure GNU bash solution (which is what you commonly run in MSYS) (interestingly not working with MSYS2, leave a comment if you know why):

#!/bin/bash

# check if we have cygpath (cygwin, newer MSYS2), then just use that 
which cygpath 1>/dev/null 2>&1
[[ $? = 0 ]] && (cygpath -wa "$1"; exit $?)

# check if it looks like a Windows path, in which case we directly convert and exit
[[ ${1} =~ ^[a-zA-Z]: ]] && \
  echo "${1}" | sed -e 's|/|\\|g' -e 's/\(.\)/\u\1/' && exit 0

# split first path entry (if any) with trailing slash and filename
[[ ${1} =~ ^\([/a-zA-Z0-9_.-]\\w*/\)?\(.*\)$ ]]

chk_root="${BASH_REMATCH[1]}"
chk_rest="${BASH_REMATCH[2]}"

# check if the root path exists and more important: let pwd binary resolve the translation according to the mount
chk_winroot="$(cd "${chk_root}." 2>/dev/null && pwd -W)"
[[ "${chk_winroot}" == "" ]] && echo "${chk_root}: No such file or directory" && exit 1

# using substition to replace all / by \ and uppercasing the first character
# pure bash solution; sadly: the first part needs a newer bash than old MSYS have ...
# chk_drv="${chk_winroot:0:1}"
# chk_all="${chk_winroot:1}/${chk_rest}"
# echo "${chk_drv^^}${chk_all//\//\\}"

# ... so fallback to GNU sed
echo "${chk_winroot}/${chk_rest}" | sed -e 's|/|\\|g' -e 's/\(.\)/\u\1/'

There's still an issue with it: if MinGW's fstab contains an entry like /mnt/c the pwd -W of /mnt/. done in this script won't work.
To fix it: replace pwd -W by inspecting $ cat /etc/fstab | cut -d'#' -f1 | grep -v "^\s*$" entries manually and replace the first match - while this will never work for cygwin or msys2 which use a different format this is covered by using cygpath there.

Related