]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Do not look for .su and .ci output files when LTO is used (#1693)
authorKristian Sloth Lauszus <lauszus@gmail.com>
Mon, 9 Mar 2026 20:06:57 +0000 (21:06 +0100)
committerGitHub <noreply@github.com>
Mon, 9 Mar 2026 20:06:57 +0000 (21:06 +0100)
When `-flto` is used the .su and .ci output files are not generated during compilation, instead they are generated during link time

This means that ccache can simply skip those files when `-fstack-usage` and `-fcallgraph-info` are used in combination with the `-flto` flag

See: https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html#index-fcallgraph-info

src/ccache/argprocessing.cpp
src/ccache/argsinfo.hpp
src/ccache/ccache.cpp
test/suites/direct.bash

index 410974f68a02dbd54fdf9d9d01ba83fce0544800..6711e29c2a26f3ba0dcede5f53c4b68576b3218a 100644 (file)
@@ -951,6 +951,12 @@ process_option_arg(const Context& ctx,
     return Statistic::none;
   }
 
+  if (arg == "-flto" || arg.starts_with("-flto=")) {
+    args_info.using_lto = true;
+    state.add_common_arg(args[i]);
+    return Statistic::none;
+  }
+
   // -Zs is MSVC's -fsyntax-only equivalent
   if (arg == "-fsyntax-only" || arg == "-Zs") {
     args_info.expect_output_obj = false;
index bf216f61239f2d4f2b8d48b5fe84dfbb23d80a4a..d17051d1f723b6e3d4b3cd7e32c61b7b329f25ef 100644 (file)
@@ -109,6 +109,9 @@ struct ArgsInfo
   // -fcallgraph-info specified.
   bool generating_callgraphinfo = false;
 
+  // -flto specified.
+  bool using_lto = false;
+
   // Are we generating a pch file (msvc -Yc)?
   bool generating_pch = false;
 
index 2cf4a3cf8159aad47d06b67d3aae15545fcbe56b..f7069236f4718e6fd595a1493e1974db91923515 100644 (file)
@@ -1020,18 +1020,23 @@ write_result(Context& ctx,
       return false;
     }
   }
-  if (ctx.args_info.generating_stackusage
-      && !serializer.add_file(core::result::FileType::stackusage,
-                              ctx.args_info.output_su)) {
-    LOG("Stack usage file {} missing", ctx.args_info.output_su);
-    return false;
-  }
-  if (ctx.args_info.generating_callgraphinfo
-      && !serializer.add_file(core::result::FileType::callgraph_info,
-                              ctx.args_info.output_ci)) {
-    LOG("Callgraph info file {} missing", ctx.args_info.output_ci);
-    return false;
+
+  // If LTO is used, then the .su and .ci files are produced during linking.
+  if (!ctx.args_info.using_lto) {
+    if (ctx.args_info.generating_stackusage
+        && !serializer.add_file(core::result::FileType::stackusage,
+                                ctx.args_info.output_su)) {
+      LOG("Stack usage file {} missing", ctx.args_info.output_su);
+      return false;
+    }
+    if (ctx.args_info.generating_callgraphinfo
+        && !serializer.add_file(core::result::FileType::callgraph_info,
+                                ctx.args_info.output_ci)) {
+      LOG("Callgraph info file {} missing", ctx.args_info.output_ci);
+      return false;
+    }
   }
+
   if (ctx.args_info.generating_ipa_clones
       && !serializer.add_file(core::result::FileType::ipa_clones,
                               ctx.args_info.output_ipa)) {
@@ -2954,11 +2959,13 @@ do_cache_compilation(Context& ctx)
   if (ctx.args_info.generating_coverage) {
     LOG("Coverage file is being generated");
   }
-  if (ctx.args_info.generating_stackusage) {
-    LOG("Stack usage file: {}", ctx.args_info.output_su);
-  }
-  if (ctx.args_info.generating_callgraphinfo) {
-    LOG("Callgraph info file: {}", ctx.args_info.output_ci);
+  if (!ctx.args_info.using_lto) {
+    if (ctx.args_info.generating_stackusage) {
+      LOG("Stack usage file: {}", ctx.args_info.output_su);
+    }
+    if (ctx.args_info.generating_callgraphinfo) {
+      LOG("Callgraph info file: {}", ctx.args_info.output_ci);
+    }
   }
   if (!ctx.args_info.output_dia.empty()) {
     LOG("Diagnostics file: {}", ctx.args_info.output_dia);
index 9333bf91323d7ccced0647c154a5d67273be327e..c1d69d458a41473fdf1dc0967085a916f7f37bb7 100644 (file)
@@ -616,6 +616,104 @@ EOF
         expect_exists code.su
     fi
 
+    # -------------------------------------------------------------------------
+    TEST "-fstack-usage with -flto"
+
+    cat <<EOF >main.c
+extern int test();
+int main() { return test(); }
+EOF
+
+    cat <<EOF >code.c
+int test() { return 0; }
+EOF
+
+    if $COMPILER -c -fstack-usage -flto main.c >/dev/null 2>&1; then
+        $CCACHE_COMPILE -c -fstack-usage -flto main.c
+        $CCACHE_COMPILE -c -fstack-usage -flto code.c
+        $CCACHE_COMPILE -o output -fstack-usage -flto main.o code.o
+        expect_stat called_for_link 1
+        expect_stat direct_cache_hit 0
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.su
+        expect_missing code.su
+
+        # clang does not produce .su files
+        if [[ "$(basename "$COMPILER")" != clang* ]]; then
+            expect_exists output.ltrans0.ltrans.su
+            expect_contains output.ltrans0.ltrans.su main.c
+            expect_contains output.ltrans0.ltrans.su code.c
+            rm output.ltrans0.ltrans.su
+        fi
+
+        $CCACHE_COMPILE -c -fstack-usage -flto main.c
+        $CCACHE_COMPILE -c -fstack-usage -flto code.c
+        $CCACHE_COMPILE -o output -fstack-usage -flto main.o code.o
+        expect_stat called_for_link 2
+        expect_stat direct_cache_hit 2
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.su
+        expect_missing code.su
+
+        # clang does not produce .su files
+        if [[ "$(basename "$COMPILER")" != clang* ]]; then
+            expect_exists output.ltrans0.ltrans.su
+            expect_contains output.ltrans0.ltrans.su main.c
+            expect_contains output.ltrans0.ltrans.su code.c
+        fi
+    fi
+
+    # -------------------------------------------------------------------------
+    TEST "-fstack-usage with -flto=auto"
+
+    cat <<EOF >main.c
+extern int test();
+int main() { return test(); }
+EOF
+
+    cat <<EOF >code.c
+int test() { return 0; }
+EOF
+
+    if $COMPILER -c -fstack-usage -flto=auto main.c >/dev/null 2>&1; then
+        $CCACHE_COMPILE -c -fstack-usage -flto=auto main.c
+        $CCACHE_COMPILE -c -fstack-usage -flto=auto code.c
+        $CCACHE_COMPILE -o output -fstack-usage -flto=auto main.o code.o
+        expect_stat called_for_link 1
+        expect_stat direct_cache_hit 0
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.su
+        expect_missing code.su
+
+        # clang does not produce .su files
+        if [[ "$(basename "$COMPILER")" != clang* ]]; then
+            expect_exists output.ltrans0.ltrans.su
+            expect_contains output.ltrans0.ltrans.su main.c
+            expect_contains output.ltrans0.ltrans.su code.c
+            rm output.ltrans0.ltrans.su
+        fi
+
+        $CCACHE_COMPILE -c -fstack-usage -flto=auto main.c
+        $CCACHE_COMPILE -c -fstack-usage -flto=auto code.c
+        $CCACHE_COMPILE -o output -fstack-usage -flto=auto main.o code.o
+        expect_stat called_for_link 2
+        expect_stat direct_cache_hit 2
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.su
+        expect_missing code.su
+
+        # clang does not produce .su files
+        if [[ "$(basename "$COMPILER")" != clang* ]]; then
+            expect_exists output.ltrans0.ltrans.su
+            expect_contains output.ltrans0.ltrans.su main.c
+            expect_contains output.ltrans0.ltrans.su code.c
+        fi
+    fi
+
     # -------------------------------------------------------------------------
     TEST "-fcallgraph-info"
 
@@ -662,6 +760,90 @@ EOF
         expect_exists code.ci
     fi
 
+    # -------------------------------------------------------------------------
+    TEST "-fcallgraph-info with -flto"
+
+    cat <<EOF >main.c
+extern int test();
+int main() { return test(); }
+EOF
+
+    cat <<EOF >code.c
+int test() { return 0; }
+EOF
+
+    if $COMPILER -c -fcallgraph-info -flto main.c >/dev/null 2>&1; then
+        $CCACHE_COMPILE -c -fcallgraph-info -flto main.c
+        $CCACHE_COMPILE -c -fcallgraph-info -flto code.c
+        $CCACHE_COMPILE -o output -fcallgraph-info -flto main.o code.o
+        expect_stat called_for_link 1
+        expect_stat direct_cache_hit 0
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.ci
+        expect_missing code.ci
+        expect_exists output.ltrans0.ltrans.ci
+        expect_contains output.ltrans0.ltrans.ci main.c
+        expect_contains output.ltrans0.ltrans.ci code.c
+
+        rm output.ltrans0.ltrans.ci
+
+        $CCACHE_COMPILE -c -fcallgraph-info -flto main.c
+        $CCACHE_COMPILE -c -fcallgraph-info -flto code.c
+        $CCACHE_COMPILE -o output -fcallgraph-info -flto main.o code.o
+        expect_stat called_for_link 2
+        expect_stat direct_cache_hit 2
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.ci
+        expect_missing code.ci
+        expect_exists output.ltrans0.ltrans.ci
+        expect_contains output.ltrans0.ltrans.ci main.c
+        expect_contains output.ltrans0.ltrans.ci code.c
+    fi
+
+    # -------------------------------------------------------------------------
+    TEST "-fcallgraph-info with -flto=auto"
+
+    cat <<EOF >main.c
+extern int test();
+int main() { return test(); }
+EOF
+
+    cat <<EOF >code.c
+int test() { return 0; }
+EOF
+
+    if $COMPILER -c -fcallgraph-info -flto=auto main.c >/dev/null 2>&1; then
+        $CCACHE_COMPILE -c -fcallgraph-info -flto=auto main.c
+        $CCACHE_COMPILE -c -fcallgraph-info -flto=auto code.c
+        $CCACHE_COMPILE -o output -fcallgraph-info -flto=auto main.o code.o
+        expect_stat called_for_link 1
+        expect_stat direct_cache_hit 0
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.ci
+        expect_missing code.ci
+        expect_exists output.ltrans0.ltrans.ci
+        expect_contains output.ltrans0.ltrans.ci main.c
+        expect_contains output.ltrans0.ltrans.ci code.c
+
+        rm output.ltrans0.ltrans.ci
+
+        $CCACHE_COMPILE -c -fcallgraph-info -flto=auto main.c
+        $CCACHE_COMPILE -c -fcallgraph-info -flto=auto code.c
+        $CCACHE_COMPILE -o output -fcallgraph-info -flto=auto main.o code.o
+        expect_stat called_for_link 2
+        expect_stat direct_cache_hit 2
+        expect_stat preprocessed_cache_hit 0
+        expect_stat cache_miss 2
+        expect_missing main.ci
+        expect_missing code.ci
+        expect_exists output.ltrans0.ltrans.ci
+        expect_contains output.ltrans0.ltrans.ci main.c
+        expect_contains output.ltrans0.ltrans.ci code.c
+    fi
+
     # -------------------------------------------------------------------------
     TEST "Direct mode on cache created by ccache without direct mode support"