Imported Upstream version 3.6 upstream/3.6
authorJinWang An <jinwang.an@samsung.com>
Tue, 3 Aug 2021 07:28:05 +0000 (16:28 +0900)
committerJinWang An <jinwang.an@samsung.com>
Tue, 3 Aug 2021 07:28:05 +0000 (16:28 +0900)
40 files changed:
LICENSE.adoc
LICENSE.html
Makefile.in
config.h.in
configure
configure.ac
dev.mk.in
doc/AUTHORS.adoc
doc/AUTHORS.html
doc/MANUAL.adoc
doc/MANUAL.html
doc/NEWS.adoc
doc/NEWS.html
doc/ccache.1
src/ccache.c
src/ccache.h
src/compopt.c
src/conf.c
src/conf.h
src/confitems.c
src/confitems.gperf
src/confitems_lookup.c
src/envtoconfitems.gperf
src/envtoconfitems_lookup.c
src/getopt_long.c
src/hashutil.c
src/system.h
src/util.c
src/version.c
test/run
test/suites/base.bash
test/suites/depend.bash [new file with mode: 0644]
test/suites/direct.bash
test/suites/direct_gcc.bash [new file with mode: 0644]
test/suites/hardlink.bash
test/suites/sanitize_blacklist.bash
unittest/test_argument_processing.c
unittest/test_compopt.c
unittest/test_conf.c
unittest/test_hashutil.c

index 007617ec7d79d7b7d9e29f795c90bef27eb5b15a..4888b83b00042c2902c0e4d58a1105c7a69979f4 100644 (file)
@@ -29,7 +29,7 @@ Copyright and authors
 ---------------------
 
 ccache is a collective work with contributions from many people, listed in
-AUTHORS.adoc and at https://ccache.samba.org/authors.html. Subsequent additions
+AUTHORS.adoc and at https://ccache.samba.org/credits.html. Subsequent additions
 by contributing authors are implicitly licensed to the public under the same
 terms (GNU GPL version 3 or later), but the contributing authors retain
 copyrights on their portions of the work.
index 8a9bf9bd97982fc8f1ee54ffadc0b6ab0029b013..68719191f41af1ca065dbba0cc922e171ba94cb8 100644 (file)
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <body class="article">\r
 <div id="header">\r
 <h1>ccache copyright and license</h1>\r
-<span id="revnumber">version 3.5.1</span>\r
+<span id="revnumber">version 3.6</span>\r
 <div id="toc">
   <div id="toctitle">Table of Contents</div>
   <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
@@ -769,7 +769,7 @@ asciidoc.install(2);
 <h2 id="_copyright_and_authors">Copyright and authors</h2>\r
 <div class="sectionbody">\r
 <div class="paragraph"><p>ccache is a collective work with contributions from many people, listed in\r
-AUTHORS.adoc and at <a href="https://ccache.samba.org/authors.html">https://ccache.samba.org/authors.html</a>. Subsequent additions\r
+AUTHORS.adoc and at <a href="https://ccache.samba.org/credits.html">https://ccache.samba.org/credits.html</a>. Subsequent additions\r
 by contributing authors are implicitly licensed to the public under the same\r
 terms (GNU GPL version 3 or later), but the contributing authors retain\r
 copyrights on their portions of the work.</p></div>\r
@@ -1206,9 +1206,9 @@ following license:</p></div>
 <div id="footnotes"><hr /></div>\r
 <div id="footer">\r
 <div id="footer-text">\r
-Version 3.5.1<br />\r
+Version 3.6<br />\r
 Last updated\r
- 2019-01-03 19:29:09 CET\r
+ 2019-01-13 21:38:14 CET\r
 </div>\r
 </div>\r
 </body>\r
index 9e90755d8daf8583d19590fbc87dc5f9ccd7429b..83beae1ef6826d819bfa849469365c381a217d74 100644 (file)
@@ -49,11 +49,11 @@ non_3pp_sources = \
     src/unify.c \
     src/util.c
 generated_sources = \
-    src/version.c
-3pp_sources = \
-    @getopt_long_c@ \
     src/confitems_lookup.c \
     src/envtoconfitems_lookup.c \
+    src/version.c
+3pp_sources = \
+    src/getopt_long.c \
     src/hashtable.c \
     src/hashtable_itr.c \
     src/murmurhashneutral2.c \
index f990225711bf1efd0290aba55f8210476656748b..1493ab9906e1320a43485c20b5a321be3d085bb5 100644 (file)
@@ -70,6 +70,9 @@
 /* Define to 1 if you have the `realpath' function. */
 #undef HAVE_REALPATH
 
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
 /* Define to 1 if you have a C99 compliant `snprintf' function. */
 #undef HAVE_SNPRINTF
 
index a0dcbb4fef69aff96375899f8cded6e5e9b39bce..b13d086766d40de481981a42123a2459acc9c665 100755 (executable)
--- a/configure
+++ b/configure
@@ -641,7 +641,6 @@ test_suites
 no_implicit_fallthrough_warning
 more_warnings
 include_dev_mk
-getopt_long_c
 extra_libs
 disable_man
 host_os
@@ -2355,6 +2354,9 @@ case $host in
 
 $as_echo "#define _WIN32_WINNT 0x0600" >>confdefs.h
 
+        ;;
+    *os400* | *aix*)
+        AR="ar -X64"
         ;;
 esac
 
@@ -2366,7 +2368,6 @@ esac
 
 
 
-
 # The later defininition of _XOPEN_SOURCE disables certain features
 # on Linux, so we need _GNU_SOURCE to re-enable them (makedev, tm_zone).
 
@@ -4680,6 +4681,17 @@ _ACEOF
 fi
 done
 
+for ac_func in setenv
+do :
+  ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv"
+if test "x$ac_cv_func_setenv" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SETENV 1
+_ACEOF
+
+fi
+done
+
 for ac_func in strndup
 do :
   ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup"
@@ -4725,10 +4737,6 @@ fi
 done
 
 
-if test x"$ac_cv_func_getopt_long" != x"yes"; then
-    getopt_long_c="src/getopt_long.c"
-fi
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compar_fn_t in stdlib.h" >&5
 $as_echo_n "checking for compar_fn_t in stdlib.h... " >&6; }
 if ${ccache_cv_COMPAR_FN_T+:} false; then :
@@ -7638,7 +7646,7 @@ cat <<EOF >config.h.tmp
 #define CCACHE_CONFIG_H
 #ifdef __clang__
 #pragma clang diagnostic push
-#if __clang_major__ >= 4
+#if __has_warning("-Wreserved-id-macro")
 #pragma clang diagnostic ignored "-Wreserved-id-macro"
 #endif
 #endif
index d354ee18196691aa3f58b38eef42f7763d8cf757..761fbdd8df9af1b12dc3564eeea03ca10e5d3863 100644 (file)
@@ -14,11 +14,13 @@ case $host in
         windows_os=yes
         AC_DEFINE(_WIN32_WINNT,0x0600, Windows Vista or newer is required)
         ;;
+    *os400* | *aix*)
+        AR="ar -X64"
+        ;;
 esac
 
 AC_SUBST(disable_man)
 AC_SUBST(extra_libs)
-AC_SUBST(getopt_long_c)
 AC_SUBST(include_dev_mk)
 AC_SUBST(more_warnings)
 AC_SUBST(no_implicit_fallthrough_warning)
@@ -86,15 +88,12 @@ AC_CHECK_FUNCS(getpwuid)
 AC_CHECK_FUNCS(gettimeofday)
 AC_CHECK_FUNCS(mkstemp)
 AC_CHECK_FUNCS(realpath)
+AC_CHECK_FUNCS(setenv)
 AC_CHECK_FUNCS(strndup)
 AC_CHECK_FUNCS(strtok_r)
 AC_CHECK_FUNCS(unsetenv)
 AC_CHECK_FUNCS(utimes)
 
-if test x"$ac_cv_func_getopt_long" != x"yes"; then
-    getopt_long_c="src/getopt_long.c"
-fi
-
 AC_CACHE_CHECK([for compar_fn_t in stdlib.h],ccache_cv_COMPAR_FN_T, [
     AC_TRY_COMPILE(
         [#include <stdlib.h>],
@@ -236,7 +235,7 @@ cat <<EOF >config.h.tmp
 #define CCACHE_CONFIG_H
 #ifdef __clang__
 #pragma clang diagnostic push
-#if __clang_major__ >= 4
+#if __has_warning("-Wreserved-id-macro")
 #pragma clang diagnostic ignored "-Wreserved-id-macro"
 #endif
 #endif
index a1ee9692e9c1b3dce546dbb1d110e4c34d725be9..cf6e17c71dec0fca1766eaecef9246bdbdfd5f5d 100644 (file)
--- a/dev.mk.in
+++ b/dev.mk.in
@@ -9,6 +9,8 @@ CPPCHECK = cppcheck
 CPPCHECK_SUPPRESSIONS = misc/cppcheck-suppressions.txt
 SHELLCHECK = shellcheck
 SHELLCHECK_EXCLUDES = misc/shellcheck-excludes.txt
+COMPILEDB = compiledb
+CLANG_TIDY = clang-tidy
 SCAN_BUILD = scan-build
 DOCKER = docker
 GPERF = gperf
@@ -60,6 +62,9 @@ generated_headers = \
     unittest/suites.h
 
 files_to_clean += *.tar.bz2 *.tar.gz *.tar.xz *.xml .deps/* perfdir.*
+files_to_clean += compile_commands.json
+files_to_clean += src/confitems_lookup.c
+files_to_clean += src/envtoconfitems_lookup.c
 files_to_distclean += $(built_dist_files) src/version.c unittest/suites.h
 files_to_distclean += .deps dev.mk
 
@@ -89,7 +94,6 @@ source_dist_files = \
     src/confitems_lookup.c \
     src/envtoconfitems.gperf \
     src/envtoconfitems_lookup.c \
-    src/getopt_long.c \
     src/main.c \
     src/zlib/*.c \
     src/zlib/*.h \
@@ -111,10 +115,23 @@ ifneq ($(shell sed 's/.*"\(.*\)".*/\1/' src/version.c 2>/dev/null),$(version))
 endif
 src/version.o: src/version.c
 
-%_lookup.c: %.gperf
-       $(if $(quiet),@echo "  GPERF    $@")
-       $(Q)$(GPERF) $< >$@
-       $(Q)echo "size_t $$(echo '$(notdir $*)_count(void)') { return $$(sed -nr 's/.*TOTAL_KEYWORDS = (.+),.*/\1/p' $@); }" >>$@
+# $(1): Name.
+# $(2): Command for fixing up source file before the gperf call.
+define generate_gperf_lookup
+src/$(1)_lookup.c: src/$(1).gperf
+       $$(if $$(quiet),@echo "  GEN      $$@")
+       $$(Q)$(2) $$< | $$(GPERF) | sed 's/#error/#warning/' >$$@.tmp
+# Fix for gperf < 3.1 (fix parameter type and remove inlining of the get function):
+       $$(Q)perl -00 -pi -e 's/unsigned int len/size_t len/; s/#ifdef __GNUC__.*?gnu_inline.*?#endif\n#endif\n//sg' $$@.tmp
+       $$(Q)echo "size_t $(1)_count(void) { return $$$$(perl -ne '/TOTAL_KEYWORDS = (.+?),/ && print $$$$1' $$@.tmp); }" >>$$@.tmp
+       $$(Q)mv $$@.tmp $$@
+endef
+
+add_confitems_numbers = \
+    perl -pae '$$$$s = 1 if /^%%/; s/ITEM/$$$$n++ . ", ITEM"/e if $$$$s == 1'
+
+$(eval $(call generate_gperf_lookup,confitems,$(add_confitems_numbers)))
+$(eval $(call generate_gperf_lookup,envtoconfitems,cat))
 
 .PHONY: dist
 dist: $(dist_archives)
@@ -195,7 +212,7 @@ cppcheck:
        $(CPPCHECK) --suppressions-list=$(CPPCHECK_SUPPRESSIONS) \
          --inline-suppr -q --enable=all --force -I . \
          --template='cppcheck: warning: {id}:{file}:{line}: {message}' \
-         $(non_3pp_sources) src/main.c $(test_sources)
+         $(non_3pp_sources) src/confitems_lookup.c src/main.c $(test_sources)
 
 .PHONY: shellcheck
 shellcheck: test/suites/*.bash
@@ -205,14 +222,26 @@ shellcheck: test/suites/*.bash
 uncrustify:
        uncrustify -c misc/uncrustify.cfg --no-backup --replace $(filter-out $(uncrustify_exclude_files), $(base_sources)) $(test_sources)
 
+# pip install compiledb
+compile_commands.json:
+       $(COMPILEDB) -n $(MAKE) all unittest
+
+.PHONY: tidy
+tidy: compile_commands.json
+       $(CLANG_TIDY) $(all_sources)
+
 .PHONY: analyze
 analyze:
        $(SCAN_BUILD) --use-cc=$(CC) $(srcdir)/configure
        $(SCAN_BUILD) --use-cc=$(CC) --status-bugs $(MAKE) -B
 
+BUILDENV = ubuntu
+DOCKER_IMAGE_TAG = ccache/build:$(BUILDENV)
+
 .PHONY: docker
-docker: misc/Dockerfile
-       $(DOCKER) build -f $< $(srcdir)
+docker: buildenv/$(BUILDENV)/Dockerfile
+       $(DOCKER) inspect $(DOCKER_IMAGE_TAG) >/dev/null || $(DOCKER) build -t $(DOCKER_IMAGE_TAG) buildenv/$(BUILDENV)
+       $(DOCKER) run --rm -v $(PWD):/build -w /build $(DOCKER_IMAGE_TAG) misc/build.sh $(TEST)
 
 .PHONY: travis
 travis: .travis/Dockerfile
index 62de02fa9b9dd72f5ee44427c1cbe4280081e550..f9c665bf63234be28ca7109b38f8c4d43a593c7e 100644 (file)
@@ -31,11 +31,14 @@ ccache is a collective work with contributions from many people, including:
 * Hongli Lai <hongli@phusion.nl>
 * Ivan Vaigult <i.vaigult@gmail.com>
 * Jiang Jiang <jiangj@opera.com>
+* Joel Galenson <jgalenson@gmail.com>
 * Joel Rosdahl <joel@rosdahl.net>
 * John Basila <jbasila@checkpoint.com>
 * John Coiner <john.coiner@amd.com>
 * Jon Bernard <jbernard@tuxion.com>
+* Jonny Yu <yingshen.yu@gmail.com>
 * Jørgen P. Tjernø <jorgen@valvesoftware.com>
+* Josh Soref <jsoref@users.noreply.github.com>
 * Justin Lebar <justin.lebar@gmail.com>
 * Karl Chen <quarl@cs.berkeley.edu>
 * Kona Blend <kona8lend@gmail.com>
@@ -44,6 +47,7 @@ ccache is a collective work with contributions from many people, including:
 * Lars Gustäbel <lars@gustaebel.de>
 * Leanid Chaika <leanid.chaika@gmail.com>
 * Luboš Luňák <l.lunak@centrum.cz>
+* Maarten Maathuis <madman2003@shikahr.net>
 * Mark Starovoytov <starovoytov.mark@googlemail.com>
 * Martin Ettl <ettl.martin78@gmail.com>
 * Martin Pool <mbp@sourcefrog.net>
@@ -52,6 +56,7 @@ ccache is a collective work with contributions from many people, including:
 * Melven Roehrig-Zoellner <Melven.Roehrig-Zoellner@DLR.de>
 * Michael Marineau <michael.marineau@coreos.com>
 * Michael Meeks <michael.meeks@suse.com>
+* Michał Mirosław <mirq-linux@rere.qmqm.pl>
 * Mihai Serban <mihai.serban@intel.com>
 * Mike Frysinger <vapier@gentoo.org>
 * Mike Gulick <mgulick@mathworks.com>
@@ -90,5 +95,6 @@ ccache is a collective work with contributions from many people, including:
 * Wilson Snyder <wsnyder@wsnyder.org>
 * Xavier René-Corail <xavier.renecorail@gmail.com>
 * Yiding Jia <yiding@fb.com>
+* Yvan Janssens <friedkiwi@yvanj.me>
 
 Thanks!
index 169a501e34aad88507fa6978383acffef31dfa26..aacab33641c1d9deb74cc46a47f7564c5959ea4e 100644 (file)
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <body class="article">\r
 <div id="header">\r
 <h1>ccache authors</h1>\r
-<span id="revnumber">version 3.5.1</span>\r
+<span id="revnumber">version 3.6</span>\r
 <div id="toc">
   <div id="toctitle">Table of Contents</div>
   <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
@@ -875,6 +875,11 @@ Jiang Jiang &lt;<a href="mailto:jiangj@opera.com">jiangj@opera.com</a>&gt;
 </li>\r
 <li>\r
 <p>\r
+Joel Galenson &lt;<a href="mailto:jgalenson@gmail.com">jgalenson@gmail.com</a>&gt;\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
 Joel Rosdahl &lt;<a href="mailto:joel@rosdahl.net">joel@rosdahl.net</a>&gt;\r
 </p>\r
 </li>\r
@@ -895,11 +900,21 @@ Jon Bernard &lt;<a href="mailto:jbernard@tuxion.com">jbernard@tuxion.com</a>&gt;
 </li>\r
 <li>\r
 <p>\r
+Jonny Yu &lt;<a href="mailto:yingshen.yu@gmail.com">yingshen.yu@gmail.com</a>&gt;\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
 Jørgen P. Tjernø &lt;<a href="mailto:jorgen@valvesoftware.com">jorgen@valvesoftware.com</a>&gt;\r
 </p>\r
 </li>\r
 <li>\r
 <p>\r
+Josh Soref &lt;<a href="mailto:jsoref@users.noreply.github.com">jsoref@users.noreply.github.com</a>&gt;\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
 Justin Lebar &lt;<a href="mailto:justin.lebar@gmail.com">justin.lebar@gmail.com</a>&gt;\r
 </p>\r
 </li>\r
@@ -940,6 +955,11 @@ Luboš Luňák &lt;<a href="mailto:l.lunak@centrum.cz">l.lunak@centrum.cz</a>&gt
 </li>\r
 <li>\r
 <p>\r
+Maarten Maathuis &lt;<a href="mailto:madman2003@shikahr.net">madman2003@shikahr.net</a>&gt;\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
 Mark Starovoytov &lt;<a href="mailto:starovoytov.mark@googlemail.com">starovoytov.mark@googlemail.com</a>&gt;\r
 </p>\r
 </li>\r
@@ -980,6 +1000,11 @@ Michael Meeks &lt;<a href="mailto:michael.meeks@suse.com">michael.meeks@suse.com
 </li>\r
 <li>\r
 <p>\r
+Michał Mirosław &lt;<a href="mailto:mirq-linux@rere.qmqm.pl">mirq-linux@rere.qmqm.pl</a>&gt;\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
 Mihai Serban &lt;<a href="mailto:mihai.serban@intel.com">mihai.serban@intel.com</a>&gt;\r
 </p>\r
 </li>\r
@@ -1168,6 +1193,11 @@ Xavier René-Corail &lt;<a href="mailto:xavier.renecorail@gmail.com">xavier.rene
 Yiding Jia &lt;<a href="mailto:yiding@fb.com">yiding@fb.com</a>&gt;\r
 </p>\r
 </li>\r
+<li>\r
+<p>\r
+Yvan Janssens &lt;<a href="mailto:friedkiwi@yvanj.me">friedkiwi@yvanj.me</a>&gt;\r
+</p>\r
+</li>\r
 </ul></div>\r
 <div class="paragraph"><p>Thanks!</p></div>\r
 </div>\r
@@ -1176,9 +1206,9 @@ Yiding Jia &lt;<a href="mailto:yiding@fb.com">yiding@fb.com</a>&gt;
 <div id="footnotes"><hr /></div>\r
 <div id="footer">\r
 <div id="footer-text">\r
-Version 3.5.1<br />\r
+Version 3.6<br />\r
 Last updated\r
- 2019-01-03 21:16:50 CET\r
+ 2019-01-14 21:09:34 CET\r
 </div>\r
 </div>\r
 </body>\r
index 9ea080541bee22423196f0cc02e678a7dfe1612b..7a5766054b93f45498e7a74b36561714f153beb3 100644 (file)
@@ -355,7 +355,12 @@ WRAPPERS>>.
     If true, enable the debug mode. The debug mode creates per-object debug
     files that are helpful when debugging unexpected cache misses. Note however
     that ccache performance will be reduced slightly. See
-    <<_cache_debugging_,debugging>> for more information. The default is false.
+    <<_cache_debugging,debugging>> for more information. The default is false.
+
+*depend_mode* (*CCACHE_DEPEND* or *CCACHE_NODEPEND*, see <<_boolean_values,Boolean values>> above)::
+
+    If true, the depend mode will be used. The default is false. See
+    <<_the_depend_mode,THE DEPEND MODE>>.
 
 *direct_mode* (*CCACHE_DIRECT* or *CCACHE_NODIRECT*, see <<_boolean_values,Boolean values>> above)::
 
@@ -526,8 +531,18 @@ still has to do _some_ preprocessing (like macros).
     should be a comma-separated string with options. Available options are:
 +
 --
+*clang_index_store*::
+    Ignore the Clang compiler option *-index-store-path* and its argument when
+    computing the manifest hash. This is useful if you use Xcode, which uses an
+    index store path derived from the local project path. Note that the index
+    store won't be updated correctly on cache hits if you enable this option.
 *file_macro*::
-    Ignore `__FILE__` being present in the source.
+    ccache normally includes the input file path in the hash in order to be
+    able to produce the correct object file if the source code includes a
+    `__FILE__` macro. If you know that `__FILE__` isn't used in practise, or
+    don't care if ccache produces objects where `__FILE__` is expanded to the
+    wrong path, you can set *sloppiness* to *file_macro*. ccache will then
+    exclude the input file path from the hash.
 *file_stat_matches*::
     ccache normally examines a file's contents to determine whether it matches
     the cached version. With this option set, ccache will consider a file as
@@ -541,13 +556,17 @@ still has to do _some_ preprocessing (like macros).
 *include_file_mtime*::
     By default, ccache will not cache a file if it includes a header whose
     mtime is too new. This option disables that check.
-*no_system_headers*::
-    By default, ccache will also include all system headers in the manifest.
-    With this option set, ccache will only include system headers in the hash
-    but not add the system header files to the list of include files.
+*locale*::
+    ccache includes the environment variables *LANG*, *LC_ALL*, *LC_CTYPE* and
+    *LC_MESSAGES* in the hash by default since they may affect localization of
+    compiler warning messages. Set this option to tell ccache not to do that.
 *pch_defines*::
     Be sloppy about **#define**s when precompiling a header file. See
     <<_precompiled_headers,PRECOMPILED HEADERS>> for more information.
+*system_headers*::
+    By default, ccache will also include all system headers in the manifest.
+    With this option set, ccache will only include system headers in the hash
+    but not add the system header files to the list of include files.
 *time_macros*::
     Ignore `__DATE__` and `__TIME__` being present in the source code.
 --
@@ -778,7 +797,8 @@ enough to be used to identify recompilations.) On a cache hit, ccache is able
 to supply all of the correct compiler outputs (including all warnings,
 dependency file, etc) from the cache.
 
-ccache has two ways of doing the detection:
+ccache has two ways of gathering information used to look up results in the
+cache:
 
 * the *direct mode*, where ccache hashes the source code and include files
   directly
@@ -788,11 +808,17 @@ ccache has two ways of doing the detection:
 The direct mode is generally faster since running the preprocessor has some
 overhead.
 
+If no previous result is detected (i.e., there is a cache miss) using the
+direct mode, ccache will fall back to the preprocessor mode unless the *depend
+mode* is enabled. In the depend mode, ccache never runs the preprocessor, not
+even on cache misses. Read more in <<_the_depend_mode,THE DEPEND MODE>>
+below.
+
 
 Common hashed information
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-For both modes, the following information is included in the hash:
+The following information is always included in the hash:
 
 * the extension used by the compiler for a file with preprocessor output
   (normally *.i* for C code and *.ii* for C++ code)
@@ -863,6 +889,38 @@ Based on the hash, the cached compilation result can be looked up directly in
 the cache.
 
 
+The depend mode
+~~~~~~~~~~~~~~~
+
+If the depend mode is enabled, ccache will not use the preprocessor at all. The
+hash used to identify results in the cache will be based on the direct mode
+hash described above plus information about include files read from the
+dependency file generated by the compiler with *-MD* or *-MMD*.
+
+Advantages:
+
+* The ccache overhead of a cache miss will be much smaller.
+* Not running the preprocessor at all can be good if compilation is performed
+  remotely, for instance when using distcc or similar; ccache then won't make
+  potentially costly preprocessor calls on the local machine.
+
+Disadvantages:
+
+* The cache hit rate will likely be lower since any change to compiler options
+  or source code will make the hash different. Compare this with the default
+  setup where ccache will fall back to the preprocessor mode, which is tolerant
+  to some types of changes of compiler options and source code changes.
+* The manifest entries will include system header files as well, thus slowing
+  down cache hits slightly.
+
+The depend mode will be disabled if any of the following holds:
+
+* the configuration setting *depend_mode* is false
+* the configuration setting *run_second_cpp* is false
+* the configuration setting *unify* is true
+* the compiler is not generating dependencies using *-MD* or *-MMD*
+
+
 Cache debugging
 ---------------
 
@@ -1140,13 +1198,12 @@ problems and what may be done to increase the hit rate:
    output. If you know that `__DATE__` isn't used in practise, or don't care if
    ccache produces objects where `__DATE__` is expanded to something in the
    past, you can set *sloppiness* to *time_macros*.
-** The `__FILE__` preprocessor macro is (potentially) being used and the file
-   path has changed. If `__FILE__` is present in the source code, ccache hashes
-   the current input file path in order to be able to produce the correct
-   object file if the `__FILE__` macro affects the output. If you know that
-   `__FILE__` isn't used in practise, or don't care if ccache produces objects
-   where `__FILE__` is expanded to the wrong path, you can set *sloppiness* to
-   *file_macro*.
+** The input file path has changed. ccache normally includes the input file
+   path in the hash in order to be able to produce the correct object file if
+   the source code includes a `__FILE__` macro. If you know that `__FILE__`
+   isn't used in practise, or don't care if ccache produces objects where
+   `__FILE__` is expanded to the wrong path, you can set *sloppiness* to
+   *file_macro*. ccache will then exclude the input file path from the hash.
 * If ``cache miss'' has been incremented even though the same code has been
   compiled and cached before, ccache has either detected that something has
   changed anyway or a cleanup has been performed (either explicitly or
index 4c520b3286c78f16db95a6c88fc6d26f152eaeff..7f3bc98de8f912a2f8e778f76ed5376b2e3b2f2a 100644 (file)
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <body class="article">\r
 <div id="header">\r
 <h1>CCACHE(1)</h1>\r
-<span id="revnumber">version 3.5.1</span>\r
+<span id="revnumber">version 3.6</span>\r
 <div id="toc">
   <div id="toctitle">Table of Contents</div>
   <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
@@ -1255,7 +1255,16 @@ the <strong>prefix_command</strong> setting if possible. See
     If true, enable the debug mode. The debug mode creates per-object debug\r
     files that are helpful when debugging unexpected cache misses. Note however\r
     that ccache performance will be reduced slightly. See\r
-    <a href="#_cache_debugging_">debugging</a> for more information. The default is false.\r
+    <a href="#_cache_debugging">debugging</a> for more information. The default is false.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<strong>depend_mode</strong> (<strong>CCACHE_DEPEND</strong> or <strong>CCACHE_NODEPEND</strong>, see <a href="#_boolean_values">Boolean values</a> above)\r
+</dt>\r
+<dd>\r
+<p>\r
+    If true, the depend mode will be used. The default is false. See\r
+    <a href="#_the_depend_mode">THE DEPEND MODE</a>.\r
 </p>\r
 </dd>\r
 <dt class="hdlist1">\r
@@ -1519,11 +1528,27 @@ still has to do <em>some</em> preprocessing (like macros).</p></div>
 <div class="content">\r
 <div class="dlist"><dl>\r
 <dt class="hdlist1">\r
+<strong>clang_index_store</strong>\r
+</dt>\r
+<dd>\r
+<p>\r
+    Ignore the Clang compiler option <strong>-index-store-path</strong> and its argument when\r
+    computing the manifest hash. This is useful if you use Xcode, which uses an\r
+    index store path derived from the local project path. Note that the index\r
+    store won&#8217;t be updated correctly on cache hits if you enable this option.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
 <strong>file_macro</strong>\r
 </dt>\r
 <dd>\r
 <p>\r
-    Ignore <code>__FILE__</code> being present in the source.\r
+    ccache normally includes the input file path in the hash in order to be\r
+    able to produce the correct object file if the source code includes a\r
+    <code>__FILE__</code> macro. If you know that <code>__FILE__</code> isn&#8217;t used in practise, or\r
+    don&#8217;t care if ccache produces objects where <code>__FILE__</code> is expanded to the\r
+    wrong path, you can set <strong>sloppiness</strong> to <strong>file_macro</strong>. ccache will then\r
+    exclude the input file path from the hash.\r
 </p>\r
 </dd>\r
 <dt class="hdlist1">\r
@@ -1564,13 +1589,13 @@ still has to do <em>some</em> preprocessing (like macros).</p></div>
 </p>\r
 </dd>\r
 <dt class="hdlist1">\r
-<strong>no_system_headers</strong>\r
+<strong>locale</strong>\r
 </dt>\r
 <dd>\r
 <p>\r
-    By default, ccache will also include all system headers in the manifest.\r
-    With this option set, ccache will only include system headers in the hash\r
-    but not add the system header files to the list of include files.\r
+    ccache includes the environment variables <strong>LANG</strong>, <strong>LC_ALL</strong>, <strong>LC_CTYPE</strong> and\r
+    <strong>LC_MESSAGES</strong> in the hash by default since they may affect localization of\r
+    compiler warning messages. Set this option to tell ccache not to do that.\r
 </p>\r
 </dd>\r
 <dt class="hdlist1">\r
@@ -1583,6 +1608,16 @@ still has to do <em>some</em> preprocessing (like macros).</p></div>
 </p>\r
 </dd>\r
 <dt class="hdlist1">\r
+<strong>system_headers</strong>\r
+</dt>\r
+<dd>\r
+<p>\r
+    By default, ccache will also include all system headers in the manifest.\r
+    With this option set, ccache will only include system headers in the hash\r
+    but not add the system header files to the list of include files.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
 <strong>time_macros</strong>\r
 </dt>\r
 <dd>\r
@@ -1888,7 +1923,8 @@ nowadays too weak to be useful in cryptographic contexts, but it should be safe
 enough to be used to identify recompilations.) On a cache hit, ccache is able\r
 to supply all of the correct compiler outputs (including all warnings,\r
 dependency file, etc) from the cache.</p></div>\r
-<div class="paragraph"><p>ccache has two ways of doing the detection:</p></div>\r
+<div class="paragraph"><p>ccache has two ways of gathering information used to look up results in the\r
+cache:</p></div>\r
 <div class="ulist"><ul>\r
 <li>\r
 <p>\r
@@ -1905,9 +1941,14 @@ the <strong>preprocessor mode</strong>, where ccache runs the preprocessor on th
 </ul></div>\r
 <div class="paragraph"><p>The direct mode is generally faster since running the preprocessor has some\r
 overhead.</p></div>\r
+<div class="paragraph"><p>If no previous result is detected (i.e., there is a cache miss) using the\r
+direct mode, ccache will fall back to the preprocessor mode unless the <strong>depend\r
+mode</strong> is enabled. In the depend mode, ccache never runs the preprocessor, not\r
+even on cache misses. Read more in <a href="#_the_depend_mode">THE DEPEND MODE</a>\r
+below.</p></div>\r
 <div class="sect2">\r
 <h3 id="_common_hashed_information">Common hashed information</h3>\r
-<div class="paragraph"><p>For both modes, the following information is included in the hash:</p></div>\r
+<div class="paragraph"><p>The following information is always included in the hash:</p></div>\r
 <div class="ulist"><ul>\r
 <li>\r
 <p>\r
@@ -2051,6 +2092,68 @@ any standard error output generated by the preprocessor
 <div class="paragraph"><p>Based on the hash, the cached compilation result can be looked up directly in\r
 the cache.</p></div>\r
 </div>\r
+<div class="sect2">\r
+<h3 id="_the_depend_mode">The depend mode</h3>\r
+<div class="paragraph"><p>If the depend mode is enabled, ccache will not use the preprocessor at all. The\r
+hash used to identify results in the cache will be based on the direct mode\r
+hash described above plus information about include files read from the\r
+dependency file generated by the compiler with <strong>-MD</strong> or <strong>-MMD</strong>.</p></div>\r
+<div class="paragraph"><p>Advantages:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+The ccache overhead of a cache miss will be much smaller.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Not running the preprocessor at all can be good if compilation is performed\r
+  remotely, for instance when using distcc or similar; ccache then won&#8217;t make\r
+  potentially costly preprocessor calls on the local machine.\r
+</p>\r
+</li>\r
+</ul></div>\r
+<div class="paragraph"><p>Disadvantages:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+The cache hit rate will likely be lower since any change to compiler options\r
+  or source code will make the hash different. Compare this with the default\r
+  setup where ccache will fall back to the preprocessor mode, which is tolerant\r
+  to some types of changes of compiler options and source code changes.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The manifest entries will include system header files as well, thus slowing\r
+  down cache hits slightly.\r
+</p>\r
+</li>\r
+</ul></div>\r
+<div class="paragraph"><p>The depend mode will be disabled if any of the following holds:</p></div>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+the configuration setting <strong>depend_mode</strong> is false\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+the configuration setting <strong>run_second_cpp</strong> is false\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+the configuration setting <strong>unify</strong> is true\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+the compiler is not generating dependencies using <strong>-MD</strong> or <strong>-MMD</strong>\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
 </div>\r
 </div>\r
 <div class="sect1">\r
@@ -2494,13 +2597,12 @@ The <code>__DATE__</code> preprocessor macro is (potentially) being used and the
 </li>\r
 <li>\r
 <p>\r
-The <code>__FILE__</code> preprocessor macro is (potentially) being used and the file\r
-   path has changed. If <code>__FILE__</code> is present in the source code, ccache hashes\r
-   the current input file path in order to be able to produce the correct\r
-   object file if the <code>__FILE__</code> macro affects the output. If you know that\r
-   <code>__FILE__</code> isn&#8217;t used in practise, or don&#8217;t care if ccache produces objects\r
-   where <code>__FILE__</code> is expanded to the wrong path, you can set <strong>sloppiness</strong> to\r
-   <strong>file_macro</strong>.\r
+The input file path has changed. ccache normally includes the input file\r
+   path in the hash in order to be able to produce the correct object file if\r
+   the source code includes a <code>__FILE__</code> macro. If you know that <code>__FILE__</code>\r
+   isn&#8217;t used in practise, or don&#8217;t care if ccache produces objects where\r
+   <code>__FILE__</code> is expanded to the wrong path, you can set <strong>sloppiness</strong> to\r
+   <strong>file_macro</strong>. ccache will then exclude the input file path from the hash.\r
 </p>\r
 </li>\r
 </ul></div>\r
@@ -2595,9 +2697,9 @@ maintained by Joel Rosdahl. See AUTHORS.txt or AUTHORS.html and
 <div id="footnotes"><hr /></div>\r
 <div id="footer">\r
 <div id="footer-text">\r
-Version 3.5.1<br />\r
+Version 3.6<br />\r
 Last updated\r
- 2019-01-03 21:16:33 CET\r
+ 2019-01-13 21:38:14 CET\r
 </div>\r
 </div>\r
 </body>\r
index 6da3a5a9bf97a16a5645cb52adaa28bd519c7c73..41197d3dfc83adb6059e6267d0c154df2648a726 100644 (file)
@@ -1,6 +1,54 @@
 ccache news
 ===========
 
+ccache 3.6
+----------
+Release date: 2019-01-14
+
+Changes
+~~~~~~~
+
+- ccache now has an opt-in ``depend mode''. When enabled, ccache never executes
+  the preprocessor, which results in much lower cache miss overhead at the
+  expense of a lower potential cache hit rate. The depend mode is only possible
+  to use when the compiler option `-MD` or `-MMD` is used.
+
+- Added support for GCC's `-ffile-prefix-map` option. The `-fmacro-prefix-map`
+  option is now also skipped from the hash.
+
+- Added support for multiple `-fsanitize-blacklist` arguments.
+
+- ccache now includes the environment variables `LANG`, `LC_ALL`, `LC_CTYPE`
+  and `LC_MESSAGES` in the hash since they may affect localization of compiler
+  warning messages. Set sloppiness to `locale` to opt out of this.
+
+- Fixed a problem due to Clang overwriting the output file when compiling an
+  assembler file.
+
+- Clarified the manual to explain the reasoning behind the “file_macro”
+  sloppiness setting in a better way.
+
+- ccache now handles several levels of nonexistent directories when rewriting
+  absolute paths to relative.
+
+- A new sloppiness setting `clang_index_store` makes ccache skip the Clang
+  compiler option `-index-store-path` and its argument when computing the
+  manifest hash. This is useful if you use Xcode, which uses an index store
+  path derived from the local project path. Note that the index store won't be
+  updated correctly on cache hits if you enable this option.
+
+- Rename sloppiness `no_system_headers` to `system_headers` for consistency
+  with other options. `no_system_headers` can still be used as an
+  (undocumented) alias.
+
+- The GCC variables “DEPENDENCIES_OUTPUT” and “SUNPRO_DEPENDENCIES” are now
+  supported correctly.
+
+- The algorithm that scans for `__DATE_` and `__TIME__` tokens in the hashed
+  source code now doesn't produce false positives for tokens where `__DATE__`
+  or `__TIME__` is a substring.
+
+
 ccache 3.5.1
 ------------
 Release date: 2019-01-02
@@ -56,7 +104,7 @@ Changes
 - It's now possible to opt out of building and installing man pages when
   running `make install` in the source repository.
 
-- If the compiler type can't be detected (e.g. if it is named *cc*), use safer
+- If the compiler type can't be detected (e.g. if it is named `cc`), use safer
   defaults that won't trip up Clang.
 
 - Made the ccache test suite work on FreeBSD.
@@ -335,7 +383,7 @@ New features and enhancements
 
 - Added a new `keep_comments_cpp` (`CCACHE_COMMENTS`) configuration option,
   which tells ccache not to discard the comments before hashing preprocessor
-  output. This can be used to check documentation with *-Wdocumentation*.
+  output. This can be used to check documentation with `-Wdocumentation`.
 
 - Added a new sloppiness option `no_system_headers`, which tells ccache not to
   include system headers in manifest files.
@@ -570,7 +618,7 @@ Bug fixes
   This makes it possible to rebuild with `CCACHE_CPP2` set without having to
   clear the cache to get new results.
 
-- Don't try to reset a non-existing stats file. This avoids ``No such file or
+- Don't try to reset a nonexistent stats file. This avoids ``No such file or
   directory'' messages in the ccache log when the cache directory doesn't
   exist.
 
@@ -757,7 +805,7 @@ Bug fixes
   This makes it possible to rebuild with `CCACHE_CPP2` set without having to
   clear the cache to get new results.
 
-- Don't try to reset a non-existing stats file. This avoids ``No such file or
+- Don't try to reset a nonexistent stats file. This avoids ``No such file or
   directory'' messages in the ccache log when the cache directory doesn't
   exist.
 
index 5c4ffe37d9c62b1c918510eacfede7217cbee3bd..1e4bf2aaf65114251f1d4e60cf796640472b54cb 100644 (file)
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <body class="article">\r
 <div id="header">\r
 <h1>ccache news</h1>\r
-<span id="revnumber">version 3.5.1</span>\r
+<span id="revnumber">version 3.6</span>\r
 <div id="toc">
   <div id="toctitle">Table of Contents</div>
   <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
@@ -743,11 +743,95 @@ asciidoc.install(2);
 </div>\r
 <div id="content">\r
 <div class="sect1">\r
+<h2 id="_ccache_3_6">ccache 3.6</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Release date: 2019-01-14</p></div>\r
+<div class="sect2">\r
+<h3 id="_changes">Changes</h3>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+ccache now has an opt-in &#8220;depend mode&#8221;. When enabled, ccache never executes\r
+  the preprocessor, which results in much lower cache miss overhead at the\r
+  expense of a lower potential cache hit rate. The depend mode is only possible\r
+  to use when the compiler option <code>-MD</code> or <code>-MMD</code> is used.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Added support for GCC&#8217;s <code>-ffile-prefix-map</code> option. The <code>-fmacro-prefix-map</code>\r
+  option is now also skipped from the hash.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Added support for multiple <code>-fsanitize-blacklist</code> arguments.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache now includes the environment variables <code>LANG</code>, <code>LC_ALL</code>, <code>LC_CTYPE</code>\r
+  and <code>LC_MESSAGES</code> in the hash since they may affect localization of compiler\r
+  warning messages. Set sloppiness to <code>locale</code> to opt out of this.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a problem due to Clang overwriting the output file when compiling an\r
+  assembler file.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Clarified the manual to explain the reasoning behind the “file_macro”\r
+  sloppiness setting in a better way.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache now handles several levels of nonexistent directories when rewriting\r
+  absolute paths to relative.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+A new sloppiness setting <code>clang_index_store</code> makes ccache skip the Clang\r
+  compiler option <code>-index-store-path</code> and its argument when computing the\r
+  manifest hash. This is useful if you use Xcode, which uses an index store\r
+  path derived from the local project path. Note that the index store won&#8217;t be\r
+  updated correctly on cache hits if you enable this option.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Rename sloppiness <code>no_system_headers</code> to <code>system_headers</code> for consistency\r
+  with other options. <code>no_system_headers</code> can still be used as an\r
+  (undocumented) alias.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The GCC variables “DEPENDENCIES_OUTPUT” and “SUNPRO_DEPENDENCIES” are now\r
+  supported correctly.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The algorithm that scans for <code>__DATE_</code> and <code>__TIME__</code> tokens in the hashed\r
+  source code now doesn&#8217;t produce false positives for tokens where <code>__DATE__</code>\r
+  or <code>__TIME__</code> is a substring.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
 <h2 id="_ccache_3_5_1">ccache 3.5.1</h2>\r
 <div class="sectionbody">\r
 <div class="paragraph"><p>Release date: 2019-01-02</p></div>\r
 <div class="sect2">\r
-<h3 id="_changes">Changes</h3>\r
+<h3 id="_changes_2">Changes</h3>\r
 <div class="ulist"><ul>\r
 <li>\r
 <p>\r
@@ -778,7 +862,7 @@ Improved development mode build flags.
 <div class="sectionbody">\r
 <div class="paragraph"><p>Release date: 2018-10-15</p></div>\r
 <div class="sect2">\r
-<h3 id="_changes_2">Changes</h3>\r
+<h3 id="_changes_3">Changes</h3>\r
 <div class="ulist"><ul>\r
 <li>\r
 <p>\r
@@ -841,7 +925,7 @@ It&#8217;s now possible to opt out of building and installing man pages when
 </li>\r
 <li>\r
 <p>\r
-If the compiler type can&#8217;t be detected (e.g. if it is named <strong>cc</strong>), use safer\r
+If the compiler type can&#8217;t be detected (e.g. if it is named <code>cc</code>), use safer\r
   defaults that won&#8217;t trip up Clang.\r
 </p>\r
 </li>\r
@@ -1329,7 +1413,7 @@ Added a new <code>limit_multiple</code> (<code>CCACHE_LIMIT_MULTIPLE</code>) con
 <p>\r
 Added a new <code>keep_comments_cpp</code> (<code>CCACHE_COMMENTS</code>) configuration option,\r
   which tells ccache not to discard the comments before hashing preprocessor\r
-  output. This can be used to check documentation with <strong>-Wdocumentation</strong>.\r
+  output. This can be used to check documentation with <code>-Wdocumentation</code>.\r
 </p>\r
 </li>\r
 <li>\r
@@ -1759,7 +1843,7 @@ Made hash of cached result created with and without <code>CCACHE_CPP2</code> dif
 </li>\r
 <li>\r
 <p>\r
-Don&#8217;t try to reset a non-existing stats file. This avoids &#8220;No such file or\r
+Don&#8217;t try to reset a nonexistent stats file. This avoids &#8220;No such file or\r
   directory&#8221; messages in the ccache log when the cache directory doesn&#8217;t\r
   exist.\r
 </p>\r
@@ -2117,7 +2201,7 @@ Made hash of cached result created with and without <code>CCACHE_CPP2</code> dif
 </li>\r
 <li>\r
 <p>\r
-Don&#8217;t try to reset a non-existing stats file. This avoids &#8220;No such file or\r
+Don&#8217;t try to reset a nonexistent stats file. This avoids &#8220;No such file or\r
   directory&#8221; messages in the ccache log when the cache directory doesn&#8217;t\r
   exist.\r
 </p>\r
@@ -3161,9 +3245,9 @@ Statistics counters are now correctly updated for -E option failures and
 <div id="footnotes"><hr /></div>\r
 <div id="footer">\r
 <div id="footer-text">\r
-Version 3.5.1<br />\r
+Version 3.6<br />\r
 Last updated\r
- 2019-01-03 21:16:33 CET\r
+ 2019-01-14 21:08:50 CET\r
 </div>\r
 </div>\r
 </body>\r
index 22a2e1dc5e5d90b259693be4a3c0e3a01e342895..8ab6adcd99b23546b35d12fa30712deb19c694f0 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: ccache
 .\"    Author: [see the "Author" section]
 .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\"      Date: 01/03/2019
+.\"      Date: 01/14/2019
 .\"    Manual: ccache Manual
-.\"    Source: ccache 3.5.1
+.\"    Source: ccache 3.6
 .\"  Language: English
 .\"
-.TH "CCACHE" "1" "01/03/2019" "ccache 3\&.5\&.1" "ccache Manual"
+.TH "CCACHE" "1" "01/14/2019" "ccache 3\&.6" "ccache Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -480,6 +480,12 @@ debugging
 for more information\&. The default is false\&.
 .RE
 .PP
+\fBdepend_mode\fR (\fBCCACHE_DEPEND\fR or \fBCCACHE_NODEPEND\fR, see Boolean values above)
+.RS 4
+If true, the depend mode will be used\&. The default is false\&. See
+THE DEPEND MODE\&.
+.RE
+.PP
 \fBdirect_mode\fR (\fBCCACHE_DIRECT\fR or \fBCCACHE_NODIRECT\fR, see Boolean values above)
 .RS 4
 If true, the direct mode will be used\&. The default is true\&. See
@@ -664,11 +670,25 @@ preprocessing (like macros)\&.
 .RS 4
 By default, ccache tries to give as few false cache hits as possible\&. However, in certain situations it\(cqs possible that you know things that ccache can\(cqt take for granted\&. This setting makes it possible to tell ccache to relax some checks in order to increase the hit rate\&. The value should be a comma\-separated string with options\&. Available options are:
 .PP
+\fBclang_index_store\fR
+.RS 4
+Ignore the Clang compiler option
+\fB\-index\-store\-path\fR
+and its argument when computing the manifest hash\&. This is useful if you use Xcode, which uses an index store path derived from the local project path\&. Note that the index store won\(cqt be updated correctly on cache hits if you enable this option\&.
+.RE
+.PP
 \fBfile_macro\fR
 .RS 4
-Ignore
+ccache normally includes the input file path in the hash in order to be able to produce the correct object file if the source code includes a
+\fB__FILE__\fR
+macro\&. If you know that
 \fB__FILE__\fR
-being present in the source\&.
+isn\(cqt used in practise, or don\(cqt care if ccache produces objects where
+\fB__FILE__\fR
+is expanded to the wrong path, you can set
+\fBsloppiness\fR
+to
+\fBfile_macro\fR\&. ccache will then exclude the input file path from the hash\&.
 .RE
 .PP
 \fBfile_stat_matches\fR
@@ -693,9 +713,15 @@ By default, ccache also will not cache a file if it includes a header whose ctim
 By default, ccache will not cache a file if it includes a header whose mtime is too new\&. This option disables that check\&.
 .RE
 .PP
-\fBno_system_headers\fR
+\fBlocale\fR
 .RS 4
-By default, ccache will also include all system headers in the manifest\&. With this option set, ccache will only include system headers in the hash but not add the system header files to the list of include files\&.
+ccache includes the environment variables
+\fBLANG\fR,
+\fBLC_ALL\fR,
+\fBLC_CTYPE\fR
+and
+\fBLC_MESSAGES\fR
+in the hash by default since they may affect localization of compiler warning messages\&. Set this option to tell ccache not to do that\&.
 .RE
 .PP
 \fBpch_defines\fR
@@ -706,6 +732,11 @@ PRECOMPILED HEADERS
 for more information\&.
 .RE
 .PP
+\fBsystem_headers\fR
+.RS 4
+By default, ccache will also include all system headers in the manifest\&. With this option set, ccache will only include system headers in the hash but not add the system header files to the list of include files\&.
+.RE
+.PP
 \fBtime_macros\fR
 .RS 4
 Ignore
@@ -1082,7 +1113,7 @@ T}
 .sp
 The basic idea is to detect when you are compiling exactly the same code a second time and reuse the previously produced output\&. The detection is done by hashing different kinds of information that should be unique for the compilation and then using the hash sum to identify the cached output\&. ccache uses MD4, a very fast cryptographic hash algorithm, for the hashing\&. (MD4 is nowadays too weak to be useful in cryptographic contexts, but it should be safe enough to be used to identify recompilations\&.) On a cache hit, ccache is able to supply all of the correct compiler outputs (including all warnings, dependency file, etc) from the cache\&.
 .sp
-ccache has two ways of doing the detection:
+ccache has two ways of gathering information used to look up results in the cache:
 .sp
 .RS 4
 .ie n \{\
@@ -1109,9 +1140,11 @@ the
 .RE
 .sp
 The direct mode is generally faster since running the preprocessor has some overhead\&.
+.sp
+If no previous result is detected (i\&.e\&., there is a cache miss) using the direct mode, ccache will fall back to the preprocessor mode unless the \fBdepend mode\fR is enabled\&. In the depend mode, ccache never runs the preprocessor, not even on cache misses\&. Read more in THE DEPEND MODE below\&.
 .SS "Common hashed information"
 .sp
-For both modes, the following information is included in the hash:
+The following information is always included in the hash:
 .sp
 .RS 4
 .ie n \{\
@@ -1360,6 +1393,112 @@ any standard error output generated by the preprocessor
 .RE
 .sp
 Based on the hash, the cached compilation result can be looked up directly in the cache\&.
+.SS "The depend mode"
+.sp
+If the depend mode is enabled, ccache will not use the preprocessor at all\&. The hash used to identify results in the cache will be based on the direct mode hash described above plus information about include files read from the dependency file generated by the compiler with \fB\-MD\fR or \fB\-MMD\fR\&.
+.sp
+Advantages:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+The ccache overhead of a cache miss will be much smaller\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Not running the preprocessor at all can be good if compilation is performed remotely, for instance when using distcc or similar; ccache then won\(cqt make potentially costly preprocessor calls on the local machine\&.
+.RE
+.sp
+Disadvantages:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+The cache hit rate will likely be lower since any change to compiler options or source code will make the hash different\&. Compare this with the default setup where ccache will fall back to the preprocessor mode, which is tolerant to some types of changes of compiler options and source code changes\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+The manifest entries will include system header files as well, thus slowing down cache hits slightly\&.
+.RE
+.sp
+The depend mode will be disabled if any of the following holds:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+the configuration setting
+\fBdepend_mode\fR
+is false
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+the configuration setting
+\fBrun_second_cpp\fR
+is false
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+the configuration setting
+\fBunify\fR
+is true
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+the compiler is not generating dependencies using
+\fB\-MD\fR
+or
+\fB\-MMD\fR
+.RE
 .SH "CACHE DEBUGGING"
 .sp
 To find out what information ccache actually is hashing, you can enable the debug mode via the configuration setting \fBdebug\fR or by setting \fBCCACHE_DEBUG\fR in the environment\&. This can be useful if you are investigating why you don\(cqt get cache hits\&. Note that performance will be reduced slightly\&.
@@ -1992,20 +2131,16 @@ to
 .sp -1
 .IP \(bu 2.3
 .\}
-The
+The input file path has changed\&. ccache normally includes the input file path in the hash in order to be able to produce the correct object file if the source code includes a
 \fB__FILE__\fR
-preprocessor macro is (potentially) being used and the file path has changed\&. If
-\fB__FILE__\fR
-is present in the source code, ccache hashes the current input file path in order to be able to produce the correct object file if the
-\fB__FILE__\fR
-macro affects the output\&. If you know that
+macro\&. If you know that
 \fB__FILE__\fR
 isn\(cqt used in practise, or don\(cqt care if ccache produces objects where
 \fB__FILE__\fR
 is expanded to the wrong path, you can set
 \fBsloppiness\fR
 to
-\fBfile_macro\fR\&.
+\fBfile_macro\fR\&. ccache will then exclude the input file path from the hash\&.
 .RE
 .RE
 .sp
index 2b88b2864ad1430b768d36dceff08d37e7c207ac..b4cdb865f81fc62f247a01d838af9b8ddcd30e39 100644 (file)
@@ -237,7 +237,10 @@ static bool profile_use = false;
 static bool profile_generate = false;
 
 // Sanitize blacklist
-static char *sanitize_blacklist = NULL;
+static char **sanitize_blacklists = NULL;
+
+// Size of sanitize_blacklists
+static size_t sanitize_blacklists_len = 0;
 
 // Whether we are using a precompiled header (either via -include, #include or
 // clang's -include-pch or -include-pth).
@@ -581,7 +584,8 @@ get_path_in_cache(const char *name, const char *suffix)
 // global included_files variable. If the include file is a PCH, cpp_hash is
 // also updated. Takes over ownership of path.
 static void
-remember_include_file(char *path, struct hash *cpp_hash, bool system)
+remember_include_file(char *path, struct hash *cpp_hash, bool system,
+                      struct hash *depend_mode_hash)
 {
        struct hash *fhash = NULL;
 
@@ -596,7 +600,7 @@ remember_include_file(char *path, struct hash *cpp_hash, bool system)
                goto out;
        }
 
-       if (system && (conf->sloppiness & SLOPPY_NO_SYSTEM_HEADERS)) {
+       if (system && (conf->sloppiness & SLOPPY_SYSTEM_HEADERS)) {
                // Don't remember this system header.
                goto out;
        }
@@ -722,6 +726,11 @@ remember_include_file(char *path, struct hash *cpp_hash, bool system)
                h->size = hash_input_size(fhash);
                hashtable_insert(included_files, path, h);
                path = NULL; // Ownership transferred to included_files.
+
+               if (depend_mode_hash) {
+                       hash_delimiter(depend_mode_hash, "include");
+                       hash_buffer(depend_mode_hash, h->hash, sizeof(h->hash));
+               }
        }
 
        goto out;
@@ -737,6 +746,16 @@ out:
        free(path);
 }
 
+static void
+print_included_files(FILE *fp)
+{
+       struct hashtable_itr *iter = hashtable_iterator(included_files);
+       do {
+               char *path = hashtable_iterator_key(iter);
+               fprintf(fp, "%s\n", path);
+       } while (hashtable_iterator_advance(iter));
+}
+
 // Make a relative path from current working directory to path if path is under
 // the base directory. Takes over ownership of path. Caller frees.
 static char *
@@ -761,15 +780,21 @@ make_relative_path(char *path)
        if (stat(path, &st) != 0) {
                // path doesn't exist.
                char *dir = dirname(path);
-               if (stat(dir, &st) != 0) {
-                       // And neither does its parent directory, so no action to take.
+               // find the nearest existing directory in path
+               while (stat(dir, &st) != 0) {
+                       char *parent_dir = dirname(dir);
                        free(dir);
-                       return path;
+                       dir = parent_dir;
+               }
+
+               // suffix is the remaining of the path, skip the first delimiter
+               size_t dir_len = strlen(dir);
+               if (path[dir_len] == '/' || path[dir_len] == '\\') {
+                       dir_len++;
                }
-               free(dir);
-               path_suffix = basename(path);
+               path_suffix = x_strdup(&path[dir_len]);
                char *p = path;
-               path = dirname(path);
+               path = dir;
                free(p);
        }
 
@@ -793,6 +818,16 @@ make_relative_path(char *path)
        }
 }
 
+static void
+init_included_files_table(void)
+{
+       // (This function may be called multiple times if several -arch options are
+       // used.)
+       if (!included_files) {
+               included_files = create_hashtable(1000, hash_from_string, strings_equal);
+       }
+}
+
 // This function reads and hashes a file. While doing this, it also does these
 // things:
 //
@@ -824,9 +859,7 @@ process_preprocessed_file(struct hash *hash, const char *path, bool pump)
                free(p);
        }
 
-       if (!included_files) {
-               included_files = create_hashtable(1000, hash_from_string, strings_equal);
-       }
+       init_included_files_table();
 
        char *cwd = gnu_getcwd();
 
@@ -945,7 +978,7 @@ process_preprocessed_file(struct hash *hash, const char *path, bool pump)
                                hash_string_buffer(hash, inc_path, strlen(inc_path));
                        }
 
-                       remember_include_file(inc_path, hash, system);
+                       remember_include_file(inc_path, hash, system, NULL);
                        p = q; // Everything of interest between p and q has been hashed now.
                } else if (q[0] == '.' && q[1] == 'i' && q[2] == 'n' && q[3] == 'c'
                           && q[4] == 'b' && q[5] == 'i' && q[6] == 'n') {
@@ -984,7 +1017,12 @@ process_preprocessed_file(struct hash *hash, const char *path, bool pump)
                char *pch_path = x_strdup(included_pch_file);
                pch_path = make_relative_path(pch_path);
                hash_string(hash, pch_path);
-               remember_include_file(pch_path, hash, false);
+               remember_include_file(pch_path, hash, false, NULL);
+       }
+
+       bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
+       if (debug_included) {
+               print_included_files(stdout);
        }
 
        return true;
@@ -1070,6 +1108,46 @@ out:
        free(tmp_file);
 }
 
+// Extract the used includes from the dependency file. Note that we cannot
+// distinguish system headers from other includes here.
+static struct file_hash *
+object_hash_from_depfile(const char *depfile, struct hash *hash)
+{
+       FILE *f = fopen(depfile, "r");
+       if (!f) {
+               cc_log("Cannot open dependency file %s: %s", depfile, strerror(errno));
+               return NULL;
+       }
+
+       init_included_files_table();
+
+       char buf[10000];
+       while (fgets(buf, sizeof(buf), f) && !ferror(f)) {
+               char *saveptr;
+               char *token;
+               for (token = strtok_r(buf, " \t\n", &saveptr);
+                    token;
+                    token = strtok_r(NULL, " \t\n", &saveptr)) {
+                       if (str_endswith(token, ":") || str_eq(token, "\\")) {
+                               continue;
+                       }
+                       remember_include_file(x_strdup(token), hash, false, hash);
+               }
+       }
+
+       fclose(f);
+
+       bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
+       if (debug_included) {
+               print_included_files(stdout);
+       }
+
+       struct file_hash *result = x_malloc(sizeof(*result));
+       hash_result_as_bytes(hash, result->hash);
+       result->size = hash_input_size(hash);
+       return result;
+}
+
 // Helper method for copy_file_to_cache and move_file_to_cache_same_fs.
 static void
 do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
@@ -1230,18 +1308,34 @@ update_manifest_file(void)
        }
 }
 
-// Run the real compiler and put the result in cache.
 static void
-to_cache(struct args *args)
+update_cached_result_globals(struct file_hash *hash)
 {
-       char *tmp_stdout = format("%s.tmp.stdout", cached_obj);
-       int tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
-       char *tmp_stderr = format("%s.tmp.stderr", cached_obj);
-       int tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+       char *object_name = format_hash_as_string(hash->hash, hash->size);
+       cached_obj_hash = hash;
+       cached_obj = get_path_in_cache(object_name, ".o");
+       cached_stderr = get_path_in_cache(object_name, ".stderr");
+       cached_dep = get_path_in_cache(object_name, ".d");
+       cached_cov = get_path_in_cache(object_name, ".gcno");
+       cached_su = get_path_in_cache(object_name, ".su");
+       cached_dia = get_path_in_cache(object_name, ".dia");
+       cached_dwo = get_path_in_cache(object_name, ".dwo");
 
+       stats_file = format("%s/%c/stats", conf->cache_dir, object_name[0]);
+       free(object_name);
+}
+
+// Run the real compiler and put the result in cache.
+static void
+to_cache(struct args *args, struct hash *depend_mode_hash)
+{
        args_add(args, "-o");
        args_add(args, output_obj);
 
+       if (conf->hard_link) {
+               x_unlink(output_obj);
+       }
+
        if (generating_diagnostics) {
                args_add(args, "--serialize-diagnostics");
                args_add(args, output_dia);
@@ -1252,6 +1346,7 @@ to_cache(struct args *args)
        //
        //   tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i
        x_unsetenv("DEPENDENCIES_OUTPUT");
+       x_unsetenv("SUNPRO_DEPENDENCIES");
 
        if (conf->run_second_cpp) {
                args_add(args, input_file);
@@ -1260,9 +1355,38 @@ to_cache(struct args *args)
        }
 
        cc_log("Running real compiler");
-       int status =
-               execute(args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
-       args_pop(args, 3);
+       char *tmp_stdout;
+       int tmp_stdout_fd;
+       char *tmp_stderr;
+       int tmp_stderr_fd;
+       int status;
+       if (!conf->depend_mode) {
+               tmp_stdout = format("%s.tmp.stdout", cached_obj);
+               tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
+               tmp_stderr = format("%s.tmp.stderr", cached_obj);
+               tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+
+               status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
+               args_pop(args, 3);
+       } else {
+               // The cached object path is not known yet, use temporary files.
+               tmp_stdout = format("%s/tmp.stdout", temp_dir());
+               tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
+               tmp_stderr = format("%s/tmp.stderr", temp_dir());
+               tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+
+               // Use the original arguments (including dependency options) in depend
+               // mode.
+               assert(orig_args);
+               struct args *depend_mode_args = args_copy(orig_args);
+               args_strip(depend_mode_args, "--ccache-");
+               add_prefix(depend_mode_args, conf->prefix_command);
+
+               time_of_compilation = time(NULL);
+               status = execute(
+                       depend_mode_args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
+               args_free(depend_mode_args);
+       }
 
        struct stat st;
        if (x_stat(tmp_stdout, &st) != 0) {
@@ -1340,6 +1464,23 @@ to_cache(struct args *args)
                failed();
        }
 
+       if (generating_dependencies) {
+               use_relative_paths_in_depfile(output_dep);
+       }
+
+       if (conf->depend_mode) {
+               struct file_hash *object_hash =
+                       object_hash_from_depfile(output_dep, depend_mode_hash);
+               if (!object_hash) {
+                       failed();
+               }
+               update_cached_result_globals(object_hash);
+
+               // It does not make sense to update an existing manifest file in the depend
+               // mode.
+               x_unlink(manifest_path);
+       }
+
        if (stat(output_obj, &st) != 0) {
                cc_log("Compiler didn't produce an object file");
                stats_update(STATS_NOOUTPUT);
@@ -1356,7 +1497,11 @@ to_cache(struct args *args)
                failed();
        }
        if (st.st_size > 0) {
-               move_file_to_cache_same_fs(tmp_stderr, cached_stderr);
+               if (!conf->depend_mode) {
+                       move_file_to_cache_same_fs(tmp_stderr, cached_stderr);
+               } else {
+                       copy_file_to_cache(tmp_stderr, cached_stderr);
+               }
        } else {
                tmp_unlink(tmp_stderr);
                if (conf->recache) {
@@ -1367,7 +1512,6 @@ to_cache(struct args *args)
 
        copy_file_to_cache(output_obj, cached_obj);
        if (generating_dependencies) {
-               use_relative_paths_in_depfile(output_dep);
                copy_file_to_cache(output_dep, cached_dep);
        }
        if (generating_coverage) {
@@ -1445,6 +1589,7 @@ get_object_name_from_cpp(struct args *args, struct hash *hash)
                }
 
                path_stdout = format("%s/%s.stdout", temp_dir(), input_base);
+               free(input_base);
                int path_stdout_fd = create_tmp_fd(&path_stdout);
                add_pending_tmp_file(path_stdout);
 
@@ -1525,23 +1670,6 @@ get_object_name_from_cpp(struct args *args, struct hash *hash)
        return result;
 }
 
-static void
-update_cached_result_globals(struct file_hash *hash)
-{
-       char *object_name = format_hash_as_string(hash->hash, hash->size);
-       cached_obj_hash = hash;
-       cached_obj = get_path_in_cache(object_name, ".o");
-       cached_stderr = get_path_in_cache(object_name, ".stderr");
-       cached_dep = get_path_in_cache(object_name, ".d");
-       cached_cov = get_path_in_cache(object_name, ".gcno");
-       cached_su = get_path_in_cache(object_name, ".su");
-       cached_dia = get_path_in_cache(object_name, ".dia");
-       cached_dwo = get_path_in_cache(object_name, ".dwo");
-
-       stats_file = format("%s/%c/stats", conf->cache_dir, object_name[0]);
-       free(object_name);
-}
-
 // Hash mtime or content of a file, or the output of a command, according to
 // the CCACHE_COMPILERCHECK setting.
 static void
@@ -1659,6 +1787,25 @@ calculate_common_hash(struct args *args, struct hash *hash)
        hash_string(hash, base);
        free(base);
 
+       if (!(conf->sloppiness & SLOPPY_LOCALE)) {
+               // Hash environment variables that may affect localization of compiler
+               // warning messages.
+               const char *envvars[] = {
+                       "LANG",
+                       "LC_ALL",
+                       "LC_CTYPE",
+                       "LC_MESSAGES",
+                       NULL
+               };
+               for (const char **p = envvars; *p; ++p) {
+                       char *v = getenv(*p);
+                       if (v) {
+                               hash_delimiter(hash, *p);
+                               hash_string(hash, v);
+                       }
+               }
+       }
+
        // Possibly hash the current working directory.
        if (generating_debuginfo && conf->hash_dir) {
                char *cwd = gnu_getcwd();
@@ -1710,7 +1857,8 @@ calculate_common_hash(struct args *args, struct hash *hash)
        }
 
        // Possibly hash the sanitize blacklist file path.
-       if (sanitize_blacklist) {
+       for (size_t i = 0; i < sanitize_blacklists_len; i++) {
+               char *sanitize_blacklist = sanitize_blacklists[i];
                cc_log("Hashing sanitize blacklist %s", sanitize_blacklist);
                hash_delimiter(hash, "sanitizeblacklist");
                if (!hash_file(hash, sanitize_blacklist)) {
@@ -1786,6 +1934,12 @@ calculate_object_hash(struct args *args, struct hash *hash, int direct_mode)
                if (str_startswith(args->argv[i], "-fdebug-prefix-map=")) {
                        continue;
                }
+               if (str_startswith(args->argv[i], "-ffile-prefix-map=")) {
+                       continue;
+               }
+               if (str_startswith(args->argv[i], "-fmacro-prefix-map=")) {
+                       continue;
+               }
 
                // When using the preprocessor, some arguments don't contribute to the
                // hash. The theory is that these arguments will change the output of -E if
@@ -2231,6 +2385,9 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
        bool dependency_filename_specified = false;
        // Is the dependency makefile target name specified with -MT or -MQ?
        bool dependency_target_specified = false;
+       // Is the dependency target name implicitly specified using
+       // DEPENDENCIES_OUTPUT or SUNPRO_DEPENDENCIES?
+       bool dependency_implicit_target_specified = false;
        // expanded_args is a copy of the original arguments given to the compiler
        // but with arguments from @file and similar constructs expanded. It's only
        // used as a temporary data structure to loop over.
@@ -2449,11 +2606,13 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                        args_add(stripped_args, argv[i]);
                        continue;
                }
-               if (str_startswith(argv[i], "-fdebug-prefix-map=")) {
+               if (str_startswith(argv[i], "-fdebug-prefix-map=")
+                   || str_startswith(argv[i], "-ffile-prefix-map=")) {
                        debug_prefix_maps = x_realloc(
                                debug_prefix_maps,
                                (debug_prefix_maps_len + 1) * sizeof(char *));
-                       debug_prefix_maps[debug_prefix_maps_len++] = x_strdup(argv[i] + 19);
+                       debug_prefix_maps[debug_prefix_maps_len++] =
+                               x_strdup(&argv[i][argv[i][2] == 'f' ? 18 : 19]);
                        args_add(stripped_args, argv[i]);
                        continue;
                }
@@ -2569,7 +2728,10 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                        continue;
                }
                if (str_startswith(argv[i], "-fsanitize-blacklist=")) {
-                       sanitize_blacklist = x_strdup(argv[i] + 21);
+                       sanitize_blacklists = x_realloc(
+                               sanitize_blacklists,
+                               (sanitize_blacklists_len + 1) * sizeof(char *));
+                       sanitize_blacklists[sanitize_blacklists_len++] = x_strdup(argv[i] + 21);
                        args_add(stripped_args, argv[i]);
                        continue;
                }
@@ -2772,6 +2934,18 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                        continue;
                }
 
+               if (conf->sloppiness & SLOPPY_CLANG_INDEX_STORE
+                   && str_eq(argv[i], "-index-store-path")) {
+                       // Xcode 9 or later calls Clang with this option. The given path includes
+                       // a UUID that might lead to cache misses, especially when cache is
+                       // shared among multiple users.
+                       i++;
+                       if (i <= argc - 1) {
+                               cc_log("Skipping argument -index-store-path %s", argv[i]);
+                       }
+                       continue;
+               }
+
                // Options taking an argument that we may want to rewrite to relative paths
                // to get better hit rate. A secondary effect is that paths in the standard
                // error output produced by the compiler will be normalized.
@@ -2905,6 +3079,55 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                }
        } // for
 
+       // See <http://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html>.
+       // Contrary to what the documentation seems to imply the compiler still
+       // creates object files with these defined (confirmed with GCC 8.2.1), i.e.
+       // they work as -MMD/-MD, not -MM/-M. These environment variables do nothing
+       // on Clang.
+       char *dependencies_env = getenv("DEPENDENCIES_OUTPUT");
+       bool using_sunpro_dependencies = false;
+       if (!dependencies_env) {
+               dependencies_env = getenv("SUNPRO_DEPENDENCIES");
+               using_sunpro_dependencies = true;
+       }
+       if (dependencies_env) {
+               generating_dependencies = true;
+               dependency_filename_specified = true;
+               char *saveptr = NULL;
+               char *abspath_file = strtok_r(dependencies_env, " ", &saveptr);
+
+               free(output_dep);
+               output_dep = make_relative_path(x_strdup(abspath_file));
+
+               // Specifying target object is optional.
+               char *abspath_obj = strtok_r(NULL, " ", &saveptr);
+               if (abspath_obj) {
+                       // It's the "file target" form.
+
+                       dependency_target_specified = true;
+                       char *relpath_obj = make_relative_path(x_strdup(abspath_obj));
+                       // Ensure compiler gets relative path.
+                       char *relpath_both = format("%s %s", output_dep, relpath_obj);
+                       if (using_sunpro_dependencies) {
+                               x_setenv("SUNPRO_DEPENDENCIES", relpath_both);
+                       } else {
+                               x_setenv("DEPENDENCIES_OUTPUT", relpath_both);
+                       }
+                       free(relpath_obj);
+                       free(relpath_both);
+               } else {
+                       // It's the "file" form.
+
+                       dependency_implicit_target_specified = true;
+                       // Ensure compiler gets relative path.
+                       if (using_sunpro_dependencies) {
+                               x_setenv("SUNPRO_DEPENDENCIES", output_dep);
+                       } else {
+                               x_setenv("DEPENDENCIES_OUTPUT", output_dep);
+                       }
+               }
+       }
+
        if (found_S_opt) {
                // Even if -gsplit-dwarf is given, the .dwo file is not generated when -S
                // is also given.
@@ -3100,6 +3323,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                }
 
                if (!dependency_target_specified
+                   && !dependency_implicit_target_specified
                    && !str_eq(get_extension(output_dep), ".o")) {
                        args_add(dep_args, "-MQ");
                        args_add(dep_args, output_obj);
@@ -3153,7 +3377,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                args_add(*compiler_args, arch_args[i]);
        }
 
-       // Only pass dependency arguments to the preprocesor since Intel's C++
+       // Only pass dependency arguments to the preprocessor since Intel's C++
        // compiler doesn't produce a correct .d file when compiling preprocessed
        // source.
        args_extend(cpp_args, dep_args);
@@ -3291,7 +3515,12 @@ cc_reset(void)
        free(debug_prefix_maps); debug_prefix_maps = NULL;
        debug_prefix_maps_len = 0;
        free(profile_dir); profile_dir = NULL;
-       free(sanitize_blacklist); sanitize_blacklist = NULL;
+       for (size_t i = 0; i < sanitize_blacklists_len; i++) {
+               free(sanitize_blacklists[i]);
+               sanitize_blacklists[i] = NULL;
+       }
+       free(sanitize_blacklists); sanitize_blacklists = NULL;
+       sanitize_blacklists_len = 0;
        free(included_pch_file); included_pch_file = NULL;
        args_free(orig_args); orig_args = NULL;
        free(input_file); input_file = NULL;
@@ -3409,6 +3638,12 @@ ccache(int argc, char *argv[])
                failed();
        }
 
+       if (conf->depend_mode
+           && (!generating_dependencies || !conf->run_second_cpp || conf->unify)) {
+               cc_log("Disabling depend mode");
+               conf->depend_mode = false;
+       }
+
        cc_log("Source file: %s", input_file);
        if (generating_dependencies) {
                cc_log("Dependency file: %s", output_dep);
@@ -3477,42 +3712,45 @@ ccache(int argc, char *argv[])
                failed();
        }
 
-       // Find the hash using the preprocessed output. Also updates included_files.
-       struct hash *cpp_hash = hash_copy(common_hash);
-       init_hash_debug(
-               cpp_hash, output_obj, 'p', "PREPROCESSOR MODE", debug_text_file);
-
-       object_hash = calculate_object_hash(preprocessor_args, cpp_hash, 0);
-       if (!object_hash) {
-               fatal("internal error: object hash from cpp returned NULL");
-       }
-       update_cached_result_globals(object_hash);
+       if (!conf->depend_mode) {
+               // Find the hash using the preprocessed output. Also updates
+               // included_files.
+               struct hash *cpp_hash = hash_copy(common_hash);
+               init_hash_debug(
+                       cpp_hash, output_obj, 'p', "PREPROCESSOR MODE", debug_text_file);
+
+               object_hash = calculate_object_hash(preprocessor_args, cpp_hash, 0);
+               if (!object_hash) {
+                       fatal("internal error: object hash from cpp returned NULL");
+               }
+               update_cached_result_globals(object_hash);
+
+               if (object_hash_from_manifest
+                   && !file_hashes_equal(object_hash_from_manifest, object_hash)) {
+                       // The hash from manifest differs from the hash of the preprocessor
+                       // output. This could be because:
+                       //
+                       // - The preprocessor produces different output for the same input (not
+                       //   likely).
+                       // - There's a bug in ccache (maybe incorrect handling of compiler
+                       //   arguments).
+                       // - The user has used a different CCACHE_BASEDIR (most likely).
+                       //
+                       // The best thing here would probably be to remove the hash entry from
+                       // the manifest. For now, we use a simpler method: just remove the
+                       // manifest file.
+                       cc_log("Hash from manifest doesn't match preprocessor output");
+                       cc_log("Likely reason: different CCACHE_BASEDIRs used");
+                       cc_log("Removing manifest as a safety measure");
+                       x_unlink(manifest_path);
 
-       if (object_hash_from_manifest
-           && !file_hashes_equal(object_hash_from_manifest, object_hash)) {
-               // The hash from manifest differs from the hash of the preprocessor output.
-               // This could be because:
-               //
-               // - The preprocessor produces different output for the same input (not
-               //   likely).
-               // - There's a bug in ccache (maybe incorrect handling of compiler
-               //   arguments).
-               // - The user has used a different CCACHE_BASEDIR (most likely).
-               //
-               // The best thing here would probably be to remove the hash entry from the
-               // manifest. For now, we use a simpler method: just remove the manifest
-               // file.
-               cc_log("Hash from manifest doesn't match preprocessor output");
-               cc_log("Likely reason: different CCACHE_BASEDIRs used");
-               cc_log("Removing manifest as a safety measure");
-               x_unlink(manifest_path);
+                       put_object_in_manifest = true;
+               }
 
-               put_object_in_manifest = true;
+               // If we can return from cache at this point then do.
+               from_cache(FROMCACHE_CPP_MODE, put_object_in_manifest);
        }
 
-       // If we can return from cache at this point then do.
-       from_cache(FROMCACHE_CPP_MODE, put_object_in_manifest);
-
        if (conf->read_only) {
                cc_log("Read-only mode; running real compiler");
                failed();
@@ -3520,8 +3758,11 @@ ccache(int argc, char *argv[])
 
        add_prefix(compiler_args, conf->prefix_command);
 
+       // In depend_mode, extend the direct hash.
+       struct hash *depend_mode_hash = conf->depend_mode ? direct_hash : NULL;
+
        // Run real compiler, sending output to cache.
-       to_cache(compiler_args);
+       to_cache(compiler_args, depend_mode_hash);
 
        x_exit(0);
 }
index 9ed4571447d8e44b974a9e4db147e89b33f123e1..70c18b38da871e3c8ff45541216b2a72456956ec 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright (C) 2002-2007 Andrew Tridgell
-// Copyright (C) 2009-2018 Joel Rosdahl
+// Copyright (C) 2009-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -84,20 +84,24 @@ enum guessed_compiler {
 
 extern enum guessed_compiler guessed_compiler;
 
-#define SLOPPY_INCLUDE_FILE_MTIME 1
-#define SLOPPY_INCLUDE_FILE_CTIME 2
-#define SLOPPY_FILE_MACRO 4
-#define SLOPPY_TIME_MACROS 8
-#define SLOPPY_PCH_DEFINES 16
+#define SLOPPY_INCLUDE_FILE_MTIME (1U << 0)
+#define SLOPPY_INCLUDE_FILE_CTIME (1U << 1)
+#define SLOPPY_FILE_MACRO (1U << 2)
+#define SLOPPY_TIME_MACROS (1U << 3)
+#define SLOPPY_PCH_DEFINES (1U << 4)
 // Allow us to match files based on their stats (size, mtime, ctime), without
 // looking at their contents.
-#define SLOPPY_FILE_STAT_MATCHES 32
+#define SLOPPY_FILE_STAT_MATCHES (1U << 5)
 // Allow us to not include any system headers in the manifest include files,
 // similar to -MM versus -M for dependencies.
-#define SLOPPY_NO_SYSTEM_HEADERS 64
+#define SLOPPY_SYSTEM_HEADERS (1U << 6)
 // Allow us to ignore ctimes when comparing file stats, so we can fake mtimes
 // if we want to (it is much harder to fake ctimes, requires changing clock)
-#define SLOPPY_FILE_STAT_MATCHES_CTIME 128
+#define SLOPPY_FILE_STAT_MATCHES_CTIME (1U << 7)
+// Allow us to not include the -index-store-path option in the manifest hash.
+#define SLOPPY_CLANG_INDEX_STORE (1U << 8)
+// Ignore locale settings.
+#define SLOPPY_LOCALE (1U << 9)
 
 #define str_eq(s1, s2) (strcmp((s1), (s2)) == 0)
 #define str_startswith(s, prefix) \
@@ -163,6 +167,7 @@ char *x_strndup(const char *s, size_t n);
 void *x_malloc(size_t size);
 void *x_calloc(size_t nmemb, size_t size);
 void *x_realloc(void *ptr, size_t size);
+void x_setenv(const char *name, const char *value);
 void x_unsetenv(const char *name);
 int x_fstat(int fd, struct stat *buf);
 int x_lstat(const char *pathname, struct stat *buf);
index cb67d7a73f4ff141a1ea844761e0a484f539305a..dbf32f0cdfc2a76b8d5a5df61fcd9482992c9a9d 100644 (file)
@@ -208,7 +208,7 @@ compopt_takes_concat_arg(const char *option)
 bool
 compopt_prefix_affects_cpp(const char *option)
 {
-       // Prefix options have to take concatentated args.
+       // Prefix options have to take concatenated args.
        const struct compopt *co = find_prefix(option);
        return co && (co->type & TAKES_CONCAT_ARG) && (co->type & AFFECTS_CPP);
 }
index b9ca0a2401a0152f82327f3fa16875d0e82c65f6..4c7d35df34c9b4ece15dd00bcf2d867cfcc3d9d6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2018 Joel Rosdahl
+// Copyright (C) 2011-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -131,6 +131,7 @@ conf_create(void)
        conf->compression_level = 6;
        conf->cpp_extension = x_strdup("");
        conf->debug = false;
+       conf->depend_mode = false;
        conf->direct_mode = true;
        conf->disable = false;
        conf->extra_files_to_hash = x_strdup("");
@@ -186,7 +187,7 @@ conf_free(struct conf *conf)
 
 // Note: The path pointer is stored in conf, so path must outlive conf.
 //
-// On failure, if an I/O error occured errno is set approriately, otherwise
+// On failure, if an I/O error occured errno is set appropriately, otherwise
 // errno is set to zero indicating that config itself was invalid.
 bool
 conf_read(struct conf *conf, const char *path, char **errmsg)
@@ -390,6 +391,7 @@ conf_print_items(struct conf *conf,
        ok &= print_item(conf, "compression_level", printer, context);
        ok &= print_item(conf, "cpp_extension", printer, context);
        ok &= print_item(conf, "debug", printer, context);
+       ok &= print_item(conf, "depend_mode", printer, context);
        ok &= print_item(conf, "direct_mode", printer, context);
        ok &= print_item(conf, "disable", printer, context);
        ok &= print_item(conf, "extra_files_to_hash", printer, context);
index f45d09b58b9e2afc0ebe54b9c199b1119b8ef229..52a48c8e796ae046ed2af3071dc0752f10315724 100644 (file)
@@ -13,6 +13,7 @@ struct conf {
        unsigned compression_level;
        char *cpp_extension;
        bool debug;
+       bool depend_mode;
        bool direct_mode;
        bool disable;
        char *extra_files_to_hash;
index 6e6e22af4b845541647686f3e81c6b143f3450e3..f6fb89d29edf2b684abe2e26d4e3e016a375ad02 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 Joel Rosdahl
+// Copyright (C) 2018-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -130,12 +130,17 @@ confitem_parse_sloppiness(const char *str, void *result, char **errmsg)
                        *value |= SLOPPY_INCLUDE_FILE_CTIME;
                } else if (str_eq(word, "include_file_mtime")) {
                        *value |= SLOPPY_INCLUDE_FILE_MTIME;
-               } else if (str_eq(word, "no_system_headers")) {
-                       *value |= SLOPPY_NO_SYSTEM_HEADERS;
+               } else if (str_eq(word, "system_headers")
+                          || str_eq(word, "no_system_headers")) {
+                       *value |= SLOPPY_SYSTEM_HEADERS;
                } else if (str_eq(word, "pch_defines")) {
                        *value |= SLOPPY_PCH_DEFINES;
                } else if (str_eq(word, "time_macros")) {
                        *value |= SLOPPY_TIME_MACROS;
+               } else if (str_eq(word, "clang_index_store")) {
+                       *value |= SLOPPY_CLANG_INDEX_STORE;
+               } else if (str_eq(word, "locale")) {
+                       *value |= SLOPPY_LOCALE;
                } else {
                        *errmsg = format("unknown sloppiness: \"%s\"", word);
                        free(p);
@@ -173,8 +178,14 @@ confitem_format_sloppiness(void *value)
        if (*sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME) {
                reformat(&s, "%sfile_stat_matches_ctime, ", s);
        }
-       if (*sloppiness & SLOPPY_NO_SYSTEM_HEADERS) {
-               reformat(&s, "%sno_system_headers, ", s);
+       if (*sloppiness & SLOPPY_SYSTEM_HEADERS) {
+               reformat(&s, "%ssystem_headers, ", s);
+       }
+       if (*sloppiness & SLOPPY_CLANG_INDEX_STORE) {
+               reformat(&s, "%sclang_index_store, ", s);
+       }
+       if (*sloppiness & SLOPPY_LOCALE) {
+               reformat(&s, "%slocale, ", s);
        }
        if (*sloppiness) {
                // Strip last ", ".
index 8d6a76756e827142add09cdcf82b3d468e7ae6f6..828e62eb3f4a566e6ff8a756735137060aeba8c4 100644 (file)
 %}
 struct conf_item;
 %%
-base_dir,             0, ITEM_V(base_dir, env_string, absolute_path)
-cache_dir,            1, ITEM(cache_dir, env_string)
-cache_dir_levels,     2, ITEM_V(cache_dir_levels, unsigned, dir_levels)
-compiler,             3, ITEM(compiler, string)
-compiler_check,       4, ITEM(compiler_check, string)
-compression,          5, ITEM(compression, bool)
-compression_level,    6, ITEM(compression_level, unsigned)
-cpp_extension,        7, ITEM(cpp_extension, string)
-debug,                8, ITEM(debug, bool)
-direct_mode,          9, ITEM(direct_mode, bool)
-disable,             10, ITEM(disable, bool)
-extra_files_to_hash, 11, ITEM(extra_files_to_hash, env_string)
-hard_link,           12, ITEM(hard_link, bool)
-hash_dir,            13, ITEM(hash_dir, bool)
-ignore_headers_in_manifest, 14, ITEM(ignore_headers_in_manifest, env_string)
-keep_comments_cpp,   15, ITEM(keep_comments_cpp, bool)
-limit_multiple,      16, ITEM(limit_multiple, double)
-log_file,            17, ITEM(log_file, env_string)
-max_files,           18, ITEM(max_files, unsigned)
-max_size,            19, ITEM(max_size, size)
-path,                20, ITEM(path, env_string)
-pch_external_checksum, 21, ITEM(pch_external_checksum, bool)
-prefix_command,      22, ITEM(prefix_command, env_string)
-prefix_command_cpp,  23, ITEM(prefix_command_cpp, env_string)
-read_only,           24, ITEM(read_only, bool)
-read_only_direct,    25, ITEM(read_only_direct, bool)
-recache,             26, ITEM(recache, bool)
-run_second_cpp,      27, ITEM(run_second_cpp, bool)
-sloppiness,          28, ITEM(sloppiness, sloppiness)
-stats,               29, ITEM(stats, bool)
-temporary_dir,       30, ITEM(temporary_dir, env_string)
-umask,               31, ITEM(umask, umask)
-unify,               32, ITEM(unify, bool)
+base_dir,                   ITEM_V(base_dir, env_string, absolute_path)
+cache_dir,                  ITEM(cache_dir, env_string)
+cache_dir_levels,           ITEM_V(cache_dir_levels, unsigned, dir_levels)
+compiler,                   ITEM(compiler, string)
+compiler_check,             ITEM(compiler_check, string)
+compression,                ITEM(compression, bool)
+compression_level,          ITEM(compression_level, unsigned)
+cpp_extension,              ITEM(cpp_extension, string)
+debug,                      ITEM(debug, bool)
+depend_mode,                ITEM(depend_mode, bool)
+direct_mode,                ITEM(direct_mode, bool)
+disable,                    ITEM(disable, bool)
+extra_files_to_hash,        ITEM(extra_files_to_hash, env_string)
+hard_link,                  ITEM(hard_link, bool)
+hash_dir,                   ITEM(hash_dir, bool)
+ignore_headers_in_manifest, ITEM(ignore_headers_in_manifest, env_string)
+keep_comments_cpp,          ITEM(keep_comments_cpp, bool)
+limit_multiple,             ITEM(limit_multiple, double)
+log_file,                   ITEM(log_file, env_string)
+max_files,                  ITEM(max_files, unsigned)
+max_size,                   ITEM(max_size, size)
+path,                       ITEM(path, env_string)
+pch_external_checksum,      ITEM(pch_external_checksum, bool)
+prefix_command,             ITEM(prefix_command, env_string)
+prefix_command_cpp,         ITEM(prefix_command_cpp, env_string)
+read_only,                  ITEM(read_only, bool)
+read_only_direct,           ITEM(read_only_direct, bool)
+recache,                    ITEM(recache, bool)
+run_second_cpp,             ITEM(run_second_cpp, bool)
+sloppiness,                 ITEM(sloppiness, sloppiness)
+stats,                      ITEM(stats, bool)
+temporary_dir,              ITEM(temporary_dir, env_string)
+umask,                      ITEM(umask, umask)
+unify,                      ITEM(unify, bool)
index 02a6efd7b20bc6c5ba459aae51e7bef15e2d9f03..8cd130a064b823e1af69b74ef8029ede8e1af924 100644 (file)
@@ -1,5 +1,5 @@
 /* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf src/confitems.gperf  */
+/* Command-line: gperf  */
 /* Computed positions: -k'1-2' */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
       && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
       && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
 /* The character set is not based on ISO-646.  */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
+#warning "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
 #endif
 
-#line 8 "src/confitems.gperf"
-
 #include "confitems.h"
 #include "conf.h"
 
@@ -42,9 +40,8 @@
        ITEM_ENTRY(name, type, NULL)
 #define ITEM_V(name, type, verification) \
        ITEM_ENTRY(name, type, confitem_verify_ ## verification)
-#line 21 "src/confitems.gperf"
 struct conf_item;
-/* maximum key range = 48, duplicates = 0 */
+/* maximum key range = 46, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -58,32 +55,32 @@ confitems_hash (register const char *str, register size_t len)
 {
   static const unsigned char asso_values[] =
     {
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52,  0, 35,  0,
-       0, 10, 52,  0, 30, 25, 52,  0, 10, 20,
-      10,  0,  0, 52,  5,  5, 10, 15, 52, 52,
-      15, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-      52, 52, 52, 52, 52, 52
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50,  0, 35,  0,
+       5, 10, 50,  0, 30, 20, 50,  0, 10, 20,
+      15,  0,  0, 50,  5, 10, 10, 15, 50, 50,
+      20, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50
     };
   return len + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]];
 }
@@ -93,94 +90,60 @@ confitems_get (register const char *str, register size_t len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 33,
+      TOTAL_KEYWORDS = 34,
       MIN_WORD_LENGTH = 4,
       MAX_WORD_LENGTH = 26,
       MIN_HASH_VALUE = 4,
-      MAX_HASH_VALUE = 51
+      MAX_HASH_VALUE = 49
     };
 
   static const struct conf_item wordlist[] =
     {
       {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
       {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
-#line 43 "src/confitems.gperf"
-      {"path",                20, ITEM(path, env_string)},
+      {"path",                       21, ITEM(path, env_string)},
       {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
       {"",0,0,NULL,NULL,NULL},
-#line 26 "src/confitems.gperf"
-      {"compiler",             3, ITEM(compiler, string)},
-#line 24 "src/confitems.gperf"
-      {"cache_dir",            1, ITEM(cache_dir, env_string)},
-      {"",0,0,NULL,NULL,NULL},
-#line 28 "src/confitems.gperf"
-      {"compression",          5, ITEM(compression, bool)},
+      {"compiler",                   3, ITEM(compiler, string)},
+      {"cache_dir",                  1, ITEM(cache_dir, env_string)},
       {"",0,0,NULL,NULL,NULL},
-#line 30 "src/confitems.gperf"
-      {"cpp_extension",        7, ITEM(cpp_extension, string)},
-#line 27 "src/confitems.gperf"
-      {"compiler_check",       4, ITEM(compiler_check, string)},
-#line 31 "src/confitems.gperf"
-      {"debug",                8, ITEM(debug, bool)},
-#line 25 "src/confitems.gperf"
-      {"cache_dir_levels",     2, ITEM_V(cache_dir_levels, unsigned, dir_levels)},
-#line 29 "src/confitems.gperf"
-      {"compression_level",    6, ITEM(compression_level, unsigned)},
-#line 40 "src/confitems.gperf"
-      {"log_file",            17, ITEM(log_file, env_string)},
-#line 45 "src/confitems.gperf"
-      {"prefix_command",      22, ITEM(prefix_command, env_string)},
-#line 52 "src/confitems.gperf"
-      {"stats",               29, ITEM(stats, bool)},
-#line 44 "src/confitems.gperf"
-      {"pch_external_checksum", 21, ITEM(pch_external_checksum, bool)},
-#line 49 "src/confitems.gperf"
-      {"recache",             26, ITEM(recache, bool)},
-#line 46 "src/confitems.gperf"
-      {"prefix_command_cpp",  23, ITEM(prefix_command_cpp, env_string)},
-#line 47 "src/confitems.gperf"
-      {"read_only",           24, ITEM(read_only, bool)},
-#line 51 "src/confitems.gperf"
-      {"sloppiness",          28, ITEM(sloppiness, sloppiness)},
+      {"compression",                5, ITEM(compression, bool)},
       {"",0,0,NULL,NULL,NULL},
-#line 38 "src/confitems.gperf"
-      {"keep_comments_cpp",   15, ITEM(keep_comments_cpp, bool)},
-#line 42 "src/confitems.gperf"
-      {"max_size",            19, ITEM(max_size, size)},
-#line 41 "src/confitems.gperf"
-      {"max_files",           18, ITEM(max_files, unsigned)},
-#line 55 "src/confitems.gperf"
-      {"unify",               32, ITEM(unify, bool)},
-#line 48 "src/confitems.gperf"
-      {"read_only_direct",    25, ITEM(read_only_direct, bool)},
-#line 33 "src/confitems.gperf"
-      {"disable",             10, ITEM(disable, bool)},
-#line 53 "src/confitems.gperf"
-      {"temporary_dir",       30, ITEM(temporary_dir, env_string)},
-#line 50 "src/confitems.gperf"
-      {"run_second_cpp",      27, ITEM(run_second_cpp, bool)},
+      {"cpp_extension",              7, ITEM(cpp_extension, string)},
+      {"compiler_check",             4, ITEM(compiler_check, string)},
       {"",0,0,NULL,NULL,NULL},
-#line 32 "src/confitems.gperf"
-      {"direct_mode",          9, ITEM(direct_mode, bool)},
+      {"cache_dir_levels",           2, ITEM_V(cache_dir_levels, unsigned, dir_levels)},
+      {"compression_level",          6, ITEM(compression_level, unsigned)},
+      {"log_file",                   18, ITEM(log_file, env_string)},
+      {"prefix_command",             23, ITEM(prefix_command, env_string)},
+      {"debug",                      8, ITEM(debug, bool)},
+      {"pch_external_checksum",      22, ITEM(pch_external_checksum, bool)},
+      {"recache",                    27, ITEM(recache, bool)},
+      {"prefix_command_cpp",         24, ITEM(prefix_command_cpp, env_string)},
+      {"read_only",                  25, ITEM(read_only, bool)},
+      {"stats",                      30, ITEM(stats, bool)},
+      {"depend_mode",                9, ITEM(depend_mode, bool)},
+      {"keep_comments_cpp",          16, ITEM(keep_comments_cpp, bool)},
+      {"max_size",                   20, ITEM(max_size, size)},
+      {"max_files",                  19, ITEM(max_files, unsigned)},
+      {"sloppiness",                 29, ITEM(sloppiness, sloppiness)},
+      {"read_only_direct",           26, ITEM(read_only_direct, bool)},
+      {"disable",                    11, ITEM(disable, bool)},
+      {"temporary_dir",              31, ITEM(temporary_dir, env_string)},
+      {"run_second_cpp",             28, ITEM(run_second_cpp, bool)},
+      {"unify",                      33, ITEM(unify, bool)},
+      {"direct_mode",                10, ITEM(direct_mode, bool)},
       {"",0,0,NULL,NULL,NULL},
-#line 36 "src/confitems.gperf"
-      {"hash_dir",            13, ITEM(hash_dir, bool)},
-#line 35 "src/confitems.gperf"
-      {"hard_link",           12, ITEM(hard_link, bool)},
-#line 54 "src/confitems.gperf"
-      {"umask",               31, ITEM(umask, umask)},
-      {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
-#line 23 "src/confitems.gperf"
-      {"base_dir",             0, ITEM_V(base_dir, env_string, absolute_path)},
-#line 34 "src/confitems.gperf"
-      {"extra_files_to_hash", 11, ITEM(extra_files_to_hash, env_string)},
+      {"hash_dir",                   14, ITEM(hash_dir, bool)},
+      {"hard_link",                  13, ITEM(hard_link, bool)},
+      {"umask",                      32, ITEM(umask, umask)},
       {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
-      {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
-#line 39 "src/confitems.gperf"
-      {"limit_multiple",      16, ITEM(limit_multiple, double)},
+      {"base_dir",                   0, ITEM_V(base_dir, env_string, absolute_path)},
+      {"limit_multiple",             17, ITEM(limit_multiple, double)},
       {"",0,0,NULL,NULL,NULL},
-#line 37 "src/confitems.gperf"
-      {"ignore_headers_in_manifest", 14, ITEM(ignore_headers_in_manifest, env_string)}
+      {"ignore_headers_in_manifest", 15, ITEM(ignore_headers_in_manifest, env_string)},
+      {"",0,0,NULL,NULL,NULL}, {"",0,0,NULL,NULL,NULL},
+      {"extra_files_to_hash",        12, ITEM(extra_files_to_hash, env_string)}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -197,4 +160,4 @@ confitems_get (register const char *str, register size_t len)
     }
   return 0;
 }
-size_t confitems_count(void) { return 33; }
+size_t confitems_count(void) { return 34; }
index ffd354b2b331c66b8d82cc59f51d7bfeb520aa66..374d19c5d3f16653b9bdbb799d594dda6a19f959 100644 (file)
@@ -19,6 +19,7 @@ COMPRESS, "compression"
 COMPRESSLEVEL, "compression_level"
 CPP2, "run_second_cpp"
 COMMENTS, "keep_comments_cpp"
+DEPEND, "depend_mode"
 DIR, "cache_dir"
 DEBUG, "debug"
 DIRECT, "direct_mode"
index 30432af4b3e06f091685332c47ba3da33b960ba2..08117ef4d15165059a5a46606e061be8e98f3908 100644 (file)
@@ -1,5 +1,5 @@
 /* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf src/envtoconfitems.gperf  */
+/* Command-line: gperf  */
 /* Computed positions: -k'4-5' */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
       && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
       && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
 /* The character set is not based on ISO-646.  */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
+#warning "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
 #endif
 
-#line 9 "src/envtoconfitems.gperf"
-
 #include "envtoconfitems.h"
-#line 12 "src/envtoconfitems.gperf"
 struct env_to_conf_item;
 /* maximum key range = 52, duplicates = 0 */
 
@@ -54,10 +51,10 @@ envtoconfitems_hash (register const char *str, register size_t len)
       54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
       54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
        0, 54, 54, 54, 54, 54, 54, 54, 54, 54,
-      54, 54, 54, 54, 54, 25, 10,  0,  0, 15,
-      10,  0,  5,  0, 54, 10, 35, 15,  0, 25,
-       0, 54, 15, 20,  0,  0, 15, 54, 54,  0,
-      54, 54, 54, 54, 54,  5, 54, 54, 54, 54,
+      54, 54, 54, 54, 54, 25, 10,  0,  0,  5,
+      10,  0, 15,  0, 54, 10, 35, 25, 10, 25,
+       0, 54, 15, 20,  0,  0, 25, 54, 54, 15,
+      54, 54, 54, 54, 54,  0, 54, 54, 54, 54,
       54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
       54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
       54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
@@ -97,7 +94,7 @@ envtoconfitems_get (register const char *str, register size_t len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 34,
+      TOTAL_KEYWORDS = 35,
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 15,
       MIN_HASH_VALUE = 2,
@@ -107,85 +104,51 @@ envtoconfitems_get (register const char *str, register size_t len)
   static const struct env_to_conf_item wordlist[] =
     {
       {"",""}, {"",""},
-#line 15 "src/envtoconfitems.gperf"
       {"CC", "compiler"},
-#line 22 "src/envtoconfitems.gperf"
       {"DIR", "cache_dir"},
-#line 20 "src/envtoconfitems.gperf"
       {"CPP2", "run_second_cpp"},
-#line 23 "src/envtoconfitems.gperf"
       {"DEBUG", "debug"},
       {"",""},
-#line 45 "src/envtoconfitems.gperf"
       {"TEMPDIR", "temporary_dir"},
-#line 16 "src/envtoconfitems.gperf"
       {"COMPILER", "compiler"},
-#line 36 "src/envtoconfitems.gperf"
-      {"PATH", "path"},
-#line 43 "src/envtoconfitems.gperf"
-      {"SLOPPINESS", "sloppiness"},
       {"",""},
-#line 29 "src/envtoconfitems.gperf"
-      {"HASHDIR", "hash_dir"},
-#line 17 "src/envtoconfitems.gperf"
+      {"SLOPPINESS", "sloppiness"},
+      {"DIRECT", "direct_mode"},
+      {"BASEDIR", "base_dir"},
       {"COMPILERCHECK", "compiler_check"},
-#line 31 "src/envtoconfitems.gperf"
       {"LIMIT_MULTIPLE", "limit_multiple"},
-#line 47 "src/envtoconfitems.gperf"
-      {"UNIFY", "unify"},
-#line 38 "src/envtoconfitems.gperf"
+      {"PCH_EXTSUM", "pch_external_checksum"},
       {"PREFIX", "prefix_command"},
-#line 32 "src/envtoconfitems.gperf"
       {"LOGFILE", "log_file"},
-#line 33 "src/envtoconfitems.gperf"
       {"MAXFILES", "max_files"},
-      {"",""},
-#line 39 "src/envtoconfitems.gperf"
+      {"PATH", "path"},
       {"PREFIX_CPP", "prefix_command_cpp"},
-#line 24 "src/envtoconfitems.gperf"
-      {"DIRECT", "direct_mode"},
-#line 14 "src/envtoconfitems.gperf"
-      {"BASEDIR", "base_dir"},
-#line 18 "src/envtoconfitems.gperf"
+      {"DEPEND", "depend_mode"},
+      {"HASHDIR", "hash_dir"},
       {"COMPRESS", "compression"},
-#line 26 "src/envtoconfitems.gperf"
       {"EXTENSION", "cpp_extension"},
-#line 44 "src/envtoconfitems.gperf"
       {"STATS", "stats"},
       {"",""},
-#line 34 "src/envtoconfitems.gperf"
       {"MAXSIZE", "max_size"},
-#line 19 "src/envtoconfitems.gperf"
       {"COMPRESSLEVEL", "compression_level"},
       {"",""},
-#line 37 "src/envtoconfitems.gperf"
-      {"PCH_EXTSUM", "pch_external_checksum"},
+      {"UNIFY", "unify"},
       {"",""},
-#line 42 "src/envtoconfitems.gperf"
       {"RECACHE", "recache"},
-#line 40 "src/envtoconfitems.gperf"
       {"READONLY", "read_only"},
       {"",""},
-#line 46 "src/envtoconfitems.gperf"
       {"UMASK", "umask"},
       {"",""},
-#line 35 "src/envtoconfitems.gperf"
       {"NLEVELS", "cache_dir_levels"},
-#line 21 "src/envtoconfitems.gperf"
       {"COMMENTS", "keep_comments_cpp"},
       {"",""},
-#line 41 "src/envtoconfitems.gperf"
       {"READONLY_DIRECT", "read_only_direct"},
       {"",""},
-#line 25 "src/envtoconfitems.gperf"
       {"DISABLE", "disable"},
-#line 28 "src/envtoconfitems.gperf"
       {"HARDLINK", "hard_link"},
       {"",""}, {"",""}, {"",""}, {"",""}, {"",""}, {"",""},
-#line 27 "src/envtoconfitems.gperf"
       {"EXTRAFILES", "extra_files_to_hash"},
       {"",""}, {"",""},
-#line 30 "src/envtoconfitems.gperf"
       {"IGNOREHEADERS", "ignore_headers_in_manifest"}
     };
 
@@ -203,4 +166,4 @@ envtoconfitems_get (register const char *str, register size_t len)
     }
   return 0;
 }
-size_t envtoconfitems_count(void) { return 34; }
+size_t envtoconfitems_count(void) { return 35; }
index 61141c236b5241c724bfb4e1b8bf1d98a2e91a03..3e321930e4fbe74cd8e741d8beeb8f63bda283c8 100644 (file)
 
 #include "config.h"
 
-#ifndef HAVE_GETOPT_LONG
+#ifdef HAVE_GETOPT_LONG
+
+typedef int do_not_warn_about_empty_compilation_unit;
+
+#else
 
 #include "getopt_long.h"
 
index 4ed10d774d2a8d425811fb4960d22db50019e223..789bf437b51efcffe869a5eb67e89f540ba9aa7e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2009-2018 Joel Rosdahl
+// Copyright (C) 2009-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -62,18 +62,18 @@ check_for_temporal_macros(const char *str, size_t len)
                // Check whether the substring ending at str[i] has the form "__...E__". On
                // the assumption that 'E' is less common in source than '_', we check
                // str[i-2] first.
-               if (str[i - 2] == 'E' &&
-                   str[i - 0] == '_' &&
-                   str[i - 7] == '_' &&
-                   str[i - 1] == '_' &&
-                   str[i - 6] == '_') {
+               if (str[i - 2] == 'E'
+                   && str[i - 0] == '_'
+                   && str[i - 7] == '_'
+                   && str[i - 1] == '_'
+                   && str[i - 6] == '_'
+                   && (i < 8 || (str[i - 8] != '_' && !isalnum(str[i - 8])))
+                   && (i + 1 >= len || (str[i + 1] != '_' && !isalnum(str[i + 1])))) {
                        // Check the remaining characters to see if the substring is "__DATE__"
                        // or "__TIME__".
-                       if (str[i - 5] == 'D' && str[i - 4] == 'A' &&
-                           str[i - 3] == 'T') {
+                       if (str[i - 5] == 'D' && str[i - 4] == 'A' && str[i - 3] == 'T') {
                                result |= HASH_SOURCE_CODE_FOUND_DATE;
-                       } else if (str[i - 5] == 'T' && str[i - 4] == 'I' &&
-                                  str[i - 3] == 'M') {
+                       } else if (str[i - 5] == 'T' && str[i - 4] == 'I' && str[i - 3] == 'M') {
                                result |= HASH_SOURCE_CODE_FOUND_TIME;
                        }
                }
index 0de03da70a08a363fa5244533579fd25168219a4..c669553c4639c5422b7b6920bb4e875a3c158bcf 100644 (file)
 #include <unistd.h>
 #include <utime.h>
 
+// AIX/PASE does not properly define usleep within its headers. However, the
+// function is available in libc.a. This extern define ensures that it is
+// usable within the ccache code base.
+#ifdef _AIX
+extern int usleep(useconds_t);
+#endif
+
 extern char **environ;
 
 #ifndef ESTALE
index 36d3b632319fdf7553647fed1f5f18fb744ca46b..e442cc42b9450db343371eef9b14cfba36c060a9 100644 (file)
@@ -780,6 +780,16 @@ x_realloc(void *ptr, size_t size)
        return p2;
 }
 
+// This is like setenv.
+void x_setenv(const char *name, const char *value)
+{
+#ifdef HAVE_SETENV
+       setenv(name, value, true);
+#else
+       putenv(format("%s=%s", name, value)); // Leak to environment.
+#endif
+}
+
 // This is like unsetenv.
 void x_unsetenv(const char *name)
 {
index 6c7363bae68fe56cda022cff4f5a6e7b9f709a96..29a6c5f8425958455dde3a90ec59bd816d1ebed0 100644 (file)
@@ -1 +1 @@
-extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.5.1";
+extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.6";
index 0aac132a792a3f5476ba014ab0d8f729a3e0f897..10666c6a4977aadd6c26c89f8eb0e430ef3561b3 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -378,6 +378,8 @@ debug_prefix_map
 masquerading
 hardlink
 direct
+direct_gcc
+depend
 basedir
 compression
 readonly
index 63ef9e7145da5d46b4cd69e686848e2cab7a3084..212e148ff2b821e1d0218435fbeddae2c8777dc9 100644 (file)
@@ -138,6 +138,47 @@ base_tests() {
     $CCACHE_COMPILE -c -O2 2>/dev/null
     expect_stat 'no input file' 1
 
+    # -------------------------------------------------------------------------
+    TEST "LANG"
+
+    $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 1
+
+    $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 1
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 1
+
+    LANG=foo $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 1
+    expect_stat 'cache miss' 2
+    expect_stat 'files in cache' 2
+
+    LANG=foo $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 2
+    expect_stat 'cache miss' 2
+    expect_stat 'files in cache' 2
+
+    # -------------------------------------------------------------------------
+    TEST "LANG with sloppiness"
+
+    CCACHE_SLOPPINESS=locale LANG=foo $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 1
+
+    CCACHE_SLOPPINESS=locale LANG=foo $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 1
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 1
+
+    CCACHE_SLOPPINESS=locale LANG=bar $CCACHE_COMPILE -c test1.c
+    expect_stat 'cache hit (preprocessed)' 2
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 1
+
     # -------------------------------------------------------------------------
     TEST "CCACHE_DISABLE"
 
diff --git a/test/suites/depend.bash b/test/suites/depend.bash
new file mode 100644 (file)
index 0000000..f59b36c
--- /dev/null
@@ -0,0 +1,96 @@
+SUITE_depend_SETUP() {
+    unset CCACHE_NODIRECT
+
+    cat <<EOF >test.c
+// test.c
+#include "test1.h"
+#include "test2.h"
+EOF
+    cat <<EOF >test1.h
+#include "test3.h"
+int test1;
+EOF
+    cat <<EOF >test2.h
+int test2;
+EOF
+    cat <<EOF >test3.h
+int test3;
+EOF
+    backdate test1.h test2.h test3.h
+
+    $REAL_COMPILER -c -Wp,-MD,expected.d test.c
+    $REAL_COMPILER -c -Wp,-MMD,expected_mmd.d test.c
+    rm test.o
+
+    DEPSFLAGS_REAL="-MP -MMD -MF reference_test.d"
+    DEPSFLAGS_CCACHE="-MP -MMD -MF test.d"
+}
+
+SUITE_depend() {
+    # -------------------------------------------------------------------------
+    TEST "Base case"
+
+    $REAL_COMPILER $DEPSFLAGS_REAL -c -o reference_test.o test.c
+
+    CCACHE_DEPEND=1 $CCACHE_COMPILE $DEPSFLAGS_CCACHE -c test.c
+    expect_equal_object_files reference_test.o test.o
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 3 # .o + .manifest + .d
+
+
+    CCACHE_DEPEND=1 $CCACHE_COMPILE $DEPSFLAGS_CCACHE -c test.c
+    expect_equal_object_files reference_test.o test.o
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 3
+
+    # -------------------------------------------------------------------------
+    TEST "No explicit dependency file"
+
+    $REAL_COMPILER $DEPSFLAGS_REAL -c -o reference_test.o test.c
+
+    CCACHE_DEPEND=1 $CCACHE_COMPILE -MD -c test.c
+    expect_equal_object_files reference_test.o test.o
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 3 # .o + .manifest + .d
+
+    CCACHE_DEPEND=1 $CCACHE_COMPILE -MD -c test.c
+    expect_equal_object_files reference_test.o test.o
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 3
+
+    # -------------------------------------------------------------------------
+    TEST "stderr from both preprocessor and compiler"
+
+    cat <<EOF >cpp-warning.c
+#if FOO
+// Trigger preprocessor warning about extra token after #endif.
+#endif FOO
+int stderr(void)
+{
+  // Trigger compiler warning by having no return statement.
+}
+EOF
+    $REAL_COMPILER -MD -Wall -W -c cpp-warning.c 2>stderr-baseline.txt
+
+    CCACHE_DEPEND=1 $CCACHE_COMPILE -MD -Wall -W -c cpp-warning.c 2>stderr-orig.txt
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_file_content stderr-orig.txt "`cat stderr-baseline.txt`"
+
+    CCACHE_DEPEND=1 $CCACHE_COMPILE -MD -Wall -W -c cpp-warning.c 2>stderr-mf.txt
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_file_content stderr-mf.txt "`cat stderr-baseline.txt`"
+
+    # TODO: Add more test cases (see direct.bash for inspiration)
+}
index f12d6c481fd3bc04f759755442bf2b322e340608..f3025b139d8ac47c08b3da18b6accfcd1329894c 100644 (file)
@@ -744,6 +744,19 @@ EOF
     expect_stat 'cache hit (preprocessed)' 0
     expect_stat 'cache miss' 1
 
+    # -------------------------------------------------------------------------
+    TEST "Sloppy Clang index store"
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS clang_index_store" $CCACHE_COMPILE -index-store-path foo -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS clang_index_store" $CCACHE_COMPILE -index-store-path bar -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+
     # -------------------------------------------------------------------------
     # Check that environment variables that affect the preprocessor are taken
     # into account.
diff --git a/test/suites/direct_gcc.bash b/test/suites/direct_gcc.bash
new file mode 100644 (file)
index 0000000..4eb9bf6
--- /dev/null
@@ -0,0 +1,142 @@
+SUITE_direct_gcc_PROBE() {
+    if [[ $REAL_COMPILER != *"gcc"* ]]; then
+        echo "Skipping GCC only test cases"
+    fi
+}
+
+SUITE_direct_gcc_SETUP() {
+    unset CCACHE_NODIRECT
+
+    cat <<EOF >test.c
+// test.c
+#include "test1.h"
+#include "test2.h"
+EOF
+    cat <<EOF >test1.h
+#include "test3.h"
+int test1;
+EOF
+    cat <<EOF >test2.h
+int test2;
+EOF
+    cat <<EOF >test3.h
+int test3;
+EOF
+    backdate test1.h test2.h test3.h
+
+    DEPENDENCIES_OUTPUT="expected_dependencies_output.d" $REAL_COMPILER -c test.c
+    DEPENDENCIES_OUTPUT="expected_dependencies_output_target.d target.o" $REAL_COMPILER -c test.c
+    SUNPRO_DEPENDENCIES="expected_sunpro_dependencies.d" $REAL_COMPILER -c test.c
+    SUNPRO_DEPENDENCIES="expected_sunpro_dependencies_target.d target.o" $REAL_COMPILER -c test.c
+    rm test.o
+}
+
+SUITE_direct_gcc() {
+    # -------------------------------------------------------------------------
+    TEST "DEPENDENCIES_OUTPUT environment variable"
+
+    DEPENDENCIES_OUTPUT="other.d" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_dependencies_output.d
+
+    DEPENDENCIES_OUTPUT="other.d" $REAL_COMPILER -c test.c -o reference_test.o
+    expect_equal_object_files reference_test.o test.o
+
+    rm -f other.d
+    DEPENDENCIES_OUTPUT="other.d" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_dependencies_output.d
+    expect_equal_object_files reference_test.o test.o
+
+    DEPENDENCIES_OUTPUT="different_name.d" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 2
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files different_name.d expected_dependencies_output.d
+    expect_equal_object_files reference_test.o test.o
+
+    # -------------------------------------------------------------------------
+    TEST "DEPENDENCIES_OUTPUT environment variable with target"
+
+    DEPENDENCIES_OUTPUT="other.d target.o" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_dependencies_output_target.d
+
+    DEPENDENCIES_OUTPUT="other.d target.o" $REAL_COMPILER -c test.c -o reference_test.o
+    expect_equal_object_files reference_test.o test.o
+
+    rm -f other.d
+    DEPENDENCIES_OUTPUT="other.d target.o" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_dependencies_output_target.d
+    expect_equal_object_files reference_test.o test.o
+
+    DEPENDENCIES_OUTPUT="different_name.d target.o" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 2
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files different_name.d expected_dependencies_output_target.d
+    expect_equal_object_files reference_test.o test.o
+
+    # -------------------------------------------------------------------------
+    TEST "SUNPRO_DEPENDENCIES environment variable"
+
+    SUNPRO_DEPENDENCIES="other.d" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_sunpro_dependencies.d
+
+    SUNPRO_DEPENDENCIES="other.d" $REAL_COMPILER -c test.c -o reference_test.o
+    expect_equal_object_files reference_test.o test.o
+
+    rm -f other.d
+    SUNPRO_DEPENDENCIES="other.d" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_sunpro_dependencies.d
+    expect_equal_object_files reference_test.o test.o
+
+    SUNPRO_DEPENDENCIES="different_name.d" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 2
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files different_name.d expected_sunpro_dependencies.d
+    expect_equal_object_files reference_test.o test.o
+
+    # -------------------------------------------------------------------------
+    TEST "SUNPRO_DEPENDENCIES environment variable with target"
+
+    SUNPRO_DEPENDENCIES="other.d target.o" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_sunpro_dependencies_target.d
+
+    SUNPRO_DEPENDENCIES="other.d target.o" $REAL_COMPILER -c test.c -o reference_test.o
+    expect_equal_object_files reference_test.o test.o
+
+    rm -f other.d
+    SUNPRO_DEPENDENCIES="other.d target.o" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files other.d expected_sunpro_dependencies_target.d
+    expect_equal_object_files reference_test.o test.o
+
+    SUNPRO_DEPENDENCIES="different_name.d target.o" $CCACHE_COMPILE -c test.c
+    expect_stat 'cache hit (direct)' 2
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_equal_files different_name.d expected_sunpro_dependencies_target.d
+    expect_equal_object_files reference_test.o test.o
+}
index f4f969e3cfdeb74f023230adb55950e945cc9e0a..bc93018572520a40c92b782d7edc721c7cb248c7 100644 (file)
@@ -30,4 +30,34 @@ SUITE_hardlink() {
     if [ ! $obj_in_cache -ef test1.o ]; then
         test_failed "Object file not hard-linked to cached object file"
     fi
+
+    # -------------------------------------------------------------------------
+    TEST "Overwrite assembler"
+
+    generate_code 1 test1.c
+    $REAL_COMPILER -S -o test1.s test1.c
+
+    $REAL_COMPILER -c -o reference_test1.o test1.s
+
+    CCACHE_HARDLINK=1 $CCACHE_COMPILE -c test1.s
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 1
+
+    generate_code 2 test1.c
+    $REAL_COMPILER -S -o test1.s test1.c
+
+    CCACHE_HARDLINK=1 $CCACHE_COMPILE -c test1.s
+    expect_stat 'cache hit (preprocessed)' 0
+    expect_stat 'cache miss' 2
+    expect_stat 'files in cache' 2
+
+    generate_code 1 test1.c
+    $REAL_COMPILER -S -o test1.s test1.c
+
+    CCACHE_HARDLINK=1 $CCACHE_COMPILE -c test1.s
+    expect_stat 'cache hit (preprocessed)' 1
+    expect_stat 'cache miss' 2
+    expect_stat 'files in cache' 2
+    expect_equal_object_files reference_test1.o test1.o
 }
index a2411e9bcbd67b332b000f675b2d21247855d4fa..fbe70f88db51447cd75c99b47d67e9316b99aed6 100644 (file)
@@ -7,8 +7,9 @@ SUITE_sanitize_blacklist_PROBE() {
 }
 
 SUITE_sanitize_blacklist_SETUP() {
-    generate_code 1 test1.c
+    generate_code 2 test1.c
     echo "fun:foo" >blacklist.txt
+    echo "fun_1:foo" >blacklist2.txt
 
     unset CCACHE_NODIRECT
 }
@@ -55,4 +56,31 @@ SUITE_sanitize_blacklist() {
     fi
 
     expect_stat 'error hashing extra file' 1
+
+    # -------------------------------------------------------------------------
+    TEST "Multiple -fsanitize-blacklist"
+
+    $REAL_COMPILER -c -fsanitize-blacklist=blacklist2.txt -fsanitize-blacklist=blacklist.txt test1.c
+
+    $CCACHE_COMPILE -c -fsanitize-blacklist=blacklist2.txt -fsanitize-blacklist=blacklist.txt test1.c
+    expect_stat 'cache hit (direct)' 0
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 2
+
+    $CCACHE_COMPILE -c -fsanitize-blacklist=blacklist2.txt -fsanitize-blacklist=blacklist.txt test1.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 1
+    expect_stat 'files in cache' 2
+
+    echo "fun_2:foo" >blacklist2.txt
+
+    $CCACHE_COMPILE -c -fsanitize-blacklist=blacklist2.txt -fsanitize-blacklist=blacklist.txt test1.c
+    expect_stat 'cache hit (direct)' 1
+    expect_stat 'cache miss' 2
+    expect_stat 'files in cache' 4
+
+    $CCACHE_COMPILE -c -fsanitize-blacklist=blacklist2.txt -fsanitize-blacklist=blacklist.txt test1.c
+    expect_stat 'cache hit (direct)' 2
+    expect_stat 'cache miss' 2
+    expect_stat 'files in cache' 4
 }
index fb30c98498b262c511789fed7efd6e32630255f2..8d40a511f5203e8b654e717856019ae1670ee7ec 100644 (file)
@@ -184,12 +184,12 @@ TEST(sysroot_should_be_rewritten_if_basedir_is_used)
        free(conf->base_dir);
        conf->base_dir = get_root();
        current_working_dir = get_cwd();
-       arg_string = format("cc --sysroot=%s/foo -c foo.c", current_working_dir);
+       arg_string = format("cc --sysroot=%s/foo/bar -c foo.c", current_working_dir);
        orig = args_init_from_string(arg_string);
        free(arg_string);
 
        CHECK(cc_process_args(orig, &act_cpp, &act_cc));
-       CHECK_STR_EQ(act_cpp->argv[1], "--sysroot=./foo");
+       CHECK_STR_EQ(act_cpp->argv[1], "--sysroot=./foo/bar");
 
        args_free(orig);
        args_free(act_cpp);
@@ -366,7 +366,7 @@ TEST(fprofile_flag_with_existing_dir_should_be_rewritten_to_real_path)
        args_free(orig);
 }
 
-TEST(fprofile_flag_with_nonexisting_dir_should_not_be_rewritten)
+TEST(fprofile_flag_with_nonexistent_dir_should_not_be_rewritten)
 {
        struct args *orig = args_init_from_string(
                "gcc -c -fprofile-generate=some/dir foo.c");
index 263e649706f6f21764f604fc603799a80b384b3f..94dc2dd491f1d1d1abb9c9300cfd61ae4fd31619 100644 (file)
@@ -45,7 +45,7 @@ TEST(dash_V_doesnt_affect_cpp)
        CHECK(!compopt_affects_cpp("-V"));
 }
 
-TEST(dash_doesnexist_doesnt_affect_cpp)
+TEST(dash_doesntexist_doesnt_affect_cpp)
 {
        CHECK(!compopt_affects_cpp("-doesntexist"));
 }
@@ -90,7 +90,7 @@ TEST(dash_fstack_usage_not_too_hard)
        CHECK(!compopt_too_hard("-fstack-usage"));
 }
 
-TEST(dash_doesnexist_not_too_hard)
+TEST(dash_doesntexist_not_too_hard)
 {
        CHECK(!compopt_too_hard("-doesntexist"));
 }
index 849a2c0b4c62cdf14bbc05853fab9b4639b2135e..371a3951607e4ddd8f368a9591d469279422571a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2018 Joel Rosdahl
+// Copyright (C) 2011-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -18,7 +18,7 @@
 #include "framework.h"
 #include "util.h"
 
-#define N_CONFIG_ITEMS 33
+#define N_CONFIG_ITEMS 34
 static struct {
        char *descr;
        char *origin;
@@ -59,6 +59,7 @@ TEST(conf_create)
        CHECK_INT_EQ(6, conf->compression_level);
        CHECK_STR_EQ("", conf->cpp_extension);
        CHECK(!conf->debug);
+       CHECK(!conf->depend_mode);
        CHECK(conf->direct_mode);
        CHECK(!conf->disable);
        CHECK_STR_EQ("", conf->extra_files_to_hash);
@@ -111,6 +112,7 @@ TEST(conf_read_valid_config)
                "compression=true\n"
                "compression_level= 2\n"
                "cpp_extension = .foo\n"
+               "depend_mode = true\n"
                "direct_mode = false\n"
                "disable = true\n"
                "extra_files_to_hash = a:b c:$USER\n"
@@ -130,7 +132,7 @@ TEST(conf_read_valid_config)
                "read_only_direct = true\n"
                "recache = true\n"
                "run_second_cpp = false\n"
-               "sloppiness =     file_macro   ,time_macros,  include_file_mtime,include_file_ctime,file_stat_matches,file_stat_matches_ctime,pch_defines ,  no_system_headers  \n"
+               "sloppiness =     file_macro   ,time_macros,  include_file_mtime,include_file_ctime,file_stat_matches,file_stat_matches_ctime,pch_defines ,  no_system_headers,system_headers,clang_index_store\n"
                "stats = false\n"
                "temporary_dir = ${USER}_foo\n"
                "umask = 777\n"
@@ -150,6 +152,7 @@ TEST(conf_read_valid_config)
        CHECK(conf->compression);
        CHECK_INT_EQ(2, conf->compression_level);
        CHECK_STR_EQ(".foo", conf->cpp_extension);
+       CHECK(conf->depend_mode);
        CHECK(!conf->direct_mode);
        CHECK(conf->disable);
        CHECK_STR_EQ_FREE1(format("a:b c:%s", user), conf->extra_files_to_hash);
@@ -169,11 +172,17 @@ TEST(conf_read_valid_config)
        CHECK(conf->read_only_direct);
        CHECK(conf->recache);
        CHECK(!conf->run_second_cpp);
-       CHECK_INT_EQ(SLOPPY_INCLUDE_FILE_MTIME|SLOPPY_INCLUDE_FILE_CTIME|
-                    SLOPPY_FILE_MACRO|SLOPPY_TIME_MACROS|
-                    SLOPPY_FILE_STAT_MATCHES|SLOPPY_FILE_STAT_MATCHES_CTIME|
-                    SLOPPY_NO_SYSTEM_HEADERS|SLOPPY_PCH_DEFINES,
-                    conf->sloppiness);
+       CHECK_INT_EQ(
+               SLOPPY_INCLUDE_FILE_MTIME
+               |SLOPPY_INCLUDE_FILE_CTIME
+               |SLOPPY_FILE_MACRO
+               |SLOPPY_TIME_MACROS
+               |SLOPPY_FILE_STAT_MATCHES
+               |SLOPPY_FILE_STAT_MATCHES_CTIME
+               |SLOPPY_SYSTEM_HEADERS
+               |SLOPPY_PCH_DEFINES
+               |SLOPPY_CLANG_INDEX_STORE,
+               conf->sloppiness);
        CHECK(!conf->stats);
        CHECK_STR_EQ_FREE1(format("%s_foo", user), conf->temporary_dir);
        CHECK_INT_EQ(0777, conf->umask);
@@ -440,6 +449,7 @@ TEST(conf_print_items)
                8,
                "ce",
                false,
+               true,
                false,
                true,
                "efth",
@@ -462,7 +472,7 @@ TEST(conf_print_items)
                SLOPPY_FILE_MACRO|SLOPPY_INCLUDE_FILE_MTIME|
                SLOPPY_INCLUDE_FILE_CTIME|SLOPPY_TIME_MACROS|
                SLOPPY_FILE_STAT_MATCHES|SLOPPY_FILE_STAT_MATCHES_CTIME|
-               SLOPPY_PCH_DEFINES|SLOPPY_NO_SYSTEM_HEADERS,
+               SLOPPY_PCH_DEFINES|SLOPPY_SYSTEM_HEADERS|SLOPPY_CLANG_INDEX_STORE,
                false,
                "td",
                022,
@@ -491,6 +501,7 @@ TEST(conf_print_items)
        CHECK_STR_EQ("compression_level = 8", received_conf_items[n++].descr);
        CHECK_STR_EQ("cpp_extension = ce", received_conf_items[n++].descr);
        CHECK_STR_EQ("debug = false", received_conf_items[n++].descr);
+       CHECK_STR_EQ("depend_mode = true", received_conf_items[n++].descr);
        CHECK_STR_EQ("direct_mode = false", received_conf_items[n++].descr);
        CHECK_STR_EQ("disable = true", received_conf_items[n++].descr);
        CHECK_STR_EQ("extra_files_to_hash = efth", received_conf_items[n++].descr);
@@ -513,7 +524,8 @@ TEST(conf_print_items)
        CHECK_STR_EQ("run_second_cpp = false", received_conf_items[n++].descr);
        CHECK_STR_EQ("sloppiness = file_macro, include_file_mtime,"
                     " include_file_ctime, time_macros, pch_defines,"
-                    " file_stat_matches, file_stat_matches_ctime, no_system_headers",
+                    " file_stat_matches, file_stat_matches_ctime, system_headers,"
+                    " clang_index_store",
                     received_conf_items[n++].descr);
        CHECK_STR_EQ("stats = false", received_conf_items[n++].descr);
        CHECK_STR_EQ("temporary_dir = td", received_conf_items[n++].descr);
index 2b2dbc9b1e488bb6b1c8153a37f1e393de93c45c..d05769e5f69f7ce61dde74c227cca0f485d8ff51 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2010-2018 Joel Rosdahl
+// Copyright (C) 2010-2019 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -149,6 +149,13 @@ TEST(check_for_temporal_macros)
                "#define ab __DATE__";
 
        const char no_temporal[] =
+               "#define ab a__DATE__\n"
+               "#define ab  __DATE__a\n"
+               "#define ab A__DATE__\n"
+               "#define ab  __DATE__A\n"
+               "#define ab 0__DATE__\n"
+               "#define ab  __DATE__0\n"
+               "#define ab _ _DATE__\n"
                "#define ab _ _DATE__\n"
                "#define ab __ DATE__\n"
                "#define ab __D ATE__\n"