]> git.ozlabs.org Git - ccan/blobdiff - tools/configurator/configurator.c
tools/configurator: allow overriding of which cc we will run.
[ccan] / tools / configurator / configurator.c
index a7cbfa53e724ad7119ba89025f0c58c3b22b5aca..ff9f64904bb06a7759c7c453fbf53a3dae47f5e8 100644 (file)
 #define pclose _pclose
 #endif
 
+#ifdef _MSC_VER
+#define DEFAULT_COMPILER "cl"
+/* Note:  Dash options avoid POSIX path conversion when used under msys bash
+ *        and are therefore preferred to slash (e.g. -nologo over /nologo)
+ * Note:  Disable Warning 4200 "nonstandard extension used : zero-sized array
+ *        in struct/union" for flexible array members.
+ */
+#define DEFAULT_FLAGS "-nologo -Zi -W4 -wd4200 " \
+       "-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS"
+#define DEFAULT_OUTPUT_EXE_FLAG "-Fe:"
+#else
 #define DEFAULT_COMPILER "cc"
 #define DEFAULT_FLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition"
+#define DEFAULT_OUTPUT_EXE_FLAG "-o"
+#endif
 
 #define OUTPUT_FILE "configurator.out"
 #define INPUT_FILE "configuratortest.c"
@@ -302,6 +315,8 @@ static struct test tests[] = {
          "#include <sys/filio.h>\n" },
        { "HAVE_SYS_TERMIOS_H", OUTSIDE_MAIN, NULL, NULL,
          "#include <sys/termios.h>\n" },
+       { "HAVE_SYS_UNISTD_H", OUTSIDE_MAIN, NULL, NULL,
+         "#include <sys/unistd.h>\n" },
        { "HAVE_TYPEOF", INSIDE_MAIN, NULL, NULL,
          "__typeof__(argc) i; i = argc; return i == argc ? 0 : 1;" },
        { "HAVE_UNALIGNED_ACCESS", DEFINES_EVERYTHING|EXECUTE, NULL, NULL,
@@ -407,6 +422,22 @@ static void c12r_errx(int eval, const char *fmt, ...)
        exit(eval);
 }
 
+static size_t fcopy(FILE *fsrc, FILE *fdst)
+{
+       char buffer[BUFSIZ];
+       size_t rsize, wsize;
+       size_t copied = 0;
+
+       while ((rsize = fread(buffer, 1, BUFSIZ, fsrc)) > 0) {
+               wsize = fwrite(buffer, 1, rsize, fdst);
+               copied += wsize;
+               if (wsize != rsize)
+                       break;
+       }
+
+       return copied;
+}
+
 static char *grab_stream(FILE *file)
 {
        size_t max, ret, size = 0;
@@ -449,10 +480,12 @@ static char *run(const char *cmd, int *exitstatus)
        return ret;
 }
 
-static char *connect_args(const char *argv[], const char *extra)
+static char *connect_args(const char *argv[], const char *outflag,
+               const char *files)
 {
-       unsigned int i, len = strlen(extra) + 1;
+       unsigned int i;
        char *ret;
+       size_t len = strlen(outflag) + strlen(files) + 1;
 
        for (i = 1; argv[i]; i++)
                len += 1 + strlen(argv[i]);
@@ -462,10 +495,12 @@ static char *connect_args(const char *argv[], const char *extra)
        for (i = 1; argv[i]; i++) {
                strcpy(ret + len, argv[i]);
                len += strlen(argv[i]);
-               if (argv[i+1])
+               if (argv[i+1] || *outflag)
                        ret[len++] = ' ';
        }
-       strcpy(ret + len, extra);
+       strcpy(ret + len, outflag);
+       len += strlen(outflag);
+       strcpy(ret + len, files);
        return ret;
 }
 
@@ -530,7 +565,7 @@ static bool run_test(const char *cmd, struct test *test)
                }
        }
 
-       outf = fopen(INPUT_FILE, "w");
+       outf = fopen(INPUT_FILE, verbose > 1 ? "w+" : "w");
        if (!outf)
                c12r_err(1, "creating %s", INPUT_FILE);
 
