Implement clang-target-wrapper as an executable for windows
This allows non-msys build systems to use the triplet prefixed compiler frontends on windows. Keep the old shell script version as well, for easier hackability on unix platforms.
This commit is contained in:
1 parent
9f3a4a25f2
commit
ad47efba70
3 files changed
+171
-1
No files matched your search
+16
-1
@@ -15,13 +15,28 @@ if [ -n "$HOST" ] && [ -z "$CC" ]; then
|
||||
fi
|
||||
: ${CC:=cc}
|
||||
|
||||
case $(uname) in
|
||||
MINGW*)
|
||||
EXEEXT=.exe
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p $PREFIX/bin
|
||||
cp wrappers/*-wrapper.sh $PREFIX/bin
|
||||
$CC wrappers/change-pe-arch.c -o $PREFIX/bin/change-pe-arch$EXEEXT
|
||||
$CC wrappers/clang-target-wrapper.c -o $PREFIX/bin/clang-target-wrapper$EXEEXT -O2 -Wl,-s
|
||||
if [ -n "$EXEEXT" ]; then
|
||||
# For Windows, we should prefer the executable wrapper, which also works
|
||||
# when invoked from outside of MSYS.
|
||||
CTW_SUFFIX=$EXEEXT
|
||||
CTW_LINK_SUFFIX=$EXEEXT
|
||||
else
|
||||
CTW_SUFFIX=.sh
|
||||
fi
|
||||
cd $PREFIX/bin
|
||||
for arch in $ARCHS; do
|
||||
for exec in clang clang++ gcc g++; do
|
||||
ln -sf clang-target-wrapper.sh $arch-w64-mingw32-$exec
|
||||
ln -sf clang-target-wrapper$CTW_SUFFIX $arch-w64-mingw32-$exec$CTW_LINK_SUFFIX
|
||||
done
|
||||
for exec in ar ranlib nm strings; do
|
||||
ln -sf llvm-$exec$EXEEXT $arch-w64-mingw32-$exec || true
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Martin Storsjo
|
||||
*
|
||||
* This file is part of llvm-mingw.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef UNICODE
|
||||
#define _UNICODE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#define EXECVP_CAST
|
||||
#else
|
||||
#include <unistd.h>
|
||||
typedef char TCHAR;
|
||||
#define _T(x) x
|
||||
#define _tcsrchr strrchr
|
||||
#define _tcschr strchr
|
||||
#define _tcsdup strdup
|
||||
#define _tcscpy strcpy
|
||||
#define _tcslen strlen
|
||||
#define _tcscmp strcmp
|
||||
#define _tperror perror
|
||||
#define _texecvp execvp
|
||||
#define _tmain main
|
||||
#define EXECVP_CAST (char **)
|
||||
#endif
|
||||
|
||||
int _tmain(int argc, TCHAR* argv[]) {
|
||||
const TCHAR *argv0 = argv[0];
|
||||
const TCHAR *sep = _tcsrchr(argv0, '/');
|
||||
if (!sep)
|
||||
sep = _tcsrchr(argv0, '\\');
|
||||
TCHAR *clang = _T("clang");
|
||||
const TCHAR *basename = argv0;
|
||||
if (sep) {
|
||||
int baselen = sep + 1 - argv0;
|
||||
clang = malloc((_tcslen(argv0) + 50) * sizeof(*clang));
|
||||
memcpy(clang, argv0, baselen * sizeof(*clang));
|
||||
_tcscpy(clang + baselen, _T("clang"));
|
||||
basename = sep + 1;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
TCHAR module_path[8192];
|
||||
GetModuleFileName(NULL, module_path, sizeof(module_path)/sizeof(module_path[0]));
|
||||
TCHAR *sep2 = _tcsrchr(module_path, '\\');
|
||||
if (sep2) {
|
||||
_tcscpy(sep2 + 1, _T("clang"));
|
||||
clang = module_path;
|
||||
}
|
||||
#endif
|
||||
basename = _tcsdup(basename);
|
||||
TCHAR *period = _tcschr(basename, '.');
|
||||
if (period)
|
||||
*period = '\0';
|
||||
TCHAR *dash = _tcsrchr(basename, '-');
|
||||
const TCHAR *target = basename;
|
||||
const TCHAR *exe = basename;
|
||||
if (dash) {
|
||||
*dash = '\0';
|
||||
exe = dash + 1;
|
||||
}
|
||||
TCHAR *arch = _tcsdup(target);
|
||||
dash = _tcschr(arch, '-');
|
||||
if (dash)
|
||||
*dash = '\0';
|
||||
|
||||
int max_arg = argc + 20;
|
||||
const TCHAR **exec_argv = malloc(max_arg * sizeof(*exec_argv));
|
||||
int arg = 0;
|
||||
if (getenv("CCACHE"))
|
||||
exec_argv[arg++] = _T("ccache");
|
||||
exec_argv[arg++] = clang;
|
||||
|
||||
// If changing this wrapper, change clang-target-wrapper.sh accordingly.
|
||||
if (!_tcscmp(exe, _T("clang++")) || !_tcscmp(exe, _T("g++")) || !_tcscmp(exe, _T("c++")))
|
||||
exec_argv[arg++] = _T("--driver-mode=g++");
|
||||
|
||||
if (!_tcscmp(arch, _T("i686"))) {
|
||||
// Dwarf is the default for i686, but libunwind sometimes fails to
|
||||
// to unwind correctly on i686. The issue can be reproduced with
|
||||
// test/exception-locale.cpp. The issue might be related to
|
||||
// DW_CFA_GNU_args_size, since it goes away if building
|
||||
// libunwind/libcxxabi/libcxx and the test example with
|
||||
// -mstack-alignment=16 -mstackrealign. (libunwind SVN r337312 fixed
|
||||
// some handling relating to this dwarf opcode, which made
|
||||
// test/hello-exception.cpp work properly, but apparently there are
|
||||
// still issues with it).
|
||||
exec_argv[arg++] = _T("-fsjlj-exceptions");
|
||||
} else if (!_tcscmp(arch, _T("x86_64"))) {
|
||||
// SEH is the default here.
|
||||
} else if (!_tcscmp(arch, _T("armv7"))) {
|
||||
// Dwarf is the default here.
|
||||
} else if (!_tcscmp(arch, _T("aarch64"))) {
|
||||
// Dwarf is the default here.
|
||||
}
|
||||
|
||||
exec_argv[arg++] = _T("-target");
|
||||
exec_argv[arg++] = target;
|
||||
exec_argv[arg++] = _T("-rtlib=compiler-rt");
|
||||
exec_argv[arg++] = _T("-stdlib=libc++");
|
||||
exec_argv[arg++] = _T("-fuse-ld=lld");
|
||||
exec_argv[arg++] = _T("-fuse-cxa-atexit");
|
||||
exec_argv[arg++] = _T("-Qunused-arguments");
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
exec_argv[arg++] = argv[i];
|
||||
|
||||
exec_argv[arg] = NULL;
|
||||
if (arg > max_arg) {
|
||||
fprintf(stderr, "Too many options added\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int ret = _tspawnvp(_P_WAIT, exec_argv[0], exec_argv);
|
||||
if (ret == -1) {
|
||||
_tperror(exec_argv[0]);
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
// On unix, exec() runs the target executable within this same process,
|
||||
// making the return code propagate implicitly.
|
||||
// Windows doesn't have such mechanisms, and the exec() family of functions
|
||||
// makes the calling process exit immediately and always returning
|
||||
// a zero return. This doesn't work for our case where we need the
|
||||
// return code propagated.
|
||||
_texecvp(exec_argv[0], EXECVP_CAST exec_argv);
|
||||
|
||||
_tperror(exec_argv[0]);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
@@ -9,6 +9,7 @@ if [ -n "$CCACHE" ]; then
|
||||
CCACHE=ccache
|
||||
fi
|
||||
|
||||
# If changing this wrapper, change clang-target-wrapper.c accordingly.
|
||||
CLANG="$DIR/clang"
|
||||
FLAGS=""
|
||||
case $EXE in
|
||||
|
||||
Reference in new issue
Block a user