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