<body class="article">\r
<div id="header">\r
<h1>ccache authors</h1>\r
-<span id="revnumber">version 3.3.4</span>\r
+<span id="revnumber">version 3.3.5</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
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Alfred Landrum <<a href="mailto:alfred.landrum@riverbed.com">alfred.landrum@riverbed.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Anders Björklund <<a href="mailto:anders@psqr.se">anders@psqr.se</a>>\r
+Anders F Björklund <<a href="mailto:anders.f.bjorklund@gmail.com">anders.f.bjorklund@gmail.com</a>>\r
</p>\r
</li>\r
<li>\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
+Andreas Huber <<a href="mailto:andreas.huber@deltaww.com">andreas.huber@deltaww.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andrew Stubbs <<a href="mailto:ams@codesourcery.com">ams@codesourcery.com</a>>\r
+André Klitzing <<a href="mailto:aklitzing@gmail.com">aklitzing@gmail.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Andrew Tridgell <<a href="mailto:tridge@samba.org">tridge@samba.org</a>>\r
+Andrew P Boie <<a href="mailto:andrew.p.boie@intel.com">andrew.p.boie@intel.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-André Klitzing <<a href="mailto:aklitzing@gmail.com">aklitzing@gmail.com</a>>\r
+Andrew Stubbs <<a href="mailto:ams@codesourcery.com">ams@codesourcery.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Andrew Tridgell <<a href="mailto:tridge@samba.org">tridge@samba.org</a>>\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
+Edward Z. Yang <<a href="mailto:ezyang@fb.com">ezyang@fb.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Eric Blau <<a href="mailto:Eric.Blau@tekelec.com">Eric.Blau@tekelec.com</a>>\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
+Geert Bosch <<a href="mailto:geert@mongodb.com">geert@mongodb.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Hongli Lai <<a href="mailto:hongli@phusion.nl">hongli@phusion.nl</a>>\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
-Justin Lebar <<a href="mailto:justin.lebar@gmail.com">justin.lebar@gmail.com</a>>\r
+Jørgen P. Tjernø <<a href="mailto:jorgen@valvesoftware.com">jorgen@valvesoftware.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Jørgen P. Tjernø <<a href="mailto:jorgen@valvesoftware.com">jorgen@valvesoftware.com</a>>\r
+Justin Lebar <<a href="mailto:justin.lebar@gmail.com">justin.lebar@gmail.com</a>>\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
+Oded Shimon <<a href="mailto:oded@istraresearch.com">oded@istraresearch.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+orbitcowboy <<a href="mailto:ettl.martin78@gmail.com">ettl.martin78@gmail.com</a>>\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Orgad Shaneh <<a href="mailto:orgad.shaneh@audiocodes.com">orgad.shaneh@audiocodes.com</a>>\r
</p>\r
</li>\r
</li>\r
<li>\r
<p>\r
-RW <<a href="mailto:fbsd06@mlists.homeunix.com">fbsd06@mlists.homeunix.com</a>>\r
+Ramiro Polla <<a href="mailto:ramiro.polla@gmail.com">ramiro.polla@gmail.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Ramiro Polla <<a href="mailto:ramiro.polla@gmail.com">ramiro.polla@gmail.com</a>>\r
+Robin H. Johnson <<a href="mailto:robbat2@gentoo.org">robbat2@gentoo.org</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Robin H. Johnson <<a href="mailto:robbat2@gentoo.org">robbat2@gentoo.org</a>>\r
+Rolf Bjarne Kvinge <<a href="mailto:rolf@xamarin.com">rolf@xamarin.com</a>>\r
</p>\r
</li>\r
<li>\r
<p>\r
-Rolf Bjarne Kvinge <<a href="mailto:rolf@xamarin.com">rolf@xamarin.com</a>>\r
+RW <<a href="mailto:fbsd06@mlists.homeunix.com">fbsd06@mlists.homeunix.com</a>>\r
</p>\r
</li>\r
<li>\r
</li>\r
<li>\r
<p>\r
-Tor Arne Vestbø <<a href="mailto:torarnv@gmail.com">torarnv@gmail.com</a>>\r
+Tom Hughes <<a href="mailto:tomtheengineer@gmail.com">tomtheengineer@gmail.com</a>>\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
</p>\r
</li>\r
<li>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.3.4<br />\r
+Version 3.3.5<br />\r
Last updated\r
- 2017-02-17 22:27:14 CET\r
+ 2018-01-13 19:31:06 CET\r
</div>\r
</div>\r
</body>\r
ccache is a collective work with contributions from many people, including:
+* Alexey Tourbin <alexey.tourbin@gmail.com>
* Alfred Landrum <alfred.landrum@riverbed.com>
-* Anders Björklund <anders@psqr.se>
+* 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>
-* André Klitzing <aklitzing@gmail.com>
* Bernhard Bauer <bauerb@chromium.org>
* Björn Jacke <bj@sernet.de>
* Bo Rydberg <bolry@hotmail.com>
* Chris AtLee <chris@atlee.ca>
* Clemens Rabe <clemens.rabe@gmail.com>
* David Givone <david@givone.net>
+* Edward Z. Yang <ezyang@fb.com>
* Eric Blau <Eric.Blau@tekelec.com>
* Francois Marier <francois@debian.org>
+* Geert Bosch <geert@mongodb.com>
* Hongli Lai <hongli@phusion.nl>
* Ivan Vaigult <i.vaigult@gmail.com>
* Jiang Jiang <jiangj@opera.com>
* John Basila <jbasila@checkpoint.com>
* John Coiner <john.coiner@amd.com>
* Jon Bernard <jbernard@tuxion.com>
-* Justin Lebar <justin.lebar@gmail.com>
* Jørgen P. Tjernø <jorgen@valvesoftware.com>
+* Justin Lebar <justin.lebar@gmail.com>
* Karl Chen <quarl@cs.berkeley.edu>
* KonaBlend <kona8lend@gmail.com>
* Kovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>
* Neil Mushell <nmushell@bloomberg.net>
* Nick Schultz <nick.schultz@intel.com>
* Norbert Lange <nolange79@gmail.com>
+* Oded Shimon <oded@istraresearch.com>
+* orbitcowboy <ettl.martin78@gmail.com>
* Orgad Shaneh <orgad.shaneh@audiocodes.com>
* Orion Poplawski <orion@cora.nwra.com>
* Owen Mann <owen@mann.org>
* Paul Griffith <paulg@cse.yorku.ca>
* Pavel Boldin <pboldin@cloudlinux.com>
* Philippe Proulx <eeppeliteloop@gmail.com>
-* RW <fbsd06@mlists.homeunix.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>
* Tim Potter <tpot@samba.org>
-* Tor Arne Vestbø <torarnv@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>
<body class="article">\r
<div id="header">\r
<h1>ccache copyright and license</h1>\r
-<span id="revnumber">version 3.3.4</span>\r
+<span id="revnumber">version 3.3.5</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="listingblock">\r
<div class="content">\r
<pre><code> Copyright (C) 2002-2007 Andrew Tridgell\r
- Copyright (C) 2009-2017 Joel Rosdahl</code></pre>\r
+ Copyright (C) 2009-2018 Joel Rosdahl</code></pre>\r
</div></div>\r
</div>\r
</div>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.3.4<br />\r
+Version 3.3.5<br />\r
Last updated\r
- 2017-02-17 22:27:14 CET\r
+ 2018-01-13 19:31:27 CET\r
</div>\r
</div>\r
</body>\r
-------------------------------------------------------------------------------
Copyright (C) 2002-2007 Andrew Tridgell
- Copyright (C) 2009-2017 Joel Rosdahl
+ Copyright (C) 2009-2018 Joel Rosdahl
-------------------------------------------------------------------------------
<body class="article">\r
<div id="header">\r
<h1>CCACHE(1)</h1>\r
-<span id="revnumber">version 3.3.4</span>\r
+<span id="revnumber">version 3.3.5</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>
<dd>\r
<p>\r
Sets the limit when cleaning up. Files are deleted (in LRU order) until the\r
- levels are below the limit. The default is 0.8 (= 80%).\r
+ levels are below the limit. The default is 0.8 (= 80%). See\r
+ <a href="#_automatic_cleanup">AUTOMATIC CLEANUP</a> for more information.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
<dd>\r
<p>\r
This option specifies the maximum number of files to keep in the cache. Use\r
- 0 for no limit (which is the default).\r
+ 0 for no limit (which is the default). See also\r
+ <a href="#_cache_size_management">CACHE SIZE MANAGEMENT</a>.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
<p>\r
This option specifies the maximum size of the cache. Use 0 for no limit.\r
The default value is 5G. Available suffixes: k, M, G, T (decimal) and Ki,\r
- Mi, Gi, Ti (binary). The default suffix is "G".\r
+ Mi, Gi, Ti (binary). The default suffix is "G". See also\r
+ <a href="#_cache_size_management">CACHE SIZE MANAGEMENT</a>.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
<p>\r
ccache normally examines a file’s contents to determine whether it matches\r
the cached version. With this option set, ccache will consider a file as\r
- matching its cached version if the sizes, mtimes and ctimes match.\r
+ matching its cached version if the mtimes and ctimes match.\r
</p>\r
</dd>\r
<dt class="hdlist1">\r
</dt>\r
<dd>\r
<p>\r
- Be sloppy about #defines when precompiling a header file. See\r
+ Be sloppy about <strong>#define</strong>s when precompiling a header file. See\r
<a href="#_precompiled_headers">PRECOMPILED HEADERS</a> for more information.\r
</p>\r
</dd>\r
<div class="sect1">\r
<h2 id="_cache_size_management">Cache size management</h2>\r
<div class="sectionbody">\r
-<div class="paragraph"><p>By default, ccache has a five gigabyte limit on the total size of files in the\r
-cache and no maximum number of files. You can set different limits using the\r
+<div class="paragraph"><p>By default, ccache has a 5 GB limit on the total size of files in the cache and\r
+no limit on the number of files. You can set different limits using the\r
<strong>-M</strong>/<strong>--max-size</strong> and <strong>-F</strong>/<strong>--max-files</strong> options. Use <strong>ccache -s/--show-stats</strong>\r
to see the cache size and the currently configured limits (in addition to other\r
various statistics).</p></div>\r
+<div class="paragraph"><p>Cleanup can be triggered in two different ways: automatic and manual.</p></div>\r
+<div class="sect2">\r
+<h3 id="_automatic_cleanup">Automatic cleanup</h3>\r
+<div class="paragraph"><p>ccache maintains counters for various statistics about the cache, including the\r
+size and number of all cached files. In order to improve performance and reduce\r
+issues with concurrent ccache invocations, there is one statistics file for\r
+each of the sixteen subdirectories in the cache.</p></div>\r
+<div class="paragraph"><p>After a new compilation result has been written to the cache, ccache will\r
+update the size and file number statistics for the subdirectory (one of\r
+sixteen) to which the result was written. Then, if the size counter for said\r
+subdirectory is greater than <strong>max_size / 16</strong> or the file number counter is\r
+greater than <strong>max_files / 16</strong>, automatic cleanup is triggered.</p></div>\r
+<div class="paragraph"><p>When automatic cleanup is triggered for a subdirectory in the cache, ccache\r
+will:</p></div>\r
+<div class="olist arabic"><ol class="arabic">\r
+<li>\r
+<p>\r
+Count all files in the subdirectory and compute their aggregated size.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Remove files in LRU (least recently used) order until the size is at most\r
+ <strong>limit_multiple * max_size / 16</strong> and the number of files is at most\r
+ <strong>limit_multiple * max_files / 16</strong>, where <strong>limit_multiple</strong>, <strong>max_size</strong> and\r
+ <strong>max_files</strong> are configuration settings.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Set the size and file number counters to match the files that were kept.\r
+</p>\r
+</li>\r
+</ol></div>\r
+<div class="paragraph"><p>The reason for removing more files than just those needed to not exceed the max\r
+limits is that a cleanup is a fairly slow operation, so it would not be a good\r
+idea to trigger it often, like after each cache miss.</p></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_manual_cleanup">Manual cleanup</h3>\r
+<div class="paragraph"><p>You can run <strong>ccache -c/--cleanup</strong> to force cleanup of the whole cache, i.e. all\r
+of the sixteen subdirectories. This will recalculate the statistics counters\r
+and make sure that the <strong>max_size</strong> and <strong>max_files</strong> settings are not exceeded.\r
+Note that <strong>limit_multiple</strong> is not taken into account for manual cleanup.</p></div>\r
+</div>\r
</div>\r
</div>\r
<div class="sect1">\r
<p>\r
You must set <strong>sloppiness</strong> to <strong>pch_defines,time_macros</strong>. The reason is that\r
ccache can’t tell whether <strong>__TIME__</strong> or <strong>__DATE__</strong> is used when using a\r
- precompiled header. Further, it can’t detect changes in #defines in the\r
+ precompiled header. Further, it can’t detect changes in <strong>#define</strong>s in the\r
source code because of how preprocessing works in combination with\r
precompiled headers.\r
</p>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.3.4<br />\r
+Version 3.3.5<br />\r
Last updated\r
- 2017-02-12 14:58:39 CET\r
+ 2018-01-13 17:47:38 CET\r
</div>\r
</div>\r
</body>\r
*limit_multiple* (*CCACHE_LIMIT_MULTIPLE*)::
Sets the limit when cleaning up. Files are deleted (in LRU order) until the
- levels are below the limit. The default is 0.8 (= 80%).
+ levels are below the limit. The default is 0.8 (= 80%). See
+ <<_automatic_cleanup,AUTOMATIC CLEANUP>> for more information.
*log_file* (*CCACHE_LOGFILE*)::
*max_files* (*CCACHE_MAXFILES*)::
This option specifies the maximum number of files to keep in the cache. Use
- 0 for no limit (which is the default).
+ 0 for no limit (which is the default). See also
+ <<_cache_size_management,CACHE SIZE MANAGEMENT>>.
*max_size* (*CCACHE_MAXSIZE*)::
This option specifies the maximum size of the cache. Use 0 for no limit.
The default value is 5G. Available suffixes: k, M, G, T (decimal) and Ki,
- Mi, Gi, Ti (binary). The default suffix is "G".
+ Mi, Gi, Ti (binary). The default suffix is "G". See also
+ <<_cache_size_management,CACHE SIZE MANAGEMENT>>.
*path* (*CCACHE_PATH*)::
*file_stat_matches*::
ccache normally examines a file's contents to determine whether it matches
the cached version. With this option set, ccache will consider a file as
- matching its cached version if the sizes, mtimes and ctimes match.
+ matching its cached version if the mtimes and ctimes match.
*include_file_ctime*::
By default, ccache also will not cache a file if it includes a header whose
ctime is too new. This option disables that check.
With this option set, ccache will only include system headers in the hash
but not add the system header files to the list of include files.
*pch_defines*::
- Be sloppy about #defines when precompiling a header file. See
+ Be sloppy about **#define**s when precompiling a header file. See
<<_precompiled_headers,PRECOMPILED HEADERS>> for more information.
*time_macros*::
Ignore *\_\_DATE\__* and *\_\_TIME__* being present in the source code.
Cache size management
---------------------
-By default, ccache has a five gigabyte limit on the total size of files in the
-cache and no maximum number of files. You can set different limits using the
+By default, ccache has a 5 GB limit on the total size of files in the cache and
+no limit on the number of files. You can set different limits using the
*-M*/*--max-size* and *-F*/*--max-files* options. Use *ccache -s/--show-stats*
to see the cache size and the currently configured limits (in addition to other
various statistics).
+Cleanup can be triggered in two different ways: automatic and manual.
+
+
+Automatic cleanup
+~~~~~~~~~~~~~~~~~
+
+ccache maintains counters for various statistics about the cache, including the
+size and number of all cached files. In order to improve performance and reduce
+issues with concurrent ccache invocations, there is one statistics file for
+each of the sixteen subdirectories in the cache.
+
+After a new compilation result has been written to the cache, ccache will
+update the size and file number statistics for the subdirectory (one of
+sixteen) to which the result was written. Then, if the size counter for said
+subdirectory is greater than *max_size / 16* or the file number counter is
+greater than *max_files / 16*, automatic cleanup is triggered.
+
+When automatic cleanup is triggered for a subdirectory in the cache, ccache
+will:
+
+1. Count all files in the subdirectory and compute their aggregated size.
+2. Remove files in LRU (least recently used) order until the size is at most
+ *limit_multiple * max_size / 16* and the number of files is at most
+ *limit_multiple * max_files / 16*, where *limit_multiple*, *max_size* and
+ *max_files* are configuration settings.
+3. Set the size and file number counters to match the files that were kept.
+
+The reason for removing more files than just those needed to not exceed the max
+limits is that a cleanup is a fairly slow operation, so it would not be a good
+idea to trigger it often, like after each cache miss.
+
+
+Manual cleanup
+~~~~~~~~~~~~~~
+
+You can run *ccache -c/--cleanup* to force cleanup of the whole cache, i.e. all
+of the sixteen subdirectories. This will recalculate the statistics counters
+and make sure that the *max_size* and *max_files* settings are not exceeded.
+Note that *limit_multiple* is not taken into account for manual cleanup.
+
Cache compression
-----------------
* You must set *sloppiness* to *pch_defines,time_macros*. The reason is that
ccache can't tell whether *\_\_TIME\__* or *\_\_DATE__* is used when using a
- precompiled header. Further, it can't detect changes in #defines in the
+ precompiled header. Further, it can't detect changes in **#define**s in the
source code because of how preprocessing works in combination with
precompiled headers.
* You must either:
<body class="article">\r
<div id="header">\r
<h1>ccache news</h1>\r
-<span id="revnumber">version 3.3.4</span>\r
+<span id="revnumber">version 3.3.5</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_3_5">ccache 3.3.5</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Release date: 2018-01-13</p></div>\r
+<div class="sect2">\r
+<h3 id="_new_features_and_improvements">New features and improvements</h3>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Documented how automatic cache cleanup works.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+<div class="sect2">\r
+<h3 id="_bug_fixes">Bug fixes</h3>\r
+<div class="ulist"><ul>\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
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Multiple <code>-fdebug-prefix-map</code> options should now be handled correctly.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed matching of directories in the <code>ignore_headers_in_manifest</code>\r
+ configuration option.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed detection of missing argument to <code>-opt</code>/<code>--options-file</code>.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache now bails out when building a precompiled header if any of the\r
+ corresponding header files have an updated timestamp. This fixes complaints\r
+ from clang.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a bug related to erroneously storing a dependency file with absolute\r
+ paths in the cache on a preprocessed hit.\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
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache no longer ignores linker arguments for clang since clang warns about\r
+ them.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Plugged a couple of file descriptor leaks.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a bug where ccache would skip hashing the compiler argument following a\r
+ <code>-fno-working-directory</code>, <code>-fworking-directory</code>, <code>-nostdinc</code>, <code>-nostdinc++</code>,\r
+ <code>-remap</code> or <code>-trigraphs</code> option in preprocessor mode.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
<h2 id="_ccache_3_3_4">ccache 3.3.4</h2>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2017-02-17</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_2">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes">Bug fixes</h3>\r
+<h3 id="_bug_fixes_2">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-10-26</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_2">Bug fixes</h3>\r
+<h3 id="_bug_fixes_3">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-28</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_3">Bug fixes</h3>\r
+<h3 id="_bug_fixes_4">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_4">Bug fixes</h3>\r
+<h3 id="_bug_fixes_5">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_2">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_3">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_5">Bug fixes</h3>\r
+<h3 id="_bug_fixes_6">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-28</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_6">Bug fixes</h3>\r
+<h3 id="_bug_fixes_7">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_7">Bug fixes</h3>\r
+<h3 id="_bug_fixes_8">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-07-20</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_8">Bug fixes</h3>\r
+<h3 id="_bug_fixes_9">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-07-12</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_9">Bug fixes</h3>\r
+<h3 id="_bug_fixes_10">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-04-17</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_3">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_4">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_10">Bug fixes</h3>\r
+<h3 id="_bug_fixes_11">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2015-10-08</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_11">Bug fixes</h3>\r
+<h3 id="_bug_fixes_12">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2015-08-16</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_4">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_5">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_12">Bug fixes</h3>\r
+<h3 id="_bug_fixes_13">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2015-05-10</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_5">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_6">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_13">Bug fixes</h3>\r
+<h3 id="_bug_fixes_14">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2014-12-10</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_14">Bug fixes</h3>\r
+<h3 id="_bug_fixes_15">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2014-11-17</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_6">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_7">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_15">Bug fixes</h3>\r
+<h3 id="_bug_fixes_16">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-07-12</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_16">Bug fixes</h3>\r
+<h3 id="_bug_fixes_17">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2015-03-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_17">Bug fixes</h3>\r
+<h3 id="_bug_fixes_18">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2014-10-19</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_7">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_8">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_18">Bug fixes</h3>\r
+<h3 id="_bug_fixes_19">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2013-01-06</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_19">Bug fixes</h3>\r
+<h3 id="_bug_fixes_20">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2012-08-11</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_8">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_9">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_20">Bug fixes</h3>\r
+<h3 id="_bug_fixes_21">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2012-01-08</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_21">Bug fixes</h3>\r
+<h3 id="_bug_fixes_22">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2011-08-21</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_9">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_10">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_22">Bug fixes</h3>\r
+<h3 id="_bug_fixes_23">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2011-05-29</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_10">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_11">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_23">Bug fixes</h3>\r
+<h3 id="_bug_fixes_24">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2011-01-09</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_24">Bug fixes</h3>\r
+<h3 id="_bug_fixes_25">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-11-28</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_25">Bug fixes</h3>\r
+<h3 id="_bug_fixes_26">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-11-21</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_26">Bug fixes</h3>\r
+<h3 id="_bug_fixes_27">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-11-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_27">Bug fixes</h3>\r
+<h3 id="_bug_fixes_28">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-09-16</p></div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_11">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_12">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_28">Bug fixes</h3>\r
+<h3 id="_bug_fixes_29">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-07-15</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_29">Bug fixes</h3>\r
+<h3 id="_bug_fixes_30">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_new_features_and_improvements_12">New features and improvements</h3>\r
+<h3 id="_new_features_and_improvements_13">New features and improvements</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_30">Bug fixes</h3>\r
+<h3 id="_bug_fixes_31">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.3.4<br />\r
+Version 3.3.5<br />\r
Last updated\r
- 2017-02-17 22:28:35 CET\r
+ 2018-01-13 17:52:20 CET\r
</div>\r
</div>\r
</body>\r
ccache news
===========
+ccache 3.3.5
+------------
+Release date: 2018-01-13
+
+
+New features and improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Documented how automatic cache cleanup works.
+
+
+Bug fixes
+~~~~~~~~~
+
+- 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.
+
+- Multiple `-fdebug-prefix-map` options should now be handled correctly.
+
+- Fixed matching of directories in the `ignore_headers_in_manifest`
+ configuration option.
+
+- Fixed detection of missing argument to `-opt`/`--options-file`.
+
+- ccache now bails out when building a precompiled header if any of the
+ corresponding header files have an updated timestamp. This fixes complaints
+ from clang.
+
+- Fixed a bug related to erroneously storing a dependency file with absolute
+ paths in the cache on a preprocessed hit.
+
+- `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.
+
+- ccache no longer ignores linker arguments for clang since clang warns about
+ them.
+
+- Plugged a couple of file descriptor leaks.
+
+- Fixed a bug where ccache would skip hashing the compiler argument following a
+ `-fno-working-directory`, `-fworking-directory`, `-nostdinc`, `-nostdinc++`,
+ `-remap` or `-trigraphs` option in preprocessor mode.
+
+
ccache 3.3.4
------------
Release date: 2017-02-17
.\" Title: ccache
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 02/17/2017
+.\" Date: 01/13/2018
.\" Manual: ccache Manual
-.\" Source: ccache 3.3.4
+.\" Source: ccache 3.3.5
.\" Language: English
.\"
-.TH "CCACHE" "1" "02/17/2017" "ccache 3\&.3\&.4" "ccache Manual"
+.TH "CCACHE" "1" "01/13/2018" "ccache 3\&.3\&.5" "ccache Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.PP
\fBlimit_multiple\fR (\fBCCACHE_LIMIT_MULTIPLE\fR)
.RS 4
-Sets the limit when cleaning up\&. Files are deleted (in LRU order) until the levels are below the limit\&. The default is 0\&.8 (= 80%)\&.
+Sets the limit when cleaning up\&. Files are deleted (in LRU order) until the levels are below the limit\&. The default is 0\&.8 (= 80%)\&. See
+AUTOMATIC CLEANUP
+for more information\&.
.RE
.PP
\fBlog_file\fR (\fBCCACHE_LOGFILE\fR)
.PP
\fBmax_files\fR (\fBCCACHE_MAXFILES\fR)
.RS 4
-This option specifies the maximum number of files to keep in the cache\&. Use 0 for no limit (which is the default)\&.
+This option specifies the maximum number of files to keep in the cache\&. Use 0 for no limit (which is the default)\&. See also
+CACHE SIZE MANAGEMENT\&.
.RE
.PP
\fBmax_size\fR (\fBCCACHE_MAXSIZE\fR)
.RS 4
-This option specifies the maximum size of the cache\&. Use 0 for no limit\&. The default value is 5G\&. Available suffixes: k, M, G, T (decimal) and Ki, Mi, Gi, Ti (binary)\&. The default suffix is "G"\&.
+This option specifies the maximum size of the cache\&. Use 0 for no limit\&. The default value is 5G\&. Available suffixes: k, M, G, T (decimal) and Ki, Mi, Gi, Ti (binary)\&. The default suffix is "G"\&. See also
+CACHE SIZE MANAGEMENT\&.
.RE
.PP
\fBpath\fR (\fBCCACHE_PATH\fR)
.PP
\fBfile_stat_matches\fR
.RS 4
-ccache normally examines a file\(cqs contents to determine whether it matches the cached version\&. With this option set, ccache will consider a file as matching its cached version if the sizes, mtimes and ctimes match\&.
+ccache normally examines a file\(cqs contents to determine whether it matches the cached version\&. With this option set, ccache will consider a file as matching its cached version if the mtimes and ctimes match\&.
.RE
.PP
\fBinclude_file_ctime\fR
.PP
\fBpch_defines\fR
.RS 4
-Be sloppy about #defines when precompiling a header file\&. See
+Be sloppy about
+\fB#define\fRs when precompiling a header file\&. See
PRECOMPILED HEADERS
for more information\&.
.RE
.RE
.SH "CACHE SIZE MANAGEMENT"
.sp
-By default, ccache has a five gigabyte limit on the total size of files in the cache and no maximum number of files\&. You can set different limits using the \fB\-M\fR/\fB\-\-max\-size\fR and \fB\-F\fR/\fB\-\-max\-files\fR options\&. Use \fBccache \-s/\-\-show\-stats\fR to see the cache size and the currently configured limits (in addition to other various statistics)\&.
+By default, ccache has a 5 GB limit on the total size of files in the cache and no limit on the number of files\&. You can set different limits using the \fB\-M\fR/\fB\-\-max\-size\fR and \fB\-F\fR/\fB\-\-max\-files\fR options\&. Use \fBccache \-s/\-\-show\-stats\fR to see the cache size and the currently configured limits (in addition to other various statistics)\&.
+.sp
+Cleanup can be triggered in two different ways: automatic and manual\&.
+.SS "Automatic cleanup"
+.sp
+ccache maintains counters for various statistics about the cache, including the size and number of all cached files\&. In order to improve performance and reduce issues with concurrent ccache invocations, there is one statistics file for each of the sixteen subdirectories in the cache\&.
+.sp
+After a new compilation result has been written to the cache, ccache will update the size and file number statistics for the subdirectory (one of sixteen) to which the result was written\&. Then, if the size counter for said subdirectory is greater than \fBmax_size / 16\fR or the file number counter is greater than \fBmax_files / 16\fR, automatic cleanup is triggered\&.
+.sp
+When automatic cleanup is triggered for a subdirectory in the cache, ccache will:
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 1.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 1." 4.2
+.\}
+Count all files in the subdirectory and compute their aggregated size\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 2.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 2." 4.2
+.\}
+Remove files in LRU (least recently used) order until the size is at most
+\fBlimit_multiple * max_size / 16\fR
+and the number of files is at most
+\fBlimit_multiple * max_files / 16\fR, where
+\fBlimit_multiple\fR,
+\fBmax_size\fR
+and
+\fBmax_files\fR
+are configuration settings\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 3.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 3." 4.2
+.\}
+Set the size and file number counters to match the files that were kept\&.
+.RE
+.sp
+The reason for removing more files than just those needed to not exceed the max limits is that a cleanup is a fairly slow operation, so it would not be a good idea to trigger it often, like after each cache miss\&.
+.SS "Manual cleanup"
+.sp
+You can run \fBccache \-c/\-\-cleanup\fR to force cleanup of the whole cache, i\&.e\&. all of the sixteen subdirectories\&. This will recalculate the statistics counters and make sure that the \fBmax_size\fR and \fBmax_files\fR settings are not exceeded\&. Note that \fBlimit_multiple\fR is not taken into account for manual cleanup\&.
.SH "CACHE COMPRESSION"
.sp
ccache can optionally compress all files it puts into the cache using the compression library zlib\&. While this may involve a tiny performance slowdown, it increases the number of files that fit in the cache\&. You can turn on compression with the \fBcompression\fR configuration setting and you can also tweak the compression level with \fBcompression_level\fR\&.
\fB__TIME__\fR
or
\fB__DATE__\fR
-is used when using a precompiled header\&. Further, it can\(cqt detect changes in #defines in the source code because of how preprocessing works in combination with precompiled headers\&.
+is used when using a precompiled header\&. Further, it can\(cqt detect changes in
+\fB#define\fRs in the source code because of how preprocessing works in combination with precompiled headers\&.
.RE
.sp
.RS 4
// ccache -- a fast C/C++ compiler cache
//
// Copyright (C) 2002-2007 Andrew Tridgell
-// Copyright (C) 2009-2017 Joel Rosdahl
+// Copyright (C) 2009-2018 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
MYNAME " version %s\n"
"\n"
"Copyright (C) 2002-2007 Andrew Tridgell\n"
- "Copyright (C) 2009-2017 Joel Rosdahl\n"
+ "Copyright (C) 2009-2018 Joel Rosdahl\n"
"\n"
"This program is free software; you can redistribute it and/or modify it under\n"
"the terms of the GNU General Public License as published by the Free Software\n"
static bool generating_coverage;
// Relocating debuginfo in the format old=new.
-static char *debug_prefix_map = NULL;
+static char **debug_prefix_maps = NULL;
+
+// Size of debug_prefix_maps list.
+static size_t debug_prefix_maps_len = 0;
// Is the compiler being asked to output coverage data (.gcda) at runtime?
static bool profile_arcs;
char *stats_file = NULL;
// Whether the output is a precompiled header.
-static bool output_is_precompiled_header = false;
+bool output_is_precompiled_header = false;
// Profile generation / usage information.
static char *profile_dir = NULL;
}
}
+ // The comparison using >= is intentional, due to a possible race between
+ // starting compilation and writing the include file. See also the notes
+ // under "Performance" in MANUAL.txt.
if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_MTIME)
&& st.st_mtime >= time_of_compilation) {
cc_log("Include file %s too new", path);
goto failure;
}
+ // The same >= logic as above applies to the change time of the file.
if (!(conf->sloppiness & SLOPPY_INCLUDE_FILE_CTIME)
&& st.st_ctime >= time_of_compilation) {
cc_log("Include file %s ctime too new", path);
// Possibly hash the current working directory.
if (generating_debuginfo && conf->hash_dir) {
char *cwd = gnu_getcwd();
- if (debug_prefix_map) {
- char *map = debug_prefix_map;
+ for (size_t i = 0; i < debug_prefix_maps_len; i++) {
+ char *map = debug_prefix_maps[i];
char *sep = strchr(map, '=');
if (sep) {
char *old = x_strndup(map, sep - map);
hash_int(hash, MANIFEST_VERSION);
}
+ // clang will emit warnings for unused linker flags, so we shouldn't skip
+ // those arguments.
+ int is_clang = compiler_is_clang(args);
+
// First the arguments.
for (int i = 1; i < args->argc; i++) {
- // -L doesn't affect compilation.
- if (i < args->argc-1 && str_eq(args->argv[i], "-L")) {
+ // -L doesn't affect compilation (except for clang).
+ if (i < args->argc-1 && str_eq(args->argv[i], "-L") && !is_clang) {
i++;
continue;
}
- if (str_startswith(args->argv[i], "-L")) {
+ if (str_startswith(args->argv[i], "-L") && !is_clang) {
continue;
}
- // -Wl,... doesn't affect compilation.
- if (str_startswith(args->argv[i], "-Wl,")) {
+ // -Wl,... doesn't affect compilation (except for clang).
+ if (str_startswith(args->argv[i], "-Wl,") && !is_clang) {
continue;
}
if (!direct_mode && !output_is_precompiled_header
&& !using_precompiled_header) {
if (compopt_affects_cpp(args->argv[i])) {
- i++;
+ if (compopt_takes_arg(args->argv[i])) {
+ i++;
+ }
continue;
}
if (compopt_short(compopt_affects_cpp, args->argv[i])) {
return;
}
- struct stat st;
- if (stat(cached_obj, &st) != 0) {
- cc_log("Object file %s not in cache", cached_obj);
+ // We can't trust the objects based on running the preprocessor
+ // when the output is precompiled headers, as the hash does not
+ // include the mtime of each included header, breaking compilation
+ // with clang when the precompiled header is used after touching
+ // one of the included files.
+ if (output_is_precompiled_header && mode == FROMCACHE_CPP_MODE) {
+ cc_log("Not using preprocessed cached object for precompiled header");
return;
}
- // Check if the diagnostic file is there.
- if (output_dia && stat(cached_dia, &st) != 0) {
- cc_log("Diagnostic file %s not in cache", cached_dia);
+ struct stat st;
+ if (stat(cached_obj, &st) != 0) {
+ cc_log("Object file %s not in cache", cached_obj);
return;
}
return;
}
+ // Check if the diagnostic file is there.
+ if (output_dia && stat(cached_dia, &st) != 0) {
+ cc_log("Diagnostic file %s not in cache", cached_dia);
+ return;
+ }
+
// Copy object file from cache. Do so also for FissionDwarf file, cached_dwo,
// when -gsplit-dwarf is specified.
if (!str_eq(output_obj, "/dev/null")) {
update_mtime(cached_dwo);
}
- if (generating_dependencies && mode == FROMCACHE_CPP_MODE
- && !conf->read_only && !conf->read_only_direct) {
- put_file_in_cache(output_dep, cached_dep);
- }
-
send_cached_stderr();
if (put_object_in_manifest) {
struct args *dep_args = args_init(0, NULL);
bool found_color_diagnostics = false;
- int debug_level = 0;
- const char *debug_argument = NULL;
int argc = expanded_args->argc;
char **argv = expanded_args->argv;
// Handle cuda "-optf" and "--options-file" argument.
if (str_eq(argv[i], "-optf") || str_eq(argv[i], "--options-file")) {
- if (i > argc) {
- cc_log("Expected argument after -optf/--options-file");
+ if (i == argc - 1) {
+ cc_log("Expected argument after %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
goto out;
// Special handling for -x: remember the last specified language before the
// input file and strip all -x options from the arguments.
if (str_eq(argv[i], "-x")) {
- if (i == argc-1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
// We need to work out where the output was meant to go.
if (str_eq(argv[i], "-o")) {
- if (i == argc-1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
continue;
}
if (str_startswith(argv[i], "-fdebug-prefix-map=")) {
- debug_prefix_map = x_strdup(argv[i] + 19);
+ debug_prefix_maps = x_realloc(
+ debug_prefix_maps,
+ (debug_prefix_maps_len + 1) * sizeof(char *));
+ debug_prefix_maps[debug_prefix_maps_len++] = x_strdup(argv[i] + 19);
args_add(stripped_args, argv[i]);
continue;
}
// Debugging is handled specially, so that we know if we can strip line
// number info.
if (str_startswith(argv[i], "-g")) {
- const char *pLevel = argv[i] + 2;
- if (str_startswith(argv[i], "-ggdb")) {
- pLevel = argv[i] + 5;
- } else if (str_startswith(argv[i], "-gstabs")) {
- pLevel = argv[i] + 7;
- } else if (str_startswith(argv[i], "-gcoff")) {
- pLevel = argv[i] + 6;
- } else if (str_startswith(argv[i], "-gxcoff")) {
- pLevel = argv[i] + 7;
- } else if (str_startswith(argv[i], "-gvms")) {
- pLevel = argv[i] + 5;
- }
-
- // Deduce level from argument, default is 2.
- int foundlevel = -1;
- if (pLevel[0] == '\0') {
- foundlevel = 2;
- } else if (pLevel[0] >= '0' && pLevel[0] <= '9') {
- foundlevel = atoi(pLevel);
- }
-
- if (foundlevel >= 0) {
- debug_level = foundlevel;
- debug_argument = argv[i];
- continue;
+ 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;
+ }
+ continue;
}
// These options require special handling, because they behave differently
bool separate_argument = (strlen(argv[i]) == 3);
if (separate_argument) {
// -MF arg
- if (i >= argc - 1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
char *relpath;
if (strlen(argv[i]) == 3) {
// -MQ arg or -MT arg
- if (i >= argc - 1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
}
if (str_eq(argv[i], "--serialize-diagnostics")) {
- if (i >= argc - 1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
// to get better hit rate. A secondary effect is that paths in the standard
// error output produced by the compiler will be normalized.
if (compopt_takes_path(argv[i])) {
- if (i == argc-1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
// Options that take an argument.
if (compopt_takes_arg(argv[i])) {
- if (i == argc-1) {
+ if (i == argc - 1) {
cc_log("Missing argument to %s", argv[i]);
stats_update(STATS_ARGS);
result = false;
}
} // for
- if (debug_level > 0) {
- generating_debuginfo = true;
- args_add(stripped_args, debug_argument);
- if (conf->unify) {
- cc_log("%s used; disabling unify mode", debug_argument);
- conf->unify = false;
- }
- if (debug_level >= 3 && !conf->run_second_cpp) {
- cc_log("%s used; not compiling preprocessed code", debug_argument);
- conf->run_second_cpp = true;
- }
- }
-
if (found_S_opt) {
// Even if -gsplit-dwarf is given, the .dwo file is not generated when -S
// is also given.
free(primary_config_path); primary_config_path = NULL;
free(secondary_config_path); secondary_config_path = NULL;
free(current_working_dir); current_working_dir = NULL;
- free(debug_prefix_map); debug_prefix_map = NULL;
+ for (size_t i = 0; i < debug_prefix_maps_len; i++) {
+ free(debug_prefix_maps[i]);
+ debug_prefix_maps[i] = NULL;
+ }
+ free(debug_prefix_maps); debug_prefix_maps = NULL;
+ debug_prefix_maps_len = 0;
free(profile_dir); profile_dir = NULL;
free(included_pch_file); included_pch_file = NULL;
args_free(orig_args); orig_args = NULL;
setup_uncached_err(void)
{
int uncached_fd = dup(2);
+ set_cloexec_flag(uncached_fd);
if (uncached_fd == -1) {
cc_log("dup(2) failed: %s", strerror(errno));
failed();
case 'c': // --cleanup
initialize();
- cleanup_all(conf);
+ clean_up_all(conf);
printf("Cleaned cache\n");
break;
bool read_file(const char *path, size_t size_hint, char **data, size_t *size);
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);
// ----------------------------------------------------------------------------
// stats.c
// ----------------------------------------------------------------------------
// cleanup.c
-void cleanup_dir(struct conf *conf, const char *dir);
-void cleanup_all(struct conf *conf);
+void clean_up_dir(struct conf *conf, const char *dir, float limit_multiple);
+void clean_up_all(struct conf *conf);
void wipe_all(struct conf *conf);
// ----------------------------------------------------------------------------
// ccache.c
extern time_t time_of_compilation;
+extern bool output_is_precompiled_header;
void block_signals(void);
void unblock_signals(void);
bool cc_process_args(struct args *args, struct args **preprocessor_args,
# define lstat(a,b) stat(a,b)
# define execv(a,b) win32execute(a,b,0,-1,-1)
# define execute(a,b,c,d) win32execute(*(a),a,1,b,c)
-# define DIR_DELIM_CH '/'
+# define DIR_DELIM_CH '\\'
# define PATH_DELIM ";"
# define F_RDLCK 0
# define F_WRLCK 0
#else
-# define DIR_DELIM_CH '\\'
+# define DIR_DELIM_CH '/'
# define PATH_DELIM ":"
#endif
// Copyright (C) 2002-2006 Andrew Tridgell
-// Copyright (C) 2009-2016 Joel Rosdahl
+// Copyright (C) 2009-2018 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
// Clean up one cache subdirectory.
void
-cleanup_dir(struct conf *conf, const char *dir)
+clean_up_dir(struct conf *conf, const char *dir, float limit_multiple)
{
cc_log("Cleaning up cache directory %s", dir);
// When "max files" or "max cache size" is reached, one of the 16 cache
// subdirectories is cleaned up. When doing so, files are deleted (in LRU
// order) until the levels are below limit_multiple.
- cache_size_threshold = conf->max_size * conf->limit_multiple / 16;
- files_in_cache_threshold = conf->max_files * conf->limit_multiple / 16;
+ cache_size_threshold = conf->max_size * limit_multiple / 16;
+ files_in_cache_threshold = conf->max_files * limit_multiple / 16;
num_files = 0;
cache_size = 0;
stats_add_cleanup(dir, 1);
}
+ cc_log("After cleanup: %lu KiB, %zu files",
+ (unsigned long)cache_size / 1024,
+ files_in_cache);
stats_set_sizes(dir, files_in_cache, cache_size);
// Free it up.
}
// Clean up all cache subdirectories.
-void cleanup_all(struct conf *conf)
+void clean_up_all(struct conf *conf)
{
for (int i = 0; i <= 0xF; i++) {
char *dname = format("%s/%1x", conf->cache_dir, i);
- cleanup_dir(conf, dname);
+ clean_up_dir(conf, dname, 1.0);
free(dname);
}
}
}
// Fix the counters.
- cleanup_all(conf);
+ clean_up_all(conf);
}
place++;
- if (place[0] && place[0] == '-' && place[1] == '\0')
+ if (place[0] == '-' && place[1] == '\0')
{ /* found "--" */
++optind;
place = EMSG;
return -1;
}
- if (place[0] && place[0] == '-' && place[1])
+ if (place[0] == '-' && place[1])
{
/* long option */
size_t namelen;
hashtable_insert(stated_files, x_strdup(path), st);
}
+ if (fi->size != st->size) {
+ return 0;
+ }
+
+ // Clang stores the mtime of the included files in the precompiled header,
+ // and will error out if that header is later used without rebuilding.
+ if (output_is_precompiled_header && fi->mtime != st->mtime) {
+ cc_log("Precompiled header includes %s, which has a new mtime", path);
+ return 0;
+ }
+
if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
- // st->ctime is sometimes 0, so we can't check that both st->ctime and
- // st->mtime are greater than time_of_compilation. But it's sufficient to
- // check that either is.
- if (fi->size == st->size
- && fi->mtime == st->mtime
- && fi->ctime == st->ctime
- && MAX(st->mtime, st->ctime) >= time_of_compilation) {
- cc_log("size/mtime/ctime hit for %s", path);
+ if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
+ cc_log("mtime/ctime hit for %s", path);
continue;
} else {
- cc_log("size/mtime/ctime miss for %s", path);
+ cc_log("mtime/ctime miss for %s", path);
}
}
switch (len)
{
- case 3: h ^= ((unsigned int) data[2]) << 16;
- case 2: h ^= ((unsigned int) data[1]) << 8;
+ case 3: h ^= ((unsigned int) data[2]) << 16; // Fallthrough.
+ case 2: h ^= ((unsigned int) data[1]) << 8; // Fallthrough.
case 1: h ^= ((unsigned int) data[0]);
h *= m;
};
// Copyright (C) 2002-2004 Andrew Tridgell
-// Copyright (C) 2009-2016 Joel Rosdahl
+// Copyright (C) 2009-2018 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
}
}
+ char *subdir = dirname(stats_file);
bool need_cleanup = false;
+
if (conf->max_files != 0
&& counters->data[STATS_NUMFILES] > conf->max_files / 16) {
+ cc_log("Need to clean up %s since it holds %u files (limit: %u files)",
+ subdir,
+ counters->data[STATS_NUMFILES],
+ conf->max_files / 16);
need_cleanup = true;
}
if (conf->max_size != 0
&& counters->data[STATS_TOTALSIZE] > conf->max_size / 1024 / 16) {
+ cc_log("Need to clean up %s since it holds %u KiB (limit: %lu KiB)",
+ subdir,
+ counters->data[STATS_TOTALSIZE],
+ (unsigned long)conf->max_size / 1024 / 16);
need_cleanup = true;
}
if (need_cleanup) {
- char *p = dirname(stats_file);
- cleanup_dir(conf, p);
- free(p);
+ clean_up_dir(conf, subdir, conf->limit_multiple);
}
+ free(subdir);
counters_free(counters);
}
# A simple test suite for ccache.
#
# Copyright (C) 2002-2007 Andrew Tridgell
-# Copyright (C) 2009-2017 Joel Rosdahl
+# Copyright (C) 2009-2018 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
echo
echo "Test suite: $(bold $CURRENT_SUITE)"
echo "Test case: $(bold $CURRENT_TEST)"
- echo "Failure reason: $(red $1)"
+ echo "Failure reason: $(red "$1")"
echo
echo "ccache -s:"
$CCACHE -s
}
run_suite() {
- local name=$1
+ local suite_name=$1
- CURRENT_SUITE=$name
+ CURRENT_SUITE=$suite_name
UNCACHED_COMPILE=uncached_compile
cd $ABS_TESTDIR
rm -rf $ABS_TESTDIR/fixture
- if type SUITE_${name}_PROBE >/dev/null 2>&1; then
+ if type SUITE_${suite_name}_PROBE >/dev/null 2>&1; then
mkdir $ABS_TESTDIR/probe
cd $ABS_TESTDIR/probe
- local skip_reason="$(SUITE_${name}_PROBE)"
+ local skip_reason="$(SUITE_${suite_name}_PROBE)"
cd $ABS_TESTDIR
rm -rf $ABS_TESTDIR/probe
if [ -n "$skip_reason" ]; then
- echo "Skipped test suite $name [$skip_reason]"
+ echo "Skipped test suite $suite_name [$skip_reason]"
return
fi
fi
- printf "Running test suite %s" "$(bold $name)"
- SUITE_$name
+ printf "Running test suite %s" "$(bold $suite_name)"
+ SUITE_$suite_name
echo
}
TEST() {
CURRENT_TEST=$1
- unset CCACHE_BASEDIR
- unset CCACHE_CC
- unset CCACHE_COMMENTS
- unset CCACHE_COMPILERCHECK
- unset CCACHE_COMPRESS
- unset CCACHE_CPP2
- unset CCACHE_DIR
- unset CCACHE_DISABLE
- unset CCACHE_EXTENSION
- unset CCACHE_EXTRAFILES
- unset CCACHE_HARDLINK
- unset CCACHE_IGNOREHEADERS
- unset CCACHE_LIMIT_MULTIPLE
- unset CCACHE_LOGFILE
- unset CCACHE_NLEVELS
- unset CCACHE_NOCPP2
- unset CCACHE_NOHASHDIR
- unset CCACHE_NOSTATS
- unset CCACHE_PATH
- unset CCACHE_PREFIX
- unset CCACHE_PREFIX_CPP
- unset CCACHE_READONLY
- unset CCACHE_READONLY_DIRECT
- unset CCACHE_RECACHE
- unset CCACHE_SLOPPINESS
- unset CCACHE_TEMPDIR
- unset CCACHE_UMASK
- unset CCACHE_UNIFY
+ while read name; do
+ unset $name
+ done <<EOF
+$(env | sed -n 's/^\(CCACHE_[A-Z0-9_]*\)=.*$/\1/p')
+EOF
unset GCC_COLORS
export CCACHE_CONFIGPATH=$ABS_TESTDIR/ccache.conf
CCACHE_COMPILE="$CCACHE $COMPILER"
if $VERBOSE; then
- printf "\n %s" $CURRENT_TEST
+ printf "\n %s" "$CURRENT_TEST"
else
printf .
fi
rm -rf $ABS_TESTDIR/run
mkdir $ABS_TESTDIR/run
cd $ABS_TESTDIR/run
- if type SUITE_${name}_SETUP >/dev/null 2>&1; then
- SUITE_${name}_SETUP
+ if type SUITE_${suite_name}_SETUP >/dev/null 2>&1; then
+ SUITE_${suite_name}_SETUP
fi
}
# =============================================================================
SUITE_debug_prefix_map_PROBE() {
- if ! $COMPILER_TYPE_GCC || $COMPILER_USES_MINGW; then
+ if $COMPILER_USES_MINGW; then
echo "-fdebug-prefix-map not supported by compiler"
fi
}
if grep -E "[^=]`pwd`[^=]" test.o >/dev/null 2>&1; then
test_failed "Source dir (`pwd`) found in test.o"
fi
+
+ # -------------------------------------------------------------------------
+ TEST "Multiple -fdebug-prefix-map"
+
+ cd dir1
+ CCACHE_BASEDIR=`pwd` $CCACHE_COMPILE -I`pwd`/include -g -fdebug-prefix-map=`pwd`=name -fdebug-prefix-map=foo=bar -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' 2
+ if grep -E "[^=]`pwd`[^=]" test.o >/dev/null 2>&1; then
+ test_failed "Source dir (`pwd`) found in test.o"
+ fi
+ if ! grep "name" test.o >/dev/null 2>&1; then
+ test_failed "Relocation (name) not found in test.o"
+ fi
+
+ cd ../dir2
+ CCACHE_BASEDIR=`pwd` $CCACHE_COMPILE -I`pwd`/include -g -fdebug-prefix-map=`pwd`=name -fdebug-prefix-map=foo=bar -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' 2
+ if grep -E "[^=]`pwd`[^=]" test.o >/dev/null 2>&1; then
+ test_failed "Source dir (`pwd`) found in test.o"
+ fi
}
# =============================================================================
expect_stat 'cache miss' 2
# -------------------------------------------------------------------------
- TEST "CCACHE_IGNOREHEADERS"
+ TEST "CCACHE_IGNOREHEADERS with filename"
- cat <<EOF >ignore.h
+ mkdir subdir
+ cat <<EOF >subdir/ignore.h
// We don't want this header in the manifest.
EOF
- backdate ignore.h
+ backdate subdir/ignore.h
cat <<EOF >ignore.c
-#include "ignore.h"
+#include "subdir/ignore.h"
int foo;
EOF
- CCACHE_IGNOREHEADERS="ignore.h" $CCACHE_COMPILE -c ignore.c
+ CCACHE_IGNOREHEADERS="subdir/ignore.h" $CCACHE_COMPILE -c ignore.c
manifest=`find $CCACHE_DIR -name '*.manifest'`
- data="`$CCACHE --dump-manifest $manifest | grep ignore.h`"
+ data="`$CCACHE --dump-manifest $manifest | grep subdir/ignore.h`"
+ if [ -n "$data" ]; then
+ test_failed "$manifest contained ignored header: $data"
+ fi
+
+ # -------------------------------------------------------------------------
+ TEST "CCACHE_IGNOREHEADERS with directory"
+
+ mkdir subdir
+ cat <<EOF >subdir/ignore.h
+// We don't want this header in the manifest.
+EOF
+ backdate subdir/ignore.h
+ cat <<EOF >ignore.c
+#include "subdir/ignore.h"
+int foo;
+EOF
+
+ CCACHE_IGNOREHEADERS="subdir" $CCACHE_COMPILE -c ignore.c
+ manifest=`find $CCACHE_DIR -name '*.manifest'`
+ data="`$CCACHE --dump-manifest $manifest | grep subdir/ignore.h`"
if [ -n "$data" ]; then
test_failed "$manifest contained ignored header: $data"
fi
expect_stat 'cache hit (preprocessed)' 0
expect_stat 'cache miss' 1
+ mkdir subdir
+ ln -s `pwd`/include subdir/symlink
+
# Rewriting triggered by CCACHE_BASEDIR should handle paths with multiple
- # slashes correctly:
- CCACHE_BASEDIR=`pwd` $CCACHE_COMPILE -I`pwd`//include -c `pwd`//src/test.c
+ # slashes, redundant "/." parts and "foo/.." parts correctly. Note that the
+ # ".." part of the path is resolved after the symlink has been resolved.
+ CCACHE_BASEDIR=`pwd` $CCACHE_COMPILE -I`pwd`//./subdir/symlink/../include -c `pwd`/src/test.c
expect_stat 'cache hit (direct)' 1
expect_stat 'cache hit (preprocessed)' 0
expect_stat 'cache miss' 1
prepare_cleanup_test_dir $CCACHE_DIR/a
- # (9/10) * 30 * 16 = 432
- $CCACHE -F 432 -M 0 >/dev/null
+ # No cleanup needed.
+ #
+ # 30 * 16 = 480
+ $CCACHE -F 480 -M 0 >/dev/null
+ $CCACHE -c >/dev/null
+ expect_file_count 10 '*.o' $CCACHE_DIR
+ expect_file_count 10 '*.d' $CCACHE_DIR
+ expect_file_count 10 '*.stderr' $CCACHE_DIR
+ expect_stat 'files in cache' 30
+ expect_stat 'cleanups performed' 0
+
+ # Reduce file limit
+ #
+ # 21 * 16 = 336
+ $CCACHE -F 336 -M 0 >/dev/null
$CCACHE -c >/dev/null
- # floor(0.8 * 9) = 7
expect_file_count 7 '*.o' $CCACHE_DIR
expect_file_count 7 '*.d' $CCACHE_DIR
expect_file_count 7 '*.stderr' $CCACHE_DIR
prepare_cleanup_test_dir $CCACHE_DIR/a
- # (4/10) * 10 * 4 * 16 = 256
$CCACHE -F 0 -M 256K >/dev/null
- $CCACHE -c >/dev/null
- # floor(0.8 * 4) = 3
+ CCACHE_LOGFILE=/tmp/foo $CCACHE -c >/dev/null
expect_file_count 3 '*.o' $CCACHE_DIR
expect_file_count 3 '*.d' $CCACHE_DIR
expect_file_count 3 '*.stderr' $CCACHE_DIR
done
# -------------------------------------------------------------------------
- TEST "Automatic cache cleanup"
+ TEST "Automatic cache cleanup, limit_multiple 0.9"
for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
prepare_cleanup_test_dir $CCACHE_DIR/$x
done
- # (9/10) * 30 * 16 = 432
- $CCACHE -F 432 -M 0 >/dev/null
+ $CCACHE -F 480 -M 0 >/dev/null
+
expect_file_count 160 '*.o' $CCACHE_DIR
expect_file_count 160 '*.d' $CCACHE_DIR
expect_file_count 160 '*.stderr' $CCACHE_DIR
expect_stat 'files in cache' 480
+ expect_stat 'cleanups performed' 0
touch empty.c
- $CCACHE_COMPILE -c empty.c -o empty.o
- # floor(0.8 * 9) = 7
+ CCACHE_LIMIT_MULTIPLE=0.9 $CCACHE_COMPILE -c empty.c -o empty.o
+ expect_file_count 159 '*.o' $CCACHE_DIR
+ expect_file_count 158 '*.d' $CCACHE_DIR
+ expect_file_count 158 '*.stderr' $CCACHE_DIR
+ expect_stat 'files in cache' 475
+ expect_stat 'cleanups performed' 1
+
+ # -------------------------------------------------------------------------
+ TEST "Automatic cache cleanup, limit_multiple 0.7"
+
+ for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+ prepare_cleanup_test_dir $CCACHE_DIR/$x
+ done
+
+ $CCACHE -F 480 -M 0 >/dev/null
+
+ expect_file_count 160 '*.o' $CCACHE_DIR
+ expect_file_count 160 '*.d' $CCACHE_DIR
+ expect_file_count 160 '*.stderr' $CCACHE_DIR
+ expect_stat 'files in cache' 480
+ expect_stat 'cleanups performed' 0
+
+ touch empty.c
+ CCACHE_LIMIT_MULTIPLE=0.7 $CCACHE_COMPILE -c empty.c -o empty.o
expect_file_count 157 '*.o' $CCACHE_DIR
expect_file_count 156 '*.d' $CCACHE_DIR
expect_file_count 156 '*.stderr' $CCACHE_DIR
prepare_cleanup_test_dir $CCACHE_DIR/a
- # (9/10) * 30 * 16 = 432
- $CCACHE -F 432 -M 0 >/dev/null
+ $CCACHE -F 336 -M 0 >/dev/null
backdate $CCACHE_DIR/a/result2-4017.stderr
$CCACHE -c >/dev/null
# floor(0.8 * 9) = 7
touch $CCACHE_DIR/a/abcd.unknown
$CCACHE -F 0 -M 0 -c >/dev/null # update counters
expect_stat 'files in cache' 31
- # (9/10) * 30 * 16 = 432
- $CCACHE -F 432 -M 0 >/dev/null
+
+ $CCACHE -F 480 -M 0 >/dev/null
$CCACHE -c >/dev/null
if [ ! -f $CCACHE_DIR/a/abcd.unknown ]; then
test_failed "$CCACHE_DIR/a/abcd.unknown removed"
fi
- expect_stat 'files in cache' 19
+ expect_stat 'files in cache' 28
# -------------------------------------------------------------------------
TEST "Cleanup of old unknown file"
prepare_cleanup_test_dir $CCACHE_DIR/a
- # (9/10) * 30 * 16 = 432
- $CCACHE -F 432 -M 0 >/dev/null
+ $CCACHE -F 480 -M 0 >/dev/null
touch $CCACHE_DIR/a/abcd.unknown
backdate $CCACHE_DIR/a/abcd.unknown
- $CCACHE -c >/dev/null
+ $CCACHE -F 0 -M 0 -c >/dev/null # update counters
+ expect_stat 'files in cache' 31
+
+ $CCACHE -F 480 -M 0 -c >/dev/null
if [ -f $CCACHE_DIR/a/abcd.unknown ]; then
test_failed "$CCACHE_DIR/a/abcd.unknown not removed"
fi
+ expect_stat 'files in cache' 30
# -------------------------------------------------------------------------
TEST "Cleanup of tmp file"
$CCACHE -c >/dev/null
expect_file_count 1 '.nfs*' $CCACHE_DIR
expect_stat 'files in cache' 30
-
- # -------------------------------------------------------------------------
- TEST "CCACHE_LIMIT_MULTIPLE"
-
- prepare_cleanup_test_dir $CCACHE_DIR/a
-
- # (1/1) * 30 * 16 = 480
- $CCACHE -F 480 >/dev/null
- CCACHE_LIMIT_MULTIPLE=0.5 $CCACHE -c >/dev/null
- expect_stat 'files in cache' 15
}
# =============================================================================
# -------------------------------------------------------------------------
TEST "Create .gch, -c, no -o, with opt-in"
- CCACHE_SLOPPINESS=pch_defines $CCACHE_COMPILE $SYSROOT -c pch.h
+ 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=pch_defines $CCACHE_COMPILE $SYSROOT -c pch.h
+ 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
# -------------------------------------------------------------------------
TEST "Create .gch, no -c, -o, with opt-in"
- CCACHE_SLOPPINESS=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
+ 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=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
+ 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
# -------------------------------------------------------------------------
TEST "Create .gch, -c, no -o, with opt-in"
- CCACHE_SLOPPINESS=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT -c pch.h
+ 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=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT -c pch.h
+ 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
# -------------------------------------------------------------------------
TEST "Create .gch, no -c, -o, with opt-in"
- CCACHE_SLOPPINESS=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
+ 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=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT pch.h -o pch.gch
+ 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
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
+
+ $UNCACHED_COMPILE $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"
# -------------------------------------------------------------------------
TEST "Create .pth, -c, -o"
- CCACHE_SLOPPINESS=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT -c pch.h -o 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)' 0
expect_stat 'cache hit (preprocessed)' 0
expect_stat 'cache miss' 1
rm -f pch.h.pth
- CCACHE_SLOPPINESS=pch_defines,time_macros $CCACHE_COMPILE $SYSROOT -c pch.h -o 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
-// Copyright (C) 2010-2016 Joel Rosdahl
+// Copyright (C) 2010-2017 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
args_free(act_cc);
}
+TEST(debug_flag_order_with_known_option_first)
+{
+ struct args *orig = args_init_from_string("cc -g1 -gsplit-dwarf foo.c -c");
+ struct args *exp_cpp = args_init_from_string("cc -g1 -gsplit-dwarf");
+ struct args *exp_cc = args_init_from_string("cc -g1 -gsplit-dwarf -c");
+ struct args *act_cpp = NULL;
+ struct args *act_cc = NULL;
+
+ create_file("foo.c", "");
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
+}
+
+TEST(debug_flag_order_with_known_option_last)
+{
+ struct args *orig = args_init_from_string("cc -gsplit-dwarf -g1 foo.c -c");
+ struct args *exp_cpp = args_init_from_string("cc -gsplit-dwarf -g1");
+ struct args *exp_cc = args_init_from_string("cc -gsplit-dwarf -g1 -c");
+ struct args *act_cpp = NULL;
+ struct args *act_cc = NULL;
+
+ create_file("foo.c", "");
+ CHECK(cc_process_args(orig, &act_cpp, &act_cc));
+ CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
+ CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
+
+ args_free(orig);
+}
+
TEST_SUITE_END
// Copyright (C) 2002 Andrew Tridgell
-// Copyright (C) 2009-2016 Joel Rosdahl
+// Copyright (C) 2009-2018 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
logfile = fopen(conf->log_file, "a");
if (logfile) {
#ifndef _WIN32
- int fd = fileno(logfile);
- int flags = fcntl(fd, F_GETFD, 0);
- if (flags >= 0) {
- fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
- }
+ set_cloexec_flag(fileno(logfile));
#endif
return true;
} else {
switch (*p) {
case 'T':
x *= multiplier;
+ // Fallthrough.
case 'G':
x *= multiplier;
+ // Fallthrough.
case 'M':
x *= multiplier;
+ // Fallthrough.
case 'K':
case 'k':
x *= multiplier;
fatal("Failed to create temporary file for %s: %s",
*fname, strerror(errno));
}
+ set_cloexec_flag(fd);
#ifndef _WIN32
fchmod(fd, 0666 & ~get_umask());
reformat(&result, "%s%.*s", result, (int)(q - p), p);
return result;
}
+
+void
+set_cloexec_flag(int fd)
+{
+#ifndef _WIN32
+ int flags = fcntl(fd, F_GETFD, 0);
+ if (flags >= 0) {
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ }
+#endif
+}
-const char CCACHE_VERSION[] = "3.3.4";
+const char CCACHE_VERSION[] = "3.3.5";