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 "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 = "_$<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 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<std::string> 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);
}

View File

@@ -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;

View File

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

View File

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

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)

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

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(EmptyListArgs)
run_cmake(TryRunArgs)
run_cmake(BuildType)
run_cmake(BuildTypeAsFlag)
run_cmake(OutputDirAsFlag)
run_cmake(EnvConfig)