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:
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
@@ -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
|
@@ -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)
|
@@ -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()
|
@@ -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)
|
||||
|
6
Tests/RunCMake/try_compile/BuildType.cmake
Normal file
6
Tests/RunCMake/try_compile/BuildType.cmake
Normal 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"
|
||||
)
|
7
Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake
Normal file
7
Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake
Normal 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"
|
||||
)
|
7
Tests/RunCMake/try_compile/OutputDirAsFlag.cmake
Normal file
7
Tests/RunCMake/try_compile/OutputDirAsFlag.cmake
Normal 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"
|
||||
)
|
@@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user