<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
<head>\r
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
-<meta name="generator" content="AsciiDoc 8.6.10" />\r
+<meta name="generator" content="AsciiDoc 9.0.0rc1" />\r
<title>ccache copyright and license</title>\r
<style type="text/css">\r
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
p.table {\r
margin-top: 0;\r
}\r
-/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+/* Because the table frame attribute is overridden by CSS in most browsers. */\r
div.tableblock > table[frame="void"] {\r
border-style: none;\r
}\r
<body class="article">\r
<div id="header">\r
<h1>ccache copyright and license</h1>\r
-<span id="revnumber">version 3.7.9</span>\r
+<span id="revnumber">version 3.7.10</span>\r
<div id="toc">
<div id="toctitle">Table of Contents</div>
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.7.9<br />\r
+Version 3.7.10<br />\r
Last updated\r
- 2020-03-29 16:11:12 CEST\r
+ 2020-06-22 19:59:54 CEST\r
</div>\r
</div>\r
</body>\r
/* Define to 1 if your compiler supports extern inline */
#undef HAVE_EXTERN_INLINE
-/* Define to 1 if you have the `GetFinalPathNameByHandleW' function. */
-#undef HAVE_GETFINALPATHNAMEBYHANDLEW
-
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
if test x${windows_os} = xyes; then
LIBS="$LIBS -lws2_32"
- for ac_func in GetFinalPathNameByHandleW
-do :
- ac_fn_c_check_func "$LINENO" "GetFinalPathNameByHandleW" "ac_cv_func_GetFinalPathNameByHandleW"
-if test "x$ac_cv_func_GetFinalPathNameByHandleW" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETFINALPATHNAMEBYHANDLEW 1
-_ACEOF
-
-else
- LIBS="$LIBS -lpsapi"
-fi
-done
-
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
dnl Linking on Windows needs ws2_32
if test x${windows_os} = xyes; then
LIBS="$LIBS -lws2_32"
- AC_CHECK_FUNCS(GetFinalPathNameByHandleW,[],[LIBS="$LIBS -lpsapi"])
fi
AC_C_BIGENDIAN
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
<head>\r
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
-<meta name="generator" content="AsciiDoc 8.6.10" />\r
+<meta name="generator" content="AsciiDoc 9.0.0rc1" />\r
<title>ccache authors</title>\r
<style type="text/css">\r
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
p.table {\r
margin-top: 0;\r
}\r
-/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+/* Because the table frame attribute is overridden by CSS in most browsers. */\r
div.tableblock > table[frame="void"] {\r
border-style: none;\r
}\r
<body class="article">\r
<div id="header">\r
<h1>ccache authors</h1>\r
-<span id="revnumber">version 3.7.9</span>\r
+<span id="revnumber">version 3.7.10</span>\r
<div id="toc">
<div id="toctitle">Table of Contents</div>
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.7.9<br />\r
+Version 3.7.10<br />\r
Last updated\r
- 2020-03-29 16:11:12 CEST\r
+ 2020-06-22 19:59:54 CEST\r
</div>\r
</div>\r
</body>\r
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
<head>\r
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
-<meta name="generator" content="AsciiDoc 8.6.10" />\r
+<meta name="generator" content="AsciiDoc 9.0.0rc1" />\r
<title>CCACHE(1)</title>\r
<style type="text/css">\r
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
p.table {\r
margin-top: 0;\r
}\r
-/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+/* Because the table frame attribute is overridden by CSS in most browsers. */\r
div.tableblock > table[frame="void"] {\r
border-style: none;\r
}\r
<body class="article">\r
<div id="header">\r
<h1>CCACHE(1)</h1>\r
-<span id="revnumber">version 3.7.9</span>\r
+<span id="revnumber">version 3.7.10</span>\r
<div id="toc">
<div id="toctitle">Table of Contents</div>
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.7.9<br />\r
+Version 3.7.10<br />\r
Last updated\r
- 2020-03-29 16:11:12 CEST\r
+ 2020-06-22 19:59:54 CEST\r
</div>\r
</div>\r
</body>\r
ccache news
===========
+ccache 3.7.10
+------------
+Release date: 2020-06-22
+
+Bug fixes
+~~~~~~~~~
+
+- Improved handling of profiling options. ccache should now work correctly for
+ profiling options like `-fprofile-{generate,use}[=path]` for GCC ≥ 9 and
+ Clang as well as `-fauto-profile[=path]` and the Clang-specific
+ `-fprofile-instr-{generate,use}[=path]` and `-fprofile-sample-{use,accurate}`
+ options.
+
+- ccache now copies files directly from the cache to the destination file
+ instead of via a temporary file. This avoids problems when using filenames
+ long enough to be near the file system's filename max limit.
+
+- When the hard-link mode is enabled, ccache now only uses hard links for
+ object files, not other files like dependency files. This is because
+ compilers unlink object files before writing to them but they don't do that
+ for dependency files, so the latter can become overwritten and therefore
+ corrupted in the cache.
+
+- Fixed a glitch related to hard-link mode and an empty cache.
+
+- ccache now supports the ccache.conf file to be a symlink.
+
+- Temporary files are now deleted immediately on signals like SIGTERM and
+ SIGINT instead of some time later in a cleanup phase.
+
+- Fixed a bug that affected ccache's `-o/--set-config` option for the
+ `base_dir` and `cache_dir_levels` keys.
+
+
ccache 3.7.9
------------
Release date: 2020-03-29
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
<head>\r
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
-<meta name="generator" content="AsciiDoc 8.6.10" />\r
+<meta name="generator" content="AsciiDoc 9.0.0rc1" />\r
<title>ccache news</title>\r
<style type="text/css">\r
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
p.table {\r
margin-top: 0;\r
}\r
-/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+/* Because the table frame attribute is overridden by CSS in most browsers. */\r
div.tableblock > table[frame="void"] {\r
border-style: none;\r
}\r
<body class="article">\r
<div id="header">\r
<h1>ccache news</h1>\r
-<span id="revnumber">version 3.7.9</span>\r
+<span id="revnumber">version 3.7.10</span>\r
<div id="toc">
<div id="toctitle">Table of Contents</div>
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
</div>\r
<div id="content">\r
<div class="sect1">\r
+<h2 id="_ccache_3_7_10">ccache 3.7.10</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Release date: 2020-06-22</p></div>\r
+<div class="sect2">\r
+<h3 id="_bug_fixes">Bug fixes</h3>\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Improved handling of profiling options. ccache should now work correctly for\r
+ profiling options like <code>-fprofile-{generate,use}[=path]</code> for GCC ≥ 9 and\r
+ Clang as well as <code>-fauto-profile[=path]</code> and the Clang-specific\r
+ <code>-fprofile-instr-{generate,use}[=path]</code> and <code>-fprofile-sample-{use,accurate}</code>\r
+ options.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache now copies files directly from the cache to the destination file\r
+ instead of via a temporary file. This avoids problems when using filenames\r
+ long enough to be near the file system’s filename max limit.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+When the hard-link mode is enabled, ccache now only uses hard links for\r
+ object files, not other files like dependency files. This is because\r
+ compilers unlink object files before writing to them but they don’t do that\r
+ for dependency files, so the latter can become overwritten and therefore\r
+ corrupted in the cache.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a glitch related to hard-link mode and an empty cache.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+ccache now supports the ccache.conf file to be a symlink.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Temporary files are now deleted immediately on signals like SIGTERM and\r
+ SIGINT instead of some time later in a cleanup phase.\r
+</p>\r
+</li>\r
+<li>\r
+<p>\r
+Fixed a bug that affected ccache’s <code>-o/--set-config</code> option for the\r
+ <code>base_dir</code> and <code>cache_dir_levels</code> keys.\r
+</p>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
<h2 id="_ccache_3_7_9">ccache 3.7.9</h2>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2020-03-29</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes">Bug fixes</h3>\r
+<h3 id="_bug_fixes_2">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2020-03-16</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_2">Bug fixes</h3>\r
+<h3 id="_bug_fixes_3">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2020-01-05</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_3">Bug fixes</h3>\r
+<h3 id="_bug_fixes_4">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2019-11-17</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_4">Bug fixes</h3>\r
+<h3 id="_bug_fixes_5">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_5">Bug fixes</h3>\r
+<h3 id="_bug_fixes_6">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2019-08-17</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_6">Bug fixes</h3>\r
+<h3 id="_bug_fixes_7">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2019-07-19</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_7">Bug fixes</h3>\r
+<h3 id="_bug_fixes_8">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2018-09-02</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_8">Bug fixes</h3>\r
+<h3 id="_bug_fixes_9">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2018-03-25</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_9">Bug fixes</h3>\r
+<h3 id="_bug_fixes_10">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2018-02-11</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_10">Bug fixes</h3>\r
+<h3 id="_bug_fixes_11">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_11">Bug fixes</h3>\r
+<h3 id="_bug_fixes_12">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_12">Bug fixes</h3>\r
+<h3 id="_bug_fixes_13">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_13">Bug fixes</h3>\r
+<h3 id="_bug_fixes_14">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_14">Bug fixes</h3>\r
+<h3 id="_bug_fixes_15">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-10-26</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_15">Bug fixes</h3>\r
+<h3 id="_bug_fixes_16">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-28</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_16">Bug fixes</h3>\r
+<h3 id="_bug_fixes_17">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_17">Bug fixes</h3>\r
+<h3 id="_bug_fixes_18">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_18">Bug fixes</h3>\r
+<h3 id="_bug_fixes_19">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-28</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_19">Bug fixes</h3>\r
+<h3 id="_bug_fixes_20">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-09-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_20">Bug fixes</h3>\r
+<h3 id="_bug_fixes_21">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-07-20</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_21">Bug fixes</h3>\r
+<h3 id="_bug_fixes_22">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-07-12</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_22">Bug fixes</h3>\r
+<h3 id="_bug_fixes_23">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_23">Bug fixes</h3>\r
+<h3 id="_bug_fixes_24">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2015-10-08</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_24">Bug fixes</h3>\r
+<h3 id="_bug_fixes_25">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_25">Bug fixes</h3>\r
+<h3 id="_bug_fixes_26">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_26">Bug fixes</h3>\r
+<h3 id="_bug_fixes_27">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2014-12-10</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_27">Bug fixes</h3>\r
+<h3 id="_bug_fixes_28">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_28">Bug fixes</h3>\r
+<h3 id="_bug_fixes_29">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2016-07-12</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_29">Bug fixes</h3>\r
+<h3 id="_bug_fixes_30">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2015-03-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_30">Bug fixes</h3>\r
+<h3 id="_bug_fixes_31">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_31">Bug fixes</h3>\r
+<h3 id="_bug_fixes_32">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2013-01-06</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_32">Bug fixes</h3>\r
+<h3 id="_bug_fixes_33">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_33">Bug fixes</h3>\r
+<h3 id="_bug_fixes_34">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2012-01-08</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_34">Bug fixes</h3>\r
+<h3 id="_bug_fixes_35">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_35">Bug fixes</h3>\r
+<h3 id="_bug_fixes_36">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_36">Bug fixes</h3>\r
+<h3 id="_bug_fixes_37">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2011-01-09</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_37">Bug fixes</h3>\r
+<h3 id="_bug_fixes_38">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-11-28</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_38">Bug fixes</h3>\r
+<h3 id="_bug_fixes_39">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-11-21</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_39">Bug fixes</h3>\r
+<h3 id="_bug_fixes_40">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-11-07</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_40">Bug fixes</h3>\r
+<h3 id="_bug_fixes_41">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_41">Bug fixes</h3>\r
+<h3 id="_bug_fixes_42">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div class="sectionbody">\r
<div class="paragraph"><p>Release date: 2010-07-15</p></div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_42">Bug fixes</h3>\r
+<h3 id="_bug_fixes_43">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
</ul></div>\r
</div>\r
<div class="sect2">\r
-<h3 id="_bug_fixes_43">Bug fixes</h3>\r
+<h3 id="_bug_fixes_44">Bug fixes</h3>\r
<div class="ulist"><ul>\r
<li>\r
<p>\r
<div id="footnotes"><hr /></div>\r
<div id="footer">\r
<div id="footer-text">\r
-Version 3.7.9<br />\r
+Version 3.7.10<br />\r
Last updated\r
- 2020-03-29 16:11:12 CEST\r
+ 2020-06-22 19:59:54 CEST\r
</div>\r
</div>\r
</body>\r
.\" Title: ccache
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 03/29/2020
+.\" Date: 06/22/2020
.\" Manual: ccache Manual
-.\" Source: ccache 3.7.9
+.\" Source: ccache 3.7.10
.\" Language: English
.\"
-.TH "CCACHE" "1" "03/29/2020" "ccache 3\&.7\&.9" "ccache Manual"
+.TH "CCACHE" "1" "06/22/2020" "ccache 3\&.7\&.10" "ccache Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
// Is the compiler 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 preprocessed file.
static char *i_tmpfile;
enum guessed_compiler guessed_compiler = GUESSED_UNKNOWN;
// Profile generation / usage information.
-static char *profile_dir = NULL;
+static char *profile_path = NULL; // directory (GCC/Clang) or file (Clang)
static bool profile_use = false;
static bool profile_generate = false;
return result;
}
-// Helper function for copy_file_to_cache and move_file_to_cache_same_fs.
+// Helper function for put_file_in_cache and move_file_to_cache_same_fs.
static void
-do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
+do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy,
+ bool attempt_link)
{
assert(!conf->read_only);
assert(!conf->read_only_direct);
bool orig_dest_existed = stat(dest, &orig_dest_st) == 0;
int compression_level = conf->compression ? conf->compression_level : 0;
bool do_move = !copy && !conf->compression;
- bool do_link = copy && conf->hard_link && !conf->compression;
+ bool do_link = attempt_link && copy && conf->hard_link && !conf->compression;
if (do_move) {
move_uncompressed_file(source, dest, compression_level);
if (do_link) {
x_unlink(dest);
int ret = link(source, dest);
+ if (ret != 0 && errno == ENOENT) {
+ create_parent_dirs(dest);
+ ret = link(source, dest);
+ }
if (ret != 0) {
cc_log("Failed to link %s to %s: %s", source, dest, strerror(errno));
cc_log("Falling back to copying");
}
}
if (!do_link) {
- int ret = copy_file(source, dest, compression_level);
+ int ret = copy_file(source, dest, compression_level, true);
if (ret != 0) {
cc_log("Failed to copy %s to %s: %s", source, dest, strerror(errno));
stats_update(STATS_ERROR);
orig_dest_existed ? 0 : 1);
}
-// Copy a file into the cache.
+// Copy or link a file into the cache.
//
// dest must be a path in the cache (see get_path_in_cache). source does not
// have to be on the same file system as dest.
// true and conf->compression is false, otherwise copy. dest will be compressed
// if conf->compression is true.
static void
+put_file_in_cache(const char *source, const char *dest)
+{
+ do_copy_or_move_file_to_cache(source, dest, true, true);
+}
+
+// Copy a file to the cache.
+//
+// dest must be a path in the cache (see get_path_in_cache). source does not
+// have to be on the same file system as dest.
+static void
copy_file_to_cache(const char *source, const char *dest)
{
- do_copy_or_move_file_to_cache(source, dest, true);
+ do_copy_or_move_file_to_cache(source, dest, true, false);
}
// Move a file into the cache.
static void
move_file_to_cache_same_fs(const char *source, const char *dest)
{
- do_copy_or_move_file_to_cache(source, dest, false);
+ do_copy_or_move_file_to_cache(source, dest, false, true);
}
// Helper function for get_file_from_cache and copy_file_from_cache.
x_unlink(dest);
ret = link(source, dest);
} else {
- ret = copy_file(source, dest, 0);
+ ret = copy_file(source, dest, 0, false);
}
if (ret == -1) {
if (!conf->depend_mode) {
tmp_stdout = format("%s.tmp.stdout", cached_obj);
tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
+ add_pending_tmp_file(tmp_stdout);
+
tmp_stderr = format("%s.tmp.stderr", cached_obj);
tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+ add_pending_tmp_file(tmp_stderr);
status = execute(args->argv, tmp_stdout_fd, tmp_stderr_fd, &compiler_pid);
args_pop(args, 3);
// The cached object path is not known yet, use temporary files.
tmp_stdout = format("%s/tmp.stdout", temp_dir());
tmp_stdout_fd = create_tmp_fd(&tmp_stdout);
+ add_pending_tmp_file(tmp_stdout);
+
tmp_stderr = format("%s/tmp.stderr", temp_dir());
tmp_stderr_fd = create_tmp_fd(&tmp_stderr);
+ add_pending_tmp_file(tmp_stderr);
// Use the original arguments (including dependency options) in depend
// mode.
if (!conf->depend_mode) {
move_file_to_cache_same_fs(tmp_stderr, cached_stderr);
} else {
- copy_file_to_cache(tmp_stderr, cached_stderr);
+ put_file_in_cache(tmp_stderr, cached_stderr);
}
} else if (conf->recache) {
// If recaching, we need to remove any previous .stderr.
MTR_BEGIN("file", "file_put");
- copy_file_to_cache(output_obj, cached_obj);
+ put_file_in_cache(output_obj, cached_obj);
if (produce_dep_file) {
copy_file_to_cache(output_dep, cached_dep);
}
// Possibly hash the coverage data file path.
if (generating_coverage && profile_arcs) {
char *dir = dirname(output_obj);
- if (profile_dir) {
- dir = x_strdup(profile_dir);
+ if (profile_path) {
+ dir = x_strdup(profile_path);
} else {
char *real_dir = x_realpath(dir);
free(dir);
}
}
+static bool
+hash_profile_data_file(const char *path, struct hash *hash)
+{
+ assert(path);
+
+ char *base_name = remove_extension(output_obj);
+ char *hashified_cwd = get_cwd();
+ for (char *p = hashified_cwd; *p; ++p) {
+ if (*p == '/') {
+ *p = '#';
+ }
+ }
+ char *paths_to_try[] = {
+ // -fprofile-use[=dir]/-fbranch-probabilities (GCC <9)
+ format("%s/%s.gcda", path, base_name),
+ // -fprofile-use[=dir]/-fbranch-probabilities (GCC >=9)
+ format("%s/%s#%s.gcda", path, hashified_cwd, base_name),
+ // -fprofile(-instr|-sample)-use=file (Clang), -fauto-profile=file (GCC >=5)
+ x_strdup(path),
+ // -fprofile(-instr|-sample)-use=dir (Clang)
+ format("%s/default.profdata", path),
+ // -fauto-profile (GCC >=5)
+ x_strdup("fbdata.afdo"), // -fprofile-dir is not used
+ NULL
+ };
+ free(hashified_cwd);
+ free(base_name);
+
+ bool found = false;
+ for (char **p = paths_to_try; *p; ++p) {
+ cc_log("Checking for profile data file %s", *p);
+ struct stat st;
+ if (stat(*p, &st) == 0 && !S_ISDIR(st.st_mode)) {
+ cc_log("Adding profile data %s to the hash", *p);
+ hash_delimiter(hash, "-fprofile-use");
+ if (hash_file(hash, *p)) {
+ found = true;
+ }
+ }
+ free(*p);
+ }
+
+ return found;
+}
+
// Update a hash sum with information specific to the direct and preprocessor
// modes and calculate the object hash. Returns the object hash on success,
// otherwise NULL. Caller frees.
hash_nvcc_host_compiler(hash, NULL, NULL);
}
- // For profile generation (-fprofile-arcs, -fprofile-generate):
- // - hash profile directory
+ // For profile generation (-fprofile(-instr)-generate[=path])
+ // - hash profile path
//
- // For profile usage (-fprofile-use):
+ // For profile usage (-fprofile(-instr|-sample)-use, -fbranch-probabilities):
// - hash profile data
//
- // -fbranch-probabilities and -fvpt usage is covered by
- // -fprofile-generate/-fprofile-use.
- //
// The profile directory can be specified as an argument to
- // -fprofile-generate=, -fprofile-use= or -fprofile-dir=.
+ // -fprofile(-instr)-generate=, -fprofile(-instr|-sample)-use= or
+ // --fprofile-dir=.
if (profile_generate) {
- if (!profile_dir) {
- profile_dir = get_cwd();
- }
- cc_log("Adding profile directory %s to our hash", profile_dir);
+ assert(profile_path);
+ cc_log("Adding profile directory %s to our hash", profile_path);
hash_delimiter(hash, "-fprofile-dir");
- hash_string(hash, profile_dir);
+ hash_string(hash, profile_path);
}
- if (profile_use) {
- // Calculate gcda name.
- if (!profile_dir) {
- profile_dir = get_cwd();
- }
- char *base_name = remove_extension(output_obj);
- char *gcda_name = format("%s/%s.gcda", profile_dir, base_name);
- cc_log("Adding profile data %s to our hash", gcda_name);
- // Add the gcda to our hash.
- hash_delimiter(hash, "-fprofile-use");
- hash_file(hash, gcda_name);
- free(base_name);
- free(gcda_name);
+ if (profile_use && !hash_profile_data_file(profile_path, hash)) {
+ cc_log("No profile data file found");
+ stats_update(STATS_NOINPUT);
+ failed();
}
// Adding -arch to hash since cpp output is affected.
if (!str_eq(output_obj, "/dev/null")) {
get_file_from_cache(cached_obj, output_obj);
if (using_split_dwarf) {
- get_file_from_cache(cached_dwo, output_dwo);
+ copy_file_from_cache(cached_dwo, output_dwo);
}
}
if (produce_dep_file) {
copy_file_from_cache(cached_dep, output_dep);
}
if (generating_coverage) {
- get_file_from_cache(cached_cov, output_cov);
+ copy_file_from_cache(cached_cov, output_cov);
}
if (generating_stackusage) {
- get_file_from_cache(cached_su, output_su);
+ copy_file_from_cache(cached_su, output_su);
}
if (generating_diagnostics) {
- get_file_from_cache(cached_dia, output_dia);
+ copy_file_from_cache(cached_dia, output_dia);
}
MTR_END("file", "file_get");
return true;
}
+static bool
+process_profiling_option(const char *arg)
+{
+ char *new_profile_path = NULL;
+ bool new_profile_use = false;
+
+ if (str_startswith(arg, "-fprofile-dir=")) {
+ new_profile_path = x_strdup(strchr(arg, '=') + 1);
+ } else if (str_eq(arg, "-fprofile-generate")
+ || str_eq(arg, "-fprofile-instr-generate")) {
+ profile_generate = true;
+ if (guessed_compiler == GUESSED_CLANG) {
+ new_profile_path = x_strdup(".");
+ } else {
+ // GCC uses $PWD/$(basename $obj).
+ new_profile_path = get_cwd();
+ }
+ } else if (str_startswith(arg, "-fprofile-generate=")
+ || str_startswith(arg, "-fprofile-instr-generate=")) {
+ profile_generate = true;
+ new_profile_path = x_strdup(strchr(arg, '=') + 1);
+ } else if (str_eq(arg, "-fprofile-use")
+ || str_eq(arg, "-fprofile-instr-use")
+ || str_eq(arg, "-fprofile-sample-use")
+ || str_eq(arg, "-fbranch-probabilities")
+ || str_eq(arg, "-fauto-profile")) {
+ new_profile_use = true;
+ if (!profile_path) {
+ new_profile_path = x_strdup(".");
+ }
+ } else if (str_startswith(arg, "-fprofile-use=")
+ || str_startswith(arg, "-fprofile-instr-use=")
+ || str_startswith(arg, "-fprofile-sample-use=")
+ || str_startswith(arg, "-fauto-profile=")) {
+ new_profile_use = true;
+ new_profile_path = x_strdup(strchr(arg, '=') + 1);
+ } else if (str_eq(arg, "-fprofile-sample-accurate")) {
+ return true;
+ } else {
+ cc_log("Unknown profiling option: %s", arg);
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ return false;
+ }
+
+ if (new_profile_use) {
+ if (profile_use) {
+ free(new_profile_path);
+ cc_log("Multiple profiling options not supported");
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ return false;
+ }
+ profile_use = true;
+ }
+
+ if (new_profile_path) {
+ free(profile_path);
+ profile_path = new_profile_path;
+ cc_log("Set profile directory to %s", profile_path);
+ }
+
+ if (profile_generate && profile_use) {
+ // Too hard to figure out what the compiler will do.
+ cc_log("Both generating and using profile info, giving up");
+ stats_update(STATS_UNSUPPORTED_OPTION);
+ return false;
+ }
+
+ return true;
+}
+
// Process the compiler options into options suitable for passing to the
// preprocessor and the real compiler. preprocessor_args doesn't include -E;
// this is added later. extra_args_to_hash are the arguments that are not
// -Xarch_* options are too hard.
if (str_startswith(argv[i], "-Xarch_")) {
- cc_log("Unsupported compiler option :%s", argv[i]);
+ cc_log("Unsupported compiler option: %s", argv[i]);
stats_update(STATS_UNSUPPORTED_OPTION);
result = false;
goto out;
args_add(common_args, argv[i]);
continue;
}
- if (str_startswith(argv[i], "-fprofile-dir=")) {
- profile_dir = x_strdup(argv[i] + 14);
- args_add(common_args, argv[i]);
- continue;
+ if (str_startswith(argv[i], "-fprofile-")
+ || str_startswith(argv[i], "-fauto-profile")
+ || str_eq(argv[i], "-fbranch-probabilities")) {
+ if (process_profiling_option(argv[i])) {
+ args_add(common_args, argv[i]);
+ continue;
+ } else {
+ result = false;
+ goto out;
+ }
}
if (str_startswith(argv[i], "-fsanitize-blacklist=")) {
sanitize_blacklists = x_realloc(
continue;
}
- if (str_startswith(argv[i], "-fprofile-")) {
- char *arg = x_strdup(argv[i]);
- const char *arg_profile_dir = strchr(argv[i], '=');
- if (arg_profile_dir) {
- // Convert to absolute path.
- char *dir = x_realpath(arg_profile_dir + 1);
- if (!dir) {
- // Directory doesn't exist.
- dir = x_strdup(arg_profile_dir + 1);
- }
-
- // We can get a better hit rate by using the real path here.
- free(arg);
- char *option = x_strndup(argv[i], arg_profile_dir - argv[i]);
- arg = format("%s=%s", option, dir);
- cc_log("Rewriting %s to %s", argv[i], arg);
- free(option);
- free(dir);
- }
-
- bool supported_profile_option = false;
- if (str_startswith(argv[i], "-fprofile-generate")
- || str_eq(argv[i], "-fprofile-arcs")) {
- profile_generate = true;
- supported_profile_option = true;
- } else if (str_startswith(argv[i], "-fprofile-use")
- || str_eq(argv[i], "-fbranch-probabilities")) {
- profile_use = true;
- supported_profile_option = true;
- } else if (str_eq(argv[i], "-fprofile-dir")) {
- supported_profile_option = true;
- }
-
- if (supported_profile_option) {
- args_add(common_args, arg);
- free(arg);
-
- // If the profile directory has already been set, give up... Hard to
- // know what the user means, and what the compiler will do.
- if (arg_profile_dir && profile_dir) {
- cc_log("Profile directory already set; giving up");
- stats_update(STATS_UNSUPPORTED_OPTION);
- result = false;
- goto out;
- } else if (arg_profile_dir) {
- cc_log("Setting profile directory to %s", arg_profile_dir);
- profile_dir = x_strdup(arg_profile_dir);
- }
- continue;
- }
- cc_log("Unknown profile option: %s", argv[i]);
- free(arg);
- }
-
if (str_eq(argv[i], "-fcolor-diagnostics")
|| str_eq(argv[i], "-fno-color-diagnostics")
|| str_eq(argv[i], "-fdiagnostics-color")
}
free(debug_prefix_maps); debug_prefix_maps = NULL;
debug_prefix_maps_len = 0;
- free(profile_dir); profile_dir = NULL;
+ free(profile_path); profile_path = NULL;
+ profile_use = false;
+ profile_generate = false;
for (size_t i = 0; i < sanitize_blacklists_len; i++) {
free(sanitize_blacklists[i]);
sanitize_blacklists[i] = NULL;
generating_coverage = false;
generating_stackusage = false;
profile_arcs = false;
- free(profile_dir); profile_dir = NULL;
i_tmpfile = NULL;
direct_i_file = false;
free(cpp_stderr); cpp_stderr = NULL;
void warn(const char *format, ...) ATTR_FORMAT(printf, 1, 2);
void copy_fd(int fd_in, int fd_out);
-int copy_file(const char *src, const char *dest, int compress_level);
+int copy_file(const char *src, const char *dest, int compress_level,
+ bool via_tmp_file);
int move_file(const char *src, const char *dest, int compress_level);
int move_uncompressed_file(const char *src, const char *dest,
int compress_level);
-// Copyright (C) 2010-2019 Joel Rosdahl
+// Copyright (C) 2010-2020 Joel Rosdahl
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// run_second_cpp is false.
#define AFFECTS_CPP (1 << 5)
-// The option only affects compilation; not passed to the preprocesor.
+// The option only affects compilation; not passed to the preprocessor.
#define AFFECTS_COMP (1 << 6)
struct compopt {
}
bool
-conf_set_value_in_file(const char *path, const char *key, const char *value,
- char **errmsg)
+conf_set_value_in_file(const char *conf_path, const char *key,
+ const char *value, char **errmsg)
{
const struct conf_item *item = find_conf(key);
if (!item) {
return false;
}
- char dummy[8] = {0}; // The maximum entry size in struct conf.
- if (!item->parser(value, (void *)dummy, errmsg)
- || (item->verifier && !item->verifier(value, errmsg))) {
+ char parsed[8] = {0}; // The maximum entry size in struct conf.
+ if (!item->parser(value, (void *)parsed, errmsg)
+ || (item->verifier && !item->verifier(&parsed, errmsg))) {
return false;
}
+ char *path = x_realpath(conf_path);
+ if (!path) {
+ path = x_strdup(conf_path);
+ }
FILE *infile = fopen(path, "r");
if (!infile) {
*errmsg = format("%s: %s", path, strerror(errno));
+ free(path);
return false;
}
if (!outfile) {
*errmsg = format("%s: %s", outpath, strerror(errno));
free(outpath);
+ free(path);
fclose(infile);
return false;
}
fclose(outfile);
if (x_rename(outpath, path) != 0) {
*errmsg = format("rename %s to %s: %s", outpath, path, strerror(errno));
+ free(outpath);
+ free(path);
return false;
}
free(outpath);
+ free(path);
return true;
}
// 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)
+copy_file(const char *src,
+ const char *dest,
+ int compress_level,
+ bool via_tmp_file)
{
int fd_out;
+ char *tmp_name = NULL;
gzFile gz_in = NULL;
gzFile gz_out = NULL;
int saved_errno = 0;
// Open destination file.
- char *tmp_name = x_strdup(dest);
- fd_out = create_tmp_fd(&tmp_name);
- cc_log("Copying %s to %s via %s (%scompressed)",
- src, dest, tmp_name, compress_level > 0 ? "" : "un");
+ if (via_tmp_file) {
+ tmp_name = x_strdup(dest);
+ fd_out = create_tmp_fd(&tmp_name);
+ cc_log("Copying %s to %s via %s (%scompressed)",
+ src, dest, tmp_name, compress_level > 0 ? "" : "un");
+ } else {
+ fd_out = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (fd_out == -1) {
+ saved_errno = errno;
+ close(fd_out);
+ errno = saved_errno;
+ return -1;
+ }
+ cc_log("Copying %s to %s (%scompressed)",
+ src, dest, compress_level > 0 ? "" : "un");
+ }
// Open source file.
int fd_in = open(src, O_RDONLY | O_BINARY);
gzclose(gz_out);
}
close(fd_out);
- tmp_unlink(tmp_name);
- free(tmp_name);
+ if (via_tmp_file) {
+ tmp_unlink(tmp_name);
+ free(tmp_name);
+ }
return -1;
}
goto error;
}
- if (x_rename(tmp_name, dest) == -1) {
- saved_errno = errno;
- cc_log("rename error: %s", strerror(saved_errno));
- goto error;
- }
+ if (via_tmp_file) {
+ if (x_rename(tmp_name, dest) == -1) {
+ saved_errno = errno;
+ cc_log("rename error: %s", strerror(saved_errno));
+ goto error;
+ }
- free(tmp_name);
+ free(tmp_name);
+ }
return 0;
if (fd_out != -1) {
close(fd_out);
}
- tmp_unlink(tmp_name);
- free(tmp_name);
+ if (via_tmp_file) {
+ tmp_unlink(tmp_name);
+ free(tmp_name);
+ }
errno = saved_errno;
return -1;
}
int
move_file(const char *src, const char *dest, int compress_level)
{
- int ret = copy_file(src, dest, compress_level);
+ int ret = copy_file(src, dest, compress_level, true);
if (ret != -1) {
x_unlink(src);
}
return true;
}
-
-#if !defined(HAVE_REALPATH) && \
- defined(_WIN32) && \
- !defined(HAVE_GETFINALPATHNAMEBYHANDLEW)
-static BOOL GetFileNameFromHandle(HANDLE file_handle, TCHAR *filename,
- WORD cch_filename)
-{
- BOOL success = FALSE;
-
- // Get the file size.
- DWORD file_size_hi = 0;
- DWORD file_size_lo = GetFileSize(file_handle, &file_size_hi);
- if (file_size_lo == 0 && file_size_hi == 0) {
- // Cannot map a file with a length of zero.
- return FALSE;
- }
-
- // Create a file mapping object.
- HANDLE file_map =
- CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 1, NULL);
- if (!file_map) {
- return FALSE;
- }
-
- // Create a file mapping to get the file name.
- void *mem = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 1);
- if (mem) {
- if (GetMappedFileName(GetCurrentProcess(),
- mem,
- filename,
- cch_filename)) {
- // Translate path with device name to drive letters.
- TCHAR temp[512];
- temp[0] = '\0';
-
- if (GetLogicalDriveStrings(512-1, temp)) {
- TCHAR name[MAX_PATH];
- TCHAR drive[3] = TEXT(" :");
- BOOL found = FALSE;
- TCHAR *p = temp;
-
- do {
- // Copy the drive letter to the template string.
- *drive = *p;
-
- // Look up each device name.
- if (QueryDosDevice(drive, name, MAX_PATH)) {
- size_t name_len = _tcslen(name);
- if (name_len < MAX_PATH) {
- found = _tcsnicmp(filename, name, name_len) == 0
- && *(filename + name_len) == _T('\\');
- if (found) {
- // Reconstruct filename using temp_file and replace device path
- // with DOS path.
- TCHAR temp_file[MAX_PATH];
- _sntprintf(temp_file,
- MAX_PATH - 1,
- TEXT("%s%s"),
- drive,
- filename+name_len);
- strcpy(filename, temp_file);
- }
- }
- }
-
- // Go to the next NULL character.
- while (*p++) {
- // Do nothing.
- }
- } while (!found && *p); // End of string.
- }
- }
- success = TRUE;
- UnmapViewOfFile(mem);
- }
-
- CloseHandle(file_map);
- return success;
-}
-#endif
-
// A sane realpath() function, trying to cope with stupid path limits and a
// broken API. Caller frees.
char *
path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != path_handle) {
-#ifdef HAVE_GETFINALPATHNAMEBYHANDLEW
- GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED);
-#else
- GetFileNameFromHandle(path_handle, ret, maxlen);
-#endif
+ bool ok = GetFinalPathNameByHandle(
+ path_handle, ret, maxlen, FILE_NAME_NORMALIZED) != 0;
CloseHandle(path_handle);
+ if (!ok) {
+ free(ret);
+ return x_strdup(path);
+ }
p = ret + 4; // Strip \\?\ from the file name.
} else {
snprintf(ret, maxlen, "%s", path);
-extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7.9";
+extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7.10";
;;
*clang*)
COMPILER_TYPE_CLANG=true
+ CLANG_VERSION_SUFFIX=$(echo $COMPILER | sed -r 's/.*clang//')
;;
*)
echo "WARNING: Compiler $COMPILER not supported (version: $compiler_version) -- not running tests" >&2
serialize_diagnostics
sanitize_blacklist
debug_prefix_map
+profiling
+profiling_gcc
+profiling_clang
split_dwarf
masquerading
hardlink
expect_stat 'cache hit (direct)' 1
mv test1.d.tmp test1.d || test_failed "second mv failed"
+ # -------------------------------------------------------------------------
+ TEST ".d file corrupted by compiler"
+
+ unset CCACHE_NODIRECT
+ export CCACHE_SLOPPINESS=include_file_mtime,include_file_ctime
+ export CCACHE_HARDLINK=1
+
+ echo "int x;" >test1.c
+
+ $CCACHE_COMPILE -c -MMD test1.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+ expect_file_content test1.d "test1.o: test1.c"
+
+ touch test1.h
+ echo '#include "test1.h"' >>test1.c
+
+ $CCACHE_COMPILE -c -MMD test1.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+ expect_file_content test1.d "test1.o: test1.c test1.h"
+
+ echo "int x;" >test1.c
+
+ $CCACHE_COMPILE -c -MMD test1.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+ expect_file_content test1.d "test1.o: test1.c"
}
--- /dev/null
+SUITE_profiling_PROBE() {
+ touch test.c
+ if ! $COMPILER -fprofile-generate -c test.c 2>/dev/null; then
+ echo "compiler does not support profiling"
+ fi
+ if $COMPILER_TYPE_CLANG && ! which llvm-profdata$CLANG_VERSION_SUFFIX >/dev/null 2>/dev/null; then
+ echo "llvm-profdata$CLANG_VERSION_SUFFIX tool not found"
+ fi
+}
+
+SUITE_profiling_SETUP() {
+ echo 'int main(void) { return 0; }' >test.c
+ unset CCACHE_NODIRECT
+}
+
+SUITE_profiling() {
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-use, missing file"
+
+ $CCACHE_COMPILE -fprofile-use -c test.c 2>/dev/null
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 0
+ expect_stat 'no input file' 1
+
+ # -------------------------------------------------------------------------
+ TEST "-fbranch-probabilities, missing file"
+
+ $CCACHE_COMPILE -fbranch-probabilities -c test.c 2>/dev/null
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 0
+ expect_stat 'no input file' 1
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-use=file, missing file"
+
+ $CCACHE_COMPILE -fprofile-use=data.gcda -c test.c 2>/dev/null
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 0
+ expect_stat 'no input file' 1
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-use"
+
+ $CCACHE_COMPILE -fprofile-generate -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-generate test.o -o test
+
+ ./test
+ merge_profiling_data .
+
+ $CCACHE_COMPILE -fprofile-use -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-use -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+ merge_profiling_data .
+
+ $CCACHE_COMPILE -fprofile-use -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-use=dir"
+
+ mkdir data
+
+ $CCACHE_COMPILE -fprofile-generate=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-generate=data test.o -o test
+
+ ./test
+ merge_profiling_data data
+
+ $CCACHE_COMPILE -fprofile-use=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-use=data -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+ merge_profiling_data data
+
+ $CCACHE_COMPILE -fprofile-use=data -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+}
+
+merge_profiling_data() {
+ local dir=$1
+ if $COMPILER_TYPE_CLANG; then
+ llvm-profdata$CLANG_VERSION_SUFFIX merge -output $dir/default.profdata $dir/*.profraw
+ fi
+}
--- /dev/null
+SUITE_profiling_clang_PROBE() {
+ if ! $COMPILER_TYPE_CLANG; then
+ echo "compiler is not Clang"
+ fi
+ if ! which llvm-profdata$CLANG_VERSION_SUFFIX >/dev/null 2>/dev/null; then
+ echo "llvm-profdata$CLANG_VERSION_SUFFIX tool not found"
+ fi
+}
+
+SUITE_profiling_clang_SETUP() {
+ echo 'int main(void) { return 0; }' >test.c
+ unset CCACHE_NODIRECT
+}
+
+SUITE_profiling_clang() {
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-use=file"
+
+ mkdir data
+
+ $CCACHE_COMPILE -fprofile-generate=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-generate=data test.o -o test
+
+ ./test
+ llvm-profdata$CLANG_VERSION_SUFFIX merge -output foo.profdata data/default_*.profraw
+
+ $CCACHE_COMPILE -fprofile-use=foo.profdata -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-use=foo.profdata -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+ llvm-profdata$CLANG_VERSION_SUFFIX merge -output foo.profdata data/default_*.profraw
+
+ $CCACHE_COMPILE -fprofile-use=foo.profdata -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-instr-use"
+
+ mkdir data
+
+ $CCACHE_COMPILE -fprofile-instr-generate -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-instr-generate test.o -o test
+
+ ./test
+ llvm-profdata$CLANG_VERSION_SUFFIX merge -output default.profdata default.profraw
+
+ $CCACHE_COMPILE -fprofile-instr-use -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-instr-use -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ echo >>default.profdata # Dummy change to trigger modification
+
+ $CCACHE_COMPILE -fprofile-instr-use -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-instr-use=file"
+
+ $CCACHE_COMPILE -fprofile-instr-generate=foo.profraw -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-instr-generate=data=foo.profraw test.o -o test
+
+ ./test
+ llvm-profdata$CLANG_VERSION_SUFFIX merge -output foo.profdata foo.profraw
+
+ $CCACHE_COMPILE -fprofile-instr-use=foo.profdata -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-instr-use=foo.profdata -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ echo >>foo.profdata # Dummy change to trigger modification
+
+ $CCACHE_COMPILE -fprofile-instr-use=foo.profdata -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-sample-use"
+
+ echo 'main:1:1' > sample.prof
+
+ $CCACHE_COMPILE -fprofile-sample-use=sample.prof -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $CCACHE_COMPILE -fprofile-sample-use=sample.prof -fprofile-sample-accurate -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-sample-use=sample.prof -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-sample-use=sample.prof -fprofile-sample-accurate -c test.c
+ expect_stat 'cache hit (direct)' 2
+ expect_stat 'cache miss' 2
+
+ echo 'main:2:2' > sample.prof
+
+ $CCACHE_COMPILE -fprofile-sample-use=sample.prof -c test.c
+ expect_stat 'cache hit (direct)' 2
+ expect_stat 'cache miss' 3
+
+ echo 'main:1:1' > sample.prof
+
+ $CCACHE_COMPILE -fprofile-sample-use=sample.prof -c test.c
+ expect_stat 'cache hit (direct)' 3
+ expect_stat 'cache miss' 3
+}
--- /dev/null
+SUITE_profiling_gcc_PROBE() {
+ if ! $COMPILER_TYPE_GCC; then
+ echo "compiler is not GCC"
+ fi
+}
+
+SUITE_profiling_gcc_SETUP() {
+ echo 'int main(void) { return 0; }' >test.c
+ unset CCACHE_NODIRECT
+}
+
+SUITE_profiling_gcc() {
+ # -------------------------------------------------------------------------
+ TEST "-fbranch-probabilities"
+
+ $CCACHE_COMPILE -fprofile-generate -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-generate test.o -o test
+
+ ./test
+
+ $CCACHE_COMPILE -fbranch-probabilities -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fbranch-probabilities -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+
+ $CCACHE_COMPILE -fbranch-probabilities -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-dir=dir + -fprofile-use"
+
+ mkdir data
+
+ $CCACHE_COMPILE -fprofile-dir=data -fprofile-generate -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-dir=data -fprofile-generate test.o -o test
+
+ ./test
+
+ $CCACHE_COMPILE -fprofile-dir=data -fprofile-use -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-dir=data -fprofile-use -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+
+ $CCACHE_COMPILE -fprofile-dir=data -fprofile-use -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-use + -fprofile-dir=dir"
+
+ mkdir data
+
+ $CCACHE_COMPILE -fprofile-generate -fprofile-dir=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-generate -fprofile-dir=data test.o -o test
+
+ ./test
+
+ $CCACHE_COMPILE -fprofile-use -fprofile-dir=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-use -fprofile-dir=data -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+
+ $CCACHE_COMPILE -fprofile-use -fprofile-dir=data -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+
+ # -------------------------------------------------------------------------
+ TEST "-fprofile-dir=path1 + -fprofile-use=path2"
+
+ mkdir data
+
+ $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-generate=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 1
+
+ $COMPILER -fprofile-dir=data2 -fprofile-generate=data test.o -o test
+
+ ./test
+
+ $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-use=data -c test.c
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache miss' 2
+
+ $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-use=data -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 2
+
+ ./test
+
+ $CCACHE_COMPILE -fprofile-dir=data2 -fprofile-use=data -c test.c
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache miss' 3
+}
args_free(orig);
}
-TEST(fprofile_flag_with_existing_dir_should_be_rewritten_to_real_path)
-{
- struct args *orig = args_init_from_string(
- "gcc -c -fprofile-generate=some/dir foo.c");
- struct args *exp_cpp = args_init_from_string("gcc");
- struct args *exp_cc = args_init_from_string("gcc");
- struct args *act_cpp = NULL, *act_cc = NULL;
- char *s, *path;
-
- create_file("foo.c", "");
- mkdir("some", 0777);
- mkdir("some/dir", 0777);
- path = x_realpath("some/dir");
- s = format("-fprofile-generate=%s", path);
- free(path);
- args_add(exp_cpp, s);
- args_add(exp_cc, s);
- args_add(exp_cc, "-c");
- free(s);
-
- CHECK(cc_process_args(orig, &act_cpp, NULL, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
-}
-
-TEST(fprofile_flag_with_nonexistent_dir_should_not_be_rewritten)
-{
- struct args *orig = args_init_from_string(
- "gcc -c -fprofile-generate=some/dir foo.c");
- struct args *exp_cpp = args_init_from_string(
- "gcc -fprofile-generate=some/dir");
- struct args *exp_cc = args_init_from_string(
- "gcc -fprofile-generate=some/dir -c");
- struct args *act_cpp = NULL, *act_cc = NULL;
-
- create_file("foo.c", "");
-
- CHECK(cc_process_args(orig, &act_cpp, NULL, &act_cc));
- CHECK_ARGS_EQ_FREE12(exp_cpp, act_cpp);
- CHECK_ARGS_EQ_FREE12(exp_cc, act_cc);
-
- args_free(orig);
-}
-
TEST(isystem_flag_with_separate_arg_should_be_rewritten_if_basedir_is_used)
{
extern char *current_working_dir;
args_free(orig);
}
-TEST(options_not_to_be_passed_to_the_preprocesor)
+TEST(options_not_to_be_passed_to_the_preprocessor)
{
struct args *orig = args_init_from_string(
"cc -Wa,foo foo.c -g -c -DX -Werror -Xlinker fie -Xlinker,fum -Wno-error");