From b611bc190465aff49524f22c2a0081c218ee74ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sun, 7 Oct 2018 22:23:25 +0300 Subject: [PATCH] Convert the windres wrapper from shell script to C This allow running windres on windows without a surrounding posix shell. --- install-wrappers.sh | 16 +- wrappers/windres-wrapper.c | 484 ++++++++++++++++++++++++++++++++++++ wrappers/windres-wrapper.sh | 220 ---------------- 3 files changed, 494 insertions(+), 226 deletions(-) create mode 100644 wrappers/windres-wrapper.c delete mode 100755 wrappers/windres-wrapper.sh diff --git a/install-wrappers.sh b/install-wrappers.sh index 4c15cab..ebf5e19 100755 --- a/install-wrappers.sh +++ b/install-wrappers.sh @@ -23,20 +23,21 @@ esac if [ -n "$EXEEXT" ]; then CLANG_MAJOR=$(basename $(echo $PREFIX/lib/clang/* | awk '{print $NF}') | cut -f 1 -d .) - CTW_FLAGS="$CTW_FLAGS -municode -DCLANG=\"clang-$CLANG_MAJOR\"" + WRAPPER_FLAGS="$WRAPPER_FLAGS -municode -DCLANG=\"clang-$CLANG_MAJOR\"" fi mkdir -p $PREFIX/bin cp wrappers/*-wrapper.sh $PREFIX/bin if [ -n "$HOST" ]; then # TODO: If building natively on msys, pick up the default HOST value from there. - CTW_FLAGS="$CTW_FLAGS -DDEFAULT_TARGET=\"$HOST\"" + WRAPPER_FLAGS="$WRAPPER_FLAGS -DDEFAULT_TARGET=\"$HOST\"" for i in wrappers/*-wrapper.sh; do cat $i | sed 's/^DEFAULT_TARGET=.*/DEFAULT_TARGET='$HOST/ > $PREFIX/bin/$(basename $i) done fi $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 $CTW_FLAGS +$CC wrappers/clang-target-wrapper.c -o $PREFIX/bin/clang-target-wrapper$EXEEXT -O2 -Wl,-s $WRAPPER_FLAGS +$CC wrappers/windres-wrapper.c -o $PREFIX/bin/windres-wrapper$EXEEXT -O2 -Wl,-s $WRAPPER_FLAGS if [ -n "$EXEEXT" ]; then # For Windows, we should prefer the executable wrapper, which also works # when invoked from outside of MSYS. @@ -53,7 +54,10 @@ for arch in $ARCHS; do for exec in ar ranlib nm strings; do ln -sf llvm-$exec$EXEEXT $arch-w64-mingw32-$exec$EXEEXT || true done - for exec in ld objdump windres dlltool; do + for exec in windres; do + ln -sf $exec-wrapper$EXEEXT $arch-w64-mingw32-$exec$EXEEXT + done + for exec in ld objdump dlltool; do ln -sf $exec-wrapper.sh $arch-w64-mingw32-$exec done for exec in objcopy strip; do @@ -65,10 +69,10 @@ if [ -n "$EXEEXT" ]; then mv clang$EXEEXT clang-$CLANG_MAJOR$EXEEXT fi if [ -n "$HOST" ]; then - for exec in clang clang++ gcc g++ ar ranlib nm strings widl; do + for exec in clang clang++ gcc g++ ar ranlib nm strings widl windres; do ln -sf $HOST-$exec$EXEEXT $exec$EXEEXT done - for exec in ld objdump windres dlltool objcopy strip; do + for exec in ld objdump dlltool objcopy strip; do ln -sf $HOST-$exec $exec done fi diff --git a/wrappers/windres-wrapper.c b/wrappers/windres-wrapper.c new file mode 100644 index 0000000..c3ad017 --- /dev/null +++ b/wrappers/windres-wrapper.c @@ -0,0 +1,484 @@ +/* + * author: Josh de Kock , Martin Storsjo + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to + */ + +#ifdef UNICODE +#define _UNICODE +#endif + +#ifndef DEFAULT_TARGET +#define DEFAULT_TARGET "x86_64-w64-mingw32" +#endif + +#include +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#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 _tspawnvp _spawnvp +#define _ftprintf fprintf +#define _vftprintf vfprintf +#define _tunlink unlink + +#include +#include + +#define _P_WAIT 0 +static int _spawnvp(int mode, const char *filename, const char * const *argv) { + pid_t pid; + if (!(pid = fork())) { + execvp(filename, (char **) argv); + perror(filename); + exit(1); + } + int stat = 0; + if (waitpid(pid, &stat, 0) == -1) + return -1; + if (WIFEXITED(stat)) + return WEXITSTATUS(stat); + errno = EIO; + return -1; +} +#endif + +#ifdef _UNICODE +#define TS "%ls" +#else +#define TS "%s" +#endif + +static TCHAR *escape(const TCHAR *str) { +#ifdef _WIN32 + 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; +#else + return _tcsdup(str); +#endif +} + +static 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; +} + +// GNU binutils windres seem to require an extra level of escaping of +// -D options to the preprocessor, which we need to undo here. +// For defines that produce quoted strings, this windres frontend is +// called with parameters like this: -DSTRING=\\\"1.2.3\\\" +static const TCHAR *unescape_cpp(const TCHAR *str) { + TCHAR *out = _tcsdup(str); + int len = _tcslen(str); + int i, outpos = 0; + for (i = 0; i < len - 1; i++) { + if (str[i] == '\\' && str[i + 1] == '"') + continue; + out[outpos++] = str[i]; + } + while (i < len) + out[outpos++] = str[i++]; + out[outpos++] = '\0'; + return out; +} + +static void print_version(void) { + printf( +"version: LLVM windres (GNU windres compatible) 0.1\n" + ); + exit(1); +} + +static void print_help(void) { + printf( +"usage: llvm-windres