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/0df0a4f6
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/0df0a4f6
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/0df0a4f6

Branch: refs/heads/perl_build_with_make
Commit: 0df0a4f650c7f77744b147cf49054e687d39b31d
Parents: 390395e
Author: Nick Wellnhofer <[email protected]>
Authored: Sat Nov 8 18:27:01 2014 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Sat Nov 8 19:51:56 2014 +0100

----------------------------------------------------------------------
 common/charmonizer.c | 734 ++++++++++++++++++++++++++++------------------
 1 file changed, 441 insertions(+), 293 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/0df0a4f6/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 5ec0079..465938b 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -622,9 +622,11 @@ typedef void (*chaz_Make_list_files_callback_t)(const char 
*dir, char *file,
                                                 void *context);
 
 /** Initialize the environment.
+ *
+ * @param make_command Name of the make command. Auto-detect if NULL.
  */
 void
-chaz_Make_init(void);
+chaz_Make_init(const char *make_command);
 
 /** Clean up the environment.
  */
@@ -4332,15 +4334,17 @@ static void
 S_write_rule(chaz_MakeRule *rule, FILE *out);
 
 void
-chaz_Make_init(void) {
-    const char *make;
-
-    chaz_Make_detect("make", "gmake", "nmake", "dmake", "mingw32-make",
-                     "mingw64-make", NULL);
-    make = chaz_Make.make_command;
+chaz_Make_init(const char *make_command) {
+    if (make_command) {
+        chaz_Make.make_command = chaz_Util_strdup(make_command);
+    }
+    else {
+        chaz_Make_detect("make", "gmake", "nmake", "dmake", "mingw32-make",
+                         "mingw64-make", NULL);
+    }
 
-    if (make) {
-        if (strcmp(make, "nmake") == 0) {
+    if (chaz_Make.make_command) {
+        if (strcmp(chaz_Make.make_command, "nmake") == 0) {
             chaz_Make.shell_type = CHAZ_OS_CMD_EXE;
         }
         else {
@@ -5554,6 +5558,7 @@ chaz_Probe_parse_cli_args(int argc, const char *argv[], 
chaz_CLI *cli) {
     chaz_CLI_register(cli, "enable-coverage", NULL, CHAZ_CLI_NO_ARG);
     chaz_CLI_register(cli, "cc", "compiler command", CHAZ_CLI_ARG_REQUIRED);
     chaz_CLI_register(cli, "cflags", NULL, CHAZ_CLI_ARG_REQUIRED);
+    chaz_CLI_register(cli, "make", "make command", 0);
 
     /* Parse options, exiting on failure. */
     if (!chaz_CLI_parse(cli, argc, argv)) {
@@ -5642,7 +5647,7 @@ chaz_Probe_init(struct chaz_CLI *cli) {
     chaz_CC_init(chaz_CLI_strval(cli, "cc"), chaz_CLI_strval(cli, "cflags"));
     chaz_ConfWriter_init();
     chaz_HeadCheck_init();
-    chaz_Make_init();
+    chaz_Make_init(chaz_CLI_strval(cli, "make"));
 
     /* Enable output. */
     if (chaz_CLI_defined(cli, "enable-c")) {
@@ -7712,6 +7717,40 @@ chaz_VariadicMacros_run(void) {
 /* #include "Charmonizer/Core/ConfWriterPerl.h" */
 /* #include "Charmonizer/Core/ConfWriterRuby.h" */
 
+typedef struct lucy_MakeFile {
+    chaz_MakeFile *makefile;
+    chaz_CLI      *cli;
+
+    /* Directories. */
+    const char *base_dir;
+    char       *core_dir;
+    const char *host_src_dir;
+    char       *autogen_src_dir;
+    char       *autogen_inc_dir;
+    char       *lemon_dir;
+    char       *modules_dir;
+    char       *snowstem_dir;
+    char       *snowstem_inc_dir;
+    char       *snowstop_dir;
+    char       *ucd_dir;
+    char       *utf8proc_dir;
+
+    /* Files. */
+    char        *autogen_target;
+    const char **autogen_src_files;
+    char        *json_parser;
+
+    /* Clownfish library. */
+    char       *cfish_lib_dir;
+    const char *cfish_lib_name;
+
+    /* Lucy libraries. */
+    chaz_Lib *shared_lib;
+    chaz_Lib *static_lib;
+    char     *shared_lib_filename;
+    char     *static_lib_filename;
+} lucy_MakeFile;
+
 typedef struct SourceFileContext {
     chaz_MakeVar *var;
 } SourceFileContext;
@@ -7720,6 +7759,111 @@ static const char lucy_version[]        = "0.4.0";
 static const char lucy_major_version[]  = "0.4";
 
 static void
+S_add_compiler_flags(struct chaz_CLI *cli);
+
+static lucy_MakeFile*
+lucy_MakeFile_new(chaz_CLI *cli);
+
+static void
+lucy_MakeFile_destroy(lucy_MakeFile *self);
+
+static void
+lucy_MakeFile_write(lucy_MakeFile *self);
+
+static void
+lucy_MakeFile_write_c_cfc_rules(lucy_MakeFile *self);
+
+static void
+lucy_MakeFile_write_c_test_rules(lucy_MakeFile *self);
+
+static void
+S_c_file_callback(const char *dir, char *file, void *context);
+
+static void
+S_cfh_file_callback(const char *dir, char *file, void *context);
+
+static int
+S_ends_with(const char *string, const char *postfix);
+
+int main(int argc, const char **argv) {
+    /* Initialize. */
+    chaz_CLI *cli
+        = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment");
+    chaz_CLI_register(cli, "clownfish-prefix",
+                      "prefix of Clownfish installation",
+                      CHAZ_CLI_ARG_OPTIONAL);
+    chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]");
+    if (!chaz_Probe_parse_cli_args(argc, argv, cli)) {
+        chaz_Probe_die_usage();
+    }
+    chaz_Probe_init(cli);
+    S_add_compiler_flags(cli);
+
+    /* Employ integer features but don't define stdint types in charmony.h. */
+    chaz_ConfWriter_append_conf(
+        "#define CHY_EMPLOY_INTEGERLIMITS\n"
+        "#define CHY_EMPLOY_INTEGERLITERALS\n"
+        "#define CHY_EMPLOY_INTEGERFORMATSTRINGS\n\n"
+    );
+
+    /* Run probe modules. Booleans is only needed for the Charmonizer tests. */
+    chaz_BuildEnv_run();
+    chaz_DirManip_run();
+    chaz_Headers_run();
+    chaz_Booleans_run();
+    chaz_Integers_run();
+    chaz_Floats_run();
+    chaz_LargeFiles_run();
+    chaz_Memory_run();
+    chaz_RegularExpressions_run();
+    chaz_VariadicMacros_run();
+
+    /* Write custom postamble. */
+    chaz_ConfWriter_append_conf(
+        "#ifdef CHY_HAS_SYS_TYPES_H\n"
+        "  #include <sys/types.h>\n"
+        "#endif\n\n"
+    );
+    chaz_ConfWriter_append_conf(
+        "#ifdef CHY_HAS_ALLOCA_H\n"
+        "  #include <alloca.h>\n"
+        "#elif defined(CHY_HAS_MALLOC_H)\n"
+        "  #include <malloc.h>\n"
+        "#elif defined(CHY_ALLOCA_IN_STDLIB_H)\n"
+        "  #include <stdlib.h>\n"
+        "#endif\n\n"
+    );
+    chaz_ConfWriter_append_conf(
+        "#ifdef CHY_HAS_WINDOWS_H\n"
+        "  /* Target Windows XP. */\n"
+        "  #ifndef WINVER\n"
+        "    #define WINVER 0x0500\n"
+        "  #endif\n"
+        "  #ifndef _WIN32_WINNT\n"
+        "    #define _WIN32_WINNT 0x0500\n"
+        "  #endif\n"
+        "#endif\n\n"
+    );
+
+    if (chaz_CLI_defined(cli, "enable-makefile")) {
+        lucy_MakeFile *mf = lucy_MakeFile_new(cli);
+        lucy_MakeFile_write(mf);
+        /* Export filenames. */
+        chaz_ConfWriter_add_def("SHARED_LIB_FILENAME",
+                                mf->shared_lib_filename);
+        chaz_ConfWriter_add_def("STATIC_LIB_FILENAME",
+                                mf->static_lib_filename);
+        lucy_MakeFile_destroy(mf);
+    }
+
+    /* Clean up. */
+    chaz_CLI_destroy(cli);
+    chaz_Probe_clean_up();
+
+    return 0;
+}
+
+static void
 S_add_compiler_flags(struct chaz_CLI *cli) {
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
 
@@ -7760,87 +7904,132 @@ S_add_compiler_flags(struct chaz_CLI *cli) {
     chaz_CFlags_hide_symbols(extra_cflags);
 }
 
-static int
-S_ends_with(const char *string, const char *postfix) {
-    size_t len         = strlen(string);
-    size_t postfix_len = strlen(postfix);
-    return len >= postfix_len
-           && memcmp(string + len - postfix_len, postfix, postfix_len) == 0;
-}
+static lucy_MakeFile*
+lucy_MakeFile_new(chaz_CLI *cli) {
+    const char *dir_sep      = chaz_OS_dir_sep();
+    const char *cfish_prefix = chaz_CLI_strval(cli, "clownfish-prefix");
 
-static void
-S_c_file_callback(const char *dir, char *file, void *context) {
-    SourceFileContext *sfc = (SourceFileContext*)context;
-    const char *dir_sep = chaz_OS_dir_sep();
-    const char *obj_ext = chaz_CC_obj_ext();
-    size_t file_len = strlen(file);
-    char *obj_file;
+    lucy_MakeFile *self = malloc(sizeof(lucy_MakeFile));
 
-    /* Strip extension */
-    if (!S_ends_with(file, ".c")) {
-        chaz_Util_warn("Unexpected C filename: %s", file);
-        return;
+    self->makefile = chaz_MakeFile_new();
+    self->cli      = cli;
+
+    /* Initialize directories. */
+    self->base_dir = "..";
+    self->core_dir = chaz_Util_join(dir_sep, self->base_dir, "core", NULL);
+    if (chaz_CLI_defined(cli, "enable-perl")) {
+        self->host_src_dir = "xs";
     }
-    file[file_len-2] = '\0';
+    else {
+        self->host_src_dir = "src";
+    }
+    self->autogen_src_dir = chaz_Util_join(dir_sep, "autogen", "source", NULL);
+    self->autogen_inc_dir
+        = chaz_Util_join(dir_sep, "autogen", "include", NULL);
+    self->lemon_dir = chaz_Util_join(dir_sep, self->base_dir, "lemon", NULL);
+    self->modules_dir
+        = chaz_Util_join(dir_sep, self->base_dir, "modules", NULL);
+    self->snowstem_dir
+        = chaz_Util_join(dir_sep, self->modules_dir, "analysis", "snowstem",
+                         "source", NULL);
+    self->snowstem_inc_dir
+        = chaz_Util_join(dir_sep, self->snowstem_dir, "include", NULL);
+    self->snowstop_dir
+        = chaz_Util_join(dir_sep, self->modules_dir, "analysis", "snowstop",
+                         "source", NULL);
+    self->ucd_dir
+        = chaz_Util_join(dir_sep, self->modules_dir, "unicode", "ucd", NULL);
+    self->utf8proc_dir
+        = chaz_Util_join(dir_sep, self->modules_dir, "unicode", "utf8proc",
+                         NULL);
+
+    /* Initialize file names. */
+    if (chaz_CLI_defined(cli, "enable-perl")) {
+        static const char *perl_autogen_src_files[] = {
+            "boot",
+            "callbacks",
+            "lucy_parcel",
+            "testlucy_parcel",
+            NULL
+        };
+        self->autogen_src_files = perl_autogen_src_files;
+    }
+    else {
+        static const char *c_autogen_src_files[] = {
+            "lucy_parcel",
+            "testlucy_parcel",
+            NULL
+        };
+        self->autogen_src_files = c_autogen_src_files;
+    }
+    self->autogen_target
+        = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL);
+    self->json_parser
+        = chaz_Util_join(dir_sep, self->core_dir, "Lucy", "Util", "Json",
+                         "JsonParser", NULL);
 
-    if (!S_ends_with(file, "JsonParser")) {
-        obj_file = chaz_Util_join("", dir, dir_sep, file, obj_ext, NULL);
-        chaz_MakeVar_append(sfc->var, obj_file);
-        free(obj_file);
+    /* Clownfish library. */
+    if (cfish_prefix) {
+        self->cfish_lib_dir
+            = chaz_Util_join(dir_sep, cfish_prefix, "lib", NULL);
     }
+    else {
+        self->cfish_lib_dir = NULL;
+    }
+    if (strcmp(chaz_OS_shared_lib_ext(), ".dll") == 0) {
+        self->cfish_lib_name = "cfish-0.4";
+    }
+    else {
+        self->cfish_lib_name = "cfish";
+    }
+
+    /* Lucy libraries. */
+    self->shared_lib = chaz_Lib_new("lucy", chaz_Lib_SHARED, lucy_version,
+                                    lucy_major_version);
+    self->static_lib = chaz_Lib_new("lucy", chaz_Lib_STATIC, lucy_version,
+                                    lucy_major_version);
+    self->shared_lib_filename = chaz_Lib_filename(self->shared_lib);
+    self->static_lib_filename = chaz_Lib_filename(self->static_lib);
+
+    return self;
 }
 
 static void
-S_cfh_file_callback(const char *dir, char *file, void *context) {
-    SourceFileContext *sfc = (SourceFileContext*)context;
-    const char *dir_sep = chaz_OS_dir_sep();
-    char *cfh_file;
+lucy_MakeFile_destroy(lucy_MakeFile *self) {
+    chaz_MakeFile_destroy(self->makefile);
 
-    if (!S_ends_with(file, ".cfh")) {
-        chaz_Util_warn("Unexpected Clownfish header filename: %s", file);
-        return;
-    }
+    free(self->core_dir);
+    free(self->autogen_inc_dir);
+    free(self->autogen_src_dir);
+    free(self->lemon_dir);
+    free(self->modules_dir);
+    free(self->snowstem_dir);
+    free(self->snowstem_inc_dir);
+    free(self->snowstop_dir);
+    free(self->ucd_dir);
+    free(self->utf8proc_dir);
 
-    cfh_file = chaz_Util_join(dir_sep, dir, file, NULL);
-    chaz_MakeVar_append(sfc->var, cfh_file);
-    free(cfh_file);
+    free(self->autogen_target);
+    free(self->json_parser);
+
+    free(self->cfish_lib_dir);
+
+    chaz_Lib_destroy(self->shared_lib);
+    chaz_Lib_destroy(self->static_lib);
+    free(self->shared_lib_filename);
+    free(self->static_lib_filename);
+
+    free(self);
 }
 
 static void
-S_write_makefile(chaz_CLI *cli) {
+lucy_MakeFile_write(lucy_MakeFile *self) {
     SourceFileContext sfc;
 
-    const char *base_dir     = "..";
-    const char *dir_sep      = chaz_OS_dir_sep();
-    const char *exe_ext      = chaz_OS_exe_ext();
-    const char *obj_ext      = chaz_CC_obj_ext();
-    const char *math_lib     = chaz_Floats_math_library();
-    const char *cfish_prefix = chaz_CLI_strval(cli, "clownfish-prefix");
+    const char *dir_sep  = chaz_OS_dir_sep();
+    const char *obj_ext  = chaz_CC_obj_ext();
+    const char *math_lib = chaz_Floats_math_library();
 
-    char *core_dir      = chaz_Util_join(dir_sep, base_dir, "core", NULL);
-    char *lemon_dir     = chaz_Util_join(dir_sep, base_dir, "lemon", NULL);
-    char *modules_dir   = chaz_Util_join(dir_sep, base_dir, "modules", NULL);
-    char *snowstem_dir  = chaz_Util_join(dir_sep, modules_dir, "analysis",
-                                         "snowstem", "source", NULL);
-    char *snowstop_dir  = chaz_Util_join(dir_sep, modules_dir, "analysis",
-                                         "snowstop", "source", NULL);
-    char *ucd_dir       = chaz_Util_join(dir_sep, modules_dir, "unicode",
-                                         "ucd", NULL);
-    char *utf8proc_dir  = chaz_Util_join(dir_sep, modules_dir, "unicode",
-                                         "utf8proc", NULL);
-    char *json_parser   = chaz_Util_join(dir_sep, core_dir, "Lucy", "Util",
-                                         "Json", "JsonParser", NULL);
-    char *test_lucy_exe = chaz_Util_join("", "t", dir_sep, "test_lucy",
-                                         exe_ext, NULL);
-
-    char *autogen_inc_dir
-        = chaz_Util_join(dir_sep, "autogen", "include", NULL);
-    char *autogen_target
-        = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL);
-    char *snowstem_inc_dir
-        = chaz_Util_join(dir_sep, snowstem_dir, "include", NULL);
-
-    chaz_MakeFile *makefile;
     chaz_MakeVar  *var;
     chaz_MakeRule *rule;
     chaz_MakeRule *clean_rule;
@@ -7848,29 +8037,19 @@ S_write_makefile(chaz_CLI *cli) {
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
     chaz_CFlags *link_flags;
-    chaz_CFlags *test_cflags;
 
-    chaz_Lib *shared_lib;
-    chaz_Lib *static_lib;
-
-    const char *cfish_lib_name = NULL;
-    char       *cfish_lib_dir  = NULL;
-    char       *test_command   = NULL;
-    char       *scratch        = NULL;
-    char       *shared_lib_filename = NULL;
-    char       *static_lib_filename = NULL;
+    char *scratch;
+    int   i;
 
     printf("Creating Makefile...\n");
 
-    makefile = chaz_MakeFile_new();
-
     /* Directories */
 
-    chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
+    chaz_MakeFile_add_var(self->makefile, "BASE_DIR", self->base_dir);
 
     /* C compiler */
 
-    chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
+    chaz_MakeFile_add_var(self->makefile, "CC", chaz_CC_get_cc());
 
     makefile_cflags = chaz_CC_new_cflags();
 
@@ -7878,18 +8057,18 @@ S_write_makefile(chaz_CLI *cli) {
     chaz_CFlags_enable_debugging(makefile_cflags);
     chaz_CFlags_disable_strict_aliasing(makefile_cflags);
     chaz_CFlags_compile_shared_library(makefile_cflags);
-    if (chaz_CLI_defined(cli, "enable-coverage")) {
+    if (chaz_CLI_defined(self->cli, "enable-coverage")) {
         chaz_CFlags_enable_code_coverage(makefile_cflags);
     }
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
-    chaz_CFlags_add_include_dir(makefile_cflags, core_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, autogen_inc_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, snowstem_inc_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, ucd_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, utf8proc_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, self->core_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, self->autogen_inc_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, self->snowstem_inc_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, self->ucd_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, self->utf8proc_dir);
 
-    var = chaz_MakeFile_add_var(makefile, "CFLAGS", NULL);
+    var = chaz_MakeFile_add_var(self->makefile, "CFLAGS", NULL);
     chaz_MakeVar_append(var, chaz_CFlags_get_string(extra_cflags));
     chaz_MakeVar_append(var, chaz_CFlags_get_string(makefile_cflags));
     chaz_MakeVar_append(var, chaz_CC_get_cflags());
@@ -7898,137 +8077,171 @@ S_write_makefile(chaz_CLI *cli) {
 
     /* Object files */
 
-    var = chaz_MakeFile_add_var(makefile, "LUCY_OBJS", NULL);
+    var = chaz_MakeFile_add_var(self->makefile, "LUCY_OBJS", NULL);
     sfc.var = var;
 
-    chaz_Make_list_files("src",        "c", S_c_file_callback, &sfc);
-    chaz_Make_list_files(core_dir,     "c", S_c_file_callback, &sfc);
-    chaz_Make_list_files(snowstem_dir, "c", S_c_file_callback, &sfc);
-    chaz_Make_list_files(snowstop_dir, "c", S_c_file_callback, &sfc);
-    chaz_Make_list_files(utf8proc_dir, "c", S_c_file_callback, &sfc);
+    chaz_Make_list_files(self->host_src_dir, "c", S_c_file_callback, &sfc);
+    chaz_Make_list_files(self->core_dir,     "c", S_c_file_callback, &sfc);
+    chaz_Make_list_files(self->snowstem_dir, "c", S_c_file_callback, &sfc);
+    chaz_Make_list_files(self->snowstop_dir, "c", S_c_file_callback, &sfc);
+    chaz_Make_list_files(self->utf8proc_dir, "c", S_c_file_callback, &sfc);
 
-    scratch = chaz_Util_join("", json_parser, obj_ext, NULL);
+    scratch = chaz_Util_join("", self->json_parser, obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
 
-    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
-                             "lucy_parcel", obj_ext, NULL);
-    chaz_MakeVar_append(var, scratch);
-    free(scratch);
-    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
-                             "testlucy_parcel", obj_ext, NULL);
-    chaz_MakeVar_append(var, scratch);
-    free(scratch);
-
-    /* Clownfish header files */
-
-    var = chaz_MakeFile_add_var(makefile, "CLOWNFISH_HEADERS", NULL);
-    sfc.var = var;
-
-    chaz_Make_list_files(core_dir, "cfh", S_cfh_file_callback, &sfc);
+    for (i = 0; self->autogen_src_files[i] != NULL; ++i) {
+        char *path = chaz_Util_join("", self->autogen_src_dir, dir_sep,
+                                    self->autogen_src_files[i], obj_ext, NULL);
+        chaz_MakeVar_append(var, path);
+        free(path);
+    }
 
     /* Rules */
 
-    shared_lib = chaz_Lib_new("lucy", chaz_Lib_SHARED, lucy_version,
-                              lucy_major_version);
-    shared_lib_filename = chaz_Lib_filename(shared_lib);
-    static_lib = chaz_Lib_new("lucy", chaz_Lib_STATIC, lucy_version,
-                              lucy_major_version);
-    static_lib_filename = chaz_Lib_filename(static_lib);
-    scratch = chaz_Util_join(" ", shared_lib_filename, static_lib_filename,
-                             NULL);
-    chaz_MakeFile_add_rule(makefile, "all", scratch);
+    scratch = chaz_Util_join(" ", self->shared_lib_filename,
+                             self->static_lib_filename, NULL);
+    chaz_MakeFile_add_rule(self->makefile, "all", scratch);
     free(scratch);
 
-    chaz_MakeFile_add_lemon_exe(makefile, lemon_dir);
-    chaz_MakeFile_add_lemon_grammar(makefile, json_parser);
+    chaz_MakeFile_add_lemon_exe(self->makefile, self->lemon_dir);
+    chaz_MakeFile_add_lemon_grammar(self->makefile, self->json_parser);
 
-    rule = chaz_MakeFile_add_rule(makefile, autogen_target, NULL);
-    chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
-    if (cfish_prefix == NULL) {
-        scratch = chaz_Util_join("", "cfc --source=", core_dir,
-                                 " --dest=autogen --header=cfc_header", NULL);
-    }
-    else {
-        scratch = chaz_Util_join("", cfish_prefix, dir_sep, "bin", dir_sep,
-                                 "cfc --source=", core_dir, " --include=",
-                                 cfish_prefix, dir_sep, "share", dir_sep,
-                                 "clownfish", dir_sep, "include",
-                                 " --dest=autogen --header=cfc_header", NULL);
+    if (!chaz_CLI_defined(self->cli, "enable-perl")) {
+        lucy_MakeFile_write_c_cfc_rules(self);
     }
-    chaz_MakeRule_add_command(rule, scratch);
-    free(scratch);
 
     /* Needed for parallel builds. */
-    scratch = chaz_Util_join(dir_sep, "autogen", "source", "lucy_parcel.c",
-                             NULL);
-    rule = chaz_MakeFile_add_rule(makefile, scratch, autogen_target);
-    free(scratch);
-    scratch = chaz_Util_join(dir_sep, "autogen", "source", "testlucy_parcel.c",
-                             NULL);
-    rule = chaz_MakeFile_add_rule(makefile, scratch, autogen_target);
-    free(scratch);
+    for (i = 0; self->autogen_src_files[i] != NULL; ++i) {
+        char *path = chaz_Util_join("", self->autogen_src_dir, dir_sep,
+                                    self->autogen_src_files[i], ".c", NULL);
+        rule = chaz_MakeFile_add_rule(self->makefile, path,
+                                      self->autogen_target);
+        free(path);
+    }
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", autogen_target);
+    rule = chaz_MakeFile_add_rule(self->makefile, "$(LUCY_OBJS)",
+                                  self->autogen_target);
     /*
      * The dependency is actually on JsonParser.h, but make doesn't cope
      * well with multiple output files.
      */
-    scratch = chaz_Util_join(".", json_parser, "c", NULL);
+    scratch = chaz_Util_join(".", self->json_parser, "c", NULL);
     chaz_MakeRule_add_prereq(rule, scratch);
     free(scratch);
 
-    if (cfish_prefix) {
-        cfish_lib_dir = chaz_Util_join(dir_sep, cfish_prefix, "lib", NULL);
-    }
-
-    if (strcmp(chaz_OS_shared_lib_ext(), ".dll") == 0) {
-        cfish_lib_name = "cfish-0.4";
-    }
-    else {
-        cfish_lib_name = "cfish";
-    }
-
     link_flags = chaz_CC_new_cflags();
     chaz_CFlags_enable_debugging(link_flags);
-    if (cfish_lib_dir) {
-        chaz_CFlags_add_library_path(link_flags, cfish_lib_dir);
+    if (self->cfish_lib_dir) {
+        chaz_CFlags_add_library_path(link_flags, self->cfish_lib_dir);
     }
     if (math_lib) {
         chaz_CFlags_add_external_library(link_flags, math_lib);
     }
-    chaz_CFlags_add_external_library(link_flags, cfish_lib_name);
+    chaz_CFlags_add_external_library(link_flags, self->cfish_lib_name);
     if (chaz_HeadCheck_check_header("pcre.h")) {
         chaz_CFlags_add_external_library(link_flags, "pcre");
     }
-    if (chaz_CLI_defined(cli, "enable-coverage")) {
+    if (chaz_CLI_defined(self->cli, "enable-coverage")) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
-    rule = chaz_MakeFile_add_shared_lib(makefile, shared_lib, "$(LUCY_OBJS)",
-                                        link_flags);
+    rule = chaz_MakeFile_add_shared_lib(self->makefile, self->shared_lib,
+                                        "$(LUCY_OBJS)", link_flags);
     chaz_CFlags_destroy(link_flags);
-    chaz_MakeFile_add_static_lib(makefile, static_lib, "$(LUCY_OBJS)");
+    chaz_MakeFile_add_static_lib(self->makefile, self->static_lib, 
"$(LUCY_OBJS)");
+
+    if (!chaz_CLI_defined(self->cli, "enable-perl")) {
+        lucy_MakeFile_write_c_test_rules(self);
+    }
+
+    clean_rule = chaz_MakeFile_clean_rule(self->makefile);
+
+    if (chaz_Make_shell_type() == CHAZ_OS_CMD_EXE) {
+        /*
+         * The length of the command would exceed the limit of 8191
+         * characters. As a work-around, delete all .obj files in BASE_DIR
+         * using 'del /s /q'.
+         */
+        scratch = chaz_Util_join("", "del /s /q ", self->base_dir, "\\*",
+                                 obj_ext, NULL);
+        chaz_MakeRule_add_command(clean_rule, scratch);
+        free(scratch);
+    }
+    else {
+        chaz_MakeRule_add_rm_command(clean_rule, "$(LUCY_OBJS)");
+    }
+
+    chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen");
+
+    chaz_MakeFile_write(self->makefile);
+}
+
+static void
+lucy_MakeFile_write_c_cfc_rules(lucy_MakeFile *self) {
+    SourceFileContext sfc;
+    chaz_MakeRule *rule;
+
+    const char *dir_sep      = chaz_OS_dir_sep();
+    const char *cfish_prefix = chaz_CLI_strval(self->cli, "clownfish-prefix");
+
+    char *cfc_command;
 
+    sfc.var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS", NULL);
+    chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, &sfc);
+
+    rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, NULL);
+    chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
+    if (cfish_prefix == NULL) {
+        cfc_command
+            = chaz_Util_join("", "cfc --source=", self->core_dir,
+                             " --dest=autogen --header=cfc_header", NULL);
+    }
+    else {
+        cfc_command
+            = chaz_Util_join("", cfish_prefix, dir_sep, "bin", dir_sep,
+                             "cfc --source=", self->core_dir, " --include=",
+                             cfish_prefix, dir_sep, "share", dir_sep,
+                             "clownfish", dir_sep, "include",
+                             " --dest=autogen --header=cfc_header", NULL);
+    }
+    chaz_MakeRule_add_command(rule, cfc_command);
+
+    free(cfc_command);
+}
+
+static void
+lucy_MakeFile_write_c_test_rules(lucy_MakeFile *self) {
+    const char *dir_sep  = chaz_OS_dir_sep();
+    const char *exe_ext  = chaz_OS_exe_ext();
+
+    chaz_CFlags   *test_cflags;
+    chaz_MakeRule *rule;
+
+    char *test_lucy_exe;
+    char *test_lucy_c;
+    char *test_command;
+
+    test_lucy_exe = chaz_Util_join("", "t", dir_sep, "test_lucy", exe_ext,
+                                   NULL);
+    test_lucy_c = chaz_Util_join(dir_sep, "t", "test_lucy.c", NULL);
     test_cflags = chaz_CC_new_cflags();
     chaz_CFlags_enable_optimization(test_cflags);
-    chaz_CFlags_add_include_dir(test_cflags, autogen_inc_dir);
-    chaz_CFlags_add_library(test_cflags, shared_lib);
-    if (cfish_lib_dir) {
-        chaz_CFlags_add_library_path(link_flags, cfish_lib_dir);
-    }
-    chaz_CFlags_add_external_library(test_cflags, cfish_lib_name);
-    scratch = chaz_Util_join(dir_sep, "t", "test_lucy.c", NULL);
-    rule = chaz_MakeFile_add_compiled_exe(makefile, test_lucy_exe, scratch,
-                                          test_cflags);
-    free(scratch);
-    chaz_MakeRule_add_prereq(rule, shared_lib_filename);
+    chaz_CFlags_add_include_dir(test_cflags, self->autogen_inc_dir);
+    chaz_CFlags_add_library(test_cflags, self->shared_lib);
+    if (self->cfish_lib_dir) {
+        chaz_CFlags_add_library_path(test_cflags, self->cfish_lib_dir);
+    }
+    chaz_CFlags_add_external_library(test_cflags, self->cfish_lib_name);
+    rule = chaz_MakeFile_add_compiled_exe(self->makefile, test_lucy_exe,
+                                          test_lucy_c, test_cflags);
+    chaz_MakeRule_add_prereq(rule, self->shared_lib_filename);
     chaz_CFlags_destroy(test_cflags);
 
-    rule = chaz_MakeFile_add_rule(makefile, "test", test_lucy_exe);
+    rule = chaz_MakeFile_add_rule(self->makefile, "test", test_lucy_exe);
     if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
-        if (cfish_lib_dir) {
+        if (self->cfish_lib_dir) {
             test_command
-                = chaz_Util_join("", "LD_LIBRARY_PATH=.:", cfish_lib_dir,
+                = chaz_Util_join("", "LD_LIBRARY_PATH=.:", self->cfish_lib_dir,
                                  ":$$LD_LIBRARY_PATH ", test_lucy_exe, NULL);
         }
         else {
@@ -8042,8 +8255,8 @@ S_write_makefile(chaz_CLI *cli) {
     }
     chaz_MakeRule_add_command(rule, test_command);
 
-    if (chaz_CLI_defined(cli, "enable-coverage")) {
-        rule = chaz_MakeFile_add_rule(makefile, "coverage", test_lucy_exe);
+    if (chaz_CLI_defined(self->cli, "enable-coverage")) {
+        rule = chaz_MakeFile_add_rule(self->makefile, "coverage", 
test_lucy_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --zerocounters"
@@ -8061,126 +8274,61 @@ S_write_makefile(chaz_CLI *cli) {
                                   " --branch-coverage"
                                   " --output-directory coverage"
                                   " lucy.info");
-    }
-
-    clean_rule = chaz_MakeFile_clean_rule(makefile);
-
-    if (chaz_Make_shell_type() == CHAZ_OS_CMD_EXE) {
-        /*
-         * The length of the command would exceed the limit of 8191
-         * characters. As a work-around, delete all .obj files in BASE_DIR
-         * using 'del /s /q'.
-         */
-        scratch = chaz_Util_join("", "del /s /q ", base_dir, "\\*", obj_ext,
-                                 NULL);
-        chaz_MakeRule_add_command(clean_rule, scratch);
-        free(scratch);
-    }
-    else {
-        chaz_MakeRule_add_rm_command(clean_rule, "$(LUCY_OBJS)");
-    }
 
-    chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen");
-
-    if (chaz_CLI_defined(cli, "enable-coverage")) {
-        chaz_MakeRule_add_rm_command(clean_rule, "lucy.info");
-        chaz_MakeRule_add_recursive_rm_command(clean_rule, "coverage");
+        rule = chaz_MakeFile_clean_rule(self->makefile);
+        chaz_MakeRule_add_rm_command(rule, "lucy.info");
+        chaz_MakeRule_add_recursive_rm_command(rule, "coverage");
     }
 
-    chaz_MakeFile_distclean_rule(makefile);
-
-    chaz_MakeFile_write(makefile);
-
-    chaz_MakeFile_destroy(makefile);
-    chaz_Lib_destroy(shared_lib);
-    chaz_Lib_destroy(static_lib);
-    free(core_dir);
-    free(lemon_dir);
-    free(modules_dir);
-    free(snowstem_dir);
-    free(snowstop_dir);
-    free(ucd_dir);
-    free(utf8proc_dir);
-    free(json_parser);
     free(test_lucy_exe);
-    free(autogen_inc_dir);
-    free(autogen_target);
-    free(snowstem_inc_dir);
-    free(cfish_lib_dir);
-    free(shared_lib_filename);
-    free(static_lib_filename);
+    free(test_lucy_c);
     free(test_command);
 }
 
-int main(int argc, const char **argv) {
-    /* Initialize. */
-    chaz_CLI *cli
-        = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment");
-    chaz_CLI_register(cli, "clownfish-prefix",
-                      "prefix of Clownfish installation",
-                      CHAZ_CLI_ARG_OPTIONAL);
-    chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]");
-    if (!chaz_Probe_parse_cli_args(argc, argv, cli)) {
-        chaz_Probe_die_usage();
-    }
-    chaz_Probe_init(cli);
-    S_add_compiler_flags(cli);
+static void
+S_c_file_callback(const char *dir, char *file, void *context) {
+    SourceFileContext *sfc = (SourceFileContext*)context;
+    const char *dir_sep = chaz_OS_dir_sep();
+    const char *obj_ext = chaz_CC_obj_ext();
+    size_t file_len = strlen(file);
+    char *obj_file;
 
-    /* Employ integer features but don't define stdint types in charmony.h. */
-    chaz_ConfWriter_append_conf(
-        "#define CHY_EMPLOY_INTEGERLIMITS\n"
-        "#define CHY_EMPLOY_INTEGERLITERALS\n"
-        "#define CHY_EMPLOY_INTEGERFORMATSTRINGS\n\n"
-    );
+    /* Strip extension */
+    if (!S_ends_with(file, ".c")) {
+        chaz_Util_warn("Unexpected C filename: %s", file);
+        return;
+    }
+    file[file_len-2] = '\0';
 
-    /* Run probe modules. Booleans is only needed for the Charmonizer tests. */
-    chaz_BuildEnv_run();
-    chaz_DirManip_run();
-    chaz_Headers_run();
-    chaz_Booleans_run();
-    chaz_Integers_run();
-    chaz_Floats_run();
-    chaz_LargeFiles_run();
-    chaz_Memory_run();
-    chaz_RegularExpressions_run();
-    chaz_VariadicMacros_run();
+    if (!S_ends_with(file, "JsonParser")) {
+        obj_file = chaz_Util_join("", dir, dir_sep, file, obj_ext, NULL);
+        chaz_MakeVar_append(sfc->var, obj_file);
+        free(obj_file);
+    }
+}
 
-    /* Write custom postamble. */
-    chaz_ConfWriter_append_conf(
-        "#ifdef CHY_HAS_SYS_TYPES_H\n"
-        "  #include <sys/types.h>\n"
-        "#endif\n\n"
-    );
-    chaz_ConfWriter_append_conf(
-        "#ifdef CHY_HAS_ALLOCA_H\n"
-        "  #include <alloca.h>\n"
-        "#elif defined(CHY_HAS_MALLOC_H)\n"
-        "  #include <malloc.h>\n"
-        "#elif defined(CHY_ALLOCA_IN_STDLIB_H)\n"
-        "  #include <stdlib.h>\n"
-        "#endif\n\n"
-    );
-    chaz_ConfWriter_append_conf(
-        "#ifdef CHY_HAS_WINDOWS_H\n"
-        "  /* Target Windows XP. */\n"
-        "  #ifndef WINVER\n"
-        "    #define WINVER 0x0500\n"
-        "  #endif\n"
-        "  #ifndef _WIN32_WINNT\n"
-        "    #define _WIN32_WINNT 0x0500\n"
-        "  #endif\n"
-        "#endif\n\n"
-    );
+static void
+S_cfh_file_callback(const char *dir, char *file, void *context) {
+    SourceFileContext *sfc = (SourceFileContext*)context;
+    const char *dir_sep = chaz_OS_dir_sep();
+    char *cfh_file;
 
-    if (chaz_CLI_defined(cli, "enable-makefile")) {
-        S_write_makefile(cli);
+    if (!S_ends_with(file, ".cfh")) {
+        chaz_Util_warn("Unexpected Clownfish header filename: %s", file);
+        return;
     }
 
-    /* Clean up. */
-    chaz_CLI_destroy(cli);
-    chaz_Probe_clean_up();
+    cfh_file = chaz_Util_join(dir_sep, dir, file, NULL);
+    chaz_MakeVar_append(sfc->var, cfh_file);
+    free(cfh_file);
+}
 
-    return 0;
+static int
+S_ends_with(const char *string, const char *postfix) {
+    size_t len         = strlen(string);
+    size_t postfix_len = strlen(postfix);
+    return len >= postfix_len
+           && memcmp(string + len - postfix_len, postfix, postfix_len) == 0;
 }
 
 

Reply via email to