Also, consider reading [Effective Ways to Get Help from Maintainers](
https://www.snoyman.com/blog/2017/10/effective-ways-help-from-maintainers).
-
## Contributing code?
-Great! You can create a pull request with your proposal on github, or you could
-post one or several patches to the
-[mailing list](https://lists.samba.org/mailman/listinfo/ccache/).
+The preferred way is to create one or several pull request with your
+proposal(s) on [GitHub](https://github.com/ccache/ccache).
+
+If you plan to implement major changes it is wise to open an issue on GitHub
+(or send a mail to the mailing list) asking for comments on your plans before
+doing the bulk of the work. That way you can avoid potentially wasting time on
+doing something that might not end up being accepted.
### How to write commit messages
-------------
To build ccache from a
-[release archive](https://ccache.samba.org/download.html), you need:
+[release archive](https://ccache.dev/download.html), you need:
- A C compiler (for instance GCC)
---------------------
ccache is a collective work with contributions from many people, listed in
-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.
+AUTHORS.adoc and at https://ccache.dev/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.
The copyright for ccache as a whole is as follows:
modified) versions of this file, nor is leaving this notice intact mandatory.
-------------------------------------------------------------------------------
+src/minitrace.[hc]
+~~~~~~~~~~~~~~~~~~
+
+A library for producing JSON traces suitable for Chrome's built-in trace viewer
+(chrome://tracing). Downloaded from <https://github.com/hrydgard/minitrace>.
+
+-------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014 Henrik Rydgård
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+-------------------------------------------------------------------------------
src/zlib/*.[hc]
~~~~~~~~~~~~~~~
<body class="article">\r
<div id="header">\r
<h1>ccache copyright and license</h1>\r
-<span id="revnumber">version 3.6</span>\r
+<span id="revnumber">version 3.7</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/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
+AUTHORS.adoc and at <a href="https://ccache.dev/credits.html">https://ccache.dev/credits.html</a>. Subsequent additions by\r
+contributing authors are implicitly licensed to the public under the same terms\r
+(GNU GPL version 3 or later), but the contributing authors retain copyrights on\r
+their portions of the work.</p></div>\r
<div class="paragraph"><p>The copyright for ccache as a whole is as follows:</p></div>\r
<div class="listingblock">\r
<div class="content">\r
</div></div>\r
</div>\r
<div class="sect2">\r
+<h3 id="_src_minitrace_hc">src/minitrace.[hc]</h3>\r
+<div class="paragraph"><p>A library for producing JSON traces suitable for Chrome’s built-in trace viewer\r
+(chrome://tracing). Downloaded from <a href="https://github.com/hrydgard/minitrace">https://github.com/hrydgard/minitrace</a>.</p></div>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code>The MIT License (MIT)\r
+\r
+Copyright (c) 2014 Henrik Rydgård\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy\r
+of this software and associated documentation files (the "Software"), to deal\r
+in the Software without restriction, including without limitation the rights\r
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+copies of the Software, and to permit persons to whom the Software is\r
+furnished to do so, subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+SOFTWARE.</code></pre>\r
+</div></div>\r
+</div>\r
+<div class="sect2">\r
<h3 id="_src_zlib_hc">src/zlib/*.[hc]</h3>\r
<div class="paragraph"><p>This is a bundled subset of zlib 1.2.11 from <a href="http://zlib.net">http://zlib.net</a> with the\r
following license:</p></div>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.6<br />\r
+Version 3.7<br />\r
Last updated\r
- 2019-01-13 21:38:14 CET\r
+ 2019-04-23 21:35:11 CEST\r
</div>\r
</div>\r
</body>\r
src/hashtable_itr.c \
src/murmurhashneutral2.c \
src/snprintf.c
-base_sources = $(non_3pp_sources) $(generated_sources) $(3pp_sources)
+extra_sources = @extra_sources@
+base_sources = $(non_3pp_sources) $(generated_sources) $(3pp_sources) $(extra_sources)
base_objs = $(base_sources:.c=.o)
+non_3pp_objs = $(non_3pp_sources:.c=.o)
+
ccache_sources = src/main.c $(base_sources)
ccache_objs = $(ccache_sources:.c=.o)
$(if $(quiet),@echo " RANLIB $@")
$(Q)$(RANLIB) $@
-.PHONY: perf
-perf: ccache$(EXEEXT)
- $(srcdir)/perf/perf.py --ccache ccache$(EXEEXT) $(CC) $(all_cppflags) $(all_cflags) $(srcdir)/src/ccache.c
+.PHONY: performance
+performance: ccache$(EXEEXT)
+ $(srcdir)/misc/performance --ccache ccache$(EXEEXT) $(CC) $(all_cppflags) $(all_cflags) $(srcdir)/src/ccache.c
.PHONY: test
test: ccache$(EXEEXT) unittest/run$(EXEEXT)
General information
-------------------
-* [Main web site](https://ccache.samba.org)
-* [Documentation](https://ccache.samba.org/documentation.html)
- * [Latest manual](https://ccache.samba.org/manual/latest.html)
+* [Main web site](https://ccache.dev)
+* [Documentation](https://ccache.dev/documentation.html)
+ * [Latest manual](https://ccache.dev/manual/latest.html)
* [Installation from Git source repository](https://github.com/ccache/ccache/blob/master/doc/INSTALL.md)
* [Installation from release archive](https://github.com/ccache/ccache/blob/master/doc/INSTALL-from-release-archive.md)
-* [Release notes](https://ccache.samba.org/releasenotes.html)
-* [Credits and history](https://ccache.samba.org/credits.html)
-* [License and copyright](https://ccache.samba.org/license.html)
+* [Release notes](https://ccache.dev/releasenotes.html)
+* [Credits and history](https://ccache.dev/credits.html)
+* [License and copyright](https://ccache.dev/license.html)
Contributing to ccache
* [Source repository](https://github.com/ccache/ccache)
* [Notes on how to contribute](https://github.com/ccache/ccache/blob/master/CONTRIBUTING.md)
* [Mailing list](https://lists.samba.org/mailman/listinfo/ccache/)
-* [Bug report info](https://ccache.samba.org/bugs.html)
+* [Bug report info](https://ccache.dev/bugs.html)
* [Issue tracker](https://github.com/ccache/ccache/issues)
* [Help wanted!](https://github.com/ccache/ccache/issues/help%20wanted)
* [Good first issues!](https://github.com/ccache/ccache/issues/good%20first%20issue)
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
/* Define to 1 if the system has the type `long long'. */
#undef HAVE_LONG_LONG
ac_header_list=
ac_subst_vars='LTLIBOBJS
+GPERF
LIBOBJS
EGREP
GREP
no_implicit_fallthrough_warning
more_warnings
include_dev_mk
+extra_sources
extra_libs
disable_man
host_os
enable_more_warnings
with_bundled_zlib
enable_man
+enable_tracing
'
ac_precious_vars='build_alias
host_alias
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-more-warnings enable more compiler warnings
--disable-man disable installing man pages
+ --enable-tracing enable possibility to use internal ccache tracing
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+
# 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 localtime_r
+do :
+ ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r"
+if test "x$ac_cv_func_localtime_r" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LOCALTIME_R 1
+_ACEOF
+
+fi
+done
+
for ac_func in mkstemp
do :
ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
disable_man='#'
fi
+# Check whether --enable-tracing was given.
+if test "${enable_tracing+set}" = set; then :
+ enableval=$enable_tracing;
+fi
+
+if test x${enable_tracing} = xyes; then
+ CPPFLAGS="$CPPFLAGS -DMTR_ENABLED"
+ extra_sources="src/minitrace.c"
+fi
+
if test x${windows_os} = xyes; then
LIBS="$LIBS -lws2_32"
for ac_func in GetFinalPathNameByHandleW
include_dev_mk='include dev.mk'
version=`(git --git-dir=$srcdir/.git describe --dirty 2>/dev/null || echo vunknown) | sed -e 's/v//' -e 's/-/+/' -e 's/-/_/g'`
echo "extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = \"$version\";" >src/version.c
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gperf", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gperf; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_GPERF+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$GPERF"; then
+ ac_cv_prog_GPERF="$GPERF" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_GPERF="${ac_tool_prefix}gperf"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+GPERF=$ac_cv_prog_GPERF
+if test -n "$GPERF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GPERF" >&5
+$as_echo "$GPERF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_GPERF"; then
+ ac_ct_GPERF=$GPERF
+ # Extract the first word of "gperf", so it can be a program name with args.
+set dummy gperf; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_GPERF+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_GPERF"; then
+ ac_cv_prog_ac_ct_GPERF="$ac_ct_GPERF" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_GPERF="gperf"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_GPERF=$ac_cv_prog_ac_ct_GPERF
+if test -n "$ac_ct_GPERF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_GPERF" >&5
+$as_echo "$ac_ct_GPERF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_GPERF" = x; then
+ GPERF=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ GPERF=$ac_ct_GPERF
+ fi
+else
+ GPERF="$ac_cv_prog_GPERF"
+fi
+
+ if test -z "$GPERF"; then
+ as_fn_error $? "please install gperf" "$LINENO" 5
+ fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: developer mode disabled" >&5
$as_echo "$as_me: developer mode disabled" >&6;}
AC_SUBST(disable_man)
AC_SUBST(extra_libs)
+AC_SUBST(extra_sources)
AC_SUBST(include_dev_mk)
AC_SUBST(more_warnings)
AC_SUBST(no_implicit_fallthrough_warning)
AC_CHECK_FUNCS(getopt_long)
AC_CHECK_FUNCS(getpwuid)
AC_CHECK_FUNCS(gettimeofday)
+AC_CHECK_FUNCS(localtime_r)
AC_CHECK_FUNCS(mkstemp)
AC_CHECK_FUNCS(realpath)
AC_CHECK_FUNCS(setenv)
disable_man='#'
fi
+AC_ARG_ENABLE(tracing,
+ [AS_HELP_STRING([--enable-tracing],
+ [enable possibility to use internal ccache tracing])])
+if test x${enable_tracing} = xyes; then
+ CPPFLAGS="$CPPFLAGS -DMTR_ENABLED"
+ extra_sources="src/minitrace.c"
+fi
+
dnl Linking on Windows needs ws2_32
if test x${windows_os} = xyes; then
LIBS="$LIBS -lws2_32"
include_dev_mk='include dev.mk'
version=`(git --git-dir=$srcdir/.git describe --dirty 2>/dev/null || echo vunknown) | sed -e 's/v//' -e 's/-/+/' -e 's/-/_/g'`
echo "extern const char CCACHE_VERSION@<:@@:>@; const char CCACHE_VERSION@<:@@:>@ = \"$version\";" >src/version.c
+ AC_CHECK_TOOL(GPERF, gperf)
+ if test -z "$GPERF"; then
+ AC_MSG_ERROR(please install gperf)
+ fi
else
AC_MSG_NOTICE(developer mode disabled)
fi
# GNU make syntax reigns in this file.
-all_cflags += -Werror @more_warnings@
-all_cppflags += -MD -MP -MF .deps/$(subst .._,,$(subst /,_,$<)).d
+all_cflags += -Werror
+all_cppflags += -MD -MP -MF .deps/$(subst .._,,$(subst /,_,$(subst $(srcdir)/,,$<))).d
A2X = a2x
ASCIIDOC = asciidoc
CLANG_TIDY = clang-tidy
SCAN_BUILD = scan-build
DOCKER = docker
-GPERF = gperf
+GPERF = @GPERF@
TEST = test
version := \
src/macroskip.h \
src/manifest.h \
src/mdfour.h \
+ src/minitrace.h \
src/murmurhashneutral2.h \
src/system.h \
src/unify.h \
src/envtoconfitems.gperf \
src/envtoconfitems_lookup.c \
src/main.c \
+ src/minitrace.c \
src/zlib/*.c \
src/zlib/*.h \
test/run \
- test/suites/*
+ test/suites/*.bash
dist_files = \
$(addprefix $(srcdir)/, $(source_dist_files)) \
$(built_dist_files)
-uncrustify_exclude_files = \
- src/getopt_long.c \
- src/hashtable.c \
- src/hashtable_itr.c \
- src/snprintf.c
-
ifneq ($(shell sed 's/.*"\(.*\)".*/\1/' src/version.c 2>/dev/null),$(version))
$(shell echo 'extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "$(version)";' >src/version.c)
endif
$(Q)$(ASCIIDOC) -a revnumber=$(version) -d manpage -b docbook -o - $< | \
perl -pe 's!<literal>(.*?)</literal>!<emphasis role="strong">\1</emphasis>!g' >$@
+$(non_3pp_objs) $(test_objs): CFLAGS += @more_warnings@
+
doc/ccache.1: doc/MANUAL.xml
$(if $(quiet),@echo " A2X $@")
$(Q)$(A2X) --doctype manpage --format manpage $<
.PHONY: update-authors
update-authors:
- git log --pretty=format:"* %aN <%aE>" \
+ git log --pretty=format:"* %aN" \
| sort -u \
| perl -00 -p -i -e 's/^\*.*/<STDIN> . "\n"/es' doc/AUTHORS.adoc
.PHONY: uncrustify
uncrustify:
- uncrustify -c misc/uncrustify.cfg --no-backup --replace $(filter-out $(uncrustify_exclude_files), $(base_sources)) $(test_sources)
+ uncrustify -c misc/uncrustify.cfg --no-backup --replace $(non_3pp_sources) $(test_sources)
# pip install compiledb
compile_commands.json:
travis: .travis/Dockerfile
$(DOCKER) inspect travis-build >/dev/null || $(DOCKER) build -t travis-build .travis
$(DOCKER) run --rm --volume $(PWD):/src --tmpfs /dst:rw,exec --env ASAN_OPTIONS='$(ASAN_OPTIONS)' travis-build \
- sh -c "cd /src && ./autogen.sh && cd /dst && CC=$(CC) CFLAGS='$(CFLAGS)' /src/configure $(HOST) && make && make $(TEST)"
+ sh -c "cd /src && ./autogen.sh && cd /dst && CC=$(CC) CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS)' /src/configure $(HOST) && make V=$(V) && make V=$(V) $(TEST)"
-include .deps/*.d
ccache is a collective work with contributions from many people, including:
-* Alexey Tourbin <alexey.tourbin@gmail.com>
-* Alfred Landrum <alfred.landrum@riverbed.com>
-* Anders F Björklund <anders.f.bjorklund@gmail.com>
-* Andrea Bittau <a.bittau@cs.ucl.ac.uk>
-* Andreas Huber <andreas.huber@deltaww.com>
-* André Klitzing <aklitzing@gmail.com>
-* Andrew P Boie <andrew.p.boie@intel.com>
-* Andrew Stubbs <ams@codesourcery.com>
-* Andrew Tridgell <tridge@samba.org>
-* Bernhard Bauer <bauerb@chromium.org>
-* Björn Jacke <bj@sernet.de>
-* Chiaki Ishikawa <ishikawa@yk.rim.or.jp>
-* Chris AtLee <catlee@mozilla.com>
-* Clemens Rabe <clemens.rabe@gmail.com>
-* David Givone <david@givone.net>
-* Edward Z. Yang <ezyang@fb.com>
-* Francois Marier <francois@debian.org>
-* Gabriel Scherer <gabriel.scherer@gmail.com>
-* Geert Bosch <geert@mongodb.com>
-* Geert Kloosterman <geert.kloosterman@brightcomputing.com>
-* Grigory Entin <grigorye@dins.ru>
-* Havard Graff <havard.graff@gmail.com>
-* 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>
-* Kovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>
-* Lalit Chhabra <lchhabra@linuxmail.org>
-* 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>
-* Mathias De Maré <mathias.de_mare@nokia.com>
-* Matthias Kretz <kretz@kde.org>
-* 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>
-* Mikhail Kolomeytsev <mkolom@yandex-team.ru>
-* Mostyn Bramley-Moore <mostyn@antipode.se>
-* Neil Mushell <nmushell@bloomberg.net>
-* Nick Schultz <nick.schultz@intel.com>
-* Norbert Lange <nolange79@gmail.com>
-* Oded Shimon <oded@istraresearch.com>
-* Orgad Shaneh <orgad.shaneh@audiocodes.com>
-* Orion Poplawski <orion@cora.nwra.com>
-* Owen Mann <owen@mann.org>
-* Patrick von Reth <vonreth@kde.org>
-* Paul Griffith <paulg@cse.yorku.ca>
-* Pavel Boldin <pboldin@cloudlinux.com>
-* Per Nordlöw <per.nordlow@autoliv.com>
-* Peter Budai <peterbudai@hotmail.com>
-* Philippe Proulx <eeppeliteloop@gmail.com>
-* Rafael Kitover <rkitover@gmail.com>
-* Ramiro Polla <ramiro.polla@gmail.com>
-* Robin H. Johnson <robbat2@gentoo.org>
-* Rolf Bjarne Kvinge <rolf@xamarin.com>
-* RW <fbsd06@mlists.homeunix.com>
-* Ryan Brown <ryb@ableton.com>
-* Sam Gross <sgross@fb.com>
-* Thomas Otto <thomas.otto@psd-fs.de>
-* Thomas Röfer <Thomas.Roefer@dfki.de>
-* Timofei Kushnir <timophey@rdp.ru>
-* Tim Potter <tpot@samba.org>
-* Tomasz Miąsko <tomasz.miasko@gmail.com>
-* Tom Hughes <tomtheengineer@gmail.com>
-* Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-* Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
-* Ville Skyttä <ville.skytta@iki.fi>
-* William S Fulton <wsf@fultondesigns.co.uk>
-* Wilson Snyder <wsnyder@wsnyder.org>
-* Xavier René-Corail <xavier.renecorail@gmail.com>
-* Yiding Jia <yiding@fb.com>
-* Yvan Janssens <friedkiwi@yvanj.me>
+* Alexey Tourbin
+* Alfred Landrum
+* Anders F Björklund
+* Andrea Bittau
+* Andreas Huber
+* André Klitzing
+* Andrew P Boie
+* Andrew Stubbs
+* Andrew Tridgell
+* Bernhard Bauer
+* Björn Jacke
+* Chiaki Ishikawa
+* Chris AtLee
+* Clemens Rabe
+* David Givone
+* Doug Anderson
+* Edward Z. Yang
+* Francois Marier
+* Gabriel Scherer
+* Geert Bosch
+* Geert Kloosterman
+* Grigory Entin
+* Havard Graff
+* Hongli Lai
+* Ivan Vaigult
+* Jiang Jiang
+* Joel Galenson
+* Joel Rosdahl
+* John Basila
+* John Coiner
+* Jon Bernard
+* Jonny Yu
+* Jørgen P. Tjernø
+* Josh Soref
+* Justin Lebar
+* Karl Chen
+* Kona Blend
+* Kovarththanan Rajaratnam
+* Lalit Chhabra
+* Lars Gustäbel
+* Leanid Chaika
+* Luboš Luňák
+* Maarten Maathuis
+* Mark Starovoytov
+* Martin Ettl
+* Martin Pool
+* Mathias De Maré
+* Matthias Kretz
+* Melven Roehrig-Zoellner
+* Michael Marineau
+* Michael Meeks
+* Michał Mirosław
+* Mihai Serban
+* Mike Frysinger
+* Mike Gulick
+* Mikhail Kolomeytsev
+* Mostyn Bramley-Moore
+* Neil Mushell
+* Nick Schultz
+* Norbert Lange
+* Oded Shimon
+* Orgad Shaneh
+* Orion Poplawski
+* Owen Mann
+* Patrick von Reth
+* Paul Griffith
+* Pavel Boldin
+* Pavol Sakac
+* Per Nordlöw
+* Peter Budai
+* Philippe Proulx
+* Rafael Kitover
+* Ramiro Polla
+* Robert Yang
+* Robin H. Johnson
+* Rolf Bjarne Kvinge
+* RW
+* Ryan Brown
+* Sam Gross
+* Thomas Otto
+* Thomas Röfer
+* Timofei Kushnir
+* Tim Potter
+* Tomasz Miąsko
+* Tom Hughes
+* Tor Arne Vestbø
+* Vadim Petrochenkov
+* Ville Skyttä
+* William S Fulton
+* Wilson Snyder
+* Xavier René-Corail
+* Yiding Jia
+* Yvan Janssens
Thanks!
<body class="article">\r
<div id="header">\r
<h1>ccache authors</h1>\r
-<span id="revnumber">version 3.6</span>\r
+<span id="revnumber">version 3.7</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 class="ulist"><ul>\r
<li>\r
<p>\r
-Alexey Tourbin <<a href="mailto:alexey.tourbin@gmail.com">alexey.tourbin@gmail.com</a>>\r
+Alexey Tourbin\r
</p>\r
</li>\r
<li>\r
<p>\r
-Alfred Landrum <<a href="mailto:alfred.landrum@riverbed.com">alfred.landrum@riverbed.com</a>>\r
+Alfred Landrum\r
</p>\r
</li>\r
<li>\r
<p>\r
-Anders F Björklund <<a href="mailto:anders.f.bjorklund@gmail.com">anders.f.bjorklund@gmail.com</a>>\r
+Anders F Björklund\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andrea Bittau <<a href="mailto:a.bittau@cs.ucl.ac.uk">a.bittau@cs.ucl.ac.uk</a>>\r
+Andrea Bittau\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andreas Huber <<a href="mailto:andreas.huber@deltaww.com">andreas.huber@deltaww.com</a>>\r
+Andreas Huber\r
</p>\r
</li>\r
<li>\r
<p>\r
-André Klitzing <<a href="mailto:aklitzing@gmail.com">aklitzing@gmail.com</a>>\r
+André Klitzing\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andrew P Boie <<a href="mailto:andrew.p.boie@intel.com">andrew.p.boie@intel.com</a>>\r
+Andrew P Boie\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andrew Stubbs <<a href="mailto:ams@codesourcery.com">ams@codesourcery.com</a>>\r
+Andrew Stubbs\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andrew Tridgell <<a href="mailto:tridge@samba.org">tridge@samba.org</a>>\r
+Andrew Tridgell\r
</p>\r
</li>\r
<li>\r
<p>\r
-Bernhard Bauer <<a href="mailto:bauerb@chromium.org">bauerb@chromium.org</a>>\r
+Bernhard Bauer\r
</p>\r
</li>\r
<li>\r
<p>\r
-Björn Jacke <<a href="mailto:bj@sernet.de">bj@sernet.de</a>>\r
+Björn Jacke\r
</p>\r
</li>\r
<li>\r
<p>\r
-Chiaki Ishikawa <<a href="mailto:ishikawa@yk.rim.or.jp">ishikawa@yk.rim.or.jp</a>>\r
+Chiaki Ishikawa\r
</p>\r
</li>\r
<li>\r
<p>\r
-Chris AtLee <<a href="mailto:catlee@mozilla.com">catlee@mozilla.com</a>>\r
+Chris AtLee\r
</p>\r
</li>\r
<li>\r
<p>\r
-Clemens Rabe <<a href="mailto:clemens.rabe@gmail.com">clemens.rabe@gmail.com</a>>\r
+Clemens Rabe\r
</p>\r
</li>\r
<li>\r
<p>\r
-David Givone <<a href="mailto:david@givone.net">david@givone.net</a>>\r
+David Givone\r
</p>\r
</li>\r
<li>\r
<p>\r
-Edward Z. Yang <<a href="mailto:ezyang@fb.com">ezyang@fb.com</a>>\r
+Doug Anderson\r
</p>\r
</li>\r
<li>\r
<p>\r
-Francois Marier <<a href="mailto:francois@debian.org">francois@debian.org</a>>\r
+Edward Z. Yang\r
</p>\r
</li>\r
<li>\r
<p>\r
-Gabriel Scherer <<a href="mailto:gabriel.scherer@gmail.com">gabriel.scherer@gmail.com</a>>\r
+Francois Marier\r
</p>\r
</li>\r
<li>\r
<p>\r
-Geert Bosch <<a href="mailto:geert@mongodb.com">geert@mongodb.com</a>>\r
+Gabriel Scherer\r
</p>\r
</li>\r
<li>\r
<p>\r
-Geert Kloosterman <<a href="mailto:geert.kloosterman@brightcomputing.com">geert.kloosterman@brightcomputing.com</a>>\r
+Geert Bosch\r
</p>\r
</li>\r
<li>\r
<p>\r
-Grigory Entin <<a href="mailto:grigorye@dins.ru">grigorye@dins.ru</a>>\r
+Geert Kloosterman\r
</p>\r
</li>\r
<li>\r
<p>\r
-Havard Graff <<a href="mailto:havard.graff@gmail.com">havard.graff@gmail.com</a>>\r
+Grigory Entin\r
</p>\r
</li>\r
<li>\r
<p>\r
-Hongli Lai <<a href="mailto:hongli@phusion.nl">hongli@phusion.nl</a>>\r
+Havard Graff\r
</p>\r
</li>\r
<li>\r
<p>\r
-Ivan Vaigult <<a href="mailto:i.vaigult@gmail.com">i.vaigult@gmail.com</a>>\r
+Hongli Lai\r
</p>\r
</li>\r
<li>\r
<p>\r
-Jiang Jiang <<a href="mailto:jiangj@opera.com">jiangj@opera.com</a>>\r
+Ivan Vaigult\r
</p>\r
</li>\r
<li>\r
<p>\r
-Joel Galenson <<a href="mailto:jgalenson@gmail.com">jgalenson@gmail.com</a>>\r
+Jiang Jiang\r
</p>\r
</li>\r
<li>\r
<p>\r
-Joel Rosdahl <<a href="mailto:joel@rosdahl.net">joel@rosdahl.net</a>>\r
+Joel Galenson\r
</p>\r
</li>\r
<li>\r
<p>\r
-John Basila <<a href="mailto:jbasila@checkpoint.com">jbasila@checkpoint.com</a>>\r
+Joel Rosdahl\r
</p>\r
</li>\r
<li>\r
<p>\r
-John Coiner <<a href="mailto:john.coiner@amd.com">john.coiner@amd.com</a>>\r
+John Basila\r
</p>\r
</li>\r
<li>\r
<p>\r
-Jon Bernard <<a href="mailto:jbernard@tuxion.com">jbernard@tuxion.com</a>>\r
+John Coiner\r
</p>\r
</li>\r
<li>\r
<p>\r
-Jonny Yu <<a href="mailto:yingshen.yu@gmail.com">yingshen.yu@gmail.com</a>>\r
+Jon Bernard\r
</p>\r
</li>\r
<li>\r
<p>\r
-Jørgen P. Tjernø <<a href="mailto:jorgen@valvesoftware.com">jorgen@valvesoftware.com</a>>\r
+Jonny Yu\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
+Jørgen P. Tjernø\r
</p>\r
</li>\r
<li>\r
<p>\r
-Justin Lebar <<a href="mailto:justin.lebar@gmail.com">justin.lebar@gmail.com</a>>\r
+Josh Soref\r
</p>\r
</li>\r
<li>\r
<p>\r
-Karl Chen <<a href="mailto:quarl@cs.berkeley.edu">quarl@cs.berkeley.edu</a>>\r
+Justin Lebar\r
</p>\r
</li>\r
<li>\r
<p>\r
-Kona Blend <<a href="mailto:kona8lend@gmail.com">kona8lend@gmail.com</a>>\r
+Karl Chen\r
</p>\r
</li>\r
<li>\r
<p>\r
-Kovarththanan Rajaratnam <<a href="mailto:kovarththanan.rajaratnam@gmail.com">kovarththanan.rajaratnam@gmail.com</a>>\r
+Kona Blend\r
</p>\r
</li>\r
<li>\r
<p>\r
-Lalit Chhabra <<a href="mailto:lchhabra@linuxmail.org">lchhabra@linuxmail.org</a>>\r
+Kovarththanan Rajaratnam\r
</p>\r
</li>\r
<li>\r
<p>\r
-Lars Gustäbel <<a href="mailto:lars@gustaebel.de">lars@gustaebel.de</a>>\r
+Lalit Chhabra\r
</p>\r
</li>\r
<li>\r
<p>\r
-Leanid Chaika <<a href="mailto:leanid.chaika@gmail.com">leanid.chaika@gmail.com</a>>\r
+Lars Gustäbel\r
</p>\r
</li>\r
<li>\r
<p>\r
-Luboš Luňák <<a href="mailto:l.lunak@centrum.cz">l.lunak@centrum.cz</a>>\r
+Leanid Chaika\r
</p>\r
</li>\r
<li>\r
<p>\r
-Maarten Maathuis <<a href="mailto:madman2003@shikahr.net">madman2003@shikahr.net</a>>\r
+Luboš Luňák\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mark Starovoytov <<a href="mailto:starovoytov.mark@googlemail.com">starovoytov.mark@googlemail.com</a>>\r
+Maarten Maathuis\r
</p>\r
</li>\r
<li>\r
<p>\r
-Martin Ettl <<a href="mailto:ettl.martin78@gmail.com">ettl.martin78@gmail.com</a>>\r
+Mark Starovoytov\r
</p>\r
</li>\r
<li>\r
<p>\r
-Martin Pool <<a href="mailto:mbp@sourcefrog.net">mbp@sourcefrog.net</a>>\r
+Martin Ettl\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mathias De Maré <<a href="mailto:mathias.de_mare@nokia.com">mathias.de_mare@nokia.com</a>>\r
+Martin Pool\r
</p>\r
</li>\r
<li>\r
<p>\r
-Matthias Kretz <<a href="mailto:kretz@kde.org">kretz@kde.org</a>>\r
+Mathias De Maré\r
</p>\r
</li>\r
<li>\r
<p>\r
-Melven Roehrig-Zoellner <<a href="mailto:Melven.Roehrig-Zoellner@DLR.de">Melven.Roehrig-Zoellner@DLR.de</a>>\r
+Matthias Kretz\r
</p>\r
</li>\r
<li>\r
<p>\r
-Michael Marineau <<a href="mailto:michael.marineau@coreos.com">michael.marineau@coreos.com</a>>\r
+Melven Roehrig-Zoellner\r
</p>\r
</li>\r
<li>\r
<p>\r
-Michael Meeks <<a href="mailto:michael.meeks@suse.com">michael.meeks@suse.com</a>>\r
+Michael Marineau\r
</p>\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
+Michael Meeks\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mihai Serban <<a href="mailto:mihai.serban@intel.com">mihai.serban@intel.com</a>>\r
+Michał Mirosław\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mike Frysinger <<a href="mailto:vapier@gentoo.org">vapier@gentoo.org</a>>\r
+Mihai Serban\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mike Gulick <<a href="mailto:mgulick@mathworks.com">mgulick@mathworks.com</a>>\r
+Mike Frysinger\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mikhail Kolomeytsev <<a href="mailto:mkolom@yandex-team.ru">mkolom@yandex-team.ru</a>>\r
+Mike Gulick\r
</p>\r
</li>\r
<li>\r
<p>\r
-Mostyn Bramley-Moore <<a href="mailto:mostyn@antipode.se">mostyn@antipode.se</a>>\r
+Mikhail Kolomeytsev\r
</p>\r
</li>\r
<li>\r
<p>\r
-Neil Mushell <<a href="mailto:nmushell@bloomberg.net">nmushell@bloomberg.net</a>>\r
+Mostyn Bramley-Moore\r
</p>\r
</li>\r
<li>\r
<p>\r
-Nick Schultz <<a href="mailto:nick.schultz@intel.com">nick.schultz@intel.com</a>>\r
+Neil Mushell\r
</p>\r
</li>\r
<li>\r
<p>\r
-Norbert Lange <<a href="mailto:nolange79@gmail.com">nolange79@gmail.com</a>>\r
+Nick Schultz\r
</p>\r
</li>\r
<li>\r
<p>\r
-Oded Shimon <<a href="mailto:oded@istraresearch.com">oded@istraresearch.com</a>>\r
+Norbert Lange\r
</p>\r
</li>\r
<li>\r
<p>\r
-Orgad Shaneh <<a href="mailto:orgad.shaneh@audiocodes.com">orgad.shaneh@audiocodes.com</a>>\r
+Oded Shimon\r
</p>\r
</li>\r
<li>\r
<p>\r
-Orion Poplawski <<a href="mailto:orion@cora.nwra.com">orion@cora.nwra.com</a>>\r
+Orgad Shaneh\r
</p>\r
</li>\r
<li>\r
<p>\r
-Owen Mann <<a href="mailto:owen@mann.org">owen@mann.org</a>>\r
+Orion Poplawski\r
</p>\r
</li>\r
<li>\r
<p>\r
-Patrick von Reth <<a href="mailto:vonreth@kde.org">vonreth@kde.org</a>>\r
+Owen Mann\r
</p>\r
</li>\r
<li>\r
<p>\r
-Paul Griffith <<a href="mailto:paulg@cse.yorku.ca">paulg@cse.yorku.ca</a>>\r
+Patrick von Reth\r
</p>\r
</li>\r
<li>\r
<p>\r
-Pavel Boldin <<a href="mailto:pboldin@cloudlinux.com">pboldin@cloudlinux.com</a>>\r
+Paul Griffith\r
</p>\r
</li>\r
<li>\r
<p>\r
-Per Nordlöw <<a href="mailto:per.nordlow@autoliv.com">per.nordlow@autoliv.com</a>>\r
+Pavel Boldin\r
</p>\r
</li>\r
<li>\r
<p>\r
-Peter Budai <<a href="mailto:peterbudai@hotmail.com">peterbudai@hotmail.com</a>>\r
+Pavol Sakac\r
</p>\r
</li>\r
<li>\r
<p>\r
-Philippe Proulx <<a href="mailto:eeppeliteloop@gmail.com">eeppeliteloop@gmail.com</a>>\r
+Per Nordlöw\r
</p>\r
</li>\r
<li>\r
<p>\r
-Rafael Kitover <<a href="mailto:rkitover@gmail.com">rkitover@gmail.com</a>>\r
+Peter Budai\r
</p>\r
</li>\r
<li>\r
<p>\r
-Ramiro Polla <<a href="mailto:ramiro.polla@gmail.com">ramiro.polla@gmail.com</a>>\r
+Philippe Proulx\r
</p>\r
</li>\r
<li>\r
<p>\r
-Robin H. Johnson <<a href="mailto:robbat2@gentoo.org">robbat2@gentoo.org</a>>\r
+Rafael Kitover\r
</p>\r
</li>\r
<li>\r
<p>\r
-Rolf Bjarne Kvinge <<a href="mailto:rolf@xamarin.com">rolf@xamarin.com</a>>\r
+Ramiro Polla\r
</p>\r
</li>\r
<li>\r
<p>\r
-RW <<a href="mailto:fbsd06@mlists.homeunix.com">fbsd06@mlists.homeunix.com</a>>\r
+Robert Yang\r
</p>\r
</li>\r
<li>\r
<p>\r
-Ryan Brown <<a href="mailto:ryb@ableton.com">ryb@ableton.com</a>>\r
+Robin H. Johnson\r
</p>\r
</li>\r
<li>\r
<p>\r
-Sam Gross <<a href="mailto:sgross@fb.com">sgross@fb.com</a>>\r
+Rolf Bjarne Kvinge\r
</p>\r
</li>\r
<li>\r
<p>\r
-Thomas Otto <<a href="mailto:thomas.otto@psd-fs.de">thomas.otto@psd-fs.de</a>>\r
+RW\r
</p>\r
</li>\r
<li>\r
<p>\r
-Thomas Röfer <<a href="mailto:Thomas.Roefer@dfki.de">Thomas.Roefer@dfki.de</a>>\r
+Ryan Brown\r
</p>\r
</li>\r
<li>\r
<p>\r
-Timofei Kushnir <<a href="mailto:timophey@rdp.ru">timophey@rdp.ru</a>>\r
+Sam Gross\r
</p>\r
</li>\r
<li>\r
<p>\r
-Tim Potter <<a href="mailto:tpot@samba.org">tpot@samba.org</a>>\r
+Thomas Otto\r
</p>\r
</li>\r
<li>\r
<p>\r
-Tomasz Miąsko <<a href="mailto:tomasz.miasko@gmail.com">tomasz.miasko@gmail.com</a>>\r
+Thomas Röfer\r
</p>\r
</li>\r
<li>\r
<p>\r
-Tom Hughes <<a href="mailto:tomtheengineer@gmail.com">tomtheengineer@gmail.com</a>>\r
+Timofei Kushnir\r
</p>\r
</li>\r
<li>\r
<p>\r
-Tor Arne Vestbø <<a href="mailto:tor.arne.vestbo@qt.io">tor.arne.vestbo@qt.io</a>>\r
+Tim Potter\r
</p>\r
</li>\r
<li>\r
<p>\r
-Vadim Petrochenkov <<a href="mailto:vadim.petrochenkov@gmail.com">vadim.petrochenkov@gmail.com</a>>\r
+Tomasz Miąsko\r
</p>\r
</li>\r
<li>\r
<p>\r
-Ville Skyttä <<a href="mailto:ville.skytta@iki.fi">ville.skytta@iki.fi</a>>\r
+Tom Hughes\r
</p>\r
</li>\r
<li>\r
<p>\r
-William S Fulton <<a href="mailto:wsf@fultondesigns.co.uk">wsf@fultondesigns.co.uk</a>>\r
+Tor Arne Vestbø\r
</p>\r
</li>\r
<li>\r
<p>\r
-Wilson Snyder <<a href="mailto:wsnyder@wsnyder.org">wsnyder@wsnyder.org</a>>\r
+Vadim Petrochenkov\r
</p>\r
</li>\r
<li>\r
<p>\r
-Xavier René-Corail <<a href="mailto:xavier.renecorail@gmail.com">xavier.renecorail@gmail.com</a>>\r
+Ville Skyttä\r
</p>\r
</li>\r
<li>\r
<p>\r
-Yiding Jia <<a href="mailto:yiding@fb.com">yiding@fb.com</a>>\r
+William S Fulton\r
</p>\r
</li>\r
<li>\r
<p>\r
-Yvan Janssens <<a href="mailto:friedkiwi@yvanj.me">friedkiwi@yvanj.me</a>>\r
+Wilson Snyder\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Xavier René-Corail\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Yiding Jia\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Yvan Janssens\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.6<br />\r
+Version 3.7<br />\r
Last updated\r
- 2019-01-14 21:09:34 CET\r
+ 2019-04-23 21:35:11 CEST\r
</div>\r
</div>\r
</body>\r
Clear the entire cache, removing all cached files, but keeping the
configuration file.
-*`-F, --max-files`*=_N_::
+*`--dump-manifest`*=_PATH_::
- Set the maximum number of files allowed in the cache. Use 0 for no limit.
- The value is stored in a configuration file in the cache directory and
- applies to all future compilations.
+ Dump manifest file at PATH in text format. This is only useful when
+ debugging ccache and its behavior.
+
+*`-k, --get-config`*=_KEY_::
+
+ Print the value of configuration option _KEY_. See
+ <<_configuration,CONFIGURATION>> for more information.
+
+*`--hash-file`*=_PATH_::
+
+ Print the hash (in format `<MD4>-<size>`) of the file at PATH. This is only
+ useful when debugging ccache and its behavior.
*`-h, --help`*::
Print an options summary page.
+*`-F, --max-files`*=_N_::
+
+ Set the maximum number of files allowed in the cache. Use 0 for no limit.
+ The value is stored in a configuration file in the cache directory and
+ applies to all future compilations.
+
*`-M, --max-size`*=_SIZE_::
Set the maximum size of the files stored in the cache. _SIZE_ should be a
stored in a configuration file in the cache directory and applies to all
future compilations.
+*`--print-stats`*::
+
+ Print statistics counter IDs and corresponding values machine-parsable
+ (tab-separated) format.
+
*`-o, --set-config`*=_KEY=VALUE_::
- Set configuration _KEY_ to _VALUE_. See <<_configuration,CONFIGURATION>>
- for more information.
+ Set configuration option _KEY_ to _VALUE_. See
+ <<_configuration,CONFIGURATION>> for more information.
-*`-p, --print-config`*::
+*`-p, --show-config`*::
Print current configuration options and from where they originate
- (environment variable, configuration file or compile-time default).
+ (environment variable, configuration file or compile-time default) in
+ human-readable format.
*`-s, --show-stats`*::
- Print the current statistics summary for the cache.
+ Print a summary of configuration and statistics counters in human-readable
+ format.
*`-V, --version`*::
~~~~~~~
A general tip for getting information about what ccache is doing is to enable
-debug logging by setting *log_file*. The log contains executed commands,
-important decisions that ccache makes, read and written files, etc. Another way
-of keeping track of what is happening is to check the output of *ccache -s*.
+debug logging by setting the configuration option *debug* (or the environment
+variable *CCACHE_DEBUG*); see <<_cache_debugging,debugging>> for more
+information. Another way of keeping track of what is happening is to check the
+output of *ccache -s*.
Performance
----------------
Credits, mailing list information, bug reporting instructions, source code,
-etc, can be found on ccache's web site: <https://ccache.samba.org>.
+etc, can be found on ccache's web site: <https://ccache.dev>.
Author
ccache was originally written by Andrew Tridgell and is currently developed and
maintained by Joel Rosdahl. See AUTHORS.txt or AUTHORS.html and
-<https://ccache.samba.org/credits.html> for a list of contributors.
+<https://ccache.dev/credits.html> for a list of contributors.
<body class="article">\r
<div id="header">\r
<h1>CCACHE(1)</h1>\r
-<span id="revnumber">version 3.6</span>\r
+<span id="revnumber">version 3.7</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>
</p>\r
</dd>\r
<dt class="hdlist1">\r
-<strong><code>-F, --max-files</code></strong>=<em>N</em>\r
+<strong><code>--dump-manifest</code></strong>=<em>PATH</em>\r
</dt>\r
<dd>\r
<p>\r
- Set the maximum number of files allowed in the cache. Use 0 for no limit.\r
- The value is stored in a configuration file in the cache directory and\r
- applies to all future compilations.\r
+ Dump manifest file at PATH in text format. This is only useful when\r
+ debugging ccache and its behavior.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<strong><code>-k, --get-config</code></strong>=<em>KEY</em>\r
+</dt>\r
+<dd>\r
+<p>\r
+ Print the value of configuration option <em>KEY</em>. See\r
+ <a href="#_configuration">CONFIGURATION</a> for more information.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+<strong><code>--hash-file</code></strong>=<em>PATH</em>\r
+</dt>\r
+<dd>\r
+<p>\r
+ Print the hash (in format <code><MD4>-<size></code>) of the file at PATH. This is only\r
+ useful when debugging ccache and its behavior.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
+<strong><code>-F, --max-files</code></strong>=<em>N</em>\r
+</dt>\r
+<dd>\r
+<p>\r
+ Set the maximum number of files allowed in the cache. Use 0 for no limit.\r
+ The value is stored in a configuration file in the cache directory and\r
+ applies to all future compilations.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
<strong><code>-M, --max-size</code></strong>=<em>SIZE</em>\r
</dt>\r
<dd>\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
+<strong><code>--print-stats</code></strong>\r
+</dt>\r
+<dd>\r
+<p>\r
+ Print statistics counter IDs and corresponding values machine-parsable\r
+ (tab-separated) format.\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
<strong><code>-o, --set-config</code></strong>=<em>KEY=VALUE</em>\r
</dt>\r
<dd>\r
<p>\r
- Set configuration <em>KEY</em> to <em>VALUE</em>. See <a href="#_configuration">CONFIGURATION</a>\r
- for more information.\r
+ Set configuration option <em>KEY</em> to <em>VALUE</em>. See\r
+ <a href="#_configuration">CONFIGURATION</a> for more information.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
-<strong><code>-p, --print-config</code></strong>\r
+<strong><code>-p, --show-config</code></strong>\r
</dt>\r
<dd>\r
<p>\r
Print current configuration options and from where they originate\r
- (environment variable, configuration file or compile-time default).\r
+ (environment variable, configuration file or compile-time default) in\r
+ human-readable format.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
</dt>\r
<dd>\r
<p>\r
- Print the current statistics summary for the cache.\r
+ Print a summary of configuration and statistics counters in human-readable\r
+ format.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
<div class="sect2">\r
<h3 id="_general">General</h3>\r
<div class="paragraph"><p>A general tip for getting information about what ccache is doing is to enable\r
-debug logging by setting <strong>log_file</strong>. The log contains executed commands,\r
-important decisions that ccache makes, read and written files, etc. Another way\r
-of keeping track of what is happening is to check the output of <strong>ccache -s</strong>.</p></div>\r
+debug logging by setting the configuration option <strong>debug</strong> (or the environment\r
+variable <strong>CCACHE_DEBUG</strong>); see <a href="#_cache_debugging">debugging</a> for more\r
+information. Another way of keeping track of what is happening is to check the\r
+output of <strong>ccache -s</strong>.</p></div>\r
</div>\r
<div class="sect2">\r
<h3 id="_performance">Performance</h3>\r
<h2 id="_more_information">More information</h2>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Credits, mailing list information, bug reporting instructions, source code,\r
-etc, can be found on ccache’s web site: <a href="https://ccache.samba.org">https://ccache.samba.org</a>.</p></div>\r
+etc, can be found on ccache’s web site: <a href="https://ccache.dev">https://ccache.dev</a>.</p></div>\r
</div>\r
</div>\r
<div class="sect1">\r
<div class="sectionbody">\r
<div class="paragraph"><p>ccache was originally written by Andrew Tridgell and is currently developed and\r
maintained by Joel Rosdahl. See AUTHORS.txt or AUTHORS.html and\r
-<a href="https://ccache.samba.org/credits.html">https://ccache.samba.org/credits.html</a> for a list of contributors.</p></div>\r
+<a href="https://ccache.dev/credits.html">https://ccache.dev/credits.html</a> for a list of contributors.</p></div>\r
</div>\r
</div>\r
</div>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.6<br />\r
+Version 3.7<br />\r
Last updated\r
- 2019-01-13 21:38:14 CET\r
+ 2019-04-23 21:35:11 CEST\r
</div>\r
</div>\r
</body>\r
ccache news
===========
+ccache 3.7
+----------
+Release date: 2019-04-23
+
+Changes
+~~~~~~~
+
+- Fixed crash when the debug mode is enabled and the output file is in a
+ non-writable directory, e.g. when the output file is `/dev/null`.
+
+- Fixed an issue when printing very large log messages to the debug log.
+
+- Fixed bugs related to support for `-gsplit-dwarf`. Previously ccache could
+ produce an incorrect link to the `.dwo` file in the `.o` file.
+
+- Compilations with /dev/null as the input file are now cached.
+
+- ccache has learned how to contruct the object filename if no `-o` option is
+ given and the source filename does not include a `.` or ends with a `.`.
+
+- Fixed a temporary file leak when the depend mode is enabled and the compiler
+ produces standard error output.
+
+- Fixed a bug in the depend mode where a manifest hash only could be associated
+ with one set of header dependencies.
+
+- Manifest files did not get marked as used on direct cache hits, so the LRU
+ cache cleanup would incorrectly remove them eventually. This has been fixed.
+
+- The rewriting of absolute paths into relative paths in the dependency file
+ has been enabled in the depend mode as well.
+
+- ccache now ignores unknown keys in configuration files for forward
+ compatibility.
+
+- Rearranged command-line options into sections in the help text.
+
+- Documented the previously undocumented `--dump-manifest` and `--hash-file`
+ options (only useful for debugging ccache itself).
+
+- Added missing documentation for the command-line option `-k/--get-config`
+ added in ccache 3.5.
+
+- Renamed the `--print-config` command to `--show-config`.
+
+- Added a new `--print-stats` command that prints statistics counters in
+ machine-parsable (tab-separated) format.
+
+- ccache no longer creates a missing output directory, thus mimicking the
+ compiler behavior for `-o out/obj.o` when “out” doesn’t exist.
+
+- `-fdebug-prefix-map=ARG`, `-ffile-prefix-map=ARG` and
+ `-fmacro-prefix-map=ARG` are now included in the hash, but only the part
+ before “ARG”. This fixes a bug where compiler feature detection of said flags
+ would not work correctly with ccache.
+
+- Bail out on too hard compiler option `-gtoggle`.
+
+- Bail out on too hard Clang options `--analyze` and `-analyze`.
+
+- Improved debug logging of file hashes in depend mode.
+
+- Improved handling of various `-g*` options. In particular, ccache now
+ understands that `-g0` cancels out previous `-g* options`.
+
+- Worked around a problem with Automake related to `.d` files when using the
+ hard link mode.
+
+- Added opt-in (at configure time) support for enabling trace logs for
+ profiling ccache itself. See `doc/DEVELOPER.md` in the code tree for more
+ information
+
+- Removed support for Fortran 77 again. Some Fortran support was added in
+ ccache 3.3, but the implementation did not work when Fortran modules are
+ involved.
+
+
ccache 3.6
----------
Release date: 2019-01-14
Changes
~~~~~~~
-- ccache now has an opt-in ``depend mode''. When enabled, ccache never executes
+- 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`
+- 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.
- 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
+ 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
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__`
+ source code now doesn’t produce false positives for tokens where `__DATE__`
or `__TIME__` is a substring.
- Added a boolean `debug` (`CCACHE_DEBUG`) configuration option. When enabled,
ccache will create per-object debug files that are helpful e.g. when
- debugging unexpected cache misses. See also the new ``Cache debugging''
- section in the manual.
+ debugging unexpected cache misses. See also the new “Cache debugging” section
+ in the manual.
- Renamed `CCACHE_CC` to `CCACHE_COMPILER` (keeping the former as a deprecated
alias).
- Improved performance substantially when using `hash_dir = false` on platforms
like macOS where `getcwd()` is slow.
-- Added ``stats updated'' timestamp in `ccache -s` output. This can be useful
- if you wonder whether ccache actually was used for your last build.
+- Added “stats updated” timestamp in `ccache -s` output. This can be useful if
+ you wonder whether ccache actually was used for your last build.
-- Renamed ``stats zero time'' to ``stats zeroed'' and documented it. The
- counter is also now only present in `ccache -s` output when `ccache -z`
- actually has been called.
+- Renamed “stats zero time” to “stats zeroed” and documented it. The counter is
+ also now only present in `ccache -s` output when `ccache -z` actually has
+ been called.
- The content of the `-fsanitize-blacklist` file is now included in the hash,
so updates to the file will now correctly result in separate cache entries.
-- It's now possible to opt out of building and installing man pages when
+- 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
- defaults that won't trip up Clang.
+- 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.
triggered at the same time, in extreme cases trimming the cache to a much
smaller size than the configured limits.
-- Correctly hash preprocessed headers located in a ``.gch directory''.
+- Correctly hash preprocessed headers located in a “.gch directory”.
Previously, ccache would not pick up changes to such precompiled headers,
risking false positive cache hits.
- Fixed build failure when using the bundled zlib sources.
- ccache 3.3.5 added a workaround for not triggering Clang errors when a
- precompiled header's dependency has an updated timestamp (but identical
+ precompiled header’s dependency has an updated timestamp (but identical
content). That workaround is now only applied when the compiler is Clang.
- Made it possible to perform out-of-source builds in dev mode again.
- Added support for caching `.su` files generated by GCC flag `-fstack-usage`.
-- ccache should now work with distcc's ``pump'' wrapper.
+- ccache should now work with distcc’s “pump” wrapper.
- The optional unifier is no longer disabled when the direct mode is enabled.
- Boolean environment variable settings no longer accept the following
(case-insensitive) values: `0`, `false`, `disable` and `no`. All other values
- are accepted and taken to mean ``true''. This is to stop users from setting
+ are accepted and taken to mean “true”. This is to stop users from setting
e.g. `CCACHE_DISABLE=0` and then expect the cache to be used.
- Improved support for `run_second_cpp = false`: If combined with passing
- An implicit `-MQ` is now passed to the preprocessor only if the object file
extension is non-standard. This should make it easier to use EDG-based
- compilers (e.g. GHS) which don't understand `-MQ`.
+ compilers (e.g. GHS) which don’t understand `-MQ`.
- ccache now treats an unreadable configuration file just like a missing
configuration file.
~~~~~~~~~
- Fixed a regression where the original order of debug options could be lost.
- This reverts the ``Improved parsing of `-g*` options'' feature in ccache 3.3.
+ This reverts the “Improved parsing of `-g*` options” feature in ccache 3.3.
- Multiple `-fdebug-prefix-map` options should now be handled correctly.
- `ccache -c/--cleanup` now works like documented: it just recalculates size
counters and trims the cache to not exceed the max size and file number
- limits. Previously, the forced cleanup took ``limit_multiple'' into account,
- so that `ccache -c/--cleanup` by default would trim the cache to 80% of the
- max limit.
+ limits. Previously, the forced cleanup took “limit_multiple” into account, so
+ that `ccache -c/--cleanup` by default would trim the cache to 80% of the max
+ limit.
- ccache no longer ignores linker arguments for Clang since Clang warns about
them.
- Fixed a regression in ccache 3.3 related to potentially bad content of
dependency files when compiling identical source code but with different
source paths. This was only partially fixed in 3.3.2 and reverts the new
- ``Names of included files are no longer included in the hash of the
- compiler's preprocessed output'' feature in 3.3.
+ “Names of included files are no longer included in the hash of the compiler’s
+ preprocessed output” feature in 3.3.
- Corrected statistics counter for `-optf`/`--options-file` failure.
Bug fixes
~~~~~~~~~
-- Fixed a problem in the ``multiple `-arch` options'' support introduced in
- 3.3. When using the direct mode (the default), different combinations of
- `-arch` options were not detected properly.
+- Fixed a problem in the “multiple `-arch` options” support introduced in 3.3.
+ When using the direct mode (the default), different combinations of `-arch`
+ options were not detected properly.
- Fixed an issue when compiler option `-Wp,-MT,path` is used instead of `-MT
path` (and similar for `-MF`, `-MP` and `-MQ`) and `run_second_cpp`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The configuration option `run_second_cpp` (`CCACHE_CPP2`) now defaults to
- true. This improves ccache's out-of-the-box experience for compilers that
- can't compile their own preprocessed output with the same outcome as if they
+ true. This improves ccache’s out-of-the-box experience for compilers that
+ can’t compile their own preprocessed output with the same outcome as if they
compiled the real source code directly, e.g. newer versions of GCC and Clang.
- The configuration option `hash_dir` (`CCACHE_HASHDIR`) now defaults to true.
- Added a new statistics counter that tracks the number of performed cleanups
due to the cache size being over the limit. The value is shown in the output
- of ``ccache -s''.
+ of “ccache -s”.
- Added support for relocating debug info directory using `-fdebug-prefix-map`.
This allows for cache hits even when `hash_dir` is used in combination with
`base_dir`.
-- Added a new ``cache hit rate'' field to the output of ``ccache -s''.
+- Added a new “cache hit rate” field to the output of “ccache -s”.
-- Added support for caching compilation of assembler code produced by e.g.
- ``gcc -S file.c''.
+- Added support for caching compilation of assembler code produced by e.g. “gcc
+ -S file.c”.
- Added support for cuda including the -optf/--options-file option.
- ccache now understands the undocumented `-coverage` (only one dash) GCC
option.
-- Names of included files are no longer included in the hash of the compiler's
+- Names of included files are no longer included in the hash of the compiler’s
preprocessed output. This leads to more potential cache hits when not using
the direct mode.
- Fixed a bug which could lead to false cache hits for compiler command lines
with a missing argument to an option that takes an argument.
-- ccache now knows how to work around a glitch in the output of GCC 6's
+- ccache now knows how to work around a glitch in the output of GCC 6’s
preprocessor.
Bug fixes
~~~~~~~~~
-- Fixed build problem on QNX, which lacks ``SA_RESTART''.
+- Fixed build problem on QNX, which lacks “SA_RESTART”.
- Bail out on compiler option `-fstack-usage` since it creates a `.su` file
- which ccache currently doesn't handle.
+ which ccache currently doesn’t handle.
- Fixed a bug where (due to ccache rewriting paths) the compiler could choose
incorrect include files if `CCACHE_BASEDIR` is used and the source file path
- Improved handling of stale NFS handles.
-- Made it harder to misinterpret documentation of boolean environment settings'
+- Made it harder to misinterpret documentation of boolean environment settings’
semantics.
- Fixed failure to create directories on QNX.
-- Don't (try to) update manifest file in ``read-only'' and ``read-only direct''
+- Don’t (try to) update manifest file in “read-only” and “read-only direct”
modes.
-- Fixed a bug in caching of `stat` system calls in ``file_stat_matches
- sloppiness mode''.
+- Fixed a bug in caching of `stat` system calls in “file_stat_matches
+ sloppiness mode”.
- Fixed bug in hashing of Clang plugins, leading to unnecessary cache misses.
-- Fixed --print-config to show ``pch_defines sloppiness''.
+- Fixed --print-config to show “pch_defines sloppiness”.
-- The man page is now built when running ``make install'' from Git repository
+- The man page is now built when running “make install” from Git repository
sources.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Added support for `CCACHE_COMPILERCHECK=string:<value>`. This is a faster
- alternative to `CCACHE_COMPILERCHECK=<command>` if the command's output can
+ alternative to `CCACHE_COMPILERCHECK=<command>` if the command’s output can
be precalculated by the build system.
- Add support for caching code coverage results (compiling for gcov).
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 nonexistent stats file. This avoids ``No such file or
- directory'' messages in the ccache log when the cache directory doesn't
- exist.
+- 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.
- Fixed a bug where ccache deleted Clang diagnostics after compiler failures.
- Added support for several binaries (separated by space) in `CCACHE_PREFIX`.
- The `-c` option is no longer passed to the preprocessor. This fixes problems
- with Clang and Solaris's C++ compiler.
+ with Clang and Solaris’s C++ compiler.
- ccache no longer passes preprocessor options like `-D` and `-I` to the
compiler when compiling preprocessed output. This fixes warnings emitted by
- Compiler options `-fprofile-generate`, `-fprofile-arcs`, `-fprofile-use` and
`-fbranch-probabilities` are now handled without bailing.
-- Added support for Clang's `--serialize-diagnostic` option, storing the
+- Added support for Clang’s `--serialize-diagnostic` option, storing the
diagnostic file (`.dia`) in the cache.
- Added support for precompiled headers when using Clang.
the other way around. This is needed to support compiler options like
`-fprofile-arcs` and `--serialize-diagnostics`.
-- ccache now checks that included files' ctimes aren't too new. This check can
- be turned off by adding `include_file_ctime` to the ``ccache sloppiness''
+- ccache now checks that included files’ ctimes aren’t too new. This check can
+ be turned off by adding `include_file_ctime` to the “ccache sloppiness”
setting.
- Added possibility to get cache hits based on filename, size, mtime and ctime
only. On other words, source code files are not even read, only stat-ed. This
- operation mode is opt-in by adding `file_stat_matches` to the ``ccache
- sloppiness'' setting.
+ operation mode is opt-in by adding `file_stat_matches` to the “ccache
+ sloppiness” setting.
- The filename part of options like `-Wp,-MDfilename` is no longer included in
- the hash since the filename doesn't have any bearing on the result.
+ the hash since the filename doesn’t have any bearing on the result.
-- Added a ``read-only direct'' configuration setting, which is like the
- ordinary read-only setting except that ccache will only try to retrieve
- results from the cache using the direct mode, not the preprocessor mode.
+- Added a “read-only direct” configuration setting, which is like the ordinary
+ read-only setting except that ccache will only try to retrieve results from
+ the cache using the direct mode, not the preprocessor mode.
- The display and interpretation of cache size has been changed to use SI
units.
- Added support for `@file` and `-@file` arguments (reading options from a
file).
-- `-Wl,` options are no longer included in the hash since they don't affect
+- `-Wl,` options are no longer included in the hash since they don’t affect
compilation.
- Bail out on too hard compiler option `-Wp,-P`.
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 nonexistent stats file. This avoids ``No such file or
- directory'' messages in the ccache log when the cache directory doesn't
- exist.
+- 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.
ccache 3.1.10
`CCACHE_BASEDIR` to reuse results across different directories.)
- Added note in documentation that `--ccache-skip` currently does not mean
- ``don't hash the following option''.
+ “don’t hash the following option”.
- To enable support for precompiled headers (PCH), `CCACHE_SLOPPINESS` now also
needs to include the new `pch_defines` sloppiness. This is because ccache
- can't detect changes in the source code when only defined macros have been
+ can’t detect changes in the source code when only defined macros have been
changed.
- Stale files in the internal temporary directory (`<ccache_dir>/tmp`) are now
Bug fixes
~~~~~~~~~
-- Fixed path canonicalization in `make_relative_path()` when path doesn't
+- Fixed path canonicalization in `make_relative_path()` when path doesn’t
exist.
- Fixed bug in `common_dir_prefix_length()`. This corrects the `CCACHE_BASEDIR`
- Subdirectories in the cache are no longer created in read-only mode.
-- Fixed so that ccache's log file descriptor is not made available to the
+- Fixed so that ccache’s log file descriptor is not made available to the
compiler.
- Improved error reporting when failing to create temporary stdout/stderr files
Bug fixes
~~~~~~~~~
-- Don't crash if `getcwd()` fails.
+- Don’t crash if `getcwd()` fails.
-- Fixed alignment of ``called for preprocessing'' counter.
+- Fixed alignment of “called for preprocessing” counter.
ccache 3.1.5
New features and enhancements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Added a new statistics counter named ``called for preprocessing''.
+- Added a new statistics counter named “called for preprocessing”.
- The original command line is now logged to the file specified with
`CCACHE_LOGFILE`.
- Fixed a minor memory leak.
-- Systems that lack (and don't need to be linked with) libm are now supported.
+- Systems that lack (and don’t need to be linked with) libm are now supported.
ccache 3.1.4
- Made a work-around for a bug in `gzputc()` in zlib 1.2.5.
-- Corrupt manifest files are now removed so that they won't block direct mode
+- Corrupt manifest files are now removed so that they won’t block direct mode
hits.
-- ccache now copes with file systems that don't know about symbolic links.
+- ccache now copes with file systems that don’t know about symbolic links.
- The file handle in now correctly closed on write error when trying to create
a cache dir tag.
- Improved documentation on which information is included in the hash sum.
-- Made the ``too new header file'' test case work on file systems with
+- Made the “too new header file” test case work on file systems with
unsynchronized clocks.
- The test suite now also works on systems that lack a /dev/zero.
- Fixed configure detection of ar.
- ccache development version (set by dev.mk) now works with gits whose
- `describe` command doesn't understand `--dirty`.
+ `describe` command doesn’t understand `--dirty`.
Other
- Added support for hashing the output of a custom command (e.g. `%compiler%
--version`) to identify the compiler instead of stat-ing or hashing the
compiler binary. This can improve robustness when the compiler (as seen by
- ccache) actually isn't the real compiler but another compiler wrapper.
+ ccache) actually isn’t the real compiler but another compiler wrapper.
- Added support for caching compilations that use precompiled headers. (See the
manual for important instructions regarding this.)
- Reading and writing of statistics counters has been made forward-compatible
(unknown counters are retained).
-- Files are now read without using `mmap()`. This has two benefits: it's more
+- Files are now read without using `mmap()`. This has two benefits: it’s more
robust against file changes during reading and it improves performance on
- poor systems where `mmap()` doesn't use the disk cache.
+ poor systems where `mmap()` doesn’t use the disk cache.
- Added `.cp` and `.CP` as known C++ suffixes.
Bug fixes
~~~~~~~~~
-- The statistics counter ``called for link'' is now correctly updated when
+- The statistics counter “called for link” is now correctly updated when
linking with a single object file.
- Fixed a problem with out-of-source builds.
Upgrade notes
~~~~~~~~~~~~~
-- The way the hashes are calculated has changed, so you won't get cache hits
+- The way the hashes are calculated has changed, so you won’t get cache hits
for compilation results stored by older ccache versions. Because of this, you
might as well clear the old cache directory with `ccache --clear` if you
want, unless you plan to keep using an older ccache version.
New features and enhancements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ccache now has a ``direct mode'' where it computes a hash of the source code
+- ccache now has a “direct mode” where it computes a hash of the source code
(including all included files) and compiler options without running the
preprocessor. By not running the preprocessor, CPU usage is reduced; the
speed is somewhere between 1 and 5 times that of ccache running in
- Object files are now optionally stored compressed in the cache. The runtime
cost is negligible, and more files will fit in the ccache directory and in
the disk cache. Set `CCACHE_COMPRESS` to enable object file compression. Note
- that you can't use compression in combination with the hard link feature.
+ that you can’t use compression in combination with the hard link feature.
- A `CCACHE_COMPILERCHECK` option has been added. This option tells ccache what
compiler-identifying information to hash to ensure that results retrieved
- from the cache are accurate. Possible values are: none (don't hash anything),
- mtime (hash the compiler's mtime and size) and content (hash the content of
+ from the cache are accurate. Possible values are: none (don’t hash anything),
+ mtime (hash the compiler’s mtime and size) and content (hash the content of
the compiler binary). The default is mtime.
- It is now possible to specify extra files whose contents should be included
in the hash sum by setting the `CCACHE_EXTRAFILES` option.
- Added support for Objective-C and Objective-C\+\+. The statistics counter
- ``not a C/C++ file'' has been renamed to ``unsupported source language''.
+ “not a C/C++ file” has been renamed to “unsupported source language”.
- Added support for the `-x` compiler option.
- Temporary files that later will be moved into the cache are now created in
the cache directory they will end up in. This makes ccache more friendly to
- Linux's directory layout.
+ Linux’s directory layout.
- Improved the test suite and added tests for most of the new functionality.
- It's now also possible to specify a subset of tests to run.
+ It’s now also possible to specify a subset of tests to run.
- Standard error output from the compiler is now only stored in the cache if
- it's non-empty.
+ it’s non-empty.
- If the compiler produces no object file or an empty object file, but gives a
zero exit status (could be due to a file system problem, a buggy program
- Added `installcheck` and `distcheck` make targets.
-- Clarified cache size limit options' and cleanup semantics.
+- Clarified cache size limit options’ and cleanup semantics.
- Improved display of cache max size values.
`-save-temps`. Also bail out on `@file` style options.
- Errors when using multiple `-arch` compiler options are now noted as
- ``unsupported compiler option''.
+ “unsupported compiler option”.
- `-MD`/`-MMD` options without `-MT`/`-MF` are now handled correctly.
<body class="article">\r
<div id="header">\r
<h1>ccache news</h1>\r
-<span id="revnumber">version 3.6</span>\r
+<span id="revnumber">version 3.7</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_7">ccache 3.7</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Release date: 2019-04-23</p></div>\r
+<div class="sect2">\r
+<h3 id="_changes">Changes</h3>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Fixed crash when the debug mode is enabled and the output file is in a\r
+ non-writable directory, e.g. when the output file is <code>/dev/null</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed an issue when printing very large log messages to the debug log.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed bugs related to support for <code>-gsplit-dwarf</code>. Previously ccache could\r
+ produce an incorrect link to the <code>.dwo</code> file in the <code>.o</code> file.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Compilations with /dev/null as the input file are now cached.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache has learned how to contruct the object filename if no <code>-o</code> option is\r
+ given and the source filename does not include a <code>.</code> or ends with a <code>.</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a temporary file leak when the depend mode is enabled and the compiler\r
+ produces standard error output.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a bug in the depend mode where a manifest hash only could be associated\r
+ with one set of header dependencies.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Manifest files did not get marked as used on direct cache hits, so the LRU\r
+ cache cleanup would incorrectly remove them eventually. This has been fixed.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The rewriting of absolute paths into relative paths in the dependency file\r
+ has been enabled in the depend mode as well.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache now ignores unknown keys in configuration files for forward\r
+ compatibility.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Rearranged command-line options into sections in the help text.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Documented the previously undocumented <code>--dump-manifest</code> and <code>--hash-file</code>\r
+ options (only useful for debugging ccache itself).\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Added missing documentation for the command-line option <code>-k/--get-config</code>\r
+ added in ccache 3.5.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Renamed the <code>--print-config</code> command to <code>--show-config</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Added a new <code>--print-stats</code> command that prints statistics counters in\r
+ machine-parsable (tab-separated) format.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache no longer creates a missing output directory, thus mimicking the\r
+ compiler behavior for <code>-o out/obj.o</code> when “out” doesn’t exist.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+<code>-fdebug-prefix-map=ARG</code>, <code>-ffile-prefix-map=ARG</code> and\r
+ <code>-fmacro-prefix-map=ARG</code> are now included in the hash, but only the part\r
+ before “ARG”. This fixes a bug where compiler feature detection of said flags\r
+ would not work correctly with ccache.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Bail out on too hard compiler option <code>-gtoggle</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Bail out on too hard Clang options <code>--analyze</code> and <code>-analyze</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Improved debug logging of file hashes in depend mode.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Improved handling of various <code>-g*</code> options. In particular, ccache now\r
+ understands that <code>-g0</code> cancels out previous <code>-g* options</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Worked around a problem with Automake related to <code>.d</code> files when using the\r
+ hard link mode.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Added opt-in (at configure time) support for enabling trace logs for\r
+ profiling ccache itself. See <code>doc/DEVELOPER.md</code> in the code tree for more\r
+ information\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Removed support for Fortran 77 again. Some Fortran support was added in\r
+ ccache 3.3, but the implementation did not work when Fortran modules are\r
+ involved.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+</div>\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
+<h3 id="_changes_2">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
+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
</li>\r
<li>\r
<p>\r
-Added support for GCC’s <code>-ffile-prefix-map</code> option. The <code>-fmacro-prefix-map</code>\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
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
+ 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
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
+ 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
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2019-01-02</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
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2018-10-15</p></div>\r
<div class="sect2">\r
-<h3 id="_changes_3">Changes</h3>\r
+<h3 id="_changes_4">Changes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
Added a boolean <code>debug</code> (<code>CCACHE_DEBUG</code>) configuration option. When enabled,\r
ccache will create per-object debug files that are helpful e.g. when\r
- debugging unexpected cache misses. See also the new “Cache debugging”\r
- section in the manual.\r
+ debugging unexpected cache misses. See also the new “Cache debugging” section\r
+ in the manual.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Added “stats updated” timestamp in <code>ccache -s</code> output. This can be useful\r
- if you wonder whether ccache actually was used for your last build.\r
+Added “stats updated” timestamp in <code>ccache -s</code> output. This can be useful if\r
+ you wonder whether ccache actually was used for your last build.\r
</p>\r
</li>\r
<li>\r
<p>\r
-Renamed “stats zero time” to “stats zeroed” and documented it. The\r
- counter is also now only present in <code>ccache -s</code> output when <code>ccache -z</code>\r
- actually has been called.\r
+Renamed “stats zero time” to “stats zeroed” and documented it. The counter is\r
+ also now only present in <code>ccache -s</code> output when <code>ccache -z</code> actually has\r
+ been called.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-It’s now possible to opt out of building and installing man pages when\r
+It’s now possible to opt out of building and installing man pages when\r
running <code>make install</code> in the source repository.\r
</p>\r
</li>\r
<li>\r
<p>\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
+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
<li>\r
</li>\r
<li>\r
<p>\r
-Correctly hash preprocessed headers located in a “.gch directory”.\r
+Correctly hash preprocessed headers located in a “.gch directory”.\r
Previously, ccache would not pick up changes to such precompiled headers,\r
risking false positive cache hits.\r
</p>\r
<li>\r
<p>\r
ccache 3.3.5 added a workaround for not triggering Clang errors when a\r
- precompiled header’s dependency has an updated timestamp (but identical\r
+ precompiled header’s dependency has an updated timestamp (but identical\r
content). That workaround is now only applied when the compiler is Clang.\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
-ccache should now work with distcc’s “pump” wrapper.\r
+ccache should now work with distcc’s “pump” wrapper.\r
</p>\r
</li>\r
<li>\r
<p>\r
Boolean environment variable settings no longer accept the following\r
(case-insensitive) values: <code>0</code>, <code>false</code>, <code>disable</code> and <code>no</code>. All other values\r
- are accepted and taken to mean “true”. This is to stop users from setting\r
+ are accepted and taken to mean “true”. This is to stop users from setting\r
e.g. <code>CCACHE_DISABLE=0</code> and then expect the cache to be used.\r
</p>\r
</li>\r
<p>\r
An implicit <code>-MQ</code> is now passed to the preprocessor only if the object file\r
extension is non-standard. This should make it easier to use EDG-based\r
- compilers (e.g. GHS) which don’t understand <code>-MQ</code>.\r
+ compilers (e.g. GHS) which don’t understand <code>-MQ</code>.\r
</p>\r
</li>\r
<li>\r
<li>\r
<p>\r
Fixed a regression where the original order of debug options could be lost.\r
- This reverts the “Improved parsing of <code>-g*</code> options” feature in ccache 3.3.\r
+ This reverts the “Improved parsing of <code>-g*</code> options” feature in ccache 3.3.\r
</p>\r
</li>\r
<li>\r
<p>\r
<code>ccache -c/--cleanup</code> now works like documented: it just recalculates size\r
counters and trims the cache to not exceed the max size and file number\r
- limits. Previously, the forced cleanup took “limit_multiple” into account,\r
- so that <code>ccache -c/--cleanup</code> by default would trim the cache to 80% of the\r
- max limit.\r
+ limits. Previously, the forced cleanup took “limit_multiple” into account, so\r
+ that <code>ccache -c/--cleanup</code> by default would trim the cache to 80% of the max\r
+ limit.\r
</p>\r
</li>\r
<li>\r
Fixed a regression in ccache 3.3 related to potentially bad content of\r
dependency files when compiling identical source code but with different\r
source paths. This was only partially fixed in 3.3.2 and reverts the new\r
- “Names of included files are no longer included in the hash of the\r
- compiler’s preprocessed output” feature in 3.3.\r
+ “Names of included files are no longer included in the hash of the compiler’s\r
+ preprocessed output” feature in 3.3.\r
</p>\r
</li>\r
<li>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-Fixed a problem in the “multiple <code>-arch</code> options” support introduced in\r
- 3.3. When using the direct mode (the default), different combinations of\r
- <code>-arch</code> options were not detected properly.\r
+Fixed a problem in the “multiple <code>-arch</code> options” support introduced in 3.3.\r
+ When using the direct mode (the default), different combinations of <code>-arch</code>\r
+ options were not detected properly.\r
</p>\r
</li>\r
<li>\r
<li>\r
<p>\r
The configuration option <code>run_second_cpp</code> (<code>CCACHE_CPP2</code>) now defaults to\r
- true. This improves ccache’s out-of-the-box experience for compilers that\r
- can’t compile their own preprocessed output with the same outcome as if they\r
+ true. This improves ccache’s out-of-the-box experience for compilers that\r
+ can’t compile their own preprocessed output with the same outcome as if they\r
compiled the real source code directly, e.g. newer versions of GCC and Clang.\r
</p>\r
</li>\r
<p>\r
Added a new statistics counter that tracks the number of performed cleanups\r
due to the cache size being over the limit. The value is shown in the output\r
- of “ccache -s”.\r
+ of “ccache -s”.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Added a new “cache hit rate” field to the output of “ccache -s”.\r
+Added a new “cache hit rate” field to the output of “ccache -s”.\r
</p>\r
</li>\r
<li>\r
<p>\r
-Added support for caching compilation of assembler code produced by e.g.\r
- “gcc -S file.c”.\r
+Added support for caching compilation of assembler code produced by e.g. “gcc\r
+ -S file.c”.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Names of included files are no longer included in the hash of the compiler’s\r
+Names of included files are no longer included in the hash of the compiler’s\r
preprocessed output. This leads to more potential cache hits when not using\r
the direct mode.\r
</p>\r
</li>\r
<li>\r
<p>\r
-ccache now knows how to work around a glitch in the output of GCC 6’s\r
+ccache now knows how to work around a glitch in the output of GCC 6’s\r
preprocessor.\r
</p>\r
</li>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-Fixed build problem on QNX, which lacks “SA_RESTART”.\r
+Fixed build problem on QNX, which lacks “SA_RESTART”.\r
</p>\r
</li>\r
<li>\r
<p>\r
Bail out on compiler option <code>-fstack-usage</code> since it creates a <code>.su</code> file\r
- which ccache currently doesn’t handle.\r
+ which ccache currently doesn’t handle.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Made it harder to misinterpret documentation of boolean environment settings'\r
+Made it harder to misinterpret documentation of boolean environment settings’\r
semantics.\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
-Don’t (try to) update manifest file in “read-only” and “read-only direct”\r
+Don’t (try to) update manifest file in “read-only” and “read-only direct”\r
modes.\r
</p>\r
</li>\r
<li>\r
<p>\r
-Fixed a bug in caching of <code>stat</code> system calls in “file_stat_matches\r
- sloppiness mode”.\r
+Fixed a bug in caching of <code>stat</code> system calls in “file_stat_matches\r
+ sloppiness mode”.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Fixed --print-config to show “pch_defines sloppiness”.\r
+Fixed --print-config to show “pch_defines sloppiness”.\r
</p>\r
</li>\r
<li>\r
<p>\r
-The man page is now built when running “make install” from Git repository\r
+The man page is now built when running “make install” from Git repository\r
sources.\r
</p>\r
</li>\r
<li>\r
<p>\r
Added support for <code>CCACHE_COMPILERCHECK=string:<value></code>. This is a faster\r
- alternative to <code>CCACHE_COMPILERCHECK=<command></code> if the command’s output can\r
+ alternative to <code>CCACHE_COMPILERCHECK=<command></code> if the command’s output can\r
be precalculated by the build system.\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\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
+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 exist.\r
</p>\r
</li>\r
<li>\r
<li>\r
<p>\r
The <code>-c</code> option is no longer passed to the preprocessor. This fixes problems\r
- with Clang and Solaris’s C++ compiler.\r
+ with Clang and Solaris’s C++ compiler.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Added support for Clang’s <code>--serialize-diagnostic</code> option, storing the\r
+Added support for Clang’s <code>--serialize-diagnostic</code> option, storing the\r
diagnostic file (<code>.dia</code>) in the cache.\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
-ccache now checks that included files' ctimes aren’t too new. This check can\r
- be turned off by adding <code>include_file_ctime</code> to the “ccache sloppiness”\r
+ccache now checks that included files’ ctimes aren’t too new. This check can\r
+ be turned off by adding <code>include_file_ctime</code> to the “ccache sloppiness”\r
setting.\r
</p>\r
</li>\r
<p>\r
Added possibility to get cache hits based on filename, size, mtime and ctime\r
only. On other words, source code files are not even read, only stat-ed. This\r
- operation mode is opt-in by adding <code>file_stat_matches</code> to the “ccache\r
- sloppiness” setting.\r
+ operation mode is opt-in by adding <code>file_stat_matches</code> to the “ccache\r
+ sloppiness” setting.\r
</p>\r
</li>\r
<li>\r
<p>\r
The filename part of options like <code>-Wp,-MDfilename</code> is no longer included in\r
- the hash since the filename doesn’t have any bearing on the result.\r
+ the hash since the filename doesn’t have any bearing on the result.\r
</p>\r
</li>\r
<li>\r
<p>\r
-Added a “read-only direct” configuration setting, which is like the\r
- ordinary read-only setting except that ccache will only try to retrieve\r
- results from the cache using the direct mode, not the preprocessor mode.\r
+Added a “read-only direct” configuration setting, which is like the ordinary\r
+ read-only setting except that ccache will only try to retrieve results from\r
+ the cache using the direct mode, not the preprocessor mode.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-<code>-Wl,</code> options are no longer included in the hash since they don’t affect\r
+<code>-Wl,</code> options are no longer included in the hash since they don’t affect\r
compilation.\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\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
+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 exist.\r
</p>\r
</li>\r
</ul></div>\r
<li>\r
<p>\r
Added note in documentation that <code>--ccache-skip</code> currently does not mean\r
- “don’t hash the following option”.\r
+ “don’t hash the following option”.\r
</p>\r
</li>\r
<li>\r
<p>\r
To enable support for precompiled headers (PCH), <code>CCACHE_SLOPPINESS</code> now also\r
needs to include the new <code>pch_defines</code> sloppiness. This is because ccache\r
- can’t detect changes in the source code when only defined macros have been\r
+ can’t detect changes in the source code when only defined macros have been\r
changed.\r
</p>\r
</li>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-Fixed path canonicalization in <code>make_relative_path()</code> when path doesn’t\r
+Fixed path canonicalization in <code>make_relative_path()</code> when path doesn’t\r
exist.\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
-Fixed so that ccache’s log file descriptor is not made available to the\r
+Fixed so that ccache’s log file descriptor is not made available to the\r
compiler.\r
</p>\r
</li>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-Don’t crash if <code>getcwd()</code> fails.\r
+Don’t crash if <code>getcwd()</code> fails.\r
</p>\r
</li>\r
<li>\r
<p>\r
-Fixed alignment of “called for preprocessing” counter.\r
+Fixed alignment of “called for preprocessing” counter.\r
</p>\r
</li>\r
</ul></div>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-Added a new statistics counter named “called for preprocessing”.\r
+Added a new statistics counter named “called for preprocessing”.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Systems that lack (and don’t need to be linked with) libm are now supported.\r
+Systems that lack (and don’t need to be linked with) libm are now supported.\r
</p>\r
</li>\r
</ul></div>\r
</li>\r
<li>\r
<p>\r
-Corrupt manifest files are now removed so that they won’t block direct mode\r
+Corrupt manifest files are now removed so that they won’t block direct mode\r
hits.\r
</p>\r
</li>\r
<li>\r
<p>\r
-ccache now copes with file systems that don’t know about symbolic links.\r
+ccache now copes with file systems that don’t know about symbolic links.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Made the “too new header file” test case work on file systems with\r
+Made the “too new header file” test case work on file systems with\r
unsynchronized clocks.\r
</p>\r
</li>\r
<li>\r
<p>\r
ccache development version (set by dev.mk) now works with gits whose\r
- <code>describe</code> command doesn’t understand <code>--dirty</code>.\r
+ <code>describe</code> command doesn’t understand <code>--dirty</code>.\r
</p>\r
</li>\r
</ul></div>\r
Added support for hashing the output of a custom command (e.g. <code>%compiler%\r
--version</code>) to identify the compiler instead of stat-ing or hashing the\r
compiler binary. This can improve robustness when the compiler (as seen by\r
- ccache) actually isn’t the real compiler but another compiler wrapper.\r
+ ccache) actually isn’t the real compiler but another compiler wrapper.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Files are now read without using <code>mmap()</code>. This has two benefits: it’s more\r
+Files are now read without using <code>mmap()</code>. This has two benefits: it’s more\r
robust against file changes during reading and it improves performance on\r
- poor systems where <code>mmap()</code> doesn’t use the disk cache.\r
+ poor systems where <code>mmap()</code> doesn’t use the disk cache.\r
</p>\r
</li>\r
<li>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-The statistics counter “called for link” is now correctly updated when\r
+The statistics counter “called for link” is now correctly updated when\r
linking with a single object file.\r
</p>\r
</li>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-The way the hashes are calculated has changed, so you won’t get cache hits\r
+The way the hashes are calculated has changed, so you won’t get cache hits\r
for compilation results stored by older ccache versions. Because of this, you\r
might as well clear the old cache directory with <code>ccache --clear</code> if you\r
want, unless you plan to keep using an older ccache version.\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
-ccache now has a “direct mode” where it computes a hash of the source code\r
+ccache now has a “direct mode” where it computes a hash of the source code\r
(including all included files) and compiler options without running the\r
preprocessor. By not running the preprocessor, CPU usage is reduced; the\r
speed is somewhere between 1 and 5 times that of ccache running in\r
Object files are now optionally stored compressed in the cache. The runtime\r
cost is negligible, and more files will fit in the ccache directory and in\r
the disk cache. Set <code>CCACHE_COMPRESS</code> to enable object file compression. Note\r
- that you can’t use compression in combination with the hard link feature.\r
+ that you can’t use compression in combination with the hard link feature.\r
</p>\r
</li>\r
<li>\r
<p>\r
A <code>CCACHE_COMPILERCHECK</code> option has been added. This option tells ccache what\r
compiler-identifying information to hash to ensure that results retrieved\r
- from the cache are accurate. Possible values are: none (don’t hash anything),\r
- mtime (hash the compiler’s mtime and size) and content (hash the content of\r
+ from the cache are accurate. Possible values are: none (don’t hash anything),\r
+ mtime (hash the compiler’s mtime and size) and content (hash the content of\r
the compiler binary). The default is mtime.\r
</p>\r
</li>\r
<li>\r
<p>\r
Added support for Objective-C and Objective-C++. The statistics counter\r
- “not a C/C++ file” has been renamed to “unsupported source language”.\r
+ “not a C/C++ file” has been renamed to “unsupported source language”.\r
</p>\r
</li>\r
<li>\r
<p>\r
Temporary files that later will be moved into the cache are now created in\r
the cache directory they will end up in. This makes ccache more friendly to\r
- Linux’s directory layout.\r
+ Linux’s directory layout.\r
</p>\r
</li>\r
<li>\r
<p>\r
Improved the test suite and added tests for most of the new functionality.\r
- It’s now also possible to specify a subset of tests to run.\r
+ It’s now also possible to specify a subset of tests to run.\r
</p>\r
</li>\r
<li>\r
<p>\r
Standard error output from the compiler is now only stored in the cache if\r
- it’s non-empty.\r
+ it’s non-empty.\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Clarified cache size limit options' and cleanup semantics.\r
+Clarified cache size limit options’ and cleanup semantics.\r
</p>\r
</li>\r
<li>\r
<li>\r
<p>\r
Errors when using multiple <code>-arch</code> compiler options are now noted as\r
- “unsupported compiler option”.\r
+ “unsupported compiler option”.\r
</p>\r
</li>\r
<li>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.6<br />\r
+Version 3.7<br />\r
Last updated\r
- 2019-01-14 21:08:50 CET\r
+ 2019-04-23 21:35:11 CEST\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/14/2019
+.\" Date: 04/23/2019
.\" Manual: ccache Manual
-.\" Source: ccache 3.6
+.\" Source: ccache 3.7
.\" Language: English
.\"
-.TH "CCACHE" "1" "01/14/2019" "ccache 3\&.6" "ccache Manual"
+.TH "CCACHE" "1" "04/23/2019" "ccache 3\&.7" "ccache Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Clear the entire cache, removing all cached files, but keeping the configuration file\&.
.RE
.PP
-\fB\fB\-F, \-\-max\-files\fR\fR=\fIN\fR
+\fB\fB\-\-dump\-manifest\fR\fR=\fIPATH\fR
.RS 4
-Set the maximum number of files allowed in the cache\&. Use 0 for no limit\&. The value is stored in a configuration file in the cache directory and applies to all future compilations\&.
+Dump manifest file at PATH in text format\&. This is only useful when debugging ccache and its behavior\&.
+.RE
+.PP
+\fB\fB\-k, \-\-get\-config\fR\fR=\fIKEY\fR
+.RS 4
+Print the value of configuration option
+\fIKEY\fR\&. See
+CONFIGURATION
+for more information\&.
+.RE
+.PP
+\fB\fB\-\-hash\-file\fR\fR=\fIPATH\fR
+.RS 4
+Print the hash (in format
+\fB<MD4>\-<size>\fR) of the file at PATH\&. This is only useful when debugging ccache and its behavior\&.
.RE
.PP
\fB\fB\-h, \-\-help\fR\fR
Print an options summary page\&.
.RE
.PP
+\fB\fB\-F, \-\-max\-files\fR\fR=\fIN\fR
+.RS 4
+Set the maximum number of files allowed in the cache\&. Use 0 for no limit\&. The value is stored in a configuration file in the cache directory and applies to all future compilations\&.
+.RE
+.PP
\fB\fB\-M, \-\-max\-size\fR\fR=\fISIZE\fR
.RS 4
Set the maximum size of the files stored in the cache\&.
should be a number followed by an optional suffix: k, M, G, T (decimal), Ki, Mi, Gi or Ti (binary)\&. The default suffix is G\&. Use 0 for no limit\&. The value is stored in a configuration file in the cache directory and applies to all future compilations\&.
.RE
.PP
+\fB\fB\-\-print\-stats\fR\fR
+.RS 4
+Print statistics counter IDs and corresponding values machine\-parsable (tab\-separated) format\&.
+.RE
+.PP
\fB\fB\-o, \-\-set\-config\fR\fR=\fIKEY=VALUE\fR
.RS 4
-Set configuration
+Set configuration option
\fIKEY\fR
to
\fIVALUE\fR\&. See
for more information\&.
.RE
.PP
-\fB\fB\-p, \-\-print\-config\fR\fR
+\fB\fB\-p, \-\-show\-config\fR\fR
.RS 4
-Print current configuration options and from where they originate (environment variable, configuration file or compile\-time default)\&.
+Print current configuration options and from where they originate (environment variable, configuration file or compile\-time default) in human\-readable format\&.
.RE
.PP
\fB\fB\-s, \-\-show\-stats\fR\fR
.RS 4
-Print the current statistics summary for the cache\&.
+Print a summary of configuration and statistics counters in human\-readable format\&.
.RE
.PP
\fB\fB\-V, \-\-version\fR\fR
.SH "TROUBLESHOOTING"
.SS "General"
.sp
-A general tip for getting information about what ccache is doing is to enable debug logging by setting \fBlog_file\fR\&. The log contains executed commands, important decisions that ccache makes, read and written files, etc\&. Another way of keeping track of what is happening is to check the output of \fBccache \-s\fR\&.
+A general tip for getting information about what ccache is doing is to enable debug logging by setting the configuration option \fBdebug\fR (or the environment variable \fBCCACHE_DEBUG\fR); see debugging for more information\&. Another way of keeping track of what is happening is to check the output of \fBccache \-s\fR\&.
.SS "Performance"
.sp
ccache has been written to perform well out of the box, but sometimes you may have to do some adjustments of how you use the compiler and ccache in order to improve performance\&.
There are no reported issues about ccache producing broken object files reproducibly\&. That doesn\(cqt mean it can\(cqt happen, so if you find a repeatable case, please report it\&.
.SH "MORE INFORMATION"
.sp
-Credits, mailing list information, bug reporting instructions, source code, etc, can be found on ccache\(cqs web site: https://ccache\&.samba\&.org\&.
+Credits, mailing list information, bug reporting instructions, source code, etc, can be found on ccache\(cqs web site: https://ccache\&.dev\&.
.SH "AUTHOR"
.sp
-ccache was originally written by Andrew Tridgell and is currently developed and maintained by Joel Rosdahl\&. See AUTHORS\&.txt or AUTHORS\&.html and https://ccache\&.samba\&.org/credits\&.html for a list of contributors\&.
+ccache was originally written by Andrew Tridgell and is currently developed and maintained by Joel Rosdahl\&. See AUTHORS\&.txt or AUTHORS\&.html and https://ccache\&.dev/credits\&.html for a list of contributors\&.
" " MYNAME " compiler [compiler options]\n"
" compiler [compiler options] (via symbolic link)\n"
"\n"
- "Options:\n"
- " -c, --cleanup delete old files and recalculate size counters\n"
- " (normally not needed as this is done automatically)\n"
- " -C, --clear clear the cache completely (except configuration)\n"
- " -F, --max-files=N set maximum number of files in cache to N (use 0 for\n"
- " no limit)\n"
- " -k, --get-config=K get the value of the configuration key K\n"
- " -M, --max-size=SIZE set maximum size of cache to SIZE (use 0 for no\n"
- " limit); available suffixes: k, M, G, T (decimal) and\n"
- " Ki, Mi, Gi, Ti (binary); default suffix: G\n"
- " -o, --set-config=K=V set configuration key K to value V\n"
- " -p, --print-config print current configuration options\n"
- " -s, --show-stats show statistics summary\n"
- " -z, --zero-stats zero statistics counters\n"
+ "Common options:\n"
+ " -c, --cleanup delete old files and recalculate size counters\n"
+ " (normally not needed as this is done\n"
+ " automatically)\n"
+ " -C, --clear clear the cache completely (except configuration)\n"
+ " -F, --max-files=N set maximum number of files in cache to N (use 0\n"
+ " for no limit)\n"
+ " -M, --max-size=SIZE set maximum size of cache to SIZE (use 0 for no\n"
+ " limit); available suffixes: k, M, G, T (decimal)\n"
+ " and Ki, Mi, Gi, Ti (binary); default suffix: G\n"
+ " -p, --show-config show current configuration options in\n"
+ " human-readable format\n"
+ " -s, --show-stats show summary of configuration and statistics\n"
+ " counters in human-readable format\n"
+ " -z, --zero-stats zero statistics counters\n"
"\n"
- " -h, --help print this help text\n"
- " -V, --version print version and copyright information\n"
+ " -h, --help print this help text\n"
+ " -V, --version print version and copyright information\n"
"\n"
- "See also <https://ccache.samba.org>.\n";
+ "Options for scripting or debugging:\n"
+ " --dump-manifest=PATH dump manifest file at PATH in text format\n"
+ " -k, --get-config=K print the value of configuration key K\n"
+ " --hash-file=PATH print the hash (<MD4>-<size>) of the file at PATH\n"
+ " --print-stats print statistics counter IDs and corresponding\n"
+ " values in machine-parsable format\n"
+ " -o, --set-config=K=V set configuration item K to value V\n"
+ "\n"
+ "See also <https://ccache.dev>.\n";
// Global configuration data.
struct conf *conf = NULL;
// Is the compiler being asked to output debug info?
static bool generating_debuginfo;
+// Is the compiler being asked to output debug info on level 3?
+static bool generating_debuginfo_level_3;
+
// Is the compiler being asked to output dependencies?
static bool generating_dependencies;
}
static void
-dump_log_buffer_exitfn(void *context)
+dump_debug_log_buffer_exitfn(void *context)
{
if (!conf->debug) {
return;
}
char *path = format("%s.ccache-log", (const char *)context);
- cc_dump_log_buffer(path);
+ cc_dump_debug_log_buffer(path);
free(path);
}
char *path = format("%s.ccache-input-%c", obj_path, type);
FILE *debug_binary_file = fopen(path, "wb");
- hash_enable_debug(hash, section_name, debug_binary_file, debug_text_file);
+ if (debug_binary_file) {
+ hash_enable_debug(hash, section_name, debug_binary_file, debug_text_file);
+ exitfn_add(fclose_exitfn, debug_binary_file);
+ } else {
+ cc_log("Failed to open %s: %s", path, strerror(errno));
+ }
free(path);
- exitfn_add(fclose_exitfn, debug_binary_file);
}
static enum guessed_compiler
if (depend_mode_hash) {
hash_delimiter(depend_mode_hash, "include");
- hash_buffer(depend_mode_hash, h->hash, sizeof(h->hash));
+ char *result = format_hash_as_string(h->hash, h->size);
+ hash_string(depend_mode_hash, result);
+ free(result);
}
}
if (str_endswith(token, ":") || str_eq(token, "\\")) {
continue;
}
- remember_include_file(x_strdup(token), hash, false, hash);
+ if (!has_absolute_include_headers) {
+ has_absolute_include_headers = is_absolute_path(token);
+ }
+ char *path = make_relative_path(x_strdup(token));
+ remember_include_file(path, hash, false, hash);
}
}
return result;
}
-// Helper method for copy_file_to_cache and move_file_to_cache_same_fs.
+// Helper function 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)
{
do_copy_or_move_file_to_cache(source, dest, false);
}
-// Copy or link a file from the cache.
+// Helper function for get_file_from_cache and copy_file_from_cache.
static void
-get_file_from_cache(const char *source, const char *dest)
+do_copy_or_link_file_from_cache(const char *source, const char *dest, bool copy)
{
int ret;
- bool do_link = conf->hard_link && !file_is_compressed(source);
+ bool do_link = !copy && conf->hard_link && !file_is_compressed(source);
if (do_link) {
x_unlink(dest);
ret = link(source, dest);
cc_log("Created from cache: %s -> %s", source, dest);
}
+// Copy or link a file from the cache.
+//
+// source must be a path in the cache (see get_path_in_cache). dest does not
+// have to be on the same file system as source.
+//
+// An attempt will be made to hard link source to dest if conf->hard_link is
+// true and conf->compression is false, otherwise copy. dest will be compressed
+// if conf->compression is true.
+static void
+get_file_from_cache(const char *source, const char *dest)
+{
+ do_copy_or_link_file_from_cache(source, dest, false);
+}
+
+// Copy a file from the cache.
+static void
+copy_file_from_cache(const char *source, const char *dest)
+{
+ do_copy_or_link_file_from_cache(source, dest, true);
+}
+
// Send cached stderr, if any, to stderr.
static void
send_cached_stderr(void)
if (stat(manifest_path, &st) == 0) {
old_size = file_size(&st);
}
+ MTR_BEGIN("manifest", "manifest_put");
if (manifest_put(manifest_path, cached_obj_hash, included_files)) {
cc_log("Added object file hash to %s", manifest_path);
- update_mtime(manifest_path);
if (x_stat(manifest_path, &st) == 0) {
stats_update_size(file_size(&st) - old_size, old_size == 0 ? 1 : 0);
}
} else {
cc_log("Failed to add object file hash to %s", manifest_path);
}
+ MTR_END("manifest", "manifest_put");
}
static void
}
cc_log("Running real compiler");
+ MTR_BEGIN("execute", "compiler");
char *tmp_stdout;
int tmp_stdout_fd;
char *tmp_stderr;
depend_mode_args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
args_free(depend_mode_args);
}
+ MTR_END("execute", "compiler");
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);
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 (generating_dependencies) {
+ use_relative_paths_in_depfile(output_dep);
}
if (stat(output_obj, &st) != 0) {
} else {
copy_file_to_cache(tmp_stderr, cached_stderr);
}
- } else {
+ } else if (conf->recache) {
+ // If recaching, we need to remove any previous .stderr.
+ x_unlink(cached_stderr);
+ }
+ if (st.st_size == 0 || conf->depend_mode) {
tmp_unlink(tmp_stderr);
- if (conf->recache) {
- // If recaching, we need to remove any previous .stderr.
- x_unlink(cached_stderr);
- }
}
+ MTR_BEGIN("file", "file_put");
+
copy_file_to_cache(output_obj, cached_obj);
if (generating_dependencies) {
copy_file_to_cache(output_dep, cached_dep);
copy_file_to_cache(output_dwo, cached_dwo);
}
+ MTR_END("file", "file_put");
+
stats_update(STATS_TOCACHE);
// Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can
args_add(args, input_file);
add_prefix(args, conf->prefix_command_cpp);
cc_log("Running preprocessor");
+ MTR_BEGIN("execute", "preprocessor");
status = execute(args->argv, path_stdout_fd, path_stderr_fd, &compiler_pid);
+ MTR_END("execute", "preprocessor");
args_pop(args, args_added);
}
}
}
+ if (using_split_dwarf) {
+ // When using -gsplit-dwarf, object files include a link to the
+ // corresponding .dwo file based on the target object filename, so we need
+ // to include the target filename in the hash to avoid handing out an
+ // object file with an incorrect .dwo link.
+ hash_delimiter(hash, "filename");
+ hash_string(hash, basename(output_obj));
+ }
+
// Possibly hash the coverage data file path.
if (generating_coverage && profile_arcs) {
char *dir = dirname(output_obj);
}
// The -fdebug-prefix-map option may be used in combination with
- // CCACHE_BASEDIR to reuse results across different directories. Skip it
- // from hashing.
+ // CCACHE_BASEDIR to reuse results across different directories. Skip using
+ // the value of the option from hashing but still hash the existence of the
+ // option.
if (str_startswith(args->argv[i], "-fdebug-prefix-map=")) {
+ hash_delimiter(hash, "arg");
+ hash_string(hash, "-fdebug-prefix-map=");
continue;
}
if (str_startswith(args->argv[i], "-ffile-prefix-map=")) {
+ hash_delimiter(hash, "arg");
+ hash_string(hash, "-ffile-prefix-map=");
continue;
}
if (str_startswith(args->argv[i], "-fmacro-prefix-map=")) {
+ hash_delimiter(hash, "arg");
+ hash_string(hash, "-fmacro-prefix-map=");
continue;
}
conf->direct_mode = false;
return NULL;
}
+
char *manifest_name = hash_result(hash);
manifest_path = get_path_in_cache(manifest_name, ".manifest");
free(manifest_name);
+
cc_log("Looking for object file hash in %s", manifest_path);
+ MTR_BEGIN("manifest", "manifest_get");
object_hash = manifest_get(conf, manifest_path);
+ MTR_END("manifest", "manifest_get");
if (object_hash) {
cc_log("Got object file hash from manifest");
+ update_mtime(manifest_path);
} else {
cc_log("Did not find object file hash in manifest");
}
return;
}
+ MTR_BEGIN("cache", "from_cache");
+
// (If mode != FROMCACHE_DIRECT_MODE, the dependency file is created by gcc.)
bool produce_dep_file =
generating_dependencies && mode == FROMCACHE_DIRECT_MODE;
+ MTR_BEGIN("file", "file_get");
+
// Get result from cache.
if (!str_eq(output_obj, "/dev/null")) {
get_file_from_cache(cached_obj, output_obj);
}
}
if (produce_dep_file) {
- get_file_from_cache(cached_dep, output_dep);
+ // Never hardlink the .d file since automake fails to move a foo.d.tmp file
+ // to foo.d if they have the same i-node.
+ copy_file_from_cache(cached_dep, output_dep);
}
if (generating_coverage) {
get_file_from_cache(cached_cov, output_cov);
get_file_from_cache(cached_dia, output_dia);
}
+ MTR_END("file", "file_get");
+
// Update modification timestamps to save files from LRU cleanup. Also gives
// files a sensible mtime when hard-linking.
update_mtime(cached_obj);
break;
}
+ MTR_END("cache", "from_cache");
+
// And exit with the right status code.
x_exit(0);
}
continue;
}
- if (str_eq(argv[i], "-gsplit-dwarf")) {
- cc_log("Enabling caching of dwarf files since -gsplit-dwarf is used");
- using_split_dwarf = true;
- args_add(stripped_args, argv[i]);
- continue;
- }
if (str_startswith(argv[i], "-fdebug-prefix-map=")
|| str_startswith(argv[i], "-ffile-prefix-map=")) {
debug_prefix_maps = x_realloc(
// Debugging is handled specially, so that we know if we can strip line
// number info.
if (str_startswith(argv[i], "-g")) {
- generating_debuginfo = true;
args_add(stripped_args, argv[i]);
- if (conf->unify && !str_eq(argv[i], "-g0")) {
- cc_log("%s used; disabling unify mode", argv[i]);
- conf->unify = false;
- }
- if (str_eq(argv[i], "-g3")) {
- cc_log("%s used; not compiling preprocessed code", argv[i]);
- conf->run_second_cpp = true;
+
+ char last_char = argv[i][strlen(argv[i]) - 1];
+ if (last_char == '0') {
+ // "-g0", "-ggdb0" or similar: All debug information disabled.
+ // "-gsplit-dwarf" is still in effect if given previously, though.
+ generating_debuginfo = false;
+ generating_debuginfo_level_3 = false;
+ } else {
+ generating_debuginfo = true;
+ if (last_char == '3') {
+ generating_debuginfo_level_3 = true;
+ }
+ if (str_eq(argv[i], "-gsplit-dwarf")) {
+ using_split_dwarf = true;
+ }
}
continue;
}
// If an argument isn't a plain file then assume its an option, not an
// input file. This allows us to cope better with unusual compiler options.
+ //
+ // Note that "/dev/null" is an exception that is sometimes used as an input
+ // file when code is testing compiler flags.
struct stat st;
- if (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode)) {
+ if (!str_eq(argv[i], "/dev/null")
+ && (stat(argv[i], &st) != 0 || !S_ISREG(st.st_mode))) {
cc_log("%s is not a regular file, not considering as input file",
argv[i]);
args_add(stripped_args, argv[i]);
}
} // for
+ if (generating_debuginfo && conf->unify) {
+ cc_log("Generating debug info; disabling unify mode");
+ conf->unify = false;
+ }
+
+ if (generating_debuginfo_level_3 && !conf->run_second_cpp) {
+ cc_log("Generating debug info level 3; not compiling preprocessed code");
+ conf->run_second_cpp = true;
+ }
+
// 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.
if (output_is_precompiled_header) {
output_obj = format("%s.gch", input_file);
} else {
+ char extension = found_S_opt ? 's' : 'o';
output_obj = basename(input_file);
char *p = strrchr(output_obj, '.');
- if (!p || !p[1]) {
- cc_log("Badly formed object filename");
- stats_update(STATS_ARGS);
- result = false;
- goto out;
+ if (!p) {
+ reformat(&output_obj, "%s.%c", output_obj, extension);
+ } else if (!p[1]) {
+ reformat(&output_obj, "%s%c", output_obj, extension);
+ } else {
+ p[1] = extension;
+ p[2] = 0;
}
- p[1] = found_S_opt ? 's' : 'o';
- p[2] = 0;
}
}
&& stat(output_obj, &st) == 0
&& !S_ISREG(st.st_mode)) {
cc_log("Not a regular file: %s", output_obj);
- stats_update(STATS_DEVICE);
+ stats_update(STATS_BADOUTPUTFILE);
result = false;
goto out;
}
+ char *output_dir = dirname(output_obj);
+ if (stat(output_dir, &st) != 0 || !S_ISDIR(st.st_mode)) {
+ cc_log("Directory does not exist: %s", output_dir);
+ stats_update(STATS_BADOUTPUTFILE);
+ result = false;
+ free(output_dir);
+ goto out;
+ }
+ free(output_dir);
+
// Some options shouldn't be passed to the real compiler when it compiles
// preprocessed code:
//
fclose(f);
}
+#ifdef MTR_ENABLED
+static void *trace_id;
+static const char *trace_file;
+
+static void
+trace_init(const char *json)
+{
+ trace_file = json;
+ mtr_init(json);
+ char *s = format("%f", time_seconds());
+ MTR_INSTANT_C("", "", "time", s);
+}
+
+static void
+trace_start(const char *tracefile)
+{
+ trace_file = tracefile;
+ MTR_META_PROCESS_NAME(MYNAME);
+ trace_id = (void *) ((long) getpid());
+ MTR_START("program", "ccache", trace_id);
+}
+
+static void
+trace_stop(void)
+{
+ const char *json = format("%s%s", output_obj, ".ccache-trace");
+ MTR_FINISH("program", "ccache", trace_id);
+ mtr_flush();
+ mtr_shutdown();
+ move_file(trace_file, json, 0);
+}
+
+static const char *
+tmpdir()
+{
+#ifndef _WIN32
+ const char *tmpdir = getenv("TMPDIR");
+ if (tmpdir != NULL) {
+ return tmpdir;
+ }
+#else
+ static char dirbuf[PATH_MAX];
+ DWORD retval = GetTempPath(PATH_MAX, dirbuf);
+ if (retval > 0 && retval < PATH_MAX) {
+ return dirbuf;
+ }
+#endif
+ return "/tmp";
+}
+
+#endif // MTR_ENABLED
+
// Read config file(s), populate variables, create configuration file in cache
// directory if missing, etc.
static void
initialize(void)
{
+ char *tracefile = getenv("CCACHE_INTERNAL_TRACE");
+ if (tracefile != NULL) {
+#ifdef MTR_ENABLED
+ // We don't have any conf yet, so we can't use temp_dir() here.
+ tracefile = format("%s/trace.%d.json", tmpdir(), (int)getpid());
+
+ trace_init(tracefile);
+#endif
+ }
+
conf_free(conf);
+ MTR_BEGIN("config", "conf_create");
conf = conf_create();
+ MTR_END("config", "conf_create");
char *errmsg;
char *p = getenv("CCACHE_CONFIGPATH");
primary_config_path = x_strdup(p);
} else {
secondary_config_path = format("%s/ccache.conf", TO_STRING(SYSCONFDIR));
+ MTR_BEGIN("config", "conf_read_secondary");
if (!conf_read(conf, secondary_config_path, &errmsg)) {
if (errno == 0) {
// We could read the file but it contained errors.
// A missing config file in SYSCONFDIR is OK.
free(errmsg);
}
+ MTR_END("config", "conf_read_secondary");
if (str_eq(conf->cache_dir, "")) {
fatal("configuration setting \"cache_dir\" must not be the empty string");
}
bool should_create_initial_config = false;
+ MTR_BEGIN("config", "conf_read_primary");
if (!conf_read(conf, primary_config_path, &errmsg)) {
if (errno == 0) {
// We could read the file but it contained errors.
should_create_initial_config = true;
}
}
+ MTR_END("config", "conf_read_primary");
+ MTR_BEGIN("config", "conf_update_from_environment");
if (!conf_update_from_environment(conf, &errmsg)) {
fatal("%s", errmsg);
}
+ MTR_END("config", "conf_update_from_environment");
if (should_create_initial_config) {
create_initial_config_file(primary_config_path);
if (conf->umask != UINT_MAX) {
umask(conf->umask);
}
+
+ if (tracefile != NULL) {
+#ifdef MTR_ENABLED
+ trace_start(tracefile);
+ exitfn_add_nullary(trace_stop);
+#else
+ cc_log("Error: tracing is not enabled!");
+#endif
+ }
}
// Reset the global state. Used by the test suite.
}
has_absolute_include_headers = false;
generating_debuginfo = false;
+ generating_debuginfo_level_3 = false;
generating_dependencies = false;
generating_coverage = false;
generating_stackusage = false;
set_up_signal_handlers();
#endif
+ // Needed for portability when using localtime_r.
+ tzset();
+
orig_args = args_init(argc, argv);
initialize();
+ MTR_BEGIN("main", "find_compiler");
find_compiler(argv);
+ MTR_END("main", "find_compiler");
+ MTR_BEGIN("main", "clean_up_internal_tempdir");
if (str_eq(conf->temporary_dir, "")) {
clean_up_internal_tempdir();
}
+ MTR_END("main", "clean_up_internal_tempdir");
if (!str_eq(conf->log_file, "") || conf->debug) {
conf_print_items(conf, configuration_logger, NULL);
failed();
}
+ MTR_BEGIN("main", "set_up_uncached_err");
set_up_uncached_err();
+ MTR_END("main", "set_up_uncached_err");
cc_log_argv("Command line: ", argv);
cc_log("Hostname: %s", get_hostname());
conf->limit_multiple = MIN(MAX(conf->limit_multiple, 0.0), 1.0);
+ MTR_BEGIN("main", "guess_compiler");
guessed_compiler = guess_compiler(orig_args->argv[0]);
+ MTR_END("main", "guess_compiler");
// Arguments (except -E) to send to the preprocessor.
struct args *preprocessor_args;
// Arguments to send to the real compiler.
struct args *compiler_args;
+ MTR_BEGIN("main", "process_args");
if (!cc_process_args(orig_args, &preprocessor_args, &compiler_args)) {
failed();
}
+ MTR_END("main", "process_args");
if (conf->depend_mode
&& (!generating_dependencies || !conf->run_second_cpp || conf->unify)) {
}
cc_log("Object file: %s", output_obj);
+ MTR_META_THREAD_NAME(output_obj);
// Need to dump log buffer as the last exit function to not lose any logs.
- exitfn_add_last(dump_log_buffer_exitfn, output_obj);
+ exitfn_add_last(dump_debug_log_buffer_exitfn, output_obj);
FILE *debug_text_file = NULL;
if (conf->debug) {
char *path = format("%s.ccache-input-text", output_obj);
debug_text_file = fopen(path, "w");
+ if (debug_text_file) {
+ exitfn_add(fclose_exitfn, debug_text_file);
+ } else {
+ cc_log("Failed to open %s: %s", path, strerror(errno));
+ }
free(path);
- exitfn_add(fclose_exitfn, debug_text_file);
}
struct hash *common_hash = hash_init();
init_hash_debug(common_hash, output_obj, 'c', "COMMON", debug_text_file);
+ MTR_BEGIN("hash", "common_hash");
calculate_common_hash(preprocessor_args, common_hash);
+ MTR_END("hash", "common_hash");
// Try to find the hash using the manifest.
struct hash *direct_hash = hash_copy(common_hash);
struct file_hash *object_hash_from_manifest = NULL;
if (conf->direct_mode) {
cc_log("Trying direct lookup");
+ MTR_BEGIN("hash", "direct_hash");
object_hash = calculate_object_hash(preprocessor_args, direct_hash, 1);
+ MTR_END("hash", "direct_hash");
if (object_hash) {
update_cached_result_globals(object_hash);
init_hash_debug(
cpp_hash, output_obj, 'p', "PREPROCESSOR MODE", debug_text_file);
+ MTR_BEGIN("hash", "cpp_hash");
object_hash = calculate_object_hash(preprocessor_args, cpp_hash, 0);
+ MTR_END("hash", "cpp_hash");
if (!object_hash) {
fatal("internal error: object hash from cpp returned NULL");
}
struct hash *depend_mode_hash = conf->depend_mode ? direct_hash : NULL;
// Run real compiler, sending output to cache.
+ MTR_BEGIN("cache", "to_cache");
to_cache(compiler_args, depend_mode_hash);
+ MTR_END("cache", "to_cache");
x_exit(0);
}
{
enum longopts {
DUMP_MANIFEST,
- HASH_FILE
+ HASH_FILE,
+ PRINT_STATS,
};
static const struct option options[] = {
{"cleanup", no_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{"max-files", required_argument, 0, 'F'},
{"max-size", required_argument, 0, 'M'},
- {"print-config", no_argument, 0, 'p'},
+ {"print-stats", no_argument, 0, PRINT_STATS},
{"set-config", required_argument, 0, 'o'},
+ {"show-config", no_argument, 0, 'p'},
{"show-stats", no_argument, 0, 's'},
{"version", no_argument, 0, 'V'},
{"zero-stats", no_argument, 0, 'z'},
break;
}
+ case PRINT_STATS:
+ initialize();
+ stats_print();
+ break;
+
case 'c': // --cleanup
initialize();
clean_up_all(conf);
}
break;
- case 'p': // --print-config
+ case 'p': // --show-config
initialize();
conf_print_items(conf, configuration_printer, stdout);
break;
#include "system.h"
#include "conf.h"
#include "counters.h"
+#include "minitrace.h"
#ifdef __GNUC__
#define ATTR_FORMAT(x, y, z) __attribute__((format (x, y, z)))
STATS_OBSOLETE_MAXFILES = 13,
STATS_OBSOLETE_MAXSIZE = 14,
STATS_SOURCELANG = 15,
- STATS_DEVICE = 16,
+ STATS_BADOUTPUTFILE = 16,
STATS_NOINPUT = 17,
STATS_MULTIPLE = 18,
STATS_CONFTEST = 19,
void cc_log(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
void cc_bulklog(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
void cc_log_argv(const char *prefix, char **argv);
-void cc_dump_log_buffer(const char *path);
+void cc_dump_debug_log_buffer(const char *path);
void fatal(const char *format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
void warn(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
bool parse_size_with_suffix(const char *str, uint64_t *size);
char *x_realpath(const char *path);
char *gnu_getcwd(void);
+#ifndef HAVE_LOCALTIME_R
+struct tm *localtime_r(const time_t *timep, struct tm *result);
+#endif
#ifndef HAVE_STRTOK_R
char *strtok_r(char *str, const char *delim, char **saveptr);
#endif
char *read_text_file(const char *path, size_t size_hint);
char *subst_env_in_string(const char *str, char **errmsg);
void set_cloexec_flag(int fd);
+double time_seconds(void);
// ----------------------------------------------------------------------------
// stats.c
unsigned stats_get_pending(enum stats stat);
void stats_zero(void);
void stats_summary(void);
+void stats_print(void);
void stats_update_size(int64_t size, int files);
void stats_get_obsolete_limits(const char *dir, unsigned *maxfiles,
uint64_t *maxsize);
-// 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
};
static const struct compopt compopts[] = {
+ {"--analyze", TOO_HARD}, // clang
{"--compiler-bindir", AFFECTS_CPP | TAKES_ARG}, // nvcc
{"--libdevice-directory", AFFECTS_CPP | TAKES_ARG}, // nvcc
{"--output-directory", AFFECTS_CPP | TAKES_ARG}, // nvcc
{"-Xclang", TAKES_ARG},
{"-Xlinker", TAKES_ARG},
{"-Xpreprocessor", AFFECTS_CPP | TOO_HARD_DIRECT | TAKES_ARG},
+ {"-analyze", TOO_HARD}, // clang
{"-arch", TAKES_ARG},
{"-aux-info", TAKES_ARG},
{"-b", TAKES_ARG},
{"-fplugin=libcc1plugin", TOO_HARD}, // interaction with GDB
{"-frepo", TOO_HARD},
{"-fworking-directory", AFFECTS_CPP},
+ {"-gtoggle", TOO_HARD},
{"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
{"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
{"-imacros", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH},
#include "envtoconfitems.h"
#include "ccache.h"
+enum handle_conf_result {
+ HANDLE_CONF_OK,
+ HANDLE_CONF_UNKNOWN,
+ HANDLE_CONF_FAIL
+};
+
static const struct conf_item *
find_conf(const char *name)
{
return envtoconfitems_get(name, strlen(name));
}
-static bool
+static enum handle_conf_result
handle_conf_setting(struct conf *conf, const char *key, const char *value,
char **errmsg, bool from_env_variable, bool negate_boolean,
const char *origin)
{
const struct conf_item *item = find_conf(key);
if (!item) {
- *errmsg = format("unknown configuration option \"%s\"", key);
- return false;
+ return HANDLE_CONF_UNKNOWN;
}
if (from_env_variable && item->parser == confitem_parse_bool) {
}
if (!item->parser(value, (char *)conf + item->offset, errmsg)) {
- return false;
+ return HANDLE_CONF_FAIL;
}
if (item->verifier && !item->verifier((char *)conf + item->offset, errmsg)) {
- return false;
+ return HANDLE_CONF_FAIL;
}
out:
conf->item_origins[item->number] = origin;
- return true;
+ return HANDLE_CONF_OK;
}
static bool
char *key;
char *value;
char *errmsg2;
+ enum handle_conf_result hcr = HANDLE_CONF_OK;
bool ok = parse_line(buf, &key, &value, &errmsg2);
if (ok && key) { // key == NULL if comment or blank line.
- ok = handle_conf_setting(conf, key, value, &errmsg2, false, false, path);
+ hcr =
+ handle_conf_setting(conf, key, value, &errmsg2, false, false, path);
+ ok = hcr != HANDLE_CONF_FAIL; // unknown is OK
}
free(key);
free(value);
continue;
}
- char *errmsg2;
- bool ok = handle_conf_setting(
+ char *errmsg2 = NULL;
+ enum handle_conf_result hcr = handle_conf_setting(
conf, env_to_conf_item->conf_name, q, &errmsg2, true, negate,
"environment");
- if (!ok) {
+ if (hcr != HANDLE_CONF_OK) {
*errmsg = format("%s: %s", key, errmsg2);
free(errmsg2);
free(key);
// Copyright (C) 2002 Andrew Tridgell
-// 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
static void
do_hash_buffer(struct hash *hash, const void *s, size_t len)
{
+ assert(s);
+
mdfour_update(&hash->md, (const unsigned char *)s, len);
if (len > 0 && hash->debug_binary) {
(void) fwrite(s, 1, len, hash->debug_binary);
size_t
hash_input_size(struct hash *hash)
{
- return hash->md.totalN;
+ return hash->md.totalN + hash->md.tail_len;
}
void
unsigned char sum[16];
hash_result_as_bytes(hash, sum);
- return format_hash_as_string(sum, (unsigned) hash->md.totalN);
+ return format_hash_as_string(sum, hash_input_size(hash));
}
void
hash_result_as_bytes(struct hash *hash, unsigned char *out)
{
- mdfour_update(&hash->md, NULL, 0);
mdfour_result(&hash->md, out);
}
// Make sure that the hash sum changes if the (potential) expansion of
// __DATE__ changes.
time_t t = time(NULL);
- struct tm *now = localtime(&t);
+ struct tm now;
+ localtime_r(&t, &now);
cc_log("Found __DATE__ in %s", path);
hash_delimiter(hash, "date");
- hash_int(hash, now->tm_year);
- hash_int(hash, now->tm_mon);
- hash_int(hash, now->tm_mday);
+ hash_int(hash, now.tm_year);
+ hash_int(hash, now.tm_mon);
+ hash_int(hash, now.tm_mday);
}
if (result & HASH_SOURCE_CODE_FOUND_TIME) {
// We don't know for sure that the program actually uses the __TIME__
{".TCC", "c++-header"},
{".cu", "cuda"},
{".ic", "cuda-output"},
- // Fixed form Fortran without preprocessing:
- {".f", "f77"},
- {".for", "f77"},
- {".ftn", "f77"},
- // Fixed form Fortran with traditional preprocessing:
- {".F", "f77-cpp-input"},
- {".FOR", "f77-cpp-input"},
- {".fpp", "f77-cpp-input"},
- {".FPP", "f77-cpp-input"},
- {".FTN", "f77-cpp-input"},
- // Free form Fortran without preprocessing:
-#if 0 // Could generate modules, ignore for now!
- {".f90", "f95"},
- {".f95", "f95"},
- {".f03", "f95"},
- {".f08", "f95"},
-#endif
- // Free form Fortran with traditional preprocessing:
-#if 0 // Could generate modules, ignore for now!
- {".F90", "f95-cpp-input"},
- {".F95", "f95-cpp-input"},
- {".F03", "f95-cpp-input"},
- {".F08", "f95-cpp-input"},
-#endif
{NULL, NULL}
};
{"cuda", "cuda-output"},
{"assembler-with-cpp", "assembler"},
{"assembler", "assembler"},
- {"f77-cpp-input", "f77"},
- {"f77", "f77"},
-#if 0 // Could generate module files, ignore for now!
- {"f95-cpp-input", "f95"},
- {"f95", "f95"},
-#endif
{NULL, NULL}
};
// Copyright (C) 1997-1998 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
md->D = 0x10325476;
md->totalN = 0;
md->tail_len = 0;
- md->finalized = 0;
}
static
void
mdfour_update(struct mdfour *md, const unsigned char *in, size_t n)
{
- if (!in) {
- if (!md->finalized) {
- mdfour_tail(md, md->tail, md->tail_len);
- md->finalized = 1;
- }
- return;
- }
+ assert(in);
uint32_t M[16];
if (md->tail_len) {
void
mdfour_result(struct mdfour *md, unsigned char *out)
{
- copy4(out, md->A);
- copy4(out+4, md->B);
- copy4(out+8, md->C);
- copy4(out+12, md->D);
+ struct mdfour result;
+ result.A = md->A;
+ result.B = md->B;
+ result.C = md->C;
+ result.D = md->D;
+ result.totalN = md->totalN;
+ result.tail_len = md->tail_len;
+ memcpy(result.tail, md->tail, result.tail_len);
+
+ mdfour_tail(&result, result.tail, result.tail_len);
+ copy4(out, result.A);
+ copy4(out+4, result.B);
+ copy4(out+8, result.C);
+ copy4(out+12, result.D);
}
struct mdfour {
uint32_t A, B, C, D;
size_t totalN;
- unsigned char tail[64];
size_t tail_len;
- int finalized;
+ unsigned char tail[64];
};
void mdfour_begin(struct mdfour *md);
--- /dev/null
+// minitrace
+// Copyright 2014 by Henrik Rydgård
+// http://www.github.com/hrydgard/minitrace
+// Released under the MIT license.
+
+// See minitrace.h for basic documentation.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+#pragma warning (disable:4996)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#define __thread __declspec(thread)
+#define pthread_mutex_t CRITICAL_SECTION
+#define pthread_mutex_init(a, b) InitializeCriticalSection(a)
+#define pthread_mutex_lock(a) EnterCriticalSection(a)
+#define pthread_mutex_unlock(a) LeaveCriticalSection(a)
+#define pthread_mutex_destroy(a) DeleteCriticalSection(a)
+#else
+#include <signal.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#include "minitrace.h"
+
+#ifdef __GNUC__
+#define ATTR_NORETURN __attribute__((noreturn))
+#else
+#define ATTR_NORETURN
+#endif
+
+#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0])
+
+// Ugh, this struct is already pretty heavy.
+// Will probably need to move arguments to a second buffer to support more than one.
+typedef struct raw_event {
+ const char *name;
+ const char *cat;
+ void *id;
+ int64_t ts;
+ uint32_t pid;
+ uint32_t tid;
+ char ph;
+ mtr_arg_type arg_type;
+ const char *arg_name;
+ union {
+ const char *a_str;
+ int a_int;
+ double a_double;
+ };
+} raw_event_t;
+
+static raw_event_t *buffer;
+static volatile int count;
+static int is_tracing = 0;
+static int64_t time_offset;
+static int first_line = 1;
+static FILE *f;
+static __thread int cur_thread_id; // Thread local storage
+static int cur_process_id;
+static pthread_mutex_t mutex;
+
+#define STRING_POOL_SIZE 100
+static char *str_pool[100];
+
+// Tiny portability layer.
+// Exposes:
+// get_cur_thread_id()
+// get_cur_process_id()
+// mtr_time_s()
+// pthread basics
+#ifdef _WIN32
+static int get_cur_thread_id() {
+ return (int)GetCurrentThreadId();
+}
+static int get_cur_process_id() {
+ return (int)GetCurrentProcessId();
+}
+
+static uint64_t _frequency = 0;
+static uint64_t _starttime = 0;
+double mtr_time_s() {
+ if (_frequency == 0) {
+ QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency);
+ QueryPerformanceCounter((LARGE_INTEGER*)&_starttime);
+ }
+ __int64 time;
+ QueryPerformanceCounter((LARGE_INTEGER*)&time);
+ return ((double) (time - _starttime) / (double) _frequency);
+}
+
+// Ctrl+C handling for Windows console apps
+static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
+ if (is_tracing && fdwCtrlType == CTRL_C_EVENT) {
+ printf("Ctrl-C detected! Flushing trace and shutting down.\n\n");
+ mtr_flush();
+ mtr_shutdown();
+ }
+ ExitProcess(1);
+}
+
+void mtr_register_sigint_handler() {
+ // For console apps:
+ SetConsoleCtrlHandler(&CtrlHandler, TRUE);
+}
+
+#else
+
+static inline int get_cur_thread_id() {
+ return (int)(intptr_t)pthread_self();
+}
+static inline int get_cur_process_id() {
+ return (int)getpid();
+}
+
+#if defined(BLACKBERRY)
+double mtr_time_s() {
+ struct timespec time;
+ clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps
+ return time.tv_sec + time.tv_nsec / 1.0e9;
+}
+#else
+double mtr_time_s() {
+ static time_t start;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ if (start == 0) {
+ start = tv.tv_sec;
+ }
+ tv.tv_sec -= start;
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+}
+#endif // !BLACKBERRY
+
+static void termination_handler(int signum) ATTR_NORETURN;
+static void termination_handler(int signum) {
+ (void) signum;
+ if (is_tracing) {
+ printf("Ctrl-C detected! Flushing trace and shutting down.\n\n");
+ mtr_flush();
+ fwrite("\n]}\n", 1, 4, f);
+ fclose(f);
+ }
+ exit(1);
+}
+
+void mtr_register_sigint_handler() {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ // Avoid altering set-to-be-ignored handlers while registering.
+ if (signal(SIGINT, &termination_handler) == SIG_IGN)
+ signal(SIGINT, SIG_IGN);
+}
+
+#endif
+
+void mtr_init_from_stream(void *stream) {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t));
+ is_tracing = 1;
+ count = 0;
+ f = (FILE *)stream;
+ const char *header = "{\"traceEvents\":[\n";
+ fwrite(header, 1, strlen(header), f);
+ time_offset = (uint64_t)(mtr_time_s() * 1000000);
+ first_line = 1;
+ pthread_mutex_init(&mutex, 0);
+}
+
+void mtr_init(const char *json_file) {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ mtr_init_from_stream(fopen(json_file, "wb"));
+}
+
+void mtr_shutdown() {
+ int i;
+#ifndef MTR_ENABLED
+ return;
+#endif
+ is_tracing = 0;
+ mtr_flush();
+ fwrite("\n]}\n", 1, 4, f);
+ fclose(f);
+ pthread_mutex_destroy(&mutex);
+ f = 0;
+ free(buffer);
+ buffer = 0;
+ for (i = 0; i < STRING_POOL_SIZE; i++) {
+ if (str_pool[i]) {
+ free(str_pool[i]);
+ str_pool[i] = 0;
+ }
+ }
+}
+
+const char *mtr_pool_string(const char *str) {
+ int i;
+ for (i = 0; i < STRING_POOL_SIZE; i++) {
+ if (!str_pool[i]) {
+ str_pool[i] = (char*)malloc(strlen(str) + 1);
+ strcpy(str_pool[i], str);
+ return str_pool[i];
+ } else {
+ if (!strcmp(str, str_pool[i]))
+ return str_pool[i];
+ }
+ }
+ return "string pool full";
+}
+
+void mtr_start() {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ is_tracing = 1;
+}
+
+void mtr_stop() {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ is_tracing = 0;
+}
+
+// TODO: fwrite more than one line at a time.
+void mtr_flush() {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ int i = 0;
+ char linebuf[1024];
+ char arg_buf[1024];
+ char id_buf[256];
+ // We have to lock while flushing. So we really should avoid flushing as much as possible.
+
+
+ pthread_mutex_lock(&mutex);
+ int old_tracing = is_tracing;
+ is_tracing = 0; // Stop logging even if using interlocked increments instead of the mutex. Can cause data loss.
+
+ for (i = 0; i < count; i++) {
+ raw_event_t *raw = &buffer[i];
+ int len;
+ switch (raw->arg_type) {
+ case MTR_ARG_TYPE_INT:
+ snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":%i", raw->arg_name, raw->a_int);
+ break;
+ case MTR_ARG_TYPE_STRING_CONST:
+ snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str);
+ break;
+ case MTR_ARG_TYPE_STRING_COPY:
+ if (strlen(raw->a_str) > 700) {
+ snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%.*s\"", raw->arg_name, 700, raw->a_str);
+ } else {
+ snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str);
+ }
+ break;
+ case MTR_ARG_TYPE_NONE:
+ arg_buf[0] = '\0';
+ break;
+ }
+ if (raw->id) {
+ switch (raw->ph) {
+ case 'S':
+ case 'T':
+ case 'F':
+ // TODO: Support full 64-bit pointers
+ snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"id\":\"0x%08x\"", (uint32_t)(uintptr_t)raw->id);
+ break;
+ case 'X':
+ snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"dur\":%i", (int)raw->a_double);
+ break;
+ }
+ } else {
+ id_buf[0] = 0;
+ }
+ const char *cat = raw->cat;
+#ifdef _WIN32
+ // On Windows, we often end up with backslashes in category.
+ char temp[256];
+ {
+ int len = (int)strlen(cat);
+ int i;
+ if (len > 255) len = 255;
+ for (i = 0; i < len; i++) {
+ temp[i] = cat[i] == '\\' ? '/' : cat[i];
+ }
+ temp[len] = 0;
+ cat = temp;
+ }
+#endif
+
+ len = snprintf(linebuf, ARRAY_SIZE(linebuf), "%s{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"name\":\"%s\",\"args\":{%s}%s}",
+ first_line ? "" : ",\n",
+ cat, raw->pid, raw->tid, raw->ts - time_offset, raw->ph, raw->name, arg_buf, id_buf);
+ fwrite(linebuf, 1, len, f);
+ first_line = 0;
+ }
+ count = 0;
+ is_tracing = old_tracing;
+ pthread_mutex_unlock(&mutex);
+}
+
+void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id) {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ if (!is_tracing || count >= INTERNAL_MINITRACE_BUFFER_SIZE)
+ return;
+ double ts = mtr_time_s();
+ if (!cur_thread_id) {
+ cur_thread_id = get_cur_thread_id();
+ }
+ if (!cur_process_id) {
+ cur_process_id = get_cur_process_id();
+ }
+
+#if 0 && _WIN32 // This should work, feel free to enable if you're adventurous and need performance.
+ int bufPos = InterlockedExchangeAdd((LONG volatile *)&count, 1);
+ raw_event_t *ev = &buffer[bufPos];
+#else
+ pthread_mutex_lock(&mutex);
+ raw_event_t *ev = &buffer[count];
+ count++;
+ pthread_mutex_unlock(&mutex);
+#endif
+
+ ev->cat = category;
+ ev->name = name;
+ ev->id = id;
+ ev->ph = ph;
+ if (ev->ph == 'X') {
+ double x;
+ memcpy(&x, id, sizeof(double));
+ ev->ts = (int64_t)(x * 1000000);
+ ev->a_double = (ts - x) * 1000000;
+ } else {
+ ev->ts = (int64_t)(ts * 1000000);
+ }
+ ev->tid = cur_thread_id;
+ ev->pid = cur_process_id;
+ ev->arg_type = MTR_ARG_TYPE_NONE;
+}
+
+void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value) {
+#ifndef MTR_ENABLED
+ return;
+#endif
+ if (!is_tracing || count >= INTERNAL_MINITRACE_BUFFER_SIZE)
+ return;
+ if (!cur_thread_id) {
+ cur_thread_id = get_cur_thread_id();
+ }
+ if (!cur_process_id) {
+ cur_process_id = get_cur_process_id();
+ }
+ double ts = mtr_time_s();
+
+#if 0 && _WIN32 // This should work, feel free to enable if you're adventurous and need performance.
+ int bufPos = InterlockedExchangeAdd((LONG volatile *)&count, 1);
+ raw_event_t *ev = &buffer[bufPos];
+#else
+ pthread_mutex_lock(&mutex);
+ raw_event_t *ev = &buffer[count];
+ count++;
+ pthread_mutex_unlock(&mutex);
+#endif
+
+ ev->cat = category;
+ ev->name = name;
+ ev->id = id;
+ ev->ts = (int64_t)(ts * 1000000);
+ ev->ph = ph;
+ ev->tid = cur_thread_id;
+ ev->pid = cur_process_id;
+ ev->arg_type = arg_type;
+ ev->arg_name = arg_name;
+ switch (arg_type) {
+ case MTR_ARG_TYPE_INT: ev->a_int = (int)(uintptr_t)arg_value; break;
+ case MTR_ARG_TYPE_STRING_CONST: ev->a_str = (const char*)arg_value; break;
+ case MTR_ARG_TYPE_STRING_COPY: ev->a_str = strdup((const char*)arg_value); break;
+ case MTR_ARG_TYPE_NONE: break;
+ }
+}
+
--- /dev/null
+// Minitrace
+//
+// Copyright 2014 by Henrik Rydgård
+// http://www.github.com/hrydgard/minitrace
+// Released under the MIT license.
+//
+// Ultra-light dependency free library for performance tracing C/C++ applications.
+// Produces traces compatible with Google Chrome's trace viewer.
+// Simply open "about:tracing" in Chrome and load the produced JSON.
+//
+// This contains far less template magic than the original libraries from Chrome
+// because this is meant to be usable from C.
+//
+// See README.md for a tutorial.
+//
+// The trace format is documented here:
+// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
+// More:
+// http://www.altdevblogaday.com/2012/08/21/using-chrometracing-to-view-your-inline-profiling-data/
+
+#ifndef MINITRACE_H
+#define MINITRACE_H
+
+#include <inttypes.h>
+
+// If MTR_ENABLED is not defined, Minitrace does nothing and has near zero overhead.
+// Preferably, set this flag in your build system. If you can't just uncomment this line.
+// #define MTR_ENABLED
+
+// By default, will collect up to 1000000 events, then you must flush.
+// It's recommended that you simply call mtr_flush on a background thread
+// occasionally. It's safe...ish.
+#define INTERNAL_MINITRACE_BUFFER_SIZE 1000000
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Initializes Minitrace. Must be called very early during startup of your executable,
+// before any MTR_ statements.
+void mtr_init(const char *json_file);
+// Same as above, but allows passing in a custom stream (FILE *), as returned by
+// fopen(). It should be opened for writing, preferably in binary mode to avoid
+// processing of line endings (i.e. the "wb" mode).
+void mtr_init_from_stream(void *stream);
+
+// Shuts down minitrace cleanly, flushing the trace buffer.
+void mtr_shutdown(void);
+
+// Lets you enable and disable Minitrace at runtime.
+// May cause strange discontinuities in the output.
+// Minitrace is enabled on startup by default.
+void mtr_start(void);
+void mtr_stop(void);
+
+// Flushes the collected data to disk, clearing the buffer for new data.
+void mtr_flush(void);
+
+// Returns the current time in seconds. Used internally by Minitrace. No caching.
+double mtr_time_s(void);
+
+// Registers a handler that will flush the trace on Ctrl+C.
+// Works on Linux and MacOSX, and in Win32 console applications.
+void mtr_register_sigint_handler(void);
+
+// Utility function that should rarely be used.
+// If str is semi dynamic, store it permanently in a small pool so we don't need to malloc it.
+// The pool fills up fast though and performance isn't great.
+// Returns a fixed string if the pool is full.
+const char *mtr_pool_string(const char *str);
+
+// Commented-out types will be supported in the future.
+typedef enum {
+ MTR_ARG_TYPE_NONE = 0,
+ MTR_ARG_TYPE_INT = 1, // I
+ // MTR_ARG_TYPE_FLOAT = 2, // TODO
+ // MTR_ARG_TYPE_DOUBLE = 3, // TODO
+ MTR_ARG_TYPE_STRING_CONST = 8, // C
+ MTR_ARG_TYPE_STRING_COPY = 9,
+ // MTR_ARG_TYPE_JSON_COPY = 10,
+} mtr_arg_type;
+
+// TODO: Add support for more than one argument (metadata) per event
+// Having more costs speed and memory.
+#define MTR_MAX_ARGS 1
+
+// Only use the macros to call these.
+void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id);
+void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value);
+
+#ifdef MTR_ENABLED
+
+// c - category. Can be filtered by in trace viewer (or at least that's the intention).
+// A good use is to pass __FILE__, there are macros further below that will do it for you.
+// n - name. Pass __FUNCTION__ in most cases, unless you are marking up parts of one.
+
+// Scopes. In C++, use MTR_SCOPE. In C, always match them within the same scope.
+#define MTR_BEGIN(c, n) internal_mtr_raw_event(c, n, 'B', 0)
+#define MTR_END(c, n) internal_mtr_raw_event(c, n, 'E', 0)
+#define MTR_SCOPE(c, n) MTRScopedTrace ____mtr_scope(c, n)
+#define MTR_SCOPE_LIMIT(c, n, l) MTRScopedTraceLimit ____mtr_scope(c, n, l)
+
+// Async events. Can span threads. ID identifies which events to connect in the view.
+#define MTR_START(c, n, id) internal_mtr_raw_event(c, n, 'S', (void *)(id))
+#define MTR_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 'T', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step))
+#define MTR_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'F', (void *)(id))
+
+// Flow events. Like async events, but displayed in a more fancy way in the viewer.
+#define MTR_FLOW_START(c, n, id) internal_mtr_raw_event(c, n, 's', (void *)(id))
+#define MTR_FLOW_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 't', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step))
+#define MTR_FLOW_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'f', (void *)(id))
+
+// The same macros, but with a single named argument which shows up as metadata in the viewer.
+// _I for int.
+// _C is for a const string arg.
+// _S will copy the string, freeing on flush (expensive but sometimes necessary).
+// but required if the string was generated dynamically.
+
+// Note that it's fine to match BEGIN_S with END and BEGIN with END_S, etc.
+#define MTR_BEGIN_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
+#define MTR_END_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
+#define MTR_SCOPE_C(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
+
+#define MTR_BEGIN_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
+#define MTR_END_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
+#define MTR_SCOPE_S(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
+
+#define MTR_BEGIN_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
+#define MTR_END_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
+#define MTR_SCOPE_I(c, n, aname, aintval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
+
+// Instant events. For things with no duration.
+#define MTR_INSTANT(c, n) internal_mtr_raw_event(c, n, 'I', 0)
+#define MTR_INSTANT_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
+#define MTR_INSTANT_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_INT, aname, (void *)(aintval))
+
+// Counters (can't do multi-value counters yet)
+#define MTR_COUNTER(c, n, val) internal_mtr_raw_event_arg(c, n, 'C', 0, MTR_ARG_TYPE_INT, n, (void *)(intptr_t)(val))
+
+// Metadata. Call at the start preferably. Must be const strings.
+
+#define MTR_META_PROCESS_NAME(n) internal_mtr_raw_event_arg("", "process_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
+#define MTR_META_THREAD_NAME(n) internal_mtr_raw_event_arg("", "thread_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
+#define MTR_META_THREAD_SORT_INDEX(i) internal_mtr_raw_event_arg("", "thread_sort_index", 'M', 0, MTR_ARG_TYPE_INT, "sort_index", (void *)(i))
+
+#else
+
+#define MTR_BEGIN(c, n)
+#define MTR_END(c, n)
+#define MTR_SCOPE(c, n)
+#define MTR_START(c, n, id)
+#define MTR_STEP(c, n, id, step)
+#define MTR_FINISH(c, n, id)
+#define MTR_FLOW_START(c, n, id)
+#define MTR_FLOW_STEP(c, n, id, step)
+#define MTR_FLOW_FINISH(c, n, id)
+#define MTR_INSTANT(c, n)
+
+#define MTR_BEGIN_C(c, n, aname, astrval)
+#define MTR_END_C(c, n, aname, astrval)
+#define MTR_SCOPE_C(c, n, aname, astrval)
+
+#define MTR_BEGIN_S(c, n, aname, astrval)
+#define MTR_END_S(c, n, aname, astrval)
+#define MTR_SCOPE_S(c, n, aname, astrval)
+
+#define MTR_BEGIN_I(c, n, aname, aintval)
+#define MTR_END_I(c, n, aname, aintval)
+#define MTR_SCOPE_I(c, n, aname, aintval)
+
+#define MTR_INSTANT(c, n)
+#define MTR_INSTANT_C(c, n, aname, astrval)
+#define MTR_INSTANT_I(c, n, aname, aintval)
+
+// Counters (can't do multi-value counters yet)
+#define MTR_COUNTER(c, n, val)
+
+// Metadata. Call at the start preferably. Must be const strings.
+
+#define MTR_META_PROCESS_NAME(n)
+
+#define MTR_META_THREAD_NAME(n)
+#define MTR_META_THREAD_SORT_INDEX(i)
+
+#endif
+
+// Shortcuts for simple function timing with automatic categories and names.
+
+#define MTR_BEGIN_FUNC() MTR_BEGIN(__FILE__, __FUNCTION__)
+#define MTR_END_FUNC() MTR_END(__FILE__, __FUNCTION__)
+#define MTR_SCOPE_FUNC() MTR_SCOPE(__FILE__, __FUNCTION__)
+#define MTR_INSTANT_FUNC() MTR_INSTANT(__FILE__, __FUNCTION__)
+#define MTR_SCOPE_FUNC_LIMIT_S(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, l)
+#define MTR_SCOPE_FUNC_LIMIT_MS(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, (double)l * 0.000001)
+
+// Same, but with a single argument of the usual types.
+#define MTR_BEGIN_FUNC_S(aname, arg) MTR_BEGIN_S(__FILE__, __FUNCTION__, aname, arg)
+#define MTR_END_FUNC_S(aname, arg) MTR_END_S(__FILE__, __FUNCTION__, aname, arg)
+#define MTR_SCOPE_FUNC_S(aname, arg) MTR_SCOPE_S(__FILE__, __FUNCTION__, aname, arg)
+
+#define MTR_BEGIN_FUNC_C(aname, arg) MTR_BEGIN_C(__FILE__, __FUNCTION__, aname, arg)
+#define MTR_END_FUNC_C(aname, arg) MTR_END_C(__FILE__, __FUNCTION__, aname, arg)
+#define MTR_SCOPE_FUNC_C(aname, arg) MTR_SCOPE_C(__FILE__, __FUNCTION__, aname, arg)
+
+#define MTR_BEGIN_FUNC_I(aname, arg) MTR_BEGIN_I(__FILE__, __FUNCTION__, aname, arg)
+#define MTR_END_FUNC_I(aname, arg) MTR_END_I(__FILE__, __FUNCTION__, aname, arg)
+#define MTR_SCOPE_FUNC_I(aname, arg) MTR_SCOPE_I(__FILE__, __FUNCTION__, aname, arg)
+
+#ifdef __cplusplus
+}
+
+#ifdef MTR_ENABLED
+// These are optimized to use X events (combined B and E). Much easier to do in C++ than in C.
+class MTRScopedTrace {
+public:
+ MTRScopedTrace(const char *category, const char *name)
+ : category_(category), name_(name) {
+ start_time_ = mtr_time_s();
+ }
+ ~MTRScopedTrace() {
+ internal_mtr_raw_event(category_, name_, 'X', &start_time_);
+ }
+
+private:
+ const char *category_;
+ const char *name_;
+ double start_time_;
+};
+
+// Only outputs a block if execution time exceeded the limit.
+// TODO: This will effectively call mtr_time_s twice at the end, which is bad.
+class MTRScopedTraceLimit {
+public:
+ MTRScopedTraceLimit(const char *category, const char *name, double limit_s)
+ : category_(category), name_(name), limit_(limit_s) {
+ start_time_ = mtr_time_s();
+ }
+ ~MTRScopedTraceLimit() {
+ double end_time = mtr_time_s();
+ if (end_time - start_time_ >= limit_) {
+ internal_mtr_raw_event(category_, name_, 'X', &start_time_);
+ }
+ }
+
+private:
+ const char *category_;
+ const char *name_;
+ double start_time_;
+ double limit_;
+};
+
+class MTRScopedTraceArg {
+public:
+ MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value)
+ : category_(category), name_(name) {
+ internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value);
+ }
+ ~MTRScopedTraceArg() {
+ internal_mtr_raw_event(category_, name_, 'E', 0);
+ }
+
+private:
+ const char *category_;
+ const char *name_;
+};
+#endif
+
+#endif
+
+#endif
// Copyright (C) 2002-2004 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
// Statistics fields in display order.
static struct {
enum stats stat;
- const char *message;
+ const char *id; // for --print-stats
+ const char *message; // for --show-stats
format_fn *format_fn; // NULL -> use plain integer format
unsigned flags;
} stats_info[] = {
{
STATS_ZEROTIMESTAMP,
+ "stats_zeroed_timestamp",
"stats zeroed",
format_timestamp,
FLAG_ALWAYS
},
{
STATS_CACHEHIT_DIR,
+ "direct_cache_hit",
"cache hit (direct)",
NULL,
FLAG_ALWAYS
},
{
STATS_CACHEHIT_CPP,
+ "preprocessed_cache_hit",
"cache hit (preprocessed)",
NULL,
FLAG_ALWAYS
},
{
STATS_TOCACHE,
+ "cache_miss",
"cache miss",
NULL,
FLAG_ALWAYS
},
{
STATS_LINK,
+ "called_for_link",
"called for link",
NULL,
0
},
{
STATS_PREPROCESSING,
+ "called_for_preprocessing",
"called for preprocessing",
NULL,
0
},
{
STATS_MULTIPLE,
+ "multiple_source_files",
"multiple source files",
NULL,
0
},
{
STATS_STDOUT,
+ "compiler_produced_stdout",
"compiler produced stdout",
NULL,
0
},
{
STATS_NOOUTPUT,
+ "compiler_produced_no_output",
"compiler produced no output",
NULL,
0
},
{
STATS_EMPTYOUTPUT,
+ "compiler_produced_empty_output",
"compiler produced empty output",
NULL,
0
},
{
STATS_STATUS,
+ "compile_failed",
"compile failed",
NULL,
0
},
{
STATS_ERROR,
+ "internal_error",
"ccache internal error",
NULL,
0
},
{
STATS_PREPROCESSOR,
+ "preprocessor_error",
"preprocessor error",
NULL,
0
},
{
STATS_CANTUSEPCH,
+ "could_not_use_precompiled_header",
"can't use precompiled header",
NULL,
0
},
{
STATS_COMPILER,
+ "could_not_find_compiler",
"couldn't find the compiler",
NULL,
0
},
{
STATS_MISSING,
+ "missing_cache_file",
"cache file missing",
NULL,
0
},
{
STATS_ARGS,
+ "bad_compiler_arguments",
"bad compiler arguments",
NULL,
0
},
{
STATS_SOURCELANG,
+ "unsupported_source_language",
"unsupported source language",
NULL,
0
},
{
STATS_COMPCHECK,
+ "compiler_check_failed",
"compiler check failed",
NULL,
0
},
{
STATS_CONFTEST,
+ "autoconf_test",
"autoconf compile/link",
NULL,
0
},
{
STATS_UNSUPPORTED_OPTION,
+ "unsupported_compiler_option",
"unsupported compiler option",
NULL,
0
},
{
STATS_UNSUPPORTED_DIRECTIVE,
+ "unsupported_code_directive",
"unsupported code directive",
NULL,
0
},
{
STATS_OUTSTDOUT,
+ "output_to_stdout",
"output to stdout",
NULL,
0
},
{
- STATS_DEVICE,
- "output to a non-regular file",
+ STATS_BADOUTPUTFILE,
+ "bad_output_file",
+ "could not write to output file",
NULL,
0
},
{
STATS_NOINPUT,
+ "no_input_file",
"no input file",
NULL,
0
},
{
STATS_BADEXTRAFILE,
+ "error_hashing_extra_file",
"error hashing extra file",
NULL,
0
},
{
STATS_NUMCLEANUPS,
+ "cleanups_performed",
"cleanups performed",
NULL,
FLAG_ALWAYS
},
{
STATS_NUMFILES,
+ "files_in_cache",
"files in cache",
NULL,
FLAG_NOZERO|FLAG_ALWAYS
},
{
STATS_TOTALSIZE,
+ "cache_size_kibibyte",
"cache size",
format_size_times_1024,
FLAG_NOZERO|FLAG_ALWAYS
{
STATS_OBSOLETE_MAXFILES,
"OBSOLETE",
+ "OBSOLETE",
NULL,
FLAG_NOZERO|FLAG_NEVER
},
{
STATS_OBSOLETE_MAXSIZE,
"OBSOLETE",
+ "OBSOLETE",
NULL,
FLAG_NOZERO|FLAG_NEVER
},
STATS_NONE,
NULL,
NULL,
+ NULL,
0
}
};
format_timestamp(uint64_t timestamp)
{
if (timestamp > 0) {
- struct tm *tm = localtime((time_t *)×tamp);
+ struct tm tm;
+ localtime_r((time_t *)×tamp, &tm);
char buffer[100];
- strftime(buffer, sizeof(buffer), "%c", tm);
+ strftime(buffer, sizeof(buffer), "%c", &tm);
return format(" %s", buffer);
} else {
return NULL;
}
}
+static double
+stats_hit_rate(struct counters *counters)
+{
+ unsigned direct = counters->data[STATS_CACHEHIT_DIR];
+ unsigned preprocessed = counters->data[STATS_CACHEHIT_CPP];
+ unsigned hit = direct + preprocessed;
+ unsigned miss = counters->data[STATS_TOCACHE];
+ unsigned total = hit + miss;
+ return total > 0 ? (100.0 * hit) / total : 0.0;
+}
+
+static void
+stats_collect(struct counters *counters, time_t *last_updated)
+{
+ struct stat st;
+ unsigned zero_timestamp = 0;
+
+ *last_updated = 0;
+
+ // Add up the stats in each directory.
+ for (int dir = -1; dir <= 0xF; dir++) {
+ char *fname;
+
+ if (dir == -1) {
+ fname = format("%s/stats", conf->cache_dir);
+ } else {
+ fname = format("%s/%1x/stats", conf->cache_dir, dir);
+ }
+
+ counters->data[STATS_ZEROTIMESTAMP] = 0; // Don't add
+ stats_read(fname, counters);
+ zero_timestamp = MAX(counters->data[STATS_ZEROTIMESTAMP], zero_timestamp);
+ if (stat(fname, &st) == 0 && st.st_mtime > *last_updated) {
+ *last_updated = st.st_mtime;
+ }
+ free(fname);
+ }
+
+ counters->data[STATS_ZEROTIMESTAMP] = zero_timestamp;
+}
+
// Record that a number of bytes and files have been added to the cache. Size
// is in bytes.
void
void
stats_summary(void)
{
- struct counters *counters = counters_init(STATS_END);
- time_t updated = 0;
- struct stat st;
- unsigned zero_timestamp = 0;
-
assert(conf);
- // Add up the stats in each directory.
- for (int dir = -1; dir <= 0xF; dir++) {
- char *fname;
-
- if (dir == -1) {
- fname = format("%s/stats", conf->cache_dir);
- } else {
- fname = format("%s/%1x/stats", conf->cache_dir, dir);
- }
-
- counters->data[STATS_ZEROTIMESTAMP] = 0; // Don't add
- stats_read(fname, counters);
- zero_timestamp = MAX(counters->data[STATS_ZEROTIMESTAMP], zero_timestamp);
- if (stat(fname, &st) == 0 && st.st_mtime > updated) {
- updated = st.st_mtime;
- }
- free(fname);
- }
-
- counters->data[STATS_ZEROTIMESTAMP] = zero_timestamp;
+ struct counters *counters = counters_init(STATS_END);
+ time_t last_updated;
+ stats_collect(counters, &last_updated);
printf("cache directory %s\n", conf->cache_dir);
printf("primary config %s\n",
primary_config_path ? primary_config_path : "");
printf("secondary config (readonly) %s\n",
secondary_config_path ? secondary_config_path : "");
- if (updated) {
- struct tm *tm = localtime(&updated);
+ if (last_updated > 0) {
+ struct tm tm;
+ localtime_r(&last_updated, &tm);
char timestamp[100];
- strftime(timestamp, sizeof(timestamp), "%c", tm);
+ strftime(timestamp, sizeof(timestamp), "%c", &tm);
printf("stats updated %s\n", timestamp);
}
}
if (stat == STATS_TOCACHE) {
- unsigned direct = counters->data[STATS_CACHEHIT_DIR];
- unsigned preprocessed = counters->data[STATS_CACHEHIT_CPP];
- unsigned hit = direct + preprocessed;
- unsigned miss = counters->data[STATS_TOCACHE];
- unsigned total = hit + miss;
- double percent = total > 0 ? (100.0 * hit) / total : 0.0;
+ double percent = stats_hit_rate(counters);
printf("cache hit rate %6.2f %%\n", percent);
}
}
counters_free(counters);
}
+// Print machine-parsable (tab-separated) statistics counters.
+void
+stats_print(void)
+{
+ assert(conf);
+
+ struct counters *counters = counters_init(STATS_END);
+ time_t last_updated;
+ stats_collect(counters, &last_updated);
+
+ printf("stats_updated_timestamp\t%llu\n", (unsigned long long)last_updated);
+
+ for (int i = 0; stats_info[i].message; i++) {
+ if (!(stats_info[i].flags & FLAG_NEVER)) {
+ printf("%s\t%u\n", stats_info[i].id, counters->data[stats_info[i].stat]);
+ }
+ }
+
+ counters_free(counters);
+}
+
// Zero all the stats structures.
void
stats_zero(void)
// Copyright (C) 2002 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
}
len = 0;
}
- hash_buffer(hash, NULL, 0);
return;
}
// Copyright (C) 2002 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
#include <tchar.h>
#endif
+// Destination for conf->log_file.
static FILE *logfile;
-static char *logbuffer;
-static size_t logbufsize;
-static size_t logsize;
-#define LOGBUFSIZ 1024
+// Buffer used for logs in conf->debug mode.
+static char *debug_log_buffer;
+
+// Allocated debug_log_buffer size.
+static size_t debug_log_buffer_capacity;
+
+// The amount of log data stored in debug_log_buffer.
+static size_t debug_log_size;
+
+#define DEBUG_LOG_BUFFER_MARGIN 1024
static bool
init_log(void)
{
extern struct conf *conf;
- if (logbuffer || logfile) {
+ if (debug_log_buffer || logfile) {
return true;
}
assert(conf);
if (conf->debug) {
- logbufsize = LOGBUFSIZ;
- logbuffer = x_malloc(logbufsize);
- logsize = 0;
+ debug_log_buffer_capacity = DEBUG_LOG_BUFFER_MARGIN;
+ debug_log_buffer = x_malloc(debug_log_buffer_capacity);
+ debug_log_size = 0;
}
if (str_eq(conf->log_file, "")) {
return conf->debug;
}
static void
-append_log(const char *s, size_t len)
+append_to_debug_log(const char *s, size_t len)
{
- assert(logbuffer);
- if (logsize + len + 1 > logbufsize) {
- logbufsize = logbufsize + len + 1 + LOGBUFSIZ;
- logbuffer = x_realloc(logbuffer, logbufsize);
+ assert(debug_log_buffer);
+ if (debug_log_size + len + 1 > debug_log_buffer_capacity) {
+ debug_log_buffer_capacity += len + 1 + DEBUG_LOG_BUFFER_MARGIN;
+ debug_log_buffer = x_realloc(debug_log_buffer, debug_log_buffer_capacity);
}
- memcpy(logbuffer + logsize, s, len);
- logsize += len;
+ memcpy(debug_log_buffer + debug_log_size, s, len);
+ debug_log_size += len;
}
static void
#ifdef HAVE_GETTIMEOFDAY
if (log_updated_time) {
char timestamp[100];
- struct tm *tm;
+ struct tm tm;
struct timeval tv;
gettimeofday(&tv, NULL);
#ifdef __MINGW64_VERSION_MAJOR
- tm = localtime((time_t *)&tv.tv_sec);
+ localtime_r((time_t *)&tv.tv_sec, &tm);
#else
- tm = localtime(&tv.tv_sec);
+ localtime_r(&tv.tv_sec, &tm);
#endif
- strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", tm);
+ strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &tm);
snprintf(prefix, sizeof(prefix),
"[%s.%06d %-5d] ", timestamp, (int)tv.tv_usec, (int)getpid());
}
if (logfile) {
fputs(prefix, logfile);
}
- if (logbuffer) {
- append_log(prefix, strlen(prefix));
+ if (debug_log_buffer) {
+ append_to_debug_log(prefix, strlen(prefix));
}
}
warn_log_fail();
}
}
- if (logbuffer) {
- char buf[1024];
- size_t len = vsnprintf(buf, sizeof(buf), format, aq);
- append_log(buf, len);
- append_log("\n", 1);
+ if (debug_log_buffer) {
+ char buf[8192];
+ int len = vsnprintf(buf, sizeof(buf), format, aq);
+ if (len >= 0) {
+ append_to_debug_log(buf, MIN((size_t)len, sizeof(buf) - 1));
+ append_to_debug_log("\n", 1);
+ }
}
va_end(aq);
}
warn_log_fail();
}
}
- if (logbuffer) {
- append_log(prefix, strlen(prefix));
+ if (debug_log_buffer) {
+ append_to_debug_log(prefix, strlen(prefix));
char *s = format_command(argv);
- append_log(s, strlen(s));
+ append_to_debug_log(s, strlen(s));
free(s);
}
}
// Copy the current log memory buffer to an output file.
void
-cc_dump_log_buffer(const char *path)
+cc_dump_debug_log_buffer(const char *path)
{
FILE *file = fopen(path, "w");
- (void) fwrite(logbuffer, 1, logsize, file);
- fclose(file);
+ if (file) {
+ (void) fwrite(debug_log_buffer, 1, debug_log_size, file);
+ fclose(file);
+ } else {
+ cc_log("Failed to open %s: %s", path, strerror(errno));
+ }
}
// Something went badly wrong!
{
va_list ap;
va_start(ap, format);
- char msg[1000];
+ char msg[8192];
vsnprintf(msg, sizeof(msg), format, ap);
va_end(ap);
}
}
+#ifndef HAVE_LOCALTIME_R
+// localtime_r replacement.
+struct tm *
+localtime_r(const time_t *timep, struct tm *result)
+{
+ struct tm *tm = localtime(timep);
+ *result = *tm;
+ return result;
+}
+#endif
+
#ifndef HAVE_STRTOK_R
// strtok_r replacement.
char *
(void)fd;
#endif
}
+
+double time_seconds(void)
+{
+#ifdef HAVE_GETTIMEOFDAY
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+#else
+ return (double)time(NULL);
+#endif
+}
-extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.6";
+extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7";
# A simple test suite for ccache.
#
# 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 Software
fi
}
-expect_equal_object_files() {
+is_equal_object_files() {
if $HOST_OS_LINUX && $COMPILER_TYPE_CLANG; then
if ! which eu-elfcmp >/dev/null 2>&1; then
test_failed "Please install elfutils to get eu-elfcmp"
else
cmp -s "$1" "$2"
fi
+}
+
+expect_equal_object_files() {
+ is_equal_object_files "$1" "$2"
if [ $? -ne 0 ]; then
test_failed "Objects differ: $1 != $2"
fi
fi
}
+# Verify that $1 is newer than (or same age as) $2.
+expect_file_newer_than() {
+ local newer_file=$1
+ local older_file=$2
+ if [ "$newer_file" -ot "$older_file" ]; then
+ test_failed "$newer_file is older than $older_file"
+ fi
+}
+
run_suite() {
local suite_name=$1
serialize_diagnostics
sanitize_blacklist
debug_prefix_map
+split_dwarf
masquerading
hardlink
direct
expect_stat 'compiler produced stdout' 1
# -------------------------------------------------------------------------
- TEST "Output to a non-regular file"
+ TEST "Output to directory"
mkdir testd
$CCACHE_COMPILE -o testd -c test1.c >/dev/null 2>&1
rmdir testd >/dev/null 2>&1
- expect_stat 'output to a non-regular file' 1
+ expect_stat 'could not write to output file' 1
+
+ # -------------------------------------------------------------------------
+ TEST "Output to file in nonexistent directory"
+
+ mkdir out
+
+ $CCACHE_COMPILE -c test1.c -o out/foo.o
+ expect_stat 'could not write to output file' ""
+ expect_stat 'cache miss' 1
+
+ rm -rf out
+
+ $CCACHE_COMPILE -c test1.c -o out/foo.o 2>/dev/null
+ expect_stat 'could not write to output file' 1
+ expect_stat 'cache miss' 1
+ expect_file_missing out/foo.o
# -------------------------------------------------------------------------
TEST "No input file"
$CCACHE_COMPILE -c -O2 2>/dev/null
expect_stat 'no input file' 1
+ # -------------------------------------------------------------------------
+ TEST "No file extension"
+
+ mkdir src
+ touch src/foo
+
+ $CCACHE_COMPILE -x c -c src/foo
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_file_exists foo.o
+ rm foo.o
+
+ $CCACHE_COMPILE -x c -c src/foo
+ expect_stat 'cache hit (preprocessed)' 1
+ expect_stat 'cache miss' 1
+ expect_file_exists foo.o
+ rm foo.o
+
+ rm -rf src
+
+ # -------------------------------------------------------------------------
+ TEST "Source file ending with dot"
+
+ mkdir src
+ touch src/foo.
+
+ $CCACHE_COMPILE -x c -c src/foo.
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_file_exists foo.o
+ rm foo.o
+
+ $CCACHE_COMPILE -x c -c src/foo.
+ expect_stat 'cache hit (preprocessed)' 1
+ expect_stat 'cache miss' 1
+ expect_file_exists foo.o
+ rm foo.o
+
+ rm -rf src
+
+ # -------------------------------------------------------------------------
+ TEST "Multiple file extensions"
+
+ mkdir src
+ touch src/foo.c.c
+
+ $CCACHE_COMPILE -c src/foo.c.c
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_file_exists foo.c.o
+ rm foo.c.o
+
+ $CCACHE_COMPILE -c src/foo.c.c
+ expect_stat 'cache hit (preprocessed)' 1
+ expect_stat 'cache miss' 1
+ expect_file_exists foo.c.o
+ rm foo.c.o
+
+ rm -rf src
+
# -------------------------------------------------------------------------
TEST "LANG"
expect_stat 'cache hit (preprocessed)' 2
expect_stat 'cache miss' 1
+ # -------------------------------------------------------------------------
+ TEST "Directory is not hashed if using -g -g0"
+
+ mkdir dir1 dir2
+ cp test1.c dir1
+ cp test1.c dir2
+
+ cd dir1
+ $CCACHE_COMPILE -c test1.c -g -g0
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ $CCACHE_COMPILE -c test1.c -g -g0
+ expect_stat 'cache hit (preprocessed)' 1
+ expect_stat 'cache miss' 1
+
+ cd ../dir2
+ $CCACHE_COMPILE -c test1.c -g -g0
+ expect_stat 'cache hit (preprocessed)' 2
+ expect_stat 'cache miss' 1
+
# -------------------------------------------------------------------------
TEST "CCACHE_NOHASHDIR"
expect_stat 'cache miss' 0
expect_stat 'unsupported source language' 1
+ # -------------------------------------------------------------------------
+ TEST "-x c -c /dev/null"
+
+ $CCACHE_COMPILE -x c -c /dev/null -o null.o 2>/dev/null
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+
+ $CCACHE_COMPILE -x c -c /dev/null -o null.o 2>/dev/null
+ expect_stat 'cache hit (preprocessed)' 1
+ expect_stat 'cache miss' 1
+
# -------------------------------------------------------------------------
TEST "-D not hashed"
DEPSFLAGS_CCACHE="-MP -MMD -MF test.d"
}
+set_up_different_sets_of_headers_test() {
+ BASEDIR=$(pwd)
+ BASEDIR1="$BASEDIR/test/dir1"
+ BASEDIR2="$BASEDIR/test/dir2"
+ BASEDIR3="$BASEDIR/test/dir3"
+ BASEDIR4="$BASEDIR/test/dir4"
+
+ mkdir -p $BASEDIR1 $BASEDIR2 $BASEDIR3 $BASEDIR4
+
+ cat <<EOF >$BASEDIR1/test.c
+#include "header.h"
+#include <stdio.h>
+
+void test(){
+#ifdef CHANGE_THAT_AFFECTS_OBJECT_FILE
+printf("with change");
+#else
+printf("no change");
+#endif
+}
+EOF
+ cp -f "$BASEDIR1/test.c" $BASEDIR2
+ cp -f "$BASEDIR1/test.c" $BASEDIR3
+ cp -f "$BASEDIR1/test.c" $BASEDIR4
+
+ cat <<EOF >"$BASEDIR1/header.h"
+void test();
+EOF
+
+ cat <<EOF >"$BASEDIR2/header.h"
+#define CHANGE_THAT_AFFECTS_OBJECT_FILE
+void test();
+EOF
+
+ cat <<EOF >"$BASEDIR3/header.h"
+#define CHANGE_THAT_DOES_NOT_AFFECT_OBJECT_FILE
+void test();
+EOF
+
+ cat <<EOF >"$BASEDIR4/header.h"
+#include "header2.h"
+void test();
+EOF
+ cat <<EOF >"$BASEDIR4/header2.h"
+static void some_function(){};
+EOF
+
+ backdate "$BASEDIR1/header.h" "$BASEDIR1/test.c"
+ backdate "$BASEDIR2/header.h" "$BASEDIR2/test.c"
+ backdate "$BASEDIR3/header.h" "$BASEDIR3/test.c"
+ backdate "$BASEDIR4/header.h" "$BASEDIR4/test.c" "$BASEDIR4/header2.h"
+
+ DEPFLAGS="-MD -MF test.d"
+}
+
+generate_reference_compiler_output() {
+ rm -f *.o *.d
+ $REAL_COMPILER $DEPFLAGS -c -o test.o test.c
+ mv test.o reference_test.o
+ mv test.d reference_test.d
+}
+
SUITE_depend() {
# -------------------------------------------------------------------------
TEST "Base case"
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 miss' 1
expect_stat 'files in cache' 3
+ # -------------------------------------------------------------------------
+ TEST "Dependency file paths converted to relative if CCACHE_BASEDIR specified"
+
+ CCACHE_DEPEND=1 CCACHE_BASEDIR="`pwd`" $CCACHE_COMPILE $DEPSFLAGS_CCACHE -c "`pwd`/test.c"
+ if grep -q "[^.]/test.c" "test.d"; then
+ test_failed "Dependency file does not contain relative path to test.c"
+ fi
+
# -------------------------------------------------------------------------
TEST "stderr from both preprocessor and compiler"
expect_stat 'cache miss' 1
expect_file_content stderr-mf.txt "`cat stderr-baseline.txt`"
+ # -------------------------------------------------------------------------
+ # This test case covers a case in depend mode with unchanged source file
+ # between compilations, but with changed headers. Header contents do not
+ # affect the common hash (by which .manifest is stored in cache), only the
+ # object's hash.
+ #
+ # dir1 is baseline
+ # dir2 has a change in header which affects object file
+ # dir3 has a change in header which does not affect object file
+ # dir4 has an additional include header which should change the dependency file
+ TEST "Different sets of headers for the same source code"
+
+ set_up_different_sets_of_headers_test
+
+ # Compile dir1.
+ cd $BASEDIR1
+
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR1 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ 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
+
+ # Recompile dir1 first time.
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR1 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_stat 'files in cache' 3
+
+ # Compile dir2. dir2 header changes the object file compared to dir1.
+ cd $BASEDIR2
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR2 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 2
+ expect_stat 'files in cache' 5 # 2x .o, 2x .d, 1x manifest
+
+ # Compile dir3. dir3 header change does not change object file compared to
+ # dir1, but ccache still adds an additional .o/.d file in the cache due to
+ # different contents of the header file.
+ cd $BASEDIR3
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR3 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 3
+ expect_stat 'files in cache' 7 # 3x .o, 3x .d, 1x manifest
+
+ # Compile dir4. dir4 header adds a new dependency.
+ cd $BASEDIR4
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR4 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_different_files reference_test.d $BASEDIR1/test.d
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 4
+ expect_stat 'files in cache' 9 # 4x .o, 4x .d, 1x manifest
+
+ # Recompile dir1 second time.
+ cd $BASEDIR1
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR1 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_stat 'cache hit (direct)' 2
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 4
+ expect_stat 'files in cache' 9
+
+ # Recompile dir2.
+ cd $BASEDIR2
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR2 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_stat 'cache hit (direct)' 3
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 4
+ expect_stat 'files in cache' 9
+
+ # Recompile dir3.
+ cd $BASEDIR3
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR3 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_stat 'cache hit (direct)' 4
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 4
+ expect_stat 'files in cache' 9
+
+ # Recompile dir4.
+ cd $BASEDIR4
+ generate_reference_compiler_output
+ CCACHE_DEPEND=1 CCACHE_BASEDIR=$BASEDIR4 $CCACHE_COMPILE $DEPFLAGS -c test.c
+ expect_equal_object_files reference_test.o test.o
+ expect_equal_files reference_test.d test.d
+ expect_different_files reference_test.d $BASEDIR1/test.d
+ expect_stat 'cache hit (direct)' 5
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 4
+ expect_stat 'files in cache' 9
+
+ # -------------------------------------------------------------------------
+
# TODO: Add more test cases (see direct.bash for inspiration)
}
expect_stat 'files in cache' 2 # .o + .manifest
expect_equal_object_files reference_test.o test.o
+ manifest_file=$(find $CCACHE_DIR -name '*.manifest')
+ backdate $manifest_file
+
$CCACHE_COMPILE -c test.c
expect_stat 'cache hit (direct)' 1
expect_stat 'cache hit (preprocessed)' 0
expect_stat 'cache miss' 1
expect_stat 'files in cache' 2
expect_equal_object_files reference_test.o test.o
+ expect_file_newer_than $manifest_file test.c
# -------------------------------------------------------------------------
TEST "Corrupt manifest file"
expect_stat 'cache miss' 2
expect_stat 'files in cache' 2
expect_equal_object_files reference_test1.o test1.o
+
+ # -------------------------------------------------------------------------
+ TEST "Automake depend move"
+
+ unset CCACHE_NODIRECT
+
+ generate_code 1 test1.c
+
+ CCACHE_HARDLINK=1 CCACHE_DEPEND=1 $CCACHE_COMPILE -c -MMD -MF test1.d.tmp test1.c
+ expect_stat 'cache hit (direct)' 0
+ mv test1.d.tmp test1.d || test_failed "first mv failed"
+
+ CCACHE_HARDLINK=1 CCACHE_DEPEND=1 $CCACHE_COMPILE -c -MMD -MF test1.d.tmp test1.c
+ expect_stat 'cache hit (direct)' 1
+ mv test1.d.tmp test1.d || test_failed "second mv failed"
+
}
+++ /dev/null
-SUITE_pch_PROBE() {
- touch pch.h
- if ! $REAL_COMPILER $SYSROOT -fpch-preprocess pch.h 2>/dev/null \
- || [ ! -f pch.h.gch ]; then
- echo "compiler ($($COMPILER --version | head -1)) doesn't support precompiled headers"
- fi
-}
-
-SUITE_pch_SETUP() {
- unset CCACHE_NODIRECT
-
- cat <<EOF >pch.c
-#include "pch.h"
-int main()
-{
- void *p = NULL;
- return 0;
-}
-EOF
- cat <<EOF >pch.h
-#include <stdlib.h>
-EOF
- backdate pch.h
- cat <<EOF >pch2.c
-int main()
-{
- void *p = NULL;
- return 0;
-}
-EOF
-}
-
-SUITE_pch() {
- # Clang and GCC handle precompiled headers similarly, but GCC is much more
- # forgiving with precompiled headers. Both GCC and Clang keep an absolute
- # path reference to the original file except that Clang uses that reference
- # to validate the pch and GCC ignores the reference. Also, Clang has an
- # additional feature: pre-tokenized headers. For these reasons, Clang
- # should be tested differently from GCC. Clang can only use pch or pth
- # headers on the command line and not as an #include statement inside a
- # source file.
-
- if $COMPILER_TYPE_CLANG; then
- pch_suite_clang
- else
- pch_suite_gcc
- fi
-}
-
-pch_suite_gcc() {
- # -------------------------------------------------------------------------
- TEST "Create .gch, -c, no -o, without opt-in"
-
- $CCACHE_COMPILE $SYSROOT -c pch.h
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, no -c, -o, without opt-in"
-
- $CCACHE_COMPILE pch.h -o pch.gch
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, -c, no -o, with opt-in"
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines" $CCACHE_COMPILE $SYSROOT -c pch.h
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- rm pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines" $CCACHE_COMPILE $SYSROOT -c pch.h
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- if [ ! -f pch.h.gch ]; then
- test_failed "pch.h.gch missing"
- fi
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, no -c, -o, with opt-in"
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- if [ ! -f pch.gch ]; then
- test_failed "pch.gch missing"
- fi
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, no -fpch-preprocess, #include"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- $CCACHE_COMPILE $SYSROOT -c pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- # Preprocessor error because GCC can't find the real include file when
- # trying to preprocess:
- expect_stat 'preprocessor error' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, no -fpch-preprocess, -include, no sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- # Must enable sloppy time macros:
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, no -fpch-preprocess, -include, sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, -fpch-preprocess, #include, no sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- # Must enable sloppy time macros:
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, -fpch-preprocess, #include, sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, -fpch-preprocess, #include, file changed"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo "updated" >>pch.h.gch # GCC seems to cope with this...
- backdate pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 2
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, preprocessor mode"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, preprocessor mode, file changed"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
- rm pch.h
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo "updated" >>pch.h.gch # GCC seems to cope with this...
- backdate pch.h.gch
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 2
-
- # -------------------------------------------------------------------------
- TEST "Create and use .gch directory"
-
- mkdir pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -x c-header -c pch.h -o pch.h.gch/foo
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- rm pch.h.gch/foo
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -x c-header -c pch.h -o pch.h.gch/foo
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- if [ ! -f pch.h.gch/foo ]; then
- test_failed "pch.h.gch/foo missing"
- fi
-
- backdate pch.h.gch/foo
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 2
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- echo "updated" >>pch.h.gch/foo # GCC seems to cope with this...
- backdate pch.h.gch/foo
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 2
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 3
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 3
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 3
-}
-
-pch_suite_clang() {
- # -------------------------------------------------------------------------
- TEST "Create .gch, -c, no -o, without opt-in"
-
- $CCACHE_COMPILE $SYSROOT -c pch.h
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, no -c, -o, without opt-in"
-
- $CCACHE_COMPILE pch.h -o pch.gch
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, -c, no -o, with opt-in"
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch.h
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- rm pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch.h
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- if [ ! -f pch.h.gch ]; then
- test_failed "pch.h.gch missing"
- fi
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, no -c, -o, with opt-in"
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- if [ ! -f pch.gch ]; then
- test_failed "pch.gch missing"
- fi
-
- # -------------------------------------------------------------------------
- TEST "Create .gch, include file mtime changed"
-
- backdate test.h
- cat <<EOF >pch2.h
- #include <stdlib.h>
- #include "test.h"
-EOF
-
- # Make sure time_of_compilation is at least one second larger than the ctime
- # of the test.h include, otherwise we might not cache its ctime/mtime.
- sleep 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch2.h
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- touch test.h
- sleep 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch2.h
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- $REAL_COMPILER $SYSROOT -c -include pch2.h pch2.c
- if [ ! -f pch2.o ]; then
- test_failed "pch.o missing"
- fi
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch2.h
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, no -fpch-preprocess, -include, no sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
-
- $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c 2>/dev/null
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- # Must enable sloppy time macros:
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, no -fpch-preprocess, -include, sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, -fpch-preprocess, -include, file changed"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo "updated" >>pch.h.gch # clang seems to cope with this...
- backdate pch.h.gch
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, preprocessor mode"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .gch, preprocessor mode, file changed"
-
- $REAL_COMPILER $SYSROOT -c pch.h
- backdate pch.h.gch
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo "updated" >>pch.h.gch # clang seems to cope with this...
- backdate pch.h.gch
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 2
-
- # -------------------------------------------------------------------------
- TEST "Create .pth, -c, -o"
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch.h -o pch.h.pth
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- rm -f pch.h.pth
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch.h -o pch.h.pth
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
- if [ ! -f pch.h.pth ]; then
- test_failed "pch.h.pth missing"
- fi
-
- # -------------------------------------------------------------------------
- TEST "Use .pth, no -fpch-preprocess, -include, no sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h -o pch.h.pth
- backdate pch.h.pth
-
- $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 0
- # Must enable sloppy time macros:
- expect_stat "can't use precompiled header" 1
-
- # -------------------------------------------------------------------------
- TEST "Use .pth, no -fpch-preprocess, -include, sloppiness"
-
- $REAL_COMPILER $SYSROOT -c pch.h -o pch.h.pth
- backdate pch.h.pth
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h pch2.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .pth, -fpch-preprocess, -include, file changed"
-
- $REAL_COMPILER $SYSROOT -c pch.h -o pch.h.pth
- backdate pch.h.pth
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo "updated" >>pch.h.pth # clang seems to cope with this...
- backdate pch.h.pth
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 1
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- # -------------------------------------------------------------------------
- TEST "Use .pth, preprocessor mode"
-
- $REAL_COMPILER $SYSROOT -c pch.h -o pch.h.pth
- backdate pch.h.pth
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 1
-
- # -------------------------------------------------------------------------
- TEST "Use .pth, preprocessor mode, file changed"
-
- $REAL_COMPILER $SYSROOT -c pch.h -o pch.h.pth
- backdate pch.h.pth
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo "updated" >>pch.h.pth # clang seems to cope with this...
- backdate pch.h.pth
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 2
-
- CCACHE_NODIRECT=1 CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c -include pch.h -fpch-preprocess pch.c
- expect_stat 'cache hit (direct)' 0
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 2
-}
--- /dev/null
+SUITE_split_dwarf_PROBE() {
+ touch test.c
+ if ! $REAL_COMPILER -c -gsplit-dwarf test.c 2>/dev/null || [ ! -e test.dwo ]; then
+ echo "-gsplit-dwarf not supported by compiler"
+ fi
+}
+
+
+SUITE_split_dwarf_SETUP() {
+ unset CCACHE_NODIRECT
+
+ mkdir -p dir1/src dir1/include
+ cat <<EOF >dir1/src/test.c
+#include <stdarg.h>
+#include <test.h>
+EOF
+ cat <<EOF >dir1/include/test.h
+int test;
+EOF
+ cp -r dir1 dir2
+ backdate dir1/include/test.h dir2/include/test.h
+}
+
+SUITE_split_dwarf() {
+ # -------------------------------------------------------------------------
+ TEST "Directory is hashed if using -gsplit-dwarf"
+
+ cd dir1
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -gsplit-dwarf
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -gsplit-dwarf
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 1
+
+ cd ../dir2
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -gsplit-dwarf
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -gsplit-dwarf
+ expect_stat 'cache hit (direct)' 2
+ expect_stat 'cache miss' 2
+
+ # -------------------------------------------------------------------------
+ TEST "Output filename is hashed if using -gsplit-dwarf"
+
+ cd dir1
+
+ $REAL_COMPILER -I$(pwd)/include -c src/test.c -o test.o -gsplit-dwarf
+ mv test.o reference.o
+ mv test.dwo reference.dwo
+
+ $REAL_COMPILER -I$(pwd)/include -c src/test.c -o test.o -gsplit-dwarf
+ mv test.o reference2.o
+ mv test.dwo reference2.dwo
+
+ if is_equal_object_files reference.o reference2.o; then
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -o test.o -gsplit-dwarf
+ expect_equal_object_files reference.o test.o
+ expect_equal_object_files reference.dwo test.dwo
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_stat 'files in cache' 3
+
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -o test.o -gsplit-dwarf
+ expect_equal_object_files reference.o test.o
+ expect_equal_object_files reference.dwo test.dwo
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_stat 'files in cache' 3
+
+ $REAL_COMPILER -I$(pwd)/include -c src/test.c -o test2.o -gsplit-dwarf
+ mv test2.o reference2.o
+ mv test2.dwo reference2.dwo
+
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -o test2.o -gsplit-dwarf
+ expect_equal_object_files reference2.o test2.o
+ expect_equal_object_files reference2.dwo test2.dwo
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 2
+ expect_stat 'files in cache' 6
+
+ $CCACHE_COMPILE -I$(pwd)/include -c src/test.c -o test2.o -gsplit-dwarf
+ expect_equal_object_files reference2.o test2.o
+ expect_equal_object_files reference2.dwo test2.dwo
+ expect_stat 'cache hit (direct)' 2
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 2
+ expect_stat 'files in cache' 6
+ fi
+ # Else: Compiler does not produce stable object file output when compiling
+ # the same source to the same output filename twice (DW_AT_GNU_dwo_id
+ # differs), so we can't verify filename hashing.
+
+ # -------------------------------------------------------------------------
+ TEST "-fdebug-prefix-map and -gsplit-dwarf"
+
+ cd dir1
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE -I$(pwd)/include -gsplit-dwarf -fdebug-prefix-map=$(pwd)=. -c $(pwd)/src/test.c -o $(pwd)/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
+ if objdump_cmd test.o | grep_cmd "$(pwd)" >/dev/null 2>&1; then
+ test_failed "Source dir ($(pwd)) found in test.o"
+ fi
+
+ cd ../dir2
+ CCACHE_BASEDIR=$(pwd) $CCACHE_COMPILE -I$(pwd)/include -gsplit-dwarf -fdebug-prefix-map=$(pwd)=. -c $(pwd)/src/test.c -o $(pwd)/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
+ if objdump_cmd test.o | grep_cmd "$(pwd)" >/dev/null 2>&1; then
+ test_failed "Source dir ($(pwd)) found in test.o"
+ fi
+}
CHECK(compopt_prefix_affects_cpp("-iframework"));
}
+TEST(dash_analyze_too_hard)
+{
+ CHECK(compopt_too_hard("-analyze"));
+}
+
+TEST(dash_dash_analyze_too_hard)
+{
+ CHECK(compopt_too_hard("--analyze"));
+}
+
TEST_SUITE_END
conf_free(conf);
}
-TEST(conf_read_with_bad_config_key)
+TEST(conf_read_with_unknown_config_key)
{
struct conf *conf = conf_create();
char *errmsg;
create_file("ccache.conf", "# Comment\nfoo = bar");
- CHECK(!conf_read(conf, "ccache.conf", &errmsg));
- CHECK_INT_EQ(errno, 0);
- CHECK_STR_EQ_FREE2("ccache.conf:2: unknown configuration option \"foo\"",
- errmsg);
+ CHECK(conf_read(conf, "ccache.conf", &errmsg));
conf_free(conf);
}
CHECK_STR_EQ_FREE2("path = vanilla\nstats = chocolate\n", data);
}
+TEST(conf_set_unknown_option)
+{
+ char *errmsg;
+ char *data;
+
+ create_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
+ CHECKM(!conf_set_value_in_file("ccache.conf", "foo", "bar", &errmsg),
+ errmsg);
+ CHECK_STR_EQ_FREE2("unknown configuration option \"foo\"", errmsg);
+
+ data = read_text_file("ccache.conf", 0);
+ CHECK(data);
+ CHECK_STR_EQ_FREE2("path = chocolate\nstats = chocolate\n", data);
+}
+
TEST(conf_print_existing_value)
{
struct conf *conf = conf_create();
-// 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
}
}
+TEST(hash_result_should_not_alter_state)
+{
+ struct hash *h = hash_init();
+ hash_string(h, "message");
+ free(hash_result(h));
+ hash_string(h, " digest");
+ CHECK_STR_EQ_FREE2("d9130a8164549fe818874806e1c7014b-14", hash_result(h));
+ hash_free(h);
+}
+
TEST(hash_result_should_be_idempotent)
{
struct hash *h = hash_init();