diff options
author | Ian Lynagh <igloo@earth.li> | 2009-10-27 20:25:03 +0000 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2009-10-27 20:25:03 +0000 |
commit | 6cf8982ac30be6836a0cdd8be5a6ac1a1a144213 (patch) | |
tree | 604f63fabadfd1d2bd2b480f5f1a7ed2211778b8 /driver | |
parent | 48196c3c2a365ce085d0b0567cbd4ea047af59df (diff) | |
download | haskell-6cf8982ac30be6836a0cdd8be5a6ac1a1a144213.tar.gz |
Wrap gcc on Windows, to provide the -B flags
Diffstat (limited to 'driver')
-rw-r--r-- | driver/gcc/gcc.c | 95 | ||||
-rw-r--r-- | driver/utils/getLocation.c | 40 | ||||
-rw-r--r-- | driver/utils/getLocation.h | 4 |
3 files changed, 139 insertions, 0 deletions
diff --git a/driver/gcc/gcc.c b/driver/gcc/gcc.c new file mode 100644 index 0000000000..cd8a511074 --- /dev/null +++ b/driver/gcc/gcc.c @@ -0,0 +1,95 @@ + +#include "getLocation.h" +#include <process.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +static void die(char *msg) { + fprintf(stderr, "%s", msg); + exit(1); +} + +static char *mkString(const char *fmt, ...) { + char *p; + int i, j; + va_list argp; + + va_start(argp, fmt); + i = vsnprintf(p, 0, fmt, argp); + va_end(argp); + + if (i < 0) { + die("snprintf failed\n"); + } + + p = malloc(i + 1); + if (p == NULL) { + die("malloc failed\n"); + } + + va_start(argp, fmt); + j = vsnprintf(p, i + 1, fmt, argp); + va_end(argp); + if (i < 0) { + die("snprintf failed\n"); + } + + return p; +} + +char *quote(char *str) { + char *quotedStr; + char *p; + int i; + + quotedStr = malloc(2 * strlen(str) + 2 + 1); + if (quotedStr == NULL) { + die("malloc failed\n"); + } + p = quotedStr; + *p++ = '"'; + while (*str) { + if (*str == '"') { + *p++ = '\\'; + } + *p++ = *str++; + } + *p++ = '"'; + *p = '\0'; + + return quotedStr; +} + +int main(int argc, char** argv) { + char *p; + char *binDir; + char *exePath; + char *bArg; + char **newArgv; + int i, j, ret; + + binDir = getExecutablePath(); + exePath = mkString("%s/realgcc.exe", binDir); + + /* Without these -B args, gcc will still work. However, if you + have a mingw installation in c:/mingw then it will use files + from that in preference to the in-tree files. */ + + newArgv = malloc(sizeof(char *) * (argc + 4 + 1)); + newArgv[0] = quote(exePath); + newArgv[1] = quote(mkString("-B%s", binDir)); + newArgv[2] = quote(mkString("-B%s/../lib", binDir)); + newArgv[3] = quote(mkString("-B%s/../lib/gcc/mingw32/3.4.5", binDir)); + newArgv[4] = quote(mkString("-B%s/../libexec/gcc/mingw32/3.4.5", binDir)); + for (i = 1; i < argc; i++) { + newArgv[4 + i] = quote(argv[i]); + } + newArgv[4 + argc] = NULL; + // execv(exePath, argv); + ret = spawnv(_P_WAIT, exePath, (const char* const*)newArgv); + if (errno) { + die("Spawn failed\n"); + } + exit(ret); +} diff --git a/driver/utils/getLocation.c b/driver/utils/getLocation.c new file mode 100644 index 0000000000..fcbe1b940c --- /dev/null +++ b/driver/utils/getLocation.c @@ -0,0 +1,40 @@ + +#include "getLocation.h" +#include <stdio.h> +#include <windows.h> + +static void die(char *msg) { + fprintf(stderr, "%s", msg); + exit(1); +} + +char *getExecutable(void) { + char *p; + int i; + int r; + + i = 2048; /* plenty, PATH_MAX is 512 under Win32 */ + p = malloc(i); + if (p == NULL) { + die("Malloc failed\n"); + } + r = GetModuleFileNameA(NULL, p, i); + if (r == 0) { + die("getModuleFileName failed\n"); + } + return p; +} + +char *getExecutablePath(void) { + char *p; + char *f; + + p = getExecutable(); + f = strrchr(p, '\\'); + if (f == NULL) { + die("No '\\' in executable location\n"); + } + f[0] = '\0'; + return p; +} + diff --git a/driver/utils/getLocation.h b/driver/utils/getLocation.h new file mode 100644 index 0000000000..689a4427ad --- /dev/null +++ b/driver/utils/getLocation.h @@ -0,0 +1,4 @@ + +char *getExecutable(void); +char *getExecutablePath(void); + |