Skip to content

Instantly share code, notes, and snippets.

@dangfan
Created April 21, 2026 06:30
Show Gist options
  • Select an option

  • Save dangfan/70bb8dc938c30df60e59e619442b3882 to your computer and use it in GitHub Desktop.

Select an option

Save dangfan/70bb8dc938c30df60e59e619442b3882 to your computer and use it in GitHub Desktop.
cx-winpath-wrap
#!/bin/bash
set -euo pipefail
CX_ROOT="/Applications/CrossOver.app/Contents/SharedSupport/CrossOver/bin"
WINE="$CX_ROOT/wine"
BOTTLE="MDK"
EXE="${1:?missing exe path}"
shift || true
abs_path() {
python3 - "$1" <<'PY'
import os, sys
print(os.path.abspath(sys.argv[1]))
PY
}
to_winpath() {
python3 - "$1" <<'PY'
import os, sys
p = sys.argv[1]
p = os.path.abspath(p)
# Normalize and convert /foo/bar -> Z:\foo\bar
p = p.replace('/', '\\')
if not p.startswith('\\'):
p = '\\' + p
print('Z:' + p)
PY
}
convert_path() {
to_winpath "$1"
}
convert_arg() {
local arg="$1"
case "$arg" in
# -I/path
-I/*|-I./*|-I../*)
printf '%s%s\n' "-I" "$(convert_path "${arg:2}")"
return
;;
# -L/path
-L/*|-L./*|-L../*)
printf '%s%s\n' "-L" "$(convert_path "${arg:2}")"
return
;;
# -o/path/file
-o/*|-o./*|-o../*)
printf '%s%s\n' "-o" "$(convert_path "${arg:2}")"
return
;;
# -MF and its path (keep Unix format for dep file generation)
-MF|*.o.d)
printf '%s\n' "$arg"
return
;;
# --key=/path
--*=/*|--*=./*|--*=../*)
local key="${arg%%=*}"
local val="${arg#*=}"
printf '%s=%s\n' "$key" "$(convert_path "$val")"
return
;;
# 单独路径
/*|./*|../*)
printf '%s\n' "$(convert_path "$arg")"
return
;;
# Compiler definitions (-DFOO or -DFOO=VALUE) - never path-convert
-D*)
printf '%s\n' "$arg"
return
;;
# 常见文件参数,可能是相对路径
*.c|*.cc|*.cpp|*.cxx|*.h|*.hpp|*.s|*.S|*.asm|*.o|*.a|*.elf|*.axf|*.map|*.txt|*.lib|*.sct|*.hex|*.bin)
printf '%s\n' "$(convert_path "$arg")"
return
;;
*)
printf '%s\n' "$arg"
return
;;
esac
}
args=()
for a in "$@"; do
args+=("$(convert_arg "$a")")
done
# Run the compiler
"$WINE" --bottle "$BOTTLE" "$EXE" "${args[@]}"
compiler_exit=$?
# Post-process .d dependency files: convert Windows paths back to Unix
for a in "$@"; do
case "$a" in
-MMD|-MD)
# Find the dependency file name from -MF flag (Unix path from args)
dep_file=""
for ((i=0; i<${#args[@]}; i++)); do
if [[ "${args[$i]}" == "-MF" ]]; then
# -MF is a separate argument, dep file is next arg (Unix path)
dep_file="${args[$((i+1))]}"
break
fi
done
# Convert to absolute path for checking
if [[ -n "$dep_file" && "${dep_file:0:1}" != "/" ]]; then
dep_file_abs="$(pwd)/$dep_file"
else
dep_file_abs="$dep_file"
fi
# If we found a dependency file, convert paths using Python
if [[ -n "$dep_file_abs" && -f "$dep_file_abs" ]]; then
python3 - "$dep_file_abs" <<'PY'
import sys, re
with open(sys.argv[1], 'r') as f:
lines = f.readlines()
# Process each line: convert paths but preserve line endings
new_lines = []
for line in lines:
# Check if line ends with \r\n or just \n
if line.endswith('\\r\n'):
ending = '\r\n'
line = line[:-4]
elif line.endswith('\\\n'):
ending = '\n'
line = line[:-2]
else:
ending = ''
if line.endswith('\n'):
ending = '\n'
line = line[:-1]
# Convert Z:\path -> /path and \\ -> /, but preserve trailing \ for continuation
line = re.sub(r'Z:\\', '/', line)
line = re.sub(r'\\(?!\n|\r|$)', '/', line) # Don't convert trailing backslash
new_lines.append(line + ending)
with open(sys.argv[1], 'w') as f:
f.writelines(new_lines)
PY
fi
break
;;
esac
done
exit $compiler_exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment