From b80339542a621a5e45d81318355f86d13d1c636c Mon Sep 17 00:00:00 2001 From: Jeremy Drake Date: Thu, 4 Nov 2021 17:15:15 -0700 Subject: [PATCH] mingw-w64-cross-clang: wrappers for cross compilation This allows using clang to target other Windows arches using prefixed cross tools (ie, aarch64-w64-mingw32-clang). --- mingw-w64-cross-clang/PKGBUILD | 90 +++++++++ mingw-w64-cross-clang/clang-target-wrapper.c | 104 ++++++++++ mingw-w64-cross-clang/dlltool-wrapper.c | 67 +++++++ mingw-w64-cross-clang/llvm-wrapper.c | 28 +++ mingw-w64-cross-clang/native-wrapper.h | 191 +++++++++++++++++++ mingw-w64-cross-clang/windres-wrapper.c | 58 ++++++ 6 files changed, 538 insertions(+) create mode 100644 mingw-w64-cross-clang/PKGBUILD create mode 100644 mingw-w64-cross-clang/clang-target-wrapper.c create mode 100644 mingw-w64-cross-clang/dlltool-wrapper.c create mode 100644 mingw-w64-cross-clang/llvm-wrapper.c create mode 100644 mingw-w64-cross-clang/native-wrapper.h create mode 100644 mingw-w64-cross-clang/windres-wrapper.c diff --git a/mingw-w64-cross-clang/PKGBUILD b/mingw-w64-cross-clang/PKGBUILD new file mode 100644 index 0000000000000..5454064d09fba --- /dev/null +++ b/mingw-w64-cross-clang/PKGBUILD @@ -0,0 +1,90 @@ +declare -g -A _cross_arches=( + ["/clang64"]="x86_64-w64-mingw32" + ["/clang32"]="i686-w64-mingw32" + ["/clangarm64"]="aarch64-w64-mingw32" +) +pkgbase=mingw-w64-cross-clang +pkgname=($(for _pfx in "${!_cross_arches[@]}"; do + if [[ "${_cross_arches[$_pfx]%%-*}" != "${CARCH}" ]]; then + echo "${MINGW_PACKAGE_PREFIX}-cross-clang-${_cross_arches[$_pfx]%%-*}" + fi + done)) +pkgver=13.0.0 +pkgrel=1 +arch=('any') +mingw_arch=('mingw32' 'mingw64' 'ucrt64' 'clang64' 'clang32' 'clangarm64') +license=('ISC') +makedepends=("${MINGW_PACKAGE_PREFIX}-gcc") +# this is unused in the packages but necessary to make CI happy +depends=("${MINGW_PACKAGE_PREFIX}-clang=${pkgver}" + "${MINGW_PACKAGE_PREFIX}-cross-compiler-rt=${pkgver}") +source=("native-wrapper.h" + "llvm-wrapper.c" + "clang-target-wrapper.c" + "dlltool-wrapper.c" + "windres-wrapper.c") +sha256sums=('c9758342cb926605cd1b30ccb92e6b47f5cc930a15904462e0445959f9be49c1' + 'd6bafc72309860e7a45a91047b5e4c4519b52d6d685069f77094ef6cc09385e5' + '10587323d163abe0ca1f094cba1c991ef8bbed71cde7a9b94ddbe36ae3e2868f' + '2adee7d81d71a167d28fc508e8b3427f63e7c064f08ca63fe330476e8ae4a2c8' + 'b121e52bc752396f887e8e6a97138117fc9c2ee4f7efbe9f5ca2be4f451b6f45') +build() { + CC=${CC:-cc} + cd "${srcdir}" + + [[ -d "build-${MSYSTEM}" ]] && rm -rf "build-${MSYSTEM}" + mkdir "build-${MSYSTEM}" && cd "build-${MSYSTEM}" + + for _pfx in "${!_cross_arches[@]}"; do + if [[ "${_cross_arches[$_pfx]%%-*}" != "${CARCH}" ]]; then + MSYS2_ARG_CONV_EXCL="-DSYSROOT=" \ + $CC $CPPFLAGS $CFLAGS $LDFLAGS -municode -DDEFAULT_TARGET="\"${_cross_arches[$_pfx]}\"" -DSYSROOT="\"${_pfx}\"" ../llvm-wrapper.c -o ${_cross_arches[$_pfx]}-llvm-wrapper.exe + MSYS2_ARG_CONV_EXCL="-DSYSROOT=" \ + $CC $CPPFLAGS $CFLAGS $LDFLAGS -municode -DDEFAULT_TARGET="\"${_cross_arches[$_pfx]}\"" -DSYSROOT="\"${_pfx}\"" ../clang-target-wrapper.c -o ${_cross_arches[$_pfx]}-clang.exe + MSYS2_ARG_CONV_EXCL="-DSYSROOT=" \ + $CC $CPPFLAGS $CFLAGS $LDFLAGS -municode -DDEFAULT_TARGET="\"${_cross_arches[$_pfx]}\"" -DSYSROOT="\"${_pfx}\"" ../dlltool-wrapper.c -o ${_cross_arches[$_pfx]}-dlltool.exe + MSYS2_ARG_CONV_EXCL="-DSYSROOT=" \ + $CC $CPPFLAGS $CFLAGS $LDFLAGS -municode -DDEFAULT_TARGET="\"${_cross_arches[$_pfx]}\"" -DSYSROOT="\"${_pfx}\"" ../windres-wrapper.c -o ${_cross_arches[$_pfx]}-windres.exe + fi + done +} +_real_package() { + local _pfx="@@@PREFIX@@@" + depends=("${MINGW_PACKAGE_PREFIX}-clang=${pkgver}" + "${MINGW_PACKAGE_PREFIX}-cross-compiler-rt=${pkgver}" + "${MINGW_PACKAGE_PREFIX}-llvm=${pkgver}" + "${MINGW_PACKAGE_PREFIX}-lld=${pkgver}" + "mingw-w64-clang-${_cross_arches[@@@PREFIX@@@]%%-*}-crt" + "mingw-w64-clang-${_cross_arches[@@@PREFIX@@@]%%-*}-headers" + "mingw-w64-clang-${_cross_arches[@@@PREFIX@@@]%%-*}-libc++=${pkgver}" + "mingw-w64-clang-${_cross_arches[@@@PREFIX@@@]%%-*}-libc++abi=${pkgver}" + "mingw-w64-clang-${_cross_arches[@@@PREFIX@@@]%%-*}-libunwind=${pkgver}") + + cd "${srcdir}/build-${MSYSTEM}" + + mkdir -p "${pkgdir}${MINGW_PREFIX}/bin" + local _tool + # c11 c99 ? + for _tool in as c++ cc clang clang++ g++ gcc; do + cp -f ${_cross_arches[$_pfx]}-clang.exe "${pkgdir}${MINGW_PREFIX}/bin/${_cross_arches[$_pfx]}-${_tool}.exe" + done + for _tool in addr2line ar ranlib nm objcopy readelf strings strip; do + cp -f ${_cross_arches[$_pfx]}-llvm-wrapper.exe "${pkgdir}${MINGW_PREFIX}/bin/${_cross_arches[$_pfx]}-${_tool}.exe" + done + # windres and dlltool can't use llvm-wrapper, as that loses the original + # target arch prefix + for _tool in dlltool windres; do + cp -f ${_cross_arches[$_pfx]}-${_tool}.exe "${pkgdir}${MINGW_PREFIX}/bin/${_cross_arches[$_pfx]}-${_tool}.exe" + done + + mkdir -p "${pkgdir}${MINGW_PREFIX}/share/licenses/${_cross_arches[${_pfx}]}-cross-clang" + sed -ne '1,/^ \*\//p' "${srcdir}/native-wrapper.h" > "${pkgdir}${MINGW_PREFIX}/share/licenses/${_cross_arches[${_pfx}]}-cross-clang/LICENSE" +} + +_func="$(declare -f "_real_package")" +for _pfx in "${!_cross_arches[@]}"; do + if [[ "${_cross_arches[$_pfx]%%-*}" != "${CARCH}" ]]; then + _func2="${_func//@@@PREFIX@@@/${_pfx}}" + eval "${_func2/#_real_package/package_${MINGW_PACKAGE_PREFIX}-cross-clang-${_cross_arches[$_pfx]%%-*}}" + fi +done diff --git a/mingw-w64-cross-clang/clang-target-wrapper.c b/mingw-w64-cross-clang/clang-target-wrapper.c new file mode 100644 index 0000000000000..f9f76b3f8bf64 --- /dev/null +++ b/mingw-w64-cross-clang/clang-target-wrapper.c @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#include "native-wrapper.h" + +#ifndef CLANG +#define CLANG "clang" +#endif +#ifndef DEFAULT_TARGET +#define DEFAULT_TARGET "x86_64-w64-mingw32" +#endif +#ifndef SYSROOT +#define SYSROOT "/clang64" +#endif + +int _tmain(int argc, TCHAR* argv[]) { + const TCHAR *dir; + const TCHAR *target; + const TCHAR *exe; + split_argv(argv[0], &dir, NULL, &target, &exe); + if (!target) + target = _T(DEFAULT_TARGET); + TCHAR *arch = _tcsdup(target); + TCHAR *dash = _tcschr(arch, '-'); + if (dash) + *dash = '\0'; + TCHAR *target_os = _tcsrchr(target, '-'); + if (target_os) + target_os++; + + // Check if trying to compile Ada; if we try to do this, invoking clang + // would end up invoking -gcc with the same arguments, which ends + // up in an infinite recursion. + for (int i = 1; i < argc - 1; i++) { + if (!_tcscmp(argv[i], _T("-x")) && !_tcscmp(argv[i + 1], _T("ada"))) { + fprintf(stderr, "Ada is not supported\n"); + return 1; + } + } + + int max_arg = argc + 20; + const TCHAR **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); + int arg = 0; + if (getenv("CCACHE")) + exec_argv[arg++] = _T("ccache"); + exec_argv[arg++] = concat(dir, _T(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 (target_os && !_tcscmp(target_os, _T("mingw32uwp"))) { + // the UWP target is for Windows 10 + exec_argv[arg++] = _T("-D_WIN32_WINNT=0x0A00"); + exec_argv[arg++] = _T("-DWINVER=0x0A00"); + // the UWP target can only use Windows Store APIs + exec_argv[arg++] = _T("-DWINAPI_FAMILY=WINAPI_FAMILY_APP"); + // the Windows Store API only supports Windows Unicode (some rare ANSI ones are available) + exec_argv[arg++] = _T("-DUNICODE"); + // add the minimum runtime to use for UWP targets + exec_argv[arg++] = _T("-Wl,-lwindowsapp"); + // This still requires that the toolchain (in particular, libc++.a) has + // been built targeting UCRT originally. + exec_argv[arg++] = _T("-Wl,-lucrtapp"); + // force the user of Universal C Runtime + exec_argv[arg++] = _T("-D_UCRT"); + } + + exec_argv[arg++] = _T("-target"); + exec_argv[arg++] = target; + exec_argv[arg++] = _T("--sysroot"); + exec_argv[arg++] = concat(dir, _T("../..") _T(SYSROOT)); + exec_argv[arg++] = _T("-rtlib=compiler-rt"); + exec_argv[arg++] = _T("-unwindlib=libunwind"); + exec_argv[arg++] = _T("-stdlib=libc++"); + exec_argv[arg++] = _T("-fuse-ld=lld"); + 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(); + } + + return run_final(exec_argv[0], exec_argv); +} diff --git a/mingw-w64-cross-clang/dlltool-wrapper.c b/mingw-w64-cross-clang/dlltool-wrapper.c new file mode 100644 index 0000000000000..abe6ba66a7606 --- /dev/null +++ b/mingw-w64-cross-clang/dlltool-wrapper.c @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include "native-wrapper.h" + +#ifndef DEFAULT_TARGET +#define DEFAULT_TARGET "x86_64-w64-mingw32" +#endif + +int _tmain(int argc, TCHAR* argv[]) { + const TCHAR *dir; + const TCHAR *target; + split_argv(argv[0], &dir, NULL, &target, NULL); + if (!target) + target = _tcsdup(_T(DEFAULT_TARGET)); + TCHAR *dash = _tcschr(target, '-'); + if (dash) + *dash = '\0'; + + int max_arg = argc + 2; + const TCHAR **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); + int arg = 0; + exec_argv[arg++] = concat(dir, _T("llvm-dlltool")); + + if (!_tcscmp(target, _T("i686"))) { + exec_argv[arg++] = _T("-m"); + exec_argv[arg++] = _T("i386"); + } else if (!_tcscmp(target, _T("x86_64"))) { + exec_argv[arg++] = _T("-m"); + exec_argv[arg++] = _T("i386:x86-64"); + } else if (!_tcscmp(target, _T("armv7"))) { + exec_argv[arg++] = _T("-m"); + exec_argv[arg++] = _T("arm"); + } else if (!_tcscmp(target, _T("aarch64"))) { + exec_argv[arg++] = _T("-m"); + exec_argv[arg++] = _T("arm64"); + } else { + _ftprintf(stderr, _T("Arch "TS" unsupported\n"), target); + return 1; + } + + 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(); + } + + return run_final(exec_argv[0], exec_argv); +} diff --git a/mingw-w64-cross-clang/llvm-wrapper.c b/mingw-w64-cross-clang/llvm-wrapper.c new file mode 100644 index 0000000000000..de7918af18e05 --- /dev/null +++ b/mingw-w64-cross-clang/llvm-wrapper.c @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#include "native-wrapper.h" + +int _tmain(int argc, TCHAR* argv[]) { + const TCHAR *dir; + const TCHAR *exe; + split_argv(argv[0], &dir, NULL, NULL, &exe); + TCHAR *exe_path = concat(dir, concat(_T("llvm-"), exe)); + + return run_final(exe_path, (const TCHAR *const *) argv); +} diff --git a/mingw-w64-cross-clang/native-wrapper.h b/mingw-w64-cross-clang/native-wrapper.h new file mode 100644 index 0000000000000..7b0c16f286813 --- /dev/null +++ b/mingw-w64-cross-clang/native-wrapper.h @@ -0,0 +1,191 @@ +/* + * 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 +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#define EXECVP_CAST +#else +#include +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 _tcsncmp strncmp +#define _tperror perror +#define _texecvp execvp +#define _tmain main +#define _ftprintf fprintf +#define _vftprintf vfprintf +#define _tunlink unlink +#define EXECVP_CAST (char **) +#endif + +#ifdef _UNICODE +#define TS "%ls" +#else +#define TS "%s" +#endif + +#ifdef _WIN32 +static inline TCHAR *escape(const TCHAR *str) { + TCHAR *out = malloc((_tcslen(str) * 2 + 3) * sizeof(*out)); + TCHAR *ptr = out; + int i; + *ptr++ = '"'; + for (i = 0; str[i]; i++) { + if (str[i] == '"') { + int j = i - 1; + // Before all double quotes, backslashes need to be escaped, but + // not elsewhere. + while (j >= 0 && str[j--] == '\\') + *ptr++ = '\\'; + // Escape the next double quote. + *ptr++ = '\\'; + } + *ptr++ = str[i]; + } + // Any final backslashes, before the quote around the whole argument, + // need to be doubled. + int j = i - 1; + while (j >= 0 && str[j--] == '\\') + *ptr++ = '\\'; + *ptr++ = '"'; + *ptr++ = '\0'; + return out; +} + +static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR * const *argv) { + int num_args = 0; + while (argv[num_args]) + num_args++; + const TCHAR **escaped_argv = malloc((num_args + 1) * sizeof(*escaped_argv)); + for (int i = 0; argv[i]; i++) + escaped_argv[i] = escape(argv[i]); + escaped_argv[num_args] = NULL; + return _tspawnvp(mode, filename, escaped_argv); +} +#else +static inline int _tcsicmp(const TCHAR *a, const TCHAR *b) { + while (*a && tolower(*a) == tolower(*b)) { + a++; + b++; + } + return *a - *b; +} +#endif + +static inline TCHAR *concat(const TCHAR *prefix, const TCHAR *suffix) { + int prefixlen = _tcslen(prefix); + int suffixlen = _tcslen(suffix); + TCHAR *buf = malloc((prefixlen + suffixlen + 1) * sizeof(*buf)); + _tcscpy(buf, prefix); + _tcscpy(buf + prefixlen, suffix); + return buf; +} + +static inline TCHAR *_tcsrchrs(const TCHAR *str, TCHAR char1, TCHAR char2) { + TCHAR *ptr1 = _tcsrchr(str, char1); + TCHAR *ptr2 = _tcsrchr(str, char2); + if (!ptr1) + return ptr2; + if (!ptr2) + return ptr1; + if (ptr1 < ptr2) + return ptr2; + return ptr1; +} + +static inline void split_argv(const TCHAR *argv0, const TCHAR **dir_ptr, const TCHAR **basename_ptr, const TCHAR **target_ptr, const TCHAR **exe_ptr) { + const TCHAR *sep = _tcsrchrs(argv0, '/', '\\'); + TCHAR *dir = _tcsdup(_T("")); + const TCHAR *basename = argv0; + if (sep) { + dir = _tcsdup(argv0); + dir[sep + 1 - argv0] = '\0'; + 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) { + sep2[1] = '\0'; + dir = _tcsdup(module_path); + } +#endif + basename = _tcsdup(basename); + TCHAR *period = _tcschr(basename, '.'); + if (period) + *period = '\0'; + TCHAR *target = _tcsdup(basename); + TCHAR *dash = _tcsrchr(target, '-'); + const TCHAR *exe = basename; + if (dash) { + *dash = '\0'; + exe = dash + 1; + } else { + target = NULL; + } + + if (dir_ptr) + *dir_ptr = dir; + if (basename_ptr) + *basename_ptr = basename; + if (target_ptr) + *target_ptr = target; + if (exe_ptr) + *exe_ptr = exe; +} + +static inline int run_final(const TCHAR *executable, const TCHAR *const *argv) { +#ifdef _WIN32 + int ret = _tspawnvp_escape(_P_WAIT, executable, argv); + if (ret == -1) { + _tperror(executable); + 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(executable, EXECVP_CAST argv); + + _tperror(executable); + return 1; +#endif +} diff --git a/mingw-w64-cross-clang/windres-wrapper.c b/mingw-w64-cross-clang/windres-wrapper.c new file mode 100644 index 0000000000000..41d0fb9fb86f6 --- /dev/null +++ b/mingw-w64-cross-clang/windres-wrapper.c @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#include "native-wrapper.h" + +#ifndef DEFAULT_TARGET +#define DEFAULT_TARGET "x86_64-w64-mingw32" +#endif +#ifndef SYSROOT +#define SYSROOT "/clang64" +#endif + +int _tmain(int argc, TCHAR* argv[]) { + const TCHAR *dir; + const TCHAR *target; + split_argv(argv[0], &dir, NULL, &target, NULL); + if (!target) + target = _T(DEFAULT_TARGET); + + int max_arg = argc + 4; + const TCHAR **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); + int arg = 0; + exec_argv[arg++] = concat(dir, _T("llvm-windres")); + exec_argv[arg++] = _T("--target"); + exec_argv[arg++] = target; + exec_argv[arg++] = _T("--preprocessor-arg"); + /* something is eating backslashes */ + TCHAR * p = (TCHAR *)dir; + while ((p = _tcschr(p, _T('\\')))) + *p = _T('/'); + exec_argv[arg++] = concat(_T("--sysroot="), concat(dir, _T("../..") _T(SYSROOT))); + + 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(); + } + + return run_final(exec_argv[0], exec_argv); +}