1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-20 04:24:36 +08:00

try_compile: Record output location instead of reverse computing it

Fixes #23887, #23942, #20163, #18288
This commit is contained in:
Robert Maynard
2022-08-31 10:14:29 -04:00
parent ecfc63a9b0
commit 0c141b0393
11 changed files with 67 additions and 71 deletions

View File

@@ -13,6 +13,7 @@
#include <cmext/string_view> #include <cmext/string_view>
#include "cmsys/Directory.hxx" #include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmArgumentParser.h" #include "cmArgumentParser.h"
#include "cmExportTryCompileFileGenerator.h" #include "cmExportTryCompileFileGenerator.h"
@@ -694,6 +695,17 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
} }
fprintf(fout, ")\n"); fprintf(fout, ")\n");
/* Write out the output location of the target we are building */
std::string perConfigGenex;
if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) {
perConfigGenex = "_$<UPPER_CASE:$<CONFIG>>";
}
fprintf(fout,
"file(GENERATE OUTPUT "
"\"${CMAKE_BINARY_DIR}/%s%s_loc\"\n",
targetName.c_str(), perConfigGenex.c_str());
fprintf(fout, " CONTENT $<TARGET_FILE:%s>)\n", targetName.c_str());
bool warnCMP0067 = false; bool warnCMP0067 = false;
bool honorStandard = true; bool honorStandard = true;
@@ -935,7 +947,7 @@ bool cmCoreTryCompile::TryCompileCode(Arguments& arguments,
if (this->SrcFileSignature) { if (this->SrcFileSignature) {
std::string copyFileErrorMessage; std::string copyFileErrorMessage;
this->FindOutputFile(targetName, targetType); this->FindOutputFile(targetName);
if ((res == 0) && arguments.CopyFileTo) { if ((res == 0) && arguments.CopyFileTo) {
std::string const& copyFile = *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, void cmCoreTryCompile::FindOutputFile(const std::string& targetName)
cmStateEnums::TargetType targetType)
{ {
this->FindErrorMessage.clear(); this->FindErrorMessage.clear();
this->OutputFile.clear(); this->OutputFile.clear();
std::string tmpOutputFile = "/"; std::string tmpOutputFile = "/";
if (targetType == cmStateEnums::EXECUTABLE) { tmpOutputFile += targetName;
tmpOutputFile += targetName;
tmpOutputFile += if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) {
this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX"); tmpOutputFile += "_DEBUG";
} else // if (targetType == cmStateEnums::STATIC_LIBRARY) }
{ tmpOutputFile += "_loc";
tmpOutputFile +=
this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX"); std::string command = cmStrCat(this->BinaryDirectory, tmpOutputFile);
tmpOutputFile += targetName; if (!cmSystemTools::FileExists(command)) {
tmpOutputFile += std::ostringstream emsg;
this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"); 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 std::string outputFileLocation;
// at first directly in the binary dir cmsys::ifstream ifs(command.c_str());
std::vector<std::string> searchDirs; cmSystemTools::GetLineFromStream(ifs, outputFileLocation);
searchDirs.emplace_back(); if (!cmSystemTools::FileExists(outputFileLocation)) {
std::ostringstream emsg;
cmValue config = emsg << "Recorded try_compile output location doesn't exist:\n";
this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); emsg << cmStrCat(" ", outputFileLocation, "\n");
// if a config was specified try that first this->FindErrorMessage = emsg.str();
if (cmNonempty(config)) { return;
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::ostringstream emsg; this->OutputFile = cmSystemTools::CollapseFullPath(outputFileLocation);
emsg << "Unable to find the executable at any of:\n";
emsg << cmWrap(" " + this->BinaryDirectory, searchDirs, tmpOutputFile, "\n")
<< "\n";
this->FindErrorMessage = emsg.str();
} }

View File

@@ -94,8 +94,7 @@ public:
TryCompileCode. The result is stored in OutputFile. If nothing is found, TryCompileCode. The result is stored in OutputFile. If nothing is found,
the error message is stored in FindErrorMessage. the error message is stored in FindErrorMessage.
*/ */
void FindOutputFile(const std::string& targetName, void FindOutputFile(const std::string& targetName);
cmStateEnums::TargetType targetType);
std::string BinaryDirectory; std::string BinaryDirectory;
std::string OutputFile; std::string OutputFile;

View File

@@ -1,5 +1,6 @@
# Change the executable suffix that try_compile will use for # 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) get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE)
if(NOT in_try_compile) if(NOT in_try_compile)
set(CMAKE_EXECUTABLE_SUFFIX .missing) set(CMAKE_EXECUTABLE_SUFFIX .missing)

View File

@@ -1,4 +1,4 @@
-- Detecting C compiler ABI info -- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed.* -- Detecting C compiler ABI info - done.*
-- Configuring done -- Configuring done
-- Generating done -- Generating done

View File

@@ -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) enable_language(C)

View File

@@ -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()

View File

@@ -1,9 +1,9 @@
include(RunCMake) include(RunCMake)
run_cmake(ContinueAfterError) run_cmake(ContinueAfterError)
run_cmake(CopyFileABI)
run_cmake(CustomTargetAfterError) run_cmake(CustomTargetAfterError)
run_cmake(ErrorLogs) run_cmake(ErrorLogs)
run_cmake(FailCopyFileABI)
# Use a single build tree for a few tests without cleaning. # Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RerunCMake-build) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RerunCMake-build)

View File

@@ -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"
)

View File

@@ -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"
)

View File

@@ -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"
)

View File

@@ -11,6 +11,9 @@ run_cmake(BadSources2)
run_cmake(EmptyValueArgs) run_cmake(EmptyValueArgs)
run_cmake(EmptyListArgs) run_cmake(EmptyListArgs)
run_cmake(TryRunArgs) run_cmake(TryRunArgs)
run_cmake(BuildType)
run_cmake(BuildTypeAsFlag)
run_cmake(OutputDirAsFlag)
run_cmake(EnvConfig) run_cmake(EnvConfig)