Hello,

 the attached patches modify ccache to also support Clang PCH in addition to 
GCC PCH.

 The changes are:

- Clang uses .pch as the extension, not .gch
- the .pch file can be directly passed using -include-pch, instead of 
using -include and trying to find the .pch file
- the use of a .pch is not reflected in the resulting .ii , so it needs to be 
explicitly added to the hash for checking if used files have changed
- I also believe that path_len passed to remember_include_file() is incorrect, 
as make_relative_path() may change the string

PS: Since I've noticed in the archives the recent mail about issues with 
ccache and warnings about unused arguments: The proper way to use ccache with 
Clang is to set CCACHE_CPP2, which not only avoids these warnings, but in 
general Clang works suboptimally if passed preprocessed output (warning/error 
messages quoting sources are affected, some warnings are not supressed in 
headers).

-- 
 Lubos Lunak
 l.lu...@suse.cz
From 768ffacb434d116759fc73cf0d2723aba6b5af4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= <l.lu...@suse.cz>
Date: Fri, 6 Jul 2012 18:09:36 +0200
Subject: [PATCH 1/3] support for precompiled headers with clang

Support the clang-specific -include-pch option, which references
the PCH file itself, and support the .pch extension when using
the gcc -include way.
---
 MANUAL.txt |    2 ++
 ccache.c   |   29 +++++++++++++++++++++--------
 compopt.c  |    1 +
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/MANUAL.txt b/MANUAL.txt
index 4be33ae..478d36b 100644
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -629,6 +629,8 @@ things to make it work properly:
 --
 ** use the *-include* compiler option to include the precompiled header
    (i.e., don't use *#include* in the source code to include the header); or
+** (Clang compiler) use the *-include-pch* compiler option to include
+   the PCH file generated from the precompiled header; or
 ** add the *-fpch-preprocess* compiler option when compiling.
 
 If you don't do this, either the non-precompiled version of the header file
diff --git a/ccache.c b/ccache.c
index 8b50c36..12b62a4 100644
--- a/ccache.c
+++ b/ccache.c
@@ -167,7 +167,7 @@ static bool profile_use = false;
 static bool profile_generate = false;
 
 /*
- * Whether we are using a precompiled header (either via -include or #include).
+ * Whether we are using a precompiled header (either via -include, #include or clang's -include-pch).
  */
 static bool using_precompiled_header = false;
 
@@ -1355,7 +1355,7 @@ find_compiler(char** argv)
 bool
 is_precompiled_header(const char *path)
 {
-	return str_eq(get_extension(path), ".gch");
+	return str_eq(get_extension(path), ".gch") || str_eq(get_extension(path), ".pch");
 }
 
 /*
@@ -1680,7 +1680,6 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
 		 */
 		if (compopt_takes_path(argv[i])) {
 			char *relpath;
-			char *pchpath;
 			if (i == argc-1) {
 				cc_log("Missing argument to %s", argv[i]);
 				stats_update(STATS_ARGS);
@@ -1693,13 +1692,27 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
 			args_add(stripped_args, relpath);
 
 			/* Try to be smart about detecting precompiled headers */
-			pchpath = format("%s.gch", argv[i+1]);
-			if (stat(pchpath, &st) == 0) {
-				cc_log("Detected use of precompiled header: %s", pchpath);
-				found_pch = true;
+			if (str_eq(argv[i], "-include-pch")) {
+				if (stat(argv[i+1], &st) == 0) {
+					cc_log("Detected use of precompiled header: %s", argv[i+1]);
+					found_pch = true;
+				}
+			} else {
+				char* gchpath = format("%s.gch", argv[i+1]);
+				if (stat(gchpath, &st) == 0) {
+					cc_log("Detected use of precompiled header: %s", gchpath);
+					found_pch = true;
+				} else {
+					char* pchpath = format("%s.pch", argv[i+1]);
+					if (stat(pchpath, &st) == 0) {
+						cc_log("Detected use of precompiled header: %s", pchpath);
+						found_pch = true;
+					}
+					free(pchpath);
+				}
+				free(gchpath);
 			}
 
-			free(pchpath);
 			free(relpath);
 			i++;
 			continue;
diff --git a/compopt.c b/compopt.c
index 77b57f5..908302e 100644
--- a/compopt.c
+++ b/compopt.c
@@ -61,6 +61,7 @@ static const struct compopt compopts[] = {
 	{"-imacros",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
 	{"-imultilib",      AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
 	{"-include",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
+	{"-include-pch",    AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
 	{"-install_name",   TAKES_ARG}, /* Darwin linker option */
 	{"-iprefix",        AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
 	{"-iquote",         AFFECTS_CPP | TAKES_ARG | TAKES_PATH},
-- 
1.7.7

From bbfc0ed55a6f730023d068773fc9fece16b94c74 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= <l.lu...@suse.cz>
Date: Fri, 6 Jul 2012 18:46:25 +0200
Subject: [PATCH 3/3] do not pass incorrect length to remember_include_file()

---
 ccache.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/ccache.c b/ccache.c
index 8f30005..e9a9b4d 100644
--- a/ccache.c
+++ b/ccache.c
@@ -307,7 +307,7 @@ get_path_in_cache(const char *name, const char *suffix)
  * also updated. Takes over ownership of path.
  */
 static void
-remember_include_file(char *path, size_t path_len, struct mdfour *cpp_hash)
+remember_include_file(char *path, struct mdfour *cpp_hash)
 {
 #ifdef _WIN32
 	DWORD attributes;
@@ -318,6 +318,7 @@ remember_include_file(char *path, size_t path_len, struct mdfour *cpp_hash)
 	size_t size;
 	int result;
 	bool is_pch;
+	size_t path_len = strlen(path);
 
 	if (path_len >= 2 && (path[0] == '<' && path[path_len - 1] == '>')) {
 		/* Typically <built-in> or <command-line>. */
@@ -528,7 +529,7 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
 			path = x_strndup(p, q - p);
 			path = make_relative_path(path);
 			hash_string(hash, path);
-			remember_include_file(path, q - p, hash);
+			remember_include_file(path, hash);
 			p = q;
 		} else {
 			q++;
@@ -544,7 +545,7 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
 		char *path = x_strdup(included_pch_file);
 		path = make_relative_path(path);
 		hash_string(hash, path);
-		remember_include_file(path, strlen(included_pch_file), hash);
+		remember_include_file(path, hash);
 	}
 
 	return true;
-- 
1.7.7

From 0675b3b406e544f3c33cc73d6d41dbed19bb40d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= <l.lu...@suse.cz>
Date: Fri, 6 Jul 2012 18:45:05 +0200
Subject: [PATCH 2/3] hash clang's .pch file explicitly

It does not appear anywhere in the preprocessed output, so
process_preprocessed_file() would miss it.
---
 ccache.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/ccache.c b/ccache.c
index 12b62a4..8f30005 100644
--- a/ccache.c
+++ b/ccache.c
@@ -171,6 +171,11 @@ static bool profile_generate = false;
  */
 static bool using_precompiled_header = false;
 
+/*
+ * The .gch/.pch file used for compilation.
+ */
+static char *included_pch_file = NULL;
+
 /* How long (in microseconds) to wait before breaking a stale lock. */
 unsigned lock_staleness_limit = 2000000;
 
@@ -532,6 +537,16 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
 
 	hash_buffer(hash, p, (end - p));
 	free(data);
+
+	/* Explicitly check the .gch/.pch file, Clang does not include any mention of it
+	   in the preprocessed output. */
+	if (included_pch_file) {
+		char *path = x_strdup(included_pch_file);
+		path = make_relative_path(path);
+		hash_string(hash, path);
+		remember_include_file(path, strlen(included_pch_file), hash);
+	}
+
 	return true;
 }
 
@@ -1680,6 +1695,7 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
 		 */
 		if (compopt_takes_path(argv[i])) {
 			char *relpath;
+			char *pch_file = NULL;
 			if (i == argc-1) {
 				cc_log("Missing argument to %s", argv[i]);
 				stats_update(STATS_ARGS);
@@ -1696,23 +1712,37 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
 				if (stat(argv[i+1], &st) == 0) {
 					cc_log("Detected use of precompiled header: %s", argv[i+1]);
 					found_pch = true;
+					pch_file = x_strdup(argv[i+1]);
 				}
 			} else {
 				char* gchpath = format("%s.gch", argv[i+1]);
 				if (stat(gchpath, &st) == 0) {
 					cc_log("Detected use of precompiled header: %s", gchpath);
 					found_pch = true;
+					pch_file = x_strdup(gchpath);
 				} else {
 					char* pchpath = format("%s.pch", argv[i+1]);
 					if (stat(pchpath, &st) == 0) {
 						cc_log("Detected use of precompiled header: %s", pchpath);
 						found_pch = true;
 					}
+					pch_file = x_strdup(pchpath);
 					free(pchpath);
 				}
 				free(gchpath);
 			}
 
+			if (pch_file) {
+				if (included_pch_file) {
+					cc_log("Multiple precompiled headers used: %s and %s\n",
+					    included_pch_file, pch_file);
+					stats_update(STATS_ARGS);
+					result = false;
+					goto out;
+				}
+				included_pch_file = pch_file;
+			}
+
 			free(relpath);
 			i++;
 			continue;
@@ -2083,6 +2113,7 @@ cc_reset(void)
 	free(secondary_config_path); secondary_config_path = NULL;
 	free(current_working_dir); current_working_dir = NULL;
 	free(profile_dir); profile_dir = NULL;
+	free(included_pch_file); included_pch_file = NULL;
 	args_free(orig_args); orig_args = NULL;
 	free(input_file); input_file = NULL;
 	free(output_obj); output_obj = NULL;
-- 
1.7.7

_______________________________________________
ccache mailing list
ccache@lists.samba.org
https://lists.samba.org/mailman/listinfo/ccache

Reply via email to