#! /usr/bin/env bash
# Note: shouldn't be executed directly, src_dir must be set.
# Common cl.exe driver that expects the VCBIN, INCLUDE, and, if running as a
# linker, SDKBIN, LIB variables to be set for the specific MSVC
# version/configuration.
trap "{ exit 1; }" ERR
set -o errtrace # Trap in functions.
function info () { echo "$*" 1>&2; }
function error () { info "$*"; exit 1; }
source "$src_dir/msvc-common/msvc-common"
# File descriptor where the diagnostics will be sent. Unless STDOUT is used
# for something else (e.g., /E), cl.exe sends the diagnostics there.
# Otherwise it goes to STDERR.
#
diag=1
# Translate absolute paths from POSIX to Windows. Use bash array to store
# arguments in case they contain spaces.
#
# This needs to be done for both certain option values and arguments.
# Arguments are tricky in that unless we recognize every option, and option
# may look a lot like an absolute POSIX path (e.g., /nologo). The heuristics
# that we are going to use here is that if the argument starts with / and
# contains at least one more /, then we consider it an argument. Otherwise --
# an options. We will also explicitly recognize certain options, like /D,
# which may not fit this scheme well.
#
# Note that the order of the cases is important. Specifically, we want, e.g.,
# /D before /D*.
#
# Note also that cl.exe options are case-sensitive.
#
args=()
while [ $# -gt 0 ]; do
case $1 in
# /I
, /AI
#
[/-]I | \
[/-]AI)
args=("${args[@]}" "$1")
shift
args=("${args[@]}" "$(translate $1)")
shift
;;
# /I
#
[/-]I*)
args=("${args[@]}" "$(split_translate 2 $1)")
shift
;;
# /AI
#
[/-]AI*)
args=("${args[@]}" "$(split_translate 3 $1)")
shift
;;
# /F*:
#
[/-]F[adeimoprR]:)
args=("${args[@]}" "$1")
shift
args=("${args[@]}" "$(translate $1)")
shift
;;
# /F*, /T{p,c}, /Yu.
#
[/-]F[adeimoprRUI]* | \
[/-]Tp* | \
[/-]Tc* | \
[/-]Yu*)
args=("${args[@]}" "$(split_translate 3 $1)")
shift
;;
# /doc
#
[/-]doc*)
args=("${args[@]}" "$(split_translate 4 $1)")
shift
;;
# @
#
@*)
args=("${args[@]}" "$(split_translate 1 $1)")
shift
;;
# Handle other options with separate values. This makes sure we don't try
# to path-translate them.
#
[/-]D | \
[/-]U | \
[/-]link)
args=("${args[@]}" "$1")
shift
args=("${args[@]}" "$1")
shift
;;
# Handle other options with combined values that could possibly be
# interpreted as paths, for example /DFOO=foo/bar.
#
[/-]D* | \
[/-]V* | \
[/-]Yl*)
args=("${args[@]}" "$1")
shift
;;
# Detect /E and /EP -- they change where the diagnostics is sent.
#
[/-]E | \
[/-]EP)
diag=2
args=("${args[@]}" "$1")
shift
;;
# Option or argument.
#
*)
# If contains at least two slashes, treat it as a path.
#
if [[ "$1" == /*/* ]]; then
args=("${args[@]}" "$(translate $1)")
else
args=("${args[@]}" "$1")
fi
shift
;;
esac
done
export INCLUDE
export LIB
# The linker may need to run mt.exe which is in the SDK.
#
export WINEPATH="$VCBIN;$VCDLL;$SDKBIN"
msvc_exec $diag "$VCBIN\\cl.exe" "${args[@]}"