diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/CTest/cmCTestRunTest.cxx | 7 | ||||
-rw-r--r-- | Source/QtDialog/CMakeLists.txt | 115 | ||||
-rw-r--r-- | Source/QtDialog/CMakeSetup.cxx | 4 | ||||
-rw-r--r-- | Source/QtDialog/EnvironmentDialog.cxx | 4 | ||||
-rw-r--r-- | Source/QtDialog/QCMakeCacheView.cxx | 4 | ||||
-rw-r--r-- | Source/QtDialog/QCMakeWidgets.cxx | 38 | ||||
-rw-r--r-- | Source/cmCTest.cxx | 2 | ||||
-rw-r--r-- | Source/cmCommandLineArgument.h | 159 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 1 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 9 | ||||
-rw-r--r-- | Source/cmake.cxx | 125 | ||||
-rw-r--r-- | Source/cmakemain.cxx | 418 |
16 files changed, 559 insertions, 335 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 4598fe4..1e9bbaa 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 19) -set(CMake_VERSION_PATCH 20210106) +set(CMake_VERSION_PATCH 20210107) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 4ba0ae1..5a6c775 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -139,7 +139,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode; } this->TestResult.CompletionStatus = s.str(); - cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped "); + outputStream << "***Skipped "; skipped = true; } else if (success != this->TestProperties->WillFail) { this->TestResult.Status = cmCTestTestHandler::COMPLETED; @@ -195,8 +195,9 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count()); outputStream << buf << "\n"; + bool passedOrSkipped = passed || skipped; if (this->CTest->GetTestProgressOutput()) { - if (!passed) { + if (!passedOrSkipped) { // If the test did not pass, reprint test name and error std::string output = this->GetTestPrefix(completed, total); std::string testName = this->TestProperties->Name; @@ -216,7 +217,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName); } } - if (!this->CTest->GetTestProgressOutput() || !passed) { + if (!this->CTest->GetTestProgressOutput() || !passedOrSkipped) { cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str()); } diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 452a303..1d3c66e 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -3,20 +3,52 @@ project(QtDialog) CMake_OPTIONAL_COMPONENT(cmake-gui) -find_package(Qt5Widgets REQUIRED) +set (QT_COMPONENTS + Core + Widgets + Gui +) + +set(CMake_QT_MAJOR_VERSION "A" CACHE + STRING "Expected Qt major version. Valid values are A (auto-select), 5, 6.") +set(SUPPORTED_QT_VERSIONS "A" 5 6) +set_property(CACHE CMake_QT_MAJOR_VERSION PROPERTY STRINGS ${SUPPORTED_QT_VERSIONS}) +if(NOT CMake_QT_MAJOR_VERSION VERSION_EQUAL "A") + if(NOT CMake_QT_MAJOR_VERSION IN_LIST SUPPORTED_QT_VERSIONS) + message(FATAL_ERROR "Supported Qt versions are \"${SUPPORTED_QT_VERSIONS}\"." + " But CMake_QT_MAJOR_VERSION is set to ${CMake_QT_MAJOR_VERSION}.") + endif() + set(INSTALLED_QT_VERSION ${CMake_QT_MAJOR_VERSION}) +else() + find_package(Qt6Widgets QUIET) + set(INSTALLED_QT_VERSION 6) + if(NOT Qt6Widgets_FOUND) + find_package(Qt5Widgets QUIET) + if(NOT Qt5Widgets_FOUND) + message(FATAL_ERROR "Could not find a valid Qt installation.") + endif() + set(INSTALLED_QT_VERSION 5) + endif() +endif() + +find_package(Qt${INSTALLED_QT_VERSION} + COMPONENTS ${QT_COMPONENTS} + REQUIRED QUIET +) set(CMake_QT_EXTRA_LIBRARIES) # Try to find the package WinExtras for the task bar progress if(WIN32) - find_package(Qt5WinExtras QUIET) - if (Qt5WinExtras_FOUND) + find_package(Qt${INSTALLED_QT_VERSION}WinExtras QUIET) + if (Qt${INSTALLED_QT_VERSION}WinExtras_FOUND) add_definitions(-DQT_WINEXTRAS) - list(APPEND CMake_QT_EXTRA_LIBRARIES Qt5::WinExtras) + list(APPEND CMake_QT_EXTRA_LIBRARIES Qt${INSTALLED_QT_VERSION}::WinExtras) + list(APPEND QT_COMPONENTS WinExtras) endif() endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt${INSTALLED_QT_VERSION}Widgets_EXECUTABLE_COMPILE_FLAGS}") if(CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES) list(APPEND CMake_QT_EXTRA_LIBRARIES ${CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES}) @@ -34,8 +66,24 @@ endif() # FIXME: This should be part of Qt5 CMake scripts, but unfortunately # Qt5 support is missing there. if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) - macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var) - get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) + function(_qt_get_plugin_name_with_version target out_var) + string(REGEX REPLACE "^Qt::(.+)" "Qt${INSTALLED_QT_VERSION}::\\1" + qt_plugin_with_version "${target}") + if(TARGET "${qt_plugin_with_version}") + set("${out_var}" "${qt_plugin_with_version}" PARENT_SCOPE) + else() + set("${out_var}" "" PARENT_SCOPE) + endif() + endfunction() + macro(install_qt_plugin _qt_plugin_name _qt_plugins_var) + if(TARGET "${_qt_plugin_name}") + get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) + else() + _qt_get_plugin_name_with_version("Qt::${_qt_plugin_name}" _qt_plugin_with_version_name) + if(TARGET "${_qt_plugin_with_version_name}") + get_target_property(_qt_plugin_path "${_qt_plugin_with_version_name}" LOCATION) + endif() + endif() if(EXISTS "${_qt_plugin_path}") get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) @@ -51,19 +99,33 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) ${COMPONENT}) set(${_qt_plugins_var} "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") - else() - message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") endif() endmacro() + macro(install_qt_plugins _comps _plugins_var) + foreach(_qt_comp ${${_comps}}) + if (INSTALLED_QT_VERSION VERSION_LESS 6) + set(_qt_module_plugins ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_PLUGINS}) + else() + get_target_property(_qt_module_plugins Qt${INSTALLED_QT_VERSION}::${_qt_comp} QT_PLUGINS) + endif() + foreach(_qt_plugin ${_qt_module_plugins}) + if (INSTALLED_QT_VERSION VERSION_GREATER_EQUAL 6) + # Qt6 provides the plugins as individual packages that need to be found. + find_package(Qt${INSTALLED_QT_VERSION}${_qt_plugin} QUIET + PATHS ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_DIR}) + endif() + install_qt_plugin(${_qt_plugin} _plugins_var) + endforeach() + endforeach() + endmacro() + install_qt_plugins(QT_COMPONENTS QT_PLUGINS) if(APPLE) - install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" "[Paths]\nPlugins = ${_qt_plugin_dir}\n") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" ${COMPONENT}) elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) - install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" "[Paths]\nPlugins = ../${_qt_plugin_dir}\n") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" @@ -72,8 +134,8 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) endif() endif() -get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) -get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) +get_property(_Qt_Core_LOCATION TARGET Qt${INSTALLED_QT_VERSION}::Core PROPERTY LOCATION) +get_filename_component(Qt_BIN_DIR "${_Qt_Core_LOCATION}" PATH) if(APPLE) get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) endif() @@ -105,7 +167,7 @@ set(SRCS WarningMessagesDialog.cxx WarningMessagesDialog.h ) -qt5_wrap_ui(UI_SRCS +set(UI_SRCS CMakeSetupDialog.ui Compilers.ui CrossCompiler.ui @@ -114,7 +176,7 @@ qt5_wrap_ui(UI_SRCS RegexExplorer.ui WarningMessagesDialog.ui ) -qt5_wrap_cpp(MOC_SRCS +set(MOC_SRCS AddCacheEntry.h Compilers.h CMakeSetupDialog.h @@ -128,7 +190,17 @@ qt5_wrap_cpp(MOC_SRCS RegexExplorer.h WarningMessagesDialog.h ) -qt5_add_resources(RC_SRCS CMakeSetup.qrc) +set(QRC_SRCS CMakeSetup.qrc) + +if (INSTALLED_QT_VERSION VERSION_LESS 6) + qt5_wrap_ui(UI_BUILT_SRCS ${UI_SRCS}) + qt5_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS}) + qt5_add_resources(QRC_BUILT_SRCS ${QRC_SRCS}) +else() + qt_wrap_ui(UI_BUILT_SRCS ${UI_SRCS}) + qt_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS}) + qt_add_resources(QRC_BUILT_SRCS ${QRC_SRCS}) +endif() if (FALSE) # CMake's bootstrap binary does not support automoc set(CMAKE_AUTOMOC 1) @@ -136,9 +208,9 @@ if (FALSE) # CMake's bootstrap binary does not support automoc set(CMAKE_AUTOUIC 1) else () list(APPEND SRCS - ${UI_SRCS} - ${MOC_SRCS} - ${RC_SRCS}) + ${UI_BUILT_SRCS} + ${MOC_BUILT_SRCS} + ${QRC_BUILT_SRCS}) endif () if(USE_LGPL) @@ -153,13 +225,14 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_library(CMakeGUILib STATIC ${SRCS}) # CMake_QT_EXTRA_LIBRARIES have to come before the main libraries on the link line -target_link_libraries(CMakeGUILib PUBLIC CMakeLib ${CMake_QT_EXTRA_LIBRARIES} Qt5::Core Qt5::Widgets) +target_link_libraries(CMakeGUILib PUBLIC CMakeLib ${CMake_QT_EXTRA_LIBRARIES} + Qt${INSTALLED_QT_VERSION}::Core Qt${INSTALLED_QT_VERSION}::Widgets) add_library(CMakeGUIMainLib STATIC CMakeSetup.cxx) target_link_libraries(CMakeGUIMainLib PUBLIC CMakeGUILib) add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx ${MANIFEST_FILE}) -target_link_libraries(cmake-gui CMakeGUIMainLib Qt5::Core) +target_link_libraries(cmake-gui CMakeGUIMainLib Qt${INSTALLED_QT_VERSION}::Core) if(WIN32) target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeVersion> CMakeSetup.rc) diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 861c6e3..5debdb8 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -7,7 +7,6 @@ #include <QDir> #include <QLocale> #include <QString> -#include <QTextCodec> #include <QTranslator> #include <QtPlugin> @@ -122,9 +121,6 @@ int main(int argc, char** argv) setlocale(LC_NUMERIC, "C"); - QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8"); - QTextCodec::setCodecForLocale(utf8_codec); - // tell the cmake library where cmake is QDir cmExecDir(QApplication::applicationDirPath()); #if defined(Q_OS_MAC) diff --git a/Source/QtDialog/EnvironmentDialog.cxx b/Source/QtDialog/EnvironmentDialog.cxx index 846456c..d4f978c 100644 --- a/Source/QtDialog/EnvironmentDialog.cxx +++ b/Source/QtDialog/EnvironmentDialog.cxx @@ -81,7 +81,11 @@ bool EnvironmentSearchFilter::filterAcceptsRow(int row, auto* model = this->sourceModel(); auto key = model->data(model->index(row, 0, parent), Qt::DisplayRole).toString(); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + return key.contains(this->filterRegularExpression()); +#else return key.contains(this->filterRegExp()); +#endif } EnvironmentDialog::EnvironmentDialog(const QProcessEnvironment& environment, diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 22f5be1..7c9032e 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -47,7 +47,11 @@ protected: // check all strings for a match foreach (QString const& str, strs) { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + if (str.contains(this->filterRegularExpression())) { +#else if (str.contains(this->filterRegExp())) { +#endif return true; } } diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx index e68faba..ca65d13 100644 --- a/Source/QtDialog/QCMakeWidgets.cxx +++ b/Source/QtDialog/QCMakeWidgets.cxx @@ -1,20 +1,23 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -// FIXME: Port to QFileSystemModel from the deprecated QDirModel. -// Be sure completion works when incrementally editing existing paths. #define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION_CHECK(5, 14, 0) #include "QCMakeWidgets.h" #include <utility> -#include <QDirModel> #include <QFileDialog> #include <QFileInfo> #include <QResizeEvent> #include <QToolButton> +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +# include <QFileSystemModel> +#else +# include <QDirModel> +#endif + QCMakeFileEditor::QCMakeFileEditor(QWidget* p, QString var) : QLineEdit(p) , Variable(std::move(var)) @@ -93,8 +96,30 @@ void QCMakePathEditor::chooseFile() } } +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +// use same QFileSystemModel for all completers +static QFileSystemModel* fileDirModel() + +{ + static QFileSystemModel* m = nullptr; + if (!m) { + m = new QFileSystemModel(); + } + return m; +} +static QFileSystemModel* pathDirModel() +{ + static QFileSystemModel* m = nullptr; + if (!m) { + m = new QFileSystemModel(); + m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot); + } + return m; +} +#else // use same QDirModel for all completers static QDirModel* fileDirModel() + { static QDirModel* m = nullptr; if (!m) { @@ -111,12 +136,19 @@ static QDirModel* pathDirModel() } return m; } +#endif QCMakeFileCompleter::QCMakeFileCompleter(QObject* o, bool dirs) : QCompleter(o) { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QFileSystemModel* m = dirs ? pathDirModel() : fileDirModel(); + this->setModel(m); + m->setRootPath(QString()); +#else QDirModel* m = dirs ? pathDirModel() : fileDirModel(); this->setModel(m); +#endif } QString QCMakeFileCompleter::pathFromIndex(const QModelIndex& idx) const diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 6507f38..6c1071d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2901,7 +2901,7 @@ bool cmCTest::GetFailover() const bool cmCTest::GetTestProgressOutput() const { - return this->Impl->TestProgressOutput; + return this->Impl->TestProgressOutput && !GetExtraVerbose(); } bool cmCTest::GetVerbose() const diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h new file mode 100644 index 0000000..cbedf0a --- /dev/null +++ b/Source/cmCommandLineArgument.h @@ -0,0 +1,159 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +template <typename FunctionSignature> +struct cmCommandLineArgument +{ + enum class Values + { + Zero, + One, + Two, + ZeroOrOne, + OneOrMore + }; + + std::string InvalidSyntaxMessage; + std::string InvalidValueMessage; + std::string Name; + Values Type; + std::function<FunctionSignature> StoreCall; + + template <typename FunctionType> + cmCommandLineArgument(std::string n, Values t, FunctionType&& func) + : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) + , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) + , Name(std::move(n)) + , Type(t) + , StoreCall(std::forward<FunctionType>(func)) + { + } + + template <typename FunctionType> + cmCommandLineArgument(std::string n, std::string failedMsg, Values t, + FunctionType&& func) + : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) + , InvalidValueMessage(std::move(failedMsg)) + , Name(std::move(n)) + , Type(t) + , StoreCall(std::forward<FunctionType>(func)) + { + } + + bool matches(std::string const& input) const + { + return (this->Type == Values::Zero) ? (input == this->Name) + : cmHasPrefix(input, this->Name); + } + + template <typename T, typename... CallState> + bool parse(std::string const& input, T& index, + std::vector<std::string> const& allArgs, + CallState&&... state) const + { + enum class ParseMode + { + Valid, + Invalid, + SyntaxError, + ValueError + }; + ParseMode parseState = ParseMode::Valid; + + if (this->Type == Values::Zero) { + if (input.size() == this->Name.size()) { + parseState = + this->StoreCall(std::string{}, std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } else { + parseState = ParseMode::SyntaxError; + } + + } else if (this->Type == Values::One || this->Type == Values::ZeroOrOne) { + if (input.size() == this->Name.size()) { + ++index; + if (index >= allArgs.size() || allArgs[index][0] == '-') { + if (this->Type == Values::ZeroOrOne) { + parseState = + this->StoreCall(std::string{}, std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } else { + parseState = ParseMode::ValueError; + } + } else { + parseState = + this->StoreCall(allArgs[index], std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } else { + // parse the string to get the value + auto possible_value = cm::string_view(input).substr(this->Name.size()); + if (possible_value.empty()) { + parseState = ParseMode::SyntaxError; + parseState = ParseMode::ValueError; + } else if (possible_value[0] == '=') { + possible_value.remove_prefix(1); + if (possible_value.empty()) { + parseState = ParseMode::ValueError; + } else { + parseState = this->StoreCall(std::string(possible_value), + std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + if (parseState == ParseMode::Valid) { + parseState = this->StoreCall(std::string(possible_value), + std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + } else if (this->Type == Values::Two) { + if (input.size() == this->Name.size()) { + if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' || + allArgs[index + 2][0] == '-') { + parseState = ParseMode::ValueError; + } else { + index += 2; + parseState = + this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]), + std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + } else if (this->Type == Values::OneOrMore) { + if (input.size() == this->Name.size()) { + auto nextValueIndex = index + 1; + if (nextValueIndex >= allArgs.size() || allArgs[index + 1][0] == '-') { + parseState = ParseMode::ValueError; + } else { + std::string buffer = allArgs[nextValueIndex++]; + while (nextValueIndex < allArgs.size() && + allArgs[nextValueIndex][0] != '-') { + buffer = cmStrCat(buffer, ";", allArgs[nextValueIndex++]); + } + parseState = + this->StoreCall(buffer, std::forward<CallState>(state)...) + ? ParseMode::Valid + : ParseMode::Invalid; + } + } + } + + if (parseState == ParseMode::SyntaxError) { + cmSystemTools::Error(this->InvalidSyntaxMessage); + } else if (parseState == ParseMode::ValueError) { + cmSystemTools::Error(this->InvalidValueMessage); + } + return (parseState == ParseMode::Valid); + } +}; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index a853bb1..113751a 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -707,7 +707,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( break; } input.replace(pos, endPos - pos + 1, targetName); - lastPos = endPos; + lastPos = pos + targetName.size(); } pos = 0; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 0f91d6d..c33fabd 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -898,7 +898,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmExpandList(compileRule, compileCommands); } - if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") && + if (this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS") && lang_can_export_cmds && compileCommands.size() == 1) { std::string compileCommand = compileCommands[0]; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 18c9d82..f1bd760 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1536,7 +1536,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( std::string const& objectFileDir, std::string const& flags, std::string const& defines, std::string const& includes) { - if (!this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) { + if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) { return; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2fd6063..1fd2355 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -383,6 +383,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("UNITY_BUILD"); initProp("UNITY_BUILD_UNIQUE_ID"); initProp("OPTIMIZE_DEPENDENCIES"); + initProp("EXPORT_COMPILE_COMMANDS"); initPropValue("UNITY_BUILD_BATCH_SIZE", "8"); initPropValue("UNITY_BUILD_MODE", "BATCH"); initPropValue("PCH_WARN_INVALID", "ON"); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9c41504..a93a78a 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1897,8 +1897,15 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } // Figure out if there's any additional flags to use if (cmProp saf = sf->GetProperty("VS_SHADER_FLAGS")) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*saf); + for (const std::string& config : this->Configurations) { - toolSettings[config]["AdditionalOptions"] = *saf; + std::string evaluated = cge->Evaluate(this->LocalGenerator, config); + + if (!evaluated.empty()) { + toolSettings[config]["AdditionalOptions"] = evaluated; + } } } // Figure out if debug information should be generated diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1691037..d6360a7 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -29,6 +29,7 @@ #include "cm_sys_stat.h" #include "cmCMakePresetsFile.h" +#include "cmCommandLineArgument.h" #include "cmCommands.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" @@ -132,131 +133,13 @@ namespace { using JsonValueMapType = std::unordered_map<std::string, Json::Value>; #endif -struct CommandArgument -{ - enum struct Values - { - Zero, - One, - Two, - }; - - std::string InvalidSyntaxMessage; - std::string InvalidValueMessage; - std::string Name; - CommandArgument::Values Type; - std::function<bool(std::string const& value, cmake* state)> StoreCall; - - template <typename FunctionType> - CommandArgument(std::string n, CommandArgument::Values t, - FunctionType&& func) - : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) - , InvalidValueMessage(cmStrCat("Invalid value used with ", n)) - , Name(std::move(n)) - , Type(t) - , StoreCall(std::forward<FunctionType>(func)) - { - } - - template <typename FunctionType> - CommandArgument(std::string n, std::string failedMsg, - CommandArgument::Values t, FunctionType&& func) - : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n)) - , InvalidValueMessage(std::move(failedMsg)) - , Name(std::move(n)) - , Type(t) - , StoreCall(std::forward<FunctionType>(func)) - { - } - - bool matches(std::string const& input) const - { - return cmHasPrefix(input, this->Name); - } - - template <typename T> - bool parse(std::string const& input, T& index, - std::vector<std::string> const& allArgs, cmake* state) const - { - enum struct ParseMode - { - Valid, - Invalid, - SyntaxError, - ValueError - }; - ParseMode parseState = ParseMode::Valid; - - // argument is the next parameter - if (this->Type == CommandArgument::Values::Zero) { - if (input.size() == this->Name.size()) { - parseState = this->StoreCall(input, state) ? ParseMode::Valid - : ParseMode::Invalid; - } else { - parseState = ParseMode::SyntaxError; - } - - } else if (this->Type == CommandArgument::Values::One) { - if (input.size() == this->Name.size()) { - ++index; - if (index >= allArgs.size() || allArgs[index][0] == '-') { - parseState = ParseMode::ValueError; - } else { - parseState = this->StoreCall(allArgs[index], state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } else { - // parse the string to get the value - auto possible_value = cm::string_view(input).substr(this->Name.size()); - if (possible_value.empty()) { - parseState = ParseMode::SyntaxError; - parseState = ParseMode::ValueError; - } else if (possible_value[0] == '=') { - possible_value.remove_prefix(1); - if (possible_value.empty()) { - parseState = ParseMode::ValueError; - } else { - parseState = this->StoreCall(std::string(possible_value), state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } - if (parseState == ParseMode::Valid) { - parseState = this->StoreCall(std::string(possible_value), state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } - } else if (this->Type == CommandArgument::Values::Two) { - if (input.size() == this->Name.size()) { - if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' || - allArgs[index + 2][0] == '-') { - parseState = ParseMode::ValueError; - } else { - index += 2; - parseState = - this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]), - state) - ? ParseMode::Valid - : ParseMode::Invalid; - } - } - } - - if (parseState == ParseMode::SyntaxError) { - cmSystemTools::Error(this->InvalidSyntaxMessage); - } else if (parseState == ParseMode::ValueError) { - cmSystemTools::Error(this->InvalidValueMessage); - } - return (parseState == ParseMode::Valid); - } -}; - auto IgnoreAndTrueLambda = [](std::string const&, cmake*) -> bool { return true; }; +using CommandArgument = + cmCommandLineArgument<bool(std::string const& value, cmake* state)>; + } // namespace static bool cmakeCheckStampFile(const std::string& stampName); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index f7734a6..ba471b7 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -5,7 +5,6 @@ #include <algorithm> #include <cassert> -#include <cctype> #include <climits> #include <cstring> #include <iostream> @@ -19,6 +18,7 @@ #include <cm3p/uv.h> +#include "cmCommandLineArgument.h" #include "cmConsoleBuf.h" #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" @@ -213,61 +213,114 @@ int do_cmake(int ac, char const* const* av) } #endif + bool wizard_mode = false; bool sysinfo = false; bool list_cached = false; bool list_all_cached = false; bool list_help = false; bool view_only = false; cmake::WorkingMode workingMode = cmake::NORMAL_MODE; - std::vector<std::string> args; - for (int i = 0; i < ac; ++i) { - if (strcmp(av[i], "-i") == 0) { - /* clang-format off */ - std::cerr << - "The \"cmake -i\" wizard mode is no longer supported.\n" - "Use the -D option to set cache values on the command line.\n" - "Use cmake-gui or ccmake for an interactive dialog.\n"; - /* clang-format on */ - return 1; - } - if (strcmp(av[i], "--system-information") == 0) { - sysinfo = true; - } else if (strcmp(av[i], "-N") == 0) { - view_only = true; - } else if (strcmp(av[i], "-L") == 0) { - list_cached = true; - } else if (strcmp(av[i], "-LA") == 0) { - list_all_cached = true; - } else if (strcmp(av[i], "-LH") == 0) { - list_cached = true; - list_help = true; - } else if (strcmp(av[i], "-LAH") == 0) { - list_all_cached = true; - list_help = true; - } else if (cmHasLiteralPrefix(av[i], "-P")) { - if (i == ac - 1) { - cmSystemTools::Error("No script specified for argument -P"); - return 1; + std::vector<std::string> parsedArgs; + + using CommandArgument = + cmCommandLineArgument<bool(std::string const& value)>; + std::vector<CommandArgument> arguments = { + CommandArgument{ + "-i", CommandArgument::Values::Zero, + [&wizard_mode](std::string const&) -> bool { + /* clang-format off */ + std::cerr << + "The \"cmake -i\" wizard mode is no longer supported.\n" + "Use the -D option to set cache values on the command line.\n" + "Use cmake-gui or ccmake for an interactive dialog.\n"; + /* clang-format on */ + wizard_mode = true; + return true; + } }, + CommandArgument{ "--system-information", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + sysinfo = true; + return true; + } }, + CommandArgument{ "-N", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + view_only = true; + return true; + } }, + CommandArgument{ "-LAH", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_all_cached = true; + list_help = true; + return true; + } }, + CommandArgument{ "-LA", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_all_cached = true; + return true; + } }, + CommandArgument{ "-LH", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_cached = true; + list_help = true; + return true; + } }, + CommandArgument{ "-L", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + list_cached = true; + return true; + } }, + CommandArgument{ "-P", "No script specified for argument -P", + CommandArgument::Values::One, + [&](std::string const& value) -> bool { + workingMode = cmake::SCRIPT_MODE; + parsedArgs.emplace_back("-P"); + parsedArgs.push_back(value); + return true; + } }, + CommandArgument{ "--find-package", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + workingMode = cmake::FIND_PACKAGE_MODE; + parsedArgs.emplace_back("--find-package"); + return true; + } }, + CommandArgument{ "--list-presets", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + workingMode = cmake::HELP_MODE; + parsedArgs.emplace_back("--list-presets"); + return true; + } }, + }; + + std::vector<std::string> inputArgs; + inputArgs.reserve(ac); + cm::append(inputArgs, av, av + ac); + + for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) { + std::string const& arg = inputArgs[i]; + bool matched = false; + for (auto const& m : arguments) { + if (m.matches(arg)) { + matched = true; + if (m.parse(arg, i, inputArgs)) { + break; + } + return 1; // failed to parse } - workingMode = cmake::SCRIPT_MODE; - args.emplace_back(av[i]); - i++; - args.emplace_back(av[i]); - } else if (cmHasLiteralPrefix(av[i], "--find-package")) { - workingMode = cmake::FIND_PACKAGE_MODE; - args.emplace_back(av[i]); - } else if (strcmp(av[i], "--list-presets") == 0) { - workingMode = cmake::HELP_MODE; - args.emplace_back(av[i]); - } else { - args.emplace_back(av[i]); } + if (!matched) { + parsedArgs.emplace_back(av[i]); + } + } + + if (wizard_mode) { + return 1; } + if (sysinfo) { cmake cm(cmake::RoleProject, cmState::Project); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); - int ret = cm.GetSystemInformation(args); + int ret = cm.GetSystemInformation(parsedArgs); return ret; } cmake::Role const role = @@ -297,7 +350,7 @@ int do_cmake(int ac, char const* const* av) }); cm.SetWorkingMode(workingMode); - int res = cm.Run(args, view_only); + int res = cm.Run(parsedArgs, view_only); if (list_cached || list_all_cached) { std::cout << "-- Cache values" << std::endl; std::vector<std::string> keys = cm.GetState()->GetCacheEntryKeys(); @@ -332,16 +385,9 @@ int do_cmake(int ac, char const* const* av) } #ifndef CMAKE_BOOTSTRAP -int extract_job_number(int& index, char const* current, char const* next, - int len_of_flag) +int extract_job_number(std::string const& command, + std::string const& jobString) { - std::string command(current); - std::string jobString = command.substr(len_of_flag); - if (jobString.empty() && next && isdigit(next[0])) { - ++index; // skip parsing the job number - jobString = std::string(next); - } - int jobs = -1; unsigned long numJobs = 0; if (jobString.empty()) { @@ -356,8 +402,8 @@ int extract_job_number(int& index, char const* current, char const* next, jobs = int(numJobs); } } else { - std::cerr << "'" << command.substr(0, len_of_flag) << "' invalid number '" - << jobString << "' given.\n\n"; + std::cerr << "'" << command << "' invalid number '" << jobString + << "' given.\n\n"; } return jobs; } @@ -374,88 +420,107 @@ int do_build(int ac, char const* const* av) std::string config; std::string dir; std::vector<std::string> nativeOptions; + bool nativeOptionsPassed = false; bool cleanFirst = false; bool foundClean = false; bool foundNonClean = false; bool verbose = cmSystemTools::HasEnv("VERBOSE"); - enum Doing - { - DoingNone, - DoingDir, - DoingTarget, - DoingConfig, - DoingNative + auto jLambda = [&](std::string const& value) -> bool { + jobs = extract_job_number("-j", value); + if (jobs < 0) { + dir.clear(); + } + return true; }; - Doing doing = DoingDir; - for (int i = 2; i < ac; ++i) { - if (doing == DoingNative) { - nativeOptions.emplace_back(av[i]); - } else if (cmHasLiteralPrefix(av[i], "-j")) { - const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); - jobs = extract_job_number(i, av[i], nextArg, sizeof("-j") - 1); - if (jobs < 0) { - dir.clear(); - } - doing = DoingNone; - } else if (cmHasLiteralPrefix(av[i], "--parallel")) { - const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); - jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1); - if (jobs < 0) { - dir.clear(); + auto parallelLambda = [&](std::string const& value) -> bool { + jobs = extract_job_number("--parallel", value); + if (jobs < 0) { + dir.clear(); + } + return true; + }; + auto targetLambda = [&](std::string const& value) -> bool { + if (!value.empty()) { + std::vector<std::string> values = cmExpandedList(value); + for (auto const& v : values) { + targets.emplace_back(v); + if (v == "clean") { + foundClean = true; + } else { + foundNonClean = true; + } } - doing = DoingNone; - } else if ((strcmp(av[i], "--target") == 0) || - (strcmp(av[i], "-t") == 0)) { - doing = DoingTarget; - } else if (strcmp(av[i], "--config") == 0) { - doing = DoingConfig; - } else if (strcmp(av[i], "--clean-first") == 0) { - cleanFirst = true; - doing = DoingNone; - } else if ((strcmp(av[i], "--verbose") == 0) || - (strcmp(av[i], "-v") == 0)) { - verbose = true; - doing = DoingNone; - } else if (strcmp(av[i], "--use-stderr") == 0) { - /* tolerate legacy option */ - } else if (strcmp(av[i], "--") == 0) { - doing = DoingNative; - } else { - switch (doing) { - case DoingDir: - dir = cmSystemTools::CollapseFullPath(av[i]); - doing = DoingNone; - break; - case DoingTarget: - if (strlen(av[i]) == 0) { - std::cerr << "Warning: Argument number " << i - << " after --target option is empty." << std::endl; - } else { - targets.emplace_back(av[i]); - if (strcmp(av[i], "clean") == 0) { - foundClean = true; - } else { - foundNonClean = true; - } - } - if (foundClean && foundNonClean) { - std::cerr << "Error: Building 'clean' and other targets together " - "is not supported." - << std::endl; - dir.clear(); - } - break; - case DoingConfig: - config = av[i]; - doing = DoingNone; - break; - default: - std::cerr << "Unknown argument " << av[i] << std::endl; - dir.clear(); + return true; + } + return false; + }; + auto verboseLambda = [&](std::string const&) -> bool { + verbose = true; + return true; + }; + + using CommandArgument = + cmCommandLineArgument<bool(std::string const& value)>; + + std::vector<CommandArgument> arguments = { + CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, jLambda }, + CommandArgument{ "--parallel", CommandArgument::Values::ZeroOrOne, + parallelLambda }, + CommandArgument{ "-t", CommandArgument::Values::OneOrMore, targetLambda }, + CommandArgument{ "--target", CommandArgument::Values::OneOrMore, + targetLambda }, + CommandArgument{ "--config", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + config = value; + return true; + } }, + CommandArgument{ "--clean-first", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + cleanFirst = true; + return true; + } }, + CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, + CommandArgument{ "--verbose", CommandArgument::Values::Zero, + verboseLambda }, + /* legacy option no-op*/ + CommandArgument{ "--use-stderr", CommandArgument::Values::Zero, + [](std::string const&) -> bool { return true; } }, + CommandArgument{ "--", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + nativeOptionsPassed = true; + return true; + } }, + }; + + if (ac >= 3) { + dir = cmSystemTools::CollapseFullPath(av[2]); + + std::vector<std::string> inputArgs; + inputArgs.reserve(ac - 3); + cm::append(inputArgs, av + 3, av + ac); + + decltype(inputArgs.size()) i = 0; + for (; i < inputArgs.size() && !nativeOptionsPassed; ++i) { + + std::string const& arg = inputArgs[i]; + for (auto const& m : arguments) { + if (m.matches(arg) && m.parse(arg, i, inputArgs)) { break; + } } } + + if (nativeOptionsPassed) { + cm::append(nativeOptions, inputArgs.begin() + i, inputArgs.end()); + } + } + + if (foundClean && foundNonClean) { + std::cerr << "Error: Building 'clean' and other targets together " + "is not supported." + << std::endl; + dir.clear(); } if (jobs == cmake::NO_BUILD_PARALLEL_LEVEL) { @@ -658,60 +723,59 @@ int do_install(int ac, char const* const* av) bool strip = false; bool verbose = cmSystemTools::HasEnv("VERBOSE"); - enum Doing - { - DoingNone, - DoingDir, - DoingConfig, - DoingComponent, - DoingPrefix, - DoingDefaultDirectoryPermissions, + auto verboseLambda = [&](std::string const&) -> bool { + verbose = true; + return true; }; - Doing doing = DoingDir; + using CommandArgument = + cmCommandLineArgument<bool(std::string const& value)>; + + std::vector<CommandArgument> arguments = { + CommandArgument{ "--config", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + config = value; + return true; + } }, + CommandArgument{ "--component", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + component = value; + return true; + } }, + CommandArgument{ "--default-directory-permissions", + CommandArgument::Values::One, + [&](std::string const& value) -> bool { + defaultDirectoryPermissions = value; + return true; + } }, + CommandArgument{ "--prefix", CommandArgument::Values::One, + [&](std::string const& value) -> bool { + prefix = value; + return true; + } }, + CommandArgument{ "--strip", CommandArgument::Values::Zero, + [&](std::string const&) -> bool { + strip = true; + return true; + } }, + CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, + CommandArgument{ "--verbose", CommandArgument::Values::Zero, + verboseLambda } + }; - for (int i = 2; i < ac; ++i) { - if (strcmp(av[i], "--config") == 0) { - doing = DoingConfig; - } else if (strcmp(av[i], "--component") == 0) { - doing = DoingComponent; - } else if (strcmp(av[i], "--prefix") == 0) { - doing = DoingPrefix; - } else if (strcmp(av[i], "--strip") == 0) { - strip = true; - doing = DoingNone; - } else if ((strcmp(av[i], "--verbose") == 0) || - (strcmp(av[i], "-v") == 0)) { - verbose = true; - doing = DoingNone; - } else if (strcmp(av[i], "--default-directory-permissions") == 0) { - doing = DoingDefaultDirectoryPermissions; - } else { - switch (doing) { - case DoingDir: - dir = cmSystemTools::CollapseFullPath(av[i]); - doing = DoingNone; - break; - case DoingConfig: - config = av[i]; - doing = DoingNone; - break; - case DoingComponent: - component = av[i]; - doing = DoingNone; - break; - case DoingPrefix: - prefix = av[i]; - doing = DoingNone; - break; - case DoingDefaultDirectoryPermissions: - defaultDirectoryPermissions = av[i]; - doing = DoingNone; - break; - default: - std::cerr << "Unknown argument " << av[i] << std::endl; - dir.clear(); + if (ac >= 3) { + dir = cmSystemTools::CollapseFullPath(av[2]); + + std::vector<std::string> inputArgs; + inputArgs.reserve(ac - 3); + cm::append(inputArgs, av + 3, av + ac); + for (decltype(inputArgs.size()) i = 0; i < inputArgs.size(); ++i) { + + std::string const& arg = inputArgs[i]; + for (auto const& m : arguments) { + if (m.matches(arg) && m.parse(arg, i, inputArgs)) { break; + } } } } |