@@ -561,11 +596,13 @@ static bool run_test(const char *cmd, struct test *test)
                abort();
 
        }
-       fclose(outf);
 
-       if (verbose > 1)
-               if (system("cat " INPUT_FILE) == -1)
-                       ;
+       if (verbose > 1) {
+               fseek(outf, 0, SEEK_SET);
+               fcopy(outf, stdout);
+       }
+
+       fclose(outf);
 
        newcmd = strdup(cmd);
 
@@ -632,33 +669,57 @@ int main(int argc, const char *argv[])
        unsigned int i;
        const char *default_args[]
                = { "", DEFAULT_COMPILER, DEFAULT_FLAGS, NULL };
+       const char *outflag = DEFAULT_OUTPUT_EXE_FLAG;
+       const char *configurator_cc = NULL;
+       const char *orig_cc;
 
        if (argc > 0)
                progname = argv[0];
 
-       if (argc > 1) {
+       while (argc > 1) {
                if (strcmp(argv[1], "--help") == 0) {
-                       printf("Usage: configurator [-v] [<compiler> <flags>...]\n"
-                              "  <compiler> <flags> will have \"-o <outfile> <infile.c>\" appended\n"
-                              "Default: %s %s\n",
-                              DEFAULT_COMPILER, DEFAULT_FLAGS);
+                       printf("Usage: configurator [-v] [-O<outflag>] [--configurator-cc=<compiler-for-tests>] [<compiler> <flags>...]\n"
+                              "  <compiler> <flags> will have \"<outflag> <outfile> <infile.c>\" appended\n"
+                              "Default: %s %s %s\n",
+                              DEFAULT_COMPILER, DEFAULT_FLAGS,
+                              DEFAULT_OUTPUT_EXE_FLAG);
                        exit(0);
                }
-               if (strcmp(argv[1], "-v") == 0) {
+               if (strncmp(argv[1], "-O", 2) == 0) {
+                       argc--;
+                       argv++;
+                       outflag = argv[1] + 2;
+                       if (!*outflag) {
+                               fprintf(stderr,
+                                       "%s: option requires an argument -- O\n",
+                                       argv[0]);
+                               exit(1);
+                       }
+               } else if (strcmp(argv[1], "-v") == 0) {
                        argc--;
                        argv++;
-                       verbose = 1;
+                       verbose++;
                } else if (strcmp(argv[1], "-vv") == 0) {
                        argc--;
                        argv++;
-                       verbose = 2;
+                       verbose += 2;
+               } else if (strncmp(argv[1], "--configurator-cc=", 18) == 0) {
+                       configurator_cc = argv[1] + 18;
+                       argc--;
+                       argv++;
+               } else {
+                       break;
                }
        }
 
        if (argc == 1)
                argv = default_args;
 
-       cmd = connect_args(argv, " -o " OUTPUT_FILE " " INPUT_FILE);
+       orig_cc = argv[1];
+       if (configurator_cc)
+               argv[1] = configurator_cc;
+
+       cmd = connect_args(argv, outflag, OUTPUT_FILE " " INPUT_FILE);
        for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
                run_test(cmd, &tests[i]);
        free(cmd);
@@ -672,10 +733,11 @@ int main(int argc, const char *argv[])
        printf("#ifndef _GNU_SOURCE\n");
        printf("#define _GNU_SOURCE /* Always use GNU extensions. */\n");
        printf("#endif\n");
-       printf("#define CCAN_COMPILER \"%s\"\n", argv[1]);
-       cmd = connect_args(argv+1, "");
-       printf("#define CCAN_CFLAGS \"%s\"\n\n", cmd);
+       printf("#define CCAN_COMPILER \"%s\"\n", orig_cc);
+       cmd = connect_args(argv + 1, "", "");
+       printf("#define CCAN_CFLAGS \"%s\"\n", cmd);
        free(cmd);
+       printf("#define CCAN_OUTPUT_EXE_CFLAG \"%s\"\n\n", outflag);
        /* This one implies "#include <ccan/..." works, eg. for tdb2.h */
        printf("#define HAVE_CCAN 1\n");
        for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)