From 09b30515247b95358fa9126ce76e35f2d177c241 Mon Sep 17 00:00:00 2001 From: Matthew Woehlke Date: Wed, 28 Sep 2022 13:41:11 -0400 Subject: try_compile: Add NO_CACHE option (also try_run) Add NO_CACHE option to try_compile and try_run, which places the results in regular, rather than cache, variables. Issue: #22799 --- Help/command/try_compile.rst | 27 ++++++++++- Help/command/try_run.rst | 2 + Help/release/dev/try_compile-no_cache.rst | 5 +++ Source/cmCoreTryCompile.cxx | 12 +++-- Source/cmCoreTryCompile.h | 1 + Source/cmTryRunCommand.cxx | 12 +++-- Tests/TryCompile/old_and_new_signature_tests.cmake | 52 ++++++++++++++++++++++ 7 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/try_compile-no_cache.rst diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index 4632cd9..6cb4f99 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -18,6 +18,7 @@ Try Compiling Whole Projects SOURCE_DIR [BINARY_DIR ] [TARGET ] + [NO_CACHE] [CMAKE_FLAGS ...] [OUTPUT_VARIABLE ]) @@ -45,7 +46,9 @@ which was present in older versions of CMake: .. code-block:: cmake try_compile( - [] [CMAKE_FLAGS ...] + [] + [NO_CACHE] + [CMAKE_FLAGS ...] [OUTPUT_VARIABLE ]) .. _`Try Compiling Source Files`: @@ -60,6 +63,7 @@ Try Compiling Source Files SOURCE_FROM_ARG ] | SOURCE_FROM_VAR ] | SOURCE_FROM_FILE >... + [NO_CACHE] [CMAKE_FLAGS ...] [COMPILE_DEFINITIONS ...] [LINK_OPTIONS ...] @@ -111,6 +115,7 @@ which was present in older versions of CMake: .. code-block:: cmake try_compile( + [NO_CACHE] [CMAKE_FLAGS ...] [COMPILE_DEFINITIONS ...] [LINK_OPTIONS ...] @@ -166,6 +171,26 @@ The options are: set the :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property in the generated project, depending on the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable. +``NO_CACHE`` + .. versionadded:: 3.25 + + The result will be stored in a normal variable rather than a cache entry. + + The result variable is normally cached so that a simple pattern can be used + to avoid repeating the test on subsequent executions of CMake: + + .. code-block:: cmake + + if(NOT DEFINED RESULTVAR) + # ...(check-specific setup code)... + try_compile(RESULTVAR ...) + # ...(check-specific logging and cleanup code)... + endif() + + If the guard variable and result variable are not the same (for example, if + the test is part of a larger inspection), ``NO_CACHE`` may be useful to avoid + leaking the intermediate result variable into the cache. + ``OUTPUT_VARIABLE `` Store the output from the build process in the given variable. diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst index efc10ec..8393e1b 100644 --- a/Help/command/try_run.rst +++ b/Help/command/try_run.rst @@ -17,6 +17,7 @@ Try Compiling and Running Source Files SOURCE_FROM_ARG ] | SOURCE_FROM_VAR ] | SOURCE_FROM_FILE >... + [NO_CACHE] [CMAKE_FLAGS ...] [COMPILE_DEFINITIONS ...] [LINK_OPTIONS ...] @@ -54,6 +55,7 @@ which was present in older versions of CMake: try_run( + [NO_CACHE] [CMAKE_FLAGS ...] [COMPILE_DEFINITIONS ...] [LINK_OPTIONS ...] diff --git a/Help/release/dev/try_compile-no_cache.rst b/Help/release/dev/try_compile-no_cache.rst new file mode 100644 index 0000000..ebabcd5 --- /dev/null +++ b/Help/release/dev/try_compile-no_cache.rst @@ -0,0 +1,5 @@ +try_compile-no_cache +-------------------- + +* The :command:`try_compile` and :command:`try_run` commands gained the option + ``NO_CACHE`` to store results in normal variables. diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index f40b3e9..323790e 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -149,6 +149,7 @@ cmArgumentParser makeTryRunParser( auto const TryCompileBaseArgParser = cmArgumentParser{} .Bind(0, &Arguments::CompileResultVariable) + .Bind("NO_CACHE"_s, &Arguments::NoCache) .Bind("CMAKE_FLAGS"_s, &Arguments::CMakeFlags) .Bind("__CMAKE_INTERNAL"_s, &Arguments::CMakeInternal) /* keep semicolon on own line */; @@ -1061,9 +1062,14 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments, } // set the result var to the return value to indicate success or failure - this->Makefile->AddCacheDefinition( - *arguments.CompileResultVariable, (res == 0 ? "TRUE" : "FALSE"), - "Result of TRY_COMPILE", cmStateEnums::INTERNAL); + if (arguments.NoCache) { + this->Makefile->AddDefinition(*arguments.CompileResultVariable, + (res == 0 ? "TRUE" : "FALSE")); + } else { + this->Makefile->AddCacheDefinition( + *arguments.CompileResultVariable, (res == 0 ? "TRUE" : "FALSE"), + "Result of TRY_COMPILE", cmStateEnums::INTERNAL); + } if (arguments.OutputVariable) { this->Makefile->AddDefinition(*arguments.OutputVariable, output); diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index 3f4a4dc..d4c9466 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -58,6 +58,7 @@ public: cm::optional OutputVariable; cm::optional CopyFileTo; cm::optional CopyFileError; + bool NoCache = false; // Argument for try_run only. // Keep in sync with warnings in cmCoreTryCompile::ParseArgs. diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 70c7cf1..1e81195 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -46,6 +46,7 @@ public: std::string* runOutputStdOutContents, std::string* runOutputStdErrContents); + bool NoCache; std::string RunResultVariable; }; @@ -57,6 +58,7 @@ bool TryRunCommandImpl::TryRunCode(std::vector const& argv) if (!arguments) { return true; } + this->NoCache = arguments.NoCache; // although they could be used together, don't allow it, because // using OUTPUT_VARIABLE makes crosscompiling harder @@ -222,9 +224,13 @@ void TryRunCommandImpl::RunExecutable(const std::string& runArgs, } else { retStr = "FAILED_TO_RUN"; } - this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr, - "Result of try_run()", - cmStateEnums::INTERNAL); + if (this->NoCache) { + this->Makefile->AddDefinition(this->RunResultVariable, retStr); + } else { + this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr, + "Result of try_run()", + cmStateEnums::INTERNAL); + } } /* This is only used when cross compiling. Instead of running the diff --git a/Tests/TryCompile/old_and_new_signature_tests.cmake b/Tests/TryCompile/old_and_new_signature_tests.cmake index 997a5a3..ab548f7 100644 --- a/Tests/TryCompile/old_and_new_signature_tests.cmake +++ b/Tests/TryCompile/old_and_new_signature_tests.cmake @@ -140,6 +140,28 @@ if(APPLE) EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}") endif() +# check that try_compile honors NO_CACHE +function(try_compile_scope_test) + try_compile( + CACHED_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c) + try_compile( + SHOULD_NOT_ESCAPE_SCOPE_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c + NO_CACHE) +endfunction() + +try_compile_scope_test() + +if(NOT DEFINED CACHE{CACHED_RESULT}) + message(SEND_ERROR " Result from try_compile was not cached") +endif() +if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_RESULT) + message(SEND_ERROR " Result from try_compile(NO_CACHE) leaked") +endif() + ###################################### # now test try_run() @@ -222,3 +244,33 @@ endif() if(NOT "${RUN_OUTPUT_STDERR}" MATCHES "error") message(SEND_ERROR " RUN_OUTPUT_STDERR didn't contain \"error\": \"${RUN_OUTPUT_STDERR}\"") endif() + +# check that try_run honors NO_CACHE +function(try_run_scope_test) + try_run( + CACHED_RUN_RESULT + CACHED_COMPILE_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/exit_success.c) + try_run( + SHOULD_NOT_ESCAPE_SCOPE_RUN_RESULT + SHOULD_NOT_ESCAPE_SCOPE_COMPILE_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/exit_success.c + NO_CACHE) +endfunction() + +try_run_scope_test() + +if(NOT DEFINED CACHE{CACHED_COMPILE_RESULT}) + message(SEND_ERROR " Compile result from try_run was not cached") +endif() +if(NOT DEFINED CACHE{CACHED_RUN_RESULT}) + message(SEND_ERROR " Run result from try_run was not cached") +endif() +if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_COMPILE_RESULT) + message(SEND_ERROR " Compile result from try_run(NO_CACHE) leaked") +endif() +if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_RUN_RESULT) + message(SEND_ERROR " Run result from try_run(NO_CACHE) leaked") +endif() -- cgit v0.12