summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--driver/gcc/gcc.c89
-rw-r--r--driver/utils/cwrapper.c100
-rw-r--r--driver/utils/cwrapper.h5
4 files changed, 114 insertions, 82 deletions
diff --git a/configure.ac b/configure.ac
index 19cb3917cf..4d83dbcf44 100644
--- a/configure.ac
+++ b/configure.ac
@@ -444,7 +444,7 @@ then
tar -zxf ../../ghc-tarballs/mingw/w32api*.tar.gz &&
mv bin/gcc.exe bin/realgcc.exe
)
- inplace/mingw/bin/realgcc.exe driver/gcc/gcc.c driver/utils/getLocation.c -Idriver/utils -o inplace/mingw/bin/gcc.exe
+ inplace/mingw/bin/realgcc.exe driver/gcc/gcc.c driver/utils/cwrapper.c driver/utils/getLocation.c -Idriver/utils -o inplace/mingw/bin/gcc.exe
AC_MSG_NOTICE([In-tree mingw tree created])
fi
if ! test -d inplace/perl ||
diff --git a/driver/gcc/gcc.c b/driver/gcc/gcc.c
index c086f748e5..4efd559b68 100644
--- a/driver/gcc/gcc.c
+++ b/driver/gcc/gcc.c
@@ -5,6 +5,7 @@
therefore need to add various -B flags to the gcc commandline,
so that it uses our in-tree mingw. Hence this wrapper. */
+#include "cwrapper.h"
#include "getLocation.h"
#include <errno.h>
#include <process.h>
@@ -13,74 +14,10 @@
#include <stdarg.h>
#include <string.h>
-static void die(const char *fmt, ...) {
- va_list argp;
-
- va_start(argp, fmt);
- vfprintf(stderr, fmt, argp);
- va_end(argp);
- exit(1);
-}
-
-static char *mkString(const char *fmt, ...) {
- char *p;
- int i, j;
- va_list argp;
-
- va_start(argp, fmt);
- i = vsnprintf(NULL, 0, fmt, argp);
- va_end(argp);
-
- if (i < 0) {
- die("snprintf 0 failed: errno %d: %s\n", errno, strerror(errno));
- }
-
- p = malloc(i + 1);
- if (p == NULL) {
- die("malloc failed: errno %d: %s\n", errno, strerror(errno));
- }
-
- va_start(argp, fmt);
- j = vsnprintf(p, i + 1, fmt, argp);
- va_end(argp);
- if (i < 0) {
- die("snprintf with %d failed: errno %d: %s\n",
- i + 1, errno, strerror(errno));
- }
-
- 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: errno %d: %s\n", errno, strerror(errno));
- }
- 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;
+ char *preArgv[4];
binDir = getExecutablePath();
exePath = mkString("%s/realgcc.exe", binDir);
@@ -88,21 +25,11 @@ int main(int argc, char** argv) {
/* 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. */
+ preArgv[0] = mkString("-B%s", binDir);
+ preArgv[1] = mkString("-B%s/../lib", binDir);
+ preArgv[2] = mkString("-B%s/../lib/gcc/mingw32/3.4.5", binDir);
+ preArgv[3] = mkString("-B%s/../libexec/gcc/mingw32/3.4.5", binDir);
- 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("spawnv failed: errno %d: %s\n", errno, strerror(errno));
- }
- exit(ret);
+ run(exePath, 4, preArgv, argc - 1, argv + 1);
}
+
diff --git a/driver/utils/cwrapper.c b/driver/utils/cwrapper.c
new file mode 100644
index 0000000000..6a58114bcf
--- /dev/null
+++ b/driver/utils/cwrapper.c
@@ -0,0 +1,100 @@
+
+/* gcc on mingw is hardcoded to use /mingw (which is c:/mingw) to
+ find various files. If this is a different version of mingw to the
+ one that we have in the GHC tree then things can go wrong. We
+ therefore need to add various -B flags to the gcc commandline,
+ so that it uses our in-tree mingw. Hence this wrapper. */
+
+#include "cwrapper.h"
+#include <errno.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+void die(const char *fmt, ...) {
+ va_list argp;
+
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ va_end(argp);
+ exit(1);
+}
+
+char *mkString(const char *fmt, ...) {
+ char *p;
+ int i, j;
+ va_list argp;
+
+ va_start(argp, fmt);
+ i = vsnprintf(NULL, 0, fmt, argp);
+ va_end(argp);
+
+ if (i < 0) {
+ die("snprintf 0 failed: errno %d: %s\n", errno, strerror(errno));
+ }
+
+ p = malloc(i + 1);
+ if (p == NULL) {
+ die("malloc failed: errno %d: %s\n", errno, strerror(errno));
+ }
+
+ va_start(argp, fmt);
+ j = vsnprintf(p, i + 1, fmt, argp);
+ va_end(argp);
+ if (i < 0) {
+ die("snprintf with %d failed: errno %d: %s\n",
+ i + 1, errno, strerror(errno));
+ }
+
+ 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: errno %d: %s\n", errno, strerror(errno));
+ }
+ p = quotedStr;
+ *p++ = '"';
+ while (*str) {
+ if (*str == '"') {
+ *p++ = '\\';
+ }
+ *p++ = *str++;
+ }
+ *p++ = '"';
+ *p = '\0';
+
+ return quotedStr;
+}
+
+int run(char *exePath, int numArgs1, char **args1, int numArgs2, char **args2) {
+ char **p;
+ char **newArgv;
+ int i, ret;
+
+ newArgv = malloc(sizeof(char *) * (1 + numArgs1 + numArgs2 + 1));
+ if (newArgv == NULL) {
+ die("malloc failed: errno %d: %s\n", errno, strerror(errno));
+ }
+ p = newArgv;
+ *p++ = quote(exePath);
+ for (i = 0; i < numArgs1; i++) {
+ *p++ = quote(args1[i]);
+ }
+ for (i = 0; i < numArgs2; i++) {
+ *p++ = quote(args2[i]);
+ }
+ *p = NULL;
+ ret = spawnv(_P_WAIT, exePath, (const char* const*)newArgv);
+ if (errno) {
+ die("spawnv failed: errno %d: %s\n", errno, strerror(errno));
+ }
+ exit(ret);
+}
diff --git a/driver/utils/cwrapper.h b/driver/utils/cwrapper.h
new file mode 100644
index 0000000000..53cf652a16
--- /dev/null
+++ b/driver/utils/cwrapper.h
@@ -0,0 +1,5 @@
+
+void die(const char *fmt, ...);
+char *mkString(const char *fmt, ...);
+int run(char *exePath, int numArgs1, char **args1, int numArgs2, char **args2);
+