From 0c141b0393de6fccbef5ab54e93c70720345ed92 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 31 Aug 2022 10:14:29 -0400 Subject: try_compile: Record output location instead of reverse computing it Fixes #23887, #23942, #20163, #18288 --- Source/cmCoreTryCompile.cxx | 85 +++++++++------------- Source/cmCoreTryCompile.h | 3 +- .../RunCMake/Configure/CopyFileABI-override.cmake | 7 ++ Tests/RunCMake/Configure/CopyFileABI-stdout.txt | 4 + Tests/RunCMake/Configure/CopyFileABI.cmake | 2 + .../RunCMake/Configure/FailCopyFileABI-check.cmake | 14 ---- .../Configure/FailCopyFileABI-override.cmake | 6 -- .../RunCMake/Configure/FailCopyFileABI-stdout.txt | 4 - Tests/RunCMake/Configure/FailCopyFileABI.cmake | 2 - Tests/RunCMake/Configure/RunCMakeTest.cmake | 2 +- Tests/RunCMake/try_compile/BuildType.cmake | 6 ++ Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake | 7 ++ Tests/RunCMake/try_compile/OutputDirAsFlag.cmake | 7 ++ .../try_compile/old_and_new_signature_tests.cmake | 3 + 14 files changed, 74 insertions(+), 78 deletions(-) create mode 100644 Tests/RunCMake/Configure/CopyFileABI-override.cmake create mode 100644 Tests/RunCMake/Configure/CopyFileABI-stdout.txt create mode 100644 Tests/RunCMake/Configure/CopyFileABI.cmake delete mode 100644 Tests/RunCMake/Configure/FailCopyFileABI-check.cmake delete mode 100644 Tests/RunCMake/Configure/FailCopyFileABI-override.cmake delete mode 100644 Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt delete mode 100644 Tests/RunCMake/Configure/FailCopyFileABI.cmake create mode 100644 Tests/RunCMake/try_compile/BuildType.cmake create mode 100644 Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake create mode 100644 Tests/RunCMake/try_compile/OutputDirAsFlag.cmake diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 0a6c359..654c9a3 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -13,6 +13,7 @@ #include #include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" #include "cmArgumentParser.h" #include "cmExportTryCompileFileGenerator.h" @@ -694,6 +695,17 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments, } fprintf(fout, ")\n"); + /* Write out the output location of the target we are building */ + std::string perConfigGenex; + if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) { + perConfigGenex = "_$>"; + } + fprintf(fout, + "file(GENERATE OUTPUT " + "\"${CMAKE_BINARY_DIR}/%s%s_loc\"\n", + targetName.c_str(), perConfigGenex.c_str()); + fprintf(fout, " CONTENT $)\n", targetName.c_str()); + bool warnCMP0067 = false; bool honorStandard = true; @@ -935,7 +947,7 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments, if (this->SrcFileSignature) { std::string copyFileErrorMessage; - this->FindOutputFile(targetName, targetType); + this->FindOutputFile(targetName); if ((res == 0) && arguments.CopyFileTo) { std::string const& copyFile = *arguments.CopyFileTo; @@ -1035,62 +1047,37 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir) } } -void cmCoreTryCompile::FindOutputFile(const std::string& targetName, - cmStateEnums::TargetType targetType) +void cmCoreTryCompile::FindOutputFile(const std::string& targetName) { this->FindErrorMessage.clear(); this->OutputFile.clear(); std::string tmpOutputFile = "/"; - if (targetType == cmStateEnums::EXECUTABLE) { - tmpOutputFile += targetName; - tmpOutputFile += - this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX"); - } else // if (targetType == cmStateEnums::STATIC_LIBRARY) - { - tmpOutputFile += - this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX"); - tmpOutputFile += targetName; - tmpOutputFile += - this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"); - } + tmpOutputFile += targetName; - // a list of directories where to search for the compilation result - // at first directly in the binary dir - std::vector searchDirs; - searchDirs.emplace_back(); - - cmValue config = - this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); - // if a config was specified try that first - if (cmNonempty(config)) { - std::string tmp = cmStrCat('/', *config); - searchDirs.emplace_back(std::move(tmp)); + if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) { + tmpOutputFile += "_DEBUG"; } - searchDirs.emplace_back("/Debug"); - - // handle app-bundles (for targeting apple-platforms) - std::string app = "/" + targetName + ".app"; - if (cmNonempty(config)) { - std::string tmp = cmStrCat('/', *config, app); - searchDirs.emplace_back(std::move(tmp)); + tmpOutputFile += "_loc"; + + std::string command = cmStrCat(this->BinaryDirectory, tmpOutputFile); + if (!cmSystemTools::FileExists(command)) { + std::ostringstream emsg; + emsg << "Unable to find the recorded try_compile output location:\n"; + emsg << cmStrCat(" ", command, "\n"); + this->FindErrorMessage = emsg.str(); + return; } - std::string tmp = "/Debug" + app; - searchDirs.emplace_back(std::move(tmp)); - searchDirs.emplace_back(std::move(app)); - - searchDirs.emplace_back("/Development"); - for (std::string const& sdir : searchDirs) { - std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile); - if (cmSystemTools::FileExists(command)) { - this->OutputFile = cmSystemTools::CollapseFullPath(command); - return; - } + std::string outputFileLocation; + cmsys::ifstream ifs(command.c_str()); + cmSystemTools::GetLineFromStream(ifs, outputFileLocation); + if (!cmSystemTools::FileExists(outputFileLocation)) { + std::ostringstream emsg; + emsg << "Recorded try_compile output location doesn't exist:\n"; + emsg << cmStrCat(" ", outputFileLocation, "\n"); + this->FindErrorMessage = emsg.str(); + return; } - std::ostringstream emsg; - emsg << "Unable to find the executable at any of:\n"; - emsg << cmWrap(" " + this->BinaryDirectory, searchDirs, tmpOutputFile, "\n") - << "\n"; - this->FindErrorMessage = emsg.str(); + this->OutputFile = cmSystemTools::CollapseFullPath(outputFileLocation); } diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index b483f0f..729aa9f 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -94,8 +94,7 @@ public: TryCompileCode. The result is stored in OutputFile. If nothing is found, the error message is stored in FindErrorMessage. */ - void FindOutputFile(const std::string& targetName, - cmStateEnums::TargetType targetType); + void FindOutputFile(const std::string& targetName); std::string BinaryDirectory; std::string OutputFile; diff --git a/Tests/RunCMake/Configure/CopyFileABI-override.cmake b/Tests/RunCMake/Configure/CopyFileABI-override.cmake new file mode 100644 index 0000000..67f6ed5 --- /dev/null +++ b/Tests/RunCMake/Configure/CopyFileABI-override.cmake @@ -0,0 +1,7 @@ +# Change the executable suffix that try_compile will use for +# COPY_FILE but not inside the test project, to verify +# we can handle envs that try and break everything +get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE) +if(NOT in_try_compile) + set(CMAKE_EXECUTABLE_SUFFIX .missing) +endif() diff --git a/Tests/RunCMake/Configure/CopyFileABI-stdout.txt b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt new file mode 100644 index 0000000..6a856a4 --- /dev/null +++ b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt @@ -0,0 +1,4 @@ +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done.* +-- Configuring done +-- Generating done diff --git a/Tests/RunCMake/Configure/CopyFileABI.cmake b/Tests/RunCMake/Configure/CopyFileABI.cmake new file mode 100644 index 0000000..4eee100 --- /dev/null +++ b/Tests/RunCMake/Configure/CopyFileABI.cmake @@ -0,0 +1,2 @@ +set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/CopyFileABI-override.cmake) +enable_language(C) diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake b/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake deleted file mode 100644 index db0cb0a..0000000 --- a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake +++ /dev/null @@ -1,14 +0,0 @@ -set(log "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/CMakeError.log") -if(EXISTS "${log}") - file(READ "${log}" error_log) -else() - set(error_log "") -endif() -string(REPLACE "\r\n" "\n" regex "Cannot copy output executable.* -to destination specified by COPY_FILE:.* -Unable to find the executable at any of: - .*\\.missing") -if(NOT error_log MATCHES "${regex}") - string(REGEX REPLACE "\n" "\n " error_log " ${error_log}") - set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected COPY_FILE failure message:\n${error_log}") -endif() diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake b/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake deleted file mode 100644 index c633555..0000000 --- a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake +++ /dev/null @@ -1,6 +0,0 @@ -# Change the executable suffix that try_compile will use for -# COPY_FILE but not inside the test project. This forces failure. -get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE) -if(NOT in_try_compile) - set(CMAKE_EXECUTABLE_SUFFIX .missing) -endif() diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt b/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt deleted file mode 100644 index 92fe233..0000000 --- a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt +++ /dev/null @@ -1,4 +0,0 @@ --- Detecting C compiler ABI info --- Detecting C compiler ABI info - failed.* --- Configuring done --- Generating done diff --git a/Tests/RunCMake/Configure/FailCopyFileABI.cmake b/Tests/RunCMake/Configure/FailCopyFileABI.cmake deleted file mode 100644 index 74efd97..0000000 --- a/Tests/RunCMake/Configure/FailCopyFileABI.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/FailCopyFileABI-override.cmake) -enable_language(C) diff --git a/Tests/RunCMake/Configure/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake index 9fd4499..750fa3c 100644 --- a/Tests/RunCMake/Configure/RunCMakeTest.cmake +++ b/Tests/RunCMake/Configure/RunCMakeTest.cmake @@ -1,9 +1,9 @@ include(RunCMake) run_cmake(ContinueAfterError) +run_cmake(CopyFileABI) run_cmake(CustomTargetAfterError) run_cmake(ErrorLogs) -run_cmake(FailCopyFileABI) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RerunCMake-build) diff --git a/Tests/RunCMake/try_compile/BuildType.cmake b/Tests/RunCMake/try_compile/BuildType.cmake new file mode 100644 index 0000000..f2709f8 --- /dev/null +++ b/Tests/RunCMake/try_compile/BuildType.cmake @@ -0,0 +1,6 @@ +enable_language(C) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + ) diff --git a/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake b/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake new file mode 100644 index 0000000..e9384c7 --- /dev/null +++ b/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake @@ -0,0 +1,7 @@ +enable_language(C) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + CMAKE_FLAGS "-DCMAKE_BUILD_TYPE=Release" + ) diff --git a/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake b/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake new file mode 100644 index 0000000..5c4dca5 --- /dev/null +++ b/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake @@ -0,0 +1,7 @@ +enable_language(C) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + CMAKE_FLAGS "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=bin" + ) diff --git a/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake b/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake index e156e12..f80d445 100644 --- a/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake +++ b/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake @@ -11,6 +11,9 @@ run_cmake(BadSources2) run_cmake(EmptyValueArgs) run_cmake(EmptyListArgs) run_cmake(TryRunArgs) +run_cmake(BuildType) +run_cmake(BuildTypeAsFlag) +run_cmake(OutputDirAsFlag) run_cmake(EnvConfig) -- cgit v0.12