]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Fix Windows quicktest, paths and bats 72/head
authorAnders Björklund <anders@itension.se>
Thu, 18 Feb 2016 21:00:59 +0000 (22:00 +0100)
committerAnders Björklund <anders@itension.se>
Thu, 18 Feb 2016 22:43:29 +0000 (23:43 +0100)
Mostly about path shenaningans, with the drive letter and backslashes
Also hack in some support for running echo command, and batch files.

All tests now pass, at least on Wine (but with some "fixme" warnings):
PASSED: 458 assertions, 89 tests, 10 suites

ccache.c
hashutil.c
test/test_args.c
test/test_argument_processing.c
test/test_conf.c
test/test_hashutil.c
util.c

index f1f1de7866b295d4facf3a0ecedfa2cc9b0f10a1..2d4209a70020d82e576ea2d1d50ceacc94ccde30 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -697,6 +697,11 @@ make_relative_path(char *path)
                return path;
        }
 
+#ifdef _WIN32
+       if (path[0] == '/')
+               path++;  /* skip leading slash */
+#endif
+
        /* x_realpath only works for existing paths, so if path doesn't exist, try
         * dirname(path) and assemble the path afterwards. We only bother to try
         * canonicalizing one of these two paths since a compiler path argument
index 6c4b2799f140eedadb69981c05ee6d6ef3d18331..ad7a56f3142133da37f2ea04b9509f4346ad9c58 100644 (file)
@@ -187,6 +187,7 @@ hash_command_output(struct mdfour *hash, const char *command,
        PROCESS_INFORMATION pi;
        STARTUPINFO si;
        DWORD exitcode;
+       bool cmd = false;
        char *sh = NULL;
        char *win32args;
        char *path;
@@ -198,6 +199,21 @@ hash_command_output(struct mdfour *hash, const char *command,
        int pipefd[2];
 #endif
 
+#ifdef _WIN32
+       /* trim leading space */
+       while (isspace(*command))
+               command++;
+       /* add "echo" command */
+       if (str_startswith(command, "echo")) {
+               command = format("cmd.exe /c \"%s\"", command);
+               cmd = true;
+       } else if (str_startswith(command, "%compiler%") && str_eq(compiler, "echo")) {
+               command = format("cmd.exe /c \"%s%s\"", compiler, command + 10);
+               cmd = true;
+       } else {
+               command = x_strdup(command);
+       }
+#endif
        struct args *args = args_init_from_string(command);
        int i;
        for (i = 0; i < args->argc; i++) {
@@ -225,11 +241,16 @@ hash_command_output(struct mdfour *hash, const char *command,
        si.hStdError = pipe_out[1];
        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
        si.dwFlags = STARTF_USESTDHANDLES;
-       win32args = win32argvtos(sh, args->argv);
+       if (!cmd)
+               win32args = win32argvtos(sh, args->argv);
+       else
+               win32args = (char *) command; /* quoted */
        ret = CreateProcess(path, win32args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
        CloseHandle(pipe_out[1]);
        args_free(args);
        free(win32args);
+       if (cmd)
+               free((char *) command); /* original argument was replaced above */
        if (ret == 0) {
                stats_update(STATS_COMPCHECK);
                return false;
index d0a3bac55ff1235f17f8c4c3367c09df4c8aaca1..5a8a4707c7caec719515ac5063bb8866c66d1789 100644 (file)
@@ -78,7 +78,11 @@ TEST(args_init_from_gcc_atfile)
        CHECK_STR_EQ("fourth", args->argv[3]);
        CHECK_STR_EQ("fif th", args->argv[4]);
        CHECK_STR_EQ("si'x\" th", args->argv[5]);
+#ifndef _WIN32
        CHECK_STR_EQ("seve\nth", args->argv[6]);
+#else
+       CHECK_STR_EQ("seve\r\nth", args->argv[6]);
+#endif
        CHECK(!args->argv[7]);
        args_free(args);
 }
index 67f73718ef164f3b8707622862eda8d58bcb2e88..6fc67ac5ea6a2f71c2fff987d045a209277304ce 100644 (file)
 
 extern struct conf *conf;
 
+static char *
+get_root(void)
+{
+#ifndef _WIN32
+       return x_strdup("/");
+#else
+       char volume[4]; /* "C:\" */
+       GetVolumePathName(get_cwd(), volume, sizeof(volume));
+       return x_strdup(volume);
+#endif
+}
+
+static char *
+get_posix_path(char *path)
+{
+#ifndef _WIN32
+       return x_strdup(path);
+#else
+       char *posix;
+       char *p;
+
+       /* / escape volume */
+       if (path[0] >= 'A' && path[0] <= 'Z' && path[1] == ':')
+               posix = format("/%s", path);
+       else
+               posix = x_strdup(path);
+       /* convert slashes */
+       for (p = posix; *p; p++) {
+               if (*p == '\\')
+                       *p = '/';
+       }
+       return posix;
+#endif
+}
+
 TEST_SUITE(argument_processing)
 
 TEST(dash_E_should_result_in_called_for_preprocessing)
@@ -121,7 +156,7 @@ TEST(sysroot_should_be_rewritten_if_basedir_is_used)
 
        create_file("foo.c", "");
        free(conf->base_dir);
-       conf->base_dir = x_strdup("/");
+       conf->base_dir = get_root();
        current_working_dir = get_cwd();
        arg_string = format("cc --sysroot=%s/foo -c foo.c", current_working_dir);
        orig = args_init_from_string(arg_string);
@@ -309,7 +344,7 @@ TEST(isystem_flag_with_separate_arg_should_be_rewritten_if_basedir_is_used)
 
        create_file("foo.c", "");
        free(conf->base_dir);
-       conf->base_dir = x_strdup("/");
+       conf->base_dir = get_root();
        current_working_dir = get_cwd();
        arg_string = format("cc -isystem %s/foo -c foo.c", current_working_dir);
        orig = args_init_from_string(arg_string);
@@ -326,15 +361,18 @@ TEST(isystem_flag_with_separate_arg_should_be_rewritten_if_basedir_is_used)
 TEST(isystem_flag_with_concat_arg_should_be_rewritten_if_basedir_is_used)
 {
        extern char *current_working_dir;
+       char *cwd;
        char *arg_string;
        struct args *orig;
        struct args *act_cpp = NULL, *act_cc = NULL;
 
        create_file("foo.c", "");
        free(conf->base_dir);
-       conf->base_dir = x_strdup("/");
+       conf->base_dir = x_strdup("/"); /* posix */
        current_working_dir = get_cwd();
-       arg_string = format("cc -isystem%s/foo -c foo.c", current_working_dir);
+       /* windows path don't work concatenated */
+       cwd = get_posix_path(current_working_dir);
+       arg_string = format("cc -isystem%s/foo -c foo.c", cwd);
        orig = args_init_from_string(arg_string);
        free(arg_string);
 
@@ -342,6 +380,7 @@ TEST(isystem_flag_with_concat_arg_should_be_rewritten_if_basedir_is_used)
        CHECK_STR_EQ("-isystem", act_cpp->argv[1]);
        CHECK_STR_EQ("./foo", act_cpp->argv[2]);
 
+       free(cwd);
        args_free(orig);
        args_free(act_cpp);
        args_free(act_cc);
index 749859ab3da15b3b0647b6d62ecc72d05367dae6..6a1524185d02fda08a6a9a12fcf1a9cd7eb4234b 100644 (file)
@@ -92,7 +92,11 @@ TEST(conf_read_valid_config)
        CHECK_STR_EQ("rabbit", user);
        create_file(
          "ccache.conf",
+#ifndef _WIN32
          "base_dir =  /$USER/foo/${USER} \n"
+#else
+         "base_dir = C:/$USER/foo/${USER}\n"
+#endif
          "cache_dir=\n"
          "cache_dir = $USER$/${USER}/.ccache\n"
          "\n"
@@ -128,7 +132,11 @@ TEST(conf_read_valid_config)
        CHECK(conf_read(conf, "ccache.conf", &errmsg));
        CHECK(!errmsg);
 
+#ifndef _WIN32
        CHECK_STR_EQ_FREE1(format("/%s/foo/%s", user, user), conf->base_dir);
+#else
+       CHECK_STR_EQ_FREE1(format("C:/%s/foo/%s", user, user), conf->base_dir);
+#endif
        CHECK_STR_EQ_FREE1(format("%s$/%s/.ccache", user, user), conf->cache_dir);
        CHECK_INT_EQ(4, conf->cache_dir_levels);
        CHECK_STR_EQ("foo", conf->compiler);
index 9b6fd349550ea3a7fed8dcbb20221a92bb7a0faa..aa77066f48cb1dfd1328b0132946e85cdef38d26 100644 (file)
@@ -72,10 +72,16 @@ TEST(hash_command_output_stdout_versus_stderr)
        struct mdfour h1, h2;
        hash_start(&h1);
        hash_start(&h2);
+#ifndef _WIN32
        create_file("stderr.sh", "#!/bin/sh\necho foo >&2\n");
        chmod("stderr.sh", 0555);
        CHECK(hash_command_output(&h1, "echo foo", "not used"));
        CHECK(hash_command_output(&h2, "./stderr.sh", "not used"));
+#else
+       create_file("stderr.bat", "@echo off\r\necho foo>&2\r\n");
+       CHECK(hash_command_output(&h1, "echo foo", "not used"));
+       CHECK(hash_command_output(&h2, "stderr.bat", "not used"));
+#endif
        CHECK(hash_equal(&h1, &h2));
 }
 
@@ -84,10 +90,16 @@ TEST(hash_multicommand_output)
        struct mdfour h1, h2;
        hash_start(&h1);
        hash_start(&h2);
+#ifndef _WIN32
        create_file("foo.sh", "#!/bin/sh\necho foo\necho bar\n");
        chmod("foo.sh", 0555);
        CHECK(hash_multicommand_output(&h2, "echo foo; echo bar", "not used"));
        CHECK(hash_multicommand_output(&h1, "./foo.sh", "not used"));
+#else
+       create_file("foo.bat", "@echo off\r\necho foo\r\necho bar\r\n");
+       CHECK(hash_multicommand_output(&h2, "echo foo; echo bar", "not used"));
+       CHECK(hash_multicommand_output(&h1, "foo.bat", "not used"));
+#endif
        CHECK(hash_equal(&h1, &h2));
 }
 
diff --git a/util.c b/util.c
index f0c7a5e17e188ad2d3bc275537e073ea08620f3c..aa55535353206060a9ed813617e3aa625fd7a681 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1094,6 +1094,8 @@ x_realpath(const char *path)
 #if HAVE_REALPATH
        p = realpath(path, ret);
 #elif defined(_WIN32)
+       if (path[0] == '/')
+               path++;  /* skip leading slash */
        path_handle = CreateFile(
          path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
          FILE_ATTRIBUTE_NORMAL, NULL);
@@ -1339,6 +1341,11 @@ get_relative_path(const char *from, const char *to)
        }
 
 #ifdef _WIN32
+       // Paths can be escaped by a slash for use with -isystem
+       if (from[0] == '/')
+               from++;
+       if (to[0] == '/')
+               to++;
        // Both paths are absolute, drop the drive letters
        assert(from[0] == to[0]); // Assume the same drive letter
        from += 2;