diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 0a6c35942f..654c9a337b 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; + + if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) { + tmpOutputFile += "_DEBUG"; + } + 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; } - // 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)); - } - 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)); - } - 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 b483f0fd5b..729aa9ff9b 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/FailCopyFileABI-override.cmake b/Tests/RunCMake/Configure/CopyFileABI-override.cmake similarity index 64% rename from Tests/RunCMake/Configure/FailCopyFileABI-override.cmake rename to Tests/RunCMake/Configure/CopyFileABI-override.cmake index c633555b64..67f6ed532d 100644 --- a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake +++ b/Tests/RunCMake/Configure/CopyFileABI-override.cmake @@ -1,5 +1,6 @@ # Change the executable suffix that try_compile will use for -# COPY_FILE but not inside the test project. This forces failure. +# 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) diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt similarity index 62% rename from Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt rename to Tests/RunCMake/Configure/CopyFileABI-stdout.txt index 92fe2330af..6a856a4d0e 100644 --- a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt +++ b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt @@ -1,4 +1,4 @@ -- Detecting C compiler ABI info --- Detecting C compiler ABI info - failed.* +-- Detecting C compiler ABI info - done.* -- Configuring done -- Generating done diff --git a/Tests/RunCMake/Configure/FailCopyFileABI.cmake b/Tests/RunCMake/Configure/CopyFileABI.cmake similarity index 71% rename from Tests/RunCMake/Configure/FailCopyFileABI.cmake rename to Tests/RunCMake/Configure/CopyFileABI.cmake index 74efd9720d..4eee100ea4 100644 --- a/Tests/RunCMake/Configure/FailCopyFileABI.cmake +++ b/Tests/RunCMake/Configure/CopyFileABI.cmake @@ -1,2 +1,2 @@ -set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/FailCopyFileABI-override.cmake) +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 db0cb0a346..0000000000 --- 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/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake index 9fd4499af0..750fa3c2bb 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 0000000000..f2709f8050 --- /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 0000000000..e9384c76a3 --- /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 0000000000..5c4dca51f6 --- /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 e156e12f8c..f80d4458f4 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)