Imported Upstream version 3.7.10 upstream/3.7.10
authorJinWang An <jinwang.an@samsung.com>
Tue, 3 Aug 2021 07:29:06 +0000 (16:29 +0900)
committerJinWang An <jinwang.an@samsung.com>
Tue, 3 Aug 2021 07:29:06 +0000 (16:29 +0900)
21 files changed:
LICENSE.html
config.h.in
configure
configure.ac
doc/AUTHORS.html
doc/MANUAL.html
doc/NEWS.adoc
doc/NEWS.html
doc/ccache.1
src/ccache.c
src/ccache.h
src/compopt.c
src/conf.c
src/util.c
src/version.c
test/run
test/suites/hardlink.bash
test/suites/profiling.bash [new file with mode: 0644]
test/suites/profiling_clang.bash [new file with mode: 0644]
test/suites/profiling_gcc.bash [new file with mode: 0644]
unittest/test_argument_processing.c

index dad2da6d1cb4fe1a7700ccb456b4dc89e199e698..9cfdae1506449e4087ded7c6eda0f170f7e492bd 100644 (file)
@@ -4,7 +4,7 @@
 <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
@@ -436,7 +436,7 @@ thead, p.table.header {
 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
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <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>
@@ -1235,9 +1235,9 @@ following license:</p></div>
 <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
index 4e8242a727927ef5c287b2143e582f6e3a07992e..9a076011f3b79ab7113edece47bccd43032a853d 100644 (file)
@@ -19,9 +19,6 @@
 /* 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
 
index 92a67ab931d8467452d062e199bcb6303aac0d61..63b22ee0dd3f60dd9194702cd8ae0de7a6222325 100755 (executable)
--- a/configure
+++ b/configure
@@ -6014,19 +6014,6 @@ fi
 
 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
index 01098842e992456aedf1bc0db49021cd7ccf2bb9..8278592c85c6fb1d162f0b7f9f58acd9a0c8d159 100644 (file)
@@ -177,7 +177,6 @@ fi
 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
index de125d0b42531153aa5c23b392056f8b070f5e3f..2d0513a02d768efa7513aa073613868d6b8e5fde 100644 (file)
@@ -4,7 +4,7 @@
 <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
@@ -436,7 +436,7 @@ thead, p.table.header {
 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
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <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>
@@ -1271,9 +1271,9 @@ Yvan Janssens
 <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
index 6dd6f3430beb7cddcaf43e448958c91a4a2aa9ae..91706a12454365b7fe6eb62b8f9df00d96566f30 100644 (file)
@@ -4,7 +4,7 @@
 <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
@@ -436,7 +436,7 @@ thead, p.table.header {
 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
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <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>
@@ -2713,9 +2713,9 @@ maintained by Joel Rosdahl. See AUTHORS.txt or AUTHORS.html and
 <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
index 8274f8868ae4594719c202bc16a8089a7702a822..48772743667f79c1791e03689227a8ce44b9c433 100644 (file)
@@ -1,6 +1,40 @@
 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
index 009f87bb65fe69351f12efd08c6dc4d9d6d231c1..ecf65da297d352040c5e33367e94061eb1bee818 100644 (file)
@@ -4,7 +4,7 @@
 <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
@@ -436,7 +436,7 @@ thead, p.table.header {
 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
@@ -735,7 +735,7 @@ asciidoc.install(2);
 <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>
@@ -743,11 +743,69 @@ asciidoc.install(2);
 </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&#8217;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&#8217;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&#8217;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
@@ -785,7 +843,7 @@ Improved name of temporary file used in NFS-safe unlink.
 <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
@@ -864,7 +922,7 @@ Clarified “include_file_ctime sloppiness” in the Performance section in the
 <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
@@ -912,7 +970,7 @@ The “cache miss” statistics counter will now be updated for read-only cache
 <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
@@ -959,7 +1017,7 @@ Added support for <code>-MF=arg</code> (with an extra equal sign) as understood
 </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
@@ -1029,7 +1087,7 @@ Added support for converting paths like “/c/users” into relative paths on
 <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
@@ -1054,7 +1112,7 @@ Fixed a regression in 3.7.2 when using the compiler option “-Werror” and the
 <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
@@ -1511,7 +1569,7 @@ Made “./configure --without-bundled-zlib” do what’s intended.
 <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
@@ -1548,7 +1606,7 @@ Upgraded bundled zlib to version 1.2.11.
 <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
@@ -1592,7 +1650,7 @@ Made it possible to perform out-of-source builds in dev mode again.
 <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
@@ -1678,7 +1736,7 @@ Documented caveats related to colored warnings from compilers.
 </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
@@ -1716,7 +1774,7 @@ Improved instructions on how to get cache hits between different working
 </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
@@ -1742,7 +1800,7 @@ Documented how automatic cache cleanup works.
 </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
@@ -1825,7 +1883,7 @@ Documented the different cache statistics counters.
 </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
@@ -1855,7 +1913,7 @@ Fixed undefined behavior warnings in ccache found by <code>-fsanitize=undefined<
 <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
@@ -1872,7 +1930,7 @@ ccache now detects usage of <code>.incbin</code> assembler directives in the sou
 <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
@@ -1897,7 +1955,7 @@ Fixed a regression in ccache 3.3.1: ccache could get confused when using the
 <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
@@ -2079,7 +2137,7 @@ Increased buffer size used when reading file data. This improves performance
 </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
@@ -2105,7 +2163,7 @@ Fixed build and test for MinGW32 and Windows.
 <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
@@ -2123,7 +2181,7 @@ Fixed a regression in ccache 3.2.8: ccache could get confused when using the
 <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
@@ -2147,7 +2205,7 @@ ccache now understands the undocumented <code>-coverage</code> (only one dash) G
 <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
@@ -2170,7 +2228,7 @@ ccache now knows how to work around a glitch in the output of GCC 6’s
 <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
@@ -2220,7 +2278,7 @@ Made it harder to misinterpret documentation of boolean environment settings’
 </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
@@ -2280,7 +2338,7 @@ The man page is now built when running “make install” from Git repository
 <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
@@ -2335,7 +2393,7 @@ Added support for compiler option <code>-gsplit-dwarf</code>.
 </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
@@ -2389,7 +2447,7 @@ Add support for caching code coverage results (compiling for gcov).
 </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
@@ -2459,7 +2517,7 @@ Fixed build error when compiling ccache with recent Clang versions.
 <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
@@ -2691,7 +2749,7 @@ Various other improvements of the test suite.
 </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
@@ -2722,7 +2780,7 @@ Fixed test suite failures when <code>CC</code> is a ccache-wrapped compiler.
 <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
@@ -2740,7 +2798,7 @@ Fixed a bug where (due to ccache rewriting paths) the compiler could choose
 <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
@@ -2822,7 +2880,7 @@ Stale files in the internal temporary directory (<code>&lt;ccache_dir&gt;/tmp</c
 </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
@@ -2862,7 +2920,7 @@ Fixed problem with logging of current working directory.
 <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
@@ -2933,7 +2991,7 @@ Clang plugins are now hashed to catch plugin upgrades.
 </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
@@ -2981,7 +3039,7 @@ Fixed <code>static_assert</code> macro definition clash with GCC 4.7.
 <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
@@ -3064,7 +3122,7 @@ Rewrite argument to <code>--sysroot</code> if <code>CCACHE_BASEDIR</code> is use
 </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
@@ -3117,7 +3175,7 @@ Improved order of statistics counters in <code>ccache -s</code> output.
 </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
@@ -3150,7 +3208,7 @@ Systems that lack (and don’t need to be linked with) libm are now supported.
 <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
@@ -3183,7 +3241,7 @@ The file handle in now correctly closed on write error when trying to create
 <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
@@ -3210,7 +3268,7 @@ Portability fixes for HP-UX 11.00 and other esoteric systems.
 <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
@@ -3258,7 +3316,7 @@ The test suite now also works on systems that lack a /dev/zero.
 <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
@@ -3380,7 +3438,7 @@ Added <code>-install_name</code> as an option known to take an argument. (This i
 </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
@@ -3466,7 +3524,7 @@ New <code>HACKING.txt</code> file with some notes about ccache code conventions.
 <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
@@ -3655,7 +3713,7 @@ The following options are no longer hashed in the preprocessor mode:
 </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
@@ -3800,9 +3858,9 @@ Statistics counters are now correctly updated for -E option failures and
 <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
index 92b423047209fae9354c4a9e9500133a3598046d..72cf3d00fc42ff9897c9a1104d76d64263fa1e8c 100644 (file)
@@ -2,12 +2,12 @@
 .\"     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
 .\" -----------------------------------------------------------------
index 0e66468f2facdabc7172dab05cab0bb037dba450..1b80fe0a5fae8e23a7d0cc7d86816679c9f67e53 100644 (file)
@@ -222,9 +222,6 @@ static size_t debug_prefix_maps_len = 0;
 // 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;
 
@@ -249,7 +246,7 @@ bool output_is_precompiled_header = false;
 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;
 
@@ -1214,9 +1211,10 @@ object_hash_from_depfile(const char *depfile, struct hash *hash)
        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);
@@ -1225,7 +1223,7 @@ do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
        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);
@@ -1233,6 +1231,10 @@ do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
                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");
@@ -1240,7 +1242,7 @@ do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
                        }
                }
                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);
@@ -1270,7 +1272,7 @@ do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
                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.
@@ -1279,9 +1281,19 @@ do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy)
 // 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.
@@ -1292,7 +1304,7 @@ copy_file_to_cache(const char *source, const char *dest)
 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.
@@ -1310,7 +1322,7 @@ do_copy_or_link_file_from_cache(const char *source, const char *dest, bool copy)
                x_unlink(dest);
                ret = link(source, dest);
        } else {
-               ret = copy_file(source, dest, 0);
+               ret = copy_file(source, dest, 0, false);
        }
 
        if (ret == -1) {
@@ -1470,8 +1482,11 @@ to_cache(struct args *args, struct hash *depend_mode_hash)
        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);
@@ -1479,8 +1494,11 @@ to_cache(struct args *args, struct hash *depend_mode_hash)
                // 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.
@@ -1615,7 +1633,7 @@ to_cache(struct args *args, struct hash *depend_mode_hash)
                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.
@@ -1627,7 +1645,7 @@ to_cache(struct args *args, struct hash *depend_mode_hash)
 
        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);
        }
@@ -1953,8 +1971,8 @@ calculate_common_hash(struct args *args, struct hash *hash)
        // 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);
@@ -2011,6 +2029,51 @@ calculate_common_hash(struct args *args, struct hash *hash)
        }
 }
 
+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.
@@ -2177,39 +2240,26 @@ calculate_object_hash(struct args *args, struct args *preprocessor_args,
                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.
@@ -2360,7 +2410,7 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest)
        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) {
@@ -2369,13 +2419,13 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest)
                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");
@@ -2530,6 +2580,76 @@ detect_pch(const char *option, const char *arg, bool *found_pch)
        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
@@ -2698,7 +2818,7 @@ cc_process_args(struct args *args,
 
                // -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;
@@ -2948,10 +3068,16 @@ cc_process_args(struct args *args,
                        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(
@@ -3074,60 +3200,6 @@ cc_process_args(struct args *args,
                        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")
@@ -3852,7 +3924,9 @@ cc_reset(void)
        }
        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;
@@ -3895,7 +3969,6 @@ cc_reset(void)
        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;
index 0d6be609a01c4e111aea6b34fad7b268a19e2993..e5524a6dac4cba0d31aa4db921cc485b278a5e67 100644 (file)
@@ -149,7 +149,8 @@ void fatal(const char *format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
 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);
index 9b42fd1b5178d3406acdad09c68218a10e79cb1c..f59def96dd3802fc883d58eefa265459b9b99fc1 100644 (file)
@@ -1,4 +1,4 @@
-// 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
@@ -37,7 +37,7 @@
 // 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 {
index a990c9200ff5ed78a3511e8b167322cb260e3be2..517d84083c5d8a6591b6d6771d709a7362562246 100644 (file)
@@ -296,8 +296,8 @@ conf_update_from_environment(struct conf *conf, char **errmsg)
 }
 
 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) {
@@ -305,15 +305,20 @@ conf_set_value_in_file(const char *path, const char *key, const char *value,
                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;
        }
 
@@ -322,6 +327,7 @@ conf_set_value_in_file(const char *path, const char *key, const char *value,
        if (!outfile) {
                *errmsg = format("%s: %s", outpath, strerror(errno));
                free(outpath);
+               free(path);
                fclose(infile);
                return false;
        }
@@ -351,9 +357,12 @@ conf_set_value_in_file(const char *path, const char *key, const char *value,
        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;
 }
index 0fd3f0fe3b53eb9f9627ca8f3b7879231ca82268..9f014bdc2abe169ed2ada9603045cba129a39701 100644 (file)
@@ -315,18 +315,34 @@ get_umask(void)
 // 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);
@@ -410,8 +426,10 @@ copy_file(const char *src, const char *dest, int compress_level)
                        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;
        }
 
@@ -433,13 +451,15 @@ copy_file(const char *src, const char *dest, int compress_level)
                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;
 
@@ -453,8 +473,10 @@ error:
        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;
 }
@@ -463,7 +485,7 @@ error:
 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);
        }
@@ -1061,87 +1083,6 @@ parse_size_with_suffix(const char *str, uint64_t *size)
        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 *
@@ -1161,12 +1102,13 @@ x_realpath(const char *path)
                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);
index 4860794f98d3e32b9ea51e870db6ee2fc8735c2f..2d81361eb1fd47c7750aa2bed8fa5956474ccc46 100644 (file)
@@ -1 +1 @@
-extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7.9";
+extern const char CCACHE_VERSION[]; const char CCACHE_VERSION[] = "3.7.10";
index d506c4657ee46219cc88c2a9dde9f99803cef32d..6b1ec7edc187a6438d70cb7aaeb872c4ad8428fd 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -322,6 +322,7 @@ case $compiler_version in
         ;;
     *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
@@ -394,6 +395,9 @@ multi_arch
 serialize_diagnostics
 sanitize_blacklist
 debug_prefix_map
+profiling
+profiling_gcc
+profiling_clang
 split_dwarf
 masquerading
 hardlink
index 388bd1f9db251206c0a733a26d28b30ff4ded55d..b80b35bd021006813a8d816c35fd70fce605c80f 100644 (file)
@@ -76,4 +76,32 @@ SUITE_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"
 }
diff --git a/test/suites/profiling.bash b/test/suites/profiling.bash
new file mode 100644 (file)
index 0000000..553f908
--- /dev/null
@@ -0,0 +1,103 @@
+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
+}
diff --git a/test/suites/profiling_clang.bash b/test/suites/profiling_clang.bash
new file mode 100644 (file)
index 0000000..c6bb7ef
--- /dev/null
@@ -0,0 +1,131 @@
+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
+}
diff --git a/test/suites/profiling_gcc.bash b/test/suites/profiling_gcc.bash
new file mode 100644 (file)
index 0000000..fe61109
--- /dev/null
@@ -0,0 +1,118 @@
+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
+}
index c0504bee1d8949c8b1f246570af00bc62d040aec..38b7664297fad8997702e5339a31fd3b2ee6eac5 100644 (file)
@@ -354,52 +354,6 @@ TEST(MT_flag_with_immediate_argument_should_not_add_MQobj)
        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;
@@ -509,7 +463,7 @@ TEST(debug_flag_order_with_known_option_last)
        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");