mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
Merge topic 'automoc-predefs-msvc'
7c3ca57b91MSVC,Clang: Set CMAKE_CXX_COMPILER_PREDEFINES_COMMAND for the MSVC ABI0fd711348cAutogen: Pass WIN32 to moc when targeting the MSVC ABI4a4a654814Autogen: Keep stderr out of the generated moc_predefs.h1c1258ad95cmWorkerPool: Allow capturing process stderr separately Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !12517
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
// An empty translation unit for CMAKE_<LANG>_COMPILER_PREDEFINES_COMMAND.
|
||||
// MSVC-like compilers echo the preprocessed source along with the macro
|
||||
// definitions, so the input must contribute no output of its own.
|
||||
@@ -20,6 +20,31 @@ if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
|
||||
endif()
|
||||
|
||||
# 'Compiler/GNU' is not included when clang simulates MSVC, so the predefines
|
||||
# command is not set up there.
|
||||
if(NOT DEFINED CMAKE_CXX_COMPILER_PREDEFINES_COMMAND)
|
||||
set(CMAKE_CXX_COMPILER_PREDEFINES_COMMAND "${CMAKE_CXX_COMPILER}")
|
||||
if(CMAKE_CXX_COMPILER_ARG1)
|
||||
separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_CXX_COMPILER_ARG1}")
|
||||
list(APPEND CMAKE_CXX_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
|
||||
unset(_COMPILER_ARGS)
|
||||
endif()
|
||||
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
# '-dM' is a cc1 option in this driver mode, and '-EP' also echoes the
|
||||
# preprocessed source, hence the empty translation unit.
|
||||
list(APPEND CMAKE_CXX_COMPILER_PREDEFINES_COMMAND
|
||||
"-nologo" "-w" "-Xclang" "-dM" "-EP"
|
||||
"${CMAKE_ROOT}/Modules/CMakeCXXCompilerPredefines.cpp")
|
||||
else()
|
||||
list(APPEND CMAKE_CXX_COMPILER_PREDEFINES_COMMAND
|
||||
"-w" "-dM" "-E" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER_TARGET)
|
||||
list(APPEND CMAKE_CXX_COMPILER_PREDEFINES_COMMAND
|
||||
"--target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") OR
|
||||
(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.1 AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
|
||||
if (CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR)
|
||||
|
||||
@@ -23,5 +23,22 @@ macro(__compiler_msvc lang)
|
||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang}_WARNING "-external:W0 ")
|
||||
endif ()
|
||||
|
||||
# '/PD' dumps the predefined macros, but it needs the conforming
|
||||
# preprocessor and one of '/E', '/EP' or '/P'. VS 2019 16.7 and older
|
||||
# ignore it with warning D9002, so require 16.8. '/EP' also echoes the
|
||||
# preprocessed source, hence the empty translation unit.
|
||||
if("${lang}" STREQUAL "CXX" AND
|
||||
CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28)
|
||||
set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}")
|
||||
if(CMAKE_${lang}_COMPILER_ARG1)
|
||||
separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}")
|
||||
list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
|
||||
unset(_COMPILER_ARGS)
|
||||
endif()
|
||||
list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND
|
||||
"-nologo" "-w" "-Zc:preprocessor" "-PD" "-EP"
|
||||
"${CMAKE_ROOT}/Modules/CMakeCXXCompilerPredefines.cpp")
|
||||
endif()
|
||||
|
||||
set(CMAKE_${lang}_LINK_MODE LINKER)
|
||||
endmacro()
|
||||
|
||||
@@ -713,6 +713,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmQtAutoGenInitializer::IsMsvcAbi() const
|
||||
{
|
||||
return this->Makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") ==
|
||||
"MSVC" ||
|
||||
this->Makefile->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") == "MSVC";
|
||||
}
|
||||
|
||||
bool cmQtAutoGenInitializer::InitMoc()
|
||||
{
|
||||
// Mocs compilation file
|
||||
@@ -814,10 +821,12 @@ bool cmQtAutoGenInitializer::InitMoc()
|
||||
auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {
|
||||
std::set<std::string> defines;
|
||||
this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);
|
||||
if (this->Moc.PredefsCmd.empty() &&
|
||||
this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") ==
|
||||
"Windows") {
|
||||
// Add WIN32 definition if we don't have a moc_predefs.h
|
||||
if (this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") ==
|
||||
"Windows" &&
|
||||
(this->Moc.PredefsCmd.empty() || this->IsMsvcAbi())) {
|
||||
// Add WIN32 definition if moc_predefs.h cannot supply it. Targeting
|
||||
// the MSVC ABI it comes from our default flags rather than from the
|
||||
// compiler, so it never appears in moc_predefs.h.
|
||||
defines.insert("WIN32");
|
||||
}
|
||||
return defines;
|
||||
|
||||
@@ -111,6 +111,9 @@ private:
|
||||
return (this->Moc.Enabled || this->Uic.Enabled);
|
||||
}
|
||||
|
||||
/** Whether the CXX compiler targets the MSVC ABI. */
|
||||
bool IsMsvcAbi() const;
|
||||
|
||||
bool InitMoc();
|
||||
bool InitUic();
|
||||
bool InitRcc();
|
||||
|
||||
@@ -359,7 +359,8 @@ public:
|
||||
/** @brief Run an external process. Use only during Process() call! */
|
||||
bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
|
||||
std::vector<std::string> const& command,
|
||||
std::string* infoMessage = nullptr);
|
||||
std::string* infoMessage = nullptr,
|
||||
bool mergedOutput = true);
|
||||
};
|
||||
|
||||
/** Fence job utility class. */
|
||||
@@ -863,7 +864,8 @@ void cmQtAutoMocUicT::JobT::MaybeWriteResponseFile(
|
||||
bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
|
||||
cmWorkerPool::ProcessResultT& result,
|
||||
std::vector<std::string> const& command,
|
||||
std::string* infoMessage)
|
||||
std::string* infoMessage,
|
||||
bool mergedOutput)
|
||||
{
|
||||
// Log command
|
||||
if (this->Log().Verbose()) {
|
||||
@@ -878,7 +880,7 @@ bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
|
||||
}
|
||||
// Run command
|
||||
return this->cmWorkerPool::JobT::RunProcess(
|
||||
result, command, this->BaseConst().AutogenBuildDir);
|
||||
result, command, this->BaseConst().AutogenBuildDir, mergedOutput);
|
||||
}
|
||||
|
||||
void cmQtAutoMocUicT::JobMocPredefsT::Process()
|
||||
@@ -904,13 +906,15 @@ void cmQtAutoMocUicT::JobMocPredefsT::Process()
|
||||
// Check if response file is necessary
|
||||
MaybeWriteResponseFile(this->MocConst().PredefsFileAbs, cmd);
|
||||
|
||||
// Execute command
|
||||
if (!this->RunProcess(GenT::MOC, result, cmd, reason.get())) {
|
||||
// Execute command. Keep stderr out of the captured stdout, which is
|
||||
// written to the predefs file verbatim: MSVC-like compilers echo the
|
||||
// name of the source file they preprocess.
|
||||
if (!this->RunProcess(GenT::MOC, result, cmd, reason.get(), false)) {
|
||||
this->LogCommandError(GenT::MOC,
|
||||
cmStrCat("The content generation command for ",
|
||||
this->MessagePath(predefsFileAbs),
|
||||
" failed.\n", result.ErrorMessage),
|
||||
cmd, result.StdOut);
|
||||
cmd, result.StdOut + result.StdErr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ public:
|
||||
*/
|
||||
bool RunProcess(cmWorkerPool::ProcessResultT& result,
|
||||
std::vector<std::string> command,
|
||||
std::string const& workingDirectory);
|
||||
std::string const& workingDirectory, bool mergedOutput);
|
||||
|
||||
private:
|
||||
// -- Libuv callbacks
|
||||
@@ -434,7 +434,8 @@ cmWorkerPoolWorker::~cmWorkerPoolWorker()
|
||||
|
||||
bool cmWorkerPoolWorker::RunProcess(cmWorkerPool::ProcessResultT& result,
|
||||
std::vector<std::string> command,
|
||||
std::string const& workingDirectory)
|
||||
std::string const& workingDirectory,
|
||||
bool mergedOutput)
|
||||
{
|
||||
if (command.empty()) {
|
||||
return false;
|
||||
@@ -443,7 +444,7 @@ bool cmWorkerPoolWorker::RunProcess(cmWorkerPool::ProcessResultT& result,
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(this->Proc_.Mutex);
|
||||
this->Proc_.ROP = cm::make_unique<cmUVReadOnlyProcess>();
|
||||
this->Proc_.ROP->setup(&result, true, std::move(command),
|
||||
this->Proc_.ROP->setup(&result, mergedOutput, std::move(command),
|
||||
workingDirectory);
|
||||
}
|
||||
// Send asynchronous process start request to libuv loop
|
||||
@@ -737,11 +738,13 @@ cmWorkerPool::JobT::~JobT() = default;
|
||||
|
||||
bool cmWorkerPool::JobT::RunProcess(ProcessResultT& result,
|
||||
std::vector<std::string> command,
|
||||
std::string const& workingDirectory)
|
||||
std::string const& workingDirectory,
|
||||
bool mergedOutput)
|
||||
{
|
||||
// Get worker by index
|
||||
auto* worker = this->Pool_->Int_->Workers.at(this->WorkerIndex_).get();
|
||||
return worker->RunProcess(result, std::move(command), workingDirectory);
|
||||
return worker->RunProcess(result, std::move(command), workingDirectory,
|
||||
mergedOutput);
|
||||
}
|
||||
|
||||
cmWorkerPool::cmWorkerPool()
|
||||
|
||||
@@ -101,9 +101,12 @@ public:
|
||||
/**
|
||||
* Run an external read only process.
|
||||
* Use only during JobT::Process() call!
|
||||
* @arg mergedOutput Append the process stderr to ProcessResultT::StdOut
|
||||
* instead of ProcessResultT::StdErr.
|
||||
*/
|
||||
bool RunProcess(ProcessResultT& result, std::vector<std::string> command,
|
||||
std::string const& workingDirectory);
|
||||
std::string const& workingDirectory,
|
||||
bool mergedOutput = true);
|
||||
|
||||
private:
|
||||
//! Needs access to Work()
|
||||
|
||||
@@ -11,6 +11,14 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
add_library(MocPredefs MocPredefs.cxx)
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_COMPILER_PREDEFINES_COMMAND)
|
||||
# Do not silently skip on toolchains that are expected to provide it.
|
||||
if((CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION GREATER_EQUAL 1928)
|
||||
OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"
|
||||
AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))
|
||||
message(FATAL_ERROR
|
||||
"CMAKE_CXX_COMPILER_PREDEFINES_COMMAND is not defined for "
|
||||
"${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}.")
|
||||
endif()
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user