Repository: lucy
Updated Branches:
  refs/heads/master 0ef4c6fe8 -> 20dbfa386


Fix Windows tests with Clownfish prefix

Compile and link test executable separately. cl.exe doesn't accept the
/LIBPATH option that is used if a Clownfish prefix is provided.

Switch over to chaz_MakeRule_add_command_with_libpath to set the search
path on Windows when running the tests.


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

Branch: refs/heads/master
Commit: c5fb1844b6415632a7941b3f229228e1467e6aea
Parents: 0ef4c6f
Author: Nick Wellnhofer <[email protected]>
Authored: Tue Jun 2 18:17:10 2015 +0200
Committer: Nick Wellnhofer <[email protected]>
Committed: Tue Jun 2 20:23:55 2015 +0200

----------------------------------------------------------------------
 common/charmonizer.c    | 228 +++++++++++++++++++++++++++++++++++--------
 common/charmonizer.main |  65 ++++++------
 2 files changed, 223 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/c5fb1844/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/common/charmonizer.c b/common/charmonizer.c
index 126129c..46bfc44 100644
--- a/common/charmonizer.c
+++ b/common/charmonizer.c
@@ -778,6 +778,16 @@ chaz_MakeRule*
 chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
                                 const char *base_name);
 
+/** Override compiler flags for a single object file.
+ *
+ * @param makefile The makefile.
+ * @param obj The object file.
+ * @param cflags Compiler flags.
+ */
+void
+chaz_MakeFile_override_cflags(chaz_MakeFile *makefile, const char *obj,
+                              chaz_CFlags *cflags);
+
 /** Write the makefile to a file named 'Makefile' in the current directory.
  *
  * @param makefile The makefile.
@@ -818,6 +828,16 @@ chaz_MakeRule_add_prereq(chaz_MakeRule *rule, const char 
*prereq);
 void
 chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command);
 
+/** Add a command to be executed with a special runtime library path.
+ *
+ * @param rule The rule.
+ * @param command The additional command.
+ * @param ... NULL-terminated list of library directories.
+ */
+void
+chaz_MakeRule_add_command_with_libpath(chaz_MakeRule *rule,
+                                       const char *command, ...);
+
 /** Add a command to remove one or more files.
  *
  * @param rule The rule.
@@ -987,6 +1007,11 @@ chaz_Util_strdup(const char *string);
 char*
 chaz_Util_join(const char *sep, ...);
 
+/* Join a NULL-terminated list of strings using a separator.
+ */
+char*
+chaz_Util_vjoin(const char *sep, va_list args);
+
 /* Get the length of a file (may overshoot on text files under DOS).
  */
 long
@@ -2569,6 +2594,7 @@ chaz_CLI_parse(chaz_CLI *self, int argc, const char 
*argv[]) {
 /***************************************************************************/
 
 #line 17 "src/Charmonizer/Core/Compiler.c"
+#include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 /* #include "Charmonizer/Core/Util.h" */
@@ -2613,6 +2639,7 @@ void
 chaz_CC_init(const char *compiler_command, const char *compiler_flags) {
     const char *code = "int main() { return 0; }\n";
     int compile_succeeded = 0;
+    int retval            = -1;
 
     if (chaz_Util_verbosity) { printf("Creating compiler object...\n"); }
 
@@ -2626,23 +2653,37 @@ chaz_CC_init(const char *compiler_command, const char 
*compiler_flags) {
     chaz_CC.try_exe_name
         = chaz_Util_join("", CHAZ_CC_TRY_BASENAME, chaz_OS_exe_ext(), NULL);
 
-    /* If we can't compile anything, game over. */
+    /* If we can't compile or execute anything, game over. */
     if (chaz_Util_verbosity) {
-        printf("Trying to compile a small test file...\n");
+        printf("Trying to compile and execute a small test file...\n");
+    }
+    if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) {
+        chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name);
     }
     /* Try MSVC argument style. */
     strcpy(chaz_CC.obj_ext, ".obj");
     chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_MSVC;
-    compile_succeeded = chaz_CC_test_compile(code);
+    compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
+                                            CHAZ_CC_TRY_BASENAME, code);
     if (!compile_succeeded) {
         /* Try POSIX argument style. */
         strcpy(chaz_CC.obj_ext, ".o");
         chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_POSIX;
-        compile_succeeded = chaz_CC_test_compile(code);
+        compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
+                                                CHAZ_CC_TRY_BASENAME, code);
     }
     if (!compile_succeeded) {
         chaz_Util_die("Failed to compile a small test file");
     }
+    retval = chaz_OS_run_local_redirected(chaz_CC.try_exe_name,
+                                          chaz_OS_dev_null());
+    chaz_Util_remove_and_verify(chaz_CC.try_exe_name);
+    if (retval < 0) {
+        chaz_Util_die("Failed to execute test file: %s", strerror(errno));
+    }
+    if (retval > 0) {
+        chaz_Util_die("Unexpected exit code %d from test file", retval);
+    }
 
     chaz_CC_detect_known_compilers();
 
@@ -4841,6 +4882,47 @@ chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
 }
 
 void
+chaz_MakeFile_override_cflags(chaz_MakeFile *makefile, const char *obj,
+                              chaz_CFlags *cflags) {
+    const char *obj_ext       = chaz_CC_obj_ext();
+    const char *cflags_string = chaz_CFlags_get_string(cflags);
+    size_t obj_ext_len = strlen(obj_ext);
+    size_t obj_len     = strlen(obj);
+    size_t base_len;
+    char *src;
+    char *command;
+    chaz_MakeRule *rule;
+
+    if (obj_len <= obj_ext_len) {
+       chaz_Util_die("Invalid object file: %s", obj);
+    }
+
+    base_len = obj_len - obj_ext_len;
+
+    if (strcmp(obj + base_len, obj_ext) != 0) {
+       chaz_Util_die("Invalid object file: %s", obj);
+    }
+
+    src = malloc(base_len + sizeof(".c"));
+    memcpy(src, obj, base_len);
+    memcpy(src + base_len, ".c", sizeof(".c"));
+
+    rule = chaz_MakeFile_add_rule(makefile, obj, src);
+    if (chaz_CC_msvc_version_num()) {
+        command = chaz_Util_join(" ", "$(CC) /nologo", cflags_string, "/c",
+                                 src, "/Fo$@", NULL);
+    }
+    else {
+        command = chaz_Util_join(" ", "$(CC)", cflags_string, "-c", src,
+                                 "-o $@", NULL);
+    }
+    chaz_MakeRule_add_command(rule, command);
+
+    free(command);
+    free(src);
+}
+
+void
 chaz_MakeFile_write(chaz_MakeFile *makefile) {
     FILE   *out;
     size_t  i;
@@ -4984,6 +5066,42 @@ chaz_MakeRule_add_command(chaz_MakeRule *rule, const 
char *command) {
 }
 
 void
+chaz_MakeRule_add_command_with_libpath(chaz_MakeRule *rule,
+                                       const char *command, ...) {
+    va_list args;
+    char *path        = NULL;
+    char *lib_command = NULL;
+
+    if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
+        va_start(args, command);
+        path = chaz_Util_vjoin(":", args);
+        va_end(args);
+
+        lib_command = chaz_Util_join("", "LD_LIBRARY_PATH=", path,
+                                     ":$$LD_LIBRARY_PATH ", command, NULL);
+
+        free(path);
+    }
+    else if (strcmp(chaz_OS_shared_lib_ext(), ".dll") == 0) {
+        va_start(args, command);
+        path = chaz_Util_vjoin(";", args);
+        va_end(args);
+
+        lib_command = chaz_Util_join("", "path ", path, ";%path% && ", command,
+                                     NULL);
+    }
+    else {
+        /* Assume that library paths are compiled into the executable on
+         * Darwin.
+         */
+        lib_command = chaz_Util_strdup(command);
+    }
+
+    chaz_MakeRule_add_command(rule, lib_command);
+    free(lib_command);
+}
+
+void
 chaz_MakeRule_add_rm_command(chaz_MakeRule *rule, const char *files) {
     char *command;
 
@@ -5414,6 +5532,13 @@ chaz_OS_rmdir(const char *filepath) {
 /* #include "Charmonizer/Core/Util.h" */
 /* #include "Charmonizer/Core/OperatingSystem.h" */
 
+/* va_copy is not part of C89. Assume that simple assignment works if it
+ * isn't defined.
+ */
+#ifndef va_copy
+  #define va_copy(dst, src) ((dst) = (src))
+#endif
+
 /* Global verbosity setting. */
 int chaz_Util_verbosity = 1;
 
@@ -5513,6 +5638,18 @@ chaz_Util_strdup(const char *string) {
 char*
 chaz_Util_join(const char *sep, ...) {
     va_list args;
+    char *result;
+
+    va_start(args, sep);
+    result = chaz_Util_vjoin(sep, args);
+    va_end(args);
+
+    return result;
+}
+
+char*
+chaz_Util_vjoin(const char *sep, va_list orig_args) {
+    va_list args;
     const char *string;
     char *result, *p;
     size_t sep_len = strlen(sep);
@@ -5520,7 +5657,7 @@ chaz_Util_join(const char *sep, ...) {
     int i;
 
     /* Determine result size. */
-    va_start(args, sep);
+    va_copy(args, orig_args);
     size = 1;
     string = va_arg(args, const char*);
     for (i = 0; string; ++i) {
@@ -5533,7 +5670,7 @@ chaz_Util_join(const char *sep, ...) {
     result = (char*)malloc(size);
 
     /* Create result string. */
-    va_start(args, sep);
+    va_copy(args, orig_args);
     p = result;
     string = va_arg(args, const char*);
     for (i = 0; string; ++i) {
@@ -6483,7 +6620,9 @@ chaz_Headers_probe_posix(void) {
         "grp.h",
         "pwd.h",
         "regex.h",
+        "sched.h",
         "sys/stat.h",
+        "sys/time.h",
         "sys/times.h",
         "sys/types.h",
         "sys/utsname.h",
@@ -7386,7 +7525,7 @@ chaz_Memory_probe_alloca(void) {
 
     /* Unixen. */
     sprintf(code_buf, alloca_code, "alloca.h", "alloca");
-    if (chaz_CC_test_compile(code_buf)) {
+    if (chaz_CC_test_link(code_buf)) {
         has_alloca = true;
         chaz_ConfWriter_add_def("HAS_ALLOCA_H", NULL);
         chaz_ConfWriter_add_def("alloca", "alloca");
@@ -7398,7 +7537,7 @@ chaz_Memory_probe_alloca(void) {
          * are subsequently repeated during the build.
          */
         sprintf(code_buf, alloca_code, "stdlib.h", "alloca");
-        if (chaz_CC_test_compile(code_buf)) {
+        if (chaz_CC_test_link(code_buf)) {
             has_alloca = true;
             chaz_ConfWriter_add_def("ALLOCA_IN_STDLIB_H", NULL);
             chaz_ConfWriter_add_def("alloca", "alloca");
@@ -7407,7 +7546,7 @@ chaz_Memory_probe_alloca(void) {
     if (!has_alloca) {
         sprintf(code_buf, alloca_code, "stdio.h", /* stdio.h is filler */
                 "__builtin_alloca");
-        if (chaz_CC_test_compile(code_buf)) {
+        if (chaz_CC_test_link(code_buf)) {
             has_builtin_alloca = true;
             chaz_ConfWriter_add_def("alloca", "__builtin_alloca");
         }
@@ -7416,7 +7555,7 @@ chaz_Memory_probe_alloca(void) {
     /* Windows. */
     if (!(has_alloca || has_builtin_alloca)) {
         sprintf(code_buf, alloca_code, "malloc.h", "alloca");
-        if (chaz_CC_test_compile(code_buf)) {
+        if (chaz_CC_test_link(code_buf)) {
             has_alloca = true;
             chaz_ConfWriter_add_def("HAS_MALLOC_H", NULL);
             chaz_ConfWriter_add_def("alloca", "alloca");
@@ -7424,9 +7563,9 @@ chaz_Memory_probe_alloca(void) {
     }
     if (!(has_alloca || has_builtin_alloca)) {
         sprintf(code_buf, alloca_code, "malloc.h", "_alloca");
-        if (chaz_CC_test_compile(code_buf)) {
+        if (chaz_CC_test_link(code_buf)) {
             chaz_ConfWriter_add_def("HAS_MALLOC_H", NULL);
-            chaz_ConfWriter_add_def("chy_alloca", "_alloca");
+            chaz_ConfWriter_add_def("alloca", "_alloca");
         }
     }
 }
@@ -8285,47 +8424,48 @@ 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();
+    const char *obj_ext  = chaz_CC_obj_ext();
 
-    chaz_CFlags   *test_cflags;
+    chaz_CFlags   *cflags;
+    chaz_CFlags   *link_flags;
     chaz_MakeRule *rule;
 
     char *test_lucy_exe;
-    char *test_lucy_c;
-    char *test_command;
+    char *test_lucy_obj;
 
     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, self->autogen_inc_dir);
-    chaz_CFlags_add_library(test_cflags, self->shared_lib);
+    test_lucy_obj = chaz_Util_join("", "t", dir_sep, "test_lucy", obj_ext,
+                                   NULL);
+
+    chaz_MakeFile_add_rule(self->makefile, test_lucy_obj,
+                           self->autogen_target);
+
+    cflags = chaz_CC_new_cflags();
+    chaz_CFlags_enable_optimization(cflags);
+    chaz_CFlags_add_include_dir(cflags, self->autogen_inc_dir);
+    chaz_MakeFile_override_cflags(self->makefile, test_lucy_obj, cflags);
+    chaz_CFlags_destroy(cflags);
+
+    link_flags = chaz_CC_new_cflags();
+    chaz_CFlags_add_library(link_flags, self->shared_lib);
     if (self->cfish_lib_dir) {
-        chaz_CFlags_add_library_path(test_cflags, self->cfish_lib_dir);
+        chaz_CFlags_add_library_path(link_flags, 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_CFlags_add_external_library(link_flags, self->cfish_lib_name);
+    rule = chaz_MakeFile_add_exe(self->makefile, test_lucy_exe, test_lucy_obj,
+                                 link_flags);
     chaz_MakeRule_add_prereq(rule, self->shared_lib_filename);
-    chaz_CFlags_destroy(test_cflags);
+    chaz_CFlags_destroy(link_flags);
 
     rule = chaz_MakeFile_add_rule(self->makefile, "test", test_lucy_exe);
-    if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
-        if (self->cfish_lib_dir) {
-            test_command
-                = chaz_Util_join("", "LD_LIBRARY_PATH=.:", self->cfish_lib_dir,
-                                 ":$$LD_LIBRARY_PATH ", test_lucy_exe, NULL);
-        }
-        else {
-            test_command
-                = chaz_Util_join(" ", "LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH",
-                                 test_lucy_exe, NULL);
-        }
+    if (self->cfish_lib_dir) {
+        chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".",
+                                               self->cfish_lib_dir, NULL);
     }
     else {
-        test_command = chaz_Util_strdup(test_lucy_exe);
+        chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".", NULL);
     }
-    chaz_MakeRule_add_command(rule, test_command);
 
     if (chaz_CLI_defined(self->cli, "enable-coverage")) {
         rule = chaz_MakeFile_add_rule(self->makefile, "coverage", 
test_lucy_exe);
@@ -8333,7 +8473,14 @@ lucy_MakeFile_write_c_test_rules(lucy_MakeFile *self) {
                                   "lcov"
                                   " --zerocounters"
                                   " --directory $(BASE_DIR)");
-        chaz_MakeRule_add_command(rule, test_command);
+        if (self->cfish_lib_dir) {
+            chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".",
+                                                   self->cfish_lib_dir, NULL);
+        }
+        else {
+            chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".",
+                                                   NULL);
+        }
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --capture"
@@ -8353,8 +8500,7 @@ lucy_MakeFile_write_c_test_rules(lucy_MakeFile *self) {
     }
 
     free(test_lucy_exe);
-    free(test_lucy_c);
-    free(test_command);
+    free(test_lucy_obj);
 }
 
 static void

http://git-wip-us.apache.org/repos/asf/lucy/blob/c5fb1844/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/common/charmonizer.main b/common/charmonizer.main
index 9e89cd7..2ae0fb1 100644
--- a/common/charmonizer.main
+++ b/common/charmonizer.main
@@ -542,47 +542,48 @@ 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();
+    const char *obj_ext  = chaz_CC_obj_ext();
 
-    chaz_CFlags   *test_cflags;
+    chaz_CFlags   *cflags;
+    chaz_CFlags   *link_flags;
     chaz_MakeRule *rule;
 
     char *test_lucy_exe;
-    char *test_lucy_c;
-    char *test_command;
+    char *test_lucy_obj;
 
     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, self->autogen_inc_dir);
-    chaz_CFlags_add_library(test_cflags, self->shared_lib);
+    test_lucy_obj = chaz_Util_join("", "t", dir_sep, "test_lucy", obj_ext,
+                                   NULL);
+
+    chaz_MakeFile_add_rule(self->makefile, test_lucy_obj,
+                           self->autogen_target);
+
+    cflags = chaz_CC_new_cflags();
+    chaz_CFlags_enable_optimization(cflags);
+    chaz_CFlags_add_include_dir(cflags, self->autogen_inc_dir);
+    chaz_MakeFile_override_cflags(self->makefile, test_lucy_obj, cflags);
+    chaz_CFlags_destroy(cflags);
+
+    link_flags = chaz_CC_new_cflags();
+    chaz_CFlags_add_library(link_flags, self->shared_lib);
     if (self->cfish_lib_dir) {
-        chaz_CFlags_add_library_path(test_cflags, self->cfish_lib_dir);
+        chaz_CFlags_add_library_path(link_flags, 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_CFlags_add_external_library(link_flags, self->cfish_lib_name);
+    rule = chaz_MakeFile_add_exe(self->makefile, test_lucy_exe, test_lucy_obj,
+                                 link_flags);
     chaz_MakeRule_add_prereq(rule, self->shared_lib_filename);
-    chaz_CFlags_destroy(test_cflags);
+    chaz_CFlags_destroy(link_flags);
 
     rule = chaz_MakeFile_add_rule(self->makefile, "test", test_lucy_exe);
-    if (strcmp(chaz_OS_shared_lib_ext(), ".so") == 0) {
-        if (self->cfish_lib_dir) {
-            test_command
-                = chaz_Util_join("", "LD_LIBRARY_PATH=.:", self->cfish_lib_dir,
-                                 ":$$LD_LIBRARY_PATH ", test_lucy_exe, NULL);
-        }
-        else {
-            test_command
-                = chaz_Util_join(" ", "LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH",
-                                 test_lucy_exe, NULL);
-        }
+    if (self->cfish_lib_dir) {
+        chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".",
+                                               self->cfish_lib_dir, NULL);
     }
     else {
-        test_command = chaz_Util_strdup(test_lucy_exe);
+        chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".", NULL);
     }
-    chaz_MakeRule_add_command(rule, test_command);
 
     if (chaz_CLI_defined(self->cli, "enable-coverage")) {
         rule = chaz_MakeFile_add_rule(self->makefile, "coverage", 
test_lucy_exe);
@@ -590,7 +591,14 @@ lucy_MakeFile_write_c_test_rules(lucy_MakeFile *self) {
                                   "lcov"
                                   " --zerocounters"
                                   " --directory $(BASE_DIR)");
-        chaz_MakeRule_add_command(rule, test_command);
+        if (self->cfish_lib_dir) {
+            chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".",
+                                                   self->cfish_lib_dir, NULL);
+        }
+        else {
+            chaz_MakeRule_add_command_with_libpath(rule, test_lucy_exe, ".",
+                                                   NULL);
+        }
         chaz_MakeRule_add_command(rule,
                                   "lcov"
                                   " --capture"
@@ -610,8 +618,7 @@ lucy_MakeFile_write_c_test_rules(lucy_MakeFile *self) {
     }
 
     free(test_lucy_exe);
-    free(test_lucy_c);
-    free(test_command);
+    free(test_lucy_obj);
 }
 
 static void

Reply via email to