Updated Branches: refs/heads/c-bindings-cfc 4cbd991ec -> 369a995c4
Regenerate charmonizer.c Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/369a995c Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/369a995c Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/369a995c Branch: refs/heads/c-bindings-cfc Commit: 369a995c4433117a4fe44aec07d4952c8f38fb25 Parents: fbb552d Author: Nick Wellnhofer <[email protected]> Authored: Sun Feb 10 22:11:22 2013 +0100 Committer: Nick Wellnhofer <[email protected]> Committed: Tue Feb 12 21:10:23 2013 +0100 ---------------------------------------------------------------------- clownfish/compiler/common/charmonizer.c | 292 ++++++++++++++++++++++---- clownfish/runtime/common/charmonizer.c | 285 ++++++++++++++++++++++---- common/charmonizer.c | 291 ++++++++++++++++++++++---- 3 files changed, 749 insertions(+), 119 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/369a995c/clownfish/compiler/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/clownfish/compiler/common/charmonizer.c b/clownfish/compiler/common/charmonizer.c index 70775c3..d687b02 100644 --- a/clownfish/compiler/common/charmonizer.c +++ b/clownfish/compiler/common/charmonizer.c @@ -93,6 +93,16 @@ chaz_CC_set_warnings_as_errors(const int flag); void chaz_CC_add_extra_cflags(const char *); +/* Add include dir to extra cflags. + */ +void +chaz_CC_add_include_dir(const char *dir); + +/* Set optimization level. + */ +void +chaz_CC_set_optimization_level(const char *level); + /* Accessor for the compiler executable's string representation. */ const char* @@ -109,25 +119,25 @@ const char* chaz_CC_get_extra_cflags(void); int -chaz_CC_gcc_version_num(); +chaz_CC_gcc_version_num(void); const char* -chaz_CC_gcc_version(); +chaz_CC_gcc_version(void); int -chaz_CC_compiler_is_msvc(void); +chaz_CC_msvc_version_num(void); const char* -chaz_CC_link_command(); +chaz_CC_link_command(void); const char* -chaz_CC_link_flags(); +chaz_CC_link_flags(void); const char* -chaz_CC_link_shared_obj_flag(); +chaz_CC_link_shared_obj_flag(void); const char* -chaz_CC_link_output_flag(); +chaz_CC_link_output_flag(void); #endif /* H_CHAZ_COMPILER */ @@ -351,6 +361,15 @@ typedef struct chaz_MakeRule chaz_MakeRule; typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context); void +chaz_Make_init(void); + +void +chaz_Make_clean_up(void); + +const char* +chaz_Make_get_make(void); + +void chaz_Make_list_files(const char *dir, const char *ext, chaz_Make_list_files_callback_t callback, void *context); @@ -631,10 +650,10 @@ chaz_Probe_gcc_version_num(void); const char* chaz_Probe_gcc_version(void); -/* Returns true if the compiler is MSVC. +/* Return the integer version of MSVC defined by _MSC_VER */ int -chaz_Probe_compiler_is_msvc(void); +chaz_Probe_msvc_version_num(void); #endif /* Include guard. */ @@ -1245,6 +1264,34 @@ chaz_CC_add_extra_cflags(const char *flags) { } } +void +chaz_CC_add_include_dir(const char *dir) { + size_t size = strlen(chaz_CC.include_flag) + strlen(dir) + 1; + char *flag = (char*)malloc(size); + sprintf(flag, "%s%s", chaz_CC.include_flag, dir); + chaz_CC_add_extra_cflags(flag); + free(flag); +} + +void +chaz_CC_set_optimization_level(const char *level) { + const char *opt_flag; + char *flag; + size_t size; + + if (chaz_CC.intval__MSC_VER) { + opt_flag = "/O"; + } + else { + opt_flag = "-O"; + } + size = strlen(opt_flag) + strlen(level) + 1; + flag = (char*)malloc(size); + sprintf(flag, "%s%s", opt_flag, level); + chaz_CC_add_extra_cflags(flag); + free(flag); +} + const char* chaz_CC_get_cc(void) { return chaz_CC.cc_command; @@ -1273,8 +1320,8 @@ chaz_CC_gcc_version(void) { } int -chaz_CC_compiler_is_msvc(void) { - return !!chaz_CC.intval__MSC_VER; +chaz_CC_msvc_version_num(void) { + return chaz_CC.intval__MSC_VER; } const char* @@ -2449,6 +2496,110 @@ struct chaz_MakeFile { size_t num_cleanups; }; +/* Static vars. */ +static struct { + char *make_command; + int is_gnu_make; + int is_nmake; +} chaz_Make = { + NULL, + 0, 0 +}; + +/* Detect make command. + * + * The argument list must be a NULL-terminated series of different spellings + * of `make`, which will be auditioned in the order they are supplied. Here + * are several possibilities: + * + * make + * gmake + * nmake + * dmake + */ +static int +chaz_Make_detect(const char *make1, ...); + +static int +chaz_Make_audition(const char *make); + +void +chaz_Make_init(void) { + const char *make; + + chaz_Make_detect("make", "gmake", "nmake", "dmake", NULL); + make = chaz_Make.make_command; + + if (make) { + if (strcmp(make, "make") == 0 || strcmp(make, "gmake") == 0) { + /* TODO: Add a feature test for GNU make. */ + chaz_Make.is_gnu_make = 1; + } + else if (strcmp(make, "nmake") == 0) { + chaz_Make.is_nmake = 1; + } + } +} + +void +chaz_Make_clean_up(void) { + free(chaz_Make.make_command); +} + +const char* +chaz_Make_get_make(void) { + return chaz_Make.make_command; +} + +static int +chaz_Make_detect(const char *make1, ...) { + va_list args; + const char *candidate; + int found = 0; + const char makefile_content[] = "foo:\n\techo \"foo!\"\n"; + chaz_Util_write_file("_charm_Makefile", makefile_content); + + /* Audition candidates. */ + found = chaz_Make_audition(make1); + va_start(args, make1); + while (!found && (NULL != (candidate = va_arg(args, const char*)))) { + found = chaz_Make_audition(candidate); + } + va_end(args); + + chaz_Util_remove_and_verify("_charm_Makefile"); + + return found; +} + +static int +chaz_Make_audition(const char *make) { + int succeeded = 0; + const char pattern[] = "%s -f _charm_Makefile"; + size_t size = strlen(make) + sizeof(pattern) + 10; + char *command = (char*)malloc(size); + sprintf(command, pattern, make); + + chaz_Util_remove_and_verify("_charm_foo"); + chaz_OS_run_redirected(command, "_charm_foo"); + if (chaz_Util_can_open_file("_charm_foo")) { + size_t len; + char *content = chaz_Util_slurp_file("_charm_foo", &len); + if (NULL != strstr(content, "foo!")) { + succeeded = 1; + } + free(content); + } + chaz_Util_remove_and_verify("_charm_foo"); + + if (succeeded) { + chaz_Make.make_command = chaz_Util_strdup(make); + } + + free(command); + return succeeded; +} + chaz_MakeFile* chaz_MakeFile_new() { chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile)); @@ -2587,6 +2738,7 @@ chaz_MakeFile_add_shared_obj(chaz_MakeFile *makefile, const char *shared_obj, void chaz_MakeFile_write(chaz_MakeFile *makefile) { + int shell_type = chaz_OS_shell_type(); FILE *file; size_t i; @@ -2615,16 +2767,40 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) { } if (makefile->cleanups[0]) { - fprintf(file, "clean :\n\trm -f"); - for (i = 0; makefile->cleanups[i]; i++) { - char *cleanup = makefile->cleanups[i]; - fprintf(file, " \\\n\t %s", cleanup); + if (shell_type == CHAZ_OS_POSIX) { + fprintf(file, "clean :\n\trm -f"); + for (i = 0; makefile->cleanups[i]; i++) { + const char *cleanup = makefile->cleanups[i]; + fprintf(file, " \\\n\t %s", cleanup); + } + fprintf(file, "\n\n"); + } + else if (shell_type == CHAZ_OS_CMD_EXE) { + fprintf(file, "clean :\n"); + for (i = 0; makefile->cleanups[i]; i++) { + const char *cleanup = makefile->cleanups[i]; + fprintf(file, "\tfor %%i in (%s) do if exist %%i del /f %%i\n", + cleanup); + } + fprintf(file, "\n"); + } + else { + chaz_Util_die("Unsupported shell type: %d", shell_type); } - fprintf(file, "\n\n"); } fprintf(file, "distclean : clean\n"); - fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n"); + if (shell_type == CHAZ_OS_POSIX) { + fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n"); + } + else if (shell_type == CHAZ_OS_CMD_EXE) { + fprintf(file, + "\tfor %%i in (charmonizer charmony.h Makefile) do" + " if exist %%i del /f %%i\n\n"); + } + else { + chaz_Util_die("Unsupported shell type: %d", shell_type); + } fclose(file); } @@ -2706,20 +2882,45 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command) { void chaz_MakeRule_add_command_make(chaz_MakeRule *rule, const char *dir, const char *target) { + const char *make = chaz_Make.make_command; char *command; - if (!target) { + if (chaz_Make.is_gnu_make) { + if (!target) { + size_t size = strlen(dir) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) -C %s", dir); + } + else { + size_t size = strlen(dir) + strlen(target) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) -C %s %s", dir, target); + } + chaz_MakeRule_add_command(rule, command); + free(command); + } + else if (chaz_Make.is_nmake) { command = (char*)malloc(strlen(dir) + 20); - sprintf(command, "make -C %s", dir); + sprintf(command, "cd %s", dir); + chaz_MakeRule_add_command(rule, command); + free(command); + + if (!target) { + chaz_MakeRule_add_command(rule, "$(MAKE)"); + } + else { + size_t size = strlen(target) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) %s", target); + chaz_MakeRule_add_command(rule, command); + free(command); + } + + chaz_MakeRule_add_command(rule, "cd $(MAKEDIR)"); } else { - command = (char*)malloc(strlen(dir) + strlen(target) + 20); - sprintf(command, "make -C %s %s", dir, target); + chaz_Util_die("Couldn't find a supported 'make' utility."); } - - chaz_MakeRule_add_command(rule, command); - - free(command); } void @@ -3316,6 +3517,7 @@ chaz_Probe_init(struct chaz_CLIArgs *args) { chaz_CC_init(args->cc, args->cflags); chaz_ConfWriter_init(); chaz_HeadCheck_init(); + chaz_Make_init(); /* Enable output. */ if (args->charmony_h) { @@ -3345,6 +3547,7 @@ chaz_Probe_clean_up(void) { /* Dispatch various clean up routines. */ chaz_ConfWriter_clean_up(); chaz_CC_clean_up(); + chaz_Make_clean_up(); if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); } } @@ -3360,8 +3563,8 @@ chaz_Probe_gcc_version(void) { } int -chaz_Probe_compiler_is_msvc(void) { - return chaz_CC_compiler_is_msvc(); +chaz_Probe_msvc_version_num(void) { + return chaz_CC_msvc_version_num(); } /***************************************************************************/ @@ -4357,16 +4560,18 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) { /* Tell GCC explicitly to run with maximum options. */ chaz_CC_add_extra_cflags("-std=gnu99 -D_GNU_SOURCE"); } - else if (chaz_Probe_compiler_is_msvc()) { + else if (chaz_Probe_msvc_version_num()) { /* Compile as C++ under MSVC. */ - chaz_CC_add_extra_cflags("-TP"); + chaz_CC_add_extra_cflags("/TP"); /* Thwart stupid warnings. */ - chaz_CC_add_extra_cflags("-D_CRT_SECURE_NO_WARNINGS"); - chaz_CC_add_extra_cflags("-D_SCL_SECURE_NO_WARNINGS"); + chaz_CC_add_extra_cflags("/D_CRT_SECURE_NO_WARNINGS"); + chaz_CC_add_extra_cflags("/D_SCL_SECURE_NO_WARNINGS"); - /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */ - chaz_CC_add_extra_cflags("-Dfor=\"if(0);else for\""); + if (chaz_Probe_msvc_version_num() < 1300) { + /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */ + chaz_CC_add_extra_cflags("/Dfor=\"if(0);else for\""); + } } } @@ -4441,15 +4646,19 @@ S_write_makefile() { chaz_MakeFile_add_var(makefile, "EXE_EXT", exe_ext); chaz_MakeFile_add_var(makefile, "OBJ_EXT", obj_ext); - chaz_MakeFile_add_var(makefile, "LEMON_EXE", - "$(LEMON_DIR)" DIR_SEP "lemon$(EXE_EXT)"); + chaz_MakeFile_add_var(makefile, "CC", chaz_CC_get_cc()); + + chaz_CC_set_optimization_level("2"); + chaz_CC_add_include_dir("."); + chaz_CC_add_include_dir("$(INCLUDE_DIR)"); + chaz_CC_add_include_dir("$(SRC_DIR)"); var = chaz_MakeFile_add_var(makefile, "CFLAGS", NULL); chaz_MakeVar_append(var, chaz_CC_get_cflags()); chaz_MakeVar_append(var, chaz_CC_get_extra_cflags()); - chaz_MakeVar_append(var, "-I."); - chaz_MakeVar_append(var, "-I$(INCLUDE_DIR)"); - chaz_MakeVar_append(var, "-I$(SRC_DIR)"); + + chaz_MakeFile_add_var(makefile, "LEMON_OBJS", + "$(LEMON_DIR)" DIR_SEP "lemon$(OBJ_EXT)"); sfc.common_objs = chaz_MakeFile_add_var(makefile, "COMMON_OBJS", NULL); sfc.test_cfc_objs = chaz_MakeFile_add_var(makefile, "TEST_CFC_OBJS", NULL); @@ -4461,6 +4670,9 @@ S_write_makefile() { chaz_MakeVar_append(sfc.test_cfc_objs, "t" DIR_SEP "test_cfc$(OBJ_EXT)"); chaz_MakeFile_add_var(makefile, "CFC_OBJS", "cfc$(OBJ_EXT)"); + + chaz_MakeFile_add_var(makefile, "LEMON_EXE", + "$(LEMON_DIR)" DIR_SEP "lemon$(EXE_EXT)"); chaz_MakeFile_add_var(makefile, "CFC_EXE", "cfc$(EXE_EXT)"); chaz_MakeFile_add_var(makefile, "TEST_CFC_EXE", "t" DIR_SEP "test_cfc$(EXE_EXT)"); @@ -4469,8 +4681,7 @@ S_write_makefile() { chaz_MakeFile_add_rule(makefile, "all", "$(CFC_EXE)"); - rule = chaz_MakeFile_add_rule(makefile, "$(LEMON_EXE)", NULL); - chaz_MakeRule_add_command_make(rule, "$(LEMON_DIR)", NULL); + chaz_MakeFile_add_exe(makefile, "$(LEMON_EXE)", "$(LEMON_OBJS)"); rule = chaz_MakeFile_add_rule(makefile, parse_header_c, NULL); chaz_MakeRule_add_prereq(rule, "$(LEMON_EXE)"); @@ -4490,6 +4701,7 @@ S_write_makefile() { rule = chaz_MakeFile_add_rule(makefile, "test", "$(TEST_CFC_EXE)"); chaz_MakeRule_add_command(rule, "$(TEST_CFC_EXE)"); + chaz_MakeFile_add_to_cleanup(makefile, "$(LEMON_OBJS)"); chaz_MakeFile_add_to_cleanup(makefile, "$(COMMON_OBJS)"); chaz_MakeFile_add_to_cleanup(makefile, "$(CFC_OBJS)"); chaz_MakeFile_add_to_cleanup(makefile, "$(TEST_CFC_OBJS)"); http://git-wip-us.apache.org/repos/asf/lucy/blob/369a995c/clownfish/runtime/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/clownfish/runtime/common/charmonizer.c b/clownfish/runtime/common/charmonizer.c index fcb9609..23f5cb1 100644 --- a/clownfish/runtime/common/charmonizer.c +++ b/clownfish/runtime/common/charmonizer.c @@ -93,6 +93,16 @@ chaz_CC_set_warnings_as_errors(const int flag); void chaz_CC_add_extra_cflags(const char *); +/* Add include dir to extra cflags. + */ +void +chaz_CC_add_include_dir(const char *dir); + +/* Set optimization level. + */ +void +chaz_CC_set_optimization_level(const char *level); + /* Accessor for the compiler executable's string representation. */ const char* @@ -109,25 +119,25 @@ const char* chaz_CC_get_extra_cflags(void); int -chaz_CC_gcc_version_num(); +chaz_CC_gcc_version_num(void); const char* -chaz_CC_gcc_version(); +chaz_CC_gcc_version(void); int -chaz_CC_compiler_is_msvc(void); +chaz_CC_msvc_version_num(void); const char* -chaz_CC_link_command(); +chaz_CC_link_command(void); const char* -chaz_CC_link_flags(); +chaz_CC_link_flags(void); const char* -chaz_CC_link_shared_obj_flag(); +chaz_CC_link_shared_obj_flag(void); const char* -chaz_CC_link_output_flag(); +chaz_CC_link_output_flag(void); #endif /* H_CHAZ_COMPILER */ @@ -351,6 +361,15 @@ typedef struct chaz_MakeRule chaz_MakeRule; typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context); void +chaz_Make_init(void); + +void +chaz_Make_clean_up(void); + +const char* +chaz_Make_get_make(void); + +void chaz_Make_list_files(const char *dir, const char *ext, chaz_Make_list_files_callback_t callback, void *context); @@ -631,10 +650,10 @@ chaz_Probe_gcc_version_num(void); const char* chaz_Probe_gcc_version(void); -/* Returns true if the compiler is MSVC. +/* Return the integer version of MSVC defined by _MSC_VER */ int -chaz_Probe_compiler_is_msvc(void); +chaz_Probe_msvc_version_num(void); #endif /* Include guard. */ @@ -1527,6 +1546,34 @@ chaz_CC_add_extra_cflags(const char *flags) { } } +void +chaz_CC_add_include_dir(const char *dir) { + size_t size = strlen(chaz_CC.include_flag) + strlen(dir) + 1; + char *flag = (char*)malloc(size); + sprintf(flag, "%s%s", chaz_CC.include_flag, dir); + chaz_CC_add_extra_cflags(flag); + free(flag); +} + +void +chaz_CC_set_optimization_level(const char *level) { + const char *opt_flag; + char *flag; + size_t size; + + if (chaz_CC.intval__MSC_VER) { + opt_flag = "/O"; + } + else { + opt_flag = "-O"; + } + size = strlen(opt_flag) + strlen(level) + 1; + flag = (char*)malloc(size); + sprintf(flag, "%s%s", opt_flag, level); + chaz_CC_add_extra_cflags(flag); + free(flag); +} + const char* chaz_CC_get_cc(void) { return chaz_CC.cc_command; @@ -1555,8 +1602,8 @@ chaz_CC_gcc_version(void) { } int -chaz_CC_compiler_is_msvc(void) { - return !!chaz_CC.intval__MSC_VER; +chaz_CC_msvc_version_num(void) { + return chaz_CC.intval__MSC_VER; } const char* @@ -2731,6 +2778,110 @@ struct chaz_MakeFile { size_t num_cleanups; }; +/* Static vars. */ +static struct { + char *make_command; + int is_gnu_make; + int is_nmake; +} chaz_Make = { + NULL, + 0, 0 +}; + +/* Detect make command. + * + * The argument list must be a NULL-terminated series of different spellings + * of `make`, which will be auditioned in the order they are supplied. Here + * are several possibilities: + * + * make + * gmake + * nmake + * dmake + */ +static int +chaz_Make_detect(const char *make1, ...); + +static int +chaz_Make_audition(const char *make); + +void +chaz_Make_init(void) { + const char *make; + + chaz_Make_detect("make", "gmake", "nmake", "dmake", NULL); + make = chaz_Make.make_command; + + if (make) { + if (strcmp(make, "make") == 0 || strcmp(make, "gmake") == 0) { + /* TODO: Add a feature test for GNU make. */ + chaz_Make.is_gnu_make = 1; + } + else if (strcmp(make, "nmake") == 0) { + chaz_Make.is_nmake = 1; + } + } +} + +void +chaz_Make_clean_up(void) { + free(chaz_Make.make_command); +} + +const char* +chaz_Make_get_make(void) { + return chaz_Make.make_command; +} + +static int +chaz_Make_detect(const char *make1, ...) { + va_list args; + const char *candidate; + int found = 0; + const char makefile_content[] = "foo:\n\techo \"foo!\"\n"; + chaz_Util_write_file("_charm_Makefile", makefile_content); + + /* Audition candidates. */ + found = chaz_Make_audition(make1); + va_start(args, make1); + while (!found && (NULL != (candidate = va_arg(args, const char*)))) { + found = chaz_Make_audition(candidate); + } + va_end(args); + + chaz_Util_remove_and_verify("_charm_Makefile"); + + return found; +} + +static int +chaz_Make_audition(const char *make) { + int succeeded = 0; + const char pattern[] = "%s -f _charm_Makefile"; + size_t size = strlen(make) + sizeof(pattern) + 10; + char *command = (char*)malloc(size); + sprintf(command, pattern, make); + + chaz_Util_remove_and_verify("_charm_foo"); + chaz_OS_run_redirected(command, "_charm_foo"); + if (chaz_Util_can_open_file("_charm_foo")) { + size_t len; + char *content = chaz_Util_slurp_file("_charm_foo", &len); + if (NULL != strstr(content, "foo!")) { + succeeded = 1; + } + free(content); + } + chaz_Util_remove_and_verify("_charm_foo"); + + if (succeeded) { + chaz_Make.make_command = chaz_Util_strdup(make); + } + + free(command); + return succeeded; +} + chaz_MakeFile* chaz_MakeFile_new() { chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile)); @@ -2869,6 +3020,7 @@ chaz_MakeFile_add_shared_obj(chaz_MakeFile *makefile, const char *shared_obj, void chaz_MakeFile_write(chaz_MakeFile *makefile) { + int shell_type = chaz_OS_shell_type(); FILE *file; size_t i; @@ -2897,16 +3049,40 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) { } if (makefile->cleanups[0]) { - fprintf(file, "clean :\n\trm -f"); - for (i = 0; makefile->cleanups[i]; i++) { - char *cleanup = makefile->cleanups[i]; - fprintf(file, " \\\n\t %s", cleanup); + if (shell_type == CHAZ_OS_POSIX) { + fprintf(file, "clean :\n\trm -f"); + for (i = 0; makefile->cleanups[i]; i++) { + const char *cleanup = makefile->cleanups[i]; + fprintf(file, " \\\n\t %s", cleanup); + } + fprintf(file, "\n\n"); + } + else if (shell_type == CHAZ_OS_CMD_EXE) { + fprintf(file, "clean :\n"); + for (i = 0; makefile->cleanups[i]; i++) { + const char *cleanup = makefile->cleanups[i]; + fprintf(file, "\tfor %%i in (%s) do if exist %%i del /f %%i\n", + cleanup); + } + fprintf(file, "\n"); + } + else { + chaz_Util_die("Unsupported shell type: %d", shell_type); } - fprintf(file, "\n\n"); } fprintf(file, "distclean : clean\n"); - fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n"); + if (shell_type == CHAZ_OS_POSIX) { + fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n"); + } + else if (shell_type == CHAZ_OS_CMD_EXE) { + fprintf(file, + "\tfor %%i in (charmonizer charmony.h Makefile) do" + " if exist %%i del /f %%i\n\n"); + } + else { + chaz_Util_die("Unsupported shell type: %d", shell_type); + } fclose(file); } @@ -2988,20 +3164,45 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command) { void chaz_MakeRule_add_command_make(chaz_MakeRule *rule, const char *dir, const char *target) { + const char *make = chaz_Make.make_command; char *command; - if (!target) { + if (chaz_Make.is_gnu_make) { + if (!target) { + size_t size = strlen(dir) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) -C %s", dir); + } + else { + size_t size = strlen(dir) + strlen(target) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) -C %s %s", dir, target); + } + chaz_MakeRule_add_command(rule, command); + free(command); + } + else if (chaz_Make.is_nmake) { command = (char*)malloc(strlen(dir) + 20); - sprintf(command, "make -C %s", dir); + sprintf(command, "cd %s", dir); + chaz_MakeRule_add_command(rule, command); + free(command); + + if (!target) { + chaz_MakeRule_add_command(rule, "$(MAKE)"); + } + else { + size_t size = strlen(target) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) %s", target); + chaz_MakeRule_add_command(rule, command); + free(command); + } + + chaz_MakeRule_add_command(rule, "cd $(MAKEDIR)"); } else { - command = (char*)malloc(strlen(dir) + strlen(target) + 20); - sprintf(command, "make -C %s %s", dir, target); + chaz_Util_die("Couldn't find a supported 'make' utility."); } - - chaz_MakeRule_add_command(rule, command); - - free(command); } void @@ -3598,6 +3799,7 @@ chaz_Probe_init(struct chaz_CLIArgs *args) { chaz_CC_init(args->cc, args->cflags); chaz_ConfWriter_init(); chaz_HeadCheck_init(); + chaz_Make_init(); /* Enable output. */ if (args->charmony_h) { @@ -3627,6 +3829,7 @@ chaz_Probe_clean_up(void) { /* Dispatch various clean up routines. */ chaz_ConfWriter_clean_up(); chaz_CC_clean_up(); + chaz_Make_clean_up(); if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); } } @@ -3642,8 +3845,8 @@ chaz_Probe_gcc_version(void) { } int -chaz_Probe_compiler_is_msvc(void) { - return chaz_CC_compiler_is_msvc(); +chaz_Probe_msvc_version_num(void) { + return chaz_CC_msvc_version_num(); } /***************************************************************************/ @@ -5486,17 +5689,6 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) { /* Only core source files require this -- not our headers and * autogenerated files. */ chaz_CC_add_extra_cflags("-std=gnu99 -D_GNU_SOURCE"); - } - else if (chaz_Probe_compiler_is_msvc()) { - /* Compile as C++ under MSVC. */ - chaz_CC_add_extra_cflags("/TP"); - - /* Thwart stupid warnings. */ - chaz_CC_add_extra_cflags("-D_CRT_SECURE_NO_WARNINGS"); - chaz_CC_add_extra_cflags("-D_SCL_SECURE_NO_WARNINGS"); - - /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */ - chaz_CC_add_extra_cflags("-Dfor=\"if(0);else for\""); /* When compiling for Perl bindings, define HAS_BOOL so that the Perl * headers don't redefine 'bool' in conflict with C++. @@ -5508,6 +5700,23 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) { chaz_CC_add_extra_cflags("-DHAS_BOOL"); } } + else if (chaz_Probe_msvc_version_num()) { + /* Compile as C++ under MSVC. */ + chaz_CC_add_extra_cflags("/TP"); + + /* Thwart stupid warnings. */ + chaz_CC_add_extra_cflags("/D_CRT_SECURE_NO_WARNINGS"); + chaz_CC_add_extra_cflags("/D_SCL_SECURE_NO_WARNINGS"); + + if (chaz_Probe_msvc_version_num() < 1300) { + /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */ + chaz_CC_add_extra_cflags("/Dfor=\"if(0);else for\""); + } + + if (args->charmony_pm) { + chaz_CC_add_extra_cflags("/DHAS_BOOL"); + } + } } int main(int argc, const char **argv) { http://git-wip-us.apache.org/repos/asf/lucy/blob/369a995c/common/charmonizer.c ---------------------------------------------------------------------- diff --git a/common/charmonizer.c b/common/charmonizer.c index 8a4feeb..4c5275d 100644 --- a/common/charmonizer.c +++ b/common/charmonizer.c @@ -93,6 +93,16 @@ chaz_CC_set_warnings_as_errors(const int flag); void chaz_CC_add_extra_cflags(const char *); +/* Add include dir to extra cflags. + */ +void +chaz_CC_add_include_dir(const char *dir); + +/* Set optimization level. + */ +void +chaz_CC_set_optimization_level(const char *level); + /* Accessor for the compiler executable's string representation. */ const char* @@ -109,25 +119,25 @@ const char* chaz_CC_get_extra_cflags(void); int -chaz_CC_gcc_version_num(); +chaz_CC_gcc_version_num(void); const char* -chaz_CC_gcc_version(); +chaz_CC_gcc_version(void); int -chaz_CC_compiler_is_msvc(void); +chaz_CC_msvc_version_num(void); const char* -chaz_CC_link_command(); +chaz_CC_link_command(void); const char* -chaz_CC_link_flags(); +chaz_CC_link_flags(void); const char* -chaz_CC_link_shared_obj_flag(); +chaz_CC_link_shared_obj_flag(void); const char* -chaz_CC_link_output_flag(); +chaz_CC_link_output_flag(void); #endif /* H_CHAZ_COMPILER */ @@ -351,6 +361,15 @@ typedef struct chaz_MakeRule chaz_MakeRule; typedef void (*chaz_Make_list_files_callback_t)(char *file, void *context); void +chaz_Make_init(void); + +void +chaz_Make_clean_up(void); + +const char* +chaz_Make_get_make(void); + +void chaz_Make_list_files(const char *dir, const char *ext, chaz_Make_list_files_callback_t callback, void *context); @@ -631,10 +650,10 @@ chaz_Probe_gcc_version_num(void); const char* chaz_Probe_gcc_version(void); -/* Returns true if the compiler is MSVC. +/* Return the integer version of MSVC defined by _MSC_VER */ int -chaz_Probe_compiler_is_msvc(void); +chaz_Probe_msvc_version_num(void); #endif /* Include guard. */ @@ -1527,6 +1546,34 @@ chaz_CC_add_extra_cflags(const char *flags) { } } +void +chaz_CC_add_include_dir(const char *dir) { + size_t size = strlen(chaz_CC.include_flag) + strlen(dir) + 1; + char *flag = (char*)malloc(size); + sprintf(flag, "%s%s", chaz_CC.include_flag, dir); + chaz_CC_add_extra_cflags(flag); + free(flag); +} + +void +chaz_CC_set_optimization_level(const char *level) { + const char *opt_flag; + char *flag; + size_t size; + + if (chaz_CC.intval__MSC_VER) { + opt_flag = "/O"; + } + else { + opt_flag = "-O"; + } + size = strlen(opt_flag) + strlen(level) + 1; + flag = (char*)malloc(size); + sprintf(flag, "%s%s", opt_flag, level); + chaz_CC_add_extra_cflags(flag); + free(flag); +} + const char* chaz_CC_get_cc(void) { return chaz_CC.cc_command; @@ -1555,8 +1602,8 @@ chaz_CC_gcc_version(void) { } int -chaz_CC_compiler_is_msvc(void) { - return !!chaz_CC.intval__MSC_VER; +chaz_CC_msvc_version_num(void) { + return chaz_CC.intval__MSC_VER; } const char* @@ -2731,6 +2778,110 @@ struct chaz_MakeFile { size_t num_cleanups; }; +/* Static vars. */ +static struct { + char *make_command; + int is_gnu_make; + int is_nmake; +} chaz_Make = { + NULL, + 0, 0 +}; + +/* Detect make command. + * + * The argument list must be a NULL-terminated series of different spellings + * of `make`, which will be auditioned in the order they are supplied. Here + * are several possibilities: + * + * make + * gmake + * nmake + * dmake + */ +static int +chaz_Make_detect(const char *make1, ...); + +static int +chaz_Make_audition(const char *make); + +void +chaz_Make_init(void) { + const char *make; + + chaz_Make_detect("make", "gmake", "nmake", "dmake", NULL); + make = chaz_Make.make_command; + + if (make) { + if (strcmp(make, "make") == 0 || strcmp(make, "gmake") == 0) { + /* TODO: Add a feature test for GNU make. */ + chaz_Make.is_gnu_make = 1; + } + else if (strcmp(make, "nmake") == 0) { + chaz_Make.is_nmake = 1; + } + } +} + +void +chaz_Make_clean_up(void) { + free(chaz_Make.make_command); +} + +const char* +chaz_Make_get_make(void) { + return chaz_Make.make_command; +} + +static int +chaz_Make_detect(const char *make1, ...) { + va_list args; + const char *candidate; + int found = 0; + const char makefile_content[] = "foo:\n\techo \"foo!\"\n"; + chaz_Util_write_file("_charm_Makefile", makefile_content); + + /* Audition candidates. */ + found = chaz_Make_audition(make1); + va_start(args, make1); + while (!found && (NULL != (candidate = va_arg(args, const char*)))) { + found = chaz_Make_audition(candidate); + } + va_end(args); + + chaz_Util_remove_and_verify("_charm_Makefile"); + + return found; +} + +static int +chaz_Make_audition(const char *make) { + int succeeded = 0; + const char pattern[] = "%s -f _charm_Makefile"; + size_t size = strlen(make) + sizeof(pattern) + 10; + char *command = (char*)malloc(size); + sprintf(command, pattern, make); + + chaz_Util_remove_and_verify("_charm_foo"); + chaz_OS_run_redirected(command, "_charm_foo"); + if (chaz_Util_can_open_file("_charm_foo")) { + size_t len; + char *content = chaz_Util_slurp_file("_charm_foo", &len); + if (NULL != strstr(content, "foo!")) { + succeeded = 1; + } + free(content); + } + chaz_Util_remove_and_verify("_charm_foo"); + + if (succeeded) { + chaz_Make.make_command = chaz_Util_strdup(make); + } + + free(command); + return succeeded; +} + chaz_MakeFile* chaz_MakeFile_new() { chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile)); @@ -2869,6 +3020,7 @@ chaz_MakeFile_add_shared_obj(chaz_MakeFile *makefile, const char *shared_obj, void chaz_MakeFile_write(chaz_MakeFile *makefile) { + int shell_type = chaz_OS_shell_type(); FILE *file; size_t i; @@ -2897,16 +3049,40 @@ chaz_MakeFile_write(chaz_MakeFile *makefile) { } if (makefile->cleanups[0]) { - fprintf(file, "clean :\n\trm -f"); - for (i = 0; makefile->cleanups[i]; i++) { - char *cleanup = makefile->cleanups[i]; - fprintf(file, " \\\n\t %s", cleanup); + if (shell_type == CHAZ_OS_POSIX) { + fprintf(file, "clean :\n\trm -f"); + for (i = 0; makefile->cleanups[i]; i++) { + const char *cleanup = makefile->cleanups[i]; + fprintf(file, " \\\n\t %s", cleanup); + } + fprintf(file, "\n\n"); + } + else if (shell_type == CHAZ_OS_CMD_EXE) { + fprintf(file, "clean :\n"); + for (i = 0; makefile->cleanups[i]; i++) { + const char *cleanup = makefile->cleanups[i]; + fprintf(file, "\tfor %%i in (%s) do if exist %%i del /f %%i\n", + cleanup); + } + fprintf(file, "\n"); + } + else { + chaz_Util_die("Unsupported shell type: %d", shell_type); } - fprintf(file, "\n\n"); } fprintf(file, "distclean : clean\n"); - fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n"); + if (shell_type == CHAZ_OS_POSIX) { + fprintf(file, "\trm -f charmonizer charmony.h Makefile\n\n"); + } + else if (shell_type == CHAZ_OS_CMD_EXE) { + fprintf(file, + "\tfor %%i in (charmonizer charmony.h Makefile) do" + " if exist %%i del /f %%i\n\n"); + } + else { + chaz_Util_die("Unsupported shell type: %d", shell_type); + } fclose(file); } @@ -2988,20 +3164,45 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command) { void chaz_MakeRule_add_command_make(chaz_MakeRule *rule, const char *dir, const char *target) { + const char *make = chaz_Make.make_command; char *command; - if (!target) { + if (chaz_Make.is_gnu_make) { + if (!target) { + size_t size = strlen(dir) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) -C %s", dir); + } + else { + size_t size = strlen(dir) + strlen(target) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) -C %s %s", dir, target); + } + chaz_MakeRule_add_command(rule, command); + free(command); + } + else if (chaz_Make.is_nmake) { command = (char*)malloc(strlen(dir) + 20); - sprintf(command, "make -C %s", dir); + sprintf(command, "cd %s", dir); + chaz_MakeRule_add_command(rule, command); + free(command); + + if (!target) { + chaz_MakeRule_add_command(rule, "$(MAKE)"); + } + else { + size_t size = strlen(target) + 20; + command = (char*)malloc(size); + sprintf(command, "$(MAKE) %s", target); + chaz_MakeRule_add_command(rule, command); + free(command); + } + + chaz_MakeRule_add_command(rule, "cd $(MAKEDIR)"); } else { - command = (char*)malloc(strlen(dir) + strlen(target) + 20); - sprintf(command, "make -C %s %s", dir, target); + chaz_Util_die("Couldn't find a supported 'make' utility."); } - - chaz_MakeRule_add_command(rule, command); - - free(command); } void @@ -3598,6 +3799,7 @@ chaz_Probe_init(struct chaz_CLIArgs *args) { chaz_CC_init(args->cc, args->cflags); chaz_ConfWriter_init(); chaz_HeadCheck_init(); + chaz_Make_init(); /* Enable output. */ if (args->charmony_h) { @@ -3627,6 +3829,7 @@ chaz_Probe_clean_up(void) { /* Dispatch various clean up routines. */ chaz_ConfWriter_clean_up(); chaz_CC_clean_up(); + chaz_Make_clean_up(); if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); } } @@ -3642,8 +3845,8 @@ chaz_Probe_gcc_version(void) { } int -chaz_Probe_compiler_is_msvc(void) { - return chaz_CC_compiler_is_msvc(); +chaz_Probe_msvc_version_num(void) { + return chaz_CC_msvc_version_num(); } /***************************************************************************/ @@ -5485,27 +5688,33 @@ S_add_compiler_flags(struct chaz_CLIArgs *args) { /* Only core source files require this -- not our headers and * autogenerated files. */ chaz_CC_add_extra_cflags("-std=gnu99 -D_GNU_SOURCE"); + + /* When compiling for Perl bindings, define HAS_BOOL so that the Perl + * headers don't redefine 'bool' in conflict with C++. + * + * TODO: Compile all files that #include Perl headers separately and + * remove this directive. + */ + if (args->charmony_pm) { + chaz_CC_add_extra_cflags("-DHAS_BOOL"); + } } - else if (chaz_Probe_compiler_is_msvc()) { + else if (chaz_Probe_msvc_version_num()) { /* Compile as C++ under MSVC. */ chaz_CC_add_extra_cflags("/TP"); /* Thwart stupid warnings. */ - chaz_CC_add_extra_cflags("-D_CRT_SECURE_NO_WARNINGS"); - chaz_CC_add_extra_cflags("-D_SCL_SECURE_NO_WARNINGS"); + chaz_CC_add_extra_cflags("/D_CRT_SECURE_NO_WARNINGS"); + chaz_CC_add_extra_cflags("/D_SCL_SECURE_NO_WARNINGS"); - /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */ - chaz_CC_add_extra_cflags("-Dfor=\"if(0);else for\""); - } + if (chaz_Probe_msvc_version_num() < 1300) { + /* Redefine 'for' to fix broken 'for' scoping under MSVC6. */ + chaz_CC_add_extra_cflags("/Dfor=\"if(0);else for\""); + } - /* When compiling for Perl bindings, define HAS_BOOL so that the Perl - * headers don't redefine 'bool' in conflict with C++. - * - * TODO: Compile all files that #include Perl headers separately and - * remove this directive. - */ - if (args->charmony_pm) { - chaz_CC_add_extra_cflags("-DHAS_BOOL"); + if (args->charmony_pm) { + chaz_CC_add_extra_cflags("/DHAS_BOOL"); + } } }
