Rework compiler version detection Don't evaluate version macros. Only check for presence and add functions that check version numbers against a predicate. Required to support cross compilation.
Project: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/commit/d8e3d937 Tree: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/tree/d8e3d937 Diff: http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/diff/d8e3d937 Branch: refs/heads/master Commit: d8e3d9377948cc9490a55519dfbcd67c2bc58162 Parents: cb8761f Author: Nick Wellnhofer <wellnho...@aevum.de> Authored: Fri Feb 3 19:32:59 2017 +0100 Committer: Nick Wellnhofer <wellnho...@aevum.de> Committed: Sat Feb 4 18:10:18 2017 +0100 ---------------------------------------------------------------------- src/Charmonizer/Core/CFlags.c | 12 ++- src/Charmonizer/Core/Compiler.c | 147 +++++++++++++------------- src/Charmonizer/Core/Compiler.h | 24 +++-- src/Charmonizer/Core/Make.c | 6 +- src/Charmonizer/Probe.c | 15 --- src/Charmonizer/Probe.h | 17 --- src/Charmonizer/Probe/Memory.c | 2 +- src/Charmonizer/Probe/SymbolVisibility.c | 2 +- 8 files changed, 105 insertions(+), 120 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Core/CFlags.c ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Core/CFlags.c b/src/Charmonizer/Core/CFlags.c index ea07dc1..ab57fcc 100644 --- a/src/Charmonizer/Core/CFlags.c +++ b/src/Charmonizer/Core/CFlags.c @@ -235,8 +235,16 @@ chaz_CFlags_hide_symbols(chaz_CFlags *flags) { } } else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { - if (chaz_CC_sun_c_version_num() >= 0x550) { - /* Sun Studio 8. */ + static int checked = 0; + static int version_ge_550; + + if (!checked) { + /* Requires Sun Studio 8. */ + version_ge_550 = chaz_CC_test_sun_c_version(">= 0x550"); + checked = 1; + } + + if (version_ge_550) { chaz_CFlags_append(flags, "-xldscope=hidden"); } } http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Core/Compiler.c ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Core/Compiler.c b/src/Charmonizer/Core/Compiler.c index f864a5d..49fed58 100644 --- a/src/Charmonizer/Core/Compiler.c +++ b/src/Charmonizer/Core/Compiler.c @@ -27,11 +27,6 @@ static void chaz_CC_detect_binary_format(const char *filename); -/** Return the numeric value of a macro or 0 if it isn't defined. - */ -static int -chaz_CC_eval_macro(const char *macro); - /* Detect macros which may help to identify some compilers. */ static void @@ -62,12 +57,10 @@ static struct { char gcc_version_str[30]; int binary_format; int cflags_style; - int intval___GNUC__; - int intval___GNUC_MINOR__; - int intval___GNUC_PATCHLEVEL__; - int intval__MSC_VER; - int intval___clang__; - int intval___SUNPRO_C; + int is_gcc; + int is_msvc; + int is_clang; + int is_sun_c; int is_cygwin; int is_mingw; chaz_CFlags *extra_cflags; @@ -75,7 +68,7 @@ static struct { } chaz_CC = { NULL, NULL, NULL, "", "", "", "", "", "", - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL }; @@ -110,6 +103,9 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) { } compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH, CHAZ_CC_TRY_BASENAME, code); + if (compile_succeeded) { + strcpy(chaz_CC.obj_ext, ".obj"); + } } /* Try POSIX argument style. */ @@ -120,6 +116,9 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) { } compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH, CHAZ_CC_TRY_BASENAME, code); + if (compile_succeeded) { + strcpy(chaz_CC.obj_ext, ".o"); + } } if (!compile_succeeded) { @@ -130,13 +129,13 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) { chaz_CC_detect_known_compilers(); - if (chaz_CC.intval___GNUC__) { + if (chaz_CC_is_gcc()) { chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_GNU; } - else if (chaz_CC.intval__MSC_VER) { + else if (chaz_CC_is_msvc()) { chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_MSVC; } - else if (chaz_CC.intval___SUNPRO_C) { + else if (chaz_CC_is_sun_c()) { chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_SUN_C; } else { @@ -170,7 +169,7 @@ chaz_CC_init(const char *compiler_command, const char *compiler_flags) { } strcpy(chaz_CC.exe_ext, ".exe"); strcpy(chaz_CC.shared_lib_ext, ".dll"); - if (chaz_CC.intval___GNUC__) { + if (chaz_CC_is_gcc()) { strcpy(chaz_CC.static_lib_ext, ".a"); strcpy(chaz_CC.import_lib_ext, ".dll.a"); strcpy(chaz_CC.obj_ext, ".o"); @@ -244,43 +243,40 @@ chaz_CC_detect_binary_format(const char *filename) { free(output); } -static const char chaz_CC_eval_macro_code[] = - CHAZ_QUOTE( #include <stdio.h> ) - CHAZ_QUOTE( int main() { ) - CHAZ_QUOTE( #ifndef %s ) - CHAZ_QUOTE( #error "nope" ) - CHAZ_QUOTE( #endif ) - CHAZ_QUOTE( printf("%%d", %s); ) - CHAZ_QUOTE( return 0; ) - CHAZ_QUOTE( } ); - -static int -chaz_CC_eval_macro(const char *macro) { - size_t size = sizeof(chaz_CC_eval_macro_code) - + (strlen(macro) * 2) +int +chaz_CC_has_macro(const char *macro) { + static const char template[] = + CHAZ_QUOTE( #ifdef %s ) + CHAZ_QUOTE( int i; ) + CHAZ_QUOTE( #else ) + CHAZ_QUOTE( #error "nope" ) + CHAZ_QUOTE( #endif ); + size_t size = sizeof(template) + + strlen(macro) + 20; char *code = (char*)malloc(size); int retval = 0; - char *output; - size_t len; - sprintf(code, chaz_CC_eval_macro_code, macro, macro); - output = chaz_CC_capture_output(code, &len); - if (output) { - retval = atoi(output); - free(output); - } + sprintf(code, template, macro); + retval = chaz_CC_test_compile(code); free(code); return retval; } int -chaz_CC_has_macro(const char *macro) { - size_t size = sizeof(chaz_CC_eval_macro_code) - + (strlen(macro) * 2) +chaz_CC_test_macro(const char *expression, const char *predicate) { + static const char template[] = + CHAZ_QUOTE( #if (%s) %s ) + CHAZ_QUOTE( int i; ) + CHAZ_QUOTE( #else ) + CHAZ_QUOTE( #error "nope" ) + CHAZ_QUOTE( #endif ); + size_t size = sizeof(template) + + strlen(expression) + + strlen(predicate) + 20; char *code = (char*)malloc(size); int retval = 0; - sprintf(code, chaz_CC_eval_macro_code, macro, macro); + sprintf(code, template, expression, predicate); retval = chaz_CC_test_compile(code); free(code); return retval; @@ -288,19 +284,10 @@ chaz_CC_has_macro(const char *macro) { static void chaz_CC_detect_known_compilers(void) { - chaz_CC.intval___GNUC__ = chaz_CC_eval_macro("__GNUC__"); - if (chaz_CC.intval___GNUC__) { - chaz_CC.intval___GNUC_MINOR__ - = chaz_CC_eval_macro("__GNUC_MINOR__"); - chaz_CC.intval___GNUC_PATCHLEVEL__ - = chaz_CC_eval_macro("__GNUC_PATCHLEVEL__"); - sprintf(chaz_CC.gcc_version_str, "%d.%d.%d", chaz_CC.intval___GNUC__, - chaz_CC.intval___GNUC_MINOR__, - chaz_CC.intval___GNUC_PATCHLEVEL__); - } - chaz_CC.intval__MSC_VER = chaz_CC_eval_macro("_MSC_VER"); - chaz_CC.intval___clang__ = chaz_CC_eval_macro("__clang__"); - chaz_CC.intval___SUNPRO_C = chaz_CC_eval_macro("__SUNPRO_C"); + chaz_CC.is_gcc = chaz_CC_has_macro("__GNUC__"); + chaz_CC.is_msvc = chaz_CC_has_macro("_MSC_VER"); + chaz_CC.is_clang = chaz_CC_has_macro("__clang__"); + chaz_CC.is_sun_c = chaz_CC_has_macro("__SUNPRO_C"); } void @@ -346,7 +333,7 @@ chaz_CC_compile_exe(const char *source_path, const char *exe_name, system(command); } - if (chaz_CC.intval__MSC_VER) { + if (chaz_CC_is_msvc()) { /* Zap MSVC junk. */ size_t junk_buf_size = strlen(exe_file) + 4; char *junk = (char*)malloc(junk_buf_size); @@ -534,25 +521,18 @@ chaz_CC_obj_ext(void) { } int -chaz_CC_gcc_version_num(void) { - return 10000 * chaz_CC.intval___GNUC__ - + 100 * chaz_CC.intval___GNUC_MINOR__ - + chaz_CC.intval___GNUC_PATCHLEVEL__; -} - -const char* -chaz_CC_gcc_version(void) { - return chaz_CC.intval___GNUC__ ? chaz_CC.gcc_version_str : NULL; +chaz_CC_is_gcc(void) { + return chaz_CC.is_gcc; } int -chaz_CC_msvc_version_num(void) { - return chaz_CC.intval__MSC_VER; +chaz_CC_is_msvc(void) { + return chaz_CC.is_msvc; } int -chaz_CC_sun_c_version_num(void) { - return chaz_CC.intval___SUNPRO_C; +chaz_CC_is_sun_c(void) { + return chaz_CC.is_sun_c; } int @@ -565,9 +545,26 @@ chaz_CC_is_mingw(void) { return chaz_CC.is_mingw; } +int +chaz_CC_test_gcc_version(const char *predicate) { + static const char version[] = + "10000 * __GNUC__ + 100 * __GNUC_MINOR__ + __GNUC_PATCHLEVEL__"; + return chaz_CC_test_macro(version, predicate); +} + +int +chaz_CC_test_msvc_version(const char *predicate) { + return chaz_CC_test_macro("_MSC_VER", predicate); +} + +int +chaz_CC_test_sun_c_version(const char *predicate) { + return chaz_CC_test_macro("__SUNPRO_C", predicate); +} + const char* chaz_CC_link_command() { - if (chaz_CC.intval__MSC_VER) { + if (chaz_CC_is_msvc()) { return "link"; } else { @@ -577,7 +574,7 @@ chaz_CC_link_command() { char* chaz_CC_format_archiver_command(const char *target, const char *objects) { - if (chaz_CC.intval__MSC_VER) { + if (chaz_CC_is_msvc()) { /* TODO: Write `objects` to a temporary file in order to avoid * exceeding line length limits. */ char *out = chaz_Util_join("", "/OUT:", target, NULL); @@ -593,7 +590,7 @@ chaz_CC_format_archiver_command(const char *target, const char *objects) { char* chaz_CC_format_ranlib_command(const char *target) { - if (chaz_CC.intval__MSC_VER) { + if (chaz_CC_is_msvc()) { return NULL; } return chaz_Util_join(" ", "ranlib", target, NULL); @@ -603,7 +600,7 @@ char* chaz_CC_shared_lib_filename(const char *dir, const char *basename, const char *version) { /* Cygwin uses a "cyg" prefix for shared libraries. */ - const char *prefix = chaz_CC_msvc_version_num() + const char *prefix = chaz_CC_is_msvc() ? "" : chaz_CC_is_cygwin() ? "cyg" : "lib"; return chaz_CC_build_lib_filename(dir, prefix, basename, version, @@ -613,7 +610,7 @@ chaz_CC_shared_lib_filename(const char *dir, const char *basename, char* chaz_CC_import_lib_filename(const char *dir, const char *basename, const char *version) { - const char *prefix = chaz_CC_msvc_version_num() ? "" : "lib"; + const char *prefix = chaz_CC_is_msvc() ? "" : "lib"; return chaz_CC_build_lib_filename(dir, prefix, basename, version, chaz_CC.import_lib_ext); } @@ -668,7 +665,7 @@ chaz_CC_build_lib_filename(const char *dir, const char *prefix, char* chaz_CC_static_lib_filename(const char *dir, const char *basename) { - const char *prefix = chaz_CC_msvc_version_num() ? "" : "lib"; + const char *prefix = chaz_CC_is_msvc() ? "" : "lib"; if (dir == NULL || strcmp(dir, ".") == 0) { return chaz_Util_join("", prefix, basename, chaz_CC.static_lib_ext, http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Core/Compiler.h ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Core/Compiler.h b/src/Charmonizer/Core/Compiler.h index 02e2925..da506f6 100644 --- a/src/Charmonizer/Core/Compiler.h +++ b/src/Charmonizer/Core/Compiler.h @@ -71,6 +71,12 @@ chaz_CC_capture_output(const char *source, size_t *output_len); int chaz_CC_has_macro(const char *macro); +/** Return true if preprocessor expression matches predicate. Predicate has + * the form "<op> value", e.g. ">= 0x1500". + */ +int +chaz_CC_test_macro(const char *expression, const char *predicate); + /** Initialize the compiler environment. */ void @@ -137,16 +143,13 @@ const char* chaz_CC_obj_ext(void); int -chaz_CC_gcc_version_num(void); - -const char* -chaz_CC_gcc_version(void); +chaz_CC_is_gcc(void); int -chaz_CC_msvc_version_num(void); +chaz_CC_is_msvc(void); int -chaz_CC_sun_c_version_num(void); +chaz_CC_is_sun_c(void); int chaz_CC_is_cygwin(void); @@ -154,6 +157,15 @@ chaz_CC_is_cygwin(void); int chaz_CC_is_mingw(void); +int +chaz_CC_test_gcc_version(const char *predicate); + +int +chaz_CC_test_msvc_version(const char *predicate); + +int +chaz_CC_test_sun_c_version(const char *predicate); + const char* chaz_CC_link_command(void); http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Core/Make.c ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Core/Make.c b/src/Charmonizer/Core/Make.c index 9c4722b..cebacd5 100644 --- a/src/Charmonizer/Core/Make.c +++ b/src/Charmonizer/Core/Make.c @@ -507,7 +507,7 @@ S_chaz_MakeFile_finish_shared_lib(chaz_MakeFile *self, free(filename); } - if (chaz_CC_msvc_version_num()) { + if (chaz_CC_is_msvc()) { /* Remove export file. */ char *filename = chaz_CC_export_filename(binary->target_dir, binary->basename, @@ -674,7 +674,7 @@ chaz_MakeFile_write(chaz_MakeFile *self) { S_chaz_MakeRule_write(self->distclean, out); /* Suffix rule for .c files. */ - if (chaz_CC_msvc_version_num()) { + if (chaz_CC_is_msvc()) { fprintf(out, ".c.obj :\n"); fprintf(out, "\t$(CC) /nologo $(CFLAGS) /c $< /Fo$@\n\n"); } @@ -691,7 +691,7 @@ S_chaz_MakeFile_write_binary_rules(chaz_MakeFile *self, chaz_MakeBinary *binary, FILE *out) { const char *cflags; - if (chaz_CC_msvc_version_num()) { + if (chaz_CC_is_msvc()) { chaz_CFlags_append(binary->compile_flags, "/nologo"); chaz_CFlags_append(binary->link_flags, "/nologo"); } http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Probe.c ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Probe.c b/src/Charmonizer/Probe.c index 5aaa988..3cc4228 100644 --- a/src/Charmonizer/Probe.c +++ b/src/Charmonizer/Probe.c @@ -171,18 +171,3 @@ chaz_Probe_clean_up(void) { if (chaz_Util_verbosity) { printf("Cleanup complete.\n"); } } - -int -chaz_Probe_gcc_version_num(void) { - return chaz_CC_gcc_version_num(); -} - -const char* -chaz_Probe_gcc_version(void) { - return chaz_CC_gcc_version_num() ? chaz_CC_gcc_version() : NULL; -} - -int -chaz_Probe_msvc_version_num(void) { - return chaz_CC_msvc_version_num(); -} http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Probe.h ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Probe.h b/src/Charmonizer/Probe.h index 3ce92d0..cd1f03c 100644 --- a/src/Charmonizer/Probe.h +++ b/src/Charmonizer/Probe.h @@ -66,23 +66,6 @@ chaz_Probe_init(struct chaz_CLI *cli); void chaz_Probe_clean_up(void); -/* Return an integer version of the GCC version number which is - * (10000 * __GNU_C__ + 100 * __GNUC_MINOR__ + __GNUC_PATCHLEVEL__). - */ -int -chaz_Probe_gcc_version_num(void); - -/* If the compiler is GCC (or claims compatibility), return an X.Y.Z string - * version of the GCC version; otherwise, return NULL. - */ -const char* -chaz_Probe_gcc_version(void); - -/* Return the integer version of MSVC defined by _MSC_VER - */ -int -chaz_Probe_msvc_version_num(void); - #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Probe/Memory.c ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Probe/Memory.c b/src/Charmonizer/Probe/Memory.c index 07bde87..a853a53 100644 --- a/src/Charmonizer/Probe/Memory.c +++ b/src/Charmonizer/Probe/Memory.c @@ -65,7 +65,7 @@ chaz_Memory_probe_alloca(void) { /* Under GCC, alloca is a builtin that works without including the * correct header, generating only a warning. To avoid misdetection, * disable the alloca builtin temporarily. */ - if (chaz_CC_gcc_version_num()) { + if (chaz_CC_is_gcc()) { chaz_CFlags_append(temp_cflags, "-fno-builtin-alloca"); } http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/d8e3d937/src/Charmonizer/Probe/SymbolVisibility.c ---------------------------------------------------------------------- diff --git a/src/Charmonizer/Probe/SymbolVisibility.c b/src/Charmonizer/Probe/SymbolVisibility.c index 73fdaf4..34e9ac4 100644 --- a/src/Charmonizer/Probe/SymbolVisibility.c +++ b/src/Charmonizer/Probe/SymbolVisibility.c @@ -59,7 +59,7 @@ chaz_SymbolVisibility_run(void) { if (chaz_CC_test_compile(code_buf)) { can_control_visibility = true; chaz_ConfWriter_add_def("EXPORT", export_win); - if (chaz_CC_gcc_version_num()) { + if (chaz_CC_is_gcc()) { /* * Under MinGW, symbols with dllimport storage class aren't * constant. If a global variable is initialized to such a