lucy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nwelln...@apache.org
Subject [lucy-commits] [8/8] git commit: refs/heads/c-bindings-cfc - Regenerate charmonizer.c
Date Tue, 12 Feb 2013 20:11:51 GMT
Updated Branches:
  refs/heads/c-bindings-cfc 4cbd991ec -> 369a995c4


Regenerate charmonizer.c


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/369a995c
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/369a995c
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/369a995c

Branch: refs/heads/c-bindings-cfc
Commit: 369a995c4433117a4fe44aec07d4952c8f38fb25
Parents: fbb552d
Author: Nick Wellnhofer <wellnhofer@aevum.de>
Authored: Sun Feb 10 22:11:22 2013 +0100
Committer: Nick Wellnhofer <wellnhofer@aevum.de>
Committed: Tue Feb 12 21:10:23 2013 +0100

----------------------------------------------------------------------
 clownfish/compiler/common/charmonizer.c |  292 ++++++++++++++++++++++----
 clownfish/runtime/common/charmonizer.c  |  285 ++++++++++++++++++++++----
 common/charmonizer.c                    |  291 ++++++++++++++++++++++----
 3 files changed, 749 insertions(+), 119 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/369a995c/clownfish/compiler/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.c b/clownfish/compiler/common/charmonizer.c
index 70775c3..d687b02 100644
--- a/clownfish/compiler/common/charmonizer.c
+++ b/clownfish/compiler/common/charmonizer.c
@@ -93,6 +93,16 @@ chaz_CC_set_warnings_as_errors(const int flag);
 void
 chaz_CC_add_extra_cflags(const char *);
 
+/* Add include dir to extra cflags.
+ */
+void
+chaz_CC_add_include_dir(const char *dir);
+
+/* Set optimization level.
+ */
+void
+chaz_CC_set_optimization_level(const char *level);
+
 /* Accessor for the compiler executable's string representation.
  */
 const char*
@@ -109,25 +119,25 @@ const char*
 chaz_CC_get_extra_cflags(void);
 
 int
-chaz_CC_gcc_version_num();
+chaz_CC_gcc_version_num(void);
 
 const char*
-chaz_CC_gcc_version();
+chaz_CC_gcc_version(void);
 
 int
-chaz_CC_compiler_is_msvc(void);
+chaz_CC_msvc_version_num(void);
 
 const char*
-chaz_CC_link_command();
+chaz_CC_link_command(void);
 
 const char*
-chaz_CC_link_flags();
+chaz_CC_link_flags(void);
 
 const char*
-chaz_CC_link_shared_obj_flag();
+chaz_CC_link_shared_obj_flag(void);
 
 const char*
-chaz_CC_link_output_flag();
+chaz_CC_link_output_flag(void);
 
 #endif /* H_CHAZ_COMPILER */
 
@@ -351,6 +361,15 @@ typedef struct chaz_MakeRule chaz_MakeRule;
 typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
 
 void
+chaz_Make_init(void);
+
+void
+chaz_Make_clean_up(void);
+
+const char*
+chaz_Make_get_make(void);
+
+void
 chaz_Make_list_files(const char *dir, const char *ext,
                      chaz_Make_list_files_callback_t callback, void *context);
 
@@ -631,10 +650,10 @@ chaz_Probe_gcc_version_num(void);
 const char*
 chaz_Probe_gcc_version(void);
 
-/* Returns true if the compiler is MSVC.
+/* Return the integer version of MSVC defined by _MSC_VER
  */
 int
-chaz_Probe_compiler_is_msvc(void);
+chaz_Probe_msvc_version_num(void);
 
 #endif /* Include guard. */
 
@@ -1245,6 +1264,34 @@ chaz_CC_add_extra_cflags(const char *flags) {
     }
 }
 
+void
+chaz_CC_add_include_dir(const char *dir) {
+    size_t size = strlen(chaz_CC.include_flag) + strlen(dir) + 1;
+    char *flag = (char*)malloc(size);
+    sprintf(flag, "%s%s", chaz_CC.include_flag, dir);
+    chaz_CC_add_extra_cflags(flag);
+    free(flag);
+}
+
+void
+chaz_CC_set_optimization_level(const char *level) {
+    const char *opt_flag;
+    char *flag;
+    size_t size;
+
+    if (chaz_CC.intval__MSC_VER) {
+        opt_flag = "/O";
+    }
+    else {
+        opt_flag = "-O";
+    }
+    size = strlen(opt_flag) + strlen(level) + 1;
+    flag = (char*)malloc(size);
+    sprintf(flag, "%s%s", opt_flag, level);
+    chaz_CC_add_extra_cflags(flag);
+    free(flag);
+}
+
 const char*
 chaz_CC_get_cc(void) {
     return chaz_CC.cc_command;
@@ -1273,8 +1320,8 @@ chaz_CC_gcc_version(void) {
 }
 
 int
-chaz_CC_compiler_is_msvc(void) {
-    return !!chaz_CC.intval__MSC_VER;
+chaz_CC_msvc_version_num(void) {
+    return chaz_CC.intval__MSC_VER;
 }
 
 const char*
@@ -2449,6 +2496,110 @@ struct chaz_MakeFile {
     size_t          num_cleanups;
 };
 
+/* Static vars. */
+static struct {
+    char *make_command;
+    int   is_gnu_make;
+    int   is_nmake;
+} chaz_Make = {
+    NULL,
+    0, 0
+};
+
+/* Detect make command.
+ *
+ * The argument list must be a NULL-terminated series of different spellings
+ * of `make`, which will be auditioned in the order they are supplied.  Here
+ * are several possibilities:
+ *
+ *      make
+ *      gmake
+ *      nmake
+ *      dmake
+ */
+static int
+chaz_Make_detect(const char *make1, ...);
+
+static int
+chaz_Make_audition(const char *make);
+
+void
+chaz_Make_init(void) {
+    const char *make;
+
+    chaz_Make_detect("make", "gmake", "nmake", "dmake", NULL);
+    make = chaz_Make.make_command;
+
+    if (make) {
+        if (strcmp(make, "make") == 0 || strcmp(make, "gmake") == 0) {
+            /* TODO: Add a feature test for GNU make. */
+            chaz_Make.is_gnu_make = 1;
+        }
+        else if (strcmp(make, "nmake") == 0) {
+            chaz_Make.is_nmake = 1;
+        }
+    }
+}
+
+void
+chaz_Make_clean_up(void) {
+    free(chaz_Make.make_command);
+}
+
+const char*
+chaz_Make_get_make(void) {
+    return chaz_Make.make_command;
+}
+
+static int
+chaz_Make_detect(const char *make1, ...) {
+    va_list args;
+    const char *candidate;
+    int found = 0;
+    const char makefile_content[] = "foo:\n\techo \"foo!\"\n";
+    chaz_Util_write_file("_charm_Makefile", makefile_content);
+
+    /* Audition candidates. */
+    found = chaz_Make_audition(make1);
+    va_start(args, make1);
+    while (!found && (NULL != (candidate = va_arg(args, const char*)))) {
+        found = chaz_Make_audition(candidate);
+    }
+    va_end(args);
+
+    chaz_Util_remove_and_verify("_charm_Makefile");
+
+    return found;
+}
+
+static int
+chaz_Make_audition(const char *make) {
+    int succeeded = 0;
+    const char pattern[] = "%s -f _charm_Makefile";
+    size_t size = strlen(make) + sizeof(pattern) + 10;
+    char *command = (char*)malloc(size);
+    sprintf(command, pattern, make);
+
+    chaz_Util_remove_and_verify("_charm_foo");
+    chaz_OS_run_redirected(command, "_charm_foo");
+    if (chaz_Util_can_open_file("_charm_foo")) {
+        size_t len;
+        char *content = chaz_Util_slurp_file("_charm_foo", &len);
+        if (NULL != strstr(content, "foo!")) {
+            succeeded = 1;
+        }
+        free(content);
+    }
+    chaz_Util_remove_and_verify("_charm_foo");
+
+    if (succeeded) {
+        chaz_Make.make_command = chaz_Util_strdup(make);
+    }
+
+    free(command);
+    return succeeded;
+}
+
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
@@ -2587,6 +2738,7 @@ chaz_MakeFile_add_shared_obj(chaz_MakeFile *makefile, const char *shared_obj,
 
 void
 chaz_MakeFile_write(chaz_MakeFile *makefile) {
+    int     shell_type = chaz_OS_shell_type();
     FILE   *file;
     size_t  i;
 
@@ -2615,16 +2767,40 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
     }
 
     if (makefile->cleanups[0]) {
-        fprintf(file, "clean :\n\trm -f");
-        for (i = 0; makefile->cleanups[i]; i++) {
-            char *cleanup = makefile->cleanups[i];
-            fprintf(file, " \\\n\t    %s", cleanup);
+        if (shell_type == CHAZ_OS_POSIX) {
+            fprintf(file, "clean :\n\trm -f");
+            for (i = 0; makefile->cleanups[i]; i++) {
+                const char *cleanup = makefile->cleanups[i];
+                fprintf(file, " \\\n\t    %s", cleanup);
+            }
+            fprintf(file, "\n\n");
+        }
+        else if (shell_type == CHAZ_OS_CMD_EXE) {
+            fprintf(file, "clean :\n");
+            for (i = 0; makefile->cleanups[i]; i++) {
+                const char *cleanup = makefile->cleanups[i];
+                fprintf(file, "\tfor %%i in (%s) do if exist %%i del /f %%i\n",
+                        cleanup);
+            }
+            fprintf(file, "\n");
+        }
+        else {
+            chaz_Util_die("Unsupported shell type: %d", shell_type);
         }
-        fprintf(file, "\n\n");
     }
 
     fprintf(file, "distclean : clean\n");
-    fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n");
+    if (shell_type == CHAZ_OS_POSIX) {
+        fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n");
+    }
+    else if (shell_type == CHAZ_OS_CMD_EXE) {
+        fprintf(file,
+            "\tfor %%i in (charmonizer charmony.h Makefile) do"
+            " if exist %%i del /f %%i\n\n");
+    }
+    else {
+        chaz_Util_die("Unsupported shell type: %d", shell_type);
+    }
 
     fclose(file);
 }
@@ -2706,20 +2882,45 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command)
{
 void
 chaz_MakeRule_add_command_make(chaz_MakeRule *rule, const char *dir,
                                const char *target) {
+    const char *make = chaz_Make.make_command;
     char *command;
 
-    if (!target) {
+    if (chaz_Make.is_gnu_make) {
+        if (!target) {
+            size_t size = strlen(dir) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) -C %s", dir);
+        }
+        else {
+            size_t size = strlen(dir) + strlen(target) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) -C %s %s", dir, target);
+        }
+        chaz_MakeRule_add_command(rule, command);
+        free(command);
+    }
+    else if (chaz_Make.is_nmake) {
         command = (char*)malloc(strlen(dir) + 20);
-        sprintf(command, "make -C %s", dir);
+        sprintf(command, "cd %s", dir);
+        chaz_MakeRule_add_command(rule, command);
+        free(command);
+
+        if (!target) {
+            chaz_MakeRule_add_command(rule, "$(MAKE)");
+        }
+        else {
+            size_t size = strlen(target) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) %s", target);
+            chaz_MakeRule_add_command(rule, command);
+            free(command);
+        }
+
+        chaz_MakeRule_add_command(rule, "cd $(MAKEDIR)");
     }
     else {
-        command = (char*)malloc(strlen(dir) + strlen(target) + 20);
-        sprintf(command, "make -C %s %s", dir, target);
+        chaz_Util_die("Couldn't find a supported 'make' utility.");
     }
-
-    chaz_MakeRule_add_command(rule, command);
-
-    free(command);
 }
 
 void
@@ -3316,6 +3517,7 @@ chaz_Probe_init(struct chaz_CLIArgs *args) {
     chaz_CC_init(args->cc, args->cflags);
     chaz_ConfWriter_init();
     chaz_HeadCheck_init();
+    chaz_Make_init();
 
     /* Enable output. */
     if (args->charmony_h) {
@@ -3345,6 +3547,7 @@ chaz_Probe_clean_up(void) {
     /* Dispatch various clean up routines. */
     chaz_ConfWriter_clean_up();
     chaz_CC_clean_up();
+    chaz_Make_clean_up();
 
     if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); }
 }
@@ -3360,8 +3563,8 @@ chaz_Probe_gcc_version(void) {
 }
 
 int
-chaz_Probe_compiler_is_msvc(void) {
-    return chaz_CC_compiler_is_msvc();
+chaz_Probe_msvc_version_num(void) {
+    return chaz_CC_msvc_version_num();
 }
 
 /***************************************************************************/
@@ -4357,16 +4560,18 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
         /* Tell GCC explicitly to run with maximum options. */
         chaz_CC_add_extra_cflags("-std=gnu99 -D_GNU_SOURCE");
     }
-    else if (chaz_Probe_compiler_is_msvc()) {
+    else if (chaz_Probe_msvc_version_num()) {
         /* Compile as C++ under MSVC. */
-        chaz_CC_add_extra_cflags("-TP");
+        chaz_CC_add_extra_cflags("/TP");
 
         /* Thwart stupid warnings. */
-        chaz_CC_add_extra_cflags("-D_CRT_SECURE_NO_WARNINGS");
-        chaz_CC_add_extra_cflags("-D_SCL_SECURE_NO_WARNINGS");
+        chaz_CC_add_extra_cflags("/D_CRT_SECURE_NO_WARNINGS");
+        chaz_CC_add_extra_cflags("/D_SCL_SECURE_NO_WARNINGS");
 
-        /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */
-        chaz_CC_add_extra_cflags("-Dfor=\"if(0);else for\"");
+        if (chaz_Probe_msvc_version_num() < 1300) {
+            /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */
+            chaz_CC_add_extra_cflags("/Dfor=\"if(0);else for\"");
+        }
     }
 }
 
@@ -4441,15 +4646,19 @@ S_write_makefile() {
     chaz_MakeFile_add_var(makefile, "EXE_EXT", exe_ext);
     chaz_MakeFile_add_var(makefile, "OBJ_EXT", obj_ext);
 
-    chaz_MakeFile_add_var(makefile, "LEMON_EXE",
-                          "$(LEMON_DIR)" DIR_SEP "lemon$(EXE_EXT)");
+    chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
+
+    chaz_CC_set_optimization_level("2");
+    chaz_CC_add_include_dir(".");
+    chaz_CC_add_include_dir("$(INCLUDE_DIR)");
+    chaz_CC_add_include_dir("$(SRC_DIR)");
 
     var = chaz_MakeFile_add_var(makefile, "CFLAGS", NULL);
     chaz_MakeVar_append(var, chaz_CC_get_cflags());
     chaz_MakeVar_append(var, chaz_CC_get_extra_cflags());
-    chaz_MakeVar_append(var, "-I.");
-    chaz_MakeVar_append(var, "-I$(INCLUDE_DIR)");
-    chaz_MakeVar_append(var, "-I$(SRC_DIR)");
+
+    chaz_MakeFile_add_var(makefile, "LEMON_OBJS",
+                          "$(LEMON_DIR)" DIR_SEP "lemon$(OBJ_EXT)");
 
     sfc.common_objs   = chaz_MakeFile_add_var(makefile, "COMMON_OBJS", NULL);
     sfc.test_cfc_objs = chaz_MakeFile_add_var(makefile, "TEST_CFC_OBJS", NULL);
@@ -4461,6 +4670,9 @@ S_write_makefile() {
     chaz_MakeVar_append(sfc.test_cfc_objs, "t" DIR_SEP "test_cfc$(OBJ_EXT)");
 
     chaz_MakeFile_add_var(makefile, "CFC_OBJS", "cfc$(OBJ_EXT)");
+
+    chaz_MakeFile_add_var(makefile, "LEMON_EXE",
+                          "$(LEMON_DIR)" DIR_SEP "lemon$(EXE_EXT)");
     chaz_MakeFile_add_var(makefile, "CFC_EXE", "cfc$(EXE_EXT)");
     chaz_MakeFile_add_var(makefile, "TEST_CFC_EXE",
                           "t" DIR_SEP "test_cfc$(EXE_EXT)");
@@ -4469,8 +4681,7 @@ S_write_makefile() {
 
     chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)");
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(LEMON_EXE)", NULL);
-    chaz_MakeRule_add_command_make(rule, "$(LEMON_DIR)", NULL);
+    chaz_MakeFile_add_exe(makefile, "$(LEMON_EXE)", "$(LEMON_OBJS)");
 
     rule = chaz_MakeFile_add_rule(makefile, parse_header_c, NULL);
     chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
@@ -4490,6 +4701,7 @@ S_write_makefile() {
     rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_CFC_EXE)");
     chaz_MakeRule_add_command(rule, "$(TEST_CFC_EXE)");
 
+    chaz_MakeFile_add_to_cleanup(makefile, "$(LEMON_OBJS)");
     chaz_MakeFile_add_to_cleanup(makefile, "$(COMMON_OBJS)");
     chaz_MakeFile_add_to_cleanup(makefile, "$(CFC_OBJS)");
     chaz_MakeFile_add_to_cleanup(makefile, "$(TEST_CFC_OBJS)");

http://git-wip-us.apache.org/repos/asf/lucy/blob/369a995c/clownfish/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/common/charmonizer.c b/clownfish/runtime/common/charmonizer.c
index fcb9609..23f5cb1 100644
--- a/clownfish/runtime/common/charmonizer.c
+++ b/clownfish/runtime/common/charmonizer.c
@@ -93,6 +93,16 @@ chaz_CC_set_warnings_as_errors(const int flag);
 void
 chaz_CC_add_extra_cflags(const char *);
 
+/* Add include dir to extra cflags.
+ */
+void
+chaz_CC_add_include_dir(const char *dir);
+
+/* Set optimization level.
+ */
+void
+chaz_CC_set_optimization_level(const char *level);
+
 /* Accessor for the compiler executable's string representation.
  */
 const char*
@@ -109,25 +119,25 @@ const char*
 chaz_CC_get_extra_cflags(void);
 
 int
-chaz_CC_gcc_version_num();
+chaz_CC_gcc_version_num(void);
 
 const char*
-chaz_CC_gcc_version();
+chaz_CC_gcc_version(void);
 
 int
-chaz_CC_compiler_is_msvc(void);
+chaz_CC_msvc_version_num(void);
 
 const char*
-chaz_CC_link_command();
+chaz_CC_link_command(void);
 
 const char*
-chaz_CC_link_flags();
+chaz_CC_link_flags(void);
 
 const char*
-chaz_CC_link_shared_obj_flag();
+chaz_CC_link_shared_obj_flag(void);
 
 const char*
-chaz_CC_link_output_flag();
+chaz_CC_link_output_flag(void);
 
 #endif /* H_CHAZ_COMPILER */
 
@@ -351,6 +361,15 @@ typedef struct chaz_MakeRule chaz_MakeRule;
 typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
 
 void
+chaz_Make_init(void);
+
+void
+chaz_Make_clean_up(void);
+
+const char*
+chaz_Make_get_make(void);
+
+void
 chaz_Make_list_files(const char *dir, const char *ext,
                      chaz_Make_list_files_callback_t callback, void *context);
 
@@ -631,10 +650,10 @@ chaz_Probe_gcc_version_num(void);
 const char*
 chaz_Probe_gcc_version(void);
 
-/* Returns true if the compiler is MSVC.
+/* Return the integer version of MSVC defined by _MSC_VER
  */
 int
-chaz_Probe_compiler_is_msvc(void);
+chaz_Probe_msvc_version_num(void);
 
 #endif /* Include guard. */
 
@@ -1527,6 +1546,34 @@ chaz_CC_add_extra_cflags(const char *flags) {
     }
 }
 
+void
+chaz_CC_add_include_dir(const char *dir) {
+    size_t size = strlen(chaz_CC.include_flag) + strlen(dir) + 1;
+    char *flag = (char*)malloc(size);
+    sprintf(flag, "%s%s", chaz_CC.include_flag, dir);
+    chaz_CC_add_extra_cflags(flag);
+    free(flag);
+}
+
+void
+chaz_CC_set_optimization_level(const char *level) {
+    const char *opt_flag;
+    char *flag;
+    size_t size;
+
+    if (chaz_CC.intval__MSC_VER) {
+        opt_flag = "/O";
+    }
+    else {
+        opt_flag = "-O";
+    }
+    size = strlen(opt_flag) + strlen(level) + 1;
+    flag = (char*)malloc(size);
+    sprintf(flag, "%s%s", opt_flag, level);
+    chaz_CC_add_extra_cflags(flag);
+    free(flag);
+}
+
 const char*
 chaz_CC_get_cc(void) {
     return chaz_CC.cc_command;
@@ -1555,8 +1602,8 @@ chaz_CC_gcc_version(void) {
 }
 
 int
-chaz_CC_compiler_is_msvc(void) {
-    return !!chaz_CC.intval__MSC_VER;
+chaz_CC_msvc_version_num(void) {
+    return chaz_CC.intval__MSC_VER;
 }
 
 const char*
@@ -2731,6 +2778,110 @@ struct chaz_MakeFile {
     size_t          num_cleanups;
 };
 
+/* Static vars. */
+static struct {
+    char *make_command;
+    int   is_gnu_make;
+    int   is_nmake;
+} chaz_Make = {
+    NULL,
+    0, 0
+};
+
+/* Detect make command.
+ *
+ * The argument list must be a NULL-terminated series of different spellings
+ * of `make`, which will be auditioned in the order they are supplied.  Here
+ * are several possibilities:
+ *
+ *      make
+ *      gmake
+ *      nmake
+ *      dmake
+ */
+static int
+chaz_Make_detect(const char *make1, ...);
+
+static int
+chaz_Make_audition(const char *make);
+
+void
+chaz_Make_init(void) {
+    const char *make;
+
+    chaz_Make_detect("make", "gmake", "nmake", "dmake", NULL);
+    make = chaz_Make.make_command;
+
+    if (make) {
+        if (strcmp(make, "make") == 0 || strcmp(make, "gmake") == 0) {
+            /* TODO: Add a feature test for GNU make. */
+            chaz_Make.is_gnu_make = 1;
+        }
+        else if (strcmp(make, "nmake") == 0) {
+            chaz_Make.is_nmake = 1;
+        }
+    }
+}
+
+void
+chaz_Make_clean_up(void) {
+    free(chaz_Make.make_command);
+}
+
+const char*
+chaz_Make_get_make(void) {
+    return chaz_Make.make_command;
+}
+
+static int
+chaz_Make_detect(const char *make1, ...) {
+    va_list args;
+    const char *candidate;
+    int found = 0;
+    const char makefile_content[] = "foo:\n\techo \"foo!\"\n";
+    chaz_Util_write_file("_charm_Makefile", makefile_content);
+
+    /* Audition candidates. */
+    found = chaz_Make_audition(make1);
+    va_start(args, make1);
+    while (!found && (NULL != (candidate = va_arg(args, const char*)))) {
+        found = chaz_Make_audition(candidate);
+    }
+    va_end(args);
+
+    chaz_Util_remove_and_verify("_charm_Makefile");
+
+    return found;
+}
+
+static int
+chaz_Make_audition(const char *make) {
+    int succeeded = 0;
+    const char pattern[] = "%s -f _charm_Makefile";
+    size_t size = strlen(make) + sizeof(pattern) + 10;
+    char *command = (char*)malloc(size);
+    sprintf(command, pattern, make);
+
+    chaz_Util_remove_and_verify("_charm_foo");
+    chaz_OS_run_redirected(command, "_charm_foo");
+    if (chaz_Util_can_open_file("_charm_foo")) {
+        size_t len;
+        char *content = chaz_Util_slurp_file("_charm_foo", &len);
+        if (NULL != strstr(content, "foo!")) {
+            succeeded = 1;
+        }
+        free(content);
+    }
+    chaz_Util_remove_and_verify("_charm_foo");
+
+    if (succeeded) {
+        chaz_Make.make_command = chaz_Util_strdup(make);
+    }
+
+    free(command);
+    return succeeded;
+}
+
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
@@ -2869,6 +3020,7 @@ chaz_MakeFile_add_shared_obj(chaz_MakeFile *makefile, const char *shared_obj,
 
 void
 chaz_MakeFile_write(chaz_MakeFile *makefile) {
+    int     shell_type = chaz_OS_shell_type();
     FILE   *file;
     size_t  i;
 
@@ -2897,16 +3049,40 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
     }
 
     if (makefile->cleanups[0]) {
-        fprintf(file, "clean :\n\trm -f");
-        for (i = 0; makefile->cleanups[i]; i++) {
-            char *cleanup = makefile->cleanups[i];
-            fprintf(file, " \\\n\t    %s", cleanup);
+        if (shell_type == CHAZ_OS_POSIX) {
+            fprintf(file, "clean :\n\trm -f");
+            for (i = 0; makefile->cleanups[i]; i++) {
+                const char *cleanup = makefile->cleanups[i];
+                fprintf(file, " \\\n\t    %s", cleanup);
+            }
+            fprintf(file, "\n\n");
+        }
+        else if (shell_type == CHAZ_OS_CMD_EXE) {
+            fprintf(file, "clean :\n");
+            for (i = 0; makefile->cleanups[i]; i++) {
+                const char *cleanup = makefile->cleanups[i];
+                fprintf(file, "\tfor %%i in (%s) do if exist %%i del /f %%i\n",
+                        cleanup);
+            }
+            fprintf(file, "\n");
+        }
+        else {
+            chaz_Util_die("Unsupported shell type: %d", shell_type);
         }
-        fprintf(file, "\n\n");
     }
 
     fprintf(file, "distclean : clean\n");
-    fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n");
+    if (shell_type == CHAZ_OS_POSIX) {
+        fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n");
+    }
+    else if (shell_type == CHAZ_OS_CMD_EXE) {
+        fprintf(file,
+            "\tfor %%i in (charmonizer charmony.h Makefile) do"
+            " if exist %%i del /f %%i\n\n");
+    }
+    else {
+        chaz_Util_die("Unsupported shell type: %d", shell_type);
+    }
 
     fclose(file);
 }
@@ -2988,20 +3164,45 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command)
{
 void
 chaz_MakeRule_add_command_make(chaz_MakeRule *rule, const char *dir,
                                const char *target) {
+    const char *make = chaz_Make.make_command;
     char *command;
 
-    if (!target) {
+    if (chaz_Make.is_gnu_make) {
+        if (!target) {
+            size_t size = strlen(dir) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) -C %s", dir);
+        }
+        else {
+            size_t size = strlen(dir) + strlen(target) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) -C %s %s", dir, target);
+        }
+        chaz_MakeRule_add_command(rule, command);
+        free(command);
+    }
+    else if (chaz_Make.is_nmake) {
         command = (char*)malloc(strlen(dir) + 20);
-        sprintf(command, "make -C %s", dir);
+        sprintf(command, "cd %s", dir);
+        chaz_MakeRule_add_command(rule, command);
+        free(command);
+
+        if (!target) {
+            chaz_MakeRule_add_command(rule, "$(MAKE)");
+        }
+        else {
+            size_t size = strlen(target) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) %s", target);
+            chaz_MakeRule_add_command(rule, command);
+            free(command);
+        }
+
+        chaz_MakeRule_add_command(rule, "cd $(MAKEDIR)");
     }
     else {
-        command = (char*)malloc(strlen(dir) + strlen(target) + 20);
-        sprintf(command, "make -C %s %s", dir, target);
+        chaz_Util_die("Couldn't find a supported 'make' utility.");
     }
-
-    chaz_MakeRule_add_command(rule, command);
-
-    free(command);
 }
 
 void
@@ -3598,6 +3799,7 @@ chaz_Probe_init(struct chaz_CLIArgs *args) {
     chaz_CC_init(args->cc, args->cflags);
     chaz_ConfWriter_init();
     chaz_HeadCheck_init();
+    chaz_Make_init();
 
     /* Enable output. */
     if (args->charmony_h) {
@@ -3627,6 +3829,7 @@ chaz_Probe_clean_up(void) {
     /* Dispatch various clean up routines. */
     chaz_ConfWriter_clean_up();
     chaz_CC_clean_up();
+    chaz_Make_clean_up();
 
     if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); }
 }
@@ -3642,8 +3845,8 @@ chaz_Probe_gcc_version(void) {
 }
 
 int
-chaz_Probe_compiler_is_msvc(void) {
-    return chaz_CC_compiler_is_msvc();
+chaz_Probe_msvc_version_num(void) {
+    return chaz_CC_msvc_version_num();
 }
 
 /***************************************************************************/
@@ -5486,17 +5689,6 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
         /* Only core source files require this -- not our headers and
          * autogenerated files. */
         chaz_CC_add_extra_cflags("-std=gnu99 -D_GNU_SOURCE");
-    }
-    else if (chaz_Probe_compiler_is_msvc()) {
-        /* Compile as C++ under MSVC. */
-        chaz_CC_add_extra_cflags("/TP");
-
-        /* Thwart stupid warnings. */
-        chaz_CC_add_extra_cflags("-D_CRT_SECURE_NO_WARNINGS");
-        chaz_CC_add_extra_cflags("-D_SCL_SECURE_NO_WARNINGS");
-
-        /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */
-        chaz_CC_add_extra_cflags("-Dfor=\"if(0);else for\"");
 
         /* When compiling for Perl bindings, define HAS_BOOL so that the Perl
          * headers don't redefine 'bool' in conflict with C++.
@@ -5508,6 +5700,23 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
             chaz_CC_add_extra_cflags("-DHAS_BOOL");
         }
     }
+    else if (chaz_Probe_msvc_version_num()) {
+        /* Compile as C++ under MSVC. */
+        chaz_CC_add_extra_cflags("/TP");
+
+        /* Thwart stupid warnings. */
+        chaz_CC_add_extra_cflags("/D_CRT_SECURE_NO_WARNINGS");
+        chaz_CC_add_extra_cflags("/D_SCL_SECURE_NO_WARNINGS");
+
+        if (chaz_Probe_msvc_version_num() < 1300) {
+            /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */
+            chaz_CC_add_extra_cflags("/Dfor=\"if(0);else for\"");
+        }
+
+        if (args->charmony_pm) {
+            chaz_CC_add_extra_cflags("/DHAS_BOOL");
+        }
+    }
 }
 
 int main(int argc, const char **argv) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/369a995c/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 8a4feeb..4c5275d 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -93,6 +93,16 @@ chaz_CC_set_warnings_as_errors(const int flag);
 void
 chaz_CC_add_extra_cflags(const char *);
 
+/* Add include dir to extra cflags.
+ */
+void
+chaz_CC_add_include_dir(const char *dir);
+
+/* Set optimization level.
+ */
+void
+chaz_CC_set_optimization_level(const char *level);
+
 /* Accessor for the compiler executable's string representation.
  */
 const char*
@@ -109,25 +119,25 @@ const char*
 chaz_CC_get_extra_cflags(void);
 
 int
-chaz_CC_gcc_version_num();
+chaz_CC_gcc_version_num(void);
 
 const char*
-chaz_CC_gcc_version();
+chaz_CC_gcc_version(void);
 
 int
-chaz_CC_compiler_is_msvc(void);
+chaz_CC_msvc_version_num(void);
 
 const char*
-chaz_CC_link_command();
+chaz_CC_link_command(void);
 
 const char*
-chaz_CC_link_flags();
+chaz_CC_link_flags(void);
 
 const char*
-chaz_CC_link_shared_obj_flag();
+chaz_CC_link_shared_obj_flag(void);
 
 const char*
-chaz_CC_link_output_flag();
+chaz_CC_link_output_flag(void);
 
 #endif /* H_CHAZ_COMPILER */
 
@@ -351,6 +361,15 @@ typedef struct chaz_MakeRule chaz_MakeRule;
 typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
 
 void
+chaz_Make_init(void);
+
+void
+chaz_Make_clean_up(void);
+
+const char*
+chaz_Make_get_make(void);
+
+void
 chaz_Make_list_files(const char *dir, const char *ext,
                      chaz_Make_list_files_callback_t callback, void *context);
 
@@ -631,10 +650,10 @@ chaz_Probe_gcc_version_num(void);
 const char*
 chaz_Probe_gcc_version(void);
 
-/* Returns true if the compiler is MSVC.
+/* Return the integer version of MSVC defined by _MSC_VER
  */
 int
-chaz_Probe_compiler_is_msvc(void);
+chaz_Probe_msvc_version_num(void);
 
 #endif /* Include guard. */
 
@@ -1527,6 +1546,34 @@ chaz_CC_add_extra_cflags(const char *flags) {
     }
 }
 
+void
+chaz_CC_add_include_dir(const char *dir) {
+    size_t size = strlen(chaz_CC.include_flag) + strlen(dir) + 1;
+    char *flag = (char*)malloc(size);
+    sprintf(flag, "%s%s", chaz_CC.include_flag, dir);
+    chaz_CC_add_extra_cflags(flag);
+    free(flag);
+}
+
+void
+chaz_CC_set_optimization_level(const char *level) {
+    const char *opt_flag;
+    char *flag;
+    size_t size;
+
+    if (chaz_CC.intval__MSC_VER) {
+        opt_flag = "/O";
+    }
+    else {
+        opt_flag = "-O";
+    }
+    size = strlen(opt_flag) + strlen(level) + 1;
+    flag = (char*)malloc(size);
+    sprintf(flag, "%s%s", opt_flag, level);
+    chaz_CC_add_extra_cflags(flag);
+    free(flag);
+}
+
 const char*
 chaz_CC_get_cc(void) {
     return chaz_CC.cc_command;
@@ -1555,8 +1602,8 @@ chaz_CC_gcc_version(void) {
 }
 
 int
-chaz_CC_compiler_is_msvc(void) {
-    return !!chaz_CC.intval__MSC_VER;
+chaz_CC_msvc_version_num(void) {
+    return chaz_CC.intval__MSC_VER;
 }
 
 const char*
@@ -2731,6 +2778,110 @@ struct chaz_MakeFile {
     size_t          num_cleanups;
 };
 
+/* Static vars. */
+static struct {
+    char *make_command;
+    int   is_gnu_make;
+    int   is_nmake;
+} chaz_Make = {
+    NULL,
+    0, 0
+};
+
+/* Detect make command.
+ *
+ * The argument list must be a NULL-terminated series of different spellings
+ * of `make`, which will be auditioned in the order they are supplied.  Here
+ * are several possibilities:
+ *
+ *      make
+ *      gmake
+ *      nmake
+ *      dmake
+ */
+static int
+chaz_Make_detect(const char *make1, ...);
+
+static int
+chaz_Make_audition(const char *make);
+
+void
+chaz_Make_init(void) {
+    const char *make;
+
+    chaz_Make_detect("make", "gmake", "nmake", "dmake", NULL);
+    make = chaz_Make.make_command;
+
+    if (make) {
+        if (strcmp(make, "make") == 0 || strcmp(make, "gmake") == 0) {
+            /* TODO: Add a feature test for GNU make. */
+            chaz_Make.is_gnu_make = 1;
+        }
+        else if (strcmp(make, "nmake") == 0) {
+            chaz_Make.is_nmake = 1;
+        }
+    }
+}
+
+void
+chaz_Make_clean_up(void) {
+    free(chaz_Make.make_command);
+}
+
+const char*
+chaz_Make_get_make(void) {
+    return chaz_Make.make_command;
+}
+
+static int
+chaz_Make_detect(const char *make1, ...) {
+    va_list args;
+    const char *candidate;
+    int found = 0;
+    const char makefile_content[] = "foo:\n\techo \"foo!\"\n";
+    chaz_Util_write_file("_charm_Makefile", makefile_content);
+
+    /* Audition candidates. */
+    found = chaz_Make_audition(make1);
+    va_start(args, make1);
+    while (!found && (NULL != (candidate = va_arg(args, const char*)))) {
+        found = chaz_Make_audition(candidate);
+    }
+    va_end(args);
+
+    chaz_Util_remove_and_verify("_charm_Makefile");
+
+    return found;
+}
+
+static int
+chaz_Make_audition(const char *make) {
+    int succeeded = 0;
+    const char pattern[] = "%s -f _charm_Makefile";
+    size_t size = strlen(make) + sizeof(pattern) + 10;
+    char *command = (char*)malloc(size);
+    sprintf(command, pattern, make);
+
+    chaz_Util_remove_and_verify("_charm_foo");
+    chaz_OS_run_redirected(command, "_charm_foo");
+    if (chaz_Util_can_open_file("_charm_foo")) {
+        size_t len;
+        char *content = chaz_Util_slurp_file("_charm_foo", &len);
+        if (NULL != strstr(content, "foo!")) {
+            succeeded = 1;
+        }
+        free(content);
+    }
+    chaz_Util_remove_and_verify("_charm_foo");
+
+    if (succeeded) {
+        chaz_Make.make_command = chaz_Util_strdup(make);
+    }
+
+    free(command);
+    return succeeded;
+}
+
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
@@ -2869,6 +3020,7 @@ chaz_MakeFile_add_shared_obj(chaz_MakeFile *makefile, const char *shared_obj,
 
 void
 chaz_MakeFile_write(chaz_MakeFile *makefile) {
+    int     shell_type = chaz_OS_shell_type();
     FILE   *file;
     size_t  i;
 
@@ -2897,16 +3049,40 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
     }
 
     if (makefile->cleanups[0]) {
-        fprintf(file, "clean :\n\trm -f");
-        for (i = 0; makefile->cleanups[i]; i++) {
-            char *cleanup = makefile->cleanups[i];
-            fprintf(file, " \\\n\t    %s", cleanup);
+        if (shell_type == CHAZ_OS_POSIX) {
+            fprintf(file, "clean :\n\trm -f");
+            for (i = 0; makefile->cleanups[i]; i++) {
+                const char *cleanup = makefile->cleanups[i];
+                fprintf(file, " \\\n\t    %s", cleanup);
+            }
+            fprintf(file, "\n\n");
+        }
+        else if (shell_type == CHAZ_OS_CMD_EXE) {
+            fprintf(file, "clean :\n");
+            for (i = 0; makefile->cleanups[i]; i++) {
+                const char *cleanup = makefile->cleanups[i];
+                fprintf(file, "\tfor %%i in (%s) do if exist %%i del /f %%i\n",
+                        cleanup);
+            }
+            fprintf(file, "\n");
+        }
+        else {
+            chaz_Util_die("Unsupported shell type: %d", shell_type);
         }
-        fprintf(file, "\n\n");
     }
 
     fprintf(file, "distclean : clean\n");
-    fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n");
+    if (shell_type == CHAZ_OS_POSIX) {
+        fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n");
+    }
+    else if (shell_type == CHAZ_OS_CMD_EXE) {
+        fprintf(file,
+            "\tfor %%i in (charmonizer charmony.h Makefile) do"
+            " if exist %%i del /f %%i\n\n");
+    }
+    else {
+        chaz_Util_die("Unsupported shell type: %d", shell_type);
+    }
 
     fclose(file);
 }
@@ -2988,20 +3164,45 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command)
{
 void
 chaz_MakeRule_add_command_make(chaz_MakeRule *rule, const char *dir,
                                const char *target) {
+    const char *make = chaz_Make.make_command;
     char *command;
 
-    if (!target) {
+    if (chaz_Make.is_gnu_make) {
+        if (!target) {
+            size_t size = strlen(dir) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) -C %s", dir);
+        }
+        else {
+            size_t size = strlen(dir) + strlen(target) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) -C %s %s", dir, target);
+        }
+        chaz_MakeRule_add_command(rule, command);
+        free(command);
+    }
+    else if (chaz_Make.is_nmake) {
         command = (char*)malloc(strlen(dir) + 20);
-        sprintf(command, "make -C %s", dir);
+        sprintf(command, "cd %s", dir);
+        chaz_MakeRule_add_command(rule, command);
+        free(command);
+
+        if (!target) {
+            chaz_MakeRule_add_command(rule, "$(MAKE)");
+        }
+        else {
+            size_t size = strlen(target) + 20;
+            command = (char*)malloc(size);
+            sprintf(command, "$(MAKE) %s", target);
+            chaz_MakeRule_add_command(rule, command);
+            free(command);
+        }
+
+        chaz_MakeRule_add_command(rule, "cd $(MAKEDIR)");
     }
     else {
-        command = (char*)malloc(strlen(dir) + strlen(target) + 20);
-        sprintf(command, "make -C %s %s", dir, target);
+        chaz_Util_die("Couldn't find a supported 'make' utility.");
     }
-
-    chaz_MakeRule_add_command(rule, command);
-
-    free(command);
 }
 
 void
@@ -3598,6 +3799,7 @@ chaz_Probe_init(struct chaz_CLIArgs *args) {
     chaz_CC_init(args->cc, args->cflags);
     chaz_ConfWriter_init();
     chaz_HeadCheck_init();
+    chaz_Make_init();
 
     /* Enable output. */
     if (args->charmony_h) {
@@ -3627,6 +3829,7 @@ chaz_Probe_clean_up(void) {
     /* Dispatch various clean up routines. */
     chaz_ConfWriter_clean_up();
     chaz_CC_clean_up();
+    chaz_Make_clean_up();
 
     if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); }
 }
@@ -3642,8 +3845,8 @@ chaz_Probe_gcc_version(void) {
 }
 
 int
-chaz_Probe_compiler_is_msvc(void) {
-    return chaz_CC_compiler_is_msvc();
+chaz_Probe_msvc_version_num(void) {
+    return chaz_CC_msvc_version_num();
 }
 
 /***************************************************************************/
@@ -5485,27 +5688,33 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
         /* Only core source files require this -- not our headers and
          * autogenerated files. */
         chaz_CC_add_extra_cflags("-std=gnu99 -D_GNU_SOURCE");
+
+        /* When compiling for Perl bindings, define HAS_BOOL so that the Perl
+         * headers don't redefine 'bool' in conflict with C++.
+         *
+         * TODO: Compile all files that #include Perl headers separately and
+         * remove this directive.
+         */
+        if (args->charmony_pm) {
+            chaz_CC_add_extra_cflags("-DHAS_BOOL");
+        }
     }
-    else if (chaz_Probe_compiler_is_msvc()) {
+    else if (chaz_Probe_msvc_version_num()) {
         /* Compile as C++ under MSVC. */
         chaz_CC_add_extra_cflags("/TP");
 
         /* Thwart stupid warnings. */
-        chaz_CC_add_extra_cflags("-D_CRT_SECURE_NO_WARNINGS");
-        chaz_CC_add_extra_cflags("-D_SCL_SECURE_NO_WARNINGS");
+        chaz_CC_add_extra_cflags("/D_CRT_SECURE_NO_WARNINGS");
+        chaz_CC_add_extra_cflags("/D_SCL_SECURE_NO_WARNINGS");
 
-        /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */
-        chaz_CC_add_extra_cflags("-Dfor=\"if(0);else for\"");
-    }
+        if (chaz_Probe_msvc_version_num() < 1300) {
+            /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */
+            chaz_CC_add_extra_cflags("/Dfor=\"if(0);else for\"");
+        }
 
-    /* When compiling for Perl bindings, define HAS_BOOL so that the Perl
-     * headers don't redefine 'bool' in conflict with C++.
-     *
-     * TODO: Compile all files that #include Perl headers separately and
-     * remove this directive.
-     */
-    if (args->charmony_pm) {
-        chaz_CC_add_extra_cflags("-DHAS_BOOL");
+        if (args->charmony_pm) {
+            chaz_CC_add_extra_cflags("/DHAS_BOOL");
+        }
     }
 }
 


Mime
View raw message