You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2013/05/15 19:24:25 UTC

[lucy-commits] [01/13] git commit: refs/heads/makefile-rework - Add MSVC /nologo automatically

Updated Branches:
  refs/heads/makefile-rework [created] 07c277014


Add MSVC /nologo automatically


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

Branch: refs/heads/makefile-rework
Commit: ff53edf2683a559372055e4ed9d99c7eb082121d
Parents: 175f115
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 14 21:46:48 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:53 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/Make.c    |   11 ++++++++++-
 clownfish/compiler/common/charmonizer.main |   12 ++----------
 common/charmonizer.main                    |   14 +++-----------
 3 files changed, 15 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/ff53edf2/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index d57034e..22d4764 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -276,6 +276,9 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_link_output(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
@@ -304,6 +307,9 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
     if (cflags) {
         cflags_string = chaz_CFlags_get_string(cflags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_output_exe(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", cc, sources, cflags_string,
@@ -335,6 +341,9 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_link_shared_library(local_flags);
     chaz_CFlags_set_shared_library_version(local_flags, lib);
     chaz_CFlags_set_link_output(local_flags, filename);
@@ -388,7 +397,7 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
         /* Inference rule for .c files. */
         fprintf(out, ".c.obj :\n");
         if (chaz_CC_msvc_version_num()) {
-            fprintf(out, "\t$(CC) $(CFLAGS) /c $< /Fo$@\n\n");
+            fprintf(out, "\t$(CC) /nologo $(CFLAGS) /c $< /Fo$@\n\n");
         }
         else {
             fprintf(out, "\t$(CC) $(CFLAGS) -c $< -o $@\n\n");

http://git-wip-us.apache.org/repos/asf/lucy/blob/ff53edf2/clownfish/compiler/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.main b/clownfish/compiler/common/charmonizer.main
index df03a70..fd713f3 100644
--- a/clownfish/compiler/common/charmonizer.main
+++ b/clownfish/compiler/common/charmonizer.main
@@ -70,14 +70,6 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 }
 
 static void
-S_add_common_cflags(chaz_CFlags *cflags) {
-    if (chaz_CC_msvc_version_num()) {
-        chaz_CFlags_append(cflags, "/nologo");
-    }
-    chaz_CFlags_enable_optimization(cflags);
-}
-
-static void
 S_source_file_callback(char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
     size_t file_len = strlen(file);
@@ -161,8 +153,8 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
 
     makefile_cflags = chaz_CC_new_cflags();
-    S_add_common_cflags(makefile_cflags);
 
+    chaz_CFlags_enable_optimization(makefile_cflags);
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
     chaz_CFlags_add_include_dir(makefile_cflags, "$(INCLUDE_DIR)");
     chaz_CFlags_add_include_dir(makefile_cflags, "$(SRC_DIR)");
@@ -203,7 +195,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)");
 
     lemon_cflags = chaz_CC_new_cflags();
-    S_add_common_cflags(lemon_cflags);
+    chaz_CFlags_enable_optimization(lemon_cflags);
     chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
                                    "$(LEMON_DIR)" DIR_SEP "lemon.c",
                                    lemon_cflags);

http://git-wip-us.apache.org/repos/asf/lucy/blob/ff53edf2/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index e8fc434..e595057 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -101,14 +101,6 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 }
 
 static void
-S_add_common_cflags(chaz_CFlags *cflags) {
-    if (chaz_CC_msvc_version_num()) {
-        chaz_CFlags_append(cflags, "/nologo");
-    }
-    chaz_CFlags_enable_optimization(cflags);
-}
-
-static void
 S_source_file_callback(char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
     const char *json_parser_c = "Lucy" DIR_SEP "Util" DIR_SEP "Json" DIR_SEP
@@ -206,8 +198,8 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
 
     makefile_cflags = chaz_CC_new_cflags();
-    S_add_common_cflags(makefile_cflags);
 
+    chaz_CFlags_enable_optimization(makefile_cflags);
     chaz_CFlags_disable_strict_aliasing(makefile_cflags);
     chaz_CFlags_compile_shared_library(makefile_cflags);
     chaz_CFlags_hide_symbols(makefile_cflags);
@@ -290,7 +282,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_add_rule(makefile, "all", lib_filename);
 
     lemon_cflags = chaz_CC_new_cflags();
-    S_add_common_cflags(lemon_cflags);
+    chaz_CFlags_enable_optimization(lemon_cflags);
     chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
                                    "$(LEMON_DIR)" DIR_SEP "lemon.c",
                                    lemon_cflags);
@@ -341,7 +333,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_CFlags_destroy(link_flags);
 
     test_cflags = chaz_CC_new_cflags();
-    S_add_common_cflags(test_cflags);
+    chaz_CFlags_enable_optimization(test_cflags);
     chaz_CFlags_add_include_dir(test_cflags, ".");
     chaz_CFlags_add_include_dir(test_cflags,
                                 "$(AUTOGEN_DIR)" DIR_SEP "include");


[lucy-commits] [10/13] git commit: refs/heads/makefile-rework - Add dependency on .cfh files in Makefile

Posted by nw...@apache.org.
Add dependency on .cfh files in Makefile


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

Branch: refs/heads/makefile-rework
Commit: 3b36502434c43a08d60c5fa20cac7e767ce1f15d
Parents: e472376
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed May 15 02:50:48 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:19:52 2013 +0200

----------------------------------------------------------------------
 common/charmonizer.main |   42 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 35 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/3b365024/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 88219d6..5b8519c 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -102,7 +102,7 @@ S_ends_with(const char *string, const char *postfix) {
 }
 
 static void
-S_source_file_callback(const char *dir, char *file, void *context) {
+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();
@@ -111,7 +111,7 @@ S_source_file_callback(const char *dir, char *file, void *context) {
 
     /* Strip extension */
     if (!S_ends_with(file, ".c")) {
-        chaz_Util_warn("Unexpected source file name: %s", file);
+        chaz_Util_warn("Unexpected C filename: %s", file);
         return;
     }
     file[file_len-2] = '\0';
@@ -124,6 +124,22 @@ S_source_file_callback(const char *dir, char *file, void *context) {
 }
 
 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 (!S_ends_with(file, ".cfh")) {
+        chaz_Util_warn("Unexpected Clownfish header filename: %s", file);
+        return;
+    }
+
+    cfh_file = chaz_Util_join(dir_sep, dir, file, NULL);
+    chaz_MakeVar_append(sfc->var, cfh_file);
+    free(cfh_file);
+}
+
+static void
 S_write_makefile(struct chaz_CLIArgs *args) {
     SourceFileContext sfc;
 
@@ -215,11 +231,11 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     var = chaz_MakeFile_add_var(makefile, "LUCY_OBJS", NULL);
     sfc.var = var;
 
-    chaz_Make_list_files("src",        "c", S_source_file_callback, &sfc);
-    chaz_Make_list_files(core_dir,     "c", S_source_file_callback, &sfc);
-    chaz_Make_list_files(snowstem_dir, "c", S_source_file_callback, &sfc);
-    chaz_Make_list_files(snowstop_dir, "c", S_source_file_callback, &sfc);
-    chaz_Make_list_files(utf8proc_dir, "c", S_source_file_callback, &sfc);
+    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);
 
     scratch = chaz_Util_join("", json_parser, obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
@@ -230,6 +246,13 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     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);
+
     /* Rules */
 
     lib = chaz_SharedLib_new("lucy", lucy_version, lucy_major_version);
@@ -247,9 +270,14 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule_add_make_command(rule, cfc_dir, NULL);
 
     rule = chaz_MakeFile_add_rule(makefile, "autogen", cfc_exe);
+    chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
     scratch = chaz_Util_join("", cfc_exe, " --source=", core_dir,
                              " --dest=autogen --header=cfc_header", NULL);
     chaz_MakeRule_add_command(rule, scratch);
+    /* TODO: Find a way to touch the autogen directory on Windows. */
+    if (chaz_Make_shell_type() == CHAZ_OS_POSIX) {
+        chaz_MakeRule_add_command(rule, "touch autogen");
+    }
     free(scratch);
 
     /* Needed for parallel builds. */


[lucy-commits] [13/13] git commit: refs/heads/makefile-rework - Regenerate charmonizer.c

Posted by nw...@apache.org.
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/07c27701
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/07c27701
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/07c27701

Branch: refs/heads/makefile-rework
Commit: 07c277014e4eb08fdc6d798cfa56450324f4ad05
Parents: 86e34de
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 13 22:31:25 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:23:22 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/common/charmonizer.c |  574 ++++++++++++++------
 clownfish/runtime/common/charmonizer.c  |  448 ++++++++++++----
 common/charmonizer.c                    |  762 +++++++++++++++++---------
 3 files changed, 1256 insertions(+), 528 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/07c27701/clownfish/compiler/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.c b/clownfish/compiler/common/charmonizer.c
index 5c74620..6119e88 100644
--- a/clownfish/compiler/common/charmonizer.c
+++ b/clownfish/compiler/common/charmonizer.c
@@ -36,12 +36,58 @@
 
 /***************************************************************************/
 
+#line 21 "src/Charmonizer/Core/SharedLibrary.h"
+/* Charmonizer/Core/SharedLibrary.h
+ */
+
+#ifndef H_CHAZ_SHARED_LIB
+#define H_CHAZ_SHARED_LIB
+
+typedef struct chaz_SharedLib chaz_SharedLib;
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version);
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *flags);
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib);
+
+#endif /* H_CHAZ_SHARED_LIB */
+
+
+
+/***************************************************************************/
+
 #line 21 "src/Charmonizer/Core/CFlags.h"
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/CFlags.h
  */
 
-#ifndef H_CHAZ_FLAGS
-#define H_CHAZ_FLAGS
+#ifndef H_CHAZ_CFLAGS
+#define H_CHAZ_CFLAGS
 
 #define CHAZ_CFLAGS_STYLE_POSIX  1
 #define CHAZ_CFLAGS_STYLE_GNU    2
@@ -96,18 +142,25 @@ void
 chaz_CFlags_link_shared_library(chaz_CFlags *flags);
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib);
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename);
 
 void
 chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory);
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library);
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib);
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library);
 
 void
 chaz_CFlags_enable_code_coverage(chaz_CFlags *flags);
 
-#endif /* H_CHAZ_FLAGS */
+#endif /* H_CHAZ_CFLAGS */
 
 
 
@@ -172,11 +225,6 @@ chaz_CC_get_cc(void);
 const char*
 chaz_CC_get_cflags(void);
 
-/* Accessor for `cflags_style`.
- */
-int
-chaz_CC_get_cflags_style(void);
-
 /* Accessor for `extra_cflags`.
  */
 chaz_CFlags*
@@ -187,6 +235,11 @@ chaz_CC_get_extra_cflags(void);
 chaz_CFlags*
 chaz_CC_get_temp_cflags(void);
 
+/* Return a new CFlags object.
+ */
+chaz_CFlags*
+chaz_CC_new_cflags(void);
+
 /* Return the extension for a compiled object.
  */
 const char*
@@ -204,9 +257,6 @@ chaz_CC_msvc_version_num(void);
 const char*
 chaz_CC_link_command(void);
 
-char*
-chaz_CC_shared_lib_file(const char *name);
-
 #endif /* H_CHAZ_COMPILER */
 
 
@@ -416,19 +466,21 @@ chaz_HeadCheck_contains_member(const char *struct_name, const char *member,
 /***************************************************************************/
 
 #line 21 "src/Charmonizer/Core/Make.h"
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/Make.h
  */
 
 #ifndef H_CHAZ_MAKE
 #define H_CHAZ_MAKE
 
 /* #include "Charmonizer/Core/CFlags.h" */
+/* #include "Charmonizer/Core/SharedLib.h" */
 
 typedef struct chaz_MakeFile chaz_MakeFile;
 typedef struct chaz_MakeVar chaz_MakeVar;
 typedef struct chaz_MakeRule chaz_MakeRule;
 
-typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
+typedef void (*chaz_Make_list_files_callback_t)(const char *dir, char *file,
+                                                void *context);
 
 /** Initialize the environment.
  */
@@ -539,14 +591,31 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
  * to the list of files to clean.
  *
  * @param makefile The makefile.
- * @param name The name of the shared library without prefix or extension.
+ * @param lib The shared library.
  * @param sources The list of source files.
  * @param link_flags Additional link flags.
  */
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags);
 
+/** Add a rule to build the lemon parser generator.
+ *
+ * @param makefile The makefile.
+ * @param dir The lemon directory.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir);
+
+/** Add a rule for a lemon grammar.
+ *
+ * @param makefile The makefile.
+ * @param base_name The filename of the grammar without extension.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name);
+
 /** Write the makefile to a file named 'Makefile' in the current directory.
  *
  * @param makefile The makefile.
@@ -696,6 +765,11 @@ chaz_OS_shared_lib_ext(void);
 const char*
 chaz_OS_dev_null(void);
 
+/* Return the directory separator on this system.
+ */
+const char*
+chaz_OS_dir_sep(void);
+
 /* Return the shell type of this system.
  */
 int
@@ -1162,12 +1236,136 @@ void chaz_UnusedVars_run(void);
 
 /***************************************************************************/
 
+#line 17 "src/Charmonizer/Core/SharedLibrary.c"
+#include <string.h>
+#include <stdlib.h>
+/* #include "Charmonizer/Core/SharedLib.h" */
+/* #include "Charmonizer/Core/Compiler.h" */
+/* #include "Charmonizer/Core/Util.h" */
+/* #include "Charmonizer/Core/OperatingSystem.h" */
+
+struct chaz_SharedLib {
+    char *name;
+    char *version;
+    char *major_version;
+};
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext);
+
+static const char*
+S_get_prefix(void);
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version) {
+    chaz_SharedLib *lib = (chaz_SharedLib*)malloc(sizeof(chaz_SharedLib));
+    lib->name          = chaz_Util_strdup(name);
+    lib->version       = chaz_Util_strdup(version);
+    lib->major_version = chaz_Util_strdup(major_version);
+    return lib;
+}
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *lib) {
+    free(lib->name);
+    free(lib->version);
+    free(lib->major_version);
+    free(lib);
+}
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib) {
+    return lib->name;
+}
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib) {
+    return lib->version;
+}
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib) {
+    return lib->major_version;
+}
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return S_build_filename(lib, lib->major_version, shlib_ext);
+    }
+    else {
+        return S_build_filename(lib, lib->version, shlib_ext);
+    }
+}
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return S_build_filename(lib, lib->major_version, shlib_ext);
+}
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return chaz_Util_join("", prefix, lib->name, shlib_ext, NULL);
+}
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".lib");
+}
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".exp");
+}
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL);
+    }
+    else if (strcmp(shlib_ext, ".dylib") == 0) {
+        return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL);
+    }
+    else {
+        return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL);
+    }
+}
+
+static const char*
+S_get_prefix() {
+    if (chaz_CC_msvc_version_num()) {
+        return "";
+    }
+    else if (chaz_OS_is_cygwin()) {
+        return "cyg";
+    }
+    else {
+        return "lib";
+    }
+}
+
+
+
+/***************************************************************************/
+
 #line 17 "src/Charmonizer/Core/CFlags.c"
 #include <string.h>
 #include <stdlib.h>
-/* #include "Charmonizer/Core/Flags.h" */
+/* #include "Charmonizer/Core/CFlags.h" */
 /* #include "Charmonizer/Core/Util.h" */
 /* #include "Charmonizer/Core/OperatingSystem.h" */
+/* #include "Charmonizer/Core/SharedLibrary.h" */
 
 struct chaz_CFlags {
     int   style;
@@ -1362,7 +1560,7 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
         string = "/DLL";
     }
     else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        if (chaz_OS_is_darwin()) {
+        if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
             string = "-dynamiclib";
         }
         else {
@@ -1377,6 +1575,30 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
 }
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+    char       *string;
+
+    if (flags->style != CHAZ_CFLAGS_STYLE_GNU
+        || strcmp(shlib_ext, ".dll") == 0) {
+        return;
+    }
+
+    if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
+        const char *version = chaz_SharedLib_get_version(lib);
+        string = chaz_Util_join(" ", "-current_version", version, NULL);
+    }
+    else {
+        char *soname = chaz_SharedLib_major_version_filename(lib);
+        string = chaz_Util_join("", "-Wl,-soname,", soname, NULL);
+        free(soname);
+    }
+    chaz_CFlags_append(flags, string);
+    free(string);
+}
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename) {
     const char *output;
     char *string;
@@ -1413,13 +1635,26 @@ chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory) {
 }
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library) {
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib) {
+    char *filename;
+    if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
+        filename = chaz_SharedLib_implib_filename(lib);
+    }
+    else {
+        filename = chaz_SharedLib_filename(lib);
+    }
+    chaz_CFlags_append(flags, filename);
+    free(filename);
+}
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library) {
     char *string;
     if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
         string = chaz_Util_join("", library, ".lib", NULL);
     }
     else {
-        string = chaz_Util_join("", "-l ", library, NULL);
+        string = chaz_Util_join(" ", "-l", library, NULL);
     }
     chaz_CFlags_append(flags, string);
     free(string);
@@ -1746,11 +1981,6 @@ chaz_CC_get_cflags(void) {
     return chaz_CC.cflags;
 }
 
-int
-chaz_CC_get_cflags_style(void) {
-    return chaz_CC.cflags_style;
-}
-
 chaz_CFlags*
 chaz_CC_get_extra_cflags(void) {
     return chaz_CC.extra_cflags;
@@ -1761,6 +1991,11 @@ chaz_CC_get_temp_cflags(void) {
     return chaz_CC.temp_cflags;
 }
 
+chaz_CFlags*
+chaz_CC_new_cflags(void) {
+    return chaz_CFlags_new(chaz_CC.cflags_style);
+}
+
 const char*
 chaz_CC_obj_ext(void) {
     return chaz_CC.obj_ext;
@@ -1793,21 +2028,6 @@ chaz_CC_link_command() {
     }
 }
 
-char*
-chaz_CC_shared_lib_file(const char *name) {
-    const char *prefix = "";
-    const char *shlib_ext = chaz_OS_shared_lib_ext();
-    if (!chaz_CC.intval__MSC_VER) {
-        if (chaz_OS_is_cygwin()) {
-            prefix = "cyg";
-        }
-        else {
-            prefix = "lib";
-        }
-    }
-    return chaz_Util_join("", prefix, name, shlib_ext, NULL);
-}
-
 
 
 /***************************************************************************/
@@ -3070,6 +3290,9 @@ chaz_Make_audition(const char *make) {
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
+    const char    *exe_ext  = chaz_OS_exe_ext();
+    const char    *obj_ext  = chaz_CC_obj_ext();
+    char *generated;
 
     makefile->vars = (chaz_MakeVar**)malloc(sizeof(chaz_MakeVar*));
     makefile->vars[0] = NULL;
@@ -3082,10 +3305,11 @@ chaz_MakeFile_new() {
     makefile->clean     = S_new_rule("clean", NULL);
     makefile->distclean = S_new_rule("distclean", "clean");
 
-    chaz_MakeRule_add_rm_command(makefile->distclean,
-                                 "charmonizer$(EXE_EXT) charmonizer$(OBJ_EXT)"
-                                 " charmony.h Makefile");
+    generated = chaz_Util_join("", "charmonizer", exe_ext, " charmonizer",
+                               obj_ext, " charmony.h Makefile", NULL);
+    chaz_MakeRule_add_rm_command(makefile->distclean, generated);
 
+    free(generated);
     return makefile;
 }
 
@@ -3165,8 +3389,7 @@ chaz_MakeFile_distclean_rule(chaz_MakeFile *makefile) {
 chaz_MakeRule*
 chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
                       const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
@@ -3178,6 +3401,9 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_link_output(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
@@ -3194,8 +3420,7 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
 chaz_MakeRule*
 chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
                                const char *sources, chaz_CFlags *cflags) {
-    int            cflags_style  = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags   = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags   = chaz_CC_new_cflags();
     const char    *cc            = chaz_CC_get_cc();
     const char    *cflags_string = "";
     const char    *local_flags_string;
@@ -3207,6 +3432,9 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
     if (cflags) {
         cflags_string = chaz_CFlags_get_string(cflags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_output_exe(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", cc, sources, cflags_string,
@@ -3222,45 +3450,91 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
 }
 
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
     chaz_MakeRule *rule;
-    char          *shared_lib;
+    char          *filename;
     char          *command;
 
-    shared_lib = chaz_CC_shared_lib_file(name);
-    rule = chaz_MakeFile_add_rule(makefile, shared_lib, sources);
+    filename = chaz_SharedLib_filename(lib);
+    rule = chaz_MakeFile_add_rule(makefile, filename, sources);
 
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_link_shared_library(local_flags);
-    chaz_CFlags_set_link_output(local_flags, shared_lib);
+    chaz_CFlags_set_shared_library_version(local_flags, lib);
+    chaz_CFlags_set_link_output(local_flags, filename);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
                              local_flags_string, NULL);
     chaz_MakeRule_add_command(rule, command);
 
-    chaz_MakeRule_add_rm_command(makefile->clean, shared_lib);
+    chaz_MakeRule_add_rm_command(makefile->clean, filename);
 
     if (chaz_CC_msvc_version_num()) {
         /* Remove import library and export file under MSVC. */
-        char *filename;
-        filename = chaz_Util_join("", name, ".lib", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
-        filename = chaz_Util_join("", name, ".exp", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
+        char *lib_filename = chaz_SharedLib_implib_filename(lib);
+        char *exp_filename = chaz_SharedLib_export_filename(lib);
+        chaz_MakeRule_add_rm_command(makefile->clean, lib_filename);
+        chaz_MakeRule_add_rm_command(makefile->clean, exp_filename);
+        free(lib_filename);
+        free(exp_filename);
     }
 
     chaz_CFlags_destroy(local_flags);
-    free(shared_lib);
+    free(filename);
+    free(command);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir) {
+    chaz_CFlags   *cflags = chaz_CC_new_cflags();
+    chaz_MakeRule *rule;
+    const char *dir_sep = chaz_OS_dir_sep();
+    const char *exe_ext = chaz_OS_exe_ext();
+    char *lemon_exe = chaz_Util_join("", dir, dir_sep, "lemon", exe_ext, NULL);
+    char *lemon_c   = chaz_Util_join(dir_sep, dir, "lemon.c", NULL);
+
+    chaz_CFlags_enable_optimization(cflags);
+    chaz_MakeFile_add_var(makefile, "LEMON_EXE", lemon_exe);
+    rule = chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)", lemon_c,
+                                          cflags);
+
+    chaz_CFlags_destroy(cflags);
+    free(lemon_c);
+    free(lemon_exe);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name) {
+    char *c_file  = chaz_Util_join(".", base_name, "c", NULL);
+    char *h_file  = chaz_Util_join(".", base_name, "h", NULL);
+    char *y_file  = chaz_Util_join(".", base_name, "y", NULL);
+    char *command = chaz_Util_join(" ", "$(LEMON_EXE) -q", y_file, NULL);
+
+    chaz_MakeRule *rule = chaz_MakeFile_add_rule(makefile, c_file, y_file);
+    chaz_MakeRule *clean_rule = chaz_MakeFile_clean_rule(makefile);
+
+    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
+    chaz_MakeRule_add_command(rule, command);
+
+    chaz_MakeRule_add_rm_command(clean_rule, h_file);
+    chaz_MakeRule_add_rm_command(clean_rule, c_file);
+
+    free(c_file);
+    free(h_file);
+    free(y_file);
     free(command);
     return rule;
 }
@@ -3292,7 +3566,7 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
         /* Inference rule for .c files. */
         fprintf(out, ".c.obj :\n");
         if (chaz_CC_msvc_version_num()) {
-            fprintf(out, "\t$(CC) $(CFLAGS) /c $< /Fo$@\n\n");
+            fprintf(out, "\t$(CC) /nologo $(CFLAGS) /c $< /Fo$@\n\n");
         }
         else {
             fprintf(out, "\t$(CC) $(CFLAGS) -c $< -o $@\n\n");
@@ -3564,7 +3838,7 @@ chaz_Make_list_files(const char *dir, const char *ext,
                           file);
         }
 
-        callback(file + prefix_len, context);
+        callback(dir, file + prefix_len, context);
     }
 
     free(prefix);
@@ -3591,11 +3865,12 @@ chaz_Make_list_files(const char *dir, const char *ext,
 static struct {
     char name[CHAZ_OS_NAME_MAX+1];
     char dev_null[20];
+    char dir_sep[2];
     char exe_ext[5];
     char shared_lib_ext[7];
     char local_command_start[3];
     int  shell_type;
-} chaz_OS = { "", "", "", "", "", 0 };
+} chaz_OS = { "", "", "", "", "", "", 0 };
 
 void
 chaz_OS_init(void) {
@@ -3627,6 +3902,7 @@ chaz_OS_init(void) {
         free(uname);
 
         strcpy(chaz_OS.dev_null, "/dev/null");
+        strcpy(chaz_OS.dir_sep, "/");
         strcpy(chaz_OS.exe_ext, "");
         if (memcmp(chaz_OS.name, "darwin", 6) == 0) {
             strcpy(chaz_OS.shared_lib_ext, ".dylib");
@@ -3642,6 +3918,7 @@ chaz_OS_init(void) {
     else if (chaz_Util_can_open_file("nul")) {
         strcpy(chaz_OS.name, "windows");
         strcpy(chaz_OS.dev_null, "nul");
+        strcpy(chaz_OS.dir_sep, "\\");
         strcpy(chaz_OS.exe_ext, ".exe");
         strcpy(chaz_OS.shared_lib_ext, ".dll");
         strcpy(chaz_OS.local_command_start, ".\\");
@@ -3683,6 +3960,11 @@ chaz_OS_dev_null(void) {
     return chaz_OS.dev_null;
 }
 
+const char*
+chaz_OS_dir_sep(void) {
+    return chaz_OS.dir_sep;
+}
+
 int
 chaz_OS_shell_type(void) {
     return chaz_OS.shell_type;
@@ -4288,23 +4570,9 @@ chaz_DirManip_try_rmdir(void) {
     if (chaz_DirManip_compile_rmdir("direct.h"))   { return; }
 }
 
-static int
-chaz_DirManip_is_cygwin(void) {
-    static int is_cygwin = -1;
-    static const char cygwin_code[] =
-        CHAZ_QUOTE(#ifndef __CYGWIN__            )
-        CHAZ_QUOTE(  #error "Not Cygwin"         )
-        CHAZ_QUOTE(#endif                        )
-        CHAZ_QUOTE(int main() { return 0; }      );
-    if (is_cygwin == -1) {
-        is_cygwin = chaz_CC_test_compile(cygwin_code);
-    }
-    return is_cygwin;
-}
-
 void
 chaz_DirManip_run(void) {
-    char dir_sep[3];
+    const char *dir_sep = chaz_OS_dir_sep();
     int remove_zaps_dirs = false;
     int has_dirent_h = chaz_HeadCheck_check_header("dirent.h");
     int has_direct_h = chaz_HeadCheck_check_header("direct.h");
@@ -4362,16 +4630,6 @@ chaz_DirManip_run(void) {
         chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "1");
     }
 
-    if (chaz_DirManip_is_cygwin()) {
-        strcpy(dir_sep, "/");
-    }
-    else if (chaz_HeadCheck_check_header("windows.h")) {
-        strcpy(dir_sep, "\\\\");
-    }
-    else {
-        strcpy(dir_sep, "/");
-    }
-
     {
         char scratch[5];
         sprintf(scratch, "\"%s\"", dir_sep);
@@ -5167,12 +5425,6 @@ chaz_UnusedVars_run(void) {
 /* #include "Charmonizer/Probe.h" */
 /* #include "Charmonizer/Probe/Integers.h" */
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  #define DIR_SEP "\\"
-#else
-  #define DIR_SEP "/"
-#endif
-
 typedef struct SourceFileContext {
     chaz_MakeVar *common_objs;
     chaz_MakeVar *test_cfc_objs;
@@ -5214,19 +5466,11 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 }
 
 static void
-S_add_common_cflags(chaz_CFlags *cflags) {
-    if (chaz_CC_msvc_version_num()) {
-        chaz_CFlags_append(cflags, "/nologo");
-    }
-    chaz_CFlags_enable_optimization(cflags);
-}
-
-static void
-S_source_file_callback(char *file, void *context) {
+S_source_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);
-    size_t obj_file_size;
-    const char *pattern;
     char *obj_file;
 
     if (strcmp(file, "CFCParseHeader.c") == 0) { return; }
@@ -5238,11 +5482,7 @@ S_source_file_callback(char *file, void *context) {
     }
     file[file_len-2] = '\0';
 
-    pattern = "$(SRC_DIR)" DIR_SEP "%s$(OBJ_EXT)";
-    obj_file_size = strlen(pattern) + file_len + 10;
-    obj_file = (char*)malloc(obj_file_size);
-    sprintf(obj_file, pattern, file);
-
+    obj_file = chaz_Util_join("", dir, dir_sep, file, obj_ext, NULL);
     if (strlen(file) >= 7 && memcmp(file, "CFCTest", 7) == 0) {
         chaz_MakeVar_append(sfc->test_cfc_objs, obj_file);
     }
@@ -5258,14 +5498,20 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     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 *parse_header_y = "$(SRC_DIR)" DIR_SEP "CFCParseHeader.y";
-    const char *parse_header_h = "$(SRC_DIR)" DIR_SEP "CFCParseHeader.h";
-    const char *parse_header_c = "$(SRC_DIR)" DIR_SEP "CFCParseHeader.c";
+    char *lemon_dir    = chaz_Util_join(dir_sep, base_dir, "..", "..", "lemon",
+                                        NULL);
+    char *src_dir      = chaz_Util_join(dir_sep, base_dir, "src", NULL);
+    char *include_dir  = chaz_Util_join(dir_sep, base_dir, "include", NULL);
+    char *parse_header = chaz_Util_join(dir_sep, src_dir, "CFCParseHeader",
+                                        NULL);
+    char *cfc_exe      = chaz_Util_join("", "cfc", exe_ext, NULL);
+    char *test_cfc_exe = chaz_Util_join("", "t", dir_sep, "test_cfc", exe_ext,
+                                        NULL);
 
-    char *src_dir;
     char *scratch;
 
     chaz_MakeFile *makefile;
@@ -5273,44 +5519,28 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule *rule;
     chaz_MakeRule *clean_rule;
 
-    int          cflags_style = chaz_CC_get_cflags_style();
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
     chaz_CFlags *link_flags;
-    chaz_CFlags *lemon_cflags;
 
     printf("Creating Makefile...\n");
 
-    src_dir = (char*)malloc(strlen(base_dir) + 20);
-    sprintf(src_dir, "%s" DIR_SEP "src", base_dir);
-
     makefile = chaz_MakeFile_new();
 
     /* Directories */
 
     chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
-    chaz_MakeFile_add_var(makefile, "SRC_DIR", src_dir);
-    chaz_MakeFile_add_var(makefile, "INCLUDE_DIR",
-                          "$(BASE_DIR)" DIR_SEP "include");
-    chaz_MakeFile_add_var(makefile, "LEMON_DIR",
-                          "$(BASE_DIR)" DIR_SEP ".." DIR_SEP ".." DIR_SEP
-                          "lemon");
-
-    /* File extensions */
-
-    chaz_MakeFile_add_var(makefile, "EXE_EXT", exe_ext);
-    chaz_MakeFile_add_var(makefile, "OBJ_EXT", obj_ext);
 
     /* C compiler */
 
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
 
-    makefile_cflags = chaz_CFlags_new(cflags_style);
-    S_add_common_cflags(makefile_cflags);
+    makefile_cflags = chaz_CC_new_cflags();
 
+    chaz_CFlags_enable_optimization(makefile_cflags);
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(INCLUDE_DIR)");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(SRC_DIR)");
+    chaz_CFlags_add_include_dir(makefile_cflags, include_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, src_dir);
     if (args->code_coverage) {
         chaz_CFlags_enable_code_coverage(makefile_cflags);
     }
@@ -5329,65 +5559,56 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_Make_list_files(src_dir, "c", S_source_file_callback, &sfc);
 
-    chaz_MakeVar_append(sfc.common_objs,
-                        "$(SRC_DIR)" DIR_SEP "CFCParseHeader$(OBJ_EXT)");
-    chaz_MakeVar_append(sfc.test_cfc_objs, "t" DIR_SEP "test_cfc$(OBJ_EXT)");
-
-    chaz_MakeFile_add_var(makefile, "CFC_OBJS", "cfc$(OBJ_EXT)");
+    scratch = chaz_Util_join("", parse_header, obj_ext, NULL);
+    chaz_MakeVar_append(sfc.common_objs, scratch);
+    free(scratch);
 
-    /* Executables */
+    scratch = chaz_Util_join("", "t", dir_sep, "test_cfc", obj_ext, NULL);
+    chaz_MakeVar_append(sfc.test_cfc_objs, scratch);
+    free(scratch);
 
-    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)");
+    scratch = chaz_Util_join("", "cfc", obj_ext, NULL);
+    chaz_MakeFile_add_var(makefile, "CFC_OBJS", scratch);
+    free(scratch);
 
     /* Rules */
 
-    chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)");
+    chaz_MakeFile_add_rule(makefile, "all", cfc_exe);
 
-    lemon_cflags = chaz_CFlags_new(cflags_style);
-    S_add_common_cflags(lemon_cflags);
-    chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
-                                   "$(LEMON_DIR)" DIR_SEP "lemon.c",
-                                   lemon_cflags);
-    chaz_CFlags_destroy(lemon_cflags);
+    chaz_MakeFile_add_lemon_exe(makefile, lemon_dir);
+    chaz_MakeFile_add_lemon_grammar(makefile, parse_header);
 
-    rule = chaz_MakeFile_add_rule(makefile, parse_header_c, NULL);
-    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
-    chaz_MakeRule_add_prereq(rule, parse_header_y);
-    scratch = (char*)malloc(strlen(parse_header_y) + 20);
-    sprintf(scratch, "$(LEMON_EXE) -q %s", parse_header_y);
-    chaz_MakeRule_add_command(rule, scratch);
+    /*
+     * The dependency is actually on CFCParseHeader.h, but make doesn't cope
+     * well with multiple output files.
+     */
+    scratch = chaz_Util_join(".", parse_header, "c", NULL);
+    chaz_MakeFile_add_rule(makefile, "$(COMMON_OBJS)", scratch);
     free(scratch);
 
-    chaz_MakeFile_add_rule(makefile, "$(COMMON_OBJS)", parse_header_c);
-
-    link_flags = chaz_CFlags_new(cflags_style);
+    link_flags = chaz_CC_new_cflags();
     if (chaz_CC_msvc_version_num()) {
         chaz_CFlags_append(link_flags, "/nologo");
     }
     if (args->code_coverage) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
-    chaz_MakeFile_add_exe(makefile, "$(CFC_EXE)",
-                          "$(COMMON_OBJS) $(CFC_OBJS)", link_flags);
-    chaz_MakeFile_add_exe(makefile, "$(TEST_CFC_EXE)",
+    chaz_MakeFile_add_exe(makefile, cfc_exe, "$(COMMON_OBJS) $(CFC_OBJS)",
+                          link_flags);
+    chaz_MakeFile_add_exe(makefile, test_cfc_exe,
                           "$(COMMON_OBJS) $(TEST_CFC_OBJS)", link_flags);
     chaz_CFlags_destroy(link_flags);
 
-    rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_CFC_EXE)");
-    chaz_MakeRule_add_command(rule, "$(TEST_CFC_EXE)");
+    rule = chaz_MakeFile_add_rule(makefile, "test", test_cfc_exe);
+    chaz_MakeRule_add_command(rule, test_cfc_exe);
 
     if (args->code_coverage) {
-        rule = chaz_MakeFile_add_rule(makefile, "coverage",
-                                      "$(TEST_CFC_EXE)");
+        rule = chaz_MakeFile_add_rule(makefile, "coverage", test_cfc_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --zerocounters"
                                   " --directory $(BASE_DIR)");
-        chaz_MakeRule_add_command(rule, "$(TEST_CFC_EXE)");
+        chaz_MakeRule_add_command(rule, test_cfc_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --capture"
@@ -5407,8 +5628,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule_add_rm_command(clean_rule, "$(COMMON_OBJS)");
     chaz_MakeRule_add_rm_command(clean_rule, "$(CFC_OBJS)");
     chaz_MakeRule_add_rm_command(clean_rule, "$(TEST_CFC_OBJS)");
-    chaz_MakeRule_add_rm_command(clean_rule, parse_header_h);
-    chaz_MakeRule_add_rm_command(clean_rule, parse_header_c);
 
     if (args->code_coverage) {
         chaz_MakeRule_add_rm_command(clean_rule, "cfc.info");
@@ -5418,7 +5637,12 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_write(makefile);
 
     chaz_MakeFile_destroy(makefile);
+    free(lemon_dir);
     free(src_dir);
+    free(include_dir);
+    free(parse_header);
+    free(cfc_exe);
+    free(test_cfc_exe);
 }
 
 int main(int argc, const char **argv) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/07c27701/clownfish/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/clownfish/runtime/common/charmonizer.c b/clownfish/runtime/common/charmonizer.c
index 3affa90..aef9a82 100644
--- a/clownfish/runtime/common/charmonizer.c
+++ b/clownfish/runtime/common/charmonizer.c
@@ -36,12 +36,58 @@
 
 /***************************************************************************/
 
+#line 21 "src/Charmonizer/Core/SharedLibrary.h"
+/* Charmonizer/Core/SharedLibrary.h
+ */
+
+#ifndef H_CHAZ_SHARED_LIB
+#define H_CHAZ_SHARED_LIB
+
+typedef struct chaz_SharedLib chaz_SharedLib;
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version);
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *flags);
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib);
+
+#endif /* H_CHAZ_SHARED_LIB */
+
+
+
+/***************************************************************************/
+
 #line 21 "src/Charmonizer/Core/CFlags.h"
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/CFlags.h
  */
 
-#ifndef H_CHAZ_FLAGS
-#define H_CHAZ_FLAGS
+#ifndef H_CHAZ_CFLAGS
+#define H_CHAZ_CFLAGS
 
 #define CHAZ_CFLAGS_STYLE_POSIX  1
 #define CHAZ_CFLAGS_STYLE_GNU    2
@@ -96,18 +142,25 @@ void
 chaz_CFlags_link_shared_library(chaz_CFlags *flags);
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib);
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename);
 
 void
 chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory);
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library);
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib);
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library);
 
 void
 chaz_CFlags_enable_code_coverage(chaz_CFlags *flags);
 
-#endif /* H_CHAZ_FLAGS */
+#endif /* H_CHAZ_CFLAGS */
 
 
 
@@ -172,11 +225,6 @@ chaz_CC_get_cc(void);
 const char*
 chaz_CC_get_cflags(void);
 
-/* Accessor for `cflags_style`.
- */
-int
-chaz_CC_get_cflags_style(void);
-
 /* Accessor for `extra_cflags`.
  */
 chaz_CFlags*
@@ -187,6 +235,11 @@ chaz_CC_get_extra_cflags(void);
 chaz_CFlags*
 chaz_CC_get_temp_cflags(void);
 
+/* Return a new CFlags object.
+ */
+chaz_CFlags*
+chaz_CC_new_cflags(void);
+
 /* Return the extension for a compiled object.
  */
 const char*
@@ -204,9 +257,6 @@ chaz_CC_msvc_version_num(void);
 const char*
 chaz_CC_link_command(void);
 
-char*
-chaz_CC_shared_lib_file(const char *name);
-
 #endif /* H_CHAZ_COMPILER */
 
 
@@ -416,19 +466,21 @@ chaz_HeadCheck_contains_member(const char *struct_name, const char *member,
 /***************************************************************************/
 
 #line 21 "src/Charmonizer/Core/Make.h"
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/Make.h
  */
 
 #ifndef H_CHAZ_MAKE
 #define H_CHAZ_MAKE
 
 /* #include "Charmonizer/Core/CFlags.h" */
+/* #include "Charmonizer/Core/SharedLib.h" */
 
 typedef struct chaz_MakeFile chaz_MakeFile;
 typedef struct chaz_MakeVar chaz_MakeVar;
 typedef struct chaz_MakeRule chaz_MakeRule;
 
-typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
+typedef void (*chaz_Make_list_files_callback_t)(const char *dir, char *file,
+                                                void *context);
 
 /** Initialize the environment.
  */
@@ -539,14 +591,31 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
  * to the list of files to clean.
  *
  * @param makefile The makefile.
- * @param name The name of the shared library without prefix or extension.
+ * @param lib The shared library.
  * @param sources The list of source files.
  * @param link_flags Additional link flags.
  */
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags);
 
+/** Add a rule to build the lemon parser generator.
+ *
+ * @param makefile The makefile.
+ * @param dir The lemon directory.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir);
+
+/** Add a rule for a lemon grammar.
+ *
+ * @param makefile The makefile.
+ * @param base_name The filename of the grammar without extension.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name);
+
 /** Write the makefile to a file named 'Makefile' in the current directory.
  *
  * @param makefile The makefile.
@@ -696,6 +765,11 @@ chaz_OS_shared_lib_ext(void);
 const char*
 chaz_OS_dev_null(void);
 
+/* Return the directory separator on this system.
+ */
+const char*
+chaz_OS_dir_sep(void);
+
 /* Return the shell type of this system.
  */
 int
@@ -1441,12 +1515,136 @@ void chaz_VariadicMacros_run(void);
 
 /***************************************************************************/
 
+#line 17 "src/Charmonizer/Core/SharedLibrary.c"
+#include <string.h>
+#include <stdlib.h>
+/* #include "Charmonizer/Core/SharedLib.h" */
+/* #include "Charmonizer/Core/Compiler.h" */
+/* #include "Charmonizer/Core/Util.h" */
+/* #include "Charmonizer/Core/OperatingSystem.h" */
+
+struct chaz_SharedLib {
+    char *name;
+    char *version;
+    char *major_version;
+};
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext);
+
+static const char*
+S_get_prefix(void);
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version) {
+    chaz_SharedLib *lib = (chaz_SharedLib*)malloc(sizeof(chaz_SharedLib));
+    lib->name          = chaz_Util_strdup(name);
+    lib->version       = chaz_Util_strdup(version);
+    lib->major_version = chaz_Util_strdup(major_version);
+    return lib;
+}
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *lib) {
+    free(lib->name);
+    free(lib->version);
+    free(lib->major_version);
+    free(lib);
+}
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib) {
+    return lib->name;
+}
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib) {
+    return lib->version;
+}
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib) {
+    return lib->major_version;
+}
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return S_build_filename(lib, lib->major_version, shlib_ext);
+    }
+    else {
+        return S_build_filename(lib, lib->version, shlib_ext);
+    }
+}
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return S_build_filename(lib, lib->major_version, shlib_ext);
+}
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return chaz_Util_join("", prefix, lib->name, shlib_ext, NULL);
+}
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".lib");
+}
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".exp");
+}
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL);
+    }
+    else if (strcmp(shlib_ext, ".dylib") == 0) {
+        return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL);
+    }
+    else {
+        return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL);
+    }
+}
+
+static const char*
+S_get_prefix() {
+    if (chaz_CC_msvc_version_num()) {
+        return "";
+    }
+    else if (chaz_OS_is_cygwin()) {
+        return "cyg";
+    }
+    else {
+        return "lib";
+    }
+}
+
+
+
+/***************************************************************************/
+
 #line 17 "src/Charmonizer/Core/CFlags.c"
 #include <string.h>
 #include <stdlib.h>
-/* #include "Charmonizer/Core/Flags.h" */
+/* #include "Charmonizer/Core/CFlags.h" */
 /* #include "Charmonizer/Core/Util.h" */
 /* #include "Charmonizer/Core/OperatingSystem.h" */
+/* #include "Charmonizer/Core/SharedLibrary.h" */
 
 struct chaz_CFlags {
     int   style;
@@ -1641,7 +1839,7 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
         string = "/DLL";
     }
     else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        if (chaz_OS_is_darwin()) {
+        if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
             string = "-dynamiclib";
         }
         else {
@@ -1656,6 +1854,30 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
 }
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+    char       *string;
+
+    if (flags->style != CHAZ_CFLAGS_STYLE_GNU
+        || strcmp(shlib_ext, ".dll") == 0) {
+        return;
+    }
+
+    if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
+        const char *version = chaz_SharedLib_get_version(lib);
+        string = chaz_Util_join(" ", "-current_version", version, NULL);
+    }
+    else {
+        char *soname = chaz_SharedLib_major_version_filename(lib);
+        string = chaz_Util_join("", "-Wl,-soname,", soname, NULL);
+        free(soname);
+    }
+    chaz_CFlags_append(flags, string);
+    free(string);
+}
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename) {
     const char *output;
     char *string;
@@ -1692,13 +1914,26 @@ chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory) {
 }
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library) {
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib) {
+    char *filename;
+    if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
+        filename = chaz_SharedLib_implib_filename(lib);
+    }
+    else {
+        filename = chaz_SharedLib_filename(lib);
+    }
+    chaz_CFlags_append(flags, filename);
+    free(filename);
+}
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library) {
     char *string;
     if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
         string = chaz_Util_join("", library, ".lib", NULL);
     }
     else {
-        string = chaz_Util_join("", "-l ", library, NULL);
+        string = chaz_Util_join(" ", "-l", library, NULL);
     }
     chaz_CFlags_append(flags, string);
     free(string);
@@ -2025,11 +2260,6 @@ chaz_CC_get_cflags(void) {
     return chaz_CC.cflags;
 }
 
-int
-chaz_CC_get_cflags_style(void) {
-    return chaz_CC.cflags_style;
-}
-
 chaz_CFlags*
 chaz_CC_get_extra_cflags(void) {
     return chaz_CC.extra_cflags;
@@ -2040,6 +2270,11 @@ chaz_CC_get_temp_cflags(void) {
     return chaz_CC.temp_cflags;
 }
 
+chaz_CFlags*
+chaz_CC_new_cflags(void) {
+    return chaz_CFlags_new(chaz_CC.cflags_style);
+}
+
 const char*
 chaz_CC_obj_ext(void) {
     return chaz_CC.obj_ext;
@@ -2072,21 +2307,6 @@ chaz_CC_link_command() {
     }
 }
 
-char*
-chaz_CC_shared_lib_file(const char *name) {
-    const char *prefix = "";
-    const char *shlib_ext = chaz_OS_shared_lib_ext();
-    if (!chaz_CC.intval__MSC_VER) {
-        if (chaz_OS_is_cygwin()) {
-            prefix = "cyg";
-        }
-        else {
-            prefix = "lib";
-        }
-    }
-    return chaz_Util_join("", prefix, name, shlib_ext, NULL);
-}
-
 
 
 /***************************************************************************/
@@ -3349,6 +3569,9 @@ chaz_Make_audition(const char *make) {
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
+    const char    *exe_ext  = chaz_OS_exe_ext();
+    const char    *obj_ext  = chaz_CC_obj_ext();
+    char *generated;
 
     makefile->vars = (chaz_MakeVar**)malloc(sizeof(chaz_MakeVar*));
     makefile->vars[0] = NULL;
@@ -3361,10 +3584,11 @@ chaz_MakeFile_new() {
     makefile->clean     = S_new_rule("clean", NULL);
     makefile->distclean = S_new_rule("distclean", "clean");
 
-    chaz_MakeRule_add_rm_command(makefile->distclean,
-                                 "charmonizer$(EXE_EXT) charmonizer$(OBJ_EXT)"
-                                 " charmony.h Makefile");
+    generated = chaz_Util_join("", "charmonizer", exe_ext, " charmonizer",
+                               obj_ext, " charmony.h Makefile", NULL);
+    chaz_MakeRule_add_rm_command(makefile->distclean, generated);
 
+    free(generated);
     return makefile;
 }
 
@@ -3444,8 +3668,7 @@ chaz_MakeFile_distclean_rule(chaz_MakeFile *makefile) {
 chaz_MakeRule*
 chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
                       const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
@@ -3457,6 +3680,9 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_link_output(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
@@ -3473,8 +3699,7 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
 chaz_MakeRule*
 chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
                                const char *sources, chaz_CFlags *cflags) {
-    int            cflags_style  = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags   = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags   = chaz_CC_new_cflags();
     const char    *cc            = chaz_CC_get_cc();
     const char    *cflags_string = "";
     const char    *local_flags_string;
@@ -3486,6 +3711,9 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
     if (cflags) {
         cflags_string = chaz_CFlags_get_string(cflags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_output_exe(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", cc, sources, cflags_string,
@@ -3501,45 +3729,91 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
 }
 
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
     chaz_MakeRule *rule;
-    char          *shared_lib;
+    char          *filename;
     char          *command;
 
-    shared_lib = chaz_CC_shared_lib_file(name);
-    rule = chaz_MakeFile_add_rule(makefile, shared_lib, sources);
+    filename = chaz_SharedLib_filename(lib);
+    rule = chaz_MakeFile_add_rule(makefile, filename, sources);
 
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_link_shared_library(local_flags);
-    chaz_CFlags_set_link_output(local_flags, shared_lib);
+    chaz_CFlags_set_shared_library_version(local_flags, lib);
+    chaz_CFlags_set_link_output(local_flags, filename);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
                              local_flags_string, NULL);
     chaz_MakeRule_add_command(rule, command);
 
-    chaz_MakeRule_add_rm_command(makefile->clean, shared_lib);
+    chaz_MakeRule_add_rm_command(makefile->clean, filename);
 
     if (chaz_CC_msvc_version_num()) {
         /* Remove import library and export file under MSVC. */
-        char *filename;
-        filename = chaz_Util_join("", name, ".lib", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
-        filename = chaz_Util_join("", name, ".exp", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
+        char *lib_filename = chaz_SharedLib_implib_filename(lib);
+        char *exp_filename = chaz_SharedLib_export_filename(lib);
+        chaz_MakeRule_add_rm_command(makefile->clean, lib_filename);
+        chaz_MakeRule_add_rm_command(makefile->clean, exp_filename);
+        free(lib_filename);
+        free(exp_filename);
     }
 
     chaz_CFlags_destroy(local_flags);
-    free(shared_lib);
+    free(filename);
+    free(command);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir) {
+    chaz_CFlags   *cflags = chaz_CC_new_cflags();
+    chaz_MakeRule *rule;
+    const char *dir_sep = chaz_OS_dir_sep();
+    const char *exe_ext = chaz_OS_exe_ext();
+    char *lemon_exe = chaz_Util_join("", dir, dir_sep, "lemon", exe_ext, NULL);
+    char *lemon_c   = chaz_Util_join(dir_sep, dir, "lemon.c", NULL);
+
+    chaz_CFlags_enable_optimization(cflags);
+    chaz_MakeFile_add_var(makefile, "LEMON_EXE", lemon_exe);
+    rule = chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)", lemon_c,
+                                          cflags);
+
+    chaz_CFlags_destroy(cflags);
+    free(lemon_c);
+    free(lemon_exe);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name) {
+    char *c_file  = chaz_Util_join(".", base_name, "c", NULL);
+    char *h_file  = chaz_Util_join(".", base_name, "h", NULL);
+    char *y_file  = chaz_Util_join(".", base_name, "y", NULL);
+    char *command = chaz_Util_join(" ", "$(LEMON_EXE) -q", y_file, NULL);
+
+    chaz_MakeRule *rule = chaz_MakeFile_add_rule(makefile, c_file, y_file);
+    chaz_MakeRule *clean_rule = chaz_MakeFile_clean_rule(makefile);
+
+    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
+    chaz_MakeRule_add_command(rule, command);
+
+    chaz_MakeRule_add_rm_command(clean_rule, h_file);
+    chaz_MakeRule_add_rm_command(clean_rule, c_file);
+
+    free(c_file);
+    free(h_file);
+    free(y_file);
     free(command);
     return rule;
 }
@@ -3571,7 +3845,7 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
         /* Inference rule for .c files. */
         fprintf(out, ".c.obj :\n");
         if (chaz_CC_msvc_version_num()) {
-            fprintf(out, "\t$(CC) $(CFLAGS) /c $< /Fo$@\n\n");
+            fprintf(out, "\t$(CC) /nologo $(CFLAGS) /c $< /Fo$@\n\n");
         }
         else {
             fprintf(out, "\t$(CC) $(CFLAGS) -c $< -o $@\n\n");
@@ -3843,7 +4117,7 @@ chaz_Make_list_files(const char *dir, const char *ext,
                           file);
         }
 
-        callback(file + prefix_len, context);
+        callback(dir, file + prefix_len, context);
     }
 
     free(prefix);
@@ -3870,11 +4144,12 @@ chaz_Make_list_files(const char *dir, const char *ext,
 static struct {
     char name[CHAZ_OS_NAME_MAX+1];
     char dev_null[20];
+    char dir_sep[2];
     char exe_ext[5];
     char shared_lib_ext[7];
     char local_command_start[3];
     int  shell_type;
-} chaz_OS = { "", "", "", "", "", 0 };
+} chaz_OS = { "", "", "", "", "", "", 0 };
 
 void
 chaz_OS_init(void) {
@@ -3906,6 +4181,7 @@ chaz_OS_init(void) {
         free(uname);
 
         strcpy(chaz_OS.dev_null, "/dev/null");
+        strcpy(chaz_OS.dir_sep, "/");
         strcpy(chaz_OS.exe_ext, "");
         if (memcmp(chaz_OS.name, "darwin", 6) == 0) {
             strcpy(chaz_OS.shared_lib_ext, ".dylib");
@@ -3921,6 +4197,7 @@ chaz_OS_init(void) {
     else if (chaz_Util_can_open_file("nul")) {
         strcpy(chaz_OS.name, "windows");
         strcpy(chaz_OS.dev_null, "nul");
+        strcpy(chaz_OS.dir_sep, "\\");
         strcpy(chaz_OS.exe_ext, ".exe");
         strcpy(chaz_OS.shared_lib_ext, ".dll");
         strcpy(chaz_OS.local_command_start, ".\\");
@@ -3962,6 +4239,11 @@ chaz_OS_dev_null(void) {
     return chaz_OS.dev_null;
 }
 
+const char*
+chaz_OS_dir_sep(void) {
+    return chaz_OS.dir_sep;
+}
+
 int
 chaz_OS_shell_type(void) {
     return chaz_OS.shell_type;
@@ -4658,23 +4940,9 @@ chaz_DirManip_try_rmdir(void) {
     if (chaz_DirManip_compile_rmdir("direct.h"))   { return; }
 }
 
-static int
-chaz_DirManip_is_cygwin(void) {
-    static int is_cygwin = -1;
-    static const char cygwin_code[] =
-        CHAZ_QUOTE(#ifndef __CYGWIN__            )
-        CHAZ_QUOTE(  #error "Not Cygwin"         )
-        CHAZ_QUOTE(#endif                        )
-        CHAZ_QUOTE(int main() { return 0; }      );
-    if (is_cygwin == -1) {
-        is_cygwin = chaz_CC_test_compile(cygwin_code);
-    }
-    return is_cygwin;
-}
-
 void
 chaz_DirManip_run(void) {
-    char dir_sep[3];
+    const char *dir_sep = chaz_OS_dir_sep();
     int remove_zaps_dirs = false;
     int has_dirent_h = chaz_HeadCheck_check_header("dirent.h");
     int has_direct_h = chaz_HeadCheck_check_header("direct.h");
@@ -4732,16 +5000,6 @@ chaz_DirManip_run(void) {
         chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "1");
     }
 
-    if (chaz_DirManip_is_cygwin()) {
-        strcpy(dir_sep, "/");
-    }
-    else if (chaz_HeadCheck_check_header("windows.h")) {
-        strcpy(dir_sep, "\\\\");
-    }
-    else {
-        strcpy(dir_sep, "/");
-    }
-
     {
         char scratch[5];
         sprintf(scratch, "\"%s\"", dir_sep);
@@ -4820,7 +5078,7 @@ chaz_Floats_math_library(void) {
         return NULL;
     }
 
-    chaz_CFlags_add_library(temp_cflags, "m");
+    chaz_CFlags_add_external_library(temp_cflags, "m");
     output = chaz_CC_capture_output(sqrt_code, &output_len);
     chaz_CFlags_clear(temp_cflags);
 
@@ -5653,7 +5911,7 @@ typedef struct chaz_LargeFiles_unbuff_combo {
 
 /* Check for a 64-bit file pointer type.
  */
-static const int
+static int
 chaz_LargeFiles_probe_off64(void);
 
 /* Check what name 64-bit ftell, fseek go by.
@@ -5720,7 +5978,7 @@ chaz_LargeFiles_run(void) {
     chaz_ConfWriter_end_module();
 }
 
-static const int
+static int
 chaz_LargeFiles_probe_off64(void) {
     static const char off64_code[] =
         CHAZ_QUOTE(  %s                                        )


[lucy-commits] [08/13] git commit: refs/heads/makefile-rework - Eliminate DIR_SEP macro in charmonizer.main

Posted by nw...@apache.org.
Eliminate DIR_SEP macro in charmonizer.main


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

Branch: refs/heads/makefile-rework
Commit: e4723761100d817f90e97f99702b6271985dd968
Parents: 239afba
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed May 15 00:45:50 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:54 2013 +0200

----------------------------------------------------------------------
 clownfish/compiler/common/charmonizer.main |   22 +++----
 common/charmonizer.main                    |   80 ++++++++++++----------
 2 files changed, 53 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/e4723761/clownfish/compiler/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.main b/clownfish/compiler/common/charmonizer.main
index 4a9df5d..460dd7e 100644
--- a/clownfish/compiler/common/charmonizer.main
+++ b/clownfish/compiler/common/charmonizer.main
@@ -23,12 +23,6 @@
 #include "Charmonizer/Probe.h"
 #include "Charmonizer/Probe/Integers.h"
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  #define DIR_SEP "\\"
-#else
-  #define DIR_SEP "/"
-#endif
-
 typedef struct SourceFileContext {
     chaz_MakeVar *common_objs;
     chaz_MakeVar *test_cfc_objs;
@@ -72,6 +66,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 static void
 S_source_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;
@@ -85,7 +80,7 @@ S_source_file_callback(const char *dir, char *file, void *context) {
     }
     file[file_len-2] = '\0';
 
-    obj_file = chaz_Util_join("", dir, DIR_SEP, file, obj_ext, NULL);
+    obj_file = chaz_Util_join("", dir, dir_sep, file, obj_ext, NULL);
     if (strlen(file) >= 7 && memcmp(file, "CFCTest", 7) == 0) {
         chaz_MakeVar_append(sfc->test_cfc_objs, obj_file);
     }
@@ -101,17 +96,18 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     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();
 
-    char *lemon_dir    = chaz_Util_join(DIR_SEP, base_dir, "..", "..", "lemon",
+    char *lemon_dir    = chaz_Util_join(dir_sep, base_dir, "..", "..", "lemon",
                                         NULL);
-    char *src_dir      = chaz_Util_join(DIR_SEP, base_dir, "src", NULL);
-    char *include_dir  = chaz_Util_join(DIR_SEP, base_dir, "include", NULL);
-    char *parse_header = chaz_Util_join(DIR_SEP, src_dir, "CFCParseHeader",
+    char *src_dir      = chaz_Util_join(dir_sep, base_dir, "src", NULL);
+    char *include_dir  = chaz_Util_join(dir_sep, base_dir, "include", NULL);
+    char *parse_header = chaz_Util_join(dir_sep, src_dir, "CFCParseHeader",
                                         NULL);
     char *cfc_exe      = chaz_Util_join("", "cfc", exe_ext, NULL);
-    char *test_cfc_exe = chaz_Util_join("", "t", DIR_SEP, "test_cfc", exe_ext,
+    char *test_cfc_exe = chaz_Util_join("", "t", dir_sep, "test_cfc", exe_ext,
                                         NULL);
 
     char *scratch;
@@ -165,7 +161,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeVar_append(sfc.common_objs, scratch);
     free(scratch);
 
-    scratch = chaz_Util_join("", "t", DIR_SEP, "test_cfc", obj_ext, NULL);
+    scratch = chaz_Util_join("", "t", dir_sep, "test_cfc", obj_ext, NULL);
     chaz_MakeVar_append(sfc.test_cfc_objs, scratch);
     free(scratch);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/e4723761/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 60cd820..88219d6 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -38,12 +38,6 @@
 #include "Charmonizer/Core/ConfWriterPerl.h"
 #include "Charmonizer/Core/ConfWriterRuby.h"
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  #define DIR_SEP "\\"
-#else
-  #define DIR_SEP "/"
-#endif
-
 typedef struct SourceFileContext {
     chaz_MakeVar *var;
 } SourceFileContext;
@@ -99,27 +93,34 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
 }
 
+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 void
 S_source_file_callback(const char *dir, char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
-    const char *obj_ext       = chaz_CC_obj_ext();
-    const char *json_parser_c = "Lucy" DIR_SEP "Util" DIR_SEP "Json" DIR_SEP
-                                "JsonParser.c";
+    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;
 
-    if (strcmp(file, json_parser_c) == 0) { return; }
-
     /* Strip extension */
-    if (file_len <= 2 || memcmp(file + file_len - 2, ".c", 2) != 0) {
+    if (!S_ends_with(file, ".c")) {
         chaz_Util_warn("Unexpected source file name: %s", file);
         return;
     }
     file[file_len-2] = '\0';
 
-    obj_file = chaz_Util_join("", dir, DIR_SEP, file, obj_ext, NULL);
-    chaz_MakeVar_append(sfc->var, obj_file);
-    free(obj_file);
+    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);
+    }
 }
 
 static void
@@ -127,31 +128,35 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     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();
 
-    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 *cfc_dir       = chaz_Util_join(DIR_SEP, base_dir, "clownfish",
+    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 *cfc_dir       = chaz_Util_join(dir_sep, base_dir, "clownfish",
                                          "compiler", "c", NULL);
-    char *modules_dir   = chaz_Util_join(DIR_SEP, base_dir, "modules", NULL);
-    char *snowstem_dir  = chaz_Util_join(DIR_SEP, modules_dir, "analysis",
+    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 *snowstem_inc_dir = chaz_Util_join(DIR_SEP, snowstem_dir, "include",
-                                            NULL);
-    char *snowstop_dir  = chaz_Util_join(DIR_SEP, modules_dir, "analysis",
+    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",
+    char *ucd_dir       = chaz_Util_join(dir_sep, modules_dir, "unicode",
                                          "ucd", NULL);
-    char *utf8proc_dir  = chaz_Util_join(DIR_SEP, modules_dir, "unicode",
+    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",
+    char *json_parser   = chaz_Util_join(dir_sep, core_dir, "Lucy", "Util",
                                          "Json", "JsonParser", NULL);
-    char *cfc_exe       = chaz_Util_join("", cfc_dir, DIR_SEP, "cfc", exe_ext,
+    char *cfc_exe       = chaz_Util_join("", cfc_dir, dir_sep, "cfc", exe_ext,
                                          NULL);
-    char *test_lucy_exe = chaz_Util_join("", "t", DIR_SEP, "test_lucy",
+    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 *snowstem_inc_dir
+        = chaz_Util_join(dir_sep, snowstem_dir, "include", NULL);
+
     chaz_MakeFile *makefile;
     chaz_MakeVar  *var;
     chaz_MakeRule *rule;
@@ -193,7 +198,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
     chaz_CFlags_add_include_dir(makefile_cflags, core_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, "autogen" DIR_SEP "include");
+    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);
@@ -220,7 +225,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeVar_append(var, scratch);
     free(scratch);
 
-    scratch = chaz_Util_join("", "autogen", DIR_SEP, "source", DIR_SEP,
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
                              "parcel", obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
@@ -248,8 +253,9 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     free(scratch);
 
     /* Needed for parallel builds. */
-    rule = chaz_MakeFile_add_rule(makefile, "autogen" DIR_SEP "source"
-                                  DIR_SEP "parcel.c", "autogen");
+    scratch = chaz_Util_join(dir_sep, "autogen", "source", "parcel.c", NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    free(scratch);
 
     rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "autogen");
     /*
@@ -279,11 +285,12 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     test_cflags = chaz_CC_new_cflags();
     chaz_CFlags_enable_optimization(test_cflags);
     chaz_CFlags_add_include_dir(test_cflags, ".");
-    chaz_CFlags_add_include_dir(test_cflags, "autogen" DIR_SEP "include");
+    chaz_CFlags_add_include_dir(test_cflags, autogen_inc_dir);
     chaz_CFlags_add_library(link_flags, lib);
-    rule = chaz_MakeFile_add_compiled_exe(makefile, test_lucy_exe,
-                                          "t" DIR_SEP "test_lucy.c",
+    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, lib_filename);
     chaz_CFlags_destroy(test_cflags);
 
@@ -353,13 +360,14 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     free(cfc_dir);
     free(modules_dir);
     free(snowstem_dir);
-    free(snowstem_inc_dir);
     free(snowstop_dir);
     free(ucd_dir);
     free(utf8proc_dir);
     free(json_parser);
     free(cfc_exe);
     free(test_lucy_exe);
+    free(autogen_inc_dir);
+    free(snowstem_inc_dir);
     free(lib_filename);
     free(test_command);
 }


[lucy-commits] [09/13] git commit: refs/heads/makefile-rework - Eliminate Makefile variables for file extensions

Posted by nw...@apache.org.
Eliminate Makefile variables for file extensions


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

Branch: refs/heads/makefile-rework
Commit: 239afba4600d1ce7034e1bfa09a48023d3bce03a
Parents: 8aacc86
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed May 15 00:28:41 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:54 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/Make.c    |   10 +++++++---
 clownfish/compiler/common/charmonizer.main |   21 ++++++++++-----------
 common/charmonizer.main                    |   18 +++++++-----------
 3 files changed, 24 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/239afba4/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index b3aba56..d15751d 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -169,6 +169,9 @@ chaz_Make_audition(const char *make) {
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
+    const char    *exe_ext  = chaz_OS_exe_ext();
+    const char    *obj_ext  = chaz_CC_obj_ext();
+    char *generated;
 
     makefile->vars = (chaz_MakeVar**)malloc(sizeof(chaz_MakeVar*));
     makefile->vars[0] = NULL;
@@ -181,10 +184,11 @@ chaz_MakeFile_new() {
     makefile->clean     = S_new_rule("clean", NULL);
     makefile->distclean = S_new_rule("distclean", "clean");
 
-    chaz_MakeRule_add_rm_command(makefile->distclean,
-                                 "charmonizer$(EXE_EXT) charmonizer$(OBJ_EXT)"
-                                 " charmony.h Makefile");
+    generated = chaz_Util_join("", "charmonizer", exe_ext, " charmonizer",
+                               obj_ext, " charmony.h Makefile", NULL);
+    chaz_MakeRule_add_rm_command(makefile->distclean, generated);
 
+    free(generated);
     return makefile;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/239afba4/clownfish/compiler/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.main b/clownfish/compiler/common/charmonizer.main
index ff38656..4a9df5d 100644
--- a/clownfish/compiler/common/charmonizer.main
+++ b/clownfish/compiler/common/charmonizer.main
@@ -72,9 +72,8 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 static void
 S_source_file_callback(const char *dir, char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
+    const char *obj_ext = chaz_CC_obj_ext();
     size_t file_len = strlen(file);
-    size_t obj_file_size;
-    const char *pattern;
     char *obj_file;
 
     if (strcmp(file, "CFCParseHeader.c") == 0) { return; }
@@ -86,7 +85,7 @@ S_source_file_callback(const char *dir, char *file, void *context) {
     }
     file[file_len-2] = '\0';
 
-    obj_file = chaz_Util_join("", dir, DIR_SEP, file, "$(OBJ_EXT)", NULL);
+    obj_file = chaz_Util_join("", dir, DIR_SEP, file, obj_ext, NULL);
     if (strlen(file) >= 7 && memcmp(file, "CFCTest", 7) == 0) {
         chaz_MakeVar_append(sfc->test_cfc_objs, obj_file);
     }
@@ -134,11 +133,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
 
-    /* File extensions */
-
-    chaz_MakeFile_add_var(makefile, "EXE_EXT", exe_ext);
-    chaz_MakeFile_add_var(makefile, "OBJ_EXT", obj_ext);
-
     /* C compiler */
 
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
@@ -167,12 +161,17 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_Make_list_files(src_dir, "c", S_source_file_callback, &sfc);
 
-    scratch = chaz_Util_join("", parse_header, "$(OBJ_EXT)", NULL);
+    scratch = chaz_Util_join("", parse_header, obj_ext, NULL);
     chaz_MakeVar_append(sfc.common_objs, scratch);
     free(scratch);
-    chaz_MakeVar_append(sfc.test_cfc_objs, "t" DIR_SEP "test_cfc$(OBJ_EXT)");
 
-    chaz_MakeFile_add_var(makefile, "CFC_OBJS", "cfc$(OBJ_EXT)");
+    scratch = chaz_Util_join("", "t", DIR_SEP, "test_cfc", obj_ext, NULL);
+    chaz_MakeVar_append(sfc.test_cfc_objs, scratch);
+    free(scratch);
+
+    scratch = chaz_Util_join("", "cfc", obj_ext, NULL);
+    chaz_MakeFile_add_var(makefile, "CFC_OBJS", scratch);
+    free(scratch);
 
     /* Rules */
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/239afba4/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 7a8bc4c..60cd820 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -102,11 +102,10 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 static void
 S_source_file_callback(const char *dir, char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
+    const char *obj_ext       = chaz_CC_obj_ext();
     const char *json_parser_c = "Lucy" DIR_SEP "Util" DIR_SEP "Json" DIR_SEP
                                 "JsonParser.c";
     size_t file_len = strlen(file);
-    size_t obj_file_size;
-    const char *pattern;
     char *obj_file;
 
     if (strcmp(file, json_parser_c) == 0) { return; }
@@ -118,7 +117,7 @@ S_source_file_callback(const char *dir, char *file, void *context) {
     }
     file[file_len-2] = '\0';
 
-    obj_file = chaz_Util_join("", dir, DIR_SEP, file, "$(OBJ_EXT)", NULL);
+    obj_file = chaz_Util_join("", dir, DIR_SEP, file, obj_ext, NULL);
     chaz_MakeVar_append(sfc->var, obj_file);
     free(obj_file);
 }
@@ -178,11 +177,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
 
-    /* File extensions */
-
-    chaz_MakeFile_add_var(makefile, "EXE_EXT", exe_ext);
-    chaz_MakeFile_add_var(makefile, "OBJ_EXT", obj_ext);
-
     /* C compiler */
 
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
@@ -222,12 +216,14 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_Make_list_files(snowstop_dir, "c", S_source_file_callback, &sfc);
     chaz_Make_list_files(utf8proc_dir, "c", S_source_file_callback, &sfc);
 
-    scratch = chaz_Util_join("", json_parser, "$(OBJ_EXT)", NULL);
+    scratch = chaz_Util_join("", json_parser, obj_ext, NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
 
-    chaz_MakeVar_append(var, "autogen" DIR_SEP "source" DIR_SEP
-                        "parcel$(OBJ_EXT)");
+    scratch = chaz_Util_join("", "autogen", DIR_SEP, "source", DIR_SEP,
+                             "parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
 
     /* Rules */
 


[lucy-commits] [02/13] git commit: refs/heads/makefile-rework - Add version to filename of shared library

Posted by nw...@apache.org.
Add version to filename of shared library

Introduce a new Charmonizer class chaz_SharedLib to build various
filenames.


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

Branch: refs/heads/makefile-rework
Commit: c66d9664cc9bc76c4550cb3c267d79186b253a21
Parents: bec7902
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 13 20:23:34 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:53 2013 +0200

----------------------------------------------------------------------
 c/.gitignore                                     |    4 +-
 charmonizer/buildbin/meld.pl                     |    1 +
 charmonizer/src/Charmonizer/Core/CFlags.c        |   20 ++-
 charmonizer/src/Charmonizer/Core/CFlags.h        |   13 +-
 charmonizer/src/Charmonizer/Core/Compiler.c      |   15 --
 charmonizer/src/Charmonizer/Core/Compiler.h      |    3 -
 charmonizer/src/Charmonizer/Core/Make.c          |   27 ++--
 charmonizer/src/Charmonizer/Core/Make.h          |    7 +-
 charmonizer/src/Charmonizer/Core/SharedLibrary.c |  135 +++++++++++++++++
 charmonizer/src/Charmonizer/Core/SharedLibrary.h |   66 ++++++++
 charmonizer/src/Charmonizer/Probe/Floats.c       |    2 +-
 common/charmonizer.main                          |   33 +++--
 12 files changed, 266 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/c/.gitignore
----------------------------------------------------------------------
diff --git a/c/.gitignore b/c/.gitignore
index 51675ab..310bb6e 100644
--- a/c/.gitignore
+++ b/c/.gitignore
@@ -2,6 +2,6 @@
 /autogen/
 /charmonizer
 /charmony.h
-/liblucy.dylib
-/liblucy.so
+/liblucy.*.dylib
+/liblucy.so.*
 /t/test_lucy

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/buildbin/meld.pl
----------------------------------------------------------------------
diff --git a/charmonizer/buildbin/meld.pl b/charmonizer/buildbin/meld.pl
index 2c73591..a615331 100755
--- a/charmonizer/buildbin/meld.pl
+++ b/charmonizer/buildbin/meld.pl
@@ -67,6 +67,7 @@ if ( !@probes ) {
 }
 
 my @core = qw(
+    SharedLibrary
     CFlags
     Compiler
     ConfWriter

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/CFlags.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/CFlags.c b/charmonizer/src/Charmonizer/Core/CFlags.c
index 1651925..4642a99 100644
--- a/charmonizer/src/Charmonizer/Core/CFlags.c
+++ b/charmonizer/src/Charmonizer/Core/CFlags.c
@@ -16,9 +16,10 @@
 
 #include <string.h>
 #include <stdlib.h>
-#include "Charmonizer/Core/Flags.h"
+#include "Charmonizer/Core/CFlags.h"
 #include "Charmonizer/Core/Util.h"
 #include "Charmonizer/Core/OperatingSystem.h"
+#include "Charmonizer/Core/SharedLibrary.h"
 
 struct chaz_CFlags {
     int   style;
@@ -264,13 +265,26 @@ chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory) {
 }
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library) {
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib) {
+    char *filename;
+    if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
+        filename = chaz_SharedLib_implib_filename(lib);
+    }
+    else {
+        filename = chaz_SharedLib_filename(lib);
+    }
+    chaz_CFlags_append(flags, filename);
+    free(filename);
+}
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library) {
     char *string;
     if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
         string = chaz_Util_join("", library, ".lib", NULL);
     }
     else {
-        string = chaz_Util_join("", "-l ", library, NULL);
+        string = chaz_Util_join(" ", "-l", library, NULL);
     }
     chaz_CFlags_append(flags, string);
     free(string);

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/CFlags.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/CFlags.h b/charmonizer/src/Charmonizer/Core/CFlags.h
index 989518f..5f4151d 100644
--- a/charmonizer/src/Charmonizer/Core/CFlags.h
+++ b/charmonizer/src/Charmonizer/Core/CFlags.h
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/CFlags.h
  */
 
-#ifndef H_CHAZ_FLAGS
-#define H_CHAZ_FLAGS
+#ifndef H_CHAZ_CFLAGS
+#define H_CHAZ_CFLAGS
 
 #ifdef __cplusplus
 extern "C" {
@@ -83,7 +83,10 @@ void
 chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory);
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library);
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib);
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library);
 
 void
 chaz_CFlags_enable_code_coverage(chaz_CFlags *flags);
@@ -92,6 +95,6 @@ chaz_CFlags_enable_code_coverage(chaz_CFlags *flags);
 }
 #endif
 
-#endif /* H_CHAZ_FLAGS */
+#endif /* H_CHAZ_CFLAGS */
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/Compiler.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Compiler.c b/charmonizer/src/Charmonizer/Core/Compiler.c
index f2683b5..9dd4841 100644
--- a/charmonizer/src/Charmonizer/Core/Compiler.c
+++ b/charmonizer/src/Charmonizer/Core/Compiler.c
@@ -366,19 +366,4 @@ chaz_CC_link_command() {
     }
 }
 
-char*
-chaz_CC_shared_lib_file(const char *name) {
-    const char *prefix = "";
-    const char *shlib_ext = chaz_OS_shared_lib_ext();
-    if (!chaz_CC.intval__MSC_VER) {
-        if (chaz_OS_is_cygwin()) {
-            prefix = "cyg";
-        }
-        else {
-            prefix = "lib";
-        }
-    }
-    return chaz_Util_join("", prefix, name, shlib_ext, NULL);
-}
-
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/Compiler.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Compiler.h b/charmonizer/src/Charmonizer/Core/Compiler.h
index 1e7803f..820f84c 100644
--- a/charmonizer/src/Charmonizer/Core/Compiler.h
+++ b/charmonizer/src/Charmonizer/Core/Compiler.h
@@ -108,9 +108,6 @@ chaz_CC_msvc_version_num(void);
 const char*
 chaz_CC_link_command(void);
 
-char*
-chaz_CC_shared_lib_file(const char *name);
-
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index f114a37..410254e 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -321,7 +321,7 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
 }
 
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags) {
     int            cflags_style = chaz_CC_get_cflags_style();
     chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
@@ -329,37 +329,36 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
     const char    *link_flags_string = "";
     const char    *local_flags_string;
     chaz_MakeRule *rule;
-    char          *shared_lib;
+    char          *filename;
     char          *command;
 
-    shared_lib = chaz_CC_shared_lib_file(name);
-    rule = chaz_MakeFile_add_rule(makefile, shared_lib, sources);
+    filename = chaz_SharedLib_filename(lib);
+    rule = chaz_MakeFile_add_rule(makefile, filename, sources);
 
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
     chaz_CFlags_link_shared_library(local_flags);
-    chaz_CFlags_set_link_output(local_flags, shared_lib);
+    chaz_CFlags_set_link_output(local_flags, filename);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
                              local_flags_string, NULL);
     chaz_MakeRule_add_command(rule, command);
 
-    chaz_MakeRule_add_rm_command(makefile->clean, shared_lib);
+    chaz_MakeRule_add_rm_command(makefile->clean, filename);
 
     if (chaz_CC_msvc_version_num()) {
         /* Remove import library and export file under MSVC. */
-        char *filename;
-        filename = chaz_Util_join("", name, ".lib", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
-        filename = chaz_Util_join("", name, ".exp", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
+        char *lib_filename = chaz_SharedLib_implib_filename(lib);
+        char *exp_filename = chaz_SharedLib_export_filename(lib);
+        chaz_MakeRule_add_rm_command(makefile->clean, lib_filename);
+        chaz_MakeRule_add_rm_command(makefile->clean, exp_filename);
+        free(lib_filename);
+        free(exp_filename);
     }
 
     chaz_CFlags_destroy(local_flags);
-    free(shared_lib);
+    free(filename);
     free(command);
     return rule;
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/Make.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.h b/charmonizer/src/Charmonizer/Core/Make.h
index 8df49f6..8f2cbc1 100644
--- a/charmonizer/src/Charmonizer/Core/Make.h
+++ b/charmonizer/src/Charmonizer/Core/Make.h
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/Make.h
  */
 
 #ifndef H_CHAZ_MAKE
@@ -25,6 +25,7 @@ extern "C" {
 #endif
 
 #include "Charmonizer/Core/CFlags.h"
+#include "Charmonizer/Core/SharedLib.h"
 
 typedef struct chaz_MakeFile chaz_MakeFile;
 typedef struct chaz_MakeVar chaz_MakeVar;
@@ -141,12 +142,12 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
  * to the list of files to clean.
  *
  * @param makefile The makefile.
- * @param name The name of the shared library without prefix or extension.
+ * @param lib The shared library.
  * @param sources The list of source files.
  * @param link_flags Additional link flags.
  */
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags);
 
 /** Write the makefile to a file named 'Makefile' in the current directory.

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/SharedLibrary.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/SharedLibrary.c b/charmonizer/src/Charmonizer/Core/SharedLibrary.c
new file mode 100644
index 0000000..5c9d0e9
--- /dev/null
+++ b/charmonizer/src/Charmonizer/Core/SharedLibrary.c
@@ -0,0 +1,135 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "Charmonizer/Core/SharedLib.h"
+#include "Charmonizer/Core/Compiler.h"
+#include "Charmonizer/Core/Util.h"
+#include "Charmonizer/Core/OperatingSystem.h"
+
+struct chaz_SharedLib {
+    char *name;
+    char *version;
+    char *major_version;
+};
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext);
+
+static const char*
+S_get_prefix(void);
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version) {
+    chaz_SharedLib *lib = (chaz_SharedLib*)malloc(sizeof(chaz_SharedLib));
+    lib->name          = chaz_Util_strdup(name);
+    lib->version       = chaz_Util_strdup(version);
+    lib->major_version = chaz_Util_strdup(major_version);
+    return lib;
+}
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *lib) {
+    free(lib->name);
+    free(lib->version);
+    free(lib->major_version);
+    free(lib);
+}
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib) {
+    return lib->name;
+}
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib) {
+    return lib->version;
+}
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib) {
+    return lib->major_version;
+}
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return S_build_filename(lib, lib->major_version, shlib_ext);
+    }
+    else {
+        return S_build_filename(lib, lib->version, shlib_ext);
+    }
+}
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return S_build_filename(lib, lib->major_version, shlib_ext);
+}
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return chaz_Util_join("", prefix, lib->name, shlib_ext, NULL);
+}
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".lib");
+}
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".exp");
+}
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL);
+    }
+    else if (strcmp(shlib_ext, ".dylib") == 0) {
+        return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL);
+    }
+    else {
+        return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL);
+    }
+}
+
+static const char*
+S_get_prefix() {
+    if (chaz_CC_msvc_version_num()) {
+        return "";
+    }
+    else if (chaz_OS_is_cygwin()) {
+        return "cyg";
+    }
+    else {
+        return "lib";
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Core/SharedLibrary.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/SharedLibrary.h b/charmonizer/src/Charmonizer/Core/SharedLibrary.h
new file mode 100644
index 0000000..723f407
--- /dev/null
+++ b/charmonizer/src/Charmonizer/Core/SharedLibrary.h
@@ -0,0 +1,66 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Charmonizer/Core/SharedLibrary.h
+ */
+
+#ifndef H_CHAZ_SHARED_LIB
+#define H_CHAZ_SHARED_LIB
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct chaz_SharedLib chaz_SharedLib;
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version);
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *flags);
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CHAZ_SHARED_LIB */
+
+

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/charmonizer/src/Charmonizer/Probe/Floats.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Probe/Floats.c b/charmonizer/src/Charmonizer/Probe/Floats.c
index fc31386..b78ec00 100644
--- a/charmonizer/src/Charmonizer/Probe/Floats.c
+++ b/charmonizer/src/Charmonizer/Probe/Floats.c
@@ -67,7 +67,7 @@ chaz_Floats_math_library(void) {
         return NULL;
     }
 
-    chaz_CFlags_add_library(temp_cflags, "m");
+    chaz_CFlags_add_external_library(temp_cflags, "m");
     output = chaz_CC_capture_output(sqrt_code, &output_len);
     chaz_CFlags_clear(temp_cflags);
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/c66d9664/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 0460724..0642089 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -49,6 +49,9 @@ typedef struct SourceFileContext {
     const char *dir;
 } SourceFileContext;
 
+static const char lucy_version[]       = "0.3.0";
+static const char lucy_major_version[] = "0.3";
+
 static void
 S_add_compiler_flags(struct chaz_CLIArgs *args) {
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
@@ -147,8 +150,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     const char *json_parser_c = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
                                 DIR_SEP "Json" DIR_SEP "JsonParser.c";
 
-    char *scratch;
-
     chaz_MakeFile *makefile;
     chaz_MakeVar  *var;
     chaz_MakeRule *rule;
@@ -161,9 +162,12 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_CFlags *lemon_cflags;
     chaz_CFlags *link_flags;
     chaz_CFlags *test_cflags;
-    const char  *math_library;
-    const char  *test_command;
-    char        *shared_lib;
+
+    chaz_SharedLib *lib;
+    const char     *math_library;
+    const char     *test_command;
+    char           *lib_filename;
+    char           *scratch;
 
     printf("Creating Makefile...\n");
 
@@ -282,8 +286,9 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     /* Rules */
 
-    shared_lib = chaz_CC_shared_lib_file("lucy");
-    chaz_MakeFile_add_rule(makefile, "all", shared_lib);
+    lib = chaz_SharedLib_new("lucy", lucy_version, lucy_major_version);
+    lib_filename = chaz_SharedLib_filename(lib);
+    chaz_MakeFile_add_rule(makefile, "all", lib_filename);
 
     lemon_cflags = chaz_CFlags_new(cflags_style);
     S_add_common_cflags(lemon_cflags);
@@ -325,15 +330,15 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     }
     math_library = chaz_Floats_math_library();
     if (math_library) {
-        chaz_CFlags_add_library(link_flags, math_library);
+        chaz_CFlags_add_external_library(link_flags, math_library);
     }
     if (chaz_HeadCheck_check_header("pcre.h")) {
-        chaz_CFlags_add_library(link_flags, "pcre");
+        chaz_CFlags_add_external_library(link_flags, "pcre");
     }
     if (args->code_coverage) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
-    chaz_MakeFile_add_shared_lib(makefile, "lucy", "$(LUCY_OBJS)", link_flags);
+    chaz_MakeFile_add_shared_lib(makefile, lib, "$(LUCY_OBJS)", link_flags);
     chaz_CFlags_destroy(link_flags);
 
     test_cflags = chaz_CFlags_new(cflags_style);
@@ -341,12 +346,11 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_CFlags_add_include_dir(test_cflags, ".");
     chaz_CFlags_add_include_dir(test_cflags,
                                 "$(AUTOGEN_DIR)" DIR_SEP "include");
-    chaz_CFlags_add_library_path(test_cflags, ".");
-    chaz_CFlags_add_library(test_cflags, "lucy");
+    chaz_CFlags_add_library(link_flags, lib);
     rule = chaz_MakeFile_add_compiled_exe(makefile, "$(TEST_LUCY_EXE)",
                                           "t" DIR_SEP "test_lucy.c",
                                           test_cflags);
-    chaz_MakeRule_add_prereq(rule, shared_lib);
+    chaz_MakeRule_add_prereq(rule, lib_filename);
     chaz_CFlags_destroy(test_cflags);
 
     rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_LUCY_EXE)");
@@ -409,7 +413,8 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_write(makefile);
 
     chaz_MakeFile_destroy(makefile);
-    free(shared_lib);
+    chaz_SharedLib_destroy(lib);
+    free(lib_filename);
 }
 
 int main(int argc, const char **argv) {


[lucy-commits] [03/13] git commit: refs/heads/makefile-rework - Move detection of directory separator to chaz_OS

Posted by nw...@apache.org.
Move detection of directory separator to chaz_OS


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

Branch: refs/heads/makefile-rework
Commit: 175f115353a6ef70449c95fd3fd76529e3f41598
Parents: 893184b
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 14 21:30:52 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:53 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/OperatingSystem.c |   10 +++++-
 charmonizer/src/Charmonizer/Core/OperatingSystem.h |    5 +++
 charmonizer/src/Charmonizer/Probe/DirManip.c       |   26 +--------------
 3 files changed, 15 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/175f1153/charmonizer/src/Charmonizer/Core/OperatingSystem.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/OperatingSystem.c b/charmonizer/src/Charmonizer/Core/OperatingSystem.c
index a8f933b..31db30c 100644
--- a/charmonizer/src/Charmonizer/Core/OperatingSystem.c
+++ b/charmonizer/src/Charmonizer/Core/OperatingSystem.c
@@ -30,11 +30,12 @@
 static struct {
     char name[CHAZ_OS_NAME_MAX+1];
     char dev_null[20];
+    char dir_sep[2];
     char exe_ext[5];
     char shared_lib_ext[7];
     char local_command_start[3];
     int  shell_type;
-} chaz_OS = { "", "", "", "", "", 0 };
+} chaz_OS = { "", "", "", "", "", "", 0 };
 
 void
 chaz_OS_init(void) {
@@ -66,6 +67,7 @@ chaz_OS_init(void) {
         free(uname);
 
         strcpy(chaz_OS.dev_null, "/dev/null");
+        strcpy(chaz_OS.dir_sep, "/");
         strcpy(chaz_OS.exe_ext, "");
         if (memcmp(chaz_OS.name, "darwin", 6) == 0) {
             strcpy(chaz_OS.shared_lib_ext, ".dylib");
@@ -81,6 +83,7 @@ chaz_OS_init(void) {
     else if (chaz_Util_can_open_file("nul")) {
         strcpy(chaz_OS.name, "windows");
         strcpy(chaz_OS.dev_null, "nul");
+        strcpy(chaz_OS.dir_sep, "\\");
         strcpy(chaz_OS.exe_ext, ".exe");
         strcpy(chaz_OS.shared_lib_ext, ".dll");
         strcpy(chaz_OS.local_command_start, ".\\");
@@ -122,6 +125,11 @@ chaz_OS_dev_null(void) {
     return chaz_OS.dev_null;
 }
 
+const char*
+chaz_OS_dir_sep(void) {
+    return chaz_OS.dir_sep;
+}
+
 int
 chaz_OS_shell_type(void) {
     return chaz_OS.shell_type;

http://git-wip-us.apache.org/repos/asf/lucy/blob/175f1153/charmonizer/src/Charmonizer/Core/OperatingSystem.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/OperatingSystem.h b/charmonizer/src/Charmonizer/Core/OperatingSystem.h
index c335cf3..84a7ac0 100644
--- a/charmonizer/src/Charmonizer/Core/OperatingSystem.h
+++ b/charmonizer/src/Charmonizer/Core/OperatingSystem.h
@@ -94,6 +94,11 @@ chaz_OS_shared_lib_ext(void);
 const char*
 chaz_OS_dev_null(void);
 
+/* Return the directory separator on this system.
+ */
+const char*
+chaz_OS_dir_sep(void);
+
 /* Return the shell type of this system.
  */
 int

http://git-wip-us.apache.org/repos/asf/lucy/blob/175f1153/charmonizer/src/Charmonizer/Probe/DirManip.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Probe/DirManip.c b/charmonizer/src/Charmonizer/Probe/DirManip.c
index 8664ed6..47f68df 100644
--- a/charmonizer/src/Charmonizer/Probe/DirManip.c
+++ b/charmonizer/src/Charmonizer/Probe/DirManip.c
@@ -117,23 +117,9 @@ chaz_DirManip_try_rmdir(void) {
     if (chaz_DirManip_compile_rmdir("direct.h"))   { return; }
 }
 
-static int
-chaz_DirManip_is_cygwin(void) {
-    static int is_cygwin = -1;
-    static const char cygwin_code[] =
-        CHAZ_QUOTE(#ifndef __CYGWIN__            )
-        CHAZ_QUOTE(  #error "Not Cygwin"         )
-        CHAZ_QUOTE(#endif                        )
-        CHAZ_QUOTE(int main() { return 0; }      );
-    if (is_cygwin == -1) {
-        is_cygwin = chaz_CC_test_compile(cygwin_code);
-    }
-    return is_cygwin;
-}
-
 void
 chaz_DirManip_run(void) {
-    char dir_sep[3];
+    const char *dir_sep = chaz_OS_dir_sep();
     int remove_zaps_dirs = false;
     int has_dirent_h = chaz_HeadCheck_check_header("dirent.h");
     int has_direct_h = chaz_HeadCheck_check_header("direct.h");
@@ -191,16 +177,6 @@ chaz_DirManip_run(void) {
         chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "1");
     }
 
-    if (chaz_DirManip_is_cygwin()) {
-        strcpy(dir_sep, "/");
-    }
-    else if (chaz_HeadCheck_check_header("windows.h")) {
-        strcpy(dir_sep, "\\\\");
-    }
-    else {
-        strcpy(dir_sep, "/");
-    }
-
     {
         char scratch[5];
         sprintf(scratch, "\"%s\"", dir_sep);


[lucy-commits] [11/13] git commit: refs/heads/makefile-rework - Remove ineffective const

Posted by nw...@apache.org.
Remove ineffective const

Discovered by -Wextra.


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

Branch: refs/heads/makefile-rework
Commit: 86e34dec53859257c2feab6c34f4c75012319f10
Parents: 3b36502
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed May 15 19:21:48 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:23:05 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Probe/LargeFiles.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/86e34dec/charmonizer/src/Charmonizer/Probe/LargeFiles.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Probe/LargeFiles.c b/charmonizer/src/Charmonizer/Probe/LargeFiles.c
index c0e51b8..c394245 100644
--- a/charmonizer/src/Charmonizer/Probe/LargeFiles.c
+++ b/charmonizer/src/Charmonizer/Probe/LargeFiles.c
@@ -47,7 +47,7 @@ typedef struct chaz_LargeFiles_unbuff_combo {
 
 /* Check for a 64-bit file pointer type.
  */
-static const int
+static int
 chaz_LargeFiles_probe_off64(void);
 
 /* Check what name 64-bit ftell, fseek go by.
@@ -114,7 +114,7 @@ chaz_LargeFiles_run(void) {
     chaz_ConfWriter_end_module();
 }
 
-static const int
+static int
 chaz_LargeFiles_probe_off64(void) {
     static const char off64_code[] =
         CHAZ_QUOTE(  %s                                        )


[lucy-commits] [04/13] git commit: refs/heads/makefile-rework - Convenience function to create new CFlags object

Posted by nw...@apache.org.
Convenience function to create new CFlags object


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

Branch: refs/heads/makefile-rework
Commit: 893184bb371e145f269db257b88e733d9473fb19
Parents: 8c0f0a1
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 14 20:19:34 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:53 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/Compiler.c |   10 +++++-----
 charmonizer/src/Charmonizer/Core/Compiler.h |   10 +++++-----
 charmonizer/src/Charmonizer/Core/Make.c     |    9 +++------
 clownfish/compiler/common/charmonizer.main  |    7 +++----
 common/charmonizer.main                     |    9 ++++-----
 5 files changed, 20 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/893184bb/charmonizer/src/Charmonizer/Core/Compiler.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Compiler.c b/charmonizer/src/Charmonizer/Core/Compiler.c
index 9dd4841..2ad4be8 100644
--- a/charmonizer/src/Charmonizer/Core/Compiler.c
+++ b/charmonizer/src/Charmonizer/Core/Compiler.c
@@ -319,11 +319,6 @@ chaz_CC_get_cflags(void) {
     return chaz_CC.cflags;
 }
 
-int
-chaz_CC_get_cflags_style(void) {
-    return chaz_CC.cflags_style;
-}
-
 chaz_CFlags*
 chaz_CC_get_extra_cflags(void) {
     return chaz_CC.extra_cflags;
@@ -334,6 +329,11 @@ chaz_CC_get_temp_cflags(void) {
     return chaz_CC.temp_cflags;
 }
 
+chaz_CFlags*
+chaz_CC_new_cflags(void) {
+    return chaz_CFlags_new(chaz_CC.cflags_style);
+}
+
 const char*
 chaz_CC_obj_ext(void) {
     return chaz_CC.obj_ext;

http://git-wip-us.apache.org/repos/asf/lucy/blob/893184bb/charmonizer/src/Charmonizer/Core/Compiler.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Compiler.h b/charmonizer/src/Charmonizer/Core/Compiler.h
index 820f84c..51ec01b 100644
--- a/charmonizer/src/Charmonizer/Core/Compiler.h
+++ b/charmonizer/src/Charmonizer/Core/Compiler.h
@@ -76,11 +76,6 @@ chaz_CC_get_cc(void);
 const char*
 chaz_CC_get_cflags(void);
 
-/* Accessor for `cflags_style`.
- */
-int
-chaz_CC_get_cflags_style(void);
-
 /* Accessor for `extra_cflags`.
  */
 chaz_CFlags*
@@ -91,6 +86,11 @@ chaz_CC_get_extra_cflags(void);
 chaz_CFlags*
 chaz_CC_get_temp_cflags(void);
 
+/* Return a new CFlags object.
+ */
+chaz_CFlags*
+chaz_CC_new_cflags(void);
+
 /* Return the extension for a compiled object.
  */
 const char*

http://git-wip-us.apache.org/repos/asf/lucy/blob/893184bb/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index 1df757a..d57034e 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -264,8 +264,7 @@ chaz_MakeFile_distclean_rule(chaz_MakeFile *makefile) {
 chaz_MakeRule*
 chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
                       const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
@@ -293,8 +292,7 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
 chaz_MakeRule*
 chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
                                const char *sources, chaz_CFlags *cflags) {
-    int            cflags_style  = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags   = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags   = chaz_CC_new_cflags();
     const char    *cc            = chaz_CC_get_cc();
     const char    *cflags_string = "";
     const char    *local_flags_string;
@@ -323,8 +321,7 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
 chaz_MakeRule*
 chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;

http://git-wip-us.apache.org/repos/asf/lucy/blob/893184bb/clownfish/compiler/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.main b/clownfish/compiler/common/charmonizer.main
index 55f9139..df03a70 100644
--- a/clownfish/compiler/common/charmonizer.main
+++ b/clownfish/compiler/common/charmonizer.main
@@ -129,7 +129,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule *rule;
     chaz_MakeRule *clean_rule;
 
-    int          cflags_style = chaz_CC_get_cflags_style();
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
     chaz_CFlags *link_flags;
@@ -161,7 +160,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
 
-    makefile_cflags = chaz_CFlags_new(cflags_style);
+    makefile_cflags = chaz_CC_new_cflags();
     S_add_common_cflags(makefile_cflags);
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
@@ -203,7 +202,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)");
 
-    lemon_cflags = chaz_CFlags_new(cflags_style);
+    lemon_cflags = chaz_CC_new_cflags();
     S_add_common_cflags(lemon_cflags);
     chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
                                    "$(LEMON_DIR)" DIR_SEP "lemon.c",
@@ -220,7 +219,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_rule(makefile, "$(COMMON_OBJS)", parse_header_c);
 
-    link_flags = chaz_CFlags_new(cflags_style);
+    link_flags = chaz_CC_new_cflags();
     if (chaz_CC_msvc_version_num()) {
         chaz_CFlags_append(link_flags, "/nologo");
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/893184bb/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 0642089..e8fc434 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -156,7 +156,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule *clean_rule;
     chaz_MakeRule *distclean_rule;
 
-    int          cflags_style = chaz_CC_get_cflags_style();
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
     chaz_CFlags *lemon_cflags;
@@ -206,7 +205,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
 
-    makefile_cflags = chaz_CFlags_new(cflags_style);
+    makefile_cflags = chaz_CC_new_cflags();
     S_add_common_cflags(makefile_cflags);
 
     chaz_CFlags_disable_strict_aliasing(makefile_cflags);
@@ -290,7 +289,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     lib_filename = chaz_SharedLib_filename(lib);
     chaz_MakeFile_add_rule(makefile, "all", lib_filename);
 
-    lemon_cflags = chaz_CFlags_new(cflags_style);
+    lemon_cflags = chaz_CC_new_cflags();
     S_add_common_cflags(lemon_cflags);
     chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
                                    "$(LEMON_DIR)" DIR_SEP "lemon.c",
@@ -324,7 +323,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule_add_prereq(rule, json_parser_c);
     chaz_MakeRule_add_prereq(rule, "$(AUTOGEN_DIR)");
 
-    link_flags = chaz_CFlags_new(cflags_style);
+    link_flags = chaz_CC_new_cflags();
     if (chaz_CC_msvc_version_num()) {
         chaz_CFlags_append(link_flags, "/nologo");
     }
@@ -341,7 +340,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_add_shared_lib(makefile, lib, "$(LUCY_OBJS)", link_flags);
     chaz_CFlags_destroy(link_flags);
 
-    test_cflags = chaz_CFlags_new(cflags_style);
+    test_cflags = chaz_CC_new_cflags();
     S_add_common_cflags(test_cflags);
     chaz_CFlags_add_include_dir(test_cflags, ".");
     chaz_CFlags_add_include_dir(test_cflags,


[lucy-commits] [06/13] git commit: refs/heads/makefile-rework - Functions to create lemon rules in chaz_MakeFile

Posted by nw...@apache.org.
Functions to create lemon rules in chaz_MakeFile


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

Branch: refs/heads/makefile-rework
Commit: 1ad02f6e3e11c21d65297f57f8a136675440362b
Parents: ff53edf
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Tue May 14 21:31:57 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:54 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/Make.c    |   44 +++++++++++++++++++++
 charmonizer/src/Charmonizer/Core/Make.h    |   17 ++++++++
 clownfish/compiler/common/charmonizer.main |   42 +++++++-------------
 common/charmonizer.main                    |   47 +++++++---------------
 4 files changed, 90 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/1ad02f6e/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index 22d4764..ef7a2ee 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -370,6 +370,50 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
     return rule;
 }
 
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir) {
+    chaz_CFlags   *cflags = chaz_CC_new_cflags();
+    chaz_MakeRule *rule;
+    const char *dir_sep = chaz_OS_dir_sep();
+    const char *exe_ext = chaz_OS_exe_ext();
+    char *lemon_exe = chaz_Util_join("", dir, dir_sep, "lemon", exe_ext, NULL);
+    char *lemon_c   = chaz_Util_join(dir_sep, dir, "lemon.c", NULL);
+
+    chaz_CFlags_enable_optimization(cflags);
+    chaz_MakeFile_add_var(makefile, "LEMON_EXE", lemon_exe);
+    rule = chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)", lemon_c,
+                                          cflags);
+
+    chaz_CFlags_destroy(cflags);
+    free(lemon_c);
+    free(lemon_exe);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name) {
+    char *c_file  = chaz_Util_join(".", base_name, "c", NULL);
+    char *h_file  = chaz_Util_join(".", base_name, "h", NULL);
+    char *y_file  = chaz_Util_join(".", base_name, "y", NULL);
+    char *command = chaz_Util_join(" ", "$(LEMON_EXE) -q", y_file, NULL);
+
+    chaz_MakeRule *rule = chaz_MakeFile_add_rule(makefile, c_file, y_file);
+    chaz_MakeRule *clean_rule = chaz_MakeFile_clean_rule(makefile);
+
+    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
+    chaz_MakeRule_add_command(rule, command);
+
+    chaz_MakeRule_add_rm_command(clean_rule, h_file);
+    chaz_MakeRule_add_rm_command(clean_rule, c_file);
+
+    free(c_file);
+    free(h_file);
+    free(y_file);
+    free(command);
+    return rule;
+}
+
 void
 chaz_MakeFile_write(chaz_MakeFile *makefile) {
     FILE   *out;

http://git-wip-us.apache.org/repos/asf/lucy/blob/1ad02f6e/charmonizer/src/Charmonizer/Core/Make.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.h b/charmonizer/src/Charmonizer/Core/Make.h
index 8f2cbc1..0ba87b0 100644
--- a/charmonizer/src/Charmonizer/Core/Make.h
+++ b/charmonizer/src/Charmonizer/Core/Make.h
@@ -150,6 +150,23 @@ chaz_MakeRule*
 chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags);
 
+/** Add a rule to build the lemon parser generator.
+ *
+ * @param makefile The makefile.
+ * @param dir The lemon directory.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir);
+
+/** Add a rule for a lemon grammar.
+ *
+ * @param makefile The makefile.
+ * @param base_name The filename of the grammar without extension.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name);
+
 /** Write the makefile to a file named 'Makefile' in the current directory.
  *
  * @param makefile The makefile.

http://git-wip-us.apache.org/repos/asf/lucy/blob/1ad02f6e/clownfish/compiler/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.main b/clownfish/compiler/common/charmonizer.main
index fd713f3..b79f461 100644
--- a/clownfish/compiler/common/charmonizer.main
+++ b/clownfish/compiler/common/charmonizer.main
@@ -109,9 +109,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     const char *exe_ext  = chaz_OS_exe_ext();
     const char *obj_ext  = chaz_CC_obj_ext();
 
-    const char *parse_header_y = "$(SRC_DIR)" DIR_SEP "CFCParseHeader.y";
-    const char *parse_header_h = "$(SRC_DIR)" DIR_SEP "CFCParseHeader.h";
-    const char *parse_header_c = "$(SRC_DIR)" DIR_SEP "CFCParseHeader.c";
+    const char *parse_header = "$(SRC_DIR)" DIR_SEP "CFCParseHeader";
 
     char *src_dir;
     char *scratch;
@@ -124,7 +122,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
     chaz_CFlags *link_flags;
-    chaz_CFlags *lemon_cflags;
 
     printf("Creating Makefile...\n");
 
@@ -139,9 +136,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_add_var(makefile, "SRC_DIR", src_dir);
     chaz_MakeFile_add_var(makefile, "INCLUDE_DIR",
                           "$(BASE_DIR)" DIR_SEP "include");
-    chaz_MakeFile_add_var(makefile, "LEMON_DIR",
-                          "$(BASE_DIR)" DIR_SEP ".." DIR_SEP ".." DIR_SEP
-                          "lemon");
 
     /* File extensions */
 
@@ -176,16 +170,15 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_Make_list_files(src_dir, "c", S_source_file_callback, &sfc);
 
-    chaz_MakeVar_append(sfc.common_objs,
-                        "$(SRC_DIR)" DIR_SEP "CFCParseHeader$(OBJ_EXT)");
+    scratch = chaz_Util_join("", parse_header, "$(OBJ_EXT)", NULL);
+    chaz_MakeVar_append(sfc.common_objs, scratch);
+    free(scratch);
     chaz_MakeVar_append(sfc.test_cfc_objs, "t" DIR_SEP "test_cfc$(OBJ_EXT)");
 
     chaz_MakeFile_add_var(makefile, "CFC_OBJS", "cfc$(OBJ_EXT)");
 
     /* Executables */
 
-    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)");
@@ -194,22 +187,17 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)");
 
-    lemon_cflags = chaz_CC_new_cflags();
-    chaz_CFlags_enable_optimization(lemon_cflags);
-    chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
-                                   "$(LEMON_DIR)" DIR_SEP "lemon.c",
-                                   lemon_cflags);
-    chaz_CFlags_destroy(lemon_cflags);
-
-    rule = chaz_MakeFile_add_rule(makefile, parse_header_c, NULL);
-    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
-    chaz_MakeRule_add_prereq(rule, parse_header_y);
-    scratch = (char*)malloc(strlen(parse_header_y) + 20);
-    sprintf(scratch, "$(LEMON_EXE) -q %s", parse_header_y);
-    chaz_MakeRule_add_command(rule, scratch);
-    free(scratch);
+    chaz_MakeFile_add_lemon_exe(makefile, "$(BASE_DIR)" DIR_SEP ".." DIR_SEP
+                                ".." DIR_SEP "lemon");
+    chaz_MakeFile_add_lemon_grammar(makefile, parse_header);
 
-    chaz_MakeFile_add_rule(makefile, "$(COMMON_OBJS)", parse_header_c);
+    /*
+     * The dependency is actually on CFCParseHeader.h, but make doesn't cope
+     * well with multiple output files.
+     */
+    scratch = chaz_Util_join(".", parse_header, "c", NULL);
+    chaz_MakeFile_add_rule(makefile, "$(COMMON_OBJS)", scratch);
+    free(scratch);
 
     link_flags = chaz_CC_new_cflags();
     if (chaz_CC_msvc_version_num()) {
@@ -254,8 +242,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule_add_rm_command(clean_rule, "$(COMMON_OBJS)");
     chaz_MakeRule_add_rm_command(clean_rule, "$(CFC_OBJS)");
     chaz_MakeRule_add_rm_command(clean_rule, "$(TEST_CFC_OBJS)");
-    chaz_MakeRule_add_rm_command(clean_rule, parse_header_h);
-    chaz_MakeRule_add_rm_command(clean_rule, parse_header_c);
 
     if (args->code_coverage) {
         chaz_MakeRule_add_rm_command(clean_rule, "cfc.info");

http://git-wip-us.apache.org/repos/asf/lucy/blob/1ad02f6e/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index e595057..00a5d1f 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -135,12 +135,8 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     const char *exe_ext  = chaz_OS_exe_ext();
     const char *obj_ext  = chaz_CC_obj_ext();
 
-    const char *json_parser_y = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                                DIR_SEP "Json" DIR_SEP "JsonParser.y";
-    const char *json_parser_h = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                                DIR_SEP "Json" DIR_SEP "JsonParser.h";
-    const char *json_parser_c = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                                DIR_SEP "Json" DIR_SEP "JsonParser.c";
+    const char *json_parser = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
+                              DIR_SEP "Json" DIR_SEP "JsonParser";
 
     chaz_MakeFile *makefile;
     chaz_MakeVar  *var;
@@ -150,7 +146,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
-    chaz_CFlags *lemon_cflags;
     chaz_CFlags *link_flags;
     chaz_CFlags *test_cflags;
 
@@ -173,8 +168,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
                           "$(BASE_DIR)" DIR_SEP "core");
     chaz_MakeFile_add_var(makefile, "MODULES_DIR",
                           "$(BASE_DIR)" DIR_SEP "modules");
-    chaz_MakeFile_add_var(makefile, "LEMON_DIR",
-                          "$(BASE_DIR)" DIR_SEP "lemon");
     chaz_MakeFile_add_var(makefile, "CFC_DIR",
                           "$(BASE_DIR)" DIR_SEP "clownfish" DIR_SEP "compiler"
                           DIR_SEP "c");
@@ -239,8 +232,9 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     sfc.dir = "$(CORE_DIR)";
     chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
     free(scratch);
-    chaz_MakeVar_append(var, "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                        DIR_SEP "Json" DIR_SEP "JsonParser$(OBJ_EXT)");
+    scratch = chaz_Util_join("", json_parser, "$(OBJ_EXT)", NULL);
+    chaz_MakeVar_append(var, scratch);
+    free(scratch);
 
     scratch = (char*)malloc(strlen(base_dir) + 80);
     sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "analysis" DIR_SEP
@@ -268,8 +262,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     /* Executables */
 
-    chaz_MakeFile_add_var(makefile, "LEMON_EXE",
-                          "$(LEMON_DIR)" DIR_SEP "lemon$(EXE_EXT)");
     chaz_MakeFile_add_var(makefile, "CFC_EXE",
                           "$(CFC_DIR)" DIR_SEP "cfc$(EXE_EXT)");
     chaz_MakeFile_add_var(makefile, "TEST_LUCY_EXE",
@@ -281,12 +273,8 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     lib_filename = chaz_SharedLib_filename(lib);
     chaz_MakeFile_add_rule(makefile, "all", lib_filename);
 
-    lemon_cflags = chaz_CC_new_cflags();
-    chaz_CFlags_enable_optimization(lemon_cflags);
-    chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
-                                   "$(LEMON_DIR)" DIR_SEP "lemon.c",
-                                   lemon_cflags);
-    chaz_CFlags_destroy(lemon_cflags);
+    chaz_MakeFile_add_lemon_exe(makefile, "$(BASE_DIR)" DIR_SEP "lemon");
+    chaz_MakeFile_add_lemon_grammar(makefile, json_parser);
 
     /*
      * CFC also builds LEMON_EXE, so it might be built twice at the same time
@@ -299,21 +287,18 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule_add_command(rule, "$(CFC_EXE) --source=$(CORE_DIR) "
                               "--dest=$(AUTOGEN_DIR) --header=cfc_header");
 
-    rule = chaz_MakeFile_add_rule(makefile, json_parser_c, NULL);
-    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
-    chaz_MakeRule_add_prereq(rule, json_parser_y);
-    scratch = (char*)malloc(strlen(json_parser_y) + 20);
-    sprintf(scratch, "$(LEMON_EXE) -q %s", json_parser_y);
-    chaz_MakeRule_add_command(rule, scratch);
-    free(scratch);
-
     /* Needed for parallel builds. */
     rule = chaz_MakeFile_add_rule(makefile, "$(AUTOGEN_DIR)" DIR_SEP "source"
                                   DIR_SEP "parcel.c", "$(AUTOGEN_DIR)");
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", NULL);
-    chaz_MakeRule_add_prereq(rule, json_parser_c);
-    chaz_MakeRule_add_prereq(rule, "$(AUTOGEN_DIR)");
+    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "$(AUTOGEN_DIR)");
+    /*
+     * 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);
+    chaz_MakeRule_add_prereq(rule, scratch);
+    free(scratch);
 
     link_flags = chaz_CC_new_cflags();
     if (chaz_CC_msvc_version_num()) {
@@ -387,8 +372,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
         chaz_MakeRule_add_rm_command(clean_rule, "$(LUCY_OBJS)");
     }
 
-    chaz_MakeRule_add_rm_command(clean_rule, json_parser_h);
-    chaz_MakeRule_add_rm_command(clean_rule, json_parser_c);
     chaz_MakeRule_add_recursive_rm_command(clean_rule, "$(AUTOGEN_DIR)");
 
     if (args->code_coverage) {


[lucy-commits] [07/13] git commit: refs/heads/makefile-rework - Rework Makefile paths

Posted by nw...@apache.org.
Rework Makefile paths

Build paths in C and don't use Makefile variables.


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

Branch: refs/heads/makefile-rework
Commit: 8aacc868272e2a35a06b8d532509e8bd27b3bd74
Parents: 1ad02f6
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed May 15 00:00:28 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:54 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/Make.c    |    2 +-
 charmonizer/src/Charmonizer/Core/Make.h    |    3 +-
 clownfish/compiler/common/charmonizer.main |   60 ++++-----
 common/charmonizer.main                    |  167 ++++++++++-------------
 4 files changed, 102 insertions(+), 130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/8aacc868/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index ef7a2ee..b3aba56 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -713,7 +713,7 @@ chaz_Make_list_files(const char *dir, const char *ext,
                           file);
         }
 
-        callback(file + prefix_len, context);
+        callback(dir, file + prefix_len, context);
     }
 
     free(prefix);

http://git-wip-us.apache.org/repos/asf/lucy/blob/8aacc868/charmonizer/src/Charmonizer/Core/Make.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.h b/charmonizer/src/Charmonizer/Core/Make.h
index 0ba87b0..7139dd4 100644
--- a/charmonizer/src/Charmonizer/Core/Make.h
+++ b/charmonizer/src/Charmonizer/Core/Make.h
@@ -31,7 +31,8 @@ typedef struct chaz_MakeFile chaz_MakeFile;
 typedef struct chaz_MakeVar chaz_MakeVar;
 typedef struct chaz_MakeRule chaz_MakeRule;
 
-typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
+typedef void (*chaz_Make_list_files_callback_t)(const char *dir, char *file,
+                                                void *context);
 
 /** Initialize the environment.
  */

http://git-wip-us.apache.org/repos/asf/lucy/blob/8aacc868/clownfish/compiler/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/clownfish/compiler/common/charmonizer.main b/clownfish/compiler/common/charmonizer.main
index b79f461..ff38656 100644
--- a/clownfish/compiler/common/charmonizer.main
+++ b/clownfish/compiler/common/charmonizer.main
@@ -70,7 +70,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 }
 
 static void
-S_source_file_callback(char *file, void *context) {
+S_source_file_callback(const char *dir, char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
     size_t file_len = strlen(file);
     size_t obj_file_size;
@@ -86,11 +86,7 @@ S_source_file_callback(char *file, void *context) {
     }
     file[file_len-2] = '\0';
 
-    pattern = "$(SRC_DIR)" DIR_SEP "%s$(OBJ_EXT)";
-    obj_file_size = strlen(pattern) + file_len + 10;
-    obj_file = (char*)malloc(obj_file_size);
-    sprintf(obj_file, pattern, file);
-
+    obj_file = chaz_Util_join("", dir, DIR_SEP, file, "$(OBJ_EXT)", NULL);
     if (strlen(file) >= 7 && memcmp(file, "CFCTest", 7) == 0) {
         chaz_MakeVar_append(sfc->test_cfc_objs, obj_file);
     }
@@ -109,9 +105,16 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     const char *exe_ext  = chaz_OS_exe_ext();
     const char *obj_ext  = chaz_CC_obj_ext();
 
-    const char *parse_header = "$(SRC_DIR)" DIR_SEP "CFCParseHeader";
+    char *lemon_dir    = chaz_Util_join(DIR_SEP, base_dir, "..", "..", "lemon",
+                                        NULL);
+    char *src_dir      = chaz_Util_join(DIR_SEP, base_dir, "src", NULL);
+    char *include_dir  = chaz_Util_join(DIR_SEP, base_dir, "include", NULL);
+    char *parse_header = chaz_Util_join(DIR_SEP, src_dir, "CFCParseHeader",
+                                        NULL);
+    char *cfc_exe      = chaz_Util_join("", "cfc", exe_ext, NULL);
+    char *test_cfc_exe = chaz_Util_join("", "t", DIR_SEP, "test_cfc", exe_ext,
+                                        NULL);
 
-    char *src_dir;
     char *scratch;
 
     chaz_MakeFile *makefile;
@@ -125,17 +128,11 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     printf("Creating Makefile...\n");
 
-    src_dir = (char*)malloc(strlen(base_dir) + 20);
-    sprintf(src_dir, "%s" DIR_SEP "src", base_dir);
-
     makefile = chaz_MakeFile_new();
 
     /* Directories */
 
     chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
-    chaz_MakeFile_add_var(makefile, "SRC_DIR", src_dir);
-    chaz_MakeFile_add_var(makefile, "INCLUDE_DIR",
-                          "$(BASE_DIR)" DIR_SEP "include");
 
     /* File extensions */
 
@@ -150,8 +147,8 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_CFlags_enable_optimization(makefile_cflags);
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(INCLUDE_DIR)");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(SRC_DIR)");
+    chaz_CFlags_add_include_dir(makefile_cflags, include_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, src_dir);
     if (args->code_coverage) {
         chaz_CFlags_enable_code_coverage(makefile_cflags);
     }
@@ -177,18 +174,11 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     chaz_MakeFile_add_var(makefile, "CFC_OBJS", "cfc$(OBJ_EXT)");
 
-    /* Executables */
-
-    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)");
-
     /* Rules */
 
-    chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)");
+    chaz_MakeFile_add_rule(makefile, "all", cfc_exe);
 
-    chaz_MakeFile_add_lemon_exe(makefile, "$(BASE_DIR)" DIR_SEP ".." DIR_SEP
-                                ".." DIR_SEP "lemon");
+    chaz_MakeFile_add_lemon_exe(makefile, lemon_dir);
     chaz_MakeFile_add_lemon_grammar(makefile, parse_header);
 
     /*
@@ -206,23 +196,22 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     if (args->code_coverage) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
-    chaz_MakeFile_add_exe(makefile, "$(CFC_EXE)",
-                          "$(COMMON_OBJS) $(CFC_OBJS)", link_flags);
-    chaz_MakeFile_add_exe(makefile, "$(TEST_CFC_EXE)",
+    chaz_MakeFile_add_exe(makefile, cfc_exe, "$(COMMON_OBJS) $(CFC_OBJS)",
+                          link_flags);
+    chaz_MakeFile_add_exe(makefile, test_cfc_exe,
                           "$(COMMON_OBJS) $(TEST_CFC_OBJS)", link_flags);
     chaz_CFlags_destroy(link_flags);
 
-    rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_CFC_EXE)");
-    chaz_MakeRule_add_command(rule, "$(TEST_CFC_EXE)");
+    rule = chaz_MakeFile_add_rule(makefile, "test", test_cfc_exe);
+    chaz_MakeRule_add_command(rule, test_cfc_exe);
 
     if (args->code_coverage) {
-        rule = chaz_MakeFile_add_rule(makefile, "coverage",
-                                      "$(TEST_CFC_EXE)");
+        rule = chaz_MakeFile_add_rule(makefile, "coverage", test_cfc_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --zerocounters"
                                   " --directory $(BASE_DIR)");
-        chaz_MakeRule_add_command(rule, "$(TEST_CFC_EXE)");
+        chaz_MakeRule_add_command(rule, test_cfc_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --capture"
@@ -251,7 +240,12 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeFile_write(makefile);
 
     chaz_MakeFile_destroy(makefile);
+    free(lemon_dir);
     free(src_dir);
+    free(include_dir);
+    free(parse_header);
+    free(cfc_exe);
+    free(test_cfc_exe);
 }
 
 int main(int argc, const char **argv) {

http://git-wip-us.apache.org/repos/asf/lucy/blob/8aacc868/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 00a5d1f..7a8bc4c 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -46,7 +46,6 @@
 
 typedef struct SourceFileContext {
     chaz_MakeVar *var;
-    const char *dir;
 } SourceFileContext;
 
 static const char lucy_version[]       = "0.3.0";
@@ -101,7 +100,7 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
 }
 
 static void
-S_source_file_callback(char *file, void *context) {
+S_source_file_callback(const char *dir, char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
     const char *json_parser_c = "Lucy" DIR_SEP "Util" DIR_SEP "Json" DIR_SEP
                                 "JsonParser.c";
@@ -119,10 +118,7 @@ S_source_file_callback(char *file, void *context) {
     }
     file[file_len-2] = '\0';
 
-    pattern = "%s" DIR_SEP "%s$(OBJ_EXT)";
-    obj_file_size = strlen(pattern) + strlen(sfc->dir) + file_len + 10;
-    obj_file = (char*)malloc(obj_file_size);
-    sprintf(obj_file, pattern, sfc->dir, file);
+    obj_file = chaz_Util_join("", dir, DIR_SEP, file, "$(OBJ_EXT)", NULL);
     chaz_MakeVar_append(sfc->var, obj_file);
     free(obj_file);
 }
@@ -135,8 +131,27 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     const char *exe_ext  = chaz_OS_exe_ext();
     const char *obj_ext  = chaz_CC_obj_ext();
 
-    const char *json_parser = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                              DIR_SEP "Json" DIR_SEP "JsonParser";
+    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 *cfc_dir       = chaz_Util_join(DIR_SEP, base_dir, "clownfish",
+                                         "compiler", "c", 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 *snowstem_inc_dir = chaz_Util_join(DIR_SEP, snowstem_dir, "include",
+                                            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 *cfc_exe       = chaz_Util_join("", cfc_dir, DIR_SEP, "cfc", exe_ext,
+                                         NULL);
+    char *test_lucy_exe = chaz_Util_join("", "t", DIR_SEP, "test_lucy",
+                                         exe_ext, NULL);
 
     chaz_MakeFile *makefile;
     chaz_MakeVar  *var;
@@ -150,9 +165,9 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_CFlags *test_cflags;
 
     chaz_SharedLib *lib;
-    const char     *math_library;
-    const char     *test_command;
+    const char     *math_library = chaz_Floats_math_library();
     char           *lib_filename;
+    char           *test_command;
     char           *scratch;
 
     printf("Creating Makefile...\n");
@@ -161,25 +176,7 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     /* Directories */
 
-    chaz_MakeFile_add_var(makefile, "SRC_DIR", "src");
-    chaz_MakeFile_add_var(makefile, "AUTOGEN_DIR", "autogen");
     chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
-    chaz_MakeFile_add_var(makefile, "CORE_DIR",
-                          "$(BASE_DIR)" DIR_SEP "core");
-    chaz_MakeFile_add_var(makefile, "MODULES_DIR",
-                          "$(BASE_DIR)" DIR_SEP "modules");
-    chaz_MakeFile_add_var(makefile, "CFC_DIR",
-                          "$(BASE_DIR)" DIR_SEP "clownfish" DIR_SEP "compiler"
-                          DIR_SEP "c");
-    chaz_MakeFile_add_var(makefile, "SNOWSTEM_DIR",
-                          "$(MODULES_DIR)" DIR_SEP "analysis" DIR_SEP
-                          "snowstem" DIR_SEP "source");
-    chaz_MakeFile_add_var(makefile, "SNOWSTOP_DIR",
-                          "$(MODULES_DIR)" DIR_SEP "analysis" DIR_SEP
-                          "snowstop" DIR_SEP "source");
-    chaz_MakeFile_add_var(makefile, "UTF8PROC_DIR",
-                          "$(MODULES_DIR)" DIR_SEP "unicode" DIR_SEP
-                          "utf8proc");
 
     /* File extensions */
 
@@ -201,16 +198,11 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     }
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(SRC_DIR)");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(CORE_DIR)");
-    chaz_CFlags_add_include_dir(makefile_cflags,
-                                "$(AUTOGEN_DIR)" DIR_SEP "include");
-    chaz_CFlags_add_include_dir(makefile_cflags,
-                                "$(SNOWSTEM_DIR)" DIR_SEP "include");
-    chaz_CFlags_add_include_dir(makefile_cflags,
-                                "$(MODULES_DIR)" DIR_SEP "unicode" DIR_SEP
-                                "ucd");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(UTF8PROC_DIR)");
+    chaz_CFlags_add_include_dir(makefile_cflags, core_dir);
+    chaz_CFlags_add_include_dir(makefile_cflags, "autogen" DIR_SEP "include");
+    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);
 
     var = chaz_MakeFile_add_var(makefile, "CFLAGS", NULL);
     chaz_MakeVar_append(var, chaz_CFlags_get_string(extra_cflags));
@@ -224,74 +216,46 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     var = chaz_MakeFile_add_var(makefile, "LUCY_OBJS", NULL);
     sfc.var = var;
 
-    sfc.dir = "$(SRC_DIR)";
-    chaz_Make_list_files("src", "c", S_source_file_callback, &sfc);
+    chaz_Make_list_files("src",        "c", S_source_file_callback, &sfc);
+    chaz_Make_list_files(core_dir,     "c", S_source_file_callback, &sfc);
+    chaz_Make_list_files(snowstem_dir, "c", S_source_file_callback, &sfc);
+    chaz_Make_list_files(snowstop_dir, "c", S_source_file_callback, &sfc);
+    chaz_Make_list_files(utf8proc_dir, "c", S_source_file_callback, &sfc);
 
-    scratch = (char*)malloc(strlen(base_dir) + 20);
-    sprintf(scratch, "%s" DIR_SEP "core", base_dir);
-    sfc.dir = "$(CORE_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
-    free(scratch);
     scratch = chaz_Util_join("", json_parser, "$(OBJ_EXT)", NULL);
     chaz_MakeVar_append(var, scratch);
     free(scratch);
 
-    scratch = (char*)malloc(strlen(base_dir) + 80);
-    sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "analysis" DIR_SEP
-            "snowstem" DIR_SEP "source", base_dir);
-    sfc.dir = "$(SNOWSTEM_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
-    free(scratch);
-
-    scratch = (char*)malloc(strlen(base_dir) + 80);
-    sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "analysis" DIR_SEP
-            "snowstop" DIR_SEP "source", base_dir);
-    sfc.dir = "$(SNOWSTOP_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
-    free(scratch);
-
-    scratch = (char*)malloc(strlen(base_dir) + 80);
-    sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "unicode" DIR_SEP
-            "utf8proc", base_dir);
-    sfc.dir = "$(UTF8PROC_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
-    free(scratch);
-
-    chaz_MakeVar_append(var, "$(AUTOGEN_DIR)" DIR_SEP "source" DIR_SEP
+    chaz_MakeVar_append(var, "autogen" DIR_SEP "source" DIR_SEP
                         "parcel$(OBJ_EXT)");
 
-    /* Executables */
-
-    chaz_MakeFile_add_var(makefile, "CFC_EXE",
-                          "$(CFC_DIR)" DIR_SEP "cfc$(EXE_EXT)");
-    chaz_MakeFile_add_var(makefile, "TEST_LUCY_EXE",
-                          "t" DIR_SEP "test_lucy$(EXE_EXT)");
-
     /* Rules */
 
     lib = chaz_SharedLib_new("lucy", lucy_version, lucy_major_version);
     lib_filename = chaz_SharedLib_filename(lib);
     chaz_MakeFile_add_rule(makefile, "all", lib_filename);
 
-    chaz_MakeFile_add_lemon_exe(makefile, "$(BASE_DIR)" DIR_SEP "lemon");
+    chaz_MakeFile_add_lemon_exe(makefile, lemon_dir);
     chaz_MakeFile_add_lemon_grammar(makefile, json_parser);
 
     /*
      * CFC also builds LEMON_EXE, so it might be built twice at the same time
      * in parallel builds. Adding LEMON_EXE as prereq of CFC_EXE avoids this.
      */
-    rule = chaz_MakeFile_add_rule(makefile, "$(CFC_EXE)", "$(LEMON_EXE)");
-    chaz_MakeRule_add_make_command(rule, "$(CFC_DIR)", NULL);
+    rule = chaz_MakeFile_add_rule(makefile, cfc_exe, "$(LEMON_EXE)");
+    chaz_MakeRule_add_make_command(rule, cfc_dir, NULL);
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(AUTOGEN_DIR)", "$(CFC_EXE)");
-    chaz_MakeRule_add_command(rule, "$(CFC_EXE) --source=$(CORE_DIR) "
-                              "--dest=$(AUTOGEN_DIR) --header=cfc_header");
+    rule = chaz_MakeFile_add_rule(makefile, "autogen", cfc_exe);
+    scratch = chaz_Util_join("", cfc_exe, " --source=", core_dir,
+                             " --dest=autogen --header=cfc_header", NULL);
+    chaz_MakeRule_add_command(rule, scratch);
+    free(scratch);
 
     /* Needed for parallel builds. */
-    rule = chaz_MakeFile_add_rule(makefile, "$(AUTOGEN_DIR)" DIR_SEP "source"
-                                  DIR_SEP "parcel.c", "$(AUTOGEN_DIR)");
+    rule = chaz_MakeFile_add_rule(makefile, "autogen" DIR_SEP "source"
+                                  DIR_SEP "parcel.c", "autogen");
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "$(AUTOGEN_DIR)");
+    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "autogen");
     /*
      * The dependency is actually on JsonParser.h, but make doesn't cope
      * well with multiple output files.
@@ -304,7 +268,6 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     if (chaz_CC_msvc_version_num()) {
         chaz_CFlags_append(link_flags, "/nologo");
     }
-    math_library = chaz_Floats_math_library();
     if (math_library) {
         chaz_CFlags_add_external_library(link_flags, math_library);
     }
@@ -320,25 +283,26 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     test_cflags = chaz_CC_new_cflags();
     chaz_CFlags_enable_optimization(test_cflags);
     chaz_CFlags_add_include_dir(test_cflags, ".");
-    chaz_CFlags_add_include_dir(test_cflags,
-                                "$(AUTOGEN_DIR)" DIR_SEP "include");
+    chaz_CFlags_add_include_dir(test_cflags, "autogen" DIR_SEP "include");
     chaz_CFlags_add_library(link_flags, lib);
-    rule = chaz_MakeFile_add_compiled_exe(makefile, "$(TEST_LUCY_EXE)",
+    rule = chaz_MakeFile_add_compiled_exe(makefile, test_lucy_exe,
                                           "t" DIR_SEP "test_lucy.c",
                                           test_cflags);
     chaz_MakeRule_add_prereq(rule, lib_filename);
     chaz_CFlags_destroy(test_cflags);
 
-    rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_LUCY_EXE)");
-    test_command = "$(TEST_LUCY_EXE)";
+    rule = chaz_MakeFile_add_rule(makefile, "test", test_lucy_exe);
     if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
-        test_command = "LD_LIBRARY_PATH=. $(TEST_LUCY_EXE)";
+        test_command = chaz_Util_join(" ", "LD_LIBRARY_PATH=.", test_lucy_exe,
+                                      NULL);
+    }
+    else {
+        test_command = chaz_Util_strdup(test_lucy_exe);
     }
     chaz_MakeRule_add_command(rule, test_command);
 
     if (args->code_coverage) {
-        rule = chaz_MakeFile_add_rule(makefile, "coverage",
-                                      "$(TEST_LUCY_EXE)");
+        rule = chaz_MakeFile_add_rule(makefile, "coverage", test_lucy_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --zerocounters"
@@ -372,23 +336,36 @@ S_write_makefile(struct chaz_CLIArgs *args) {
         chaz_MakeRule_add_rm_command(clean_rule, "$(LUCY_OBJS)");
     }
 
-    chaz_MakeRule_add_recursive_rm_command(clean_rule, "$(AUTOGEN_DIR)");
+    chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen");
 
     if (args->code_coverage) {
         chaz_MakeRule_add_rm_command(clean_rule, "lucy.info");
         chaz_MakeRule_add_recursive_rm_command(clean_rule, "coverage");
     }
 
-    chaz_MakeRule_add_make_command(clean_rule, "$(CFC_DIR)", "clean");
+    chaz_MakeRule_add_make_command(clean_rule, cfc_dir, "clean");
 
     distclean_rule = chaz_MakeFile_distclean_rule(makefile);
-    chaz_MakeRule_add_make_command(distclean_rule, "$(CFC_DIR)", "distclean");
+    chaz_MakeRule_add_make_command(distclean_rule, cfc_dir, "distclean");
 
     chaz_MakeFile_write(makefile);
 
     chaz_MakeFile_destroy(makefile);
     chaz_SharedLib_destroy(lib);
+    free(core_dir);
+    free(lemon_dir);
+    free(cfc_dir);
+    free(modules_dir);
+    free(snowstem_dir);
+    free(snowstem_inc_dir);
+    free(snowstop_dir);
+    free(ucd_dir);
+    free(utf8proc_dir);
+    free(json_parser);
+    free(cfc_exe);
+    free(test_lucy_exe);
     free(lib_filename);
+    free(test_command);
 }
 
 int main(int argc, const char **argv) {


[lucy-commits] [05/13] git commit: refs/heads/makefile-rework - Set shared library version

Posted by nw...@apache.org.
Set shared library version

Using '-current_version' for Mach-O and '-Wl,-soname' for ELF systems.


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

Branch: refs/heads/makefile-rework
Commit: 8c0f0a126ac2a427e15be8c5b714561863b76d7a
Parents: c66d966
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon May 13 20:51:50 2013 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed May 15 19:13:53 2013 +0200

----------------------------------------------------------------------
 charmonizer/src/Charmonizer/Core/CFlags.c |   26 +++++++++++++++++++++++-
 charmonizer/src/Charmonizer/Core/CFlags.h |    4 +++
 charmonizer/src/Charmonizer/Core/Make.c   |    1 +
 3 files changed, 30 insertions(+), 1 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/8c0f0a12/charmonizer/src/Charmonizer/Core/CFlags.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/CFlags.c b/charmonizer/src/Charmonizer/Core/CFlags.c
index 4642a99..5b4e15d 100644
--- a/charmonizer/src/Charmonizer/Core/CFlags.c
+++ b/charmonizer/src/Charmonizer/Core/CFlags.c
@@ -214,7 +214,7 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
         string = "/DLL";
     }
     else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        if (chaz_OS_is_darwin()) {
+        if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
             string = "-dynamiclib";
         }
         else {
@@ -229,6 +229,30 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
 }
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+    char       *string;
+
+    if (flags->style != CHAZ_CFLAGS_STYLE_GNU
+        || strcmp(shlib_ext, ".dll") == 0) {
+        return;
+    }
+
+    if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
+        const char *version = chaz_SharedLib_get_version(lib);
+        string = chaz_Util_join(" ", "-current_version", version, NULL);
+    }
+    else {
+        char *soname = chaz_SharedLib_major_version_filename(lib);
+        string = chaz_Util_join("", "-Wl,-soname,", soname, NULL);
+        free(soname);
+    }
+    chaz_CFlags_append(flags, string);
+    free(string);
+}
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename) {
     const char *output;
     char *string;

http://git-wip-us.apache.org/repos/asf/lucy/blob/8c0f0a12/charmonizer/src/Charmonizer/Core/CFlags.h
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/CFlags.h b/charmonizer/src/Charmonizer/Core/CFlags.h
index 5f4151d..cb9c75f 100644
--- a/charmonizer/src/Charmonizer/Core/CFlags.h
+++ b/charmonizer/src/Charmonizer/Core/CFlags.h
@@ -77,6 +77,10 @@ void
 chaz_CFlags_link_shared_library(chaz_CFlags *flags);
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib);
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename);
 
 void

http://git-wip-us.apache.org/repos/asf/lucy/blob/8c0f0a12/charmonizer/src/Charmonizer/Core/Make.c
----------------------------------------------------------------------
diff --git a/charmonizer/src/Charmonizer/Core/Make.c b/charmonizer/src/Charmonizer/Core/Make.c
index 410254e..1df757a 100644
--- a/charmonizer/src/Charmonizer/Core/Make.c
+++ b/charmonizer/src/Charmonizer/Core/Make.c
@@ -339,6 +339,7 @@ chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
     chaz_CFlags_link_shared_library(local_flags);
+    chaz_CFlags_set_shared_library_version(local_flags, lib);
     chaz_CFlags_set_link_output(local_flags, filename);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,


[lucy-commits] [12/13] Regenerate charmonizer.c

Posted by nw...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucy/blob/07c27701/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 0e512c3..895f677 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -36,12 +36,58 @@
 
 /***************************************************************************/
 
+#line 21 "src/Charmonizer/Core/SharedLibrary.h"
+/* Charmonizer/Core/SharedLibrary.h
+ */
+
+#ifndef H_CHAZ_SHARED_LIB
+#define H_CHAZ_SHARED_LIB
+
+typedef struct chaz_SharedLib chaz_SharedLib;
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version);
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *flags);
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib);
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib);
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib);
+
+#endif /* H_CHAZ_SHARED_LIB */
+
+
+
+/***************************************************************************/
+
 #line 21 "src/Charmonizer/Core/CFlags.h"
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/CFlags.h
  */
 
-#ifndef H_CHAZ_FLAGS
-#define H_CHAZ_FLAGS
+#ifndef H_CHAZ_CFLAGS
+#define H_CHAZ_CFLAGS
 
 #define CHAZ_CFLAGS_STYLE_POSIX  1
 #define CHAZ_CFLAGS_STYLE_GNU    2
@@ -96,18 +142,25 @@ void
 chaz_CFlags_link_shared_library(chaz_CFlags *flags);
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib);
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename);
 
 void
 chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory);
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library);
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib);
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library);
 
 void
 chaz_CFlags_enable_code_coverage(chaz_CFlags *flags);
 
-#endif /* H_CHAZ_FLAGS */
+#endif /* H_CHAZ_CFLAGS */
 
 
 
@@ -172,11 +225,6 @@ chaz_CC_get_cc(void);
 const char*
 chaz_CC_get_cflags(void);
 
-/* Accessor for `cflags_style`.
- */
-int
-chaz_CC_get_cflags_style(void);
-
 /* Accessor for `extra_cflags`.
  */
 chaz_CFlags*
@@ -187,6 +235,11 @@ chaz_CC_get_extra_cflags(void);
 chaz_CFlags*
 chaz_CC_get_temp_cflags(void);
 
+/* Return a new CFlags object.
+ */
+chaz_CFlags*
+chaz_CC_new_cflags(void);
+
 /* Return the extension for a compiled object.
  */
 const char*
@@ -204,9 +257,6 @@ chaz_CC_msvc_version_num(void);
 const char*
 chaz_CC_link_command(void);
 
-char*
-chaz_CC_shared_lib_file(const char *name);
-
 #endif /* H_CHAZ_COMPILER */
 
 
@@ -416,19 +466,21 @@ chaz_HeadCheck_contains_member(const char *struct_name, const char *member,
 /***************************************************************************/
 
 #line 21 "src/Charmonizer/Core/Make.h"
-/* Charmonizer/Core/Compiler.h
+/* Charmonizer/Core/Make.h
  */
 
 #ifndef H_CHAZ_MAKE
 #define H_CHAZ_MAKE
 
 /* #include "Charmonizer/Core/CFlags.h" */
+/* #include "Charmonizer/Core/SharedLib.h" */
 
 typedef struct chaz_MakeFile chaz_MakeFile;
 typedef struct chaz_MakeVar chaz_MakeVar;
 typedef struct chaz_MakeRule chaz_MakeRule;
 
-typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context);
+typedef void (*chaz_Make_list_files_callback_t)(const char *dir, char *file,
+                                                void *context);
 
 /** Initialize the environment.
  */
@@ -539,14 +591,31 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
  * to the list of files to clean.
  *
  * @param makefile The makefile.
- * @param name The name of the shared library without prefix or extension.
+ * @param lib The shared library.
  * @param sources The list of source files.
  * @param link_flags Additional link flags.
  */
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags);
 
+/** Add a rule to build the lemon parser generator.
+ *
+ * @param makefile The makefile.
+ * @param dir The lemon directory.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir);
+
+/** Add a rule for a lemon grammar.
+ *
+ * @param makefile The makefile.
+ * @param base_name The filename of the grammar without extension.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name);
+
 /** Write the makefile to a file named 'Makefile' in the current directory.
  *
  * @param makefile The makefile.
@@ -696,6 +765,11 @@ chaz_OS_shared_lib_ext(void);
 const char*
 chaz_OS_dev_null(void);
 
+/* Return the directory separator on this system.
+ */
+const char*
+chaz_OS_dir_sep(void);
+
 /* Return the shell type of this system.
  */
 int
@@ -1441,12 +1515,136 @@ void chaz_VariadicMacros_run(void);
 
 /***************************************************************************/
 
+#line 17 "src/Charmonizer/Core/SharedLibrary.c"
+#include <string.h>
+#include <stdlib.h>
+/* #include "Charmonizer/Core/SharedLib.h" */
+/* #include "Charmonizer/Core/Compiler.h" */
+/* #include "Charmonizer/Core/Util.h" */
+/* #include "Charmonizer/Core/OperatingSystem.h" */
+
+struct chaz_SharedLib {
+    char *name;
+    char *version;
+    char *major_version;
+};
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext);
+
+static const char*
+S_get_prefix(void);
+
+chaz_SharedLib*
+chaz_SharedLib_new(const char *name, const char *version,
+                   const char *major_version) {
+    chaz_SharedLib *lib = (chaz_SharedLib*)malloc(sizeof(chaz_SharedLib));
+    lib->name          = chaz_Util_strdup(name);
+    lib->version       = chaz_Util_strdup(version);
+    lib->major_version = chaz_Util_strdup(major_version);
+    return lib;
+}
+
+void
+chaz_SharedLib_destroy(chaz_SharedLib *lib) {
+    free(lib->name);
+    free(lib->version);
+    free(lib->major_version);
+    free(lib);
+}
+
+const char*
+chaz_SharedLib_get_name(chaz_SharedLib *lib) {
+    return lib->name;
+}
+
+const char*
+chaz_SharedLib_get_version(chaz_SharedLib *lib) {
+    return lib->version;
+}
+
+const char*
+chaz_SharedLib_get_major_version(chaz_SharedLib *lib) {
+    return lib->major_version;
+}
+
+char*
+chaz_SharedLib_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return S_build_filename(lib, lib->major_version, shlib_ext);
+    }
+    else {
+        return S_build_filename(lib, lib->version, shlib_ext);
+    }
+}
+
+char*
+chaz_SharedLib_major_version_filename(chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return S_build_filename(lib, lib->major_version, shlib_ext);
+}
+
+char*
+chaz_SharedLib_no_version_filename(chaz_SharedLib *lib) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    return chaz_Util_join("", prefix, lib->name, shlib_ext, NULL);
+}
+
+char*
+chaz_SharedLib_implib_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".lib");
+}
+
+char*
+chaz_SharedLib_export_filename(chaz_SharedLib *lib) {
+    return S_build_filename(lib, lib->major_version, ".exp");
+}
+
+static char*
+S_build_filename(chaz_SharedLib *lib, const char *version, const char *ext) {
+    const char *prefix    = S_get_prefix();
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+
+    if (strcmp(shlib_ext, ".dll") == 0) {
+        return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL);
+    }
+    else if (strcmp(shlib_ext, ".dylib") == 0) {
+        return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL);
+    }
+    else {
+        return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL);
+    }
+}
+
+static const char*
+S_get_prefix() {
+    if (chaz_CC_msvc_version_num()) {
+        return "";
+    }
+    else if (chaz_OS_is_cygwin()) {
+        return "cyg";
+    }
+    else {
+        return "lib";
+    }
+}
+
+
+
+/***************************************************************************/
+
 #line 17 "src/Charmonizer/Core/CFlags.c"
 #include <string.h>
 #include <stdlib.h>
-/* #include "Charmonizer/Core/Flags.h" */
+/* #include "Charmonizer/Core/CFlags.h" */
 /* #include "Charmonizer/Core/Util.h" */
 /* #include "Charmonizer/Core/OperatingSystem.h" */
+/* #include "Charmonizer/Core/SharedLibrary.h" */
 
 struct chaz_CFlags {
     int   style;
@@ -1641,7 +1839,7 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
         string = "/DLL";
     }
     else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
-        if (chaz_OS_is_darwin()) {
+        if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
             string = "-dynamiclib";
         }
         else {
@@ -1656,6 +1854,30 @@ chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
 }
 
 void
+chaz_CFlags_set_shared_library_version(chaz_CFlags *flags,
+                                       chaz_SharedLib *lib) {
+    const char *shlib_ext = chaz_OS_shared_lib_ext();
+    char       *string;
+
+    if (flags->style != CHAZ_CFLAGS_STYLE_GNU
+        || strcmp(shlib_ext, ".dll") == 0) {
+        return;
+    }
+
+    if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) {
+        const char *version = chaz_SharedLib_get_version(lib);
+        string = chaz_Util_join(" ", "-current_version", version, NULL);
+    }
+    else {
+        char *soname = chaz_SharedLib_major_version_filename(lib);
+        string = chaz_Util_join("", "-Wl,-soname,", soname, NULL);
+        free(soname);
+    }
+    chaz_CFlags_append(flags, string);
+    free(string);
+}
+
+void
 chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename) {
     const char *output;
     char *string;
@@ -1692,13 +1914,26 @@ chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory) {
 }
 
 void
-chaz_CFlags_add_library(chaz_CFlags *flags, const char *library) {
+chaz_CFlags_add_library(chaz_CFlags *flags, chaz_SharedLib *lib) {
+    char *filename;
+    if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
+        filename = chaz_SharedLib_implib_filename(lib);
+    }
+    else {
+        filename = chaz_SharedLib_filename(lib);
+    }
+    chaz_CFlags_append(flags, filename);
+    free(filename);
+}
+
+void
+chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library) {
     char *string;
     if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
         string = chaz_Util_join("", library, ".lib", NULL);
     }
     else {
-        string = chaz_Util_join("", "-l ", library, NULL);
+        string = chaz_Util_join(" ", "-l", library, NULL);
     }
     chaz_CFlags_append(flags, string);
     free(string);
@@ -2025,11 +2260,6 @@ chaz_CC_get_cflags(void) {
     return chaz_CC.cflags;
 }
 
-int
-chaz_CC_get_cflags_style(void) {
-    return chaz_CC.cflags_style;
-}
-
 chaz_CFlags*
 chaz_CC_get_extra_cflags(void) {
     return chaz_CC.extra_cflags;
@@ -2040,6 +2270,11 @@ chaz_CC_get_temp_cflags(void) {
     return chaz_CC.temp_cflags;
 }
 
+chaz_CFlags*
+chaz_CC_new_cflags(void) {
+    return chaz_CFlags_new(chaz_CC.cflags_style);
+}
+
 const char*
 chaz_CC_obj_ext(void) {
     return chaz_CC.obj_ext;
@@ -2072,21 +2307,6 @@ chaz_CC_link_command() {
     }
 }
 
-char*
-chaz_CC_shared_lib_file(const char *name) {
-    const char *prefix = "";
-    const char *shlib_ext = chaz_OS_shared_lib_ext();
-    if (!chaz_CC.intval__MSC_VER) {
-        if (chaz_OS_is_cygwin()) {
-            prefix = "cyg";
-        }
-        else {
-            prefix = "lib";
-        }
-    }
-    return chaz_Util_join("", prefix, name, shlib_ext, NULL);
-}
-
 
 
 /***************************************************************************/
@@ -3349,6 +3569,9 @@ chaz_Make_audition(const char *make) {
 chaz_MakeFile*
 chaz_MakeFile_new() {
     chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
+    const char    *exe_ext  = chaz_OS_exe_ext();
+    const char    *obj_ext  = chaz_CC_obj_ext();
+    char *generated;
 
     makefile->vars = (chaz_MakeVar**)malloc(sizeof(chaz_MakeVar*));
     makefile->vars[0] = NULL;
@@ -3361,10 +3584,11 @@ chaz_MakeFile_new() {
     makefile->clean     = S_new_rule("clean", NULL);
     makefile->distclean = S_new_rule("distclean", "clean");
 
-    chaz_MakeRule_add_rm_command(makefile->distclean,
-                                 "charmonizer$(EXE_EXT) charmonizer$(OBJ_EXT)"
-                                 " charmony.h Makefile");
+    generated = chaz_Util_join("", "charmonizer", exe_ext, " charmonizer",
+                               obj_ext, " charmony.h Makefile", NULL);
+    chaz_MakeRule_add_rm_command(makefile->distclean, generated);
 
+    free(generated);
     return makefile;
 }
 
@@ -3444,8 +3668,7 @@ chaz_MakeFile_distclean_rule(chaz_MakeFile *makefile) {
 chaz_MakeRule*
 chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
                       const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
@@ -3457,6 +3680,9 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_link_output(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
@@ -3473,8 +3699,7 @@ chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
 chaz_MakeRule*
 chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
                                const char *sources, chaz_CFlags *cflags) {
-    int            cflags_style  = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags   = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags   = chaz_CC_new_cflags();
     const char    *cc            = chaz_CC_get_cc();
     const char    *cflags_string = "";
     const char    *local_flags_string;
@@ -3486,6 +3711,9 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
     if (cflags) {
         cflags_string = chaz_CFlags_get_string(cflags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_set_output_exe(local_flags, exe);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", cc, sources, cflags_string,
@@ -3501,45 +3729,91 @@ chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
 }
 
 chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, const char *name,
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_SharedLib *lib,
                              const char *sources, chaz_CFlags *link_flags) {
-    int            cflags_style = chaz_CC_get_cflags_style();
-    chaz_CFlags   *local_flags  = chaz_CFlags_new(cflags_style);
+    chaz_CFlags   *local_flags  = chaz_CC_new_cflags();
     const char    *link         = chaz_CC_link_command();
     const char    *link_flags_string = "";
     const char    *local_flags_string;
     chaz_MakeRule *rule;
-    char          *shared_lib;
+    char          *filename;
     char          *command;
 
-    shared_lib = chaz_CC_shared_lib_file(name);
-    rule = chaz_MakeFile_add_rule(makefile, shared_lib, sources);
+    filename = chaz_SharedLib_filename(lib);
+    rule = chaz_MakeFile_add_rule(makefile, filename, sources);
 
     if (link_flags) {
         link_flags_string = chaz_CFlags_get_string(link_flags);
     }
+    if (chaz_CC_msvc_version_num()) {
+        chaz_CFlags_append(local_flags, "/nologo");
+    }
     chaz_CFlags_link_shared_library(local_flags);
-    chaz_CFlags_set_link_output(local_flags, shared_lib);
+    chaz_CFlags_set_shared_library_version(local_flags, lib);
+    chaz_CFlags_set_link_output(local_flags, filename);
     local_flags_string = chaz_CFlags_get_string(local_flags);
     command = chaz_Util_join(" ", link, sources, link_flags_string,
                              local_flags_string, NULL);
     chaz_MakeRule_add_command(rule, command);
 
-    chaz_MakeRule_add_rm_command(makefile->clean, shared_lib);
+    chaz_MakeRule_add_rm_command(makefile->clean, filename);
 
     if (chaz_CC_msvc_version_num()) {
         /* Remove import library and export file under MSVC. */
-        char *filename;
-        filename = chaz_Util_join("", name, ".lib", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
-        filename = chaz_Util_join("", name, ".exp", NULL);
-        chaz_MakeRule_add_rm_command(makefile->clean, filename);
-        free(filename);
+        char *lib_filename = chaz_SharedLib_implib_filename(lib);
+        char *exp_filename = chaz_SharedLib_export_filename(lib);
+        chaz_MakeRule_add_rm_command(makefile->clean, lib_filename);
+        chaz_MakeRule_add_rm_command(makefile->clean, exp_filename);
+        free(lib_filename);
+        free(exp_filename);
     }
 
     chaz_CFlags_destroy(local_flags);
-    free(shared_lib);
+    free(filename);
+    free(command);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir) {
+    chaz_CFlags   *cflags = chaz_CC_new_cflags();
+    chaz_MakeRule *rule;
+    const char *dir_sep = chaz_OS_dir_sep();
+    const char *exe_ext = chaz_OS_exe_ext();
+    char *lemon_exe = chaz_Util_join("", dir, dir_sep, "lemon", exe_ext, NULL);
+    char *lemon_c   = chaz_Util_join(dir_sep, dir, "lemon.c", NULL);
+
+    chaz_CFlags_enable_optimization(cflags);
+    chaz_MakeFile_add_var(makefile, "LEMON_EXE", lemon_exe);
+    rule = chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)", lemon_c,
+                                          cflags);
+
+    chaz_CFlags_destroy(cflags);
+    free(lemon_c);
+    free(lemon_exe);
+    return rule;
+}
+
+chaz_MakeRule*
+chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
+                                const char *base_name) {
+    char *c_file  = chaz_Util_join(".", base_name, "c", NULL);
+    char *h_file  = chaz_Util_join(".", base_name, "h", NULL);
+    char *y_file  = chaz_Util_join(".", base_name, "y", NULL);
+    char *command = chaz_Util_join(" ", "$(LEMON_EXE) -q", y_file, NULL);
+
+    chaz_MakeRule *rule = chaz_MakeFile_add_rule(makefile, c_file, y_file);
+    chaz_MakeRule *clean_rule = chaz_MakeFile_clean_rule(makefile);
+
+    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
+    chaz_MakeRule_add_command(rule, command);
+
+    chaz_MakeRule_add_rm_command(clean_rule, h_file);
+    chaz_MakeRule_add_rm_command(clean_rule, c_file);
+
+    free(c_file);
+    free(h_file);
+    free(y_file);
     free(command);
     return rule;
 }
@@ -3571,7 +3845,7 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) {
         /* Inference rule for .c files. */
         fprintf(out, ".c.obj :\n");
         if (chaz_CC_msvc_version_num()) {
-            fprintf(out, "\t$(CC) $(CFLAGS) /c $< /Fo$@\n\n");
+            fprintf(out, "\t$(CC) /nologo $(CFLAGS) /c $< /Fo$@\n\n");
         }
         else {
             fprintf(out, "\t$(CC) $(CFLAGS) -c $< -o $@\n\n");
@@ -3843,7 +4117,7 @@ chaz_Make_list_files(const char *dir, const char *ext,
                           file);
         }
 
-        callback(file + prefix_len, context);
+        callback(dir, file + prefix_len, context);
     }
 
     free(prefix);
@@ -3870,11 +4144,12 @@ chaz_Make_list_files(const char *dir, const char *ext,
 static struct {
     char name[CHAZ_OS_NAME_MAX+1];
     char dev_null[20];
+    char dir_sep[2];
     char exe_ext[5];
     char shared_lib_ext[7];
     char local_command_start[3];
     int  shell_type;
-} chaz_OS = { "", "", "", "", "", 0 };
+} chaz_OS = { "", "", "", "", "", "", 0 };
 
 void
 chaz_OS_init(void) {
@@ -3906,6 +4181,7 @@ chaz_OS_init(void) {
         free(uname);
 
         strcpy(chaz_OS.dev_null, "/dev/null");
+        strcpy(chaz_OS.dir_sep, "/");
         strcpy(chaz_OS.exe_ext, "");
         if (memcmp(chaz_OS.name, "darwin", 6) == 0) {
             strcpy(chaz_OS.shared_lib_ext, ".dylib");
@@ -3921,6 +4197,7 @@ chaz_OS_init(void) {
     else if (chaz_Util_can_open_file("nul")) {
         strcpy(chaz_OS.name, "windows");
         strcpy(chaz_OS.dev_null, "nul");
+        strcpy(chaz_OS.dir_sep, "\\");
         strcpy(chaz_OS.exe_ext, ".exe");
         strcpy(chaz_OS.shared_lib_ext, ".dll");
         strcpy(chaz_OS.local_command_start, ".\\");
@@ -3962,6 +4239,11 @@ chaz_OS_dev_null(void) {
     return chaz_OS.dev_null;
 }
 
+const char*
+chaz_OS_dir_sep(void) {
+    return chaz_OS.dir_sep;
+}
+
 int
 chaz_OS_shell_type(void) {
     return chaz_OS.shell_type;
@@ -4658,23 +4940,9 @@ chaz_DirManip_try_rmdir(void) {
     if (chaz_DirManip_compile_rmdir("direct.h"))   { return; }
 }
 
-static int
-chaz_DirManip_is_cygwin(void) {
-    static int is_cygwin = -1;
-    static const char cygwin_code[] =
-        CHAZ_QUOTE(#ifndef __CYGWIN__            )
-        CHAZ_QUOTE(  #error "Not Cygwin"         )
-        CHAZ_QUOTE(#endif                        )
-        CHAZ_QUOTE(int main() { return 0; }      );
-    if (is_cygwin == -1) {
-        is_cygwin = chaz_CC_test_compile(cygwin_code);
-    }
-    return is_cygwin;
-}
-
 void
 chaz_DirManip_run(void) {
-    char dir_sep[3];
+    const char *dir_sep = chaz_OS_dir_sep();
     int remove_zaps_dirs = false;
     int has_dirent_h = chaz_HeadCheck_check_header("dirent.h");
     int has_direct_h = chaz_HeadCheck_check_header("direct.h");
@@ -4732,16 +5000,6 @@ chaz_DirManip_run(void) {
         chaz_ConfWriter_add_def("MAKEDIR_MODE_IGNORED", "1");
     }
 
-    if (chaz_DirManip_is_cygwin()) {
-        strcpy(dir_sep, "/");
-    }
-    else if (chaz_HeadCheck_check_header("windows.h")) {
-        strcpy(dir_sep, "\\\\");
-    }
-    else {
-        strcpy(dir_sep, "/");
-    }
-
     {
         char scratch[5];
         sprintf(scratch, "\"%s\"", dir_sep);
@@ -4820,7 +5078,7 @@ chaz_Floats_math_library(void) {
         return NULL;
     }
 
-    chaz_CFlags_add_library(temp_cflags, "m");
+    chaz_CFlags_add_external_library(temp_cflags, "m");
     output = chaz_CC_capture_output(sqrt_code, &output_len);
     chaz_CFlags_clear(temp_cflags);
 
@@ -5653,7 +5911,7 @@ typedef struct chaz_LargeFiles_unbuff_combo {
 
 /* Check for a 64-bit file pointer type.
  */
-static const int
+static int
 chaz_LargeFiles_probe_off64(void);
 
 /* Check what name 64-bit ftell, fseek go by.
@@ -5720,7 +5978,7 @@ chaz_LargeFiles_run(void) {
     chaz_ConfWriter_end_module();
 }
 
-static const int
+static int
 chaz_LargeFiles_probe_off64(void) {
     static const char off64_code[] =
         CHAZ_QUOTE(  %s                                        )
@@ -6362,17 +6620,13 @@ chaz_VariadicMacros_run(void) {
 /* #include "Charmonizer/Core/ConfWriterPerl.h" */
 /* #include "Charmonizer/Core/ConfWriterRuby.h" */
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  #define DIR_SEP "\\"
-#else
-  #define DIR_SEP "/"
-#endif
-
 typedef struct SourceFileContext {
     chaz_MakeVar *var;
-    const char *dir;
 } SourceFileContext;
 
+static const char lucy_version[]       = "0.3.0";
+static const char lucy_major_version[] = "0.3";
+
 static void
 S_add_compiler_flags(struct chaz_CLIArgs *args) {
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
@@ -6421,39 +6675,50 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) {
     chaz_CFlags_add_define(extra_cflags, "CFP_LUCY", NULL);
 }
 
-static void
-S_add_common_cflags(chaz_CFlags *cflags) {
-    if (chaz_CC_msvc_version_num()) {
-        chaz_CFlags_append(cflags, "/nologo");
-    }
-    chaz_CFlags_enable_optimization(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 void
-S_source_file_callback(char *file, void *context) {
+S_c_file_callback(const char *dir, char *file, void *context) {
     SourceFileContext *sfc = (SourceFileContext*)context;
-    const char *json_parser_c = "Lucy" DIR_SEP "Util" DIR_SEP "Json" DIR_SEP
-                                "JsonParser.c";
+    const char *dir_sep = chaz_OS_dir_sep();
+    const char *obj_ext = chaz_CC_obj_ext();
     size_t file_len = strlen(file);
-    size_t obj_file_size;
-    const char *pattern;
     char *obj_file;
 
-    if (strcmp(file, json_parser_c) == 0) { return; }
-
     /* Strip extension */
-    if (file_len <= 2 || memcmp(file + file_len - 2, ".c", 2) != 0) {
-        chaz_Util_warn("Unexpected source file name: %s", file);
+    if (!S_ends_with(file, ".c")) {
+        chaz_Util_warn("Unexpected C filename: %s", file);
         return;
     }
     file[file_len-2] = '\0';
 
-    pattern = "%s" DIR_SEP "%s$(OBJ_EXT)";
-    obj_file_size = strlen(pattern) + strlen(sfc->dir) + file_len + 10;
-    obj_file = (char*)malloc(obj_file_size);
-    sprintf(obj_file, pattern, sfc->dir, file);
-    chaz_MakeVar_append(sfc->var, obj_file);
-    free(obj_file);
+    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);
+    }
+}
+
+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 (!S_ends_with(file, ".cfh")) {
+        chaz_Util_warn("Unexpected Clownfish header filename: %s", file);
+        return;
+    }
+
+    cfh_file = chaz_Util_join(dir_sep, dir, file, NULL);
+    chaz_MakeVar_append(sfc->var, cfh_file);
+    free(cfh_file);
 }
 
 static void
@@ -6461,17 +6726,34 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     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 *json_parser_y = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                                DIR_SEP "Json" DIR_SEP "JsonParser.y";
-    const char *json_parser_h = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                                DIR_SEP "Json" DIR_SEP "JsonParser.h";
-    const char *json_parser_c = "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                                DIR_SEP "Json" DIR_SEP "JsonParser.c";
-
-    char *scratch;
+    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 *cfc_dir       = chaz_Util_join(dir_sep, base_dir, "clownfish",
+                                         "compiler", "c", 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 *cfc_exe       = chaz_Util_join("", cfc_dir, dir_sep, "cfc", exe_ext,
+                                         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 *snowstem_inc_dir
+        = chaz_Util_join(dir_sep, snowstem_dir, "include", NULL);
 
     chaz_MakeFile *makefile;
     chaz_MakeVar  *var;
@@ -6479,15 +6761,16 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     chaz_MakeRule *clean_rule;
     chaz_MakeRule *distclean_rule;
 
-    int          cflags_style = chaz_CC_get_cflags_style();
     chaz_CFlags *extra_cflags = chaz_CC_get_extra_cflags();
     chaz_CFlags *makefile_cflags;
-    chaz_CFlags *lemon_cflags;
     chaz_CFlags *link_flags;
     chaz_CFlags *test_cflags;
-    const char  *math_library;
-    const char  *test_command;
-    char        *shared_lib;
+
+    chaz_SharedLib *lib;
+    const char     *math_library = chaz_Floats_math_library();
+    char           *lib_filename;
+    char           *test_command;
+    char           *scratch;
 
     printf("Creating Makefile...\n");
 
@@ -6495,40 +6778,15 @@ S_write_makefile(struct chaz_CLIArgs *args) {
 
     /* Directories */
 
-    chaz_MakeFile_add_var(makefile, "SRC_DIR", "src");
-    chaz_MakeFile_add_var(makefile, "AUTOGEN_DIR", "autogen");
     chaz_MakeFile_add_var(makefile, "BASE_DIR", base_dir);
-    chaz_MakeFile_add_var(makefile, "CORE_DIR",
-                          "$(BASE_DIR)" DIR_SEP "core");
-    chaz_MakeFile_add_var(makefile, "MODULES_DIR",
-                          "$(BASE_DIR)" DIR_SEP "modules");
-    chaz_MakeFile_add_var(makefile, "LEMON_DIR",
-                          "$(BASE_DIR)" DIR_SEP "lemon");
-    chaz_MakeFile_add_var(makefile, "CFC_DIR",
-                          "$(BASE_DIR)" DIR_SEP "clownfish" DIR_SEP "compiler"
-                          DIR_SEP "c");
-    chaz_MakeFile_add_var(makefile, "SNOWSTEM_DIR",
-                          "$(MODULES_DIR)" DIR_SEP "analysis" DIR_SEP
-                          "snowstem" DIR_SEP "source");
-    chaz_MakeFile_add_var(makefile, "SNOWSTOP_DIR",
-                          "$(MODULES_DIR)" DIR_SEP "analysis" DIR_SEP
-                          "snowstop" DIR_SEP "source");
-    chaz_MakeFile_add_var(makefile, "UTF8PROC_DIR",
-                          "$(MODULES_DIR)" DIR_SEP "unicode" DIR_SEP
-                          "utf8proc");
-
-    /* File extensions */
-
-    chaz_MakeFile_add_var(makefile, "EXE_EXT", exe_ext);
-    chaz_MakeFile_add_var(makefile, "OBJ_EXT", obj_ext);
 
     /* C compiler */
 
     chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc());
 
-    makefile_cflags = chaz_CFlags_new(cflags_style);
-    S_add_common_cflags(makefile_cflags);
+    makefile_cflags = chaz_CC_new_cflags();
 
+    chaz_CFlags_enable_optimization(makefile_cflags);
     chaz_CFlags_disable_strict_aliasing(makefile_cflags);
     chaz_CFlags_compile_shared_library(makefile_cflags);
     chaz_CFlags_hide_symbols(makefile_cflags);
@@ -6537,16 +6795,11 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     }
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(SRC_DIR)");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(CORE_DIR)");
-    chaz_CFlags_add_include_dir(makefile_cflags,
-                                "$(AUTOGEN_DIR)" DIR_SEP "include");
-    chaz_CFlags_add_include_dir(makefile_cflags,
-                                "$(SNOWSTEM_DIR)" DIR_SEP "include");
-    chaz_CFlags_add_include_dir(makefile_cflags,
-                                "$(MODULES_DIR)" DIR_SEP "unicode" DIR_SEP
-                                "ucd");
-    chaz_CFlags_add_include_dir(makefile_cflags, "$(UTF8PROC_DIR)");
+    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);
 
     var = chaz_MakeFile_add_var(makefile, "CFLAGS", NULL);
     chaz_MakeVar_append(var, chaz_CFlags_get_string(extra_cflags));
@@ -6560,129 +6813,109 @@ S_write_makefile(struct chaz_CLIArgs *args) {
     var = chaz_MakeFile_add_var(makefile, "LUCY_OBJS", NULL);
     sfc.var = var;
 
-    sfc.dir = "$(SRC_DIR)";
-    chaz_Make_list_files("src", "c", S_source_file_callback, &sfc);
+    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);
 
-    scratch = (char*)malloc(strlen(base_dir) + 20);
-    sprintf(scratch, "%s" DIR_SEP "core", base_dir);
-    sfc.dir = "$(CORE_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
-    free(scratch);
-    chaz_MakeVar_append(var, "$(CORE_DIR)" DIR_SEP "Lucy" DIR_SEP "Util"
-                        DIR_SEP "Json" DIR_SEP "JsonParser$(OBJ_EXT)");
-
-    scratch = (char*)malloc(strlen(base_dir) + 80);
-    sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "analysis" DIR_SEP
-            "snowstem" DIR_SEP "source", base_dir);
-    sfc.dir = "$(SNOWSTEM_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
-    free(scratch);
-
-    scratch = (char*)malloc(strlen(base_dir) + 80);
-    sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "analysis" DIR_SEP
-            "snowstop" DIR_SEP "source", base_dir);
-    sfc.dir = "$(SNOWSTOP_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
+    scratch = chaz_Util_join("", json_parser, obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
     free(scratch);
 
-    scratch = (char*)malloc(strlen(base_dir) + 80);
-    sprintf(scratch, "%s" DIR_SEP "modules" DIR_SEP "unicode" DIR_SEP
-            "utf8proc", base_dir);
-    sfc.dir = "$(UTF8PROC_DIR)";
-    chaz_Make_list_files(scratch, "c", S_source_file_callback, &sfc);
+    scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep,
+                             "parcel", obj_ext, NULL);
+    chaz_MakeVar_append(var, scratch);
     free(scratch);
 
-    chaz_MakeVar_append(var, "$(AUTOGEN_DIR)" DIR_SEP "source" DIR_SEP
-                        "parcel$(OBJ_EXT)");
+    /* Clownfish header files */
 
-    /* Executables */
+    var = chaz_MakeFile_add_var(makefile, "CLOWNFISH_HEADERS", NULL);
+    sfc.var = var;
 
-    chaz_MakeFile_add_var(makefile, "LEMON_EXE",
-                          "$(LEMON_DIR)" DIR_SEP "lemon$(EXE_EXT)");
-    chaz_MakeFile_add_var(makefile, "CFC_EXE",
-                          "$(CFC_DIR)" DIR_SEP "cfc$(EXE_EXT)");
-    chaz_MakeFile_add_var(makefile, "TEST_LUCY_EXE",
-                          "t" DIR_SEP "test_lucy$(EXE_EXT)");
+    chaz_Make_list_files(core_dir, "cfh", S_cfh_file_callback, &sfc);
 
     /* Rules */
 
-    shared_lib = chaz_CC_shared_lib_file("lucy");
-    chaz_MakeFile_add_rule(makefile, "all", shared_lib);
+    lib = chaz_SharedLib_new("lucy", lucy_version, lucy_major_version);
+    lib_filename = chaz_SharedLib_filename(lib);
+    chaz_MakeFile_add_rule(makefile, "all", lib_filename);
 
-    lemon_cflags = chaz_CFlags_new(cflags_style);
-    S_add_common_cflags(lemon_cflags);
-    chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)",
-                                   "$(LEMON_DIR)" DIR_SEP "lemon.c",
-                                   lemon_cflags);
-    chaz_CFlags_destroy(lemon_cflags);
+    chaz_MakeFile_add_lemon_exe(makefile, lemon_dir);
+    chaz_MakeFile_add_lemon_grammar(makefile, json_parser);
 
     /*
      * CFC also builds LEMON_EXE, so it might be built twice at the same time
      * in parallel builds. Adding LEMON_EXE as prereq of CFC_EXE avoids this.
      */
-    rule = chaz_MakeFile_add_rule(makefile, "$(CFC_EXE)", "$(LEMON_EXE)");
-    chaz_MakeRule_add_make_command(rule, "$(CFC_DIR)", NULL);
+    rule = chaz_MakeFile_add_rule(makefile, cfc_exe, "$(LEMON_EXE)");
+    chaz_MakeRule_add_make_command(rule, cfc_dir, NULL);
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(AUTOGEN_DIR)", "$(CFC_EXE)");
-    chaz_MakeRule_add_command(rule, "$(CFC_EXE) --source=$(CORE_DIR) "
-                              "--dest=$(AUTOGEN_DIR) --header=cfc_header");
-
-    rule = chaz_MakeFile_add_rule(makefile, json_parser_c, NULL);
-    chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)");
-    chaz_MakeRule_add_prereq(rule, json_parser_y);
-    scratch = (char*)malloc(strlen(json_parser_y) + 20);
-    sprintf(scratch, "$(LEMON_EXE) -q %s", json_parser_y);
+    rule = chaz_MakeFile_add_rule(makefile, "autogen", cfc_exe);
+    chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
+    scratch = chaz_Util_join("", cfc_exe, " --source=", core_dir,
+                             " --dest=autogen --header=cfc_header", NULL);
     chaz_MakeRule_add_command(rule, scratch);
+    /* TODO: Find a way to touch the autogen directory on Windows. */
+    if (chaz_Make_shell_type() == CHAZ_OS_POSIX) {
+        chaz_MakeRule_add_command(rule, "touch autogen");
+    }
     free(scratch);
 
     /* Needed for parallel builds. */
-    rule = chaz_MakeFile_add_rule(makefile, "$(AUTOGEN_DIR)" DIR_SEP "source"
-                                  DIR_SEP "parcel.c", "$(AUTOGEN_DIR)");
+    scratch = chaz_Util_join(dir_sep, "autogen", "source", "parcel.c", NULL);
+    rule = chaz_MakeFile_add_rule(makefile, scratch, "autogen");
+    free(scratch);
 
-    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", NULL);
-    chaz_MakeRule_add_prereq(rule, json_parser_c);
-    chaz_MakeRule_add_prereq(rule, "$(AUTOGEN_DIR)");
+    rule = chaz_MakeFile_add_rule(makefile, "$(LUCY_OBJS)", "autogen");
+    /*
+     * 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);
+    chaz_MakeRule_add_prereq(rule, scratch);
+    free(scratch);
 
-    link_flags = chaz_CFlags_new(cflags_style);
+    link_flags = chaz_CC_new_cflags();
     if (chaz_CC_msvc_version_num()) {
         chaz_CFlags_append(link_flags, "/nologo");
     }
-    math_library = chaz_Floats_math_library();
     if (math_library) {
-        chaz_CFlags_add_library(link_flags, math_library);
+        chaz_CFlags_add_external_library(link_flags, math_library);
     }
     if (chaz_HeadCheck_check_header("pcre.h")) {
-        chaz_CFlags_add_library(link_flags, "pcre");
+        chaz_CFlags_add_external_library(link_flags, "pcre");
     }
     if (args->code_coverage) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
-    chaz_MakeFile_add_shared_lib(makefile, "lucy", "$(LUCY_OBJS)", link_flags);
+    chaz_MakeFile_add_shared_lib(makefile, lib, "$(LUCY_OBJS)", link_flags);
     chaz_CFlags_destroy(link_flags);
 
-    test_cflags = chaz_CFlags_new(cflags_style);
-    S_add_common_cflags(test_cflags);
+    test_cflags = chaz_CC_new_cflags();
+    chaz_CFlags_enable_optimization(test_cflags);
     chaz_CFlags_add_include_dir(test_cflags, ".");
-    chaz_CFlags_add_include_dir(test_cflags,
-                                "$(AUTOGEN_DIR)" DIR_SEP "include");
-    chaz_CFlags_add_library_path(test_cflags, ".");
-    chaz_CFlags_add_library(test_cflags, "lucy");
-    rule = chaz_MakeFile_add_compiled_exe(makefile, "$(TEST_LUCY_EXE)",
-                                          "t" DIR_SEP "test_lucy.c",
+    chaz_CFlags_add_include_dir(test_cflags, autogen_inc_dir);
+    chaz_CFlags_add_library(link_flags, lib);
+    scratch = chaz_Util_join(dir_sep, "t", "test_lucy.c", NULL);
+    rule = chaz_MakeFile_add_compiled_exe(makefile, test_lucy_exe, scratch,
                                           test_cflags);
-    chaz_MakeRule_add_prereq(rule, shared_lib);
+    free(scratch);
+    chaz_MakeRule_add_prereq(rule, lib_filename);
     chaz_CFlags_destroy(test_cflags);
 
-    rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_LUCY_EXE)");
-    test_command = "$(TEST_LUCY_EXE)";
+    rule = chaz_MakeFile_add_rule(makefile, "test", test_lucy_exe);
     if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
-        test_command = "LD_LIBRARY_PATH=. $(TEST_LUCY_EXE)";
+        test_command = chaz_Util_join(" ", "LD_LIBRARY_PATH=.", test_lucy_exe,
+                                      NULL);
+    }
+    else {
+        test_command = chaz_Util_strdup(test_lucy_exe);
     }
     chaz_MakeRule_add_command(rule, test_command);
 
     if (args->code_coverage) {
-        rule = chaz_MakeFile_add_rule(makefile, "coverage",
-                                      "$(TEST_LUCY_EXE)");
+        rule = chaz_MakeFile_add_rule(makefile, "coverage", test_lucy_exe);
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --zerocounters"
@@ -6716,24 +6949,37 @@ S_write_makefile(struct chaz_CLIArgs *args) {
         chaz_MakeRule_add_rm_command(clean_rule, "$(LUCY_OBJS)");
     }
 
-    chaz_MakeRule_add_rm_command(clean_rule, json_parser_h);
-    chaz_MakeRule_add_rm_command(clean_rule, json_parser_c);
-    chaz_MakeRule_add_recursive_rm_command(clean_rule, "$(AUTOGEN_DIR)");
+    chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen");
 
     if (args->code_coverage) {
         chaz_MakeRule_add_rm_command(clean_rule, "lucy.info");
         chaz_MakeRule_add_recursive_rm_command(clean_rule, "coverage");
     }
 
-    chaz_MakeRule_add_make_command(clean_rule, "$(CFC_DIR)", "clean");
+    chaz_MakeRule_add_make_command(clean_rule, cfc_dir, "clean");
 
     distclean_rule = chaz_MakeFile_distclean_rule(makefile);
-    chaz_MakeRule_add_make_command(distclean_rule, "$(CFC_DIR)", "distclean");
+    chaz_MakeRule_add_make_command(distclean_rule, cfc_dir, "distclean");
 
     chaz_MakeFile_write(makefile);
 
     chaz_MakeFile_destroy(makefile);
-    free(shared_lib);
+    chaz_SharedLib_destroy(lib);
+    free(core_dir);
+    free(lemon_dir);
+    free(cfc_dir);
+    free(modules_dir);
+    free(snowstem_dir);
+    free(snowstop_dir);
+    free(ucd_dir);
+    free(utf8proc_dir);
+    free(json_parser);
+    free(cfc_exe);
+    free(test_lucy_exe);
+    free(autogen_inc_dir);
+    free(snowstem_inc_dir);
+    free(lib_filename);
+    free(test_command);
 }
 
 int main(int argc, const char **argv) {