diff options
author | JinWang An <jinwang.an@samsung.com> | 2021-08-03 16:16:40 +0900 |
---|---|---|
committer | JinWang An <jinwang.an@samsung.com> | 2021-08-03 16:16:40 +0900 |
commit | dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5 (patch) | |
tree | 34f25517871bedf01569c9166e175c13bf91b3aa | |
parent | 335f2c0f9f8337f0f8b5d7ecaf4c38f67b77b5f5 (diff) | |
download | ccache-dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5.tar.gz ccache-dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5.tar.bz2 ccache-dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5.zip |
Imported Upstream version 3.2.2upstream/3.2.2
-rw-r--r-- | AUTHORS.html | 32 | ||||
-rw-r--r-- | AUTHORS.txt | 5 | ||||
-rw-r--r-- | INSTALL.html | 7 | ||||
-rw-r--r-- | LICENSE.html | 13 | ||||
-rw-r--r-- | LICENSE.txt | 6 | ||||
-rw-r--r-- | MANUAL.html | 16 | ||||
-rw-r--r-- | MANUAL.txt | 3 | ||||
-rw-r--r-- | NEWS.html | 176 | ||||
-rw-r--r-- | NEWS.txt | 69 | ||||
-rw-r--r-- | README.html | 7 | ||||
-rw-r--r-- | ccache.1 | 13 | ||||
-rw-r--r-- | ccache.c | 362 | ||||
-rw-r--r-- | ccache.h | 10 | ||||
-rw-r--r-- | cleanup.c | 6 | ||||
-rw-r--r-- | compopt.c | 6 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | confitems_lookup.c | 1 | ||||
-rw-r--r-- | dev.mk.in | 2 | ||||
-rw-r--r-- | envtoconfitems_lookup.c | 1 | ||||
-rw-r--r-- | execute.c | 88 | ||||
-rw-r--r-- | hash.c | 1 | ||||
-rw-r--r-- | hashutil.c | 6 | ||||
-rw-r--r-- | lockfile.c | 17 | ||||
-rw-r--r-- | manifest.c | 5 | ||||
-rw-r--r-- | stats.c | 4 | ||||
-rwxr-xr-x | test.sh | 122 | ||||
-rw-r--r-- | test/test_compopt.c | 10 | ||||
-rw-r--r-- | util.c | 228 | ||||
-rw-r--r-- | version.c | 2 |
30 files changed, 981 insertions, 248 deletions
diff --git a/AUTHORS.html b/AUTHORS.html index f6931c2..5c61970 100644 --- a/AUTHORS.html +++ b/AUTHORS.html @@ -734,7 +734,7 @@ asciidoc.install(2); <body class="article">
<div id="header">
<h1>ccache authors</h1>
-<span id="revnumber">version 3.2.1</span>
+<span id="revnumber">version 3.2.2</span>
<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> @@ -754,6 +754,11 @@ Alfred Landrum <<a href="mailto:alfred.landrum@riverbed.com">alfred.landrum@r </li>
<li>
<p>
+Anders Björklund <<a href="mailto:anders@itension.se">anders@itension.se</a>>
+</p>
+</li>
+<li>
+<p>
Andrea Bittau <<a href="mailto:a.bittau@cs.ucl.ac.uk">a.bittau@cs.ucl.ac.uk</a>>
</p>
</li>
@@ -789,6 +794,11 @@ Bo Rydberg <<a href="mailto:bolry@hotmail.com">bolry@hotmail.com</a>> </li>
<li>
<p>
+Chiaki ISHIKAWA <<a href="mailto:ishikawa@yk.rim.or.jp">ishikawa@yk.rim.or.jp</a>>
+</p>
+</li>
+<li>
+<p>
Chris AtLee <<a href="mailto:chris@atlee.ca">chris@atlee.ca</a>>
</p>
</li>
@@ -819,6 +829,11 @@ Hongli Lai <<a href="mailto:hongli@phusion.nl">hongli@phusion.nl</a>> </li>
<li>
<p>
+Jiang Jiang <<a href="mailto:jiangj@opera.com">jiangj@opera.com</a>>
+</p>
+</li>
+<li>
+<p>
Joel Rosdahl <<a href="mailto:joel@rosdahl.net">joel@rosdahl.net</a>>
</p>
</li>
@@ -864,6 +879,11 @@ Lars Gustäbel <<a href="mailto:lars@gustaebel.de">lars@gustaebel.de</a>> </li>
<li>
<p>
+Leanid Chaika <<a href="mailto:leanid.chaika@gmail.com">leanid.chaika@gmail.com</a>>
+</p>
+</li>
+<li>
+<p>
Luboš Luňák <<a href="mailto:l.lunak@suse.cz">l.lunak@suse.cz</a>>
</p>
</li>
@@ -924,6 +944,11 @@ Robin H. Johnson <<a href="mailto:robbat2@gentoo.org">robbat2@gentoo.org</a>& </li>
<li>
<p>
+Ryb <<a href="mailto:ryb@ableton.com">ryb@ableton.com</a>>
+</p>
+</li>
+<li>
+<p>
Tim Potter <<a href="mailto:tpot@samba.org">tpot@samba.org</a>>
</p>
</li>
@@ -960,8 +985,9 @@ Yiding Jia <<a href="mailto:yiding@fb.com">yiding@fb.com</a>> <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Version 3.2.1<br />
-Last updated 2014-12-09 21:16:57 CET
+Version 3.2.2<br />
+Last updated
+ 2015-05-10 14:23:01 CEST
</div>
</div>
</body>
diff --git a/AUTHORS.txt b/AUTHORS.txt index 391000b..5484fe7 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -7,6 +7,7 @@ maintained by Joel Rosdahl. ccache is a collective work with contributions from many people, including: * Alfred Landrum <alfred.landrum@riverbed.com> +* Anders Björklund <anders@itension.se> * Andrea Bittau <a.bittau@cs.ucl.ac.uk> * Andrew P Boie <andrew.p.boie@intel.com> * Andrew Stubbs <ams@codesourcery.com> @@ -14,12 +15,14 @@ ccache is a collective work with contributions from many people, including: * Bernhard Bauer <bauerb@chromium.org> * Björn Jacke <bj@sernet.de> * Bo Rydberg <bolry@hotmail.com> +* Chiaki ISHIKAWA <ishikawa@yk.rim.or.jp> * Chris AtLee <chris@atlee.ca> * Clemens Rabe <crabe@gmx.de> * David Givone <david@givone.net> * Eric Blau <Eric.Blau@tekelec.com> * Francois Marier <francois@debian.org> * Hongli Lai <hongli@phusion.nl> +* Jiang Jiang <jiangj@opera.com> * Joel Rosdahl <joel@rosdahl.net> * John Coiner <john.coiner@amd.com> * Jon Bernard <jbernard@tuxion.com> @@ -29,6 +32,7 @@ ccache is a collective work with contributions from many people, including: * Kovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com> * Lalit Chhabra <lchhabra@linuxmail.org> * Lars Gustäbel <lars@gustaebel.de> +* Leanid Chaika <leanid.chaika@gmail.com> * Luboš Luňák <l.lunak@suse.cz> * Mark Starovoytov <starovoytov.mark@googlemail.com> * Martin Pool <mbp@sourcefrog.net> @@ -41,6 +45,7 @@ ccache is a collective work with contributions from many people, including: * RW <fbsd06@mlists.homeunix.com> * Ramiro Polla <ramiro.polla@gmail.com> * Robin H. Johnson <robbat2@gentoo.org> +* Ryb <ryb@ableton.com> * Tim Potter <tpot@samba.org> * Tor Arne Vestbø <torarnv@gmail.com> * Ville Skyttä <ville.skytta@iki.fi> diff --git a/INSTALL.html b/INSTALL.html index 734cbc4..1a55552 100644 --- a/INSTALL.html +++ b/INSTALL.html @@ -734,7 +734,7 @@ asciidoc.install(2); <body class="article">
<div id="header">
<h1>ccache installation</h1>
-<span id="revnumber">version 3.2.1</span>
+<span id="revnumber">version 3.2.2</span>
<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> @@ -853,8 +853,9 @@ above.</p></div> <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Version 3.2.1<br />
-Last updated 2014-12-09 21:16:57 CET
+Version 3.2.2<br />
+Last updated
+ 2015-03-09 20:26:56 CET
</div>
</div>
</body>
diff --git a/LICENSE.html b/LICENSE.html index 6def0cd..bb45699 100644 --- a/LICENSE.html +++ b/LICENSE.html @@ -734,7 +734,7 @@ asciidoc.install(2); <body class="article">
<div id="header">
<h1>ccache copyright and license</h1>
-<span id="revnumber">version 3.2.1</span>
+<span id="revnumber">version 3.2.2</span>
<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> @@ -776,7 +776,7 @@ copyrights on their portions of the work.</p></div> <div class="listingblock">
<div class="content">
<pre><code> Copyright (C) 2002-2007 Andrew Tridgell
- Copyright (C) 2009-2011 Joel Rosdahl</code></pre>
+ Copyright (C) 2009-2015 Joel Rosdahl</code></pre>
</div></div>
</div>
</div>
@@ -1173,11 +1173,11 @@ Appleby. See <a href="http://murmurhash.googlepages.com">http://murmurhash.googl </div>
<div class="sect2">
<h3 id="_zlib_hc">zlib/*.[hc]</h3>
-<div class="paragraph"><p>This is a bundled subset of zlib 1.2.5 from <a href="http://zlib.net">http://zlib.net</a> with the
+<div class="paragraph"><p>This is a bundled subset of zlib 1.2.8 from <a href="http://zlib.net">http://zlib.net</a> with the
following license:</p></div>
<div class="listingblock">
<div class="content">
-<pre><code> Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+<pre><code> Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -1205,8 +1205,9 @@ following license:</p></div> <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Version 3.2.1<br />
-Last updated 2014-12-09 21:16:57 CET
+Version 3.2.2<br />
+Last updated
+ 2015-04-19 13:27:37 CEST
</div>
</div>
</body>
diff --git a/LICENSE.txt b/LICENSE.txt index 7186d5a..5d32ea2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -38,7 +38,7 @@ The copyright for ccache as a whole is as follows: ------------------------------------------------------------------------------- Copyright (C) 2002-2007 Andrew Tridgell - Copyright (C) 2009-2011 Joel Rosdahl + Copyright (C) 2009-2015 Joel Rosdahl ------------------------------------------------------------------------------- @@ -448,11 +448,11 @@ http://www.jhweiss.de/software/snprintf.html and has the following license: zlib/*.[hc] ~~~~~~~~~~~ -This is a bundled subset of zlib 1.2.5 from <http://zlib.net> with the +This is a bundled subset of zlib 1.2.8 from <http://zlib.net> with the following license: ------------------------------------------------------------------------------- - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/MANUAL.html b/MANUAL.html index 57a922d..d5bf2f8 100644 --- a/MANUAL.html +++ b/MANUAL.html @@ -734,7 +734,7 @@ asciidoc.install(2); <body class="article">
<div id="header">
<h1>CCACHE(1)</h1>
-<span id="revnumber">version 3.2.1</span>
+<span id="revnumber">version 3.2.2</span>
<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> @@ -1157,6 +1157,15 @@ setting key. Boolean options are indicated with “[boolean]”</p></div </p>
</dd>
<dt class="hdlist1">
+<strong>string:value</strong>
+</dt>
+<dd>
+<p>
+ Use <strong>value</strong> as the string to calculate hash from. This can be the compiler
+ revision number you retrieved earlier and set here via environment variable.
+</p>
+</dd>
+<dt class="hdlist1">
<em>a command string</em>
</dt>
<dd>
@@ -2160,8 +2169,9 @@ maintained by Joel Rosdahl. See AUTHORS.txt or AUTHORS.html and <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Version 3.2.1<br />
-Last updated 2014-12-09 21:16:57 CET
+Version 3.2.2<br />
+Last updated
+ 2015-04-19 13:27:37 CEST
</div>
</div>
</body>
@@ -281,6 +281,9 @@ setting key. Boolean options are indicated with ``[boolean]'' compiler's source has not changed, or if the compiler only has changes that don't affect code generation). You should only use the *none* setting if you know what you are doing. +*string:value*:: + Use *value* as the string to calculate hash from. This can be the compiler + revision number you retrieved earlier and set here via environment variable. _a command string_:: Hash the standard output and standard error output of the specified command. The string will be split on whitespace to find out the command and @@ -734,7 +734,7 @@ asciidoc.install(2); <body class="article">
<div id="header">
<h1>ccache news</h1>
-<span id="revnumber">version 3.2.1</span>
+<span id="revnumber">version 3.2.2</span>
<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> @@ -742,11 +742,105 @@ asciidoc.install(2); </div>
<div id="content">
<div class="sect1">
+<h2 id="_ccache_3_2_2">ccache 3.2.2</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Release date: 2015-05-10</p></div>
+<div class="sect2">
+<h3 id="_new_features_and_improvements">New features and improvements</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+Added support for <code>CCACHE_COMPILERCHECK=string:<value></code>. This is a faster
+ alternative to <code>CCACHE_COMPILERCHECK=<command></code> if the command’s output can
+ be precalculated by the build system.
+</p>
+</li>
+<li>
+<p>
+Add support for caching code coverage results (compiling for gcov).
+</p>
+</li>
+</ul></div>
+</div>
+<div class="sect2">
+<h3 id="_bug_fixes">Bug fixes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed bug which could result in false cache hits when source code contains
+ <code>'"'</code> followed by <code>" /*"</code> or <code>" //"</code> (with variations).
+</p>
+</li>
+<li>
+<p>
+Made hash of cached result created with and without <code>CCACHE_CPP2</code> different.
+ This makes it possible to rebuild with <code>CCACHE_CPP2</code> set without having to
+ clear the cache to get new results.
+</p>
+</li>
+<li>
+<p>
+Don’t try to reset a non-existing stats file. This avoids “No such file or
+ directory” messages in the ccache log when the cache directory doesn’t
+ exist.
+</p>
+</li>
+<li>
+<p>
+Fixed a bug where ccache deleted clang diagnostics after compiler failures.
+</p>
+</li>
+<li>
+<p>
+Avoid performing an unnecessary copy of the object file on a cache miss.
+</p>
+</li>
+<li>
+<p>
+Bail out on too hard compiler option <code>-fmodules</code>.
+</p>
+</li>
+<li>
+<p>
+Bail out on too hard compiler option <code>-fplugin=libcc1plugin</code> (interaction
+ with GDB).
+</p>
+</li>
+<li>
+<p>
+Fixed build error when compiling ccache with recent clang versions.
+</p>
+</li>
+<li>
+<p>
+Removed signal-unsafe code from signal handler.
+</p>
+</li>
+<li>
+<p>
+Corrected logic for when to output cached stderr.
+</p>
+</li>
+<li>
+<p>
+Wipe the whole cached result on failure retrieving a cached file.
+</p>
+</li>
+<li>
+<p>
+Fixed build error when compiling ccache with recent clang versions.
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+</div>
+<div class="sect1">
<h2 id="_ccache_3_2_1">ccache 3.2.1</h2>
<div class="sectionbody">
<div class="paragraph"><p>Release date: 2014-12-10</p></div>
<div class="sect2">
-<h3 id="_bug_fixes">Bug fixes</h3>
+<h3 id="_bug_fixes_2">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -787,7 +881,7 @@ Added missing documentation for <code>max_files</code> and <code>max_size</code> <div class="sectionbody">
<div class="paragraph"><p>Release date: 2014-11-17</p></div>
<div class="sect2">
-<h3 id="_new_features_and_improvements">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_2">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -978,7 +1072,7 @@ Various other improvements of the test suite. </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_2">Bug fixes</h3>
+<h3 id="_bug_fixes_3">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1005,11 +1099,42 @@ Fixed test suite failures when <code>CC</code> is a ccache-wrapped compiler. </div>
</div>
<div class="sect1">
+<h2 id="_ccache_3_1_11">ccache 3.1.11</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Release date: 2015-03-07</p></div>
+<div class="sect2">
+<h3 id="_bug_fixes_4">Bug fixes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed bug which could result in false cache hits when source code contains
+ <code>'"'</code> followed by <code>" /*"</code> or <code>" //"</code> (with variations).
+</p>
+</li>
+<li>
+<p>
+Made hash of cached result created with and without <code>CCACHE_CPP2</code> different.
+ This makes it possible to rebuild with <code>CCACHE_CPP2</code> set without having to
+ clear the cache to get new results.
+</p>
+</li>
+<li>
+<p>
+Don’t try to reset a non-existing stats file. This avoids “No such file or
+ directory” messages in the ccache log when the cache directory doesn’t
+ exist.
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+</div>
+<div class="sect1">
<h2 id="_ccache_3_1_10">ccache 3.1.10</h2>
<div class="sectionbody">
<div class="paragraph"><p>Release date: 2014-10-19</p></div>
<div class="sect2">
-<h3 id="_new_features_and_improvements_2">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_3">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1061,7 +1186,7 @@ Stale files in the internal temporary directory (<code><ccache_dir>/tmp</c </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_3">Bug fixes</h3>
+<h3 id="_bug_fixes_5">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1101,7 +1226,7 @@ Fixed problem with logging of current working directory. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2013-01-06</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_4">Bug fixes</h3>
+<h3 id="_bug_fixes_6">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1151,7 +1276,7 @@ Fixed test suite to work on ecryptfs. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2012-08-11</p></div>
<div class="sect2">
-<h3 id="_new_features_and_improvements_3">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_4">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1172,7 +1297,7 @@ Clang plugins are now hashed to catch plugin upgrades. </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_5">Bug fixes</h3>
+<h3 id="_bug_fixes_7">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1220,7 +1345,7 @@ Fixed <code>static_assert</code> macro definition clash with GCC 4.7. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2012-01-08</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_6">Bug fixes</h3>
+<h3 id="_bug_fixes_8">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1293,7 +1418,7 @@ Improved documentation on how to fix bad object files in the cache. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2011-08-21</p></div>
<div class="sect2">
-<h3 id="_new_features_and_improvements_4">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_5">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1303,7 +1428,7 @@ Rewrite argument to <code>--sysroot</code> if <code>CCACHE_BASEDIR</code> is use </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_7">Bug fixes</h3>
+<h3 id="_bug_fixes_9">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1324,7 +1449,7 @@ Fixed alignment of “called for preprocessing” counter. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2011-05-29</p></div>
<div class="sect2">
-<h3 id="_new_features_and_improvements_5">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_6">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1356,7 +1481,7 @@ Improved order of statistics counters in <code>ccache -s</code> output. </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_8">Bug fixes</h3>
+<h3 id="_bug_fixes_10">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1389,7 +1514,7 @@ Systems that lack (and don’t need to be linked with) libm are now supporte <div class="sectionbody">
<div class="paragraph"><p>Release date: 2011-01-09</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_9">Bug fixes</h3>
+<h3 id="_bug_fixes_11">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1422,7 +1547,7 @@ The file handle in now correctly closed on write error when trying to create <div class="sectionbody">
<div class="paragraph"><p>Release date: 2010-11-28</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_10">Bug fixes</h3>
+<h3 id="_bug_fixes_12">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1449,7 +1574,7 @@ Portability fixes for HP-UX 11.00 and other esoteric systems. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2010-11-21</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_11">Bug fixes</h3>
+<h3 id="_bug_fixes_13">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1497,7 +1622,7 @@ The test suite now also works on systems that lack a /dev/zero. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2010-11-07</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_12">Bug fixes</h3>
+<h3 id="_bug_fixes_14">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1551,7 +1676,7 @@ Minor debug log message improvements. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2010-09-16</p></div>
<div class="sect2">
-<h3 id="_new_features_and_improvements_6">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_7">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1619,7 +1744,7 @@ Added <code>-install_name</code> as an option known to take an argument. (This i </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_13">Bug fixes</h3>
+<h3 id="_bug_fixes_15">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1705,7 +1830,7 @@ New <code>HACKING.txt</code> file with some notes about ccache code conventions. <div class="sectionbody">
<div class="paragraph"><p>Release date: 2010-07-15</p></div>
<div class="sect2">
-<h3 id="_bug_fixes_14">Bug fixes</h3>
+<h3 id="_bug_fixes_16">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1751,7 +1876,7 @@ The way the hashes are calculated has changed, so you won’t get cache hits </ul></div>
</div>
<div class="sect2">
-<h3 id="_new_features_and_improvements_7">New features and improvements</h3>
+<h3 id="_new_features_and_improvements_8">New features and improvements</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -1894,7 +2019,7 @@ The following options are no longer hashed in the preprocessor mode: </ul></div>
</div>
<div class="sect2">
-<h3 id="_bug_fixes_15">Bug fixes</h3>
+<h3 id="_bug_fixes_17">Bug fixes</h3>
<div class="ulist"><ul>
<li>
<p>
@@ -2039,8 +2164,9 @@ Statistics counters are now correctly updated for -E option failures and <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Version 3.2.1<br />
-Last updated 2014-12-10 20:38:47 CET
+Version 3.2.2<br />
+Last updated
+ 2015-05-10 14:17:58 CEST
</div>
</div>
</body>
@@ -2,6 +2,55 @@ ccache news =========== +ccache 3.2.2 +------------ +Release date: 2015-05-10 + + +New features and improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Added support for `CCACHE_COMPILERCHECK=string:<value>`. This is a faster + alternative to `CCACHE_COMPILERCHECK=<command>` if the command's output can + be precalculated by the build system. + +- Add support for caching code coverage results (compiling for gcov). + + +Bug fixes +~~~~~~~~~ + +- Fixed bug which could result in false cache hits when source code contains + `'"'` followed by `" /*"` or `" //"` (with variations). + +- Made hash of cached result created with and without `CCACHE_CPP2` different. + This makes it possible to rebuild with `CCACHE_CPP2` set without having to + clear the cache to get new results. + +- Don't try to reset a non-existing stats file. This avoids ``No such file or + directory'' messages in the ccache log when the cache directory doesn't + exist. + +- Fixed a bug where ccache deleted clang diagnostics after compiler failures. + +- Avoid performing an unnecessary copy of the object file on a cache miss. + +- Bail out on too hard compiler option `-fmodules`. + +- Bail out on too hard compiler option `-fplugin=libcc1plugin` (interaction + with GDB). + +- Fixed build error when compiling ccache with recent clang versions. + +- Removed signal-unsafe code from signal handler. + +- Corrected logic for when to output cached stderr. + +- Wipe the whole cached result on failure retrieving a cached file. + +- Fixed build error when compiling ccache with recent clang versions. + + ccache 3.2.1 ------------ Release date: 2014-12-10 @@ -137,6 +186,26 @@ Bug fixes - Fixed test suite failures when `CC` is a ccache-wrapped compiler. +ccache 3.1.11 +------------- +Release date: 2015-03-07 + + +Bug fixes +~~~~~~~~~ + +- Fixed bug which could result in false cache hits when source code contains + `'"'` followed by `" /*"` or `" //"` (with variations). + +- Made hash of cached result created with and without `CCACHE_CPP2` different. + This makes it possible to rebuild with `CCACHE_CPP2` set without having to + clear the cache to get new results. + +- Don't try to reset a non-existing stats file. This avoids ``No such file or + directory'' messages in the ccache log when the cache directory doesn't + exist. + + ccache 3.1.10 ------------- Release date: 2014-10-19 diff --git a/README.html b/README.html index 6d06405..7c5d01f 100644 --- a/README.html +++ b/README.html @@ -734,7 +734,7 @@ asciidoc.install(2); <body class="article">
<div id="header">
<h1>ccache README</h1>
-<span id="revnumber">version 3.2</span>
+<span id="revnumber">version 3.1.11</span>
<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> @@ -830,8 +830,9 @@ Thiele’s “compilercache” (see <a href="http://www.erikyyy.de/c <div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
-Version 3.2<br />
-Last updated 2012-11-07 19:42:42 CET
+Version 3.1.11<br />
+Last updated
+ 2012-11-07 19:42:42 CET
</div>
</div>
</body>
@@ -2,12 +2,12 @@ .\" Title: ccache .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> -.\" Date: 12/10/2014 +.\" Date: 05/10/2015 .\" Manual: ccache Manual -.\" Source: ccache 3.2.1 +.\" Source: ccache 3.2.2 .\" Language: English .\" -.TH "CCACHE" "1" "12/10/2014" "ccache 3\&.2\&.1" "ccache Manual" +.TH "CCACHE" "1" "05/10/2015" "ccache 3\&.2\&.2" "ccache Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -398,6 +398,13 @@ Don\(cqt hash anything\&. This may be good for situations where you can safely u setting if you know what you are doing\&. .RE .PP +\fBstring:value\fR +.RS 4 +Use +\fBvalue\fR +as the string to calculate hash from\&. This can be the compiler revision number you retrieved earlier and set here via environment variable\&. +.RE +.PP \fIa command string\fR .RS 4 Hash the standard output and standard error output of the specified command\&. The string will be split on whitespace to find out the command and arguments to run\&. No other interpretation of the command string will be done, except that the special word @@ -2,7 +2,7 @@ * ccache -- a fast C/C++ compiler cache * * Copyright (C) 2002-2007 Andrew Tridgell - * Copyright (C) 2009-2014 Joel Rosdahl + * Copyright (C) 2009-2015 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 @@ -39,7 +39,7 @@ static const char VERSION_TEXT[] = MYNAME " version %s\n" "\n" "Copyright (C) 2002-2007 Andrew Tridgell\n" -"Copyright (C) 2009-2011 Joel Rosdahl\n" +"Copyright (C) 2009-2015 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" @@ -95,6 +95,9 @@ static char *output_obj; /* The path to the dependency file (implicit or specified with -MF). */ static char *output_dep; +/* The path to the coverage file (implicit when using -ftest-coverage). */ +static char *output_cov; + /* Diagnostic generation information (clang). */ static char *output_dia = NULL; @@ -123,6 +126,12 @@ static char *cached_stderr; static char *cached_dep; /* + * Full path to the file containing the coverage information + * (cachedir/a/b/cdef[...]-size.gcno). + */ +static char *cached_cov; + +/* * Full path to the file containing the diagnostic information (for clang) * (cachedir/a/b/cdef[...]-size.dia). */ @@ -149,6 +158,15 @@ static struct hashtable *included_files; /* is gcc being asked to output dependencies? */ static bool generating_dependencies; +/* is gcc being asked to output coverage? */ +static bool generating_coverage; + +/* is gcc being asked to output coverage data (.gcda) at runtime? */ +static bool profile_arcs; + +/* name of the custom profile directory (default: object dirname) */ +static char *profile_dir; + /* the name of the temporary pre-processor file */ static char *i_tmpfile; @@ -188,8 +206,7 @@ unsigned lock_staleness_limit = 2000000; enum fromcache_call_mode { FROMCACHE_DIRECT_MODE, - FROMCACHE_CPP_MODE, - FROMCACHE_COMPILED_MODE + FROMCACHE_CPP_MODE }; struct pending_tmp_file { @@ -289,7 +306,8 @@ clean_up_pending_tmp_files(void) { struct pending_tmp_file *p = pending_tmp_files; while (p) { - tmp_unlink(p->path); + /* Can't call tmp_unlink here since its cc_log calls aren't signal safe. */ + unlink(p->path); p = p->next; /* Leak p->path and p here because clean_up_pending_tmp_files needs to be * signal safe. */ @@ -311,8 +329,7 @@ clean_up_internal_tempdir(void) struct stat st; time_t now = time(NULL); - stat(conf->cache_dir, &st); - if (st.st_mtime + 3600 >= now) { + if (x_stat(conf->cache_dir, &st) != 0 || st.st_mtime + 3600 >= now) { /* No cleanup needed. */ return; } @@ -332,7 +349,7 @@ clean_up_internal_tempdir(void) } path = format("%s/%s", temp_dir(), entry->d_name); - if (lstat(path, &st) == 0 && st.st_mtime + 3600 < now) { + if (x_lstat(path, &st) == 0 && st.st_mtime + 3600 < now) { tmp_unlink(path); } free(path); @@ -423,8 +440,7 @@ remember_include_file(char *path, struct mdfour *cpp_hash) goto ignore; #endif - if (stat(path, &st) != 0) { - cc_log("Failed to stat include file %s: %s", path, strerror(errno)); + if (x_stat(path, &st) != 0) { goto failure; } if (S_ISDIR(st.st_mode)) { @@ -689,8 +705,7 @@ put_file_in_cache(const char *source, const char *dest) failed(); } cc_log("Stored in cache: %s -> %s", source, dest); - if (stat(dest, &st) != 0) { - cc_log("Failed to stat %s: %s", dest, strerror(errno)); + if (x_stat(dest, &st) != 0) { stats_update(STATS_ERROR); failed(); } @@ -724,34 +739,91 @@ get_file_from_cache(const char *source, const char *dest) strerror(errno)); stats_update(STATS_ERROR); } + + /* If there was trouble getting a file from the cached result, wipe the + * whole cached result for consistency. */ + x_unlink(cached_stderr); + x_unlink(cached_obj); + x_unlink(cached_dep); + x_unlink(cached_dia); + failed(); } cc_log("Created from cache: %s -> %s", source, dest); } +/* Send cached stderr, if any, to stderr. */ +static void +send_cached_stderr(void) +{ + int fd_stderr = open(cached_stderr, O_RDONLY | O_BINARY); + if (fd_stderr != -1) { + copy_fd(fd_stderr, 2); + close(fd_stderr); + } +} + +/* Create or update the manifest file. */ +void update_manifest_file(void) +{ + struct stat st; + size_t old_size = 0; /* in bytes */ + + if (!conf->direct_mode + || !included_files + || conf->read_only + || conf->read_only_direct) { + return; + } + + if (stat(manifest_path, &st) == 0) { + old_size = file_size(&st); + } + if (manifest_put(manifest_path, cached_obj_hash, included_files)) { + cc_log("Added object file hash to %s", manifest_path); + update_mtime(manifest_path); + if (x_stat(manifest_path, &st) == 0) { + stats_update_size(file_size(&st) - old_size, old_size == 0 ? 1 : 0); + } + } else { + cc_log("Failed to add object file hash to %s", manifest_path); + } +} + /* run the real compiler and put the result in cache */ static void to_cache(struct args *args) { - char *tmp_stdout, *tmp_stderr, *tmp_dia; + char *tmp_stdout, *tmp_stderr, *tmp_aux, *tmp_cov; struct stat st; int status, tmp_stdout_fd, tmp_stderr_fd; + FILE *f; tmp_stdout = format("%s.tmp.stdout", cached_obj); tmp_stdout_fd = create_tmp_fd(&tmp_stdout); tmp_stderr = format("%s.tmp.stderr", cached_obj); tmp_stderr_fd = create_tmp_fd(&tmp_stderr); + if (generating_coverage) { + /* gcc has some funny rule about max extension length */ + if (strlen(get_extension(output_obj)) < 6) { + tmp_aux = remove_extension(output_obj); + } else { + tmp_aux = x_strdup(output_obj); + } + tmp_cov = format("%s.gcno", tmp_aux); + free(tmp_aux); + } else { + tmp_cov = NULL; + } + args_add(args, "-o"); args_add(args, output_obj); if (output_dia) { - tmp_dia = x_strdup(output_dia); args_add(args, "--serialize-diagnostics"); - args_add(args, tmp_dia); - } else { - tmp_dia = NULL; + args_add(args, output_dia); } /* Turn off DEPENDENCIES_OUTPUT when running cc1, because @@ -771,12 +843,14 @@ to_cache(struct args *args) status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd); args_pop(args, 3); - if (stat(tmp_stdout, &st) != 0) { + if (x_stat(tmp_stdout, &st) != 0) { /* The stdout file was removed - cleanup in progress? Better bail out. */ - cc_log("%s not found: %s", tmp_stdout, strerror(errno)); stats_update(STATS_MISSING); tmp_unlink(tmp_stdout); tmp_unlink(tmp_stderr); + if (tmp_cov) { + tmp_unlink(tmp_cov); + } failed(); } if (st.st_size != 0) { @@ -784,8 +858,8 @@ to_cache(struct args *args) stats_update(STATS_STDOUT); tmp_unlink(tmp_stdout); tmp_unlink(tmp_stderr); - if (tmp_dia) { - tmp_unlink(tmp_dia); + if (tmp_cov) { + tmp_unlink(tmp_cov); } failed(); } @@ -838,47 +912,22 @@ to_cache(struct args *args) fd = open(tmp_stderr, O_RDONLY | O_BINARY); if (fd != -1) { - if (str_eq(output_obj, "/dev/null") || errno == ENOENT) { - /* we can use a quick method of getting the failed output */ - copy_fd(fd, 2); - close(fd); - tmp_unlink(tmp_stderr); - - if (output_dia) { - int ret; - x_unlink(output_dia); - /* only make a hardlink if the cache file is uncompressed */ - ret = move_file(tmp_dia, output_dia, 0); - - if (ret == -1) { - if (errno == ENOENT) { - /* Someone removed the file just before we began copying? */ - cc_log("Diagnostic file %s just disappeared", output_dia); - stats_update(STATS_MISSING); - } else { - cc_log("Failed to move %s to %s: %s", - tmp_dia, output_dia, strerror(errno)); - stats_update(STATS_ERROR); - failed(); - } - x_unlink(tmp_dia); - } else { - cc_log("Created %s from %s", output_dia, tmp_dia); - } - } + /* We can output stderr immediately instead of rerunning the compiler. */ + copy_fd(fd, 2); + close(fd); + tmp_unlink(tmp_stderr); - exit(status); - } + exit(status); } tmp_unlink(tmp_stderr); - if (tmp_dia) { - tmp_unlink(tmp_dia); + if (tmp_cov) { + tmp_unlink(tmp_cov); } failed(); } - if (stat(output_obj, &st) != 0) { + if (x_stat(output_obj, &st) != 0) { cc_log("Compiler didn't produce an object file"); stats_update(STATS_NOOUTPUT); failed(); @@ -889,8 +938,7 @@ to_cache(struct args *args) failed(); } - if (stat(tmp_stderr, &st) != 0) { - cc_log("Failed to stat %s: %s", tmp_stderr, strerror(errno)); + if (x_stat(tmp_stderr, &st) != 0) { stats_update(STATS_ERROR); failed(); } @@ -904,10 +952,11 @@ to_cache(struct args *args) failed(); } cc_log("Stored in cache: %s", cached_stderr); - if (conf->compression) { - stat(cached_stderr, &st); + if (!conf->compression + /* If the file was compressed, obtain the size again: */ + || (conf->compression && x_stat(cached_stderr, &st) == 0)) { + stats_update_size(file_size(&st), 1); } - stats_update_size(file_size(&st), 1); } else { tmp_unlink(tmp_stderr); if (conf->recache) { @@ -916,18 +965,38 @@ to_cache(struct args *args) } } - if (tmp_dia) { - if (stat(tmp_dia, &st) != 0) { - cc_log("Failed to stat %s: %s", tmp_dia, strerror(errno)); + if (generating_coverage) { + /* gcc won't generate notes if there is no code */ + if (stat(tmp_cov, &st) != 0 && errno == ENOENT) { + cc_log("Creating placeholder: %s", cached_cov); + + f = fopen(cached_cov, "wb"); + if (!f) { + cc_log("Failed to create %s: %s", cached_cov, strerror(errno)); + stats_update(STATS_ERROR); + failed(); + } + fclose(f); + stats_update_size(0, 1); + } else { + put_file_in_cache(tmp_cov, cached_cov); + } + } + + if (output_dia) { + if (x_stat(output_dia, &st) != 0) { stats_update(STATS_ERROR); failed(); } if (st.st_size > 0) { - put_file_in_cache(tmp_dia, cached_dia); + put_file_in_cache(output_dia, cached_dia); } } put_file_in_cache(output_obj, cached_obj); + if (generating_dependencies) { + put_file_in_cache(output_dep, cached_dep); + } stats_update(STATS_TOCACHE); /* Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can @@ -948,14 +1017,18 @@ to_cache(struct args *args) * previous ccache versions. */ if (getpid() % 1000 == 0) { char *path = format("%s/CACHEDIR.TAG", conf->cache_dir); - unlink(path); + x_unlink(path); free(path); } } + /* Everything OK. */ + send_cached_stderr(); + update_manifest_file(); + free(tmp_stderr); free(tmp_stdout); - free(tmp_dia); + free(tmp_cov); } /* @@ -1059,6 +1132,8 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) * the compiler pass. */ cpp_stderr = path_stderr; + hash_delimiter(hash, "runsecondcpp"); + hash_string(hash, "false"); } result = x_malloc(sizeof(*result)); @@ -1076,6 +1151,7 @@ update_cached_result_globals(struct file_hash *hash) cached_obj = get_path_in_cache(object_name, ".o"); cached_stderr = get_path_in_cache(object_name, ".stderr"); cached_dep = get_path_in_cache(object_name, ".d"); + cached_cov = get_path_in_cache(object_name, ".gcno"); cached_dia = get_path_in_cache(object_name, ".dia"); stats_file = format("%s/%c/stats", conf->cache_dir, object_name[0]); free(object_name); @@ -1095,6 +1171,9 @@ hash_compiler(struct mdfour *hash, struct stat *st, const char *path, hash_delimiter(hash, "cc_mtime"); hash_int(hash, st->st_size); hash_int(hash, st->st_mtime); + } else if (str_startswith(conf->compiler_check, "string:")) { + hash_delimiter(hash, "cc_hash"); + hash_string(hash, conf->compiler_check + strlen("string:")); } else if (str_eq(conf->compiler_check, "content") || !allow_command) { hash_delimiter(hash, "cc_content"); hash_file(hash, path); @@ -1114,7 +1193,7 @@ hash_compiler(struct mdfour *hash, struct stat *st, const char *path, static bool compiler_is_clang(struct args *args) { - char* name = basename(args->argv[0]); + char *name = basename(args->argv[0]); bool is = strstr(name, "clang"); free(name); return is; @@ -1123,7 +1202,7 @@ compiler_is_clang(struct args *args) static bool compiler_is_gcc(struct args *args) { - char* name = basename(args->argv[0]); + char *name = basename(args->argv[0]); bool is = strstr(name, "gcc") || strstr(name, "g++"); free(name); return is; @@ -1138,6 +1217,11 @@ calculate_common_hash(struct args *args, struct mdfour *hash) { struct stat st; char *p; + const char *full_path = args->argv[0]; +#ifdef _WIN32 + const char *ext; + char full_path_win_ext[MAX_PATH + 1] = {0}; +#endif hash_string(hash, HASH_PREFIX); @@ -1148,8 +1232,14 @@ calculate_common_hash(struct args *args, struct mdfour *hash) hash_delimiter(hash, "ext"); hash_string(hash, conf->cpp_extension); - if (stat(args->argv[0], &st) != 0) { - cc_log("Couldn't stat compiler %s: %s", args->argv[0], strerror(errno)); +#ifdef _WIN32 + ext = strrchr(args->argv[0], '.'); + add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, + args->argv[0]); + full_path = full_path_win_ext; +#endif + + if (x_stat(full_path, &st) != 0) { stats_update(STATS_COMPILER); failed(); } @@ -1178,6 +1268,30 @@ calculate_common_hash(struct args *args, struct mdfour *hash) } } + /* Possibly hash the coverage data file path. */ + if (generating_coverage && profile_arcs) { + char *gcda_path; + char *dir = dirname(output_obj); + if (profile_dir) { + dir = x_strdup(profile_dir); + } else { + char *real_dir = x_realpath(dir); + free(dir); + dir = real_dir; + } + if (dir) { + char *base_name = basename(output_obj); + p = remove_extension(base_name); + free(base_name); + gcda_path = format("%s/%s.gcda", dir, p); + cc_log("Hashing coverage path %s", gcda_path); + free(p); + hash_delimiter(hash, "gcda"); + hash_string(hash, gcda_path); + free(dir); + } + } + if (!str_eq(conf->extra_files_to_hash, "")) { char *path, *p, *q, *saveptr = NULL; p = x_strdup(conf->extra_files_to_hash); @@ -1269,11 +1383,11 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) if (generating_dependencies) { if (str_startswith(args->argv[i], "-Wp,")) { if (str_startswith(args->argv[i], "-Wp,-MD,") - && !strchr(args->argv[i] + 8, ',')) { + && !strchr(args->argv[i] + 8, ',')) { hash_string_length(hash, args->argv[i], 8); continue; } else if (str_startswith(args->argv[i], "-Wp,-MMD,") - && !strchr(args->argv[i] + 9, ',')) { + && !strchr(args->argv[i] + 9, ',')) { hash_string_length(hash, args->argv[i], 9); continue; } @@ -1298,7 +1412,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) } else if (str_startswith(args->argv[i], "--specs=")) { p = args->argv[i] + 8; } - if (p && stat(p, &st) == 0) { + if (p && x_stat(p, &st) == 0) { /* If given an explicit specs file, then hash that file, but don't include the path to it in the hash. */ hash_delimiter(hash, "specs"); @@ -1307,7 +1421,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) } if (str_startswith(args->argv[i], "-fplugin=") - && stat(args->argv[i] + 9, &st) == 0) { + && x_stat(args->argv[i] + 9, &st) == 0) { hash_delimiter(hash, "plugin"); hash_compiler(hash, &st, args->argv[i] + 9, false); continue; @@ -1317,7 +1431,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) && i + 3 < args->argc && str_eq(args->argv[i+1], "-load") && str_eq(args->argv[i+2], "-Xclang") - && stat(args->argv[i+3], &st) == 0) { + && x_stat(args->argv[i+3], &st) == 0) { hash_delimiter(hash, "plugin"); hash_compiler(hash, &st, args->argv[i+3], false); continue; @@ -1439,12 +1553,11 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) static void from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) { - int fd_stderr; struct stat st; - bool produce_dep_file; + bool produce_dep_file = false; /* the user might be disabling cache hits */ - if (mode != FROMCACHE_COMPILED_MODE && conf->recache) { + if (conf->recache) { return; } @@ -1462,7 +1575,7 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) /* * Occasionally, e.g. on hard reset, our cache ends up as just filesystem - * meta-data with no content catch an easy case of this. + * meta-data with no content. Catch an easy case of this. */ if (st.st_size == 0) { cc_log("Invalid (empty) object file %s in cache", cached_obj); @@ -1488,6 +1601,10 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) if (produce_dep_file) { get_file_from_cache(cached_dep, output_dep); } + if (generating_coverage && stat(cached_cov, &st) == 0 && st.st_size > 0) { + /* gcc won't generate notes if there is no code */ + get_file_from_cache(cached_cov, output_cov); + } if (output_dia) { get_file_from_cache(cached_dia, output_dia); } @@ -1499,40 +1616,21 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) if (produce_dep_file) { update_mtime(cached_dep); } + if (generating_coverage) { + update_mtime(cached_cov); + } if (output_dia) { update_mtime(cached_dia); } - if (generating_dependencies && mode != FROMCACHE_DIRECT_MODE) { + if (generating_dependencies && mode == FROMCACHE_CPP_MODE) { put_file_in_cache(output_dep, cached_dep); } - /* Send the stderr, if any. */ - fd_stderr = open(cached_stderr, O_RDONLY | O_BINARY); - if (fd_stderr != -1) { - copy_fd(fd_stderr, 2); - close(fd_stderr); - } + send_cached_stderr(); - /* Create or update the manifest file. */ - if (conf->direct_mode - && put_object_in_manifest - && included_files - && !conf->read_only - && !conf->read_only_direct) { - struct stat st; - size_t old_size = 0; /* in bytes */ - if (stat(manifest_path, &st) == 0) { - old_size = file_size(&st); - } - if (manifest_put(manifest_path, cached_obj_hash, included_files)) { - cc_log("Added object file hash to %s", manifest_path); - update_mtime(manifest_path); - stat(manifest_path, &st); - stats_update_size(file_size(&st) - old_size, old_size == 0 ? 1 : 0); - } else { - cc_log("Failed to add object file hash to %s", manifest_path); - } + if (put_object_in_manifest) { + update_manifest_file(); } /* log the cache hit */ @@ -1546,10 +1644,6 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) cc_log("Succeeded getting cached result"); stats_update(STATS_CACHEHIT_CPP); break; - - case FROMCACHE_COMPILED_MODE: - /* Stats already updated in to_cache(). */ - break; } /* and exit with the right status code */ @@ -1873,6 +1967,27 @@ cc_process_args(struct args *args, struct args **preprocessor_args, } continue; } + if (str_eq(argv[i], "-fprofile-arcs")) { + profile_arcs = true; + args_add(stripped_args, argv[i]); + continue; + } + if (str_eq(argv[i], "-ftest-coverage")) { + generating_coverage = true; + args_add(stripped_args, argv[i]); + continue; + } + if (str_eq(argv[i], "--coverage")) { /* = -fprofile-arcs -ftest-coverage */ + profile_arcs = true; + generating_coverage = true; + args_add(stripped_args, argv[i]); + continue; + } + if (str_startswith(argv[i], "-fprofile-dir=")) { + profile_dir = x_strdup(argv[i] + 14); + args_add(stripped_args, argv[i]); + continue; + } if (str_startswith(argv[i], "--sysroot=")) { char *relpath = make_relative_path(x_strdup(argv[i] + 10)); char *option = format("--sysroot=%s", relpath); @@ -2172,6 +2287,12 @@ cc_process_args(struct args *args, struct args **preprocessor_args, goto out; } + /* The source code file path gets put into the notes */ + if (generating_coverage) { + input_file = x_strdup(argv[i]); + continue; + } + /* Rewrite to relative to increase hit rate. */ input_file = make_relative_path(x_strdup(argv[i])); } @@ -2358,6 +2479,15 @@ cc_process_args(struct args *args, struct args **preprocessor_args, args_add(dep_args, output_obj); } } + if (generating_coverage) { + char *default_covfile_name; + char *base_name; + + base_name = remove_extension(output_obj); + default_covfile_name = format("%s.gcno", base_name); + free(base_name); + output_cov = make_relative_path(x_strdup(default_covfile_name)); + } *compiler_args = args_copy(stripped_args); if (conf->run_second_cpp) { @@ -2525,11 +2655,13 @@ cc_reset(void) free(input_file); input_file = NULL; free(output_obj); output_obj = NULL; free(output_dep); output_dep = NULL; + free(output_cov); output_cov = NULL; free(output_dia); output_dia = NULL; free(cached_obj_hash); cached_obj_hash = NULL; free(cached_obj); cached_obj = NULL; free(cached_stderr); cached_stderr = NULL; free(cached_dep); cached_dep = NULL; + free(cached_cov); cached_cov = NULL; free(cached_dia); cached_dia = NULL; free(manifest_path); manifest_path = NULL; time_of_compilation = 0; @@ -2537,6 +2669,9 @@ cc_reset(void) hashtable_destroy(included_files, 1); included_files = NULL; } generating_dependencies = false; + generating_coverage = false; + profile_arcs = false; + free(profile_dir); profile_dir = NULL; i_tmpfile = NULL; direct_i_file = false; free(cpp_stderr); cpp_stderr = NULL; @@ -2636,6 +2771,9 @@ ccache(int argc, char *argv[]) if (generating_dependencies) { cc_log("Dependency file: %s", output_dep); } + if (generating_coverage) { + cc_log("Coverage file: %s", output_cov); + } if (output_dia) { cc_log("Diagnostic file: %s", output_dia); } @@ -2726,13 +2864,7 @@ ccache(int argc, char *argv[]) /* run real compiler, sending output to cache */ to_cache(compiler_args); - /* return from cache */ - from_cache(FROMCACHE_COMPILED_MODE, put_object_in_manifest); - - /* oh oh! */ - cc_log("Secondary from_cache failed"); - stats_update(STATS_ERROR); - failed(); + exit(0); } static void @@ -136,6 +136,9 @@ void *x_malloc(size_t size); void *x_calloc(size_t nmemb, size_t size); void *x_realloc(void *ptr, size_t size); void x_unsetenv(const char *name); +int x_fstat(int fd, struct stat *buf); +int x_lstat(const char *pathname, struct stat *buf); +int x_stat(const char *pathname, struct stat *buf); void traverse(const char *dir, void (*fn)(const char *, struct stat *)); char *basename(const char *path); char *dirname(const char *path); @@ -251,7 +254,9 @@ typedef int (*COMPAR_FN_T)(const void *, const void *); char *win32argvtos(char *prefix, char **argv); char *win32getshell(char *path); int win32execute(char *path, char **argv, int doreturn, - const char *path_stdout, const char *path_stderr); + int fd_stdout, int fd_stderr); +void add_exe_ext_if_no_to_fullpath(char *full_path_win_ext, size_t max_size, + const char *ext, const char *path); # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0501 # endif @@ -259,8 +264,7 @@ int win32execute(char *path, char **argv, int doreturn, # define mkdir(a,b) mkdir(a) # define link(src,dst) (CreateHardLink(dst,src,NULL) ? 0 : -1) # define lstat(a,b) stat(a,b) -# define execv(a,b) win32execute(a,b,0,NULL,NULL) -#error TODO: Adapt win32execute to new execute API +# define execv(a,b) win32execute(a,b,0,-1,-1) # define execute(a,b,c) win32execute(*(a),a,1,b,c) # define PATH_DELIM ";" # define F_RDLCK 0 @@ -1,6 +1,6 @@ /* * Copyright (C) 2002-2006 Andrew Tridgell - * Copyright (C) 2009-2014 Joel Rosdahl + * Copyright (C) 2009-2015 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 @@ -122,7 +122,7 @@ delete_sibling_file(const char *base, const char *extension) if (lstat(path, &st) == 0) { delete_file(path, file_size(&st)); } else if (errno != ENOENT) { - cc_log("Failed to stat %s (%s)", path, strerror(errno)); + cc_log("Failed to stat %s: %s", path, strerror(errno)); } free(path); } @@ -153,6 +153,7 @@ sort_and_clean(void) ext = get_extension(files[i]->fname); if (str_eq(ext, ".o") || str_eq(ext, ".d") + || str_eq(ext, ".gcno") || str_eq(ext, ".dia") || str_eq(ext, ".stderr") || str_eq(ext, "")) { @@ -167,6 +168,7 @@ sort_and_clean(void) */ delete_sibling_file(base, ".o"); delete_sibling_file(base, ".d"); + delete_sibling_file(base, ".gcno"); delete_sibling_file(base, ".dia"); delete_sibling_file(base, ".stderr"); delete_sibling_file(base, ""); /* Object file from ccache 2.4. */ @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012-2013 Joel Rosdahl + * Copyright (C) 2010-2015 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 @@ -32,7 +32,6 @@ struct compopt { }; static const struct compopt compopts[] = { - {"--coverage", TOO_HARD}, /* implies -ftest-coverage */ {"--param", TAKES_ARG}, {"--serialize-diagnostics", TAKES_ARG | TAKES_PATH}, {"-A", TAKES_ARG}, @@ -56,9 +55,10 @@ static const struct compopt compopts[] = { {"-arch", TAKES_ARG}, {"-aux-info", TAKES_ARG}, {"-b", TAKES_ARG}, + {"-fmodules", TOO_HARD}, {"-fno-working-directory", AFFECTS_CPP}, + {"-fplugin=libcc1plugin", TOO_HARD}, /* interaction with GDB */ {"-frepo", TOO_HARD}, - {"-ftest-coverage", TOO_HARD}, /* generates a .gcno file at the same time */ {"-fworking-directory", AFFECTS_CPP}, {"-gsplit-dwarf", TOO_HARD}, /* generates a .dwo file at the same time */ {"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_PATH}, @@ -2327,6 +2327,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac case $host in *mingw32* | *cygwin* | *wince* | *mingwce*) + windows_os=yes $as_echo "#define _WIN32_WINNT 0x0600" >>confdefs.h @@ -5684,6 +5685,10 @@ else extra_ldflags="-lz" fi +if test x${windows_os} = xyes; then + extra_ldflags="$extra_ldflags -lws2_32" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : diff --git a/configure.ac b/configure.ac index 2cf2939..9e65588 100644 --- a/configure.ac +++ b/configure.ac @@ -11,6 +11,7 @@ AC_CANONICAL_HOST case $host in *mingw32* | *cygwin* | *wince* | *mingwce*) + windows_os=yes AC_DEFINE(_WIN32_WINNT,0x0600, Windows Vista or newer is required) ;; esac @@ -122,6 +123,11 @@ else extra_ldflags="-lz" fi +dnl Linking on Windows needs ws2_32 +if test x${windows_os} = xyes; then + extra_ldflags="$extra_ldflags -lws2_32" +fi + AC_C_BIGENDIAN AC_C_INLINE diff --git a/confitems_lookup.c b/confitems_lookup.c index 2642dd6..39e95af 100644 --- a/confitems_lookup.c +++ b/confitems_lookup.c @@ -75,6 +75,7 @@ confitems_hash (register const char *str, register unsigned int len) return len + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]]; } +static #ifdef __GNUC__ __inline #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ @@ -92,7 +92,7 @@ endif version.o: version.c %_lookup.c: %.gperf - $(GPERF) $< >$@ + $(GPERF) $< | awk '/#ifdef __GNUC__/ { ++i; if (i == 2) { print "static"; }} {print}' >$@ echo "static const size_t `echo $* | tr a-z A-Z`_TOTAL_KEYWORDS = `sed -nr 's/.*TOTAL_KEYWORDS = ([0-9]+).*/\1/p' $@`;" >>$@ .PHONY: dist diff --git a/envtoconfitems_lookup.c b/envtoconfitems_lookup.c index 2bfd2f8..cb8b53e 100644 --- a/envtoconfitems_lookup.c +++ b/envtoconfitems_lookup.c @@ -89,6 +89,7 @@ envtoconfitems_hash (register const char *str, register unsigned int len) return hval; } +static #ifdef __GNUC__ __inline #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ @@ -117,9 +117,21 @@ win32getshell(char *path) return sh; } +void add_exe_ext_if_no_to_fullpath(char *full_path_win_ext, size_t max_size, + const char *ext, const char *path) { + if (!ext || (!str_eq(".exe", ext) + && !str_eq(".bat", ext) + && !str_eq(".EXE", ext) + && !str_eq(".BAT", ext))) { + snprintf(full_path_win_ext, max_size, "%s.exe", path); + } else { + snprintf(full_path_win_ext, max_size, "%s", path); + } +} + int win32execute(char *path, char **argv, int doreturn, - const char *path_stdout, const char *path_stderr) + int fd_stdout, int fd_stderr) { PROCESS_INFORMATION pi; STARTUPINFO si; @@ -136,29 +148,67 @@ win32execute(char *path, char **argv, int doreturn, path = sh; si.cb = sizeof(STARTUPINFO); - if (path_stdout) { - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; - si.hStdOutput = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, - CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | - FILE_FLAG_SEQUENTIAL_SCAN, NULL); - si.hStdError = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, - CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | - FILE_FLAG_SEQUENTIAL_SCAN, NULL); - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.dwFlags = STARTF_USESTDHANDLES; - if (si.hStdOutput == INVALID_HANDLE_VALUE || - si.hStdError == INVALID_HANDLE_VALUE) + if (fd_stdout != -1) { + si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout); + si.hStdError = (HANDLE)_get_osfhandle(fd_stderr); + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.dwFlags = STARTF_USESTDHANDLES; + if (si.hStdOutput == INVALID_HANDLE_VALUE + || si.hStdError == INVALID_HANDLE_VALUE) { return -1; + } + } else { + /* redirect subprocess stdout, stderr into current process */ + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.dwFlags = STARTF_USESTDHANDLES; + if (si.hStdOutput == INVALID_HANDLE_VALUE + || si.hStdError == INVALID_HANDLE_VALUE) { + return -1; + } } args = win32argvtos(sh, argv); - ret = CreateProcess(path, args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi); - free(args); - if (path_stdout) { - CloseHandle(si.hStdOutput); - CloseHandle(si.hStdError); + + const char *ext = strrchr(path, '.'); + char full_path_win_ext[MAX_PATH] = {0}; + add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path); + ret = CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL, + &si, &pi); + if (fd_stdout != -1) { + close(fd_stdout); + close(fd_stderr); } - if (ret == 0) + free(args); + if (ret == 0) { + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, + 0, NULL); + + lpDisplayBuf = + (LPVOID) LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR) lpMsgBuf) + + lstrlen((LPCTSTR) __FILE__) + 200) + * sizeof(TCHAR)); + _snprintf((LPTSTR) lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %d: %s"), __FILE__, dw, lpMsgBuf); + + cc_log("can't execute %s; OS returned error: %s", + full_path_win_ext, (char*)lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + return -1; + } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pi.hProcess); @@ -128,6 +128,7 @@ hash_file(struct mdfour *md, const char *fname) fd = open(fname, O_RDONLY|O_BINARY); if (fd == -1) { + cc_log("Failed to open %s: %s", fname, strerror(errno)); return false; } @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 Joel Rosdahl + * Copyright (C) 2009-2015 Joel Rosdahl * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -18,8 +18,8 @@ #include "ccache.h" #include "hashutil.h" -#include "murmurhashneutral2.h" #include "macroskip.h" +#include "murmurhashneutral2.h" unsigned hash_from_string(void *str) @@ -84,7 +84,7 @@ check_for_temporal_macros(const char *str, size_t len) result |= HASH_SOURCE_CODE_FOUND_DATE; } else if (str[i - 5] == 'T' && str[i - 4] == 'I' && - str[i - 3] == 'M') { + str[i - 3] == 'M') { result |= HASH_SOURCE_CODE_FOUND_TIME; } } @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 Joel Rosdahl + * Copyright (C) 2010-2015 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 @@ -31,6 +31,7 @@ bool lockfile_acquire(const char *path, unsigned staleness_limit) { + int saved_errno = 0; char *lockfile = format("%s.lock", path); char *my_content = NULL, *content = NULL, *initial_content = NULL; const char *hostname = get_hostname(); @@ -50,15 +51,16 @@ lockfile_acquire(const char *path, unsigned staleness_limit) #ifdef _WIN32 fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0666); if (fd == -1) { + saved_errno = errno; cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno)); - if (errno == ENOENT) { + if (saved_errno == ENOENT) { /* Directory doesn't exist? */ if (create_parent_dirs(lockfile) == 0) { /* OK. Retry. */ continue; } } - if (errno != EEXIST) { + if (saved_errno != EEXIST) { /* Directory doesn't exist or isn't writable? */ goto out; } @@ -105,15 +107,16 @@ lockfile_acquire(const char *path, unsigned staleness_limit) acquired = true; goto out; } - cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(errno)); - if (errno == ENOENT) { + saved_errno = errno; + cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(saved_errno)); + if (saved_errno == ENOENT) { /* Directory doesn't exist? */ if (create_parent_dirs(lockfile) == 0) { /* OK. Retry. */ continue; } } - if (errno == EPERM) { + if (saved_errno == EPERM) { /* * The file system does not support symbolic links. We have no choice but * to grant the lock anyway. @@ -121,7 +124,7 @@ lockfile_acquire(const char *path, unsigned staleness_limit) acquired = true; goto out; } - if (errno != EEXIST) { + if (saved_errno != EEXIST) { /* Directory doesn't exist or isn't writable? */ goto out; } @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014 Joel Rosdahl + * Copyright (C) 2009-2015 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 @@ -393,8 +393,7 @@ verify_object(struct conf *conf, struct manifest *mf, struct object *obj, st = hashtable_search(hashed_files, path); if (!st) { struct stat file_stat; - if (stat(path, &file_stat) == -1) { - cc_log("Failed to stat include file %s: %s", path, strerror(errno)); + if (x_stat(path, &file_stat) != 0) { return 0; } st = x_malloc(sizeof(*st)); @@ -1,6 +1,6 @@ /* * Copyright (C) 2002-2004 Andrew Tridgell - * Copyright (C) 2009-2014 Joel Rosdahl + * Copyright (C) 2009-2015 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 @@ -153,7 +153,7 @@ init_counter_updates(void) /* * Record that a number of bytes and files have been added to the cache. Size - * is in KiB. + * is in bytes. */ void stats_update_size(uint64_t size, unsigned files) @@ -3,7 +3,7 @@ # A simple test suite for ccache. # # Copyright (C) 2002-2007 Andrew Tridgell -# Copyright (C) 2009-2014 Joel Rosdahl +# Copyright (C) 2009-2015 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 @@ -240,7 +240,7 @@ base_tests() { unset CCACHE_CONFIGPATH CCACHE_DISABLE=1 $CCACHE_COMPILE -c test1.c 2> /dev/null if [ -d $CCACHE_DIR ]; then - test_failed "$CCACHE_DIR created dispite CCACHE_DISABLE being set" + test_failed "$CCACHE_DIR created despite CCACHE_DISABLE being set" fi CCACHE_CONFIGPATH=$saved_config_path mv $CCACHE_DIR.saved $CCACHE_DIR @@ -271,10 +271,10 @@ base_tests() { checkstat 'cache miss' 4 compare_file reference_test1.o test1.o - # strictly speaking should be 3 - RECACHE causes a double counting! + # strictly speaking should be 4 - RECACHE causes a double counting! checkstat 'files in cache' 4 $CCACHE -c > /dev/null - checkstat 'files in cache' 3 + checkstat 'files in cache' 4 testname="CCACHE_HASHDIR" CCACHE_HASHDIR=1 $CCACHE_COMPILE -c test1.c -O -O @@ -285,7 +285,7 @@ base_tests() { CCACHE_HASHDIR=1 $CCACHE_COMPILE -c test1.c -O -O checkstat 'cache hit (preprocessed)' 6 checkstat 'cache miss' 5 - checkstat 'files in cache' 4 + checkstat 'files in cache' 5 compare_file reference_test1.o test1.o testname="comments" @@ -316,7 +316,7 @@ base_tests() { done checkstat 'cache hit (preprocessed)' 8 checkstat 'cache miss' 37 - checkstat 'files in cache' 36 + checkstat 'files in cache' 37 $CCACHE -C >/dev/null @@ -374,9 +374,15 @@ base_tests() { CCACHE_CPP2=1 $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c checkstat 'cache hit (preprocessed)' 14 checkstat 'cache miss' 40 - $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c + CCACHE_CPP2=1 $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c checkstat 'cache hit (preprocessed)' 15 checkstat 'cache miss' 40 + $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c + checkstat 'cache hit (preprocessed)' 15 + checkstat 'cache miss' 41 + $CCACHE_COMPILE -c -finput-charset=latin1 latin1.c + checkstat 'cache hit (preprocessed)' 16 + checkstat 'cache miss' 41 fi fi @@ -449,6 +455,22 @@ EOF checkstat 'cache hit (preprocessed)' 2 checkstat 'cache miss' 1 + testname="compilercheck=string" + $CCACHE -z >/dev/null + backdate compiler.sh + CCACHE_COMPILERCHECK=string:foo $CCACHE ./compiler.sh -c test1.c + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_COMPILERCHECK=string:foo $CCACHE ./compiler.sh -c test1.c + checkstat 'cache hit (preprocessed)' 1 + checkstat 'cache miss' 1 + CCACHE_COMPILERCHECK=string:bar $CCACHE ./compiler.sh -c test1.c + checkstat 'cache hit (preprocessed)' 1 + checkstat 'cache miss' 2 + CCACHE_COMPILERCHECK=string:bar $CCACHE ./compiler.sh -c test1.c + checkstat 'cache hit (preprocessed)' 2 + checkstat 'cache miss' 2 + testname="compilercheck=command" $CCACHE -z >/dev/null backdate compiler.sh @@ -626,16 +648,45 @@ EOF ################################################################## if [ $COMPILER_TYPE_CLANG -eq 1 ]; then - $CCACHE -Cz > /dev/null testname="serialize-diagnostics" - $CCACHE_COMPILE -c --serialize-diagnostics test.dia test1.c 2> /dev/null + $CCACHE -Cz > /dev/null + $COMPILER -c --serialize-diagnostics expected.dia test1.c 2> /dev/null + # Run with CCACHE_CPP2 to ensure the same diagnostics output as above + CCACHE_CPP2=1 $CCACHE_COMPILE -c --serialize-diagnostics test.dia test1.c 2> /dev/null checkstat 'cache hit (preprocessed)' 0 checkstat 'cache miss' 1 checkstat 'files in cache' 2 - $CCACHE_COMPILE -c --serialize-diagnostics test.dia test1.c 2> /dev/null + compare_file expected.dia test.dia + rm -f test.dia + CCACHE_CPP2=1 $CCACHE_COMPILE -c --serialize-diagnostics test.dia test1.c 2> /dev/null checkstat 'cache hit (preprocessed)' 1 checkstat 'cache miss' 1 checkstat 'files in cache' 2 + compare_file expected.dia test.dia + + rm -f test.dia + rm -f expected.dia + + testname="serialize-diagnostics-compile-failed" + $CCACHE -Cz > /dev/null + echo "bad source" >error.c + $COMPILER -c --serialize-diagnostics expected.dia error.c 2> /dev/null + if [ $? -eq 0 ]; then + test_failed "expected an error compiling error.c" + fi + CCACHE_CPP2=1 $CCACHE_COMPILE -c --serialize-diagnostics test.dia error.c 2> /dev/null + checkstat 'compile failed' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 0 + checkstat 'files in cache' 0 + compare_file expected.dia test.dia + rm -f test.dia + CCACHE_CPP2=1 $CCACHE_COMPILE -c --serialize-diagnostics test.dia error.c 2> /dev/null + checkstat 'compile failed' 2 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 0 + checkstat 'files in cache' 0 + compare_file expected.dia test.dia fi ################################################################## @@ -711,6 +762,10 @@ EOF cat <<EOF >test3.h int test3; EOF + cat <<EOF >code.c +/* code.c */ +int test() {} +EOF backdate test1.h test2.h test3.h $COMPILER -c -Wp,-MD,expected.d test.c @@ -927,6 +982,35 @@ EOF compare_file reference_test.o test.o ################################################################## + # Check that coverage works. + testname="coverage (empty)" + $CCACHE -z >/dev/null + $CCACHE $COMPILER -c -fprofile-arcs -ftest-coverage test.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + $CCACHE $COMPILER -c -fprofile-arcs -ftest-coverage test.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + + testname="coverage (code)" + $CCACHE -z >/dev/null + $CCACHE $COMPILER -c -fprofile-arcs -ftest-coverage code.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + test -r code.gcno || test_failed "gcov" + + rm -f code.gcno + + $CCACHE $COMPILER -c -fprofile-arcs -ftest-coverage code.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + test -r code.gcno || test_failed "gcov" + + ################################################################## # Check the scenario of running a ccache with direct mode on a cache # built up by a ccache without direct mode support. testname="direct mode on old cache" @@ -1340,6 +1424,23 @@ EOF checkstat 'cache hit (preprocessed)' 0 checkstat 'cache miss' 2 + testname="comment in strings" + $CCACHE -Cz >/dev/null + echo 'char *comment = " /* \\\\u" "foo" " */";' >comment.c + $CCACHE $COMPILER -c comment.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + $CCACHE $COMPILER -c comment.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + echo 'char *comment = " /* \\\\u" "goo" " */";' >comment.c + $CCACHE $COMPILER -c comment.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 2 + ################################################################# # Check that strange "#line" directives are handled. testname="#line directives with troublesome files" @@ -2410,7 +2511,6 @@ all_suites=" base link !win32 hardlink -cpp2 nlevels4 nlevels1 basedir !win32 diff --git a/test/test_compopt.c b/test/test_compopt.c index 9af5e4e..6c17c3d 100644 --- a/test/test_compopt.c +++ b/test/test_compopt.c @@ -64,6 +64,16 @@ TEST(dash_MD_not_too_hard) CHECK(!compopt_too_hard("-MD")); } +TEST(dash_fprofile_arcs_not_too_hard) +{ + CHECK(!compopt_too_hard("-fprofile-arcs")); +} + +TEST(dash_ftest_coverage_not_too_hard) +{ + CHECK(!compopt_too_hard("-ftest-coverage")); +} + TEST(dash_doesnexist_not_too_hard) { CHECK(!compopt_too_hard("-doesntexist")); @@ -1,6 +1,6 @@ /* * Copyright (C) 2002 Andrew Tridgell - * Copyright (C) 2009-2014 Joel Rosdahl + * Copyright (C) 2009-2015 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 @@ -107,16 +107,34 @@ path_max(const char *path) #endif } +/* + * Warn about failure writing to the log file and then exit. + */ +static void +warn_log_fail(void) +{ + extern struct conf *conf; + + /* Note: Can't call fatal() since that would lead to recursion. */ + fprintf(stderr, "ccache: error: Failed to write to %s: %s\n", + conf->log_file, strerror(errno)); + exit(EXIT_FAILURE); +} + static void vlog(const char *format, va_list ap, bool log_updated_time) { + int rc1, rc2; if (!init_log()) { return; } log_prefix(log_updated_time); - vfprintf(logfile, format, ap); - fprintf(logfile, "\n"); + rc1 = vfprintf(logfile, format, ap); + rc2 = fprintf(logfile, "\n"); + if (rc1 < 0 || rc2 < 0) { + warn_log_fail(); + } } /* @@ -153,6 +171,7 @@ cc_bulklog(const char *format, ...) void cc_log_argv(const char *prefix, char **argv) { + int rc; if (!init_log()) { return; } @@ -160,7 +179,9 @@ cc_log_argv(const char *prefix, char **argv) log_prefix(true); fputs(prefix, logfile); print_command(logfile, argv); - fflush(logfile); + rc = fflush(logfile); + if (rc) + warn_log_fail(); } /* something went badly wrong! */ @@ -240,7 +261,8 @@ get_umask(void) /* * Copy src to dest, decompressing src if needed. compress_level > 0 decides - * whether dest will be compressed, and with which compression level. + * whether dest will be compressed, and with which compression level. Returns 0 + * on success and -1 on failure. On failure, errno represents the error. */ int copy_file(const char *src, const char *dest, int compress_level) @@ -252,6 +274,7 @@ copy_file(const char *src, const char *dest, int compress_level) char *tmp_name; struct stat st; int errnum; + int saved_errno = 0; /* open destination file */ tmp_name = x_strdup(dest); @@ -262,13 +285,15 @@ copy_file(const char *src, const char *dest, int compress_level) /* open source file */ fd_in = open(src, O_RDONLY | O_BINARY); if (fd_in == -1) { - cc_log("open error: %s", strerror(errno)); + saved_errno = errno; + cc_log("open error: %s", strerror(saved_errno)); goto error; } gz_in = gzdopen(fd_in, "rb"); if (!gz_in) { - cc_log("gzdopen(src) error: %s", strerror(errno)); + saved_errno = errno; + cc_log("gzdopen(src) error: %s", strerror(saved_errno)); close(fd_in); goto error; } @@ -279,8 +304,7 @@ copy_file(const char *src, const char *dest, int compress_level) * occupy an entire filesystem block, even for empty files. * Turn off compression for empty files to save some space. */ - if (fstat(fd_in, &st) != 0) { - cc_log("fstat error: %s", strerror(errno)); + if (x_fstat(fd_in, &st) != 0) { goto error; } if (file_size(&st) == 0) { @@ -291,7 +315,8 @@ copy_file(const char *src, const char *dest, int compress_level) if (compress_level > 0) { gz_out = gzdopen(dup(fd_out), "wb"); if (!gz_out) { - cc_log("gzdopen(dest) error: %s", strerror(errno)); + saved_errno = errno; + cc_log("gzdopen(dest) error: %s", strerror(saved_errno)); goto error; } gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY); @@ -306,6 +331,7 @@ copy_file(const char *src, const char *dest, int compress_level) do { count = write(fd_out, buf + written, n - written); if (count == -1 && errno != EINTR) { + saved_errno = errno; break; } written += count; @@ -315,9 +341,9 @@ copy_file(const char *src, const char *dest, int compress_level) if (compress_level > 0) { cc_log("gzwrite error: %s (errno: %s)", gzerror(gz_in, &errnum), - strerror(errno)); + strerror(saved_errno)); } else { - cc_log("write error: %s", strerror(errno)); + cc_log("write error: %s", strerror(saved_errno)); } goto error; } @@ -329,8 +355,9 @@ copy_file(const char *src, const char *dest, int compress_level) */ gzerror(gz_in, &errnum); if (!gzeof(gz_in) || (errnum != Z_OK && errnum != Z_STREAM_END)) { + saved_errno = errno; cc_log("gzread error: %s (errno: %s)", - gzerror(gz_in, &errnum), strerror(errno)); + gzerror(gz_in, &errnum), strerror(saved_errno)); gzclose(gz_in); if (gz_out) { gzclose(gz_out); @@ -354,12 +381,14 @@ copy_file(const char *src, const char *dest, int compress_level) /* the close can fail on NFS if out of space */ if (close(fd_out) == -1) { - cc_log("close error: %s", strerror(errno)); + saved_errno = errno; + cc_log("close error: %s", strerror(saved_errno)); goto error; } if (x_rename(tmp_name, dest) == -1) { - cc_log("rename error: %s", strerror(errno)); + saved_errno = errno; + cc_log("rename error: %s", strerror(saved_errno)); goto error; } @@ -379,6 +408,7 @@ error: } tmp_unlink(tmp_name); free(tmp_name); + errno = saved_errno; return -1; } @@ -494,16 +524,74 @@ create_parent_dirs(const char *path) const char * get_hostname(void) { - static char hostname[200] = ""; + static char hostname[260] = ""; + + if (hostname[0]) { + return hostname; + } - if (!hostname[0]) { - strcpy(hostname, "unknown"); + strcpy(hostname, "unknown"); #if HAVE_GETHOSTNAME - gethostname(hostname, sizeof(hostname)-1); -#endif - hostname[sizeof(hostname)-1] = 0; + gethostname(hostname, sizeof(hostname) - 1); +#elif defined(_WIN32) + const char *computer_name = getenv("COMPUTERNAME"); + if (computer_name) { + snprintf(hostname, sizeof(hostname), "%s", computer_name); + return hostname; + } + + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable Winsock DLL. */ + cc_log("WSAStartup failed with error: %d", err); + return hostname; + } + + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + /* Tell the user that we could not find a usable WinSock DLL. */ + cc_log("Could not find a usable version of Winsock.dll"); + WSACleanup(); + return hostname; } + int result = gethostname(hostname, sizeof(hostname) - 1); + if (result != 0) { + int last_error = WSAGetLastError(); + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = last_error; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + + lpDisplayBuf = (LPVOID) LocalAlloc( + LMEM_ZEROINIT, + (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__) + 200) + * sizeof(TCHAR)); + _snprintf((LPTSTR) lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %d: %s"), __FILE__, dw, + lpMsgBuf); + + cc_log("can't get hostname OS returned error: %s", (char*)lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + } + WSACleanup(); +#endif + + hostname[sizeof(hostname) - 1] = 0; return hostname; } @@ -712,6 +800,39 @@ void x_unsetenv(const char *name) #endif } +/* Like fstat() but also call cc_log on failure. */ +int +x_fstat(int fd, struct stat *buf) +{ + int result = fstat(fd, buf); + if (result != 0) { + cc_log("Failed to fstat fd %d: %s", fd, strerror(errno)); + } + return result; +} + +/* Like lstat() but also call cc_log on failure. */ +int +x_lstat(const char *pathname, struct stat *buf) +{ + int result = lstat(pathname, buf); + if (result != 0) { + cc_log("Failed to lstat %s: %s", pathname, strerror(errno)); + } + return result; +} + +/* Like stat() but also call cc_log on failure. */ +int +x_stat(const char *pathname, struct stat *buf) +{ + int result = stat(pathname, buf); + if (result != 0) { + cc_log("Failed to stat %s: %s", pathname, strerror(errno)); + } + return result; +} + /* * Construct a string according to the format and store it in *ptr. The * original *ptr is then freed. @@ -769,7 +890,7 @@ traverse(const char *dir, void (*fn)(const char *, struct stat *)) fname = format("%s/%s", dir, de->d_name); if (lstat(fname, &st)) { if (errno != ENOENT) { - perror(fname); + fatal("lstat %s failed: %s", fname, strerror(errno)); } free(fname); continue; @@ -986,9 +1107,14 @@ x_realpath(const char *path) path_handle = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED); - CloseHandle(path_handle); - p = ret+4;// strip the \\?\ from the file name + if (INVALID_HANDLE_VALUE != path_handle) { + GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED); + CloseHandle(path_handle); + p = ret + 4; /* strip \\?\ from the file name */ + } else { + snprintf(ret, maxlen, "%s", path); + p = ret; + } #else /* yes, there are such systems. This replacement relies on the fact that when we call x_realpath we only care about symlinks */ @@ -1301,14 +1427,46 @@ update_mtime(const char *path) /* * Rename oldpath to newpath (deleting newpath). */ + int x_rename(const char *oldpath, const char *newpath) { -#ifdef _WIN32 +#ifndef _WIN32 + return rename(oldpath, newpath); +#else /* Windows' rename() refuses to overwrite an existing file. */ unlink(newpath); /* not x_unlink, as x_unlink calls x_rename */ + /* If the function succeeds, the return value is nonzero. */ + if (MoveFileA(oldpath, newpath) == 0) { + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, + 0, NULL); + + lpDisplayBuf = (LPVOID) LocalAlloc( + LMEM_ZEROINIT, + (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__) + 40) + * sizeof(TCHAR)); + _snprintf((LPTSTR) lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %d: %s"), __FILE__, dw, lpMsgBuf); + + cc_log("can't rename file %s to %s OS returned error: %s", + oldpath, newpath, (char*) lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + return -1; + } else { + return 0; + } #endif - return rename(oldpath, newpath); } /* @@ -1318,8 +1476,13 @@ x_rename(const char *oldpath, const char *newpath) int tmp_unlink(const char *path) { + int rc; cc_log("Unlink %s", path); - return unlink(path); + rc = unlink(path); + if (rc) { + cc_log("Unlink failed: %s", strerror(errno)); + } + return rc; } /* @@ -1335,19 +1498,26 @@ x_unlink(const char *path) */ char *tmp_name = format("%s.rm.%s", path, tmp_string()); int result = 0; + int saved_errno = 0; cc_log("Unlink %s via %s", path, tmp_name); if (x_rename(path, tmp_name) == -1) { result = -1; + saved_errno = errno; goto out; } if (unlink(tmp_name) == -1) { /* If it was released in a race, that's OK. */ if (errno != ENOENT) { result = -1; + saved_errno = errno; } } out: free(tmp_name); + if (result) { + cc_log("x_unlink failed: %s", strerror(saved_errno)); + } + errno = saved_errno; return result; } @@ -1383,7 +1553,7 @@ read_file(const char *path, size_t size_hint, char **data, size_t *size) if (size_hint == 0) { struct stat st; - if (stat(path, &st) == 0) { + if (x_stat(path, &st) == 0) { size_hint = st.st_size; } } @@ -1 +1 @@ -const char CCACHE_VERSION[] = "3.2.1"; +const char CCACHE_VERSION[] = "3.2.2"; |