From: Kristian Sloth Lauszus Date: Mon, 9 Mar 2026 20:06:57 +0000 (+0100) Subject: fix: Do not look for .su and .ci output files when LTO is used (#1693) X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f848832214dc65c38d8f50f93bd7300308e80ecb;p=thirdparty%2Fccache.git fix: Do not look for .su and .ci output files when LTO is used (#1693) 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 --- diff --git a/src/ccache/argprocessing.cpp b/src/ccache/argprocessing.cpp index 410974f6..6711e29c 100644 --- a/src/ccache/argprocessing.cpp +++ b/src/ccache/argprocessing.cpp @@ -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; diff --git a/src/ccache/argsinfo.hpp b/src/ccache/argsinfo.hpp index bf216f61..d17051d1 100644 --- a/src/ccache/argsinfo.hpp +++ b/src/ccache/argsinfo.hpp @@ -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; diff --git a/src/ccache/ccache.cpp b/src/ccache/ccache.cpp index 2cf4a3cf..f7069236 100644 --- a/src/ccache/ccache.cpp +++ b/src/ccache/ccache.cpp @@ -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); diff --git a/test/suites/direct.bash b/test/suites/direct.bash index 9333bf91..c1d69d45 100644 --- a/test/suites/direct.bash +++ b/test/suites/direct.bash @@ -616,6 +616,104 @@ EOF expect_exists code.su fi + # ------------------------------------------------------------------------- + TEST "-fstack-usage with -flto" + + cat <main.c +extern int test(); +int main() { return test(); } +EOF + + cat <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 <main.c +extern int test(); +int main() { return test(); } +EOF + + cat <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 <main.c +extern int test(); +int main() { return test(); } +EOF + + cat <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 <main.c +extern int test(); +int main() { return test(); } +EOF + + cat <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"