-------------------------------------------------------------------------------
Copyright (C) 2002-2007 Andrew Tridgell
- Copyright (C) 2009-2019 Joel Rosdahl
+ Copyright (C) 2009-2020 Joel Rosdahl
-------------------------------------------------------------------------------
<body class="article">\r
<div id="header">\r
<h1>ccache copyright and license</h1>\r
-<span id="revnumber">version 3.7.6</span>\r
+<span id="revnumber">version 3.7.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="listingblock">\r
<div class="content">\r
<pre><code> Copyright (C) 2002-2007 Andrew Tridgell\r
- Copyright (C) 2009-2019 Joel Rosdahl</code></pre>\r
+ Copyright (C) 2009-2020 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.7.6<br />\r
+Version 3.7.7<br />\r
Last updated\r
- 2019-11-17 20:10:03 CET\r
+ 2020-01-05 21:09:39 CET\r
</div>\r
</div>\r
</body>\r
src/manifest.c \
src/mdfour.c \
src/stats.c \
- src/unify.c \
src/util.c
generated_sources = \
src/confitems_lookup.c \
src/minitrace.h \
src/murmurhashneutral2.h \
src/system.h \
- src/unify.h \
unittest/framework.h \
unittest/util.h
generated_headers = \
* Mike Frysinger
* Mike Gulick
* Mikhail Kolomeytsev
+* Mizuha Himuraki
* Mostyn Bramley-Moore
* Neil Mushell
* Nick Schultz
<body class="article">\r
<div id="header">\r
<h1>ccache authors</h1>\r
-<span id="revnumber">version 3.7.6</span>\r
+<span id="revnumber">version 3.7.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>
</li>\r
<li>\r
<p>\r
+Mizuha Himuraki\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
Mostyn Bramley-Moore\r
</p>\r
</li>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.7.6<br />\r
+Version 3.7.7<br />\r
Last updated\r
- 2019-11-17 20:10:03 CET\r
+ 2020-01-05 21:09:39 CET\r
</div>\r
</div>\r
</body>\r
*read_only* (*CCACHE_READONLY* or *CCACHE_NOREADONLY*, see <<_boolean_values,Boolean values>> above)::
If true, ccache will attempt to use existing cached object files, but it
- will not to try to add anything new to the cache. If you are using this
- because your ccache directory is read-only, then you need to set
- *temporary_dir* as otherwise ccache will fail to create temporary files.
+ will not add new results to the cache. Statistics counters will still be
+ updated, though, unless the *stats* option is set to *false*.
++
+If you are using this because your ccache directory is read-only, you need to
+set *temporary_dir* since ccache will fail to create temporary files otherwise.
+You may also want to set *stats = false* to make ccache not even try to update
+stats files.
*read_only_direct* (*CCACHE_READONLY_DIRECT* or *CCACHE_NOREADONLY_DIRECT*, see <<_boolean_values,Boolean values>> above)::
with other users. Note that this also affects the file permissions set on
the object files created from your compilations.
-*unify* (*CCACHE_UNIFY* or *CCACHE_NOUNIFY*, see <<_boolean_values,Boolean values>> above)::
-
- If true, ccache will use a C/C++ unifier when hashing the preprocessor
- output if the *-g* option is not used. The unifier is slower than a normal
- hash, so setting this environment variable loses a little bit of speed, but
- it means that ccache can take advantage of not recompiling when the changes
- to the source code consist of reformatting only. Note that enabling the
- unifier changes the hash, so cached compilations produced when the unifier
- is enabled cannot be reused when the unifier is disabled, and vice versa.
- Enabling the unifier may result in incorrect line number information in
- compiler warning messages and expansions of the `__LINE__` macro.
-
Cache size management
---------------------
* the configuration setting *depend_mode* is false
* the configuration setting *run_second_cpp* is false
-* the configuration setting *unify* is true
* the compiler is not generating dependencies using *-MD* or *-MMD*
<body class="article">\r
<div id="header">\r
<h1>CCACHE(1)</h1>\r
-<span id="revnumber">version 3.7.6</span>\r
+<span id="revnumber">version 3.7.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>
<dd>\r
<p>\r
If true, ccache will attempt to use existing cached object files, but it\r
- will not to try to add anything new to the cache. If you are using this\r
- because your ccache directory is read-only, then you need to set\r
- <strong>temporary_dir</strong> as otherwise ccache will fail to create temporary files.\r
+ will not add new results to the cache. Statistics counters will still be\r
+ updated, though, unless the <strong>stats</strong> option is set to <strong>false</strong>.\r
</p>\r
+<div class="paragraph"><p>If you are using this because your ccache directory is read-only, you need to\r
+set <strong>temporary_dir</strong> since ccache will fail to create temporary files otherwise.\r
+You may also want to set <strong>stats = false</strong> to make ccache not even try to update\r
+stats files.</p></div>\r
</dd>\r
<dt class="hdlist1">\r
<strong>read_only_direct</strong> (<strong>CCACHE_READONLY_DIRECT</strong> or <strong>CCACHE_NOREADONLY_DIRECT</strong>, see <a href="#_boolean_values">Boolean values</a> above)\r
the object files created from your compilations.\r
</p>\r
</dd>\r
-<dt class="hdlist1">\r
-<strong>unify</strong> (<strong>CCACHE_UNIFY</strong> or <strong>CCACHE_NOUNIFY</strong>, see <a href="#_boolean_values">Boolean values</a> above)\r
-</dt>\r
-<dd>\r
-<p>\r
- If true, ccache will use a C/C++ unifier when hashing the preprocessor\r
- output if the <strong>-g</strong> option is not used. The unifier is slower than a normal\r
- hash, so setting this environment variable loses a little bit of speed, but\r
- it means that ccache can take advantage of not recompiling when the changes\r
- to the source code consist of reformatting only. Note that enabling the\r
- unifier changes the hash, so cached compilations produced when the unifier\r
- is enabled cannot be reused when the unifier is disabled, and vice versa.\r
- Enabling the unifier may result in incorrect line number information in\r
- compiler warning messages and expansions of the <code>__LINE__</code> macro.\r
-</p>\r
-</dd>\r
</dl></div>\r
</div>\r
</div>\r
</li>\r
<li>\r
<p>\r
-the configuration setting <strong>unify</strong> is true\r
-</p>\r
-</li>\r
-<li>\r
-<p>\r
the compiler is not generating dependencies using <strong>-MD</strong> or <strong>-MMD</strong>\r
</p>\r
</li>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.7.6<br />\r
+Version 3.7.7<br />\r
Last updated\r
- 2019-11-17 20:10:03 CET\r
+ 2020-01-05 21:09:39 CET\r
</div>\r
</div>\r
</body>\r
ccache news
===========
+ccache 3.7.7
+------------
+Release date: 2020-01-05
+
+Bug fixes
+~~~~~~~~~
+
+- Fixed a bug related to object file location in the dependency file (if using
+ `-MD` or `-MMD` but not `-MF` and the build directory is not the same as the
+ source directory then the object file location in the `.d` file would become
+ incorrect). This fixes regression in ccache 3.7.5 introduced by the bug fix
+ related to EDG-based compilers. Note that this removes support for EDG-based
+ compilers again. (A better fix for this is planned for ccache 4.0.)
+
+- Removed the unify mode since it has bugs and shortcomings that are non-trivial
+ or impossible to fix: it doesn’t work with the direct mode, it doesn’t handle
+ C++ raw strings correctly, it can give false cache hits for `.incbin`
+ directives, it’s turned off when using `-g` and it can make line numbers in
+ warning messages and `__LINE__` macros incorrect.
+
+- mtime and ctime values are now stored in the manifest files only when
+ sloppy_file_stat is set. This avoids adding superfluous manifest file entries
+ on direct mode cache misses.
+
+- A “Result:” line is now always printed to the log.
+
+- The “cache miss” statistics counter will now be updated for read-only cache
+ misses, making it consistent with the cache hit case.
+
+
ccache 3.7.6
------------
Release date: 2019-11-17
<body class="article">\r
<div id="header">\r
<h1>ccache news</h1>\r
-<span id="revnumber">version 3.7.6</span>\r
+<span id="revnumber">version 3.7.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_7">ccache 3.7.7</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Release date: 2020-01-05</p></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 bug related to object file location in the dependency file (if using\r
+ <code>-MD</code> or <code>-MMD</code> but not <code>-MF</code> and the build directory is not the same as the\r
+ source directory then the object file location in the <code>.d</code> file would become\r
+ incorrect). This fixes regression in ccache 3.7.5 introduced by the bug fix\r
+ related to EDG-based compilers. Note that this removes support for EDG-based\r
+ compilers again. (A better fix for this is planned for ccache 4.0.)\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Removed the unify mode since it has bugs and shortcomings that are non-trivial\r
+ or impossible to fix: it doesn’t work with the direct mode, it doesn’t handle\r
+ C++ raw strings correctly, it can give false cache hits for <code>.incbin</code>\r
+ directives, it’s turned off when using <code>-g</code> and it can make line numbers in\r
+ warning messages and <code>__LINE__</code> macros incorrect.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+mtime and ctime values are now stored in the manifest files only when\r
+ sloppy_file_stat is set. This avoids adding superfluous manifest file entries\r
+ on direct mode cache misses.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+A “Result:” line is now always printed to the log.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+The “cache miss” statistics counter will now be updated for read-only cache\r
+ misses, making it consistent with the cache hit case.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
<h2 id="_ccache_3_7_6">ccache 3.7.6</h2>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2019-11-17</p></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
</ul></div>\r
</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: 2019-08-17</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: 2019-07-19</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
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2018-09-02</p></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: 2018-03-25</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: 2018-02-11</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
</ul></div>\r
</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
</ul></div>\r
</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
</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
</ul></div>\r
</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: 2016-10-26</p></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: 2016-09-28</p></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: 2016-09-07</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
</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-09-28</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: 2016-09-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: 2016-07-20</p></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: 2016-07-12</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
</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: 2015-10-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
</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
</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: 2014-12-10</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
</ul></div>\r
</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: 2016-07-12</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: 2015-03-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
</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: 2013-01-06</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="_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 class="sectionbody">\r
<div class="paragraph"><p>Release date: 2012-01-08</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_31">Bug fixes</h3>\r
+<h3 id="_bug_fixes_32">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_32">Bug fixes</h3>\r
+<h3 id="_bug_fixes_33">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_33">Bug fixes</h3>\r
+<h3 id="_bug_fixes_34">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_34">Bug fixes</h3>\r
+<h3 id="_bug_fixes_35">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_35">Bug fixes</h3>\r
+<h3 id="_bug_fixes_36">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_36">Bug fixes</h3>\r
+<h3 id="_bug_fixes_37">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_37">Bug fixes</h3>\r
+<h3 id="_bug_fixes_38">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_38">Bug fixes</h3>\r
+<h3 id="_bug_fixes_39">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_39">Bug fixes</h3>\r
+<h3 id="_bug_fixes_40">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_40">Bug fixes</h3>\r
+<h3 id="_bug_fixes_41">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.7.6<br />\r
+Version 3.7.7<br />\r
Last updated\r
- 2019-11-17 20:10:03 CET\r
+ 2020-01-05 21:09:39 CET\r
</div>\r
</div>\r
</body>\r
.\" Title: ccache
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 11/17/2019
+.\" Date: 01/05/2020
.\" Manual: ccache Manual
-.\" Source: ccache 3.7.6
+.\" Source: ccache 3.7.7
.\" Language: English
.\"
-.TH "CCACHE" "1" "11/17/2019" "ccache 3\&.7\&.6" "ccache Manual"
+.TH "CCACHE" "1" "01/05/2020" "ccache 3\&.7\&.7" "ccache Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.PP
\fBread_only\fR (\fBCCACHE_READONLY\fR or \fBCCACHE_NOREADONLY\fR, see Boolean values above)
.RS 4
-If true, ccache will attempt to use existing cached object files, but it will not to try to add anything new to the cache\&. If you are using this because your ccache directory is read\-only, then you need to set
+If true, ccache will attempt to use existing cached object files, but it will not add new results to the cache\&. Statistics counters will still be updated, though, unless the
+\fBstats\fR
+option is set to
+\fBfalse\fR\&.
+.sp
+If you are using this because your ccache directory is read\-only, you need to set
\fBtemporary_dir\fR
-as otherwise ccache will fail to create temporary files\&.
+since ccache will fail to create temporary files otherwise\&. You may also want to set
+\fBstats = false\fR
+to make ccache not even try to update stats files\&.
.RE
.PP
\fBread_only_direct\fR (\fBCCACHE_READONLY_DIRECT\fR or \fBCCACHE_NOREADONLY_DIRECT\fR, see Boolean values above)
.RS 4
This setting specifies the umask for ccache and all child processes (such as the compiler)\&. This is mostly useful when you wish to share your cache with other users\&. Note that this also affects the file permissions set on the object files created from your compilations\&.
.RE
-.PP
-\fBunify\fR (\fBCCACHE_UNIFY\fR or \fBCCACHE_NOUNIFY\fR, see Boolean values above)
-.RS 4
-If true, ccache will use a C/C++ unifier when hashing the preprocessor output if the
-\fB\-g\fR
-option is not used\&. The unifier is slower than a normal hash, so setting this environment variable loses a little bit of speed, but it means that ccache can take advantage of not recompiling when the changes to the source code consist of reformatting only\&. Note that enabling the unifier changes the hash, so cached compilations produced when the unifier is enabled cannot be reused when the unifier is disabled, and vice versa\&. Enabling the unifier may result in incorrect line number information in compiler warning messages and expansions of the
-\fB__LINE__\fR
-macro\&.
-.RE
.SH "CACHE SIZE MANAGEMENT"
.sp
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 -1
.IP \(bu 2.3
.\}
-the configuration setting
-\fBunify\fR
-is true
-.RE
-.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
the compiler is not generating dependencies using
\fB\-MD\fR
or
// ccache -- a fast C/C++ compiler cache
//
// Copyright (C) 2002-2007 Andrew Tridgell
-// Copyright (C) 2009-2019 Joel Rosdahl
+// Copyright (C) 2009-2020 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 "hashutil.h"
#include "language.h"
#include "manifest.h"
-#include "unify.h"
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
MYNAME " version %s\n"
"\n"
"Copyright (C) 2002-2007 Andrew Tridgell\n"
- "Copyright (C) 2009-2019 Joel Rosdahl\n"
+ "Copyright (C) 2009-2020 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"
if (!current_working_dir) {
cc_log("Unable to determine current working directory: %s",
strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
}
old_size = file_size(&st);
}
+ // See comment in get_file_hash_index for why saving of timestamps is forced
+ // for precompiled headers.
+ bool save_timestamp =
+ (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES)
+ || output_is_precompiled_header;
+
MTR_BEGIN("manifest", "manifest_put");
- if (manifest_put(manifest_path, cached_obj_hash, included_files)) {
+ if (manifest_put(manifest_path, cached_obj_hash, included_files,
+ save_timestamp)) {
cc_log("Added object file hash to %s", manifest_path);
if (x_stat(manifest_path, &st) == 0) {
stats_update_size(
if (x_rename(tmp_stderr, tmp_stderr2)) {
cc_log("Failed to rename %s to %s: %s", tmp_stderr, tmp_stderr2,
strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
int fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY);
if (fd_cpp_stderr == -1) {
cc_log("Failed opening %s: %s", cpp_stderr, strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
int fd_real_stderr = open(tmp_stderr2, O_RDONLY | O_BINARY);
if (fd_real_stderr == -1) {
cc_log("Failed opening %s: %s", tmp_stderr2, strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
open(tmp_stderr, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
if (fd_result == -1) {
cc_log("Failed opening %s: %s", tmp_stderr, strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
struct file_hash *object_hash =
object_hash_from_depfile(output_dep, depend_mode_hash);
if (!object_hash) {
+ stats_update(STATS_ERROR);
failed();
}
update_cached_result_globals(object_hash);
MTR_END("file", "file_put");
- stats_update(STATS_TOCACHE);
+ stats_update(STATS_CACHEMISS);
// Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can
// be done almost anywhere, but we might as well do it near the end as we
failed();
}
- if (conf->unify) {
- // When we are doing the unifying tricks we need to include the input file
- // name in the hash to get the warnings right.
- hash_delimiter(hash, "unifyfilename");
- hash_string(hash, input_file);
-
- hash_delimiter(hash, "unifycpp");
-
- bool debug_unify = getenv("CCACHE_DEBUG_UNIFY");
- if (unify_hash(hash, path_stdout, debug_unify) != 0) {
- stats_update(STATS_ERROR);
- cc_log("Failed to unify %s", path_stdout);
- failed();
- }
- } else {
- hash_delimiter(hash, "cpp");
- if (!process_preprocessed_file(hash, path_stdout,
- guessed_compiler == GUESSED_PUMP)) {
- stats_update(STATS_ERROR);
- failed();
- }
+ hash_delimiter(hash, "cpp");
+ if (!process_preprocessed_file(hash, path_stdout,
+ guessed_compiler == GUESSED_PUMP)) {
+ stats_update(STATS_ERROR);
+ failed();
}
hash_delimiter(hash, "cppstderr");
hash_delimiter(hash, "sourcecode");
int result = hash_source_code_file(conf, hash, input_file);
if (result & HASH_SOURCE_CODE_ERROR) {
+ stats_update(STATS_ERROR);
failed();
}
if (result & HASH_SOURCE_CODE_FOUND_TIME) {
i++;
if (i == argc) {
cc_log("--ccache-skip lacks an argument");
+ stats_update(STATS_ARGS);
result = false;
goto out;
}
// know what the user means, and what the compiler will do.
if (arg_profile_dir && profile_dir) {
cc_log("Profile directory already set; giving up");
+ stats_update(STATS_UNSUPPORTED_OPTION);
result = false;
goto out;
} else if (arg_profile_dir) {
}
} // 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;
}
if (!dependency_target_specified
- && !dependency_implicit_target_specified
- && !str_eq(get_extension(output_obj), ".o")) {
+ && !dependency_implicit_target_specified) {
args_add(dep_args, "-MQ");
args_add(dep_args, output_obj);
}
int uncached_fd = dup(2); // The file descriptor is intentionally leaked.
if (uncached_fd == -1) {
cc_log("dup(2) failed: %s", strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
char *buf = format("UNCACHED_ERR_FD=%d", uncached_fd);
if (putenv(buf) == -1) {
cc_log("putenv failed: %s", strerror(errno));
+ stats_update(STATS_ERROR);
failed();
}
}
if (conf->disable) {
cc_log("ccache is disabled");
+ stats_update(STATS_CACHEMISS); // Dummy to trigger stats_flush.
failed();
}
MTR_BEGIN("main", "process_args");
if (!cc_process_args(
orig_args, &preprocessor_args, &extra_args_to_hash, &compiler_args)) {
- failed();
+ failed(); // stats_update is called in cc_process_args.
}
MTR_END("main", "process_args");
if (conf->depend_mode
&& (!generating_dependencies || str_eq(output_dep, "/dev/null")
- || !conf->run_second_cpp || conf->unify)) {
+ || !conf->run_second_cpp)) {
cc_log("Disabling depend mode");
conf->depend_mode = false;
}
if (conf->read_only_direct) {
cc_log("Read-only direct mode; running real compiler");
+ stats_update(STATS_CACHEMISS);
failed();
}
if (conf->read_only) {
cc_log("Read-only mode; running real compiler");
+ stats_update(STATS_CACHEMISS);
failed();
}
// Copyright (C) 2002-2007 Andrew Tridgell
-// Copyright (C) 2009-2019 Joel Rosdahl
+// Copyright (C) 2009-2020 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
STATS_STDOUT = 1,
STATS_STATUS = 2,
STATS_ERROR = 3,
- STATS_TOCACHE = 4,
+ STATS_CACHEMISS = 4,
STATS_PREPROCESSOR = 5,
STATS_COMPILER = 6,
STATS_MISSING = 7,
conf->stats = true;
conf->temporary_dir = x_strdup("");
conf->umask = UINT_MAX; // Default: don't set umask.
- conf->unify = false;
conf->item_origins = x_malloc(confitems_count() * sizeof(char *));
for (size_t i = 0; i < confitems_count(); ++i) {
conf->item_origins[i] = "default";
ok &= print_item(conf, "stats", printer, context);
ok &= print_item(conf, "temporary_dir", printer, context);
ok &= print_item(conf, "umask", printer, context);
- ok &= print_item(conf, "unify", printer, context);
return ok;
}
bool stats;
char *temporary_dir;
unsigned umask;
- bool unify;
const char **item_origins;
};
stats, ITEM(stats, bool)
temporary_dir, ITEM(temporary_dir, env_string)
umask, ITEM(umask, umask)
-unify, ITEM(unify, bool)
50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 0, 35, 0,
5, 10, 50, 0, 30, 20, 50, 0, 10, 20,
- 15, 0, 0, 50, 5, 10, 10, 15, 50, 50,
+ 50, 0, 0, 50, 5, 10, 10, 15, 50, 50,
20, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
{
enum
{
- TOTAL_KEYWORDS = 34,
+ TOTAL_KEYWORDS = 33,
MIN_WORD_LENGTH = 4,
MAX_WORD_LENGTH = 26,
MIN_HASH_VALUE = 4,
{"disable", 11, ITEM(disable, bool)},
{"temporary_dir", 31, ITEM(temporary_dir, env_string)},
{"run_second_cpp", 28, ITEM(run_second_cpp, bool)},
- {"unify", 33, ITEM(unify, bool)},
+ {"",0,0,NULL,NULL,NULL},
{"direct_mode", 10, ITEM(direct_mode, bool)},
{"",0,0,NULL,NULL,NULL},
{"hash_dir", 14, ITEM(hash_dir, bool)},
}
return 0;
}
-size_t confitems_count(void) { return 34; }
+size_t confitems_count(void) { return 33; }
STATS, "stats"
TEMPDIR, "temporary_dir"
UMASK, "umask"
-UNIFY, "unify"
/* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf */
-/* Computed positions: -k'4-5' */
+/* Computed positions: -k'1,5' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
#include "envtoconfitems.h"
struct env_to_conf_item;
-/* maximum key range = 52, duplicates = 0 */
+/* maximum key range = 49, duplicates = 0 */
#ifdef __GNUC__
__inline
{
static const unsigned char asso_values[] =
{
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 0, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 25, 10, 0, 0, 5,
- 10, 0, 15, 0, 54, 10, 35, 25, 10, 25,
- 0, 54, 15, 20, 0, 0, 25, 54, 54, 15,
- 54, 54, 54, 54, 54, 0, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 30, 0, 0, 0,
+ 35, 51, 25, 5, 0, 51, 10, 15, 0, 10,
+ 5, 5, 5, 20, 20, 5, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51
};
register unsigned int hval = len;
switch (hval)
{
default:
- hval += asso_values[(unsigned char)str[4]];
+ hval += asso_values[(unsigned char)str[4]+1];
/*FALLTHROUGH*/
case 4:
- hval += asso_values[(unsigned char)str[3]];
- /*FALLTHROUGH*/
case 3:
case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
break;
}
return hval;
{
enum
{
- TOTAL_KEYWORDS = 35,
+ TOTAL_KEYWORDS = 34,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 15,
MIN_HASH_VALUE = 2,
- MAX_HASH_VALUE = 53
+ MAX_HASH_VALUE = 50
};
static const struct env_to_conf_item wordlist[] =
{"CC", "compiler"},
{"DIR", "cache_dir"},
{"CPP2", "run_second_cpp"},
- {"DEBUG", "debug"},
{"",""},
- {"TEMPDIR", "temporary_dir"},
+ {"DIRECT", "direct_mode"},
+ {"DISABLE", "disable"},
{"COMPILER", "compiler"},
+ {"PATH", "path"},
{"",""},
- {"SLOPPINESS", "sloppiness"},
- {"DIRECT", "direct_mode"},
- {"BASEDIR", "base_dir"},
- {"COMPILERCHECK", "compiler_check"},
- {"LIMIT_MULTIPLE", "limit_multiple"},
- {"PCH_EXTSUM", "pch_external_checksum"},
{"PREFIX", "prefix_command"},
- {"LOGFILE", "log_file"},
- {"MAXFILES", "max_files"},
- {"PATH", "path"},
+ {"RECACHE", "recache"},
+ {"COMPILERCHECK", "compiler_check"},
+ {"",""},
{"PREFIX_CPP", "prefix_command_cpp"},
{"DEPEND", "depend_mode"},
- {"HASHDIR", "hash_dir"},
- {"COMPRESS", "compression"},
+ {"LOGFILE", "log_file"},
+ {"READONLY", "read_only"},
{"EXTENSION", "cpp_extension"},
- {"STATS", "stats"},
+ {"UMASK", "umask"},
{"",""},
{"MAXSIZE", "max_size"},
+ {"MAXFILES", "max_files"},
+ {"",""},
+ {"READONLY_DIRECT", "read_only_direct"},
+ {"",""},
+ {"TEMPDIR", "temporary_dir"},
+ {"COMPRESS", "compression"},
+ {"LIMIT_MULTIPLE", "limit_multiple"},
+ {"DEBUG", "debug"},
+ {"",""},
+ {"HASHDIR", "hash_dir"},
{"COMPRESSLEVEL", "compression_level"},
{"",""},
- {"UNIFY", "unify"},
+ {"SLOPPINESS", "sloppiness"},
{"",""},
- {"RECACHE", "recache"},
- {"READONLY", "read_only"},
+ {"BASEDIR", "base_dir"},
+ {"IGNOREHEADERS", "ignore_headers_in_manifest"},
{"",""},
- {"UMASK", "umask"},
+ {"EXTRAFILES", "extra_files_to_hash"},
{"",""},
{"NLEVELS", "cache_dir_levels"},
{"COMMENTS", "keep_comments_cpp"},
{"",""},
- {"READONLY_DIRECT", "read_only_direct"},
- {"",""},
- {"DISABLE", "disable"},
- {"HARDLINK", "hard_link"},
- {"",""}, {"",""}, {"",""}, {"",""}, {"",""}, {"",""},
- {"EXTRAFILES", "extra_files_to_hash"},
+ {"STATS", "stats"},
{"",""}, {"",""},
- {"IGNOREHEADERS", "ignore_headers_in_manifest"}
+ {"HARDLINK", "hard_link"},
+ {"",""},
+ {"PCH_EXTSUM", "pch_external_checksum"}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
}
return 0;
}
-size_t envtoconfitems_count(void) { return 35; }
+size_t envtoconfitems_count(void) { return 34; }
-// 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
char *path,
struct file_hash *file_hash,
struct hashtable *mf_files,
- struct hashtable *mf_file_infos)
+ struct hashtable *mf_file_infos,
+ bool save_timestamp)
{
struct file_info fi;
fi.index = get_include_file_index(mf, path, mf_files);
//
// st->ctime may be 0, so we have to check time_of_compilation against
// MAX(mtime, ctime).
+ //
+ // ccache only reads mtime/ctime if file_stat_match sloppiness is enabled, so
+ // mtimes/ctimes are stored as a dummy value (-1) if not enabled. This reduces
+ // the number of file_info entries for the common case.
struct stat file_stat;
- if (stat(path, &file_stat) != -1
+ if (save_timestamp && stat(path, &file_stat) != -1
&& time_of_compilation > MAX(file_stat.st_mtime, file_stat.st_ctime)) {
fi.mtime = file_stat.st_mtime;
fi.ctime = file_stat.st_ctime;
static void
add_file_info_indexes(uint32_t *indexes, uint32_t size,
- struct manifest *mf, struct hashtable *included_files)
+ struct manifest *mf, struct hashtable *included_files,
+ bool save_timestamp)
{
if (size == 0) {
return;
char *path = hashtable_iterator_key(iter);
struct file_hash *file_hash = hashtable_iterator_value(iter);
indexes[i] = get_file_hash_index(mf, path, file_hash, mf_files,
- mf_file_infos);
+ mf_file_infos, save_timestamp);
i++;
} while (hashtable_iterator_advance(iter));
assert(i == size);
static void
add_object_entry(struct manifest *mf,
struct file_hash *object_hash,
- struct hashtable *included_files)
+ struct hashtable *included_files,
+ bool save_timestamp)
{
uint32_t n_objs = mf->n_objects;
mf->objects = x_realloc(mf->objects, (n_objs + 1) * sizeof(*mf->objects));
uint32_t n_fii = hashtable_count(included_files);
obj->n_file_info_indexes = n_fii;
obj->file_info_indexes = x_malloc(n_fii * sizeof(*obj->file_info_indexes));
- add_file_info_indexes(obj->file_info_indexes, n_fii, mf, included_files);
+ add_file_info_indexes(obj->file_info_indexes, n_fii, mf, included_files,
+ save_timestamp);
memcpy(obj->hash.hash, object_hash->hash, mf->hash_size);
obj->hash.size = object_hash->size;
}
// Returns true on success, otherwise false.
bool
manifest_put(const char *manifest_path, struct file_hash *object_hash,
- struct hashtable *included_files)
+ struct hashtable *included_files, bool save_timestamp)
{
int ret = 0;
gzFile f2 = NULL;
goto out;
}
- add_object_entry(mf, object_hash, included_files);
+ add_object_entry(mf, object_hash, included_files, save_timestamp);
if (write_manifest(f2, mf)) {
gzclose(f2);
f2 = NULL;
struct file_hash *manifest_get(struct conf *conf, const char *manifest_path);
bool manifest_put(const char *manifest_path, struct file_hash *object_hash,
- struct hashtable *included_files);
+ struct hashtable *included_files, bool save_timestamp);
bool manifest_dump(const char *manifest_path, FILE *stream);
#endif
// Copyright (C) 2002-2004 Andrew Tridgell
-// Copyright (C) 2009-2019 Joel Rosdahl
+// Copyright (C) 2009-2020 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
FLAG_ALWAYS
},
{
- STATS_TOCACHE,
+ STATS_CACHEMISS,
"cache_miss",
"cache miss",
NULL,
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 miss = counters->data[STATS_CACHEMISS];
unsigned total = hit + miss;
return total > 0 ? (100.0 * hit) / total : 0.0;
}
{
assert(conf);
- if (!conf->stats) {
+ if (!updates) {
return;
}
- if (!updates) {
+ if (conf->disable) {
+ // Just log result, don't update statistics.
+ cc_log("Result: disabled");
+ return;
+ }
+
+ if (!str_eq(conf->log_file, "") || conf->debug) {
+ for (int i = 0; i < STATS_END; ++i) {
+ if (updates->data[stats_info[i].stat] != 0
+ && !(stats_info[i].flags & FLAG_NOZERO)) {
+ cc_log("Result: %s", stats_info[i].message);
+ }
+ }
+ }
+
+ if (!conf->stats) {
return;
}
stats_write(sfile, counters);
lockfile_release(sfile);
- if (!str_eq(conf->log_file, "") || conf->debug) {
- for (int i = 0; i < STATS_END; ++i) {
- if (updates->data[stats_info[i].stat] != 0
- && !(stats_info[i].flags & FLAG_NOZERO)) {
- cc_log("Result: %s", stats_info[i].message);
- }
- }
- }
-
char *subdir = dirname(sfile);
bool need_cleanup = false;
free(value);
}
- if (stat == STATS_TOCACHE) {
+ if (stat == STATS_CACHEMISS) {
double percent = stats_hit_rate(counters);
printf("cache hit rate %6.2f %%\n", percent);
}
+++ /dev/null
-// Copyright (C) 2002 Andrew Tridgell
-// 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 Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-// C/C++ unifier
-//
-// The idea is that changes that don't affect the resulting C code should not
-// change the hash. This is achieved by folding white-space and other
-// non-semantic fluff in the input into a single unified format.
-//
-// This unifier was design to match the output of the unifier in compilercache,
-// which is flex based. The major difference is that this unifier is much
-// faster (about 2x) and more forgiving of syntactic errors. Continuing on
-// syntactic errors is important to cope with C/C++ extensions in the local
-// compiler (for example, inline assembly systems).
-
-#include "ccache.h"
-#include "hash.h"
-#include "unify.h"
-
-static bool print_unified = true;
-
-static const char *const s_tokens[] = {
- "...", ">>=", "<<=", "+=", "-=", "*=", "/=", "%=", "&=", "^=",
- "|=", ">>", "<<", "++", "--", "->", "&&", "||", "<=", ">=",
- "==", "!=", ";", "{", "<%", "}", "%>", ",", ":", "=",
- "(", ")", "[", "<:", "]", ":>", ".", "&", "!", "~",
- "-", "+", "*", "/", "%", "<", ">", "^", "|", "?",
- 0
-};
-
-#define C_ALPHA 1
-#define C_SPACE 2
-#define C_TOKEN 4
-#define C_QUOTE 8
-#define C_DIGIT 16
-#define C_HEX 32
-#define C_FLOAT 64
-#define C_SIGN 128
-
-static struct {
- unsigned char type;
- unsigned char num_toks;
- const char *toks[7];
-} tokens[256];
-
-// Build up the table used by the unifier.
-static void
-build_table(void)
-{
- static bool done;
- if (done) {
- return;
- }
- done = true;
-
- memset(tokens, 0, sizeof(tokens));
- for (unsigned char c = 0; c < 128; c++) {
- if (isalpha(c) || c == '_') {
- tokens[c].type |= C_ALPHA;
- }
- if (isdigit(c)) {
- tokens[c].type |= C_DIGIT;
- }
- if (isspace(c)) {
- tokens[c].type |= C_SPACE;
- }
- if (isxdigit(c)) {
- tokens[c].type |= C_HEX;
- }
- }
- tokens['\''].type |= C_QUOTE;
- tokens['"'].type |= C_QUOTE;
- tokens['l'].type |= C_FLOAT;
- tokens['L'].type |= C_FLOAT;
- tokens['f'].type |= C_FLOAT;
- tokens['F'].type |= C_FLOAT;
- tokens['U'].type |= C_FLOAT;
- tokens['u'].type |= C_FLOAT;
-
- tokens['-'].type |= C_SIGN;
- tokens['+'].type |= C_SIGN;
-
- for (int i = 0; s_tokens[i]; i++) {
- unsigned char c = s_tokens[i][0];
- tokens[c].type |= C_TOKEN;
- tokens[c].toks[tokens[c].num_toks] = s_tokens[i];
- tokens[c].num_toks++;
- }
-}
-
-// Buffer up characters before hashing them.
-static void
-pushchar(struct hash *hash, unsigned char c)
-{
- static unsigned char buf[64];
- static size_t len;
-
- if (c == 0) {
- if (len > 0) {
- hash_buffer(hash, (char *)buf, len);
- if (print_unified) {
- printf("%.*s", (int) len, buf);
- }
- len = 0;
- }
- return;
- }
-
- buf[len++] = c;
- if (len == 64) {
- hash_buffer(hash, (char *)buf, len);
- if (print_unified) {
- printf("%.*s", (int) len, buf);
- }
- len = 0;
- }
-}
-
-// Hash some C/C++ code after unifying.
-static void
-unify(struct hash *hash, unsigned char *p, size_t size)
-{
- build_table();
-
- for (size_t ofs = 0; ofs < size;) {
- if (p[ofs] == '#') {
- if ((size-ofs) > 2 && p[ofs+1] == ' ' && isdigit(p[ofs+2])) {
- do {
- ofs++;
- } while (ofs < size && p[ofs] != '\n');
- ofs++;
- } else {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size && p[ofs] != '\n');
- pushchar(hash, '\n');
- ofs++;
- }
- continue;
- }
-
- if (tokens[p[ofs]].type & C_ALPHA) {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size && (tokens[p[ofs]].type & (C_ALPHA|C_DIGIT)));
- pushchar(hash, '\n');
- continue;
- }
-
- if (tokens[p[ofs]].type & C_DIGIT) {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size &&
- ((tokens[p[ofs]].type & C_DIGIT) || p[ofs] == '.'));
- if (ofs < size && (p[ofs] == 'x' || p[ofs] == 'X')) {
- do {
- pushchar(hash, p[ofs]);
- ofs++;
- } while (ofs < size && (tokens[p[ofs]].type & C_HEX));
- }
- if (ofs < size && (p[ofs] == 'E' || p[ofs] == 'e')) {
- pushchar(hash, p[ofs]);
- ofs++;
- while (ofs < size && (tokens[p[ofs]].type & (C_DIGIT|C_SIGN))) {
- pushchar(hash, p[ofs]);
- ofs++;
- }
- }
- while (ofs < size && (tokens[p[ofs]].type & C_FLOAT)) {
- pushchar(hash, p[ofs]);
- ofs++;
- }
- pushchar(hash, '\n');
- continue;
- }
-
- if (tokens[p[ofs]].type & C_SPACE) {
- do {
- ofs++;
- } while (ofs < size && (tokens[p[ofs]].type & C_SPACE));
- continue;
- }
-
- if (tokens[p[ofs]].type & C_QUOTE) {
- unsigned char q = p[ofs];
- pushchar(hash, p[ofs]);
- do {
- ofs++;
- while (ofs < size-1 && p[ofs] == '\\') {
- pushchar(hash, p[ofs]);
- pushchar(hash, p[ofs+1]);
- ofs += 2;
- }
- pushchar(hash, p[ofs]);
- } while (ofs < size && p[ofs] != q);
- pushchar(hash, '\n');
- ofs++;
- continue;
- }
-
- if (tokens[p[ofs]].type & C_TOKEN) {
- unsigned char q = p[ofs];
- int i;
- for (i = 0; i < tokens[q].num_toks; i++) {
- const unsigned char *s = (const unsigned char *)tokens[q].toks[i];
- int len = strlen((const char *)s);
- if (size >= ofs+len && memcmp(&p[ofs], s, len) == 0) {
- int j;
- for (j = 0; s[j]; j++) {
- pushchar(hash, s[j]);
- ofs++;
- }
- pushchar(hash, '\n');
- break;
- }
- }
- if (i < tokens[q].num_toks) {
- continue;
- }
- }
-
- pushchar(hash, p[ofs]);
- pushchar(hash, '\n');
- ofs++;
- }
- pushchar(hash, 0);
-}
-
-
-// Hash a file that consists of preprocessor output, but remove any line number
-// information from the hash.
-int
-unify_hash(struct hash *hash, const char *fname, bool debug)
-{
- char *data;
- size_t size;
- if (!read_file(fname, 0, &data, &size)) {
- stats_update(STATS_PREPROCESSOR);
- return -1;
- }
- print_unified = debug;
- unify(hash, (unsigned char *)data, size);
- free(data);
- return 0;
-}
+++ /dev/null
-// Copyright (C) 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 Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#ifndef UNIFY_H
-#define UNIFY_H
-
-#include "hash.h"
-
-int unify_hash(struct hash *hash, const char *fname, bool print);
-
-#endif
-extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7.6";
+extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7.7";
expect_stat 'cache hit (preprocessed)' 2
expect_stat 'cache miss' 1
- # -------------------------------------------------------------------------
- TEST "CCACHE_UNIFY"
-
- echo '// a silly comment' >>test1.c
- CCACHE_UNIFY=1 $CCACHE_COMPILE -c test1.c
- expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
-
- echo '// another silly comment' >>test1.c
- CCACHE_UNIFY=1 $CCACHE_COMPILE -c test1.c
- expect_stat 'cache hit (preprocessed)' 1
- expect_stat 'cache miss' 1
-
- $REAL_COMPILER -c -o reference_test1.o test1.c
- expect_equal_object_files reference_test1.o test1.o
-
# -------------------------------------------------------------------------
TEST "CCACHE_NLEVELS"
expect_stat 'cache miss' 2
expect_stat 'files in cache' 2
+ # -------------------------------------------------------------------------
+ TEST "Dependency file content"
+
+ mkdir build
+ cp test1.c build
+
+ for src in test1.c build/test1.c; do
+ for obj in test1.o build/test1.o; do
+ $CCACHE_COMPILE -c -MMD $src -o $obj
+ dep=$(echo $obj | sed 's/\.o$/.d/')
+ expect_file_content $dep "$obj: $src"
+ done
+ done
+
# -------------------------------------------------------------------------
TEST "Buggy GCC 6 cpp"
fi
# -------------------------------------------------------------------------
+if ! $HOST_OS_WINDOWS; then
TEST ".incbin"
cat <<EOF >incbin.c
-char x[] = ".incbin";
+__asm__(".incbin \"/dev/null\"");
EOF
$CCACHE_COMPILE -c incbin.c
expect_stat 'cache miss' 0
expect_stat 'unsupported code directive' 1
+ cat <<EOF >incbin.s
+.incbin "/dev/null";
+EOF
+
+ $CCACHE_COMPILE -c incbin.s
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 0
+ expect_stat 'unsupported code directive' 2
+fi
+
# -------------------------------------------------------------------------
TEST "UNCACHED_ERR_FD"
mkdir a b
touch a/source.c b/source.c
backdate a/source.h b/source.h
- $CCACHE_COMPILE -MMD -c a/source.c
- expect_file_content source.d "source.o: a/source.c"
+ $CCACHE_COMPILE -MMD -c a/source.c -o a/source.o
+ expect_file_content a/source.d "a/source.o: a/source.c"
- $CCACHE_COMPILE -MMD -c b/source.c
- expect_file_content source.d "source.o: b/source.c"
+ $CCACHE_COMPILE -MMD -c b/source.c -o b/source.o
+ expect_file_content b/source.d "b/source.o: b/source.c"
- $CCACHE_COMPILE -MMD -c a/source.c
- expect_file_content source.d "source.o: a/source.c"
+ $CCACHE_COMPILE -MMD -c a/source.c -o a/source.o
+ expect_file_content a/source.d "a/source.o: a/source.c"
+
+ # -------------------------------------------------------------------------
+ TEST "Dependency file content"
+
+ mkdir build
+ touch test1.c
+ cp test1.c build
+
+ for src in test1.c build/test1.c; do
+ for obj in test1.o build/test1.o; do
+ $CCACHE_COMPILE -c -MMD $src -o $obj
+ dep=$(echo $obj | sed 's/\.o$/.d/')
+ expect_file_content $dep "$obj: $src"
+ done
+ done
# -------------------------------------------------------------------------
TEST "-MMD for different include file paths"
if [ $? -ne 0 ]; then
test_failed "Failure when compiling test2.c read-only"
fi
- if [ -d $CCACHE_DIR ]; then
- test_failed "ccache dir was created"
- fi
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+ expect_stat 'files in cache' 0
# -------------------------------------------------------------------------
# Check that read-only mode and direct mode work together.
CCACHE_READONLY_DIRECT=1 $CCACHE_COMPILE -DFOO -c test.c -o test.o
expect_stat 'cache hit (direct)' 0
expect_stat 'cache hit (preprocessed)' 0
- expect_stat 'cache miss' 1
+ expect_stat 'cache miss' 2
}
-// Copyright (C) 2010-2019 Joel Rosdahl
+// Copyright (C) 2010-2020 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(orig);
}
-TEST(MQ_flag_should_not_be_added_for_standard_obj_extension)
-{
- struct args *orig = args_init_from_string("cc -c -MD foo.c -o foo.o");
- struct args *exp_cpp = args_init_from_string("cc -MD -MF foo.d");
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, NULL, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
-}
-
-TEST(MQ_flag_should_be_added_for_non_standard_obj_extension)
-{
- struct args *orig = args_init_from_string("cc -c -MD foo.c -o foo.obj");
- struct args *exp_cpp = args_init_from_string("cc -MD -MF foo.d -MQ foo.obj");
- struct args *exp_cc = args_init_from_string("cc -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, NULL, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
-}
-
TEST(equal_sign_after_MF_should_be_removed)
{
struct args *orig = args_init_from_string("cc -c -MF=path foo.c -o foo.o");
#include "framework.h"
#include "util.h"
-#define N_CONFIG_ITEMS 34
+#define N_CONFIG_ITEMS 33
static struct {
char *descr;
char *origin;
CHECK(conf->stats);
CHECK_STR_EQ("", conf->temporary_dir);
CHECK_INT_EQ(UINT_MAX, conf->umask);
- CHECK(!conf->unify);
conf_free(conf);
}
"sloppiness = time_macros ,include_file_mtime include_file_ctime,file_stat_matches,file_stat_matches_ctime,pch_defines , no_system_headers,system_headers,clang_index_store\n"
"stats = false\n"
"temporary_dir = ${USER}_foo\n"
- "umask = 777\n"
- "unify = true"); // Note: no newline.
+ "umask = 777"); // Note: no newline.
CHECK(conf_read(conf, "ccache.conf", &errmsg));
CHECK(!errmsg);
CHECK(!conf->stats);
CHECK_STR_EQ_FREE1(format("%s_foo", user), conf->temporary_dir);
CHECK_INT_EQ(0777, conf->umask);
- CHECK(conf->unify);
conf_free(conf);
}
false,
"td",
022,
- true,
NULL
};
size_t n = 0;
CHECK_STR_EQ("stats = false", received_conf_items[n++].descr);
CHECK_STR_EQ("temporary_dir = td", received_conf_items[n++].descr);
CHECK_STR_EQ("umask = 022", received_conf_items[n++].descr);
- CHECK_STR_EQ("unify = true", received_conf_items[n++].descr);
for (i = 0; i < N_CONFIG_ITEMS; ++i) {
#ifndef __MINGW32__