summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2021-08-03 16:16:40 +0900
committerJinWang An <jinwang.an@samsung.com>2021-08-03 16:16:40 +0900
commitdc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5 (patch)
tree34f25517871bedf01569c9166e175c13bf91b3aa
parent335f2c0f9f8337f0f8b5d7ecaf4c38f67b77b5f5 (diff)
downloadccache-dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5.tar.gz
ccache-dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5.tar.bz2
ccache-dc64413d7c0258eaeca8ee87e9a4bc36bae0d7b5.zip
Imported Upstream version 3.2.2upstream/3.2.2
-rw-r--r--AUTHORS.html32
-rw-r--r--AUTHORS.txt5
-rw-r--r--INSTALL.html7
-rw-r--r--LICENSE.html13
-rw-r--r--LICENSE.txt6
-rw-r--r--MANUAL.html16
-rw-r--r--MANUAL.txt3
-rw-r--r--NEWS.html176
-rw-r--r--NEWS.txt69
-rw-r--r--README.html7
-rw-r--r--ccache.113
-rw-r--r--ccache.c362
-rw-r--r--ccache.h10
-rw-r--r--cleanup.c6
-rw-r--r--compopt.c6
-rwxr-xr-xconfigure5
-rw-r--r--configure.ac6
-rw-r--r--confitems_lookup.c1
-rw-r--r--dev.mk.in2
-rw-r--r--envtoconfitems_lookup.c1
-rw-r--r--execute.c88
-rw-r--r--hash.c1
-rw-r--r--hashutil.c6
-rw-r--r--lockfile.c17
-rw-r--r--manifest.c5
-rw-r--r--stats.c4
-rwxr-xr-xtest.sh122
-rw-r--r--test/test_compopt.c10
-rw-r--r--util.c228
-rw-r--r--version.c2
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 &lt;<a href="mailto:alfred.landrum@riverbed.com">alfred.landrum@r
</li>
<li>
<p>
+Anders Björklund &lt;<a href="mailto:anders@itension.se">anders@itension.se</a>&gt;
+</p>
+</li>
+<li>
+<p>
Andrea Bittau &lt;<a href="mailto:a.bittau@cs.ucl.ac.uk">a.bittau@cs.ucl.ac.uk</a>&gt;
</p>
</li>
@@ -789,6 +794,11 @@ Bo Rydberg &lt;<a href="mailto:bolry@hotmail.com">bolry@hotmail.com</a>&gt;
</li>
<li>
<p>
+Chiaki ISHIKAWA &lt;<a href="mailto:ishikawa@yk.rim.or.jp">ishikawa@yk.rim.or.jp</a>&gt;
+</p>
+</li>
+<li>
+<p>
Chris AtLee &lt;<a href="mailto:chris@atlee.ca">chris@atlee.ca</a>&gt;
</p>
</li>
@@ -819,6 +829,11 @@ Hongli Lai &lt;<a href="mailto:hongli@phusion.nl">hongli@phusion.nl</a>&gt;
</li>
<li>
<p>
+Jiang Jiang &lt;<a href="mailto:jiangj@opera.com">jiangj@opera.com</a>&gt;
+</p>
+</li>
+<li>
+<p>
Joel Rosdahl &lt;<a href="mailto:joel@rosdahl.net">joel@rosdahl.net</a>&gt;
</p>
</li>
@@ -864,6 +879,11 @@ Lars Gustäbel &lt;<a href="mailto:lars@gustaebel.de">lars@gustaebel.de</a>&gt;
</li>
<li>
<p>
+Leanid Chaika &lt;<a href="mailto:leanid.chaika@gmail.com">leanid.chaika@gmail.com</a>&gt;
+</p>
+</li>
+<li>
+<p>
Luboš Luňák &lt;<a href="mailto:l.lunak@suse.cz">l.lunak@suse.cz</a>&gt;
</p>
</li>
@@ -924,6 +944,11 @@ Robin H. Johnson &lt;<a href="mailto:robbat2@gentoo.org">robbat2@gentoo.org</a>&
</li>
<li>
<p>
+Ryb &lt;<a href="mailto:ryb@ableton.com">ryb@ableton.com</a>&gt;
+</p>
+</li>
+<li>
+<p>
Tim Potter &lt;<a href="mailto:tpot@samba.org">tpot@samba.org</a>&gt;
</p>
</li>
@@ -960,8 +985,9 @@ Yiding Jia &lt;<a href="mailto:yiding@fb.com">yiding@fb.com</a>&gt;
<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 &#8220;[boolean]&#8221;</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>
diff --git a/MANUAL.txt b/MANUAL.txt
index 4ac113e..d0ee09b 100644
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -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
diff --git a/NEWS.html b/NEWS.html
index 912ecec..af09780 100644
--- a/NEWS.html
+++ b/NEWS.html
@@ -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:&lt;value&gt;</code>. This is a faster
+ alternative to <code>CCACHE_COMPILERCHECK=&lt;command&gt;</code> if the command&#8217;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&#8217;t try to reset a non-existing stats file. This avoids &#8220;No such file or
+ directory&#8221; messages in the ccache log when the cache directory doesn&#8217;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&#8217;t try to reset a non-existing stats file. This avoids &#8220;No such file or
+ directory&#8221; messages in the ccache log when the cache directory doesn&#8217;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>&lt;ccache_dir&gt;/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 &#8220;called for preprocessing&#8221; 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&#8217;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&#8217;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>
diff --git a/NEWS.txt b/NEWS.txt
index ca57aed..4861a4f 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -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&#8217;s &#8220;compilercache&#8221; (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>
diff --git a/ccache.1 b/ccache.1
index 87abbe9..093d3f0 100644
--- a/ccache.1
+++ b/ccache.1
@@ -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
diff --git a/ccache.c b/ccache.c
index c407760..cb7e72e 100644
--- a/ccache.c
+++ b/ccache.c
@@ -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
diff --git a/ccache.h b/ccache.h
index 6fdd55f..6028f46 100644
--- a/ccache.h
+++ b/ccache.h
@@ -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
diff --git a/cleanup.c b/cleanup.c
index ee872cc..981423d 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -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. */
diff --git a/compopt.c b/compopt.c
index 1996fdf..41f710d 100644
--- a/compopt.c
+++ b/compopt.c
@@ -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},
diff --git a/configure b/configure
index 29cd51c..b004bd4 100755
--- a/configure
+++ b/configure
@@ -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__
diff --git a/dev.mk.in b/dev.mk.in
index 914e7e5..adc3557 100644
--- a/dev.mk.in
+++ b/dev.mk.in
@@ -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__
diff --git a/execute.c b/execute.c
index 78f1e4b..94d605d 100644
--- a/execute.c
+++ b/execute.c
@@ -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);
diff --git a/hash.c b/hash.c
index 80beed2..7950737 100644
--- a/hash.c
+++ b/hash.c
@@ -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;
}
diff --git a/hashutil.c b/hashutil.c
index 82b7367..b8103a6 100644
--- a/hashutil.c
+++ b/hashutil.c
@@ -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;
}
}
diff --git a/lockfile.c b/lockfile.c
index af4fa43..f4f2028 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -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;
}
diff --git a/manifest.c b/manifest.c
index 6eb53fd..1dcf83f 100644
--- a/manifest.c
+++ b/manifest.c
@@ -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));
diff --git a/stats.c b/stats.c
index aef628f..72985b4 100644
--- a/stats.c
+++ b/stats.c
@@ -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)
diff --git a/test.sh b/test.sh
index b511146..f14e287 100755
--- a/test.sh
+++ b/test.sh
@@ -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"));
diff --git a/util.c b/util.c
index 80eb58b..658cab6 100644
--- a/util.c
+++ b/util.c
@@ -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;
}
}
diff --git a/version.c b/version.c
index 4bf7d25..ec85c84 100644
--- a/version.c
+++ b/version.c
@@ -1 +1 @@
-const char CCACHE_VERSION[] = "3.2.1";
+const char CCACHE_VERSION[] = "3.2.2";