---------------------
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.
<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>
<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
<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
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 \
/* 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
no_implicit_fallthrough_warning
more_warnings
include_dev_mk
-getopt_long_c
extra_libs
disable_man
host_os
$as_echo "#define _WIN32_WINNT 0x0600" >>confdefs.h
+ ;;
+ *os400* | *aix*)
+ AR="ar -X64"
;;
esac
-
# The later defininition of _XOPEN_SOURCE disables certain features
# on Linux, so we need _GNU_SOURCE to re-enable them (makedev, tm_zone).
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"
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 :
#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
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)
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>],
#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
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
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
src/confitems_lookup.c \
src/envtoconfitems.gperf \
src/envtoconfitems_lookup.c \
- src/getopt_long.c \
src/main.c \
src/zlib/*.c \
src/zlib/*.h \
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)
$(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
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
* 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>
* 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>
* 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>
* Wilson Snyder <wsnyder@wsnyder.org>
* Xavier René-Corail <xavier.renecorail@gmail.com>
* Yiding Jia <yiding@fb.com>
+* Yvan Janssens <friedkiwi@yvanj.me>
Thanks!
<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>
</li>\r
<li>\r
<p>\r
+Joel Galenson <<a href="mailto:jgalenson@gmail.com">jgalenson@gmail.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Joel Rosdahl <<a href="mailto:joel@rosdahl.net">joel@rosdahl.net</a>>\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
+Jonny Yu <<a href="mailto:yingshen.yu@gmail.com">yingshen.yu@gmail.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Jørgen P. Tjernø <<a href="mailto:jorgen@valvesoftware.com">jorgen@valvesoftware.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
+Josh Soref <<a href="mailto:jsoref@users.noreply.github.com">jsoref@users.noreply.github.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Justin Lebar <<a href="mailto:justin.lebar@gmail.com">justin.lebar@gmail.com</a>>\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
+Maarten Maathuis <<a href="mailto:madman2003@shikahr.net">madman2003@shikahr.net</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Mark Starovoytov <<a href="mailto:starovoytov.mark@googlemail.com">starovoytov.mark@googlemail.com</a>>\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
+Michał Mirosław <<a href="mailto:mirq-linux@rere.qmqm.pl">mirq-linux@rere.qmqm.pl</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Mihai Serban <<a href="mailto:mihai.serban@intel.com">mihai.serban@intel.com</a>>\r
</p>\r
</li>\r
Yiding Jia <<a href="mailto:yiding@fb.com">yiding@fb.com</a>>\r
</p>\r
</li>\r
+<li>\r
+<p>\r
+Yvan Janssens <<a href="mailto:friedkiwi@yvanj.me">friedkiwi@yvanj.me</a>>\r
+</p>\r
+</li>\r
</ul></div>\r
<div class="paragraph"><p>Thanks!</p></div>\r
</div>\r
<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
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)::
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
*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.
--
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
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)
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
---------------
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
<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>
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
<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’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’t used in practise, or\r
+ don’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
</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
</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
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
</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
<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’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
</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’t used in practise, or don’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’t used in practise, or don’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
<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
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
- 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.
- 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.
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.
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.
<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>
</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 “depend mode”. 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’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’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’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
<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
</li>\r
<li>\r
<p>\r
-If the compiler type can’t be detected (e.g. if it is named <strong>cc</strong>), use safer\r
+If the compiler type can’t be detected (e.g. if it is named <code>cc</code>), use safer\r
defaults that won’t trip up Clang.\r
</p>\r
</li>\r
<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
</li>\r
<li>\r
<p>\r
-Don’t try to reset a non-existing stats file. This avoids “No such file or\r
+Don’t try to reset a nonexistent stats file. This avoids “No such file or\r
directory” messages in the ccache log when the cache directory doesn’t\r
exist.\r
</p>\r
</li>\r
<li>\r
<p>\r
-Don’t try to reset a non-existing stats file. This avoids “No such file or\r
+Don’t try to reset a nonexistent stats file. This avoids “No such file or\r
directory” messages in the ccache log when the cache directory doesn’t\r
exist.\r
</p>\r
<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
.\" 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
.\" -----------------------------------------------------------------
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
.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
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
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
.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 \{\
.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 \{\
.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\&.
.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
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).
// 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;
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;
}
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;
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 *
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);
}
}
}
+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:
//
free(p);
}
- if (!included_files) {
- included_files = create_hashtable(1000, hash_from_string, strings_equal);
- }
+ init_included_files_table();
char *cwd = gnu_getcwd();
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') {
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;
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)
}
}
-// 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);
//
// 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);
}
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) {
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);
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) {
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) {
}
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);
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
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();
}
// 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)) {
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
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.
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;
}
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;
}
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.
}
} // 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.
}
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);
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);
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;
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);
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();
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);
}
// 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
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) \
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);
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);
}
-// 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
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("");
// 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)
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);
unsigned compression_level;
char *cpp_extension;
bool debug;
+ bool depend_mode;
bool direct_mode;
bool disable;
char *extra_files_to_hash;
-// 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
*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);
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 ", ".
%}
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)
/* 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"
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
{
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]];
}
{
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)
}
return 0;
}
-size_t confitems_count(void) { return 33; }
+size_t confitems_count(void) { return 34; }
COMPRESSLEVEL, "compression_level"
CPP2, "run_second_cpp"
COMMENTS, "keep_comments_cpp"
+DEPEND, "depend_mode"
DIR, "cache_dir"
DEBUG, "debug"
DIRECT, "direct_mode"
/* 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, 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,
{
enum
{
- TOTAL_KEYWORDS = 34,
+ TOTAL_KEYWORDS = 35,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 15,
MIN_HASH_VALUE = 2,
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"}
};
}
return 0;
}
-size_t envtoconfitems_count(void) { return 34; }
+size_t envtoconfitems_count(void) { return 35; }
#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"
-// 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
// 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;
}
}
#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
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)
{
-extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.5.1";
+extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.6";
masquerading
hardlink
direct
+direct_gcc
+depend
basedir
compression
readonly
$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"
--- /dev/null
+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)
+}
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.
--- /dev/null
+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
+}
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
}
}
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
}
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
}
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);
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");
CHECK(!compopt_affects_cpp("-V"));
}
-TEST(dash_doesnexist_doesnt_affect_cpp)
+TEST(dash_doesntexist_doesnt_affect_cpp)
{
CHECK(!compopt_affects_cpp("-doesntexist"));
}
CHECK(!compopt_too_hard("-fstack-usage"));
}
-TEST(dash_doesnexist_not_too_hard)
+TEST(dash_doesntexist_not_too_hard)
{
CHECK(!compopt_too_hard("-doesntexist"));
}
-// 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
#include "framework.h"
#include "util.h"
-#define N_CONFIG_ITEMS 33
+#define N_CONFIG_ITEMS 34
static struct {
char *descr;
char *origin;
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);
"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"
"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"
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);
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);
8,
"ce",
false,
+ true,
false,
true,
"efth",
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,
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);
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);
-// 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
"#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"