diff -urN ccache-3.2.1.orig/ccache.c ccache-3.2.1.skip/ccache.c --- ccache-3.2.1.orig/ccache.c 2014-12-10 22:40:54.000000000 +0300 +++ ccache-3.2.1.skip/ccache.c 2015-03-20 15:39:13.473971831 +0300 @@ -1210,7 +1210,7 @@ * otherwise NULL. Caller frees. */ static struct file_hash * -calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) +calculate_object_hash(struct args *args, struct args *preprocessor_args, struct mdfour *hash, int direct_mode) { int i; char *manifest_name; @@ -1422,7 +1422,7 @@ cc_log("Did not find object file hash in manifest"); } } else { - object_hash = get_object_name_from_cpp(args, hash); + object_hash = get_object_name_from_cpp(preprocessor_args, hash); cc_log("Got object file hash from preprocessor"); if (generating_dependencies) { cc_log("Preprocessor created %s", output_dep); @@ -1618,7 +1618,7 @@ */ bool cc_process_args(struct args *args, struct args **preprocessor_args, - struct args **compiler_args) + struct args **compiler_args, struct args **hashable_args) { int i; bool found_c_opt = false; @@ -1635,7 +1635,7 @@ bool dependency_filename_specified = false; /* is the dependency makefile target name specified with -MT or -MQ? */ bool dependency_target_specified = false; - struct args *expanded_args, *stripped_args, *dep_args, *cpp_args; + struct args *expanded_args, *stripped_args, *dep_args, *cpp_args, *nonhash_args; int argc; char **argv; bool result = true; @@ -1645,6 +1645,7 @@ stripped_args = args_init(0, NULL); dep_args = args_init(0, NULL); cpp_args = args_init(0, NULL); + nonhash_args = args_init(0, NULL); argc = expanded_args->argc; argv = expanded_args->argv; @@ -1660,7 +1661,7 @@ result = false; goto out; } - args_add(stripped_args, argv[i]); + args_add(nonhash_args, argv[i]); continue; } @@ -2388,11 +2389,18 @@ *preprocessor_args = args_copy(stripped_args); args_extend(*preprocessor_args, cpp_args); + *hashable_args = args_copy(*preprocessor_args); + + /* Append args which we don't want to be hashed */ + args_extend(*compiler_args, nonhash_args); + args_extend(*preprocessor_args, nonhash_args); + out: args_free(expanded_args); args_free(stripped_args); args_free(dep_args); args_free(cpp_args); + args_free(nonhash_args); return result; } @@ -2587,6 +2595,9 @@ struct mdfour direct_hash; struct mdfour cpp_hash; + /* Arguments (except marked with --ccache-skip) to add to hash */ + struct args *hash_args; + /* Arguments (except -E) to send to the preprocessor. */ struct args *preprocessor_args; @@ -2628,7 +2639,7 @@ conf->direct_mode = false; } - if (!cc_process_args(orig_args, &preprocessor_args, &compiler_args)) { + if (!cc_process_args(orig_args, &preprocessor_args, &compiler_args, &hash_args)) { failed(); } @@ -2642,13 +2653,13 @@ cc_log("Object file: %s", output_obj); hash_start(&common_hash); - calculate_common_hash(preprocessor_args, &common_hash); + calculate_common_hash(hash_args, &common_hash); /* try to find the hash using the manifest */ direct_hash = common_hash; if (conf->direct_mode) { cc_log("Trying direct lookup"); - object_hash = calculate_object_hash(preprocessor_args, &direct_hash, 1); + object_hash = calculate_object_hash(hash_args, preprocessor_args, &direct_hash, 1); if (object_hash) { update_cached_result_globals(object_hash); @@ -2682,7 +2693,7 @@ * included_files. */ cpp_hash = common_hash; - object_hash = calculate_object_hash(preprocessor_args, &cpp_hash, 0); + object_hash = calculate_object_hash(hash_args, preprocessor_args, &cpp_hash, 0); if (!object_hash) { fatal("internal error: object hash from cpp returned NULL"); } diff -urN ccache-3.2.1.orig/ccache.h ccache-3.2.1.skip/ccache.h --- ccache-3.2.1.orig/ccache.h 2014-12-10 22:40:54.000000000 +0300 +++ ccache-3.2.1.skip/ccache.h 2015-03-18 15:40:12.000000000 +0300 @@ -224,7 +224,7 @@ extern time_t time_of_compilation; bool cc_process_args(struct args *args, struct args **preprocessor_args, - struct args **compiler_args); + struct args **compiler_args, struct args **hashable_args); void cc_reset(void); bool is_precompiled_header(const char *path); diff -urN ccache-3.2.1.orig/test/test_argument_processing.c ccache-3.2.1.skip/test/test_argument_processing.c --- ccache-3.2.1.orig/test/test_argument_processing.c 2014-12-10 22:40:54.000000000 +0300 +++ ccache-3.2.1.skip/test/test_argument_processing.c 2015-03-20 15:34:23.000000000 +0300 @@ -32,10 +32,10 @@ TEST(dash_E_should_result_in_called_for_preprocessing) { struct args *orig = args_init_from_string("cc -c foo.c -E"); - struct args *preprocessed, *compiler; + struct args *preprocessed, *compiler, *hashable; create_file("foo.c", ""); - CHECK(!cc_process_args(orig, &preprocessed, &compiler)); + CHECK(!cc_process_args(orig, &preprocessed, &compiler, &hashable)); CHECK_INT_EQ(1, stats_get_pending(STATS_PREPROCESSING)); args_free(orig); @@ -44,10 +44,10 @@ TEST(dash_M_should_be_unsupported) { struct args *orig = args_init_from_string("cc -c foo.c -M"); - struct args *preprocessed, *compiler; + struct args *preprocessed, *compiler, *hashable; create_file("foo.c", ""); - CHECK(!cc_process_args(orig, &preprocessed, &compiler)); + CHECK(!cc_process_args(orig, &preprocessed, &compiler, &hashable)); CHECK_INT_EQ(1, stats_get_pending(STATS_UNSUPPORTED)); args_free(orig); @@ -62,12 +62,15 @@ struct args *exp_cpp = args_init_from_string(CMD); #undef CMD struct args *exp_cc = args_init_from_string("cc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -85,12 +88,15 @@ struct args *exp_cpp = args_init_from_string(CMD); #undef CMD struct args *exp_cc = args_init_from_string("cc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -102,12 +108,15 @@ struct args *exp_cpp = args_init_from_string( "cc -MMD -MFfoo.d -MT mt -MTmt -MQmq"); struct args *exp_cc = args_init_from_string("cc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -117,7 +126,7 @@ extern char *current_working_dir; char *arg_string; struct args *orig; - struct args *act_cpp = NULL, *act_cc = NULL; + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); free(conf->base_dir); @@ -126,12 +135,13 @@ arg_string = format("cc --sysroot=%s/foo -c foo.c", current_working_dir); orig = args_init_from_string(arg_string); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK(str_startswith(act_cpp->argv[1], "--sysroot=./foo")); args_free(orig); args_free(act_cpp); args_free(act_cc); + args_free(act_hash); } TEST(MF_flag_with_immediate_argument_should_work_as_last_argument) @@ -141,12 +151,15 @@ struct args *exp_cpp = args_init_from_string( "cc -MMD -MT bar -MFfoo.d"); struct args *exp_cc = args_init_from_string("cc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -158,12 +171,15 @@ struct args *exp_cpp = args_init_from_string( "cc -MMD -MFfoo.d -MT foo -MTbar"); struct args *exp_cc = args_init_from_string("cc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -175,12 +191,15 @@ struct args *exp_cpp = args_init_from_string( "cc -MMD -MFfoo.d -MQ foo -MQbar"); struct args *exp_cc = args_init_from_string("cc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -192,12 +211,15 @@ struct args *exp_cpp = args_init_from_string( "gcc -MD -MP -MFfoo.d -MQ foo.d"); struct args *exp_cc = args_init_from_string("gcc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -209,12 +231,15 @@ struct args *exp_cpp = args_init_from_string( "gcc -MD -MP -MFfoo.d -MT foo.d"); struct args *exp_cc = args_init_from_string("gcc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -226,12 +251,15 @@ struct args *exp_cpp = args_init_from_string( "gcc -MD -MP -MFfoo.d -MQfoo.d"); struct args *exp_cc = args_init_from_string("gcc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -243,12 +271,15 @@ struct args *exp_cpp = args_init_from_string( "gcc -MD -MP -MFfoo.d -MTfoo.d"); struct args *exp_cc = args_init_from_string("gcc -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -259,7 +290,9 @@ "gcc -c -fprofile-generate=some/dir foo.c"); struct args *exp_cpp = args_init_from_string("gcc"); struct args *exp_cc = args_init_from_string("gcc"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; char *s; create_file("foo.c", ""); @@ -267,13 +300,15 @@ mkdir("some/dir", 0777); s = format("-fprofile-generate=%s", x_realpath("some/dir")); args_add(exp_cpp, s); + args_add(exp_hash, s); args_add(exp_cc, s); args_add(exp_cc, "-c"); free(s); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); } @@ -286,13 +321,34 @@ "gcc -fprofile-generate=some/dir"); struct args *exp_cc = args_init_from_string( "gcc -fprofile-generate=some/dir -c"); - struct args *act_cpp = NULL, *act_cc = NULL; + /* hashable args are the same as preprocessor, unless there's --ccache-skip */ + struct args *exp_hash = args_copy(exp_cpp); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; create_file("foo.c", ""); - CHECK(cc_process_args(orig, &act_cpp, &act_cc)); + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); + + args_free(orig); +} + +TEST(ccache_skip_flag_should_affect_hashing) +{ + struct args *orig = args_init_from_string("cc -c foo.c --ccache-skip -DSOME"); + struct args *exp_cpp = args_init_from_string("cc -DSOME"); + struct args *exp_cc = args_init_from_string("cc -c -DSOME"); + struct args *exp_hash = args_init_from_string("cc"); + struct args *act_cpp = NULL, *act_cc = NULL, *act_hash = NULL; + + create_file("foo.c", ""); + + CHECK(cc_process_args(orig, &act_cpp, &act_cc, &act_hash)); + CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp); + CHECK_ARGS_EQ_FREE12(exp_cc, act_cc); + CHECK_ARGS_EQ_FREE12(exp_hash, act_hash); args_free(orig); }