Repository: lucy-clownfish Updated Branches: refs/heads/master 27177dfc3 -> c3aadd5b8
Regenerate charmonizer.c Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/c3aadd5b Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/c3aadd5b Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/c3aadd5b Branch: refs/heads/master Commit: c3aadd5b83a485f13aa1486daaf1264081b0dc26 Parents: 98bb6c2 Author: Nick Wellnhofer <[email protected]> Authored: Wed Oct 29 22:15:51 2014 +0100 Committer: Nick Wellnhofer <[email protected]> Committed: Sun Nov 30 17:11:01 2014 +0100 ---------------------------------------------------------------------- compiler/common/charmonizer.c | 162 ++++++----- runtime/common/charmonizer.c | 580 ++++++++++++++++++++++--------------- 2 files changed, 442 insertions(+), 300 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c3aadd5b/compiler/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/compiler/common/charmonizer.c b/compiler/common/charmonizer.c index ea0a1f6..2a24d21 100644 --- a/compiler/common/charmonizer.c +++ b/compiler/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")) { @@ -7704,6 +7709,58 @@ typedef struct SourceFileContext { } SourceFileContext; static void +S_add_compiler_flags(struct chaz_CLI *cli); + +static void +S_write_makefile(struct chaz_CLI *cli); + +static void +S_source_file_callback(const char *dir, char *file, void *context); + +int main(int argc, const char **argv) { + /* Initialize. */ + chaz_CLI *cli + = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment"); + chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]"); + { + int result = chaz_Probe_parse_cli_args(argc, argv, cli); + if (!result) { + chaz_Probe_die_usage(); + } + chaz_Probe_init(cli); + S_add_compiler_flags(cli); + } + + /* Define stdint types in charmony.h. */ + chaz_ConfWriter_append_conf("#define CHY_EMPLOY_INTEGERTYPES\n\n"); + chaz_ConfWriter_append_conf("#define CHY_EMPLOY_INTEGERLITERALS\n\n"); + + /* Run probe modules. */ + chaz_BuildEnv_run(); + chaz_DirManip_run(); + chaz_Headers_run(); + chaz_AtomicOps_run(); + chaz_FuncMacro_run(); + chaz_Booleans_run(); + chaz_Integers_run(); + chaz_Strings_run(); + chaz_Memory_run(); + chaz_SymbolVisibility_run(); + chaz_UnusedVars_run(); + chaz_VariadicMacros_run(); + + if (chaz_CLI_defined(cli, "enable-makefile")) { + S_write_makefile(cli); + } + + /* 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(); @@ -7739,34 +7796,6 @@ S_add_compiler_flags(struct chaz_CLI *cli) { } 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; - - if (strcmp(file, "CFCParseHeader.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); - return; - } - file[file_len-2] = '\0'; - - 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); - } - else { - chaz_MakeVar_append(sfc->common_objs, obj_file); - } - - free(obj_file); -} - -static void S_write_makefile(struct chaz_CLI *cli) { SourceFileContext sfc; @@ -7923,47 +7952,32 @@ S_write_makefile(struct chaz_CLI *cli) { free(test_cfc_exe); } -int main(int argc, const char **argv) { - /* Initialize. */ - chaz_CLI *cli - = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment"); - chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]"); - { - int result = chaz_Probe_parse_cli_args(argc, argv, cli); - if (!result) { - chaz_Probe_die_usage(); - } - chaz_Probe_init(cli); - S_add_compiler_flags(cli); - } - - /* Define stdint types in charmony.h. */ - chaz_ConfWriter_append_conf("#define CHY_EMPLOY_INTEGERTYPES\n\n"); - chaz_ConfWriter_append_conf("#define CHY_EMPLOY_INTEGERLITERALS\n\n"); +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; - /* Run probe modules. */ - chaz_BuildEnv_run(); - chaz_DirManip_run(); - chaz_Headers_run(); - chaz_AtomicOps_run(); - chaz_FuncMacro_run(); - chaz_Booleans_run(); - chaz_Integers_run(); - chaz_Strings_run(); - chaz_Memory_run(); - chaz_SymbolVisibility_run(); - chaz_UnusedVars_run(); - chaz_VariadicMacros_run(); + if (strcmp(file, "CFCParseHeader.c") == 0) { return; } - if (chaz_CLI_defined(cli, "enable-makefile")) { - S_write_makefile(cli); + /* Strip extension */ + if (file_len <= 2 || memcmp(file + file_len - 2, ".c", 2) != 0) { + chaz_Util_warn("Unexpected source file name: %s", file); + return; } + file[file_len-2] = '\0'; - /* Clean up. */ - chaz_CLI_destroy(cli); - chaz_Probe_clean_up(); + 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); + } + else { + chaz_MakeVar_append(sfc->common_objs, obj_file); + } - return 0; + free(obj_file); } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c3aadd5b/runtime/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c index a2696e3..133494b 100644 --- a/runtime/common/charmonizer.c +++ b/runtime/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")) { @@ -7714,6 +7719,26 @@ chaz_VariadicMacros_run(void) { /* #include "Charmonizer/Core/ConfWriterPerl.h" */ /* #include "Charmonizer/Core/ConfWriterRuby.h" */ +typedef struct cfish_MakeFile { + chaz_MakeFile *makefile; + chaz_CLI *cli; + + /* Directories and files. */ + const char *base_dir; + const char *host_src_dir; + char *core_dir; + char *autogen_src_dir; + char *autogen_inc_dir; + char *autogen_target; + const char **autogen_src_files; + + /* Libraries. */ + chaz_Lib *shared_lib; + chaz_Lib *static_lib; + char *shared_lib_filename; + char *static_lib_filename; +} cfish_MakeFile; + typedef struct SourceFileContext { chaz_MakeVar *var; } SourceFileContext; @@ -7722,6 +7747,113 @@ static const char cfish_version[] = "0.4.0"; static const char cfish_major_version[] = "0.4"; static void +S_add_compiler_flags(struct chaz_CLI *cli); + +static cfish_MakeFile* +cfish_MakeFile_new(chaz_CLI *cli); + +static void +cfish_MakeFile_destroy(cfish_MakeFile *self); + +static void +cfish_MakeFile_write(cfish_MakeFile *self); + +static void +cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self); + +static void +cfish_MakeFile_write_c_test_rules(cfish_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, "disable-threads", "whether to disable threads", + CHAZ_CLI_NO_ARG); + 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, DirManip and LargeFiles are only needed for + * the Charmonizer tests. + */ + chaz_BuildEnv_run(); + chaz_DirManip_run(); + chaz_Headers_run(); + chaz_AtomicOps_run(); + chaz_FuncMacro_run(); + chaz_Booleans_run(); + chaz_Integers_run(); + chaz_Floats_run(); + chaz_LargeFiles_run(); + chaz_Memory_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")) { + cfish_MakeFile *mf = cfish_MakeFile_new(cli); + cfish_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); + cfish_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(); @@ -7766,72 +7898,78 @@ S_add_compiler_flags(struct chaz_CLI *cli) { } } -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_c_file_callback(const char *dir, char *file, void *context) { - SourceFileContext *sfc = (SourceFileContext*)context; +static cfish_MakeFile* +cfish_MakeFile_new(chaz_CLI *cli) { 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; - /* Strip extension */ - if (!S_ends_with(file, ".c")) { - chaz_Util_warn("Unexpected C filename: %s", file); - return; + cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile)); + + self->makefile = chaz_MakeFile_new(); + self->cli = cli; + + self->base_dir = ".."; + self->core_dir = chaz_Util_join(dir_sep, self->base_dir, "core", NULL); + 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->autogen_target + = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL); + + if (chaz_CLI_defined(cli, "enable-perl")) { + static const char *perl_autogen_src_files[] = { + "boot", + "callbacks", + "cfish_parcel", + "testcfish_parcel", + NULL + }; + self->host_src_dir = "xs"; + self->autogen_src_files = perl_autogen_src_files; + } + else { + static const char *c_autogen_src_files[] = { + "cfish_parcel", + "testcfish_parcel", + NULL + }; + self->host_src_dir = "src"; + self->autogen_src_files = c_autogen_src_files; } - 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); + self->shared_lib = chaz_Lib_new("cfish", chaz_Lib_SHARED, cfish_version, + cfish_major_version); + self->static_lib = chaz_Lib_new("cfish", chaz_Lib_STATIC, cfish_version, + cfish_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; +cfish_MakeFile_destroy(cfish_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->autogen_target); - cfh_file = chaz_Util_join(dir_sep, dir, file, NULL); - chaz_MakeVar_append(sfc->var, cfh_file); - free(cfh_file); + 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(struct chaz_CLI *cli) { +cfish_MakeFile_write(cfish_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(); - char *core_dir = chaz_Util_join(dir_sep, base_dir, "core", NULL); - char *cfc_dir = chaz_Util_join(dir_sep, base_dir, "..", "compiler", "c", - NULL); - char *cfc_exe = chaz_Util_join("", cfc_dir, dir_sep, "cfc", exe_ext, - NULL); - char *test_cfish_exe = chaz_Util_join("", "t", dir_sep, "test_cfish", - 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); - - chaz_MakeFile *makefile; chaz_MakeVar *var; chaz_MakeRule *rule; chaz_MakeRule *clean_rule; @@ -7840,27 +7978,20 @@ S_write_makefile(struct 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 *math_library = chaz_Floats_math_library(); - char *shared_lib_filename; - char *static_lib_filename; - char *test_command; - char *scratch; + const char *math_library = chaz_Floats_math_library(); + 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(); @@ -7868,14 +7999,15 @@ S_write_makefile(struct 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, autogen_inc_dir); + chaz_CFlags_add_include_dir(makefile_cflags, self->host_src_dir); + chaz_CFlags_add_include_dir(makefile_cflags, self->autogen_inc_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()); @@ -7884,87 +8016,136 @@ S_write_makefile(struct chaz_CLI *cli) { /* Object files */ - var = chaz_MakeFile_add_var(makefile, "CLOWNFISH_OBJS", NULL); + var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_OBJS", NULL); sfc.var = var; + 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("src", "c", S_c_file_callback, &sfc); - chaz_Make_list_files(core_dir, "c", S_c_file_callback, &sfc); - - scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep, - "cfish_parcel", obj_ext, NULL); - chaz_MakeVar_append(var, scratch); - free(scratch); - scratch = chaz_Util_join("", "autogen", dir_sep, "source", dir_sep, - "testcfish_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("cfish", chaz_Lib_SHARED, cfish_version, - cfish_major_version); - shared_lib_filename = chaz_Lib_filename(shared_lib); - static_lib = chaz_Lib_new("cfish", chaz_Lib_STATIC, cfish_version, - cfish_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); - rule = chaz_MakeFile_add_rule(makefile, cfc_exe, NULL); - chaz_MakeRule_add_make_command(rule, cfc_dir, NULL); - - rule = chaz_MakeFile_add_rule(makefile, autogen_target, 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); - free(scratch); + if (!chaz_CLI_defined(self->cli, "enable-perl")) { + cfish_MakeFile_write_c_cfc_rules(self); + } /* Needed for parallel builds. */ - scratch = chaz_Util_join(dir_sep, "autogen", "source", "cfish_parcel.c", - NULL); - rule = chaz_MakeFile_add_rule(makefile, scratch, autogen_target); - scratch = chaz_Util_join(dir_sep, "autogen", "source", - "testcfish_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); + chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target); + free(path); + } - chaz_MakeFile_add_rule(makefile, "$(CLOWNFISH_OBJS)", autogen_target); + chaz_MakeFile_add_rule(self->makefile, "$(CLOWNFISH_OBJS)", + self->autogen_target); link_flags = chaz_CC_new_cflags(); chaz_CFlags_enable_debugging(link_flags); if (math_library) { chaz_CFlags_add_external_library(link_flags, math_library); } - if (chaz_CLI_defined(cli, "enable-coverage")) { + if (chaz_CLI_defined(self->cli, "enable-coverage")) { chaz_CFlags_enable_code_coverage(link_flags); } - chaz_MakeFile_add_shared_lib(makefile, shared_lib, "$(CLOWNFISH_OBJS)", - link_flags); + chaz_MakeFile_add_shared_lib(self->makefile, self->shared_lib, + "$(CLOWNFISH_OBJS)", link_flags); chaz_CFlags_destroy(link_flags); - chaz_MakeFile_add_static_lib(makefile, static_lib, "$(CLOWNFISH_OBJS)"); + chaz_MakeFile_add_static_lib(self->makefile, self->static_lib, + "$(CLOWNFISH_OBJS)"); + + if (!chaz_CLI_defined(self->cli, "enable-perl")) { + cfish_MakeFile_write_c_test_rules(self); + } + + clean_rule = chaz_MakeFile_clean_rule(self->makefile); + chaz_MakeRule_add_rm_command(clean_rule, "$(CLOWNFISH_OBJS)"); + chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen"); + + chaz_MakeFile_write(self->makefile); +} + +static void +cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) { + SourceFileContext sfc; + chaz_MakeVar *var; + chaz_MakeRule *rule; + const char *dir_sep = chaz_OS_dir_sep(); + const char *exe_ext = chaz_OS_exe_ext(); + + char *cfc_dir; + char *cfc_exe; + char *cfc_command; + + cfc_dir = chaz_Util_join(dir_sep, self->base_dir, "..", "compiler", "c", + NULL); + cfc_exe = chaz_Util_join("", cfc_dir, dir_sep, "cfc", exe_ext, NULL); + + rule = chaz_MakeFile_add_rule(self->makefile, cfc_exe, NULL); + chaz_MakeRule_add_make_command(rule, cfc_dir, NULL); + + var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS", NULL); + sfc.var = var; + chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, &sfc); + + rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, cfc_exe); + chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)"); + cfc_command = chaz_Util_join("", cfc_exe, " --source=", self->core_dir, + " --dest=autogen --header=cfc_header", NULL); + chaz_MakeRule_add_command(rule, cfc_command); + + rule = chaz_MakeFile_clean_rule(self->makefile); + chaz_MakeRule_add_make_command(rule, cfc_dir, "clean"); + + rule = chaz_MakeFile_distclean_rule(self->makefile); + chaz_MakeRule_add_make_command(rule, cfc_dir, "distclean"); + + free(cfc_dir); + free(cfc_exe); + free(cfc_command); +} + +static void +cfish_MakeFile_write_c_test_rules(cfish_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_cfish_exe; + char *test_cfish_c; + char *test_command; + + test_cfish_exe = chaz_Util_join("", "t", dir_sep, "test_cfish", exe_ext, + NULL); + test_cfish_c = chaz_Util_join(dir_sep, "t", "test_cfish.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); - scratch = chaz_Util_join(dir_sep, "t", "test_cfish.c", NULL); - rule = chaz_MakeFile_add_compiled_exe(makefile, test_cfish_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); + rule = chaz_MakeFile_add_compiled_exe(self->makefile, test_cfish_exe, + test_cfish_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_cfish_exe); + /* TODO: This should be added by Charmonizer. */ + if (chaz_Probe_msvc_version_num()) { + rule = chaz_MakeFile_clean_rule(self->makefile); + chaz_MakeRule_add_rm_command(rule, "test_cfish.obj"); + } + + rule = chaz_MakeFile_add_rule(self->makefile, "test", test_cfish_exe); if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) { test_command = chaz_Util_join(" ", "LD_LIBRARY_PATH=.", test_cfish_exe, NULL); @@ -7974,8 +8155,9 @@ S_write_makefile(struct 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_cfish_exe); + if (chaz_CLI_defined(self->cli, "enable-coverage")) { + rule = chaz_MakeFile_add_rule(self->makefile, "coverage", + test_cfish_exe); chaz_MakeRule_add_command(rule, "lcov" " --zerocounters" @@ -7993,113 +8175,59 @@ S_write_makefile(struct chaz_CLI *cli) { " --branch-coverage" " --output-directory coverage" " clownfish.info"); - } - - clean_rule = chaz_MakeFile_clean_rule(makefile); - chaz_MakeRule_add_rm_command(clean_rule, "$(CLOWNFISH_OBJS)"); - chaz_MakeRule_add_recursive_rm_command(clean_rule, "autogen"); - if (chaz_CLI_defined(cli, "enable-coverage")) { - chaz_MakeRule_add_rm_command(clean_rule, "clownfish.info"); - chaz_MakeRule_add_recursive_rm_command(clean_rule, "coverage"); - } - - if (chaz_Probe_msvc_version_num()) { - chaz_MakeRule_add_rm_command(clean_rule, "test_cfish.obj"); + rule = chaz_MakeFile_clean_rule(self->makefile); + chaz_MakeRule_add_rm_command(rule, "clownfish.info"); + chaz_MakeRule_add_recursive_rm_command(rule, "coverage"); } - 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_MakeFile_write(makefile); - - chaz_MakeFile_destroy(makefile); - chaz_Lib_destroy(shared_lib); - chaz_Lib_destroy(static_lib); - free(core_dir); - free(cfc_dir); - free(cfc_exe); free(test_cfish_exe); - free(autogen_inc_dir); - free(autogen_target); - free(shared_lib_filename); - free(static_lib_filename); + free(test_cfish_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, "disable-threads", "whether to disable threads", - CHAZ_CLI_NO_ARG); - 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, DirManip and LargeFiles are only needed for - * the Charmonizer tests. - */ - chaz_BuildEnv_run(); - chaz_DirManip_run(); - chaz_Headers_run(); - chaz_AtomicOps_run(); - chaz_FuncMacro_run(); - chaz_Booleans_run(); - chaz_Integers_run(); - chaz_Floats_run(); - chaz_LargeFiles_run(); - chaz_Memory_run(); - chaz_VariadicMacros_run(); + 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; }
