diff options
102 files changed, 2498 insertions, 1840 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 72ad7f5..fafe536 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,7 +272,7 @@ if(CMake_RUN_IWYU) message(FATAL_ERROR "CMake_RUN_IWYU is ON but include-what-you-use is not found!") endif() set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE - "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp") + "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w") endif() diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index c81ba59..96d5c7d 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.11 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0072: FindOpenGL prefers GLVND by default when available. </policy/CMP0072> + Policies Introduced by CMake 3.10 ================================= diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 1927c37..0451466 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -290,6 +290,7 @@ Variables that Control the Build /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX + /variable/CMAKE_CUDA_SEPARABLE_COMPILATION /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_ENABLE_EXPORTS /variable/CMAKE_EXE_LINKER_FLAGS diff --git a/Help/policy/CMP0072.rst b/Help/policy/CMP0072.rst new file mode 100644 index 0000000..3abbad7 --- /dev/null +++ b/Help/policy/CMP0072.rst @@ -0,0 +1,26 @@ +CMP0072 +------- + +:module:`FindOpenGL` prefers GLVND by default when available. + +The :module:`FindOpenGL` module provides an ``OpenGL::GL`` target and an +``OPENGL_LIBRARIES`` variable for projects to use for legacy GL interfaces. +When both a legacy GL library (e.g. ``libGL.so``) and GLVND libraries +for OpenGL and GLX (e.g. ``libOpenGL.so`` and ``libGLX.so``) are available, +the module must choose between them. It documents an ``OpenGL_GL_PREFERENCE`` +variable that can be used to specify an explicit preference. When no such +preference is set, the module must choose a default preference. + +CMake 3.11 and above prefer to choose GLVND libraries. This policy provides +compatibility with projects that expect the legacy GL library to be used. + +The ``OLD`` behavior for this policy is to set ``OpenGL_GL_PREFERENCE`` to +``LEGACY``. The ``NEW`` behavior for this policy is to set +``OpenGL_GL_PREFERENCE`` to ``GLVND``. + +This policy was introduced in CMake version 3.11. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_tgt/COMPILE_FLAGS.rst b/Help/prop_tgt/COMPILE_FLAGS.rst index 1a5389e..8fe651b 100644 --- a/Help/prop_tgt/COMPILE_FLAGS.rst +++ b/Help/prop_tgt/COMPILE_FLAGS.rst @@ -8,4 +8,4 @@ build sources within the target. Use :prop_tgt:`COMPILE_DEFINITIONS` to pass additional preprocessor definitions. This property is deprecated. Use the :prop_tgt:`COMPILE_OPTIONS` -property or the command:`target_compile_options` command instead. +property or the :command:`target_compile_options` command instead. diff --git a/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst b/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst index 1c7dd80..d306d7f 100644 --- a/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst +++ b/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst @@ -11,3 +11,7 @@ For instance: .. code-block:: cmake set_property(TARGET myexe PROPERTY CUDA_SEPARABLE_COMPILATION ON) + +This property is initialized by the value of the +:variable:`CMAKE_CUDA_SEPARABLE_COMPILATION` variable if it is set when a +target is created. diff --git a/Help/release/dev/FindOpenGL-glvnd-policy.rst b/Help/release/dev/FindOpenGL-glvnd-policy.rst new file mode 100644 index 0000000..3348acf --- /dev/null +++ b/Help/release/dev/FindOpenGL-glvnd-policy.rst @@ -0,0 +1,5 @@ +FindOpenGL-glvnd-policy +----------------------- + +* The :module:`FindOpenGL` module now prefers GLVND libraries if available. + See policy :policy:`CMP0072`. diff --git a/Help/release/dev/cuda-sep-comp-var.rst b/Help/release/dev/cuda-sep-comp-var.rst new file mode 100644 index 0000000..23536ef --- /dev/null +++ b/Help/release/dev/cuda-sep-comp-var.rst @@ -0,0 +1,6 @@ +cuda-sep-comp-var +----------------- + +* A :variable:`CMAKE_CUDA_SEPARABLE_COMPILATION` variable was added to + initialize the :prop_tgt:`CUDA_SEPARABLE_COMPILATION` target property + on targets when they are created. diff --git a/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst b/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst new file mode 100644 index 0000000..eef92fb --- /dev/null +++ b/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst @@ -0,0 +1,6 @@ +CMAKE_CUDA_SEPARABLE_COMPILATION +-------------------------------- + +Default value for :prop_tgt:`CUDA_SEPARABLE_COMPILATION` target property. +This variable is used to initialize the property on each target as it is +created. diff --git a/Modules/AutoRccInfo.cmake.in b/Modules/AutoRccInfo.cmake.in new file mode 100644 index 0000000..5457a6f --- /dev/null +++ b/Modules/AutoRccInfo.cmake.in @@ -0,0 +1,11 @@ +# Meta +set(ARCC_MULTI_CONFIG @_multi_config@) +# Directories and files +set(ARCC_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") +set(ARCC_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") +set(ARCC_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") +set(ARCC_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") +set(ARCC_BUILD_DIR @_build_dir@) +# Qt environment +set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@) +set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@) diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 7f4b398..9a4a06d 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -9,12 +9,11 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ set(AM_BUILD_DIR @_build_dir@) set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) +set(AM_SETTINGS_FILE @_settings_file@) # Qt environment set(AM_QT_VERSION_MAJOR @_qt_version_major@) -set(AM_QT_VERSION_MINOR @_qt_version_minor@) set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) -set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) set(AM_MOC_DEFINITIONS @_moc_compile_defs@) @@ -30,8 +29,3 @@ set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) set(AM_UIC_SEARCH_PATHS @_uic_search_paths@) -# RCC settings -set(AM_RCC_SOURCES @_rcc_files@) -set(AM_RCC_BUILDS @_rcc_builds@) -set(AM_RCC_OPTIONS @_rcc_options@) -set(AM_RCC_INPUTS @_rcc_inputs@) diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index ea7dc02..812917f 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -338,7 +338,7 @@ function(cpack_encode_variables) set(value "${${var}}") endif() - string(APPEND commands "\nSET(${var} \"${value}\")") + string(APPEND commands "\nset(${var} \"${value}\")") endif() endforeach() diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake index 2374fbd..6c122e5 100644 --- a/Modules/CPackComponent.cmake +++ b/Modules/CPackComponent.cmake @@ -66,7 +66,7 @@ # the component differently depending on the value of this variable: # # * ONE_PER_GROUP (default): creates one package file per component group -# * ALL_COMPONENTS_IN_ONE : creates a single package with all (requested) component +# * ALL_COMPONENTS_IN_ONE : creates a single package with all (requested) components # * IGNORE : creates one package per component, i.e. IGNORE component group # # One can specify different grouping for different CPack generator by diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake index 9063492..91db5af 100644 --- a/Modules/FindOpenGL.cmake +++ b/Modules/FindOpenGL.cmake @@ -99,11 +99,13 @@ # If the GLVND OpenGL and GLX libraries are available, prefer them. # This forces ``OPENGL_gl_LIBRARY`` to be empty. # This is the default if components were requested (since components -# correspond to GLVND libraries). +# correspond to GLVND libraries) or if policy :policy:`CMP0072` is +# set to ``NEW``. # # ``LEGACY`` # Prefer to use the legacy libGL library, if available. -# This is the default if no components were requested. +# This is the default if no components were requested and +# policy :policy:`CMP0072` is not set to ``NEW``. # # For EGL targets the client must rely on GLVND support on the user's system. # Linking should use the ``OpenGL::OpenGL OpenGL::EGL`` targets. Using GLES* @@ -220,6 +222,7 @@ else() /usr/shlib /usr/X11R6/lib ) + set(_OpenGL_GL_POLICY_WARN 0) if(NOT DEFINED OpenGL_GL_PREFERENCE) set(OpenGL_GL_PREFERENCE "") endif() @@ -237,8 +240,17 @@ else() set(OpenGL_GL_PREFERENCE "GLVND") else() # No preference was explicitly specified and no GLVND components were - # requested. Prefer libGL for legacy GL. - set(OpenGL_GL_PREFERENCE "LEGACY") + # requested. Use a policy to choose the default. + cmake_policy(GET CMP0072 _OpenGL_GL_POLICY) + if("x${_OpenGL_GL_POLICY}x" STREQUAL "xNEWx") + set(OpenGL_GL_PREFERENCE "GLVND") + else() + set(OpenGL_GL_PREFERENCE "LEGACY") + if("x${_OpenGL_GL_POLICY}x" STREQUAL "xx") + set(_OpenGL_GL_POLICY_WARN 1) + endif() + endif() + unset(_OpenGL_GL_POLICY) endif() if("x${OpenGL_GL_PREFERENCE}x" STREQUAL "xGLVNDx" AND OPENGL_opengl_LIBRARY AND OPENGL_glx_LIBRARY) @@ -257,6 +269,23 @@ else() ) endif() + if(_OpenGL_GL_POLICY_WARN AND OPENGL_gl_LIBRARY AND OPENGL_opengl_LIBRARY AND OPENGL_glx_LIBRARY) + message(AUTHOR_WARNING + "Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when available. " + "Run \"cmake --help-policy CMP0072\" for policy details. " + "Use the cmake_policy command to set the policy and suppress this warning." + "\n" + "FindOpenGL found both a legacy GL library:\n" + " OPENGL_gl_LIBRARY: ${OPENGL_gl_LIBRARY}\n" + "and GLVND libraries for OpenGL and GLX:\n" + " OPENGL_opengl_LIBRARY: ${OPENGL_opengl_LIBRARY}\n" + " OPENGL_glx_LIBRARY: ${OPENGL_glx_LIBRARY}\n" + "OpenGL_GL_PREFERENCE has not been set to \"GLVND\" or \"LEGACY\", so for " + "compatibility with CMake 3.10 and below the legacy GL library will be used." + ) + endif() + unset(_OpenGL_GL_POLICY_WARN) + # FPHSA cannot handle "this OR that is required", so we conditionally set what # it must look for. First clear any previous config we might have done: set(_OpenGL_REQUIRED_VARS) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 54e5063..6c60675 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -311,11 +311,14 @@ set(SRCS cmPropertyMap.h cmQtAutoGen.cxx cmQtAutoGen.h - cmQtAutoGenDigest.h + cmQtAutoGenerator.cxx + cmQtAutoGenerator.h cmQtAutoGeneratorInitializer.cxx cmQtAutoGeneratorInitializer.h - cmQtAutoGenerators.cxx - cmQtAutoGenerators.h + cmQtAutoGeneratorMocUic.cxx + cmQtAutoGeneratorMocUic.h + cmQtAutoGeneratorRcc.cxx + cmQtAutoGeneratorRcc.h cmRST.cxx cmRST.h cmScriptGenerator.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1f9db43..eaa4679 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 10) -set(CMake_VERSION_PATCH 20171117) +set(CMake_VERSION_PATCH 20171120) #set(CMake_VERSION_RC 1) diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 4ad4831..f25c9c3 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -407,7 +407,7 @@ int cmCTestBuildHandler::ProcessHandler() // Remember start build time this->StartBuild = this->CTest->CurrentTime(); - this->StartBuildTime = cmSystemTools::GetTime(); + this->StartBuildTime = std::chrono::system_clock::now(); int retVal = 0; int res = cmsysProcess_State_Exited; if (!this->CTest->GetShowOnly()) { @@ -421,7 +421,7 @@ int cmCTestBuildHandler::ProcessHandler() // Remember end build time and calculate elapsed time this->EndBuild = this->CTest->CurrentTime(); - this->EndBuildTime = cmSystemTools::GetTime(); + this->EndBuildTime = std::chrono::system_clock::now(); auto elapsed_build_time = std::chrono::steady_clock::now() - elapsed_time_start; @@ -488,8 +488,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml) this->CTest->GenerateSubprojectsOutput(xml); xml.StartElement("Build"); xml.Element("StartDateTime", this->StartBuild); - xml.Element("StartBuildTime", - static_cast<unsigned int>(this->StartBuildTime)); + xml.Element("StartBuildTime", this->StartBuildTime); xml.Element("BuildCommand", this->GetMakeCommand()); } @@ -644,7 +643,7 @@ void cmCTestBuildHandler::GenerateXMLFooter( xml.EndElement(); // Log xml.Element("EndDateTime", this->EndBuild); - xml.Element("EndBuildTime", static_cast<unsigned int>(this->EndBuildTime)); + xml.Element("EndBuildTime", this->EndBuildTime); xml.Element( "ElapsedMinutes", std::chrono::duration_cast<std::chrono::minutes>(elapsed_build_time) diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index 9a29d6d..d1b9b2e 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -94,8 +94,8 @@ private: std::string StartBuild; std::string EndBuild; - double StartBuildTime; - double EndBuildTime; + std::chrono::system_clock::time_point StartBuildTime; + std::chrono::system_clock::time_point EndBuildTime; std::vector<std::string> CustomErrorMatches; std::vector<std::string> CustomErrorExceptions; diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index e732f9f..ab77986 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -4,7 +4,6 @@ #include "cmCTest.h" #include "cmGeneratedFileStream.h" -#include "cmSystemTools.h" #include "cmXMLWriter.h" #include <chrono> @@ -57,8 +56,7 @@ int cmCTestConfigureHandler::ProcessHandler() return 1; } std::string start_time = this->CTest->CurrentTime(); - unsigned int start_time_time = - static_cast<unsigned int>(cmSystemTools::GetTime()); + auto start_time_time = std::chrono::system_clock::now(); cmGeneratedFileStream ofs; this->StartLogFile("Configure", ofs); @@ -84,8 +82,7 @@ int cmCTestConfigureHandler::ProcessHandler() xml.Element("Log", output); xml.Element("ConfigureStatus", retVal); xml.Element("EndDateTime", this->CTest->CurrentTime()); - xml.Element("EndConfigureTime", - static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("EndConfigureTime", std::chrono::system_clock::now()); xml.Element("ElapsedMinutes", std::chrono::duration_cast<std::chrono::minutes>( std::chrono::steady_clock::now() - elapsed_time_start) diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 85f6ce9..bbfe9bd 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -175,14 +175,13 @@ void cmCTestCoverageHandler::StartCoverageLogXML(cmXMLWriter& xml) this->CTest->StartXML(xml, this->AppendXML); xml.StartElement("CoverageLog"); xml.Element("StartDateTime", this->CTest->CurrentTime()); - xml.Element("StartTime", - static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("StartTime", std::chrono::system_clock::now()); } void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml) { xml.Element("EndDateTime", this->CTest->CurrentTime()); - xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("EndTime", std::chrono::system_clock::now()); xml.EndElement(); // CoverageLog this->CTest->EndXML(xml); } @@ -283,8 +282,7 @@ int cmCTestCoverageHandler::ProcessHandler() } std::string coverage_start_time = this->CTest->CurrentTime(); - unsigned int coverage_start_time_time = - static_cast<unsigned int>(cmSystemTools::GetTime()); + auto coverage_start_time_time = std::chrono::system_clock::now(); std::string sourceDir = this->CTest->GetCTestConfiguration("SourceDirectory"); std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory"); @@ -622,8 +620,7 @@ int cmCTestCoverageHandler::ProcessHandler() covSumXML.Element("LOC", total_lines); covSumXML.Element("PercentCoverage", percent_coverage); covSumXML.Element("EndDateTime", end_time); - covSumXML.Element("EndTime", - static_cast<unsigned int>(cmSystemTools::GetTime())); + covSumXML.Element("EndTime", std::chrono::system_clock::now()); covSumXML.Element("ElapsedMinutes", std::chrono::duration_cast<std::chrono::minutes>( std::chrono::steady_clock::now() - elapsed_time_start) @@ -1970,8 +1967,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( std::string coverage_start_time = this->CTest->CurrentTime(); xml.StartElement("Coverage"); xml.Element("StartDateTime", coverage_start_time); - xml.Element("StartTime", - static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("StartTime", std::chrono::system_clock::now()); std::string stdline; std::string errline; // expected output: @@ -2092,7 +2088,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( xml.Element("LOC", total_functions); xml.Element("PercentCoverage", SAFEDIV(percent_coverage, number_files)); xml.Element("EndDateTime", end_time); - xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("EndTime", std::chrono::system_clock::now()); xml.Element("ElapsedMinutes", std::chrono::duration_cast<std::chrono::minutes>( std::chrono::steady_clock::now() - elapsed_time_start) diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 6534fd1..86fee7a 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -1069,6 +1069,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, if (subproject) { str << "subproject=" << curl.Escape(subproject) << "&"; } + auto timeNow = + std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); str << "stamp=" << curl.Escape(this->CTest->GetCurrentTag()) << "-" << curl.Escape(this->CTest->GetTestModelString()) << "&" << "model=" << curl.Escape(this->CTest->GetTestModelString()) << "&" @@ -1077,8 +1079,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, << "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site")) << "&" << "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&" - << "starttime=" << static_cast<int>(cmSystemTools::GetTime()) << "&" - << "endtime=" << static_cast<int>(cmSystemTools::GetTime()) << "&" + << "starttime=" << timeNow << "&" + << "endtime=" << timeNow << "&" << "datafilesmd5[0]=" << md5sum << "&" << "type=" << curl.Escape(typeString); std::string fields = str.str(); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index b814e35..e7c719c 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1204,7 +1204,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, { this->ComputeTestList(); this->StartTest = this->CTest->CurrentTime(); - this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime()); + this->StartTestTime = std::chrono::system_clock::now(); auto elapsed_time_start = std::chrono::steady_clock::now(); cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs() @@ -1271,7 +1271,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, } delete parallel; this->EndTest = this->CTest->CurrentTime(); - this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime()); + this->EndTestTime = std::chrono::system_clock::now(); this->ElapsedTestingTime = std::chrono::steady_clock::now() - elapsed_time_start; *this->LogFile << "End testing: " << this->CTest->CurrentTime() << std::endl; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index af85e72..8572e7b 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -207,8 +207,8 @@ protected: std::vector<std::string> CustomTestsIgnore; std::string StartTest; std::string EndTest; - unsigned int StartTestTime; - unsigned int EndTestTime; + std::chrono::system_clock::time_point StartTestTime; + std::chrono::system_clock::time_point EndTestTime; bool MemCheck; int CustomMaximumPassedTestOutputSize; int CustomMaximumFailedTestOutputSize; diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 2bd0253..f86d4a3 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -177,8 +177,7 @@ int cmCTestUpdateHandler::ProcessHandler() return -1; } std::string start_time = this->CTest->CurrentTime(); - unsigned int start_time_time = - static_cast<unsigned int>(cmSystemTools::GetTime()); + auto start_time_time = std::chrono::system_clock::now(); auto elapsed_time_start = std::chrono::steady_clock::now(); bool updated = vc->Update(); @@ -226,7 +225,7 @@ int cmCTestUpdateHandler::ProcessHandler() cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet); std::string end_time = this->CTest->CurrentTime(); xml.Element("EndDateTime", end_time); - xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("EndTime", std::chrono::system_clock::now()); xml.Element("ElapsedMinutes", std::chrono::duration_cast<std::chrono::minutes>( std::chrono::steady_clock::now() - elapsed_time_start) diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 847a416..fcdc632 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -54,10 +54,8 @@ bool cmAuxSourceDirectoryCommand::InitialPass( std::string ext = file.substr(dotpos + 1); std::string base = file.substr(0, dotpos); // Process only source files - std::vector<std::string> const& srcExts = - this->Makefile->GetCMakeInstance()->GetSourceExtensions(); - if (!base.empty() && - std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) { + auto cm = this->Makefile->GetCMakeInstance(); + if (!base.empty() && cm->IsSourceExtension(ext)) { std::string fullname = templateDirectory; fullname += "/"; fullname += file; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 92da9ab..d358e3d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -12,7 +12,7 @@ #include "cmsys/String.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> -#include <cstdint> +#include <chrono> #include <ctype.h> #include <iostream> #include <map> @@ -1418,7 +1418,7 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, std::string note_time = this->CurrentTime(); xml.StartElement("Note"); xml.Attribute("Name", file); - xml.Element("Time", static_cast<uint64_t>(cmSystemTools::GetTime())); + xml.Element("Time", std::chrono::system_clock::now()); xml.Element("DateTime", note_time); xml.StartElement("Text"); cmsys::ifstream ifs(file.c_str()); diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx index f482412..28ba12c 100644 --- a/Source/cmConnection.cxx +++ b/Source/cmConnection.cxx @@ -97,11 +97,10 @@ void cmEventBasedConnection::ReadData(const std::string& data) this->RawReadBuffer += data; if (BufferStrategy) { std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer); - do { + while (!packet.empty()) { ProcessRequest(packet); packet = BufferStrategy->BufferMessage(this->RawReadBuffer); - } while (!packet.empty()); - + } } else { ProcessRequest(this->RawReadBuffer); this->RawReadBuffer.clear(); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 9c9b75b..76fc8f1 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -345,8 +345,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( all_files_map_t allFiles; std::vector<std::string> cFiles; - std::vector<std::string> const& srcExts = - this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions(); + auto cm = this->GlobalGenerator->GetCMakeInstance(); for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); @@ -377,12 +376,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( std::string lang = s->GetLanguage(); if (lang == "C" || lang == "CXX") { std::string const& srcext = s->GetExtension(); - for (std::string const& ext : srcExts) { - if (srcext == ext) { - isCFile = true; - break; - } - } + isCFile = cm->IsSourceExtension(srcext); } std::string const& fullPath = s->GetFullPath(); diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 5a02d54..383942b 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -198,8 +198,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( std::map<std::string, cmSourceFile*>& cFiles, std::set<std::string>& otherFiles) { - const std::vector<std::string>& srcExts = - this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions(); + auto cm = this->GlobalGenerator->GetCMakeInstance(); std::string projectType; switch (gt->GetType()) { @@ -233,12 +232,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( std::string lang = s->GetLanguage(); if (lang == "C" || lang == "CXX") { std::string const& srcext = s->GetExtension(); - for (std::string const& ext : srcExts) { - if (srcext == ext) { - isCFile = true; - break; - } - } + isCFile = cm->IsSourceExtension(srcext); } // then put it accordingly into one of the two containers diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index a31e415..b3e3393 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -489,7 +489,7 @@ void cmGhsMultiTargetGenerator::WriteSources( char const* sourceFullPath = (*si)->GetFullPath().c_str(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups); - std::string sgPath(sourceGroup->GetFullName()); + std::string sgPath = sourceGroup->GetFullName(); cmSystemTools::ConvertToUnixSlashes(sgPath); cmGlobalGhsMultiGenerator::AddFilesUpToPath( this->GetFolderBuildStreams(), &this->FolderBuildStreams, @@ -608,7 +608,7 @@ std::string cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory( cmSourceGroup* sourceGroup = localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath, sourceGroups); - std::string const sgPath(sourceGroup->GetFullName()); + std::string const& sgPath = sourceGroup->GetFullName(); dir_max += sgPath; dir_max += "/Objs/libs/"; dir_max += generatorTarget->Target->GetName(); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index eba95f5..6e903fb 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1314,7 +1314,10 @@ bool cmGlobalGenerator::Compute() #ifdef CMAKE_BUILD_WITH_CMAKE // Iterate through all targets and set up automoc for those which have // the AUTOMOC, AUTOUIC or AUTORCC property set - cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets(); + auto autogenInits = this->CreateQtAutoGenInitializers(); + for (auto& autoGen : autogenInits) { + autoGen->InitCustomTargets(); + } #endif // Add generator specific helper commands @@ -1335,10 +1338,11 @@ bool cmGlobalGenerator::Compute() } #ifdef CMAKE_BUILD_WITH_CMAKE - for (cmQtAutoGenDigestUP const& digest : autogenDigests) { - cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest); + for (auto& autoGen : autogenInits) { + autoGen->SetupCustomTargets(); + autoGen.reset(nullptr); } - autogenDigests.clear(); + autogenInits.clear(); #endif for (cmLocalGenerator* localGen : this->LocalGenerators) { @@ -1469,9 +1473,10 @@ bool cmGlobalGenerator::ComputeTargetDepends() return true; } -cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets() +std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> +cmGlobalGenerator::CreateQtAutoGenInitializers() { - cmQtAutoGenDigestUPV autogenDigests; + std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> autogenInits; #ifdef CMAKE_BUILD_WITH_CMAKE for (cmLocalGenerator* localGen : this->LocalGenerators) { @@ -1507,25 +1512,12 @@ cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets() continue; } - { - cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target)); - digest->QtVersionMajor = std::move(qtVersionMajor); - digest->QtVersionMinor = - cmQtAutoGeneratorInitializer::GetQtMinorVersion( - target, digest->QtVersionMajor); - digest->MocEnabled = mocEnabled; - digest->UicEnabled = uicEnabled; - digest->RccEnabled = rccEnabled; - autogenDigests.emplace_back(std::move(digest)); - } + autogenInits.emplace_back(new cmQtAutoGeneratorInitializer( + target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor)); } } - // Initialize autogen targets - for (const cmQtAutoGenDigestUP& digest : autogenDigests) { - cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest); - } #endif - return autogenDigests; + return autogenInits; } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 8fcb533..99f33e5 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -15,7 +15,6 @@ #include "cmCustomCommandLines.h" #include "cmExportSetMap.h" -#include "cmQtAutoGenDigest.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -33,6 +32,7 @@ class cmLinkLineComputer; class cmLocalGenerator; class cmMakefile; class cmOutputConverter; +class cmQtAutoGeneratorInitializer; class cmSourceFile; class cmStateDirectory; class cmake; @@ -433,7 +433,8 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; // Qt auto generators - cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets(); + std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> + CreateQtAutoGenInitializers(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index dfc1bed..41fe5d2 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2797,13 +2797,13 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( // If it's the default source group (empty name) then put the source file // directly in the tgroup... // - if (std::string(sg->GetFullName()).empty()) { + if (sg->GetFullName().empty()) { this->GroupNameMap[s] = tgroup; return tgroup; } // It's a recursive folder structure, let's find the real parent group - if (std::string(sg->GetFullName()) != std::string(sg->GetName())) { + if (sg->GetFullName() != sg->GetName()) { std::string curr_folder = target; curr_folder += "/"; for (auto const& folder : diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index beb80f2..f01ed7a 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1600,7 +1600,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup( } // If the group has a name, write the header. - std::string name = sg->GetName(); + std::string const& name = sg->GetName(); if (!name.empty()) { this->WriteVCProjBeginGroup(fout, name.c_str(), ""); } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 4109b90..0855e79 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1950,7 +1950,7 @@ cmSourceGroup* cmMakefile::GetSourceGroup( // first look for source group starting with the same as the one we want for (cmSourceGroup const& srcGroup : this->SourceGroups) { - std::string sgName = srcGroup.GetName(); + std::string const& sgName = srcGroup.GetName(); if (sgName == name[0]) { sg = const_cast<cmSourceGroup*>(&srcGroup); break; @@ -2014,7 +2014,8 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, } // build the whole source group path for (++i; i <= lastElement; ++i) { - sg->AddChild(cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName())); + sg->AddChild( + cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName().c_str())); sg = sg->LookupChild(name[i].c_str()); } @@ -3120,9 +3121,16 @@ void cmMakefile::SetArgcArgv(const std::vector<std::string>& args) cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const { cmSourceFileLocation sfl(this, sourceName); - for (cmSourceFile* sf : this->SourceFiles) { - if (sf->Matches(sfl)) { - return sf; + auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName()); +#if defined(_WIN32) || defined(__APPLE__) + name = cmSystemTools::LowerCase(name); +#endif + auto sfsi = this->SourceFileSearchIndex.find(name); + if (sfsi != this->SourceFileSearchIndex.end()) { + for (auto sf : sfsi->second) { + if (sf->Matches(sfl)) { + return sf; + } } } return nullptr; @@ -3136,6 +3144,14 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName, sf->SetProperty("GENERATED", "1"); } this->SourceFiles.push_back(sf); + + auto name = + this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName()); +#if defined(_WIN32) || defined(__APPLE__) + name = cmSystemTools::LowerCase(name); +#endif + this->SourceFileSearchIndex[name].push_back(sf); + return sf; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 6867c02..7c27aef 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -821,7 +821,18 @@ protected: // libraries, classes, and executables mutable cmTargets Targets; std::map<std::string, std::string> AliasTargets; - std::vector<cmSourceFile*> SourceFiles; + + typedef std::vector<cmSourceFile*> SourceFileVec; + SourceFileVec SourceFiles; + + // Because cmSourceFile names are compared in a fuzzy way (see + // cmSourceFileLocation::Match()) we can't have a straight mapping from + // filename to cmSourceFile. To make lookups more efficient we store the + // Name portion of the cmSourceFileLocation and then compare on the list of + // cmSourceFiles that might match that name. Note that on platforms which + // have a case-insensitive filesystem we store the key in all lowercase. + typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap; + SourceFileMap SourceFileSearchIndex; // Tests std::map<std::string, cmTest*> Tests; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index f614dca..c39f927 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -211,7 +211,10 @@ class cmMakefile; "Define file(GENERATE) behavior for relative paths.", 3, 10, 0, \ cmPolicies::WARN) \ SELECT(POLICY, CMP0071, "Let AUTOMOC and AUTOUIC process GENERATED files.", \ - 3, 10, 0, cmPolicies::WARN) + 3, 10, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0072, \ + "FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \ + cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 9dc77ac..b9dd392 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -80,16 +80,6 @@ void MergeOptions(std::vector<std::string>& baseOpts, baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end()); } -static std::string utilStripCR(std::string const& line) -{ - // Strip CR characters rcc may have printed (possibly more than one!). - std::string::size_type cr = line.find('\r'); - if (cr != std::string::npos) { - return line.substr(0, cr); - } - return line; -} - /// @brief Reads the resource files list from from a .qrc file - Qt4 version /// @return True if the .qrc file was successfully parsed static bool RccListInputsQt4(std::string const& fileName, @@ -107,10 +97,10 @@ static bool RccListInputsQt4(std::string const& fileName, qrcContents = osst.str(); } else { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc file not readable:\n" - << " " << cmQtAutoGen::Quoted(fileName) << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc file not readable:\n "; + err += cmQtAutoGen::Quoted(fileName); + err += "\n"; } allGood = false; } @@ -146,6 +136,7 @@ static bool RccListInputsQt4(std::string const& fileName, /// @brief Reads the resource files list from from a .qrc file - Qt5 version /// @return True if the .qrc file was successfully parsed static bool RccListInputsQt5(std::string const& rccCommand, + std::vector<std::string> const& rccListOptions, std::string const& fileName, std::vector<std::string>& files, std::string* errorMessage) @@ -155,24 +146,6 @@ static bool RccListInputsQt5(std::string const& rccCommand, return false; } - // Read rcc features - bool hasDashDashList = false; - { - std::vector<std::string> command; - command.push_back(rccCommand); - command.push_back("--help"); - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &rccStdOut, &rccStdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - hasDashDashList = true; - } - } - std::string const fileDir = cmSystemTools::GetFilenamePath(fileName); std::string const fileNameName = cmSystemTools::GetFilenameName(fileName); @@ -184,7 +157,8 @@ static bool RccListInputsQt5(std::string const& rccCommand, { std::vector<std::string> command; command.push_back(rccCommand); - command.push_back(hasDashDashList ? "--list" : "-list"); + command.insert(command.end(), rccListOptions.begin(), + rccListOptions.end()); command.push_back(fileNameName); result = cmSystemTools::RunSingleCommand( command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(), @@ -192,22 +166,32 @@ static bool RccListInputsQt5(std::string const& rccCommand, } if (!result || retVal) { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc list process failed for\n " << cmQtAutoGen::Quoted(fileName) - << "\n" - << rccStdOut << "\n" - << rccStdErr << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc list process failed for:\n "; + err += cmQtAutoGen::Quoted(fileName); + err += "\n"; + err += rccStdOut; + err += "\n"; + err += rccStdErr; + err += "\n"; } return false; } + // Lambda to strip CR characters + auto StripCR = [](std::string& line) { + std::string::size_type cr = line.find('\r'); + if (cr != std::string::npos) { + line = line.substr(0, cr); + } + }; + // Parse rcc std output { std::istringstream ostr(rccStdOut); std::string oline; while (std::getline(ostr, oline)) { - oline = utilStripCR(oline); + StripCR(oline); if (!oline.empty()) { files.push_back(oline); } @@ -218,17 +202,17 @@ static bool RccListInputsQt5(std::string const& rccCommand, std::istringstream estr(rccStdErr); std::string eline; while (std::getline(estr, eline)) { - eline = utilStripCR(eline); + StripCR(eline); if (cmHasLiteralPrefix(eline, "RCC: Error in")) { static std::string searchString = "Cannot find file '"; std::string::size_type pos = eline.find(searchString); if (pos == std::string::npos) { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc lists unparsable output:\n" - << cmQtAutoGen::Quoted(eline) << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc lists unparsable output:\n"; + err += cmQtAutoGen::Quoted(eline); + err += "\n"; } return false; } @@ -349,25 +333,26 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts, MergeOptions(baseOpts, newOpts, valueOpts, isQt5); } -bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion, - std::string const& rccCommand, +bool cmQtAutoGen::RccListInputs(std::string const& rccCommand, + std::vector<std::string> const& rccListOptions, std::string const& fileName, std::vector<std::string>& files, std::string* errorMessage) { bool allGood = false; if (cmSystemTools::FileExists(fileName.c_str())) { - if (qtMajorVersion == "4") { + if (rccListOptions.empty()) { allGood = RccListInputsQt4(fileName, files, errorMessage); } else { - allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage); + allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files, + errorMessage); } } else { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc file does not exist:\n" - << " " << cmQtAutoGen::Quoted(fileName) << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc resource file does not exist:\n "; + err += cmQtAutoGen::Quoted(fileName); + err += "\n"; } } return allGood; diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index acc092f..e769e93 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -61,9 +61,9 @@ public: /// @brief Reads the resource files list from from a .qrc file /// @arg fileName Must be the absolute path of the .qrc file - /// @return True if the rcc file was successfully parsed - static bool RccListInputs(std::string const& qtMajorVersion, - std::string const& rccCommand, + /// @return True if the rcc file was successfully read + static bool RccListInputs(std::string const& rccCommand, + std::vector<std::string> const& rccListOptions, std::string const& fileName, std::vector<std::string>& files, std::string* errorMessage = nullptr); diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h deleted file mode 100644 index 677c397..0000000 --- a/Source/cmQtAutoGenDigest.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenDigest_h -#define cmQtAutoGenDigest_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <memory> -#include <string> -#include <vector> - -class cmGeneratorTarget; - -class cmQtAutoGenDigestQrc -{ -public: - cmQtAutoGenDigestQrc() - : Generated(false) - , Unique(false) - { - } - -public: - std::string QrcFile; - std::string QrcName; - std::string PathChecksum; - std::string RccFile; - bool Generated; - bool Unique; - std::vector<std::string> Options; - std::vector<std::string> Resources; -}; - -/** \class cmQtAutoGenDigest - * \brief Filtered set of QtAutogen variables for a specific target - */ -class cmQtAutoGenDigest -{ -public: - cmQtAutoGenDigest(cmGeneratorTarget* target) - : Target(target) - , MocEnabled(false) - , UicEnabled(false) - , RccEnabled(false) - { - } - -public: - cmGeneratorTarget* Target; - std::string QtVersionMajor; - std::string QtVersionMinor; - bool MocEnabled; - bool UicEnabled; - bool RccEnabled; - std::vector<std::string> Headers; - std::vector<std::string> Sources; - std::vector<cmQtAutoGenDigestQrc> Qrcs; -}; - -// Utility types -typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP; -typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV; - -#endif diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx new file mode 100644 index 0000000..52193af --- /dev/null +++ b/Source/cmQtAutoGenerator.cxx @@ -0,0 +1,320 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" + +#include "cmsys/FStream.hxx" +#include "cmsys/Terminal.h" + +#include "cmAlgorithms.h" +#include "cmGlobalGenerator.h" +#include "cmMakefile.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" +#include "cmSystemTools.h" +#include "cmake.h" + +// -- Static functions + +static std::string HeadLine(std::string const& title) +{ + std::string head = title; + head += '\n'; + head.append(head.size() - 1, '-'); + head += '\n'; + return head; +} + +static std::string QuotedCommand(std::vector<std::string> const& command) +{ + std::string res; + for (std::string const& item : command) { + if (!res.empty()) { + res.push_back(' '); + } + std::string const cesc = cmQtAutoGen::Quoted(item); + if (item.empty() || (cesc.size() > (item.size() + 2)) || + (cesc.find(' ') != std::string::npos)) { + res += cesc; + } else { + res += item; + } + } + return res; +} + +// -- Class methods + +cmQtAutoGenerator::cmQtAutoGenerator() + : Verbose(cmSystemTools::HasEnv("VERBOSE")) + , ColorOutput(true) +{ + { + std::string colorEnv; + cmSystemTools::GetEnv("COLOR", colorEnv); + if (!colorEnv.empty()) { + this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str()); + } + } +} + +bool cmQtAutoGenerator::Run(std::string const& infoFile, + std::string const& config) +{ + // Info settings + this->InfoFile = infoFile; + cmSystemTools::ConvertToUnixSlashes(this->InfoFile); + this->InfoDir = cmSystemTools::GetFilenamePath(infoFile); + this->InfoConfig = config; + + cmake cm(cmake::RoleScript); + cm.SetHomeOutputDirectory(this->InfoDir); + cm.SetHomeDirectory(this->InfoDir); + cm.GetCurrentSnapshot().SetDefaultDefinitions(); + cmGlobalGenerator gg(&cm); + + cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); + snapshot.GetDirectory().SetCurrentBinary(this->InfoDir); + snapshot.GetDirectory().SetCurrentSource(this->InfoDir); + + auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot); + gg.SetCurrentMakefile(makefile.get()); + + return this->Process(makefile.get()); +} + +void cmQtAutoGenerator::LogBold(std::string const& message) const +{ + cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | + cmsysTerminal_Color_ForegroundBold, + message.c_str(), true, this->ColorOutput); +} + +void cmQtAutoGenerator::LogInfo(cmQtAutoGen::Generator genType, + std::string const& message) const +{ + std::string msg = cmQtAutoGen::GeneratorName(genType); + msg += ": "; + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + cmSystemTools::Stdout(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerator::LogWarning(cmQtAutoGen::Generator genType, + std::string const& message) const +{ + std::string msg = cmQtAutoGen::GeneratorName(genType); + msg += " warning:"; + if (message.find('\n') == std::string::npos) { + // Single line message + msg.push_back(' '); + } else { + // Multi line message + msg.push_back('\n'); + } + // Message + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + cmSystemTools::Stdout(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerator::LogFileWarning(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const +{ + std::string msg = " "; + msg += cmQtAutoGen::Quoted(filename); + msg.push_back('\n'); + // Message + msg += message; + this->LogWarning(genType, msg); +} + +void cmQtAutoGenerator::LogError(cmQtAutoGen::Generator genType, + std::string const& message) const +{ + std::string msg; + msg.push_back('\n'); + msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error"); + // Message + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerator::LogFileError(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const +{ + std::string emsg = " "; + emsg += cmQtAutoGen::Quoted(filename); + emsg += '\n'; + // Message + emsg += message; + this->LogError(genType, emsg); +} + +void cmQtAutoGenerator::LogCommandError( + cmQtAutoGen::Generator genType, std::string const& message, + std::vector<std::string> const& command, std::string const& output) const +{ + std::string msg; + msg.push_back('\n'); + msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error"); + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + msg += HeadLine("Command"); + msg += QuotedCommand(command); + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + msg += HeadLine("Output"); + msg += output; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); +} + +/** + * @brief Generates the parent directory of the given file on demand + * @return True on success + */ +bool cmQtAutoGenerator::MakeParentDirectory(cmQtAutoGen::Generator genType, + std::string const& filename) const +{ + bool success = true; + std::string const dirName = cmSystemTools::GetFilenamePath(filename); + if (!dirName.empty()) { + if (!cmSystemTools::MakeDirectory(dirName)) { + this->LogFileError(genType, filename, + "Could not create parent directory"); + success = false; + } + } + return success; +} + +/** + * @brief Tests if buildFile is older than sourceFile + * @return True if buildFile is older than sourceFile. + * False may indicate an error. + */ +bool cmQtAutoGenerator::FileIsOlderThan(std::string const& buildFile, + std::string const& sourceFile, + std::string* error) +{ + int result = 0; + if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) { + return (result < 0); + } + if (error != nullptr) { + error->append( + "File modification time comparison failed for the files\n "); + error->append(cmQtAutoGen::Quoted(buildFile)); + error->append("\nand\n "); + error->append(cmQtAutoGen::Quoted(sourceFile)); + } + return false; +} + +bool cmQtAutoGenerator::FileRead(std::string& content, + std::string const& filename, + std::string* error) +{ + bool success = false; + if (cmSystemTools::FileExists(filename)) { + std::size_t const length = cmSystemTools::FileLength(filename); + cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); + if (ifs) { + content.resize(length); + ifs.read(&content.front(), content.size()); + if (ifs) { + success = true; + } else { + content.clear(); + if (error != nullptr) { + error->append("Reading from the file failed."); + } + } + } else if (error != nullptr) { + error->append("Opening the file for reading failed."); + } + } else if (error != nullptr) { + error->append("The file does not exist."); + } + return success; +} + +bool cmQtAutoGenerator::FileWrite(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& content) +{ + std::string error; + // Make sure the parent directory exists + if (this->MakeParentDirectory(genType, filename)) { + cmsys::ofstream outfile; + outfile.open(filename.c_str(), + (std::ios::out | std::ios::binary | std::ios::trunc)); + if (outfile) { + outfile << content; + // Check for write errors + if (!outfile.good()) { + error = "File writing failed"; + } + } else { + error = "Opening file for writing failed"; + } + } + if (!error.empty()) { + this->LogFileError(genType, filename, error); + return false; + } + return true; +} + +bool cmQtAutoGenerator::FileDiffers(std::string const& filename, + std::string const& content) +{ + bool differs = true; + { + std::string oldContents; + if (this->FileRead(oldContents, filename)) { + differs = (oldContents != content); + } + } + return differs; +} + +/** + * @brief Runs a command and returns true on success + * @return True on success + */ +bool cmQtAutoGenerator::RunCommand(std::vector<std::string> const& command, + std::string& output) const +{ + // Log command + if (this->Verbose) { + std::string qcmd = QuotedCommand(command); + qcmd.push_back('\n'); + cmSystemTools::Stdout(qcmd.c_str(), qcmd.size()); + } + // Execute command + int retVal = 0; + bool res = cmSystemTools::RunSingleCommand( + command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE); + return (res && (retVal == 0)); +} diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h new file mode 100644 index 0000000..285340d --- /dev/null +++ b/Source/cmQtAutoGenerator.h @@ -0,0 +1,76 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGenerator_h +#define cmQtAutoGenerator_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmQtAutoGen.h" + +#include <string> +#include <vector> + +class cmMakefile; + +class cmQtAutoGenerator +{ + CM_DISABLE_COPY(cmQtAutoGenerator) +public: + cmQtAutoGenerator(); + virtual ~cmQtAutoGenerator() = default; + bool Run(std::string const& infoFile, std::string const& config); + + std::string const& GetInfoFile() const { return InfoFile; } + std::string const& GetInfoDir() const { return InfoDir; } + std::string const& GetInfoConfig() const { return InfoConfig; } + bool GetVerbose() const { return Verbose; } + +protected: + // -- Central processing + virtual bool Process(cmMakefile* makefile) = 0; + + // -- Log info + void LogBold(std::string const& message) const; + void LogInfo(cmQtAutoGen::Generator genType, + std::string const& message) const; + // -- Log warning + void LogWarning(cmQtAutoGen::Generator genType, + std::string const& message) const; + void LogFileWarning(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const; + // -- Log error + void LogError(cmQtAutoGen::Generator genType, + std::string const& message) const; + void LogFileError(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const; + void LogCommandError(cmQtAutoGen::Generator genType, + std::string const& message, + std::vector<std::string> const& command, + std::string const& output) const; + // -- Utility + bool MakeParentDirectory(cmQtAutoGen::Generator genType, + std::string const& filename) const; + bool FileIsOlderThan(std::string const& buildFile, + std::string const& sourceFile, + std::string* error = nullptr); + bool FileRead(std::string& content, std::string const& filename, + std::string* error = nullptr); + bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename, + std::string const& content); + bool FileDiffers(std::string const& filename, std::string const& content); + bool RunCommand(std::vector<std::string> const& command, + std::string& output) const; + +private: + // -- Info settings + std::string InfoFile; + std::string InfoDir; + std::string InfoConfig; + // -- Settings + bool Verbose; + bool ColorOutput; +}; + +#endif diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c7550e6..d9a5a9a 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -14,6 +14,7 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmProcessOutput.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" @@ -51,118 +52,6 @@ inline static std::string GetSafeProperty(cmSourceFile const* sf, return std::string(SafeString(sf->GetProperty(key))); } -static cmQtAutoGen::MultiConfig AutogenMultiConfig( - cmGlobalGenerator* globalGen) -{ - if (!globalGen->IsMultiConfig()) { - return cmQtAutoGen::SINGLE; - } - - // FIXME: Xcode does not support per-config sources, yet. - // (EXCLUDED_SOURCE_FILE_NAMES) - // if (globalGen->GetName().find("Xcode") != std::string::npos) { - // return cmQtAutoGen::FULL; - //} - - // FIXME: Visual Studio does not support per-config sources, yet. - // (EXCLUDED_SOURCE_FILE_NAMES) - // if (globalGen->GetName().find("Visual Studio") != std::string::npos) { - // return cmQtAutoGen::FULL; - //} - - return cmQtAutoGen::WRAP; -} - -static std::string GetAutogenTargetName(cmGeneratorTarget const* target) -{ - std::string autogenTargetName = target->GetName(); - autogenTargetName += "_autogen"; - return autogenTargetName; -} - -static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string targetDir = makefile->GetCurrentBinaryDirectory(); - targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); - targetDir += "/"; - targetDir += GetAutogenTargetName(target); - targetDir += ".dir"; - return targetDir; -} - -static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target) -{ - std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR"); - if (targetDir.empty()) { - cmMakefile* makefile = target->Target->GetMakefile(); - targetDir = makefile->GetCurrentBinaryDirectory(); - targetDir += "/"; - targetDir += GetAutogenTargetName(target); - } - return targetDir; -} - -std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion( - cmGeneratorTarget const* target) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajor.empty()) { - qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); - } - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMajor = targetQtVersion; - } - return qtMajor; -} - -std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion( - cmGeneratorTarget const* target, std::string const& qtVersionMajor) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMinor; - if (qtVersionMajor == "5") { - qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); - } - if (qtMinor.empty()) { - qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); - } - - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMinor = targetQtVersion; - } - return qtMinor; -} - -static bool QtVersionGreaterOrEqual(std::string const& major, - std::string const& minor, - unsigned long requestMajor, - unsigned long requestMinor) -{ - unsigned long majorUL(0); - unsigned long minorUL(0); - if (cmSystemTools::StringToULong(major.c_str(), &majorUL) && - cmSystemTools::StringToULong(minor.c_str(), &minorUL)) { - return (majorUL > requestMajor) || - (majorUL == requestMajor && minorUL >= requestMinor); - } - return false; -} - -static void GetConfigs(cmMakefile* makefile, std::string& configDefault, - std::vector<std::string>& configsList) -{ - configDefault = makefile->GetConfigurations(configsList); - if (configsList.empty()) { - configsList.push_back(configDefault); - } -} - static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, std::string const& value) { @@ -258,48 +147,24 @@ static void AddCleanFile(cmMakefile* makefile, std::string const& fileName) false); } -static std::vector<std::string> AddGeneratedSource( - cmGeneratorTarget* target, std::string const& filename, - cmQtAutoGen::MultiConfig multiConfig, - const std::vector<std::string>& configsList, cmQtAutoGen::Generator genType) +static std::string FileProjectRelativePath(cmMakefile* makefile, + std::string const& fileName) { - std::vector<std::string> genFiles; - // Register source file in makefile and source group - if (multiConfig != cmQtAutoGen::FULL) { - genFiles.push_back(filename); - } else { - for (std::string const& cfg : configsList) { - genFiles.push_back( - cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg)); - } - } + std::string res; { - cmMakefile* makefile = target->Target->GetMakefile(); - for (std::string const& genFile : genFiles) { - { - cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true); - gFile->SetProperty("GENERATED", "1"); - gFile->SetProperty("SKIP_AUTOGEN", "On"); - } - AddToSourceGroup(makefile, genFile, genType); - } - } - - // Add source file to target - if (multiConfig != cmQtAutoGen::FULL) { - target->AddSource(filename); - } else { - for (std::string const& cfg : configsList) { - std::string src = "$<$<CONFIG:"; - src += cfg; - src += ">:"; - src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg); - src += ">"; - target->AddSource(src); + std::string pSource = cmSystemTools::RelativePath( + makefile->GetCurrentSourceDirectory(), fileName.c_str()); + std::string pBinary = cmSystemTools::RelativePath( + makefile->GetCurrentBinaryDirectory(), fileName.c_str()); + if (pSource.size() < pBinary.size()) { + res = std::move(pSource); + } else if (pBinary.size() < fileName.size()) { + res = std::move(pBinary); + } else { + res = fileName; } } - - return genFiles; + return res; } /* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its @@ -346,350 +211,123 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, return cycle; } -struct cmQtAutoGenSetup -{ - std::set<std::string> MocSkip; - std::set<std::string> UicSkip; - - std::map<std::string, std::string> ConfigMocIncludes; - std::map<std::string, std::string> ConfigMocDefines; - std::map<std::string, std::string> ConfigUicOptions; -}; - -static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest, - cmQtAutoGenSetup& setup) +cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer( + cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled, + std::string const& qtVersionMajor) + : Target(target) + , MocEnabled(mocEnabled) + , UicEnabled(uicEnabled) + , RccEnabled(rccEnabled) + , QtVersionMajor(qtVersionMajor) + , MultiConfig(cmQtAutoGen::WRAP) { - // Read skip files from makefile sources - { - const std::vector<cmSourceFile*>& allSources = - digest.Target->Makefile->GetSourceFiles(); - for (cmSourceFile* sf : allSources) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - std::string const& fPath = sf->GetFullPath(); - cmSystemTools::FileFormat const fileType = - cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && - !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - continue; - } - const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); - const bool mocSkip = digest.MocEnabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); - const bool uicSkip = digest.UicEnabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); - if (mocSkip || uicSkip) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - if (mocSkip) { - setup.MocSkip.insert(absFile); - } - if (uicSkip) { - setup.UicSkip.insert(absFile); - } - } - } - } + this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion( + target, this->QtVersionMajor); } -static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest, - std::string const& configDefault, - std::vector<std::string> const& configsList, - cmQtAutoGenSetup& setup) +void cmQtAutoGeneratorInitializer::InitCustomTargets() { - cmGeneratorTarget const* target = digest.Target; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - cmMakefile* makefile = target->Target->GetMakefile(); - - AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip); - AddDefinitionEscaped(makefile, "_moc_options", - GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); - AddDefinitionEscaped(makefile, "_moc_relaxed_mode", - makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" - : "FALSE"); - AddDefinitionEscaped(makefile, "_moc_macro_names", - GetSafeProperty(target, "AUTOMOC_MACRO_NAMES")); - AddDefinitionEscaped(makefile, "_moc_depend_filters", - GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS")); - - // Compiler predefines - if (target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES")) { - if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor, - 5, 8)) { - AddDefinitionEscaped( - makefile, "_moc_predefs_cmd", - makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); - } - } - // Moc includes and compile definitions - { - auto GetIncludeDirs = [target, - localGen](std::string const& cfg) -> std::string { - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see - // https://gitlab.kitware.com/cmake/cmake/issues/13667 - std::vector<std::string> includeDirs; - localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg, false); - return cmJoin(includeDirs, ";"); - }; - auto GetCompileDefinitions = - [target, localGen](std::string const& cfg) -> std::string { - std::set<std::string> defines; - localGen->AddCompileDefinitions(defines, target, cfg, "CXX"); - return cmJoin(defines, ";"); - }; + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); - // Default configuration settings - std::string const includeDirs = GetIncludeDirs(configDefault); - std::string const compileDefs = GetCompileDefinitions(configDefault); - // Other configuration settings - for (std::string const& cfg : configsList) { - { - std::string const configIncludeDirs = GetIncludeDirs(cfg); - if (configIncludeDirs != includeDirs) { - setup.ConfigMocIncludes[cfg] = configIncludeDirs; - } - } - { - std::string const configCompileDefs = GetCompileDefinitions(cfg); - if (configCompileDefs != compileDefs) { - setup.ConfigMocDefines[cfg] = configCompileDefs; - } - } - } - AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs); - AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); + // Configurations + this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList); + if (this->ConfigsList.empty()) { + this->ConfigsList.push_back(this->ConfigDefault); } - // Moc executable + // Multi configuration { - std::string mocExec; - std::string err; - - if (digest.QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt5::moc target not found"; - } - } else if (digest.QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt4::moc target not found"; - } - } else { - err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; + if (!globalGen->IsMultiConfig()) { + this->MultiConfig = cmQtAutoGen::SINGLE; } - if (err.empty()) { - AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec); - } else { - err += " (" + target->GetName() + ")"; - cmSystemTools::Error(err.c_str()); - } + // FIXME: Xcode does not support per-config sources, yet. + // (EXCLUDED_SOURCE_FILE_NAMES) + // if (globalGen->GetName().find("Xcode") != std::string::npos) { + // return cmQtAutoGen::FULL; + //} + + // FIXME: Visual Studio does not support per-config sources, yet. + // (EXCLUDED_SOURCE_FILE_NAMES) + // if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + // return cmQtAutoGen::FULL; + //} } -} -static void SetupAutoTargetUic(cmQtAutoGenDigest const& digest, - std::string const& config, - std::vector<std::string> const& configs, - cmQtAutoGenSetup& setup) -{ - cmGeneratorTarget const* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); + // Autogen target name + this->AutogenTargetName = this->Target->GetName(); + this->AutogenTargetName += "_autogen"; - // Uic search paths + // Autogen directories { - std::vector<std::string> uicSearchPaths; - { - std::string const usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"); - if (!usp.empty()) { - cmSystemTools::ExpandListArgument(usp, uicSearchPaths); - std::string const srcDir = makefile->GetCurrentSourceDirectory(); - for (std::string& path : uicSearchPaths) { - path = cmSystemTools::CollapseFullPath(path, srcDir); - } - } + // Collapsed current binary directory + std::string const cbd = cmSystemTools::CollapseFullPath( + "", makefile->GetCurrentBinaryDirectory()); + + // Autogen info dir + this->DirInfo = cbd; + this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); + this->DirInfo += "/"; + this->DirInfo += this->AutogenTargetName; + this->DirInfo += ".dir"; + cmSystemTools::ConvertToUnixSlashes(this->DirInfo); + + // Autogen build dir + this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR"); + if (this->DirBuild.empty()) { + this->DirBuild = cbd; + this->DirBuild += "/"; + this->DirBuild += this->AutogenTargetName; } - AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths); - } - // Uic target options - { - auto UicGetOpts = [target](std::string const& cfg) -> std::string { - std::vector<std::string> opts; - target->GetAutoUicOptions(opts, cfg); - return cmJoin(opts, ";"); - }; + cmSystemTools::ConvertToUnixSlashes(this->DirBuild); - // Default settings - std::string const uicOpts = UicGetOpts(config); - AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); - - // Configuration specific settings - for (std::string const& cfg : configs) { - std::string const configUicOpts = UicGetOpts(cfg); - if (configUicOpts != uicOpts) { - setup.ConfigUicOptions[cfg] = configUicOpts; - } - } - } - // .ui files skip and options - { - std::vector<std::string> uiFileFiles; - std::vector<std::vector<std::string>> uiFileOptions; - { - std::string const uiExt = "ui"; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - std::string const& fPath = sf->GetFullPath(); - if (sf->GetExtension() == uiExt) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - // Check if the file should be skipped - if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || - sf->GetPropertyAsBool("SKIP_AUTOGEN")) { - setup.UicSkip.insert(absFile); - } - // Check if the files has uic options - std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); - if (!uicOpts.empty()) { - // Check if file isn't skipped - if (setup.UicSkip.count(absFile) == 0) { - uiFileFiles.push_back(absFile); - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); - uiFileOptions.push_back(std::move(optsVec)); - } - } - } - } - } - AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); - AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); + // Working directory + this->DirWork = cbd; + cmSystemTools::ConvertToUnixSlashes(this->DirWork); } - AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip); - - // Uic executable + // Autogen files { - std::string err; - std::string uicExec; + this->AutogenInfoFile = this->DirInfo; + this->AutogenInfoFile += "/AutogenInfo.cmake"; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - if (digest.QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway - } - } else if (digest.QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOUIC: Qt4::uic target not found"; - } - } else { - err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; - } - - if (err.empty()) { - AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec); - } else { - err += " (" + target->GetName() + ")"; - cmSystemTools::Error(err.c_str()); - } + this->AutogenSettingsFile = this->DirInfo; + this->AutogenSettingsFile += "/AutogenOldSettings.cmake"; } -} -static std::string RccGetExecutable(cmGeneratorTarget const* target, - std::string const& qtMajorVersion) -{ - std::string rccExec; - std::string err; - - cmLocalGenerator* localGen = target->GetLocalGenerator(); - if (qtMajorVersion == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc"); - if (tgt != nullptr) { - rccExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt5::rcc target not found"; + // Autogen target FOLDER property + { + const char* folder = + makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); + if (folder == nullptr) { + folder = + makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); } - } else if (qtMajorVersion == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc"); - if (tgt != nullptr) { - rccExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt4::rcc target not found"; + // Inherit FOLDER property from target (#13688) + if (folder == nullptr) { + folder = SafeString(this->Target->Target->GetProperty("FOLDER")); + } + if (folder != nullptr) { + this->AutogenFolder = folder; } - } else { - err = "The AUTORCC feature supports only Qt 4 and Qt 5"; - } - - if (!err.empty()) { - err += " (" + target->GetName() + ")"; - cmSystemTools::Error(err.c_str()); - } - return rccExec; -} - -static void SetupAutoTargetRcc(cmQtAutoGenDigest const& digest) -{ - std::vector<std::string> rccFiles; - std::vector<std::string> rccBuilds; - std::vector<std::vector<std::string>> rccOptions; - std::vector<std::vector<std::string>> rccInputs; - - for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) { - rccFiles.push_back(qrcDigest.QrcFile); - rccBuilds.push_back(qrcDigest.RccFile); - rccOptions.push_back(qrcDigest.Options); - rccInputs.push_back(qrcDigest.Resources); } - cmMakefile* makefile = digest.Target->Target->GetMakefile(); - AddDefinitionEscaped(makefile, "_qt_rcc_executable", - RccGetExecutable(digest.Target, digest.QtVersionMajor)); - AddDefinitionEscaped(makefile, "_rcc_files", rccFiles); - AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds); - AddDefinitionEscaped(makefile, "_rcc_options", rccOptions); - AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs); -} - -void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( - cmQtAutoGenDigest& digest) -{ - cmGeneratorTarget* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); - cmLocalGenerator* localGen = target->GetLocalGenerator(); - cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); - - std::string const autogenTargetName = GetAutogenTargetName(target); - std::string const autogenInfoDir = GetAutogenTargetFilesDir(target); - std::string const autogenBuildDir = GetAutogenTargetBuildDir(target); - std::string const workingDirectory = - cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory()); - - cmQtAutoGen::MultiConfig const multiConfig = AutogenMultiConfig(globalGen); - std::string configDefault; - std::vector<std::string> configsList; - GetConfigs(makefile, configDefault, configsList); - std::set<std::string> autogenDependFiles; std::set<cmTarget*> autogenDependTargets; std::vector<std::string> autogenProvides; // Remove build directories on cleanup - AddCleanFile(makefile, autogenBuildDir); + AddCleanFile(makefile, this->DirBuild); // Remove old settings on cleanup { - std::string base = autogenInfoDir + "/AutogenOldSettings"; - if (multiConfig == cmQtAutoGen::SINGLE) { + std::string base = this->DirInfo; + base += "/AutogenOldSettings"; + if (this->MultiConfig == cmQtAutoGen::SINGLE) { AddCleanFile(makefile, base.append(".cmake")); } else { - for (std::string const& cfg : configsList) { + for (std::string const& cfg : this->ConfigsList) { std::string filename = base; filename += "_"; filename += cfg; @@ -699,62 +337,72 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } } - // Compose command lines - cmCustomCommandLines commandLines; - { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autogen"); - currentLine.push_back(autogenInfoDir); - currentLine.push_back("$<CONFIGURATION>"); - commandLines.push_back(currentLine); - } - - // Compose target comment - std::string autogenComment; - { - std::vector<std::string> toolNames; - if (digest.MocEnabled) { - toolNames.emplace_back("MOC"); - } - if (digest.UicEnabled) { - toolNames.emplace_back("UIC"); - } - if (digest.RccEnabled) { - toolNames.emplace_back("RCC"); - } - - std::string tools = toolNames.front(); - toolNames.erase(toolNames.begin()); - if (!toolNames.empty()) { - while (toolNames.size() > 1) { - tools += ", "; - tools += toolNames.front(); - toolNames.erase(toolNames.begin()); - } - tools += " and " + toolNames.front(); - } - autogenComment = "Automatic " + tools + " for target " + target->GetName(); - } - // Add moc compilation to generated files list - if (digest.MocEnabled) { - std::string const mocsComp = autogenBuildDir + "/mocs_compilation.cpp"; - auto files = AddGeneratedSource(target, mocsComp, multiConfig, configsList, - cmQtAutoGen::MOC); + if (this->MocEnabled) { + std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp"; + auto files = this->AddGeneratedSource(mocsComp, cmQtAutoGen::MOC); for (std::string& file : files) { autogenProvides.push_back(std::move(file)); } } // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES - if (digest.MocEnabled || digest.UicEnabled) { - std::string includeDir = autogenBuildDir + "/include"; - if (multiConfig != cmQtAutoGen::SINGLE) { + if (this->MocEnabled || this->UicEnabled) { + std::string includeDir = this->DirBuild + "/include"; + if (this->MultiConfig != cmQtAutoGen::SINGLE) { includeDir += "_$<CONFIG>"; } - target->AddIncludeDirectory(includeDir, true); + this->Target->AddIncludeDirectory(includeDir, true); + } + + // Acquire rcc executable and features + if (this->RccEnabled) { + { + std::string err; + if (this->QtVersionMajor == "5") { + cmGeneratorTarget* tgt = + localGen->FindGeneratorTargetToUse("Qt5::rcc"); + if (tgt != nullptr) { + this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTORCC: Qt5::rcc target not found"; + } + } else if (QtVersionMajor == "4") { + cmGeneratorTarget* tgt = + localGen->FindGeneratorTargetToUse("Qt4::rcc"); + if (tgt != nullptr) { + this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTORCC: Qt4::rcc target not found"; + } + } else { + err = "The AUTORCC feature supports only Qt 4 and Qt 5"; + } + if (!err.empty()) { + err += " ("; + err += this->Target->GetName(); + err += ")"; + cmSystemTools::Error(err.c_str()); + } + } + // Detect if rcc supports (-)-list + if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) { + std::vector<std::string> command; + command.push_back(this->RccExecutable); + command.push_back("--help"); + std::string rccStdOut; + std::string rccStdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &rccStdOut, &rccStdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto); + if (result && retVal == 0 && + rccStdOut.find("--list") != std::string::npos) { + this->RccListOptions.push_back("--list"); + } else { + this->RccListOptions.push_back("-list"); + } + } } // Extract relevant source files @@ -763,7 +411,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { std::string const qrcExt = "qrc"; std::vector<cmSourceFile*> srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); + this->Target->GetConfigCommonSourceFiles(srcFiles); for (cmSourceFile* sf : srcFiles) { if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) { continue; @@ -772,50 +420,50 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( std::string const& fPath = sf->GetFullPath(); std::string const& ext = sf->GetExtension(); // Register generated files that will be scanned by moc or uic - if (digest.MocEnabled || digest.UicEnabled) { + if (this->MocEnabled || this->UicEnabled) { cmSystemTools::FileFormat const fileType = cmSystemTools::GetFileFormat(ext.c_str()); if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { std::string const absPath = cmSystemTools::GetRealPath(fPath); - if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || - (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { + if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || + (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { // Register source const bool generated = sf->GetPropertyAsBool("GENERATED"); if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { if (generated) { generatedHeaders.push_back(absPath); } else { - digest.Headers.push_back(absPath); + this->Headers.push_back(absPath); } } else { if (generated) { generatedSources.push_back(absPath); } else { - digest.Sources.push_back(absPath); + this->Sources.push_back(absPath); } } } } } // Register rcc enabled files - if (digest.RccEnabled && (ext == qrcExt) && + if (this->RccEnabled && (ext == qrcExt) && !sf->GetPropertyAsBool("SKIP_AUTORCC")) { // Register qrc file { - cmQtAutoGenDigestQrc qrcDigest; - qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath); - qrcDigest.QrcName = - cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile); - qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED"); + Qrc qrc; + qrc.QrcFile = cmSystemTools::GetRealPath(fPath); + qrc.QrcName = + cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile); + qrc.Generated = sf->GetPropertyAsBool("GENERATED"); // RCC options { std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS"); if (!opts.empty()) { - cmSystemTools::ExpandListArgument(opts, qrcDigest.Options); + cmSystemTools::ExpandListArgument(opts, qrc.Options); } } - digest.Qrcs.push_back(std::move(qrcDigest)); + this->Qrcs.push_back(std::move(qrc)); } } } @@ -823,7 +471,35 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // sources meta data cache. Clear it so that OBJECT library targets that // are AUTOGEN initialized after this target get their added // mocs_compilation.cpp source acknowledged by this target. - target->ClearSourcesCache(); + this->Target->ClearSourcesCache(); + } + // Read skip files from makefile sources + if (this->MocEnabled || this->UicEnabled) { + const std::vector<cmSourceFile*>& allSources = makefile->GetSourceFiles(); + for (cmSourceFile* sf : allSources) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + std::string const& fPath = sf->GetFullPath(); + cmSystemTools::FileFormat const fileType = + cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); + if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && + !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + continue; + } + const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); + const bool mocSkip = + this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); + const bool uicSkip = + this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); + if (mocSkip || uicSkip) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + if (mocSkip) { + this->MocSkip.insert(absFile); + } + if (uicSkip) { + this->UicSkip.insert(absFile); + } + } + } } // Process GENERATED sources and headers @@ -832,7 +508,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( bool policyAccept = false; bool policyWarn = false; cmPolicies::PolicyStatus const CMP0071_status = - target->Makefile->GetPolicyStatus(cmPolicies::CMP0071); + makefile->GetPolicyStatus(cmPolicies::CMP0071); switch (CMP0071_status) { case cmPolicies::WARN: policyWarn = true; @@ -851,11 +527,11 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (policyAccept) { // Accept GENERATED sources for (std::string const& absFile : generatedHeaders) { - digest.Headers.push_back(absFile); + this->Headers.push_back(absFile); autogenDependFiles.insert(absFile); } for (std::string const& absFile : generatedSources) { - digest.Sources.push_back(absFile); + this->Sources.push_back(absFile); autogenDependFiles.insert(absFile); } } else { @@ -865,13 +541,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( msg += "\n"; std::string tools; std::string property; - if (digest.MocEnabled && digest.UicEnabled) { + if (this->MocEnabled && this->UicEnabled) { tools = "AUTOMOC and AUTOUIC"; property = "SKIP_AUTOGEN"; - } else if (digest.MocEnabled) { + } else if (this->MocEnabled) { tools = "AUTOMOC"; property = "SKIP_AUTOMOC"; - } else if (digest.UicEnabled) { + } else if (this->UicEnabled) { tools = "AUTOUIC"; property = "SKIP_AUTOUIC"; } @@ -896,57 +572,74 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } } + // Clear lists + generatedSources.clear(); + generatedHeaders.clear(); } // Sort headers and sources - std::sort(digest.Headers.begin(), digest.Headers.end()); - std::sort(digest.Sources.begin(), digest.Sources.end()); + if (this->MocEnabled || this->UicEnabled) { + std::sort(this->Headers.begin(), this->Headers.end()); + std::sort(this->Sources.begin(), this->Sources.end()); + } // Process qrc files - if (!digest.Qrcs.empty()) { - const bool QtV5 = (digest.QtVersionMajor == "5"); - std::string const rcc = RccGetExecutable(target, digest.QtVersionMajor); + if (!this->Qrcs.empty()) { + const bool QtV5 = (this->QtVersionMajor == "5"); // Target rcc options std::vector<std::string> optionsTarget; cmSystemTools::ExpandListArgument( - GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget); + GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget); // Check if file name is unique - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - qrcDigest.Unique = true; - for (cmQtAutoGenDigestQrc const& qrcDig2 : digest.Qrcs) { - if ((&qrcDigest != &qrcDig2) && - (qrcDigest.QrcName == qrcDig2.QrcName)) { - qrcDigest.Unique = false; + for (Qrc& qrc : this->Qrcs) { + qrc.Unique = true; + for (Qrc const& qrc2 : this->Qrcs) { + if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) { + qrc.Unique = false; break; } } } - // Path checksum + // Path checksum and file names { cmFilePathChecksum const fpathCheckSum(makefile); - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile); + for (Qrc& qrc : this->Qrcs) { + qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile); // RCC output file name - std::string rccFile = autogenBuildDir + "/"; - rccFile += qrcDigest.PathChecksum; - rccFile += "/qrc_"; - rccFile += qrcDigest.QrcName; - rccFile += ".cpp"; - qrcDigest.RccFile = std::move(rccFile); + { + std::string rccFile = this->DirBuild + "/"; + rccFile += qrc.PathChecksum; + rccFile += "/qrc_"; + rccFile += qrc.QrcName; + rccFile += ".cpp"; + qrc.RccFile = std::move(rccFile); + } + { + std::string base = this->DirInfo; + base += "/RCC"; + base += qrc.QrcName; + if (!qrc.Unique) { + base += qrc.PathChecksum; + } + qrc.InfoFile = base; + qrc.InfoFile += "Info.cmake"; + qrc.SettingsFile = base; + qrc.SettingsFile += "Settings.cmake"; + } } } // RCC options - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + for (Qrc& qrc : this->Qrcs) { // Target options std::vector<std::string> opts = optionsTarget; // Merge computed "-name XYZ" option { - std::string name = qrcDigest.QrcName; + std::string name = qrc.QrcName; // Replace '-' with '_'. The former is not valid for symbol names. std::replace(name.begin(), name.end(), '-', '_'); - if (!qrcDigest.Unique) { + if (!qrc.Unique) { name += "_"; - name += qrcDigest.PathChecksum; + name += qrc.PathChecksum; } std::vector<std::string> nameOpts; nameOpts.emplace_back("-name"); @@ -954,254 +647,324 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5); } // Merge file option - cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5); - qrcDigest.Options = std::move(opts); + cmQtAutoGen::RccMergeOptions(opts, qrc.Options, QtV5); + qrc.Options = std::move(opts); } - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + for (Qrc& qrc : this->Qrcs) { // Register file at target + std::vector<std::string> const ccOutput = + this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC); + + cmCustomCommandLines commandLines; { - auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig, - configsList, cmQtAutoGen::RCC); - for (std::string& file : files) { - autogenProvides.push_back(std::move(file)); - } + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autorcc"); + currentLine.push_back(qrc.InfoFile); + currentLine.push_back("$<CONFIGURATION>"); + commandLines.push_back(std::move(currentLine)); } - // Dependencies - if (qrcDigest.Generated) { - // Add the GENERATED .qrc file to the dependencies - autogenDependFiles.insert(qrcDigest.QrcFile); + std::string ccComment = "Automatic RCC for "; + ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); + + if (qrc.Generated) { + // Create custom rcc target + std::string ccName; + { + ccName = this->Target->GetName(); + ccName += "_arcc_"; + ccName += qrc.QrcName; + if (!qrc.Unique) { + ccName += "_"; + ccName += qrc.PathChecksum; + } + std::vector<std::string> ccDepends; + // Add the .qrc file to the custom target dependencies + ccDepends.push_back(qrc.QrcFile); + + cmTarget* autoRccTarget = makefile->AddUtilityCommand( + ccName, true, this->DirWork.c_str(), ccOutput, ccDepends, + commandLines, false, ccComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autoRccTarget, localGen)); + + // Set FOLDER property in autogen target + if (!this->AutogenFolder.empty()) { + autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); + } + } + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(ccName, makefile); } else { - // Add the resource files to the dependencies + // Create custom rcc command { - std::string error; - if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc, - qrcDigest.QrcFile, - qrcDigest.Resources, &error)) { - for (std::string const& fileName : qrcDigest.Resources) { - autogenDependFiles.insert(fileName); + std::vector<std::string> ccByproducts; + std::vector<std::string> ccDepends; + // Add the .qrc file to the custom command dependencies + ccDepends.push_back(qrc.QrcFile); + + // Add the resource files to the dependencies + { + std::string error; + if (cmQtAutoGen::RccListInputs(this->RccExecutable, + this->RccListOptions, qrc.QrcFile, + qrc.Resources, &error)) { + for (std::string const& fileName : qrc.Resources) { + // Add resource file to the custom command dependencies + ccDepends.push_back(fileName); + } + } else { + cmSystemTools::Error(error.c_str()); } - } else { - cmSystemTools::Error(error.c_str()); } + makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, + /*main_dependency*/ std::string(), + commandLines, ccComment.c_str(), + this->DirWork.c_str()); } - // Run cmake again when .qrc file changes - makefile->AddCMakeDependFile(qrcDigest.QrcFile); + // Reconfigure when .qrc file changes + makefile->AddCMakeDependFile(qrc.QrcFile); } } } - // Add user defined autogen target dependencies - { - std::string const deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS"); - if (!deps.empty()) { - std::vector<std::string> extraDeps; - cmSystemTools::ExpandListArgument(deps, extraDeps); - for (std::string const& depName : extraDeps) { - // Allow target and file dependencies - auto* depTarget = makefile->FindTargetToUse(depName); - if (depTarget != nullptr) { - autogenDependTargets.insert(depTarget); - } else { - autogenDependFiles.insert(depName); + // Create _autogen target + if (this->MocEnabled || this->UicEnabled) { + // Add user defined autogen target dependencies + { + std::string const deps = + GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS"); + if (!deps.empty()) { + std::vector<std::string> extraDeps; + cmSystemTools::ExpandListArgument(deps, extraDeps); + for (std::string const& depName : extraDeps) { + // Allow target and file dependencies + auto* depTarget = makefile->FindTargetToUse(depName); + if (depTarget != nullptr) { + autogenDependTargets.insert(depTarget); + } else { + autogenDependFiles.insert(depName); + } } } } - } - // Use PRE_BUILD on demand - bool usePRE_BUILD = false; - if (globalGen->GetName().find("Visual Studio") != std::string::npos) { - // Under VS use a PRE_BUILD event instead of a separate target to - // reduce the number of targets loaded into the IDE. - // This also works around a VS 11 bug that may skip updating the target: - // https://connect.microsoft.com/VisualStudio/feedback/details/769495 - usePRE_BUILD = true; - } - // Disable PRE_BUILD in some cases - if (usePRE_BUILD) { - // Cannot use PRE_BUILD with file depends - if (!autogenDependFiles.empty()) { - usePRE_BUILD = false; + // Compose target comment + std::string autogenComment; + { + std::string tools; + if (this->MocEnabled) { + tools += "MOC"; + } + if (this->UicEnabled) { + if (!tools.empty()) { + tools += " and "; + } + tools += "UIC"; + } + autogenComment = "Automatic "; + autogenComment += tools; + autogenComment += " for target "; + autogenComment += this->Target->GetName(); } - } - // Create the autogen target/command - if (usePRE_BUILD) { - // Add additional autogen target dependencies to origin target - for (cmTarget* depTarget : autogenDependTargets) { - target->Target->AddUtility(depTarget->GetName(), makefile); + + // Compose command lines + cmCustomCommandLines commandLines; + { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autogen"); + currentLine.push_back(this->AutogenInfoFile); + currentLine.push_back("$<CONFIGURATION>"); + commandLines.push_back(std::move(currentLine)); } - // Add the pre-build command directly to bypass the OBJECT_LIBRARY - // rejection in cmMakefile::AddCustomCommandToTarget because we know - // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. - // - // PRE_BUILD does not support file dependencies! - const std::vector<std::string> no_output; - const std::vector<std::string> no_deps; - cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, - commandLines, autogenComment.c_str(), - workingDirectory.c_str()); - cc.SetEscapeOldStyle(false); - cc.SetEscapeAllowMakeVars(true); - target->Target->AddPreBuildCommand(cc); - } else { + // Use PRE_BUILD on demand + bool usePRE_BUILD = false; + if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + // Under VS use a PRE_BUILD event instead of a separate target to + // reduce the number of targets loaded into the IDE. + // This also works around a VS 11 bug that may skip updating the target: + // https://connect.microsoft.com/VisualStudio/feedback/details/769495 + usePRE_BUILD = true; + } + // Disable PRE_BUILD in some cases + if (usePRE_BUILD) { + // Cannot use PRE_BUILD with file depends + if (!autogenDependFiles.empty()) { + usePRE_BUILD = false; + } + } + // Create the autogen target/command + if (usePRE_BUILD) { + // Add additional autogen target dependencies to origin target + for (cmTarget* depTarget : autogenDependTargets) { + this->Target->Target->AddUtility(depTarget->GetName(), makefile); + } - // Convert file dependencies std::set to std::vector - std::vector<std::string> autogenDepends(autogenDependFiles.begin(), - autogenDependFiles.end()); + // Add the pre-build command directly to bypass the OBJECT_LIBRARY + // rejection in cmMakefile::AddCustomCommandToTarget because we know + // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. + // + // PRE_BUILD does not support file dependencies! + const std::vector<std::string> no_output; + const std::vector<std::string> no_deps; + cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, + commandLines, autogenComment.c_str(), + this->DirWork.c_str()); + cc.SetEscapeOldStyle(false); + cc.SetEscapeAllowMakeVars(true); + this->Target->Target->AddPreBuildCommand(cc); + } else { - // Add link library target dependencies to the autogen target dependencies - for (std::string const& config : configsList) { - cmLinkImplementationLibraries const* libs = - target->GetLinkImplementationLibraries(config); - if (libs != nullptr) { - for (cmLinkItem const& item : libs->Libraries) { - cmGeneratorTarget const* libTarget = item.Target; - if ((libTarget != nullptr) && - !StaticLibraryCycle(target, libTarget, config)) { - std::string util; - if (configsList.size() > 1) { - util += "$<$<CONFIG:"; - util += config; - util += ">:"; - } - util += libTarget->GetName(); - if (configsList.size() > 1) { - util += ">"; + // Convert file dependencies std::set to std::vector + std::vector<std::string> autogenDepends(autogenDependFiles.begin(), + autogenDependFiles.end()); + + // Add link library target dependencies to the autogen target + // dependencies + for (std::string const& config : this->ConfigsList) { + cmLinkImplementationLibraries const* libs = + this->Target->GetLinkImplementationLibraries(config); + if (libs != nullptr) { + for (cmLinkItem const& item : libs->Libraries) { + cmGeneratorTarget const* libTarget = item.Target; + if ((libTarget != nullptr) && + !StaticLibraryCycle(this->Target, libTarget, config)) { + std::string util; + if (this->ConfigsList.size() > 1) { + util += "$<$<CONFIG:"; + util += config; + util += ">:"; + } + util += libTarget->GetName(); + if (this->ConfigsList.size() > 1) { + util += ">"; + } + autogenDepends.push_back(util); } - autogenDepends.push_back(util); } } } - } - // Create autogen target - cmTarget* autogenTarget = makefile->AddUtilityCommand( - autogenTargetName, true, workingDirectory.c_str(), - /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, - autogenComment.c_str()); - // Create autogen generator target - localGen->AddGeneratorTarget( - new cmGeneratorTarget(autogenTarget, localGen)); - - // Forward origin utilities to autogen target - for (std::string const& depName : target->Target->GetUtilities()) { - autogenTarget->AddUtility(depName, makefile); - } - // Add additional autogen target dependencies to autogen target - for (cmTarget* depTarget : autogenDependTargets) { - autogenTarget->AddUtility(depTarget->GetName(), makefile); - } - - // Set FOLDER property in autogen target - { - const char* autogenFolder = - makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); - if (autogenFolder == nullptr) { - autogenFolder = - makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); + // Create autogen target + cmTarget* autogenTarget = makefile->AddUtilityCommand( + this->AutogenTargetName, true, this->DirWork.c_str(), + /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, + autogenComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autogenTarget, localGen)); + + // Forward origin utilities to autogen target + for (std::string const& depName : this->Target->Target->GetUtilities()) { + autogenTarget->AddUtility(depName, makefile); } - // Inherit FOLDER property from target (#13688) - if (autogenFolder == nullptr) { - autogenFolder = SafeString(target->Target->GetProperty("FOLDER")); + // Add additional autogen target dependencies to autogen target + for (cmTarget* depTarget : autogenDependTargets) { + autogenTarget->AddUtility(depTarget->GetName(), makefile); } - if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) { - autogenTarget->SetProperty("FOLDER", autogenFolder); + + // Set FOLDER property in autogen target + if (!this->AutogenFolder.empty()) { + autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); } - } - // Add autogen target to the origin target dependencies - target->Target->AddUtility(autogenTargetName, makefile); + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(this->AutogenTargetName, makefile); + } } } -void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( - cmQtAutoGenDigest const& digest) +void cmQtAutoGeneratorInitializer::SetupCustomTargets() { - cmGeneratorTarget const* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); - cmQtAutoGen::MultiConfig const multiConfig = - AutogenMultiConfig(target->GetGlobalGenerator()); + cmMakefile* makefile = this->Target->Target->GetMakefile(); // forget the variables added here afterwards again: cmMakefile::ScopePushPop varScope(makefile); static_cast<void>(varScope); - // Configurations - std::string configDefault; - std::vector<std::string> configsList; + // Configuration suffixes std::map<std::string, std::string> configSuffixes; - { - configDefault = makefile->GetConfigurations(configsList); - if (configsList.empty()) { - configsList.push_back(""); - } + for (std::string const& cfg : this->ConfigsList) { + std::string& suffix = configSuffixes[cfg]; + suffix = "_"; + suffix += cfg; } - for (std::string const& cfg : configsList) { - configSuffixes[cfg] = "_" + cfg; - } - - // Configurations settings buffers - cmQtAutoGenSetup setup; // Basic setup AddDefinitionEscaped(makefile, "_multi_config", - cmQtAutoGen::MultiConfigName(multiConfig)); - AddDefinitionEscaped(makefile, "_build_dir", - GetAutogenTargetBuildDir(target)); - AddDefinitionEscaped(makefile, "_sources", digest.Sources); - AddDefinitionEscaped(makefile, "_headers", digest.Headers); - AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor); - AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor); - { - if (digest.MocEnabled || digest.UicEnabled) { - SetupAcquireSkipFiles(digest, setup); - if (digest.MocEnabled) { - SetupAutoTargetMoc(digest, configDefault, configsList, setup); - } - if (digest.UicEnabled) { - SetupAutoTargetUic(digest, configDefault, configsList, setup); - } + cmQtAutoGen::MultiConfigName(this->MultiConfig)); + AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild); + + if (this->MocEnabled || this->UicEnabled) { + AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor); + AddDefinitionEscaped(makefile, "_settings_file", + this->AutogenSettingsFile); + AddDefinitionEscaped(makefile, "_sources", this->Sources); + AddDefinitionEscaped(makefile, "_headers", this->Headers); + + if (this->MocEnabled) { + this->SetupCustomTargetsMoc(); } - if (digest.RccEnabled) { - SetupAutoTargetRcc(digest); + if (this->UicEnabled) { + this->SetupCustomTargetsUic(); } } + if (this->RccEnabled) { + AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable); + AddDefinitionEscaped(makefile, "_qt_rcc_list_options", + this->RccListOptions); + } - // Generate info file - { - std::string const infoDir = GetAutogenTargetFilesDir(target); - if (!cmSystemTools::MakeDirectory(infoDir)) { - std::string emsg = ("Could not create directory: "); - emsg += cmQtAutoGen::Quoted(infoDir); - cmSystemTools::Error(emsg.c_str()); - } - std::string const infoFile = infoDir + "/AutogenInfo.cmake"; - { - std::string infoFileIn = cmSystemTools::GetCMakeRoot(); - infoFileIn += "/Modules/AutogenInfo.cmake.in"; - makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false, - true, false); - } - - // Append custom definitions to info file - // -------------------------------------- + // Create info directory on demand + if (!cmSystemTools::MakeDirectory(this->DirInfo)) { + std::string emsg = ("Could not create directory: "); + emsg += cmQtAutoGen::Quoted(this->DirInfo); + cmSystemTools::Error(emsg.c_str()); + } - // Ensure we have write permission in case .in was read-only. + auto ReOpenInfoFile = [](cmsys::ofstream& ofs, + std::string const& fileName) -> bool { + // Ensure we have write permission mode_t perm = 0; #if defined(_WIN32) && !defined(__CYGWIN__) mode_t mode_write = S_IWRITE; #else mode_t mode_write = S_IWUSR; #endif - cmSystemTools::GetPermissions(infoFile, perm); + cmSystemTools::GetPermissions(fileName, perm); if (!(perm & mode_write)) { - cmSystemTools::SetPermissions(infoFile, perm | mode_write); + cmSystemTools::SetPermissions(fileName, perm | mode_write); } - // Open and write file - cmsys::ofstream ofs(infoFile.c_str(), std::ios::app); - if (ofs) { + ofs.open(fileName.c_str(), std::ios::app); + if (!ofs) { + // File open error + std::string error = "Internal CMake error when trying to open file: "; + error += cmQtAutoGen::Quoted(fileName); + error += " for writing."; + cmSystemTools::Error(error.c_str()); + } + return static_cast<bool>(ofs); + }; + + // Generate autogen target info file + if (this->MocEnabled || this->UicEnabled) { + { + std::string infoFileIn = cmSystemTools::GetCMakeRoot(); + infoFileIn += "/Modules/AutogenInfo.cmake.in"; + makefile->ConfigureFile( + infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false); + } + + // Append custom definitions to info file + // -------------------------------------- + cmsys::ofstream ofs; + if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) { auto OfsWriteMap = [&ofs]( const char* key, std::map<std::string, std::string> const& map) { for (auto const& item : map) { @@ -1211,15 +974,372 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( }; ofs << "# Configurations options\n"; OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes); - OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines); - OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes); - OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions); + OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines); + OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes); + OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions); + // Settings files (only require for multi configuration generators) + if (this->MultiConfig != cmQtAutoGen::SINGLE) { + std::map<std::string, std::string> settingsFiles; + for (std::string const& cfg : this->ConfigsList) { + settingsFiles[cfg] = cmQtAutoGen::AppendFilenameSuffix( + this->AutogenSettingsFile, "_" + cfg); + } + OfsWriteMap("AM_SETTINGS_FILE", settingsFiles); + } + } + } + + // Generate auto RCC info files + if (this->RccEnabled) { + std::string infoFileIn = cmSystemTools::GetCMakeRoot(); + infoFileIn += "/Modules/AutoRccInfo.cmake.in"; + for (Qrc const& qrc : this->Qrcs) { + // Configure info file + makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false, + true, false); + + // Append custom definitions to info file + // -------------------------------------- + cmsys::ofstream ofs; + if (ReOpenInfoFile(ofs, qrc.InfoFile)) { + { + ofs << "# Job\n"; + auto OfsWrite = [&ofs](const char* key, std::string const& value) { + ofs << "set(" << key << " " + << cmOutputConverter::EscapeForCMake(value) << ")\n"; + + }; + OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); + OfsWrite("ARCC_SOURCE", qrc.QrcFile); + OfsWrite("ARCC_OUTPUT", qrc.RccFile); + OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); + OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); + } + { + ofs << "# Configurations options\n"; + auto OfsWriteMap = [&ofs]( + const char* key, std::map<std::string, std::string> const& map) { + for (auto const& item : map) { + ofs << "set(" << key << "_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; + } + }; + OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes); + + // Settings files (only require for multi configuration generators) + if (this->MultiConfig != cmQtAutoGen::SINGLE) { + std::map<std::string, std::string> settingsFiles; + for (std::string const& cfg : this->ConfigsList) { + settingsFiles[cfg] = + cmQtAutoGen::AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); + } + OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles); + } + } + } else { + break; + } + } + } +} + +void cmQtAutoGeneratorInitializer::SetupCustomTargetsMoc() +{ + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); + AddDefinitionEscaped(makefile, "_moc_macro_names", + GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES")); + AddDefinitionEscaped( + makefile, "_moc_depend_filters", + GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS")); + + // Compiler predefines + if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && + this->QtVersionGreaterOrEqual(5, 8)) { + AddDefinitionEscaped( + makefile, "_moc_predefs_cmd", + makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); + } + // Moc includes and compile definitions + { + auto GetIncludeDirs = [this, + localGen](std::string const& cfg) -> std::string { + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + std::vector<std::string> includeDirs; + localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg, + false); + return cmJoin(includeDirs, ";"); + }; + auto GetCompileDefinitions = + [this, localGen](std::string const& cfg) -> std::string { + std::set<std::string> defines; + localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); + return cmJoin(defines, ";"); + }; + + // Default configuration settings + std::string const includeDirs = GetIncludeDirs(this->ConfigDefault); + std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault); + // Other configuration settings + for (std::string const& cfg : this->ConfigsList) { + { + std::string const configIncludeDirs = GetIncludeDirs(cfg); + if (configIncludeDirs != includeDirs) { + this->ConfigMocIncludes[cfg] = configIncludeDirs; + } + } + { + std::string const configCompileDefs = GetCompileDefinitions(cfg); + if (configCompileDefs != compileDefs) { + this->ConfigMocDefines[cfg] = configCompileDefs; + } + } + } + AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); + } + + // Moc executable + { + std::string mocExec; + std::string err; + + if (this->QtVersionMajor == "5") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc"); + if (tgt != nullptr) { + mocExec = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTOMOC: Qt5::moc target not found"; + } + } else if (this->QtVersionMajor == "4") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); + if (tgt != nullptr) { + mocExec = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTOMOC: Qt4::moc target not found"; + } } else { - // File open error - std::string error = "Internal CMake error when trying to open file: "; - error += cmQtAutoGen::Quoted(infoFile); - error += " for writing."; - cmSystemTools::Error(error.c_str()); + err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; + } + + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec); + } else { + err += " ("; + err += this->Target->GetName(); + err += ")"; + cmSystemTools::Error(err.c_str()); } } } + +void cmQtAutoGeneratorInitializer::SetupCustomTargetsUic() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Uic search paths + { + std::vector<std::string> uicSearchPaths; + { + std::string const usp = + GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS"); + if (!usp.empty()) { + cmSystemTools::ExpandListArgument(usp, uicSearchPaths); + std::string const srcDir = makefile->GetCurrentSourceDirectory(); + for (std::string& path : uicSearchPaths) { + path = cmSystemTools::CollapseFullPath(path, srcDir); + } + } + } + AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths); + } + // Uic target options + { + auto UicGetOpts = [this](std::string const& cfg) -> std::string { + std::vector<std::string> opts; + this->Target->GetAutoUicOptions(opts, cfg); + return cmJoin(opts, ";"); + }; + + // Default settings + std::string const uicOpts = UicGetOpts(this->ConfigDefault); + AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); + + // Configuration specific settings + for (std::string const& cfg : this->ConfigsList) { + std::string const configUicOpts = UicGetOpts(cfg); + if (configUicOpts != uicOpts) { + this->ConfigUicOptions[cfg] = configUicOpts; + } + } + } + // .ui files skip and options + { + std::vector<std::string> uiFileFiles; + std::vector<std::vector<std::string>> uiFileOptions; + { + std::string const uiExt = "ui"; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + std::string const& fPath = sf->GetFullPath(); + if (sf->GetExtension() == uiExt) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + // Check if the .ui file should be skipped + if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || + sf->GetPropertyAsBool("SKIP_AUTOGEN")) { + this->UicSkip.insert(absFile); + } + // Check if the .ui file has uic options + std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); + if (!uicOpts.empty()) { + // Check if file isn't skipped + if (this->UicSkip.count(absFile) == 0) { + uiFileFiles.push_back(absFile); + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + uiFileOptions.push_back(std::move(optsVec)); + } + } + } + } + } + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); + } + + AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip); + + // Uic executable + { + std::string err; + std::string uicExec; + + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + if (this->QtVersionMajor == "5") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic"); + if (tgt != nullptr) { + uicExec = SafeString(tgt->ImportedGetLocation("")); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (this->QtVersionMajor == "4") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); + if (tgt != nullptr) { + uicExec = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTOUIC: Qt4::uic target not found"; + } + } else { + err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; + } + + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec); + } else { + err += " ("; + err += this->Target->GetName(); + err += ")"; + cmSystemTools::Error(err.c_str()); + } + } +} + +std::vector<std::string> cmQtAutoGeneratorInitializer::AddGeneratedSource( + std::string const& filename, cmQtAutoGen::Generator genType) +{ + std::vector<std::string> genFiles; + // Register source file in makefile and source group + if (this->MultiConfig != cmQtAutoGen::FULL) { + genFiles.push_back(filename); + } else { + for (std::string const& cfg : this->ConfigsList) { + genFiles.push_back( + cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg)); + } + } + { + cmMakefile* makefile = this->Target->Target->GetMakefile(); + for (std::string const& genFile : genFiles) { + { + cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true); + gFile->SetProperty("GENERATED", "1"); + gFile->SetProperty("SKIP_AUTOGEN", "On"); + } + AddToSourceGroup(makefile, genFile, genType); + } + } + + // Add source file to target + if (this->MultiConfig != cmQtAutoGen::FULL) { + this->Target->AddSource(filename); + } else { + for (std::string const& cfg : this->ConfigsList) { + std::string src = "$<$<CONFIG:"; + src += cfg; + src += ">:"; + src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg); + src += ">"; + this->Target->AddSource(src); + } + } + + return genFiles; +} + +std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion( + cmGeneratorTarget const* target) +{ + cmMakefile* makefile = target->Target->GetMakefile(); + std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajor.empty()) { + qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + } + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); + if (targetQtVersion != nullptr) { + qtMajor = targetQtVersion; + } + return qtMajor; +} + +std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion( + cmGeneratorTarget const* target, std::string const& qtVersionMajor) +{ + cmMakefile* makefile = target->Target->GetMakefile(); + std::string qtMinor; + if (qtVersionMajor == "5") { + qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); + } + if (qtMinor.empty()) { + qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); + } + + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); + if (targetQtVersion != nullptr) { + qtMinor = targetQtVersion; + } + return qtMinor; +} + +bool cmQtAutoGeneratorInitializer::QtVersionGreaterOrEqual( + unsigned long requestMajor, unsigned long requestMinor) const +{ + unsigned long majorUL(0); + unsigned long minorUL(0); + if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) && + cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) { + return (majorUL > requestMajor) || + (majorUL == requestMajor && minorUL >= requestMinor); + } + return false; +} diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h index b8a5ae4..e06e1c4 100644 --- a/Source/cmQtAutoGeneratorInitializer.h +++ b/Source/cmQtAutoGeneratorInitializer.h @@ -4,9 +4,12 @@ #define cmQtAutoGeneratorInitializer_h #include "cmConfigure.h" // IWYU pragma: keep -#include "cmQtAutoGenDigest.h" +#include "cmQtAutoGen.h" +#include <map> +#include <set> #include <string> +#include <vector> class cmGeneratorTarget; @@ -17,8 +20,78 @@ public: static std::string GetQtMinorVersion(cmGeneratorTarget const* target, std::string const& qtVersionMajor); - static void InitializeAutogenTarget(cmQtAutoGenDigest& digest); - static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest); + class Qrc + { + public: + Qrc() + : Generated(false) + , Unique(false) + { + } + + public: + std::string QrcFile; + std::string QrcName; + std::string PathChecksum; + std::string InfoFile; + std::string SettingsFile; + std::string RccFile; + bool Generated; + bool Unique; + std::vector<std::string> Options; + std::vector<std::string> Resources; + }; + +public: + cmQtAutoGeneratorInitializer(cmGeneratorTarget* target, bool mocEnabled, + bool uicEnabled, bool rccEnabled, + std::string const& qtVersionMajor); + + void InitCustomTargets(); + void SetupCustomTargets(); + +private: + void SetupCustomTargetsMoc(); + void SetupCustomTargetsUic(); + + std::vector<std::string> AddGeneratedSource(std::string const& filename, + cmQtAutoGen::Generator genType); + + bool QtVersionGreaterOrEqual(unsigned long requestMajor, + unsigned long requestMinor) const; + +private: + cmGeneratorTarget* Target; + bool MocEnabled; + bool UicEnabled; + bool RccEnabled; + // Qt + std::string QtVersionMajor; + std::string QtVersionMinor; + std::string RccExecutable; + std::vector<std::string> RccListOptions; + // Configurations + std::string ConfigDefault; + std::vector<std::string> ConfigsList; + cmQtAutoGen::MultiConfig MultiConfig; + // Names + std::string AutogenTargetName; + std::string AutogenFolder; + std::string AutogenInfoFile; + std::string AutogenSettingsFile; + // Directories + std::string DirInfo; + std::string DirBuild; + std::string DirWork; + // Sources + std::vector<std::string> Headers; + std::vector<std::string> Sources; + std::set<std::string> MocSkip; + std::set<std::string> UicSkip; + std::map<std::string, std::string> ConfigMocIncludes; + std::map<std::string, std::string> ConfigMocDefines; + std::map<std::string, std::string> ConfigUicOptions; + std::vector<Qrc> Qrcs; }; #endif diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index 28a8df1..0de02b5 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1,10 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGen.h" -#include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorMocUic.h" -#include "cmsys/FStream.hxx" -#include "cmsys/Terminal.h" #include <algorithm> #include <array> #include <list> @@ -15,12 +13,8 @@ #include "cmAlgorithms.h" #include "cmCryptoHash.h" -#include "cmFilePathChecksum.h" -#include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmStateDirectory.h" -#include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmake.h" @@ -32,37 +26,9 @@ static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH"; static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH"; -static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH"; // -- Static functions -static std::string HeadLine(std::string const& title) -{ - std::string head = title; - head += '\n'; - head.append(head.size() - 1, '-'); - head += '\n'; - return head; -} - -static std::string QuotedCommand(std::vector<std::string> const& command) -{ - std::string res; - for (std::string const& item : command) { - if (!res.empty()) { - res.push_back(' '); - } - std::string const cesc = cmQtAutoGen::Quoted(item); - if (item.empty() || (cesc.size() > (item.size() + 2)) || - (cesc.find(' ') != std::string::npos)) { - res += cesc; - } else { - res += item; - } - } - return res; -} - static std::string SubDirPrefix(std::string const& fileName) { std::string res(cmSystemTools::GetFilenamePath(fileName)); @@ -72,56 +38,6 @@ static std::string SubDirPrefix(std::string const& fileName) return res; } -static bool ReadFile(std::string& content, std::string const& filename, - std::string* error = nullptr) -{ - bool success = false; - if (cmSystemTools::FileExists(filename)) { - std::size_t const length = cmSystemTools::FileLength(filename); - cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); - if (ifs) { - content.resize(length); - ifs.read(&content.front(), content.size()); - if (ifs) { - success = true; - } else { - content.clear(); - if (error != nullptr) { - error->append("Reading from the file failed."); - } - } - } else if (error != nullptr) { - error->append("Opening the file for reading failed."); - } - } else if (error != nullptr) { - error->append("The file does not exist."); - } - return success; -} - -/** - * @brief Tests if buildFile is older than sourceFile - * @return True if buildFile is older than sourceFile. - * False may indicate an error. - */ -static bool FileIsOlderThan(std::string const& buildFile, - std::string const& sourceFile, - std::string* error = nullptr) -{ - int result = 0; - if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) { - return (result < 0); - } - if (error != nullptr) { - error->append( - "File modification time comparison failed for the files\n "); - error->append(cmQtAutoGen::Quoted(buildFile)); - error->append("\nand\n "); - error->append(cmQtAutoGen::Quoted(sourceFile)); - } - return false; -} - static bool ListContains(std::vector<std::string> const& list, std::string const& entry) { @@ -130,25 +46,15 @@ static bool ListContains(std::vector<std::string> const& list, // -- Class methods -cmQtAutoGenerators::cmQtAutoGenerators() +cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() : MultiConfig(cmQtAutoGen::WRAP) , IncludeProjectDirsBefore(false) - , Verbose(cmSystemTools::HasEnv("VERBOSE")) - , ColorOutput(true) + , QtVersionMajor(4) , MocSettingsChanged(false) , MocPredefsChanged(false) , MocRelaxedMode(false) , UicSettingsChanged(false) - , RccSettingsChanged(false) { - { - std::string colorEnv; - cmSystemTools::GetEnv("COLOR", colorEnv); - if (!colorEnv.empty()) { - this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str()); - } - } - // Precompile regular expressions this->MocRegExpInclude.compile( "[\n][ \t]*#[ \t]*include[ \t]+" @@ -157,39 +63,7 @@ cmQtAutoGenerators::cmQtAutoGenerators() "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); } -bool cmQtAutoGenerators::Run(std::string const& targetDirectory, - std::string const& config) -{ - cmake cm(cmake::RoleScript); - cm.SetHomeOutputDirectory(targetDirectory); - cm.SetHomeDirectory(targetDirectory); - cm.GetCurrentSnapshot().SetDefaultDefinitions(); - cmGlobalGenerator gg(&cm); - - cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); - snapshot.GetDirectory().SetCurrentBinary(targetDirectory); - snapshot.GetDirectory().SetCurrentSource(targetDirectory); - - auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot); - gg.SetCurrentMakefile(makefile.get()); - - bool success = false; - if (this->InitInfoFile(makefile.get(), targetDirectory, config)) { - // Read latest settings - this->SettingsFileRead(makefile.get()); - if (this->Process()) { - // Write current settings - if (this->SettingsFileWrite()) { - success = true; - } - } - } - return success; -} - -bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, - std::string const& targetDirectory, - std::string const& config) +bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile) { // -- Meta this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); @@ -233,12 +107,12 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } return lists; }; - auto InfoGetConfig = [makefile, &config](const char* key) -> std::string { + auto InfoGetConfig = [makefile, this](const char* key) -> std::string { const char* valueConf = nullptr; { std::string keyConf = key; keyConf += '_'; - keyConf += config; + keyConf += this->GetInfoConfig(); valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { @@ -254,11 +128,8 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, }; // -- Read info file - this->InfoFile = cmSystemTools::CollapseFullPath(targetDirectory); - cmSystemTools::ConvertToUnixSlashes(this->InfoFile); - this->InfoFile += "/AutogenInfo.cmake"; - if (!makefile->ReadListFile(this->InfoFile.c_str())) { - this->LogFileError(cmQtAutoGen::GEN, this->InfoFile, + if (!makefile->ReadListFile(this->GetInfoFile().c_str())) { + this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(), "File processing failed"); return false; } @@ -268,7 +139,14 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX"); if (this->ConfigSuffix.empty()) { this->ConfigSuffix = "_"; - this->ConfigSuffix += config; + this->ConfigSuffix += this->GetInfoConfig(); + } + + this->SettingsFile = InfoGetConfig("AM_SETTINGS_FILE"); + if (this->SettingsFile.empty()) { + this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(), + "Settings file name missing"); + return false; } // - Files and directories @@ -280,25 +158,18 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); this->AutogenBuildDir = InfoGet("AM_BUILD_DIR"); if (this->AutogenBuildDir.empty()) { - this->LogFileError(cmQtAutoGen::GEN, this->InfoFile, + this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(), "Autogen build directory missing"); return false; } // - Qt environment - this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR"); - this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR"); + if (!cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"), + &this->QtVersionMajor)) { + this->QtVersionMajor = 4; + } this->MocExecutable = InfoGet("AM_QT_MOC_EXECUTABLE"); this->UicExecutable = InfoGet("AM_QT_UIC_EXECUTABLE"); - this->RccExecutable = InfoGet("AM_QT_RCC_EXECUTABLE"); - - // Check Qt version - if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { - this->LogFileError(cmQtAutoGen::GEN, this->InfoFile, - "Unsupported Qt version: " + - cmQtAutoGen::Quoted(this->QtMajorVersion)); - return false; - } // - Moc if (this->MocEnabled()) { @@ -327,7 +198,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, std::vector<std::string> const mocDependFilters = InfoGetList("AM_MOC_DEPEND_FILTERS"); // Insert Q_PLUGIN_METADATA dependency filter - if (this->QtMajorVersion != "4") { + if (this->QtVersionMajor != 4) { this->MocDependFilterPush("Q_PLUGIN_METADATA", "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" "[^\\)]*FILE[ \t]*\"([^\"]+)\""); @@ -344,7 +215,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } } else { this->LogFileError( - cmQtAutoGen::MOC, this->InfoFile, + cmQtAutoGen::MOC, this->GetInfoFile(), "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2"); return false; } @@ -365,7 +236,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, std::ostringstream ost; ost << "files/options lists sizes missmatch (" << sources.size() << "/" << options.size() << ")"; - this->LogFileError(cmQtAutoGen::UIC, this->InfoFile, ost.str()); + this->LogFileError(cmQtAutoGen::UIC, this->GetInfoFile(), ost.str()); return false; } auto fitEnd = sources.cend(); @@ -379,53 +250,6 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } } - // - Rcc - if (this->RccEnabled()) { - // File lists - auto sources = InfoGetList("AM_RCC_SOURCES"); - auto builds = InfoGetList("AM_RCC_BUILDS"); - auto options = InfoGetLists("AM_RCC_OPTIONS"); - auto inputs = InfoGetLists("AM_RCC_INPUTS"); - - if (sources.size() != builds.size()) { - std::ostringstream ost; - ost << "sources, builds lists sizes missmatch (" << sources.size() << "/" - << builds.size() << ")"; - this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str()); - return false; - } - if (sources.size() != options.size()) { - std::ostringstream ost; - ost << "sources, options lists sizes missmatch (" << sources.size() - << "/" << options.size() << ")"; - this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str()); - return false; - } - if (sources.size() != inputs.size()) { - std::ostringstream ost; - ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/" - << inputs.size() << ")"; - this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str()); - return false; - } - { - auto srcItEnd = sources.end(); - auto srcIt = sources.begin(); - auto bldIt = builds.begin(); - auto optIt = options.begin(); - auto inpIt = inputs.begin(); - while (srcIt != srcItEnd) { - this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt), - std::move(*optIt), - std::move(*inpIt) }); - ++srcIt; - ++bldIt; - ++optIt; - ++inpIt; - } - } - } - // Initialize source file jobs { // Utility lambdas @@ -585,21 +409,10 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } } - // - Old settings file - { - this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory); - cmSystemTools::ConvertToUnixSlashes(this->SettingsFile); - this->SettingsFile += "/AutogenOldSettings"; - if (this->MultiConfig != cmQtAutoGen::SINGLE) { - this->SettingsFile += this->ConfigSuffix; - } - this->SettingsFile += ".cmake"; - } - return true; } -void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) +void cmQtAutoGeneratorMocUic::SettingsFileRead(cmMakefile* makefile) { // Compose current settings strings { @@ -631,20 +444,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) str += sep; this->SettingsStringUic = crypt.HashString(str); } - if (this->RccEnabled()) { - std::string str; - str += this->RccExecutable; - for (const RccJob& rccJob : this->RccJobs) { - str += sep; - str += rccJob.QrcFile; - str += sep; - str += rccJob.RccFile; - str += sep; - str += cmJoin(rccJob.Options, ";"); - } - str += sep; - this->SettingsStringRcc = crypt.HashString(str); - } } // Read old settings @@ -659,9 +458,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) if (!SMatch(SettingsKeyUic, this->SettingsStringUic)) { this->UicSettingsChanged = true; } - if (!SMatch(SettingsKeyRcc, this->SettingsStringRcc)) { - this->RccSettingsChanged = true; - } } // In case any setting changed remove the old settings file. // This triggers a full rebuild on the next run if the current @@ -673,16 +469,15 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) // If the file could not be read re-generate everythiung. this->MocSettingsChanged = true; this->UicSettingsChanged = true; - this->RccSettingsChanged = true; } } -bool cmQtAutoGenerators::SettingsFileWrite() +bool cmQtAutoGeneratorMocUic::SettingsFileWrite() { bool success = true; // Only write if any setting changed if (this->SettingsChanged()) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " + cmQtAutoGen::Quoted(this->SettingsFile)); } @@ -699,7 +494,6 @@ bool cmQtAutoGenerators::SettingsFileWrite() }; SettingAppend(SettingsKeyMoc, this->SettingsStringMoc); SettingAppend(SettingsKeyUic, this->SettingsStringUic); - SettingAppend(SettingsKeyRcc, this->SettingsStringRcc); } // Write settings file if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) { @@ -713,7 +507,7 @@ bool cmQtAutoGenerators::SettingsFileWrite() return success; } -bool cmQtAutoGenerators::Process() +bool cmQtAutoGeneratorMocUic::Process(cmMakefile* makefile) { // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but @@ -723,6 +517,12 @@ bool cmQtAutoGenerators::Process() // moc file is included anywhere a moc_<filename>.cpp file is created and // included in the mocs_compilation.cpp file. + if (!this->InitInfoFile(makefile)) { + return false; + } + // Read latest settings + this->SettingsFileRead(makefile); + // Create AUTOGEN include directory { std::string const incDirAbs = cmSystemTools::CollapseCombinedPath( @@ -758,7 +558,8 @@ bool cmQtAutoGenerators::Process() if (!this->UicGenerateAll()) { return false; } - if (!this->RccGenerateAll()) { + + if (!this->SettingsFileWrite()) { return false; } @@ -768,12 +569,12 @@ bool cmQtAutoGenerators::Process() /** * @return True on success */ -bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename, - const SourceJob& job) +bool cmQtAutoGeneratorMocUic::ParseSourceFile(std::string const& absFilename, + const SourceJob& job) { std::string contentText; std::string error; - bool success = ReadFile(contentText, absFilename, &error); + bool success = this->FileRead(contentText, absFilename, &error); if (success) { if (!contentText.empty()) { if (job.Moc) { @@ -796,12 +597,12 @@ bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename, /** * @return True on success */ -bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename, - const SourceJob& job) +bool cmQtAutoGeneratorMocUic::ParseHeaderFile(std::string const& absFilename, + const SourceJob& job) { std::string contentText; std::string error; - bool success = ReadFile(contentText, absFilename, &error); + bool success = this->FileRead(contentText, absFilename, &error); if (success) { if (!contentText.empty()) { if (job.Moc) { @@ -824,7 +625,7 @@ bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename, /** * @return True on success */ -bool cmQtAutoGenerators::ParsePostprocess() +bool cmQtAutoGeneratorMocUic::ParsePostprocess() { bool success = true; // Read missing dependencies @@ -832,7 +633,7 @@ bool cmQtAutoGenerators::ParsePostprocess() if (!item->DependsValid) { std::string content; std::string error; - if (ReadFile(content, item->SourceFile, &error)) { + if (this->FileRead(content, item->SourceFile, &error)) { this->MocFindDepends(item->SourceFile, content, item->Depends); item->DependsValid = true; } else { @@ -855,7 +656,7 @@ bool cmQtAutoGenerators::ParsePostprocess() * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const +bool cmQtAutoGeneratorMocUic::MocSkip(std::string const& absFilename) const { if (this->MocEnabled()) { // Test if the file name is on the skip list @@ -870,8 +671,8 @@ bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const * @brief Tests if the C++ content requires moc processing * @return True if moc is required */ -bool cmQtAutoGenerators::MocRequired(std::string const& contentText, - std::string* macroName) +bool cmQtAutoGeneratorMocUic::MocRequired(std::string const& contentText, + std::string* macroName) { for (KeyRegExp& filter : this->MocMacroFilters) { // Run a simple find string operation before the expensive @@ -889,7 +690,7 @@ bool cmQtAutoGenerators::MocRequired(std::string const& contentText, return false; } -std::string cmQtAutoGenerators::MocStringMacros() const +std::string cmQtAutoGeneratorMocUic::MocStringMacros() const { std::string res; const auto itB = this->MocMacroFilters.cbegin(); @@ -911,7 +712,7 @@ std::string cmQtAutoGenerators::MocStringMacros() const return res; } -std::string cmQtAutoGenerators::MocStringHeaders( +std::string cmQtAutoGeneratorMocUic::MocStringHeaders( std::string const& fileBase) const { std::string res = fileBase; @@ -921,7 +722,7 @@ std::string cmQtAutoGenerators::MocStringHeaders( return res; } -std::string cmQtAutoGenerators::MocFindIncludedHeader( +std::string cmQtAutoGeneratorMocUic::MocFindIncludedHeader( std::string const& sourcePath, std::string const& includeBase) const { std::string header; @@ -944,7 +745,7 @@ std::string cmQtAutoGenerators::MocFindIncludedHeader( return header; } -bool cmQtAutoGenerators::MocFindIncludedFile( +bool cmQtAutoGeneratorMocUic::MocFindIncludedFile( std::string& absFile, std::string const& sourcePath, std::string const& includeString) const { @@ -974,8 +775,8 @@ bool cmQtAutoGenerators::MocFindIncludedFile( return success; } -bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key, - std::string const& regExp) +bool cmQtAutoGeneratorMocUic::MocDependFilterPush(std::string const& key, + std::string const& regExp) { std::string error; if (!key.empty()) { @@ -1009,9 +810,9 @@ bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key, return true; } -void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename, - std::string const& contentText, - std::set<std::string>& depends) +void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename, + std::string const& contentText, + std::set<std::string>& depends) { if (this->MocDependFilters.empty() && contentText.empty()) { return; @@ -1040,7 +841,7 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename, std::string incFile; if (this->MocFindIncludedFile(incFile, sourcePath, match)) { depends.insert(incFile); - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n " + cmQtAutoGen::Quoted(absFilename) + "\n " + cmQtAutoGen::Quoted(incFile)); @@ -1057,10 +858,10 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename, /** * @return True on success */ -bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename, - std::string const& contentText) +bool cmQtAutoGeneratorMocUic::MocParseSourceContent( + std::string const& absFilename, std::string const& contentText) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename); } @@ -1296,10 +1097,10 @@ bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename, return true; } -void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename, - std::string const& contentText) +void cmQtAutoGeneratorMocUic::MocParseHeaderContent( + std::string const& absFilename, std::string const& contentText) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename); } @@ -1329,7 +1130,7 @@ void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename, } } -bool cmQtAutoGenerators::MocGenerateAll() +bool cmQtAutoGeneratorMocUic::MocGenerateAll() { if (!this->MocEnabled()) { return true; @@ -1384,7 +1185,7 @@ bool cmQtAutoGenerators::MocGenerateAll() if (!this->MocPredefsCmd.empty()) { if (this->MocSettingsChanged || !cmSystemTools::FileExists(this->MocPredefsFileAbs)) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel); } @@ -1419,7 +1220,7 @@ bool cmQtAutoGenerators::MocGenerateAll() } } else { // Touch to update the time stamp - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Touching moc_predefs " + this->MocPredefsFileRel); } @@ -1470,7 +1271,7 @@ bool cmQtAutoGenerators::MocGenerateAll() if (this->FileDiffers(this->MocCompFileAbs, mocs)) { // Actually write mocs compilation file - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating MOC compilation " + this->MocCompFileRel); } if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, mocs)) { @@ -1480,7 +1281,7 @@ bool cmQtAutoGenerators::MocGenerateAll() } } else if (autoNameGenerated) { // Only touch mocs compilation file - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Touching mocs compilation " + this->MocCompFileRel); } @@ -1494,8 +1295,8 @@ bool cmQtAutoGenerators::MocGenerateAll() /** * @return True on success */ -bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, - bool* generated) +bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob, + bool* generated) { bool success = true; @@ -1505,7 +1306,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, bool generate = false; std::string generateReason; if (!generate && !cmSystemTools::FileExists(mocFileAbs.c_str())) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from its source file "; @@ -1515,7 +1316,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, generate = true; } if (!generate && this->MocSettingsChanged) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from "; @@ -1525,7 +1326,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, generate = true; } if (!generate && this->MocPredefsChanged) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from "; @@ -1537,7 +1338,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, if (!generate) { std::string error; if (FileIsOlderThan(mocFileAbs, mocJob.SourceFile, &error)) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " because it's older than its source file "; @@ -1556,7 +1357,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, std::string error; for (std::string const& depFile : mocJob.Depends) { if (FileIsOlderThan(mocFileAbs, depFile, &error)) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from "; @@ -1577,7 +1378,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, if (generate) { // Log - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating MOC source " + mocJob.BuildFileRel); this->LogInfo(cmQtAutoGen::MOC, generateReason); } @@ -1627,7 +1428,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const +bool cmQtAutoGeneratorMocUic::UicSkip(std::string const& absFilename) const { if (this->UicEnabled()) { // Test if the file name is on the skip list @@ -1638,10 +1439,10 @@ bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const return true; } -bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename, - std::string const& contentText) +bool cmQtAutoGeneratorMocUic::UicParseContent(std::string const& absFilename, + std::string const& contentText) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename); } @@ -1689,9 +1490,9 @@ bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename, return true; } -bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, - std::string const& sourceFile, - std::string const& includeString) +bool cmQtAutoGeneratorMocUic::UicFindIncludedFile( + std::string& absFile, std::string const& sourceFile, + std::string const& includeString) { bool success = false; std::string searchFile = @@ -1753,7 +1554,7 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, return success; } -bool cmQtAutoGenerators::UicGenerateAll() +bool cmQtAutoGeneratorMocUic::UicGenerateAll() { if (!this->UicEnabled()) { return true; @@ -1817,7 +1618,7 @@ bool cmQtAutoGenerators::UicGenerateAll() /** * @return True on success */ -bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) +bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob) { bool success = true; @@ -1827,7 +1628,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) bool generate = false; std::string generateReason; if (!generate && !cmSystemTools::FileExists(uicFileAbs.c_str())) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(uicFileAbs); generateReason += " from its source file "; @@ -1837,7 +1638,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) generate = true; } if (!generate && this->UicSettingsChanged) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(uicFileAbs); generateReason += " from "; @@ -1849,7 +1650,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) if (!generate) { std::string error; if (FileIsOlderThan(uicFileAbs, uicJob.SourceFile, &error)) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(uicFileAbs); generateReason += " because it's older than its source file "; @@ -1865,7 +1666,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) } if (generate) { // Log - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating UIC header " + uicJob.BuildFileRel); this->LogInfo(cmQtAutoGen::UIC, generateReason); } @@ -1880,7 +1681,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) auto optionIt = this->UicOptions.find(uicJob.SourceFile); if (optionIt != this->UicOptions.end()) { cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second, - (this->QtMajorVersion == "5")); + (this->QtVersionMajor == 5)); } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } @@ -1911,413 +1712,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) return success; } -bool cmQtAutoGenerators::RccGenerateAll() -{ - if (!this->RccEnabled()) { - return true; - } - - // Generate rcc files - for (const RccJob& rccJob : this->RccJobs) { - if (!this->RccGenerateFile(rccJob)) { - return false; - } - } - return true; -} - -/** - * @return True on success - */ -bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) -{ - bool success = true; - bool rccGenerated = false; - - std::string rccFileAbs; - { - std::string suffix; - switch (this->MultiConfig) { - case cmQtAutoGen::SINGLE: - break; - case cmQtAutoGen::WRAP: - suffix = "_CMAKE"; - suffix += this->ConfigSuffix; - suffix += "_"; - break; - case cmQtAutoGen::FULL: - suffix = this->ConfigSuffix; - break; - } - rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(rccJob.RccFile, suffix); - } - std::string const rccFileRel = cmSystemTools::RelativePath( - this->AutogenBuildDir.c_str(), rccFileAbs.c_str()); - - // Check if regeneration is required - bool generate = false; - std::string generateReason; - if (!cmSystemTools::FileExists(rccJob.QrcFile)) { - { - std::string error = "Could not find the file\n "; - error += cmQtAutoGen::Quoted(rccJob.QrcFile); - this->LogError(cmQtAutoGen::RCC, error); - } - success = false; - } - if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " from its source file "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - generateReason += " because it doesn't exist"; - } - generate = true; - } - if (success && !generate && this->RccSettingsChanged) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " from "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - generateReason += " because the RCC settings changed"; - } - generate = true; - } - if (success && !generate) { - std::string error; - if (FileIsOlderThan(rccFileAbs, rccJob.QrcFile, &error)) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " because it is older than "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - } - generate = true; - } else { - if (!error.empty()) { - this->LogError(cmQtAutoGen::RCC, error); - success = false; - } - } - } - if (success && !generate) { - // Acquire input file list - std::vector<std::string> readFiles; - std::vector<std::string> const* files = nullptr; - if (!rccJob.Inputs.empty()) { - files = &rccJob.Inputs; - } else { - // Read input file list from qrc file - std::string error; - if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable, - rccJob.QrcFile, readFiles, &error)) { - files = &readFiles; - } else { - this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error); - success = false; - } - } - // Test if any input file is newer than the build file - if (files != nullptr) { - std::string error; - for (std::string const& resFile : *files) { - if (!cmSystemTools::FileExists(resFile.c_str())) { - error = "Could not find the file\n "; - error += cmQtAutoGen::Quoted(resFile); - error += "\nwhich is listed in\n "; - error += cmQtAutoGen::Quoted(rccJob.QrcFile); - break; - } - if (FileIsOlderThan(rccFileAbs, resFile, &error)) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " from "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - generateReason += " because it is older than "; - generateReason += cmQtAutoGen::Quoted(resFile); - } - generate = true; - break; - } - if (!error.empty()) { - break; - } - } - // Print error - if (!error.empty()) { - this->LogError(cmQtAutoGen::RCC, error); - success = false; - } - } - } - // Regenerate on demand - if (generate) { - // Log - if (this->Verbose) { - this->LogBold("Generating RCC source " + rccFileRel); - this->LogInfo(cmQtAutoGen::RCC, generateReason); - } - - // Make sure the parent directory exists - if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) { - // Compose rcc command - std::vector<std::string> cmd; - cmd.push_back(this->RccExecutable); - cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end()); - cmd.push_back("-o"); - cmd.push_back(rccFileAbs); - cmd.push_back(rccJob.QrcFile); - - std::string output; - if (this->RunCommand(cmd, output)) { - // Success - rccGenerated = true; - } else { - { - std::string emsg = "rcc failed for\n "; - emsg += cmQtAutoGen::Quoted(rccJob.QrcFile); - this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output); - } - cmSystemTools::RemoveFile(rccFileAbs); - success = false; - } - } else { - // Parent directory creation failed - success = false; - } - } - - // Generate a wrapper source file on demand - if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) { - // Wrapper file name - std::string const& wrapperFileAbs = rccJob.RccFile; - std::string const wrapperFileRel = cmSystemTools::RelativePath( - this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str()); - // Wrapper file content - std::string content = "// This is an autogenerated configuration " - "wrapper file. Changes will be overwritten.\n" - "#include \""; - content += cmSystemTools::GetFilenameName(rccFileRel); - content += "\"\n"; - // Write content to file - if (this->FileDiffers(wrapperFileAbs, content)) { - // Write new wrapper file - if (this->Verbose) { - this->LogBold("Generating RCC wrapper " + wrapperFileRel); - } - if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) { - this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs, - "rcc wrapper file writing failed"); - success = false; - } - } else if (rccGenerated) { - // Just touch the wrapper file - if (this->Verbose) { - this->LogInfo(cmQtAutoGen::RCC, - "Touching RCC wrapper " + wrapperFileRel); - } - cmSystemTools::Touch(wrapperFileAbs, false); - } - } - - return success; -} - -void cmQtAutoGenerators::LogBold(std::string const& message) const -{ - cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | - cmsysTerminal_Color_ForegroundBold, - message.c_str(), true, this->ColorOutput); -} - -void cmQtAutoGenerators::LogInfo(cmQtAutoGen::Generator genType, - std::string const& message) const -{ - std::string msg = cmQtAutoGen::GeneratorName(genType); - msg += ": "; - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - cmSystemTools::Stdout(msg.c_str(), msg.size()); -} - -void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType, - std::string const& message) const -{ - std::string msg = cmQtAutoGen::GeneratorName(genType); - msg += " warning:"; - if (message.find('\n') == std::string::npos) { - // Single line message - msg.push_back(' '); - } else { - // Multi line message - msg.push_back('\n'); - } - // Message - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - cmSystemTools::Stdout(msg.c_str(), msg.size()); -} - -void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const -{ - std::string msg = " "; - msg += cmQtAutoGen::Quoted(filename); - msg.push_back('\n'); - // Message - msg += message; - this->LogWarning(genType, msg); -} - -void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType, - std::string const& message) const -{ - std::string msg; - msg.push_back('\n'); - msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error"); - // Message - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - cmSystemTools::Stderr(msg.c_str(), msg.size()); -} - -void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const -{ - std::string emsg = " "; - emsg += cmQtAutoGen::Quoted(filename); - emsg += '\n'; - // Message - emsg += message; - this->LogError(genType, emsg); -} - -void cmQtAutoGenerators::LogCommandError( - cmQtAutoGen::Generator genType, std::string const& message, - std::vector<std::string> const& command, std::string const& output) const -{ - std::string msg; - msg.push_back('\n'); - msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error"); - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - msg += HeadLine("Command"); - msg += QuotedCommand(command); - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - msg += HeadLine("Output"); - msg += output; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - cmSystemTools::Stderr(msg.c_str(), msg.size()); -} - -/** - * @brief Generates the parent directory of the given file on demand - * @return True on success - */ -bool cmQtAutoGenerators::MakeParentDirectory(cmQtAutoGen::Generator genType, - std::string const& filename) const -{ - bool success = true; - std::string const dirName = cmSystemTools::GetFilenamePath(filename); - if (!dirName.empty()) { - if (!cmSystemTools::MakeDirectory(dirName)) { - this->LogFileError(genType, filename, - "Could not create parent directory"); - success = false; - } - } - return success; -} - -bool cmQtAutoGenerators::FileDiffers(std::string const& filename, - std::string const& content) -{ - bool differs = true; - { - std::string oldContents; - if (ReadFile(oldContents, filename)) { - differs = (oldContents != content); - } - } - return differs; -} - -bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& content) -{ - std::string error; - // Make sure the parent directory exists - if (this->MakeParentDirectory(genType, filename)) { - cmsys::ofstream outfile; - outfile.open(filename.c_str(), - (std::ios::out | std::ios::binary | std::ios::trunc)); - if (outfile) { - outfile << content; - // Check for write errors - if (!outfile.good()) { - error = "File writing failed"; - } - } else { - error = "Opening file for writing failed"; - } - } - if (!error.empty()) { - this->LogFileError(genType, filename, error); - return false; - } - return true; -} - -/** - * @brief Runs a command and returns true on success - * @return True on success - */ -bool cmQtAutoGenerators::RunCommand(std::vector<std::string> const& command, - std::string& output) const -{ - // Log command - if (this->Verbose) { - std::string qcmd = QuotedCommand(command); - qcmd.push_back('\n'); - cmSystemTools::Stdout(qcmd.c_str(), qcmd.size()); - } - // Execute command - int retVal = 0; - bool res = cmSystemTools::RunSingleCommand( - command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE); - return (res && (retVal == 0)); -} - /** * @brief Tries to find the header file to the given file base path by * appending different header extensions * @return True on success */ -bool cmQtAutoGenerators::FindHeader(std::string& header, - std::string const& testBasePath) const +bool cmQtAutoGeneratorMocUic::FindHeader(std::string& header, + std::string const& testBasePath) const { for (std::string const& ext : this->HeaderExtensions) { std::string testFilePath(testBasePath); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGeneratorMocUic.h index a7bb538..d510939 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGeneratorMocUic.h @@ -1,12 +1,13 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenerators_h -#define cmQtAutoGenerators_h +#ifndef cmQtAutoGeneratorMocUic_h +#define cmQtAutoGeneratorMocUic_h #include "cmConfigure.h" // IWYU pragma: keep #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" #include "cmsys/RegularExpression.hxx" #include <map> @@ -17,12 +18,11 @@ class cmMakefile; -class cmQtAutoGenerators +class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator { - CM_DISABLE_COPY(cmQtAutoGenerators) + CM_DISABLE_COPY(cmQtAutoGeneratorMocUic) public: - cmQtAutoGenerators(); - bool Run(std::string const& targetDirectory, std::string const& config); + cmQtAutoGeneratorMocUic(); private: // -- Types @@ -80,30 +80,19 @@ private: std::string IncludeString; }; - /// @brief RCC job - struct RccJob - { - std::string QrcFile; - std::string RccFile; - std::vector<std::string> Options; - std::vector<std::string> Inputs; - }; - // -- Initialization - bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory, - std::string const& config); + bool InitInfoFile(cmMakefile* makefile); // -- Settings file void SettingsFileRead(cmMakefile* makefile); bool SettingsFileWrite(); bool SettingsChanged() const { - return (this->MocSettingsChanged || this->RccSettingsChanged || - this->UicSettingsChanged); + return (this->MocSettingsChanged || this->UicSettingsChanged); } // -- Central processing - bool Process(); + bool Process(cmMakefile* makefile) override; // -- Source parsing bool ParseSourceFile(std::string const& absFilename, const SourceJob& job); @@ -146,54 +135,17 @@ private: bool UicGenerateAll(); bool UicGenerateFile(const UicJob& uicJob); - // -- Rcc - bool RccEnabled() const { return !this->RccExecutable.empty(); } - bool RccGenerateAll(); - bool RccGenerateFile(const RccJob& rccJob); - - // -- Log info - void LogBold(std::string const& message) const; - void LogInfo(cmQtAutoGen::Generator genType, - std::string const& message) const; - // -- Log warning - void LogWarning(cmQtAutoGen::Generator genType, - std::string const& message) const; - void LogFileWarning(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const; - // -- Log error - void LogError(cmQtAutoGen::Generator genType, - std::string const& message) const; - void LogFileError(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const; - void LogCommandError(cmQtAutoGen::Generator genType, - std::string const& message, - std::vector<std::string> const& command, - std::string const& output) const; - // -- Utility - bool MakeParentDirectory(cmQtAutoGen::Generator genType, - std::string const& filename) const; - bool FileDiffers(std::string const& filename, std::string const& content); - bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename, - std::string const& content); bool FindHeader(std::string& header, std::string const& testBasePath) const; - bool RunCommand(std::vector<std::string> const& command, - std::string& output) const; // -- Meta - std::string InfoFile; std::string ConfigSuffix; cmQtAutoGen::MultiConfig MultiConfig; // -- Settings bool IncludeProjectDirsBefore; - bool Verbose; - bool ColorOutput; std::string SettingsFile; std::string SettingsStringMoc; std::string SettingsStringUic; - std::string SettingsStringRcc; // -- Directories std::string ProjectSourceDir; std::string ProjectBinaryDir; @@ -202,11 +154,9 @@ private: std::string AutogenBuildDir; std::string AutogenIncludeDir; // -- Qt environment - std::string QtMajorVersion; - std::string QtMinorVersion; + unsigned long QtVersionMajor; std::string MocExecutable; std::string UicExecutable; - std::string RccExecutable; // -- File lists std::map<std::string, SourceJob> HeaderJobs; std::map<std::string, SourceJob> SourceJobs; @@ -240,9 +190,6 @@ private: std::vector<std::string> UicSearchPaths; cmsys::RegularExpression UicRegExpInclude; std::vector<std::unique_ptr<UicJob>> UicJobs; - // -- Rcc - bool RccSettingsChanged; - std::vector<RccJob> RccJobs; }; #endif diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx new file mode 100644 index 0000000..3c9f1a8 --- /dev/null +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -0,0 +1,425 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGen.h" +#include "cmQtAutoGeneratorRcc.h" + +#include "cmAlgorithms.h" +#include "cmCryptoHash.h" +#include "cmMakefile.h" +#include "cmOutputConverter.h" +#include "cmSystemTools.h" + +// -- Static variables + +static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH"; + +// -- Class methods + +cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc() + : MultiConfig(cmQtAutoGen::WRAP) + , SettingsChanged(false) +{ +} + +bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile) +{ + // Utility lambdas + auto InfoGet = [makefile](const char* key) { + return makefile->GetSafeDefinition(key); + }; + auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + return list; + }; + auto InfoGetConfig = [makefile, this](const char* key) -> std::string { + const char* valueConf = nullptr; + { + std::string keyConf = key; + keyConf += '_'; + keyConf += this->GetInfoConfig(); + valueConf = makefile->GetDefinition(keyConf); + } + if (valueConf == nullptr) { + valueConf = makefile->GetSafeDefinition(key); + } + return std::string(valueConf); + }; + auto InfoGetConfigList = + [&InfoGetConfig](const char* key) -> std::vector<std::string> { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); + return list; + }; + + // -- Read info file + if (!makefile->ReadListFile(this->GetInfoFile().c_str())) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "File processing failed"); + return false; + } + + // -- Meta + this->MultiConfig = + cmQtAutoGen::MultiConfigType(InfoGet("ARCC_MULTI_CONFIG")); + this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX"); + if (this->ConfigSuffix.empty()) { + this->ConfigSuffix = "_"; + this->ConfigSuffix += this->GetInfoConfig(); + } + + this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE"); + + // - Files and directories + this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR"); + this->ProjectBinaryDir = InfoGet("ARCC_CMAKE_BINARY_DIR"); + this->CurrentSourceDir = InfoGet("ARCC_CMAKE_CURRENT_SOURCE_DIR"); + this->CurrentBinaryDir = InfoGet("ARCC_CMAKE_CURRENT_BINARY_DIR"); + this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR"); + + // - Qt environment + this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE"); + this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS"); + + // - Job + this->QrcFile = InfoGet("ARCC_SOURCE"); + this->RccFile = InfoGet("ARCC_OUTPUT"); + this->Options = InfoGetConfigList("ARCC_OPTIONS"); + this->Inputs = InfoGetList("ARCC_INPUTS"); + + // - Validity checks + if (this->SettingsFile.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "Settings file name missing"); + return false; + } + if (this->AutogenBuildDir.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "Autogen build directory missing"); + return false; + } + if (this->RccExecutable.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "rcc executable missing"); + return false; + } + if (this->QrcFile.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "rcc input file missing"); + return false; + } + if (this->RccFile.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "rcc output file missing"); + return false; + } + + // Init derived information + // ------------------------ + + // Init file path checksum generator + this->FilePathChecksum.setupParentDirs( + this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir, + this->ProjectBinaryDir); + + return true; +} + +void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile) +{ + // Compose current settings strings + { + cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); + std::string const sep(" ~~~ "); + { + std::string str; + str += this->RccExecutable; + str += sep; + str += cmJoin(this->RccListOptions, ";"); + str += sep; + str += this->QrcFile; + str += sep; + str += this->RccFile; + str += sep; + str += cmJoin(this->Options, ";"); + str += sep; + str += cmJoin(this->Inputs, ";"); + str += sep; + this->SettingsString = crypt.HashString(str); + } + } + + // Read old settings + if (makefile->ReadListFile(this->SettingsFile.c_str())) { + { + auto SMatch = [makefile](const char* key, std::string const& value) { + return (value == makefile->GetSafeDefinition(key)); + }; + if (!SMatch(SettingsKeyRcc, this->SettingsString)) { + this->SettingsChanged = true; + } + } + // In case any setting changed remove the old settings file. + // This triggers a full rebuild on the next run if the current + // build is aborted before writing the current settings in the end. + if (this->SettingsChanged) { + cmSystemTools::RemoveFile(this->SettingsFile); + } + } else { + // If the file could not be read re-generate everythiung. + this->SettingsChanged = true; + } +} + +bool cmQtAutoGeneratorRcc::SettingsFileWrite() +{ + bool success = true; + // Only write if any setting changed + if (this->SettingsChanged) { + if (this->GetVerbose()) { + this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " + + cmQtAutoGen::Quoted(this->SettingsFile)); + } + // Compose settings file content + std::string settings; + { + auto SettingAppend = [&settings](const char* key, + std::string const& value) { + settings += "set("; + settings += key; + settings += " "; + settings += cmOutputConverter::EscapeForCMake(value); + settings += ")\n"; + }; + SettingAppend(SettingsKeyRcc, this->SettingsString); + } + // Write settings file + if (!this->FileWrite(cmQtAutoGen::RCC, this->SettingsFile, settings)) { + this->LogFileError(cmQtAutoGen::RCC, this->SettingsFile, + "Settings file writing failed"); + // Remove old settings file to trigger a full rebuild on the next run + cmSystemTools::RemoveFile(this->SettingsFile); + success = false; + } + } + return success; +} + +bool cmQtAutoGeneratorRcc::Process(cmMakefile* makefile) +{ + // Read info file + if (!this->InfoFileRead(makefile)) { + return false; + } + // Read latest settings + this->SettingsFileRead(makefile); + // Generate rcc file + if (!this->RccGenerate()) { + return false; + } + // Write latest settings + if (!this->SettingsFileWrite()) { + return false; + } + return true; +} + +/** + * @return True on success + */ +bool cmQtAutoGeneratorRcc::RccGenerate() +{ + bool success = true; + bool rccGenerated = false; + + std::string rccFileAbs; + { + std::string suffix; + switch (this->MultiConfig) { + case cmQtAutoGen::SINGLE: + break; + case cmQtAutoGen::WRAP: + suffix = "_CMAKE"; + suffix += this->ConfigSuffix; + suffix += "_"; + break; + case cmQtAutoGen::FULL: + suffix = this->ConfigSuffix; + break; + } + rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(this->RccFile, suffix); + } + std::string const rccFileRel = cmSystemTools::RelativePath( + this->AutogenBuildDir.c_str(), rccFileAbs.c_str()); + + // Check if regeneration is required + bool generate = false; + std::string generateReason; + if (!cmSystemTools::FileExists(this->QrcFile)) { + { + std::string error = "Could not find the file\n "; + error += cmQtAutoGen::Quoted(this->QrcFile); + this->LogError(cmQtAutoGen::RCC, error); + } + success = false; + } + if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " from its source file "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + generateReason += " because it doesn't exist"; + } + generate = true; + } + if (success && !generate && this->SettingsChanged) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " from "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + generateReason += " because the RCC settings changed"; + } + generate = true; + } + if (success && !generate) { + std::string error; + if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " because it is older than "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + } + generate = true; + } else { + if (!error.empty()) { + this->LogError(cmQtAutoGen::RCC, error); + success = false; + } + } + } + if (success && !generate) { + // Acquire input file list + std::vector<std::string> readFiles; + std::vector<std::string> const* files = nullptr; + if (!this->Inputs.empty()) { + files = &this->Inputs; + } else { + // Read input file list from qrc file + std::string error; + if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions, + this->QrcFile, readFiles, &error)) { + files = &readFiles; + } else { + this->LogFileError(cmQtAutoGen::RCC, this->QrcFile, error); + success = false; + } + } + // Test if any input file is newer than the build file + if (files != nullptr) { + std::string error; + for (std::string const& resFile : *files) { + if (!cmSystemTools::FileExists(resFile.c_str())) { + error = "Could not find the file\n "; + error += cmQtAutoGen::Quoted(resFile); + error += "\nwhich is listed in\n "; + error += cmQtAutoGen::Quoted(this->QrcFile); + break; + } + if (FileIsOlderThan(rccFileAbs, resFile, &error)) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " from "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + generateReason += " because it is older than "; + generateReason += cmQtAutoGen::Quoted(resFile); + } + generate = true; + break; + } + if (!error.empty()) { + break; + } + } + // Print error + if (!error.empty()) { + this->LogError(cmQtAutoGen::RCC, error); + success = false; + } + } + } + // Regenerate on demand + if (generate) { + // Log + if (this->GetVerbose()) { + this->LogBold("Generating RCC source " + rccFileRel); + this->LogInfo(cmQtAutoGen::RCC, generateReason); + } + + // Make sure the parent directory exists + if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) { + // Compose rcc command + std::vector<std::string> cmd; + cmd.push_back(this->RccExecutable); + cmd.insert(cmd.end(), this->Options.begin(), this->Options.end()); + cmd.push_back("-o"); + cmd.push_back(rccFileAbs); + cmd.push_back(this->QrcFile); + + std::string output; + if (this->RunCommand(cmd, output)) { + // Success + rccGenerated = true; + } else { + { + std::string emsg = "rcc failed for\n "; + emsg += cmQtAutoGen::Quoted(this->QrcFile); + this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output); + } + cmSystemTools::RemoveFile(rccFileAbs); + success = false; + } + } else { + // Parent directory creation failed + success = false; + } + } + + // Generate a wrapper source file on demand + if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) { + // Wrapper file name + std::string const& wrapperFileAbs = this->RccFile; + std::string const wrapperFileRel = cmSystemTools::RelativePath( + this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str()); + // Wrapper file content + std::string content = "// This is an autogenerated configuration " + "wrapper file. Changes will be overwritten.\n" + "#include \""; + content += cmSystemTools::GetFilenameName(rccFileRel); + content += "\"\n"; + // Write content to file + if (this->FileDiffers(wrapperFileAbs, content)) { + // Write new wrapper file + if (this->GetVerbose()) { + this->LogBold("Generating RCC wrapper " + wrapperFileRel); + } + if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) { + this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs, + "rcc wrapper file writing failed"); + success = false; + } + } else if (rccGenerated) { + // Just touch the wrapper file + if (this->GetVerbose()) { + this->LogInfo(cmQtAutoGen::RCC, + "Touching RCC wrapper " + wrapperFileRel); + } + cmSystemTools::Touch(wrapperFileAbs, false); + } + } + + return success; +} diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h new file mode 100644 index 0000000..0e3f690 --- /dev/null +++ b/Source/cmQtAutoGeneratorRcc.h @@ -0,0 +1,56 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGeneratorRcc_h +#define cmQtAutoGeneratorRcc_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmFilePathChecksum.h" +#include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" + +#include <string> +#include <vector> + +class cmMakefile; + +class cmQtAutoGeneratorRcc : public cmQtAutoGenerator +{ + CM_DISABLE_COPY(cmQtAutoGeneratorRcc) +public: + cmQtAutoGeneratorRcc(); + +private: + // -- Initialization & settings + bool InfoFileRead(cmMakefile* makefile); + void SettingsFileRead(cmMakefile* makefile); + bool SettingsFileWrite(); + // -- Central processing + bool Process(cmMakefile* makefile) override; + bool RccGenerate(); + + // -- Config settings + std::string ConfigSuffix; + cmQtAutoGen::MultiConfig MultiConfig; + // -- Settings + bool SettingsChanged; + std::string SettingsFile; + std::string SettingsString; + // -- Directories + std::string ProjectSourceDir; + std::string ProjectBinaryDir; + std::string CurrentSourceDir; + std::string CurrentBinaryDir; + std::string AutogenBuildDir; + cmFilePathChecksum FilePathChecksum; + // -- Qt environment + std::string RccExecutable; + std::vector<std::string> RccListOptions; + // -- Job + std::string QrcFile; + std::string RccFile; + std::vector<std::string> Options; + std::vector<std::string> Inputs; +}; + +#endif diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 07df488..aae0a9d 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -1118,11 +1118,24 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) const cmMakefile* mf = lg->GetMakefile(); pObj[kMINIMUM_CMAKE_VERSION] = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); - pObj[kHAS_INSTALL_RULE] = mf->GetInstallGenerators().empty() == false; pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config); + // For a project-level install rule it might be defined in any of its + // associated generators. + bool hasInstallRule = false; + for (const auto generator : projectIt.second) { + hasInstallRule = + generator->GetMakefile()->GetInstallGenerators().empty() == false; + + if (hasInstallRule) { + break; + } + } + + pObj[kHAS_INSTALL_RULE] = hasInstallRule; + result.append(pObj); } diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 4f337f2..6add7b3 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -8,9 +8,7 @@ #include "cmSystemTools.h" #include "cmake.h" -#include <algorithm> #include <assert.h> -#include <vector> cmSourceFileLocation::cmSourceFileLocation() : Makefile(nullptr) @@ -86,13 +84,9 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name) // The global generator checks extensions of enabled languages. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); cmMakefile const* mf = this->Makefile; - const std::vector<std::string>& srcExts = - mf->GetCMakeInstance()->GetSourceExtensions(); - const std::vector<std::string>& hdrExts = - mf->GetCMakeInstance()->GetHeaderExtensions(); + auto cm = mf->GetCMakeInstance(); if (!gg->GetLanguageFromExtension(ext.c_str()).empty() || - std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end() || - std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end()) { + cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext)) { // This is a known extension. Use the given filename with extension. this->Name = cmSystemTools::GetFilenameName(name); this->AmbiguousExtension = false; @@ -149,14 +143,8 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension( // disk. One of these must match if loc refers to this source file. std::string const& ext = this->Name.substr(loc.Name.size() + 1); cmMakefile const* mf = this->Makefile; - const std::vector<std::string>& srcExts = - mf->GetCMakeInstance()->GetSourceExtensions(); - if (std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) { - return true; - } - std::vector<std::string> hdrExts = - mf->GetCMakeInstance()->GetHeaderExtensions(); - return std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end(); + auto cm = mf->GetCMakeInstance(); + return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext); } bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index fba4c31..18bcb49 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -60,14 +60,14 @@ void cmSourceGroup::AddGroupFile(const std::string& name) this->GroupFiles.insert(name); } -const char* cmSourceGroup::GetName() const +std::string const& cmSourceGroup::GetName() const { - return this->Name.c_str(); + return this->Name; } -const char* cmSourceGroup::GetFullName() const +std::string const& cmSourceGroup::GetFullName() const { - return this->FullName.c_str(); + return this->FullName; } bool cmSourceGroup::MatchesRegex(const char* name) @@ -105,7 +105,7 @@ cmSourceGroup* cmSourceGroup::LookupChild(const char* name) const // st for (; iter != end; ++iter) { - std::string sgName = iter->GetName(); + std::string const& sgName = iter->GetName(); // look if descenened is the one were looking for if (sgName == name) { diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index e8bd697..7c7c35f 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -55,12 +55,12 @@ public: /** * Get the name of this group. */ - const char* GetName() const; + std::string const& GetName() const; /** * Get the full path name for group. */ - const char* GetFullName() const; + std::string const& GetFullName() const; /** * Check if the given name matches this group's regex. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9cf835c..bf36074 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -279,6 +279,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("CUDA_STANDARD_REQUIRED", nullptr); this->SetPropertyDefault("CUDA_EXTENSIONS", nullptr); this->SetPropertyDefault("CUDA_COMPILER_LAUNCHER", nullptr); + this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr); this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr); this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr); } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 6486c8b..caeeeb9 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1469,11 +1469,14 @@ void cmVisualStudio10TargetGenerator::WriteGroups() } this->WriteString("<ItemGroup>\n", 1); - for (std::set<cmSourceGroup*>::iterator g = groupsUsed.begin(); - g != groupsUsed.end(); ++g) { - cmSourceGroup* sg = *g; - const char* name = sg->GetFullName(); - if (strlen(name) != 0) { + std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(), groupsUsed.end()); + std::sort(groupsVec.begin(), groupsVec.end(), + [](cmSourceGroup* l, cmSourceGroup* r) { + return l->GetFullName() < r->GetFullName(); + }); + for (cmSourceGroup* sg : groupsVec) { + std::string const& name = sg->GetFullName(); + if (!name.empty()) { this->WriteString("<Filter Include=\"", 2); (*this->BuildFileStream) << name << "\">\n"; std::string guidName = "SG_Filter_"; @@ -1558,12 +1561,12 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( std::string const& source = sf->GetFullPath(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); - const char* filter = sourceGroup->GetFullName(); + std::string const& filter = sourceGroup->GetFullName(); this->WriteString("<", 2); std::string path = this->ConvertPath(source, s->RelativePath); this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path); - if (strlen(filter)) { + if (!filter.empty()) { (*this->BuildFileStream) << "\">\n"; this->WriteString("<Filter>", 3); (*this->BuildFileStream) << filter << "</Filter>\n"; diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index 981255d..c890acf 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -7,6 +7,8 @@ #include "cmXMLSafe.h" +#include <chrono> +#include <ctime> #include <ostream> #include <stack> #include <string> @@ -99,6 +101,22 @@ private: return cmXMLSafe(value).Quotes(false); } + /* + * Convert a std::chrono::system::time_point to the number of seconds since + * the UN*X epoch. + * + * It would be tempting to convert a time_point to number of seconds by + * using time_since_epoch(). Unfortunately the C++11 standard does not + * specify what the epoch of the system_clock must be. + * Therefore we must assume it is an arbitary point in time. Instead of this + * method, it is recommended to convert it by means of the to_time_t method. + */ + static std::time_t SafeContent( + std::chrono::system_clock::time_point const& value) + { + return std::chrono::system_clock::to_time_t(value); + } + template <typename T> static T SafeContent(T value) { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index fde77a7..2a5bb6c 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -200,6 +200,11 @@ cmake::cmake(Role role) this->SourceFileExtensions.push_back("M"); this->SourceFileExtensions.push_back("mm"); + std::copy(this->SourceFileExtensions.begin(), + this->SourceFileExtensions.end(), + std::inserter(this->SourceFileExtensionsSet, + this->SourceFileExtensionsSet.end())); + this->HeaderFileExtensions.push_back("h"); this->HeaderFileExtensions.push_back("hh"); this->HeaderFileExtensions.push_back("h++"); @@ -208,6 +213,11 @@ cmake::cmake(Role role) this->HeaderFileExtensions.push_back("hxx"); this->HeaderFileExtensions.push_back("in"); this->HeaderFileExtensions.push_back("txx"); + + std::copy(this->HeaderFileExtensions.begin(), + this->HeaderFileExtensions.end(), + std::inserter(this->HeaderFileExtensionsSet, + this->HeaderFileExtensionsSet.end())); } cmake::~cmake() @@ -1647,6 +1657,21 @@ void cmake::AddCacheEntry(const std::string& key, const char* value, this->UnwatchUnusedCli(key); } +std::string cmake::StripExtension(const std::string& file) const +{ + auto dotpos = file.rfind('.'); + if (dotpos != std::string::npos) { + auto ext = file.substr(dotpos + 1); +#if defined(_WIN32) || defined(__APPLE__) + ext = cmSystemTools::LowerCase(ext); +#endif + if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) { + return file.substr(0, dotpos); + } + } + return file; +} + const char* cmake::GetCacheDefinition(const std::string& name) const { return this->State->GetInitializedCacheValue(name); diff --git a/Source/cmake.h b/Source/cmake.h index 5c5a90d..02c6cdb 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -8,6 +8,7 @@ #include <map> #include <set> #include <string> +#include <unordered_set> #include <vector> #include "cmInstalledFile.h" @@ -225,11 +226,27 @@ public: { return this->SourceFileExtensions; } + + bool IsSourceExtension(const std::string& ext) const + { + return this->SourceFileExtensionsSet.find(ext) != + this->SourceFileExtensionsSet.end(); + } + const std::vector<std::string>& GetHeaderExtensions() const { return this->HeaderFileExtensions; } + bool IsHeaderExtension(const std::string& ext) const + { + return this->HeaderFileExtensionsSet.find(ext) != + this->HeaderFileExtensionsSet.end(); + } + + // Strips the extension (if present and known) from a filename + std::string StripExtension(const std::string& file) const; + /** * Given a variable name, return its value (as a string). */ @@ -486,7 +503,9 @@ private: std::string CheckStampList; std::string VSSolutionFile; std::vector<std::string> SourceFileExtensions; + std::unordered_set<std::string> SourceFileExtensionsSet; std::vector<std::string> HeaderFileExtensions; + std::unordered_set<std::string> HeaderFileExtensionsSet; bool ClearBuildSystem; bool DebugTryCompile; cmFileTimeComparison* FileComparison; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 449db9d..3d9f65a 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -6,7 +6,8 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorMocUic.h" +#include "cmQtAutoGeneratorRcc.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" @@ -992,11 +993,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) } #ifdef CMAKE_BUILD_WITH_CMAKE - if (args[1] == "cmake_autogen" && args.size() >= 4) { - cmQtAutoGenerators autogen; + if ((args[1] == "cmake_autogen") && (args.size() >= 4)) { + cmQtAutoGeneratorMocUic autoGen; + std::string const& infoDir = args[2]; std::string const& config = args[3]; - bool autogenSuccess = autogen.Run(args[2], config); - return autogenSuccess ? 0 : 1; + return autoGen.Run(infoDir, config) ? 0 : 1; + } + if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) { + cmQtAutoGeneratorRcc autoGen; + std::string const& infoFile = args[2]; + std::string config; + if (args.size() > 3) { + config = args[3]; + }; + return autoGen.Run(infoFile, config) ? 0 : 1; } #endif diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index 7ef626f..cfca823 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -13,7 +13,13 @@ string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) +set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu) +get_property(sep_comp TARGET CUDASeparateLibA PROPERTY CUDA_SEPARABLE_COMPILATION) +if(NOT sep_comp) + message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized") +endif() +unset(CMAKE_CUDA_SEPARABLE_COMPILATION) if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC") # Test adding a flag that is not in our CUDA flag table for VS. diff --git a/Tests/FindOpenGL/Test/CMakeLists.txt b/Tests/FindOpenGL/Test/CMakeLists.txt index 3b5ffee..9004a98 100644 --- a/Tests/FindOpenGL/Test/CMakeLists.txt +++ b/Tests/FindOpenGL/Test/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.9) +cmake_minimum_required(VERSION 3.10) +cmake_policy(SET CMP0072 NEW) project(TestFindOpenGL C) include(CTest) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 6b7b723..f306200 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -144,6 +144,7 @@ add_RunCMake_test(ExternalData) add_RunCMake_test(FeatureSummary) add_RunCMake_test(FPHSA) add_RunCMake_test(FindBoost) +add_RunCMake_test(FindOpenGL) if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom") add_RunCMake_test(GenerateExportHeader) endif() diff --git a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake index 99d3155..948c6ab 100644 --- a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake +++ b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake @@ -45,13 +45,22 @@ function(toExpectedContentList FILE_NO CONTENT_VAR) unset(prefix_) endif() - if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH) - set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr") + # add install prefix to expected paths + if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX) + set(EXPECTED_FILE_PACKAGING_PREFIX + "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}") + elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX) + # default CPack Archive packaging install prefix + set(EXPECTED_FILE_PACKAGING_PREFIX "/") endif() + set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}") + foreach(part_ IN LISTS ${CONTENT_VAR}) + list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}") + endforeach() unset(filtered_) - foreach(part_ IN LISTS ${CONTENT_VAR}) - string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}") + foreach(part_ IN LISTS prepared_) + string(REGEX REPLACE "^/" "" part_ "${part_}") if(part_) list(APPEND filtered_ "${prefix_}${part_}") diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake index 5337b2c..447b08b 100644 --- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake +++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake @@ -35,10 +35,27 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK "-DRunCMake_TEST_FILE_PREFIX=${TEST_NAME}" "-DRunCMake_SUBTEST_SUFFIX=${SUBTEST_SUFFIX}" "-DPACKAGING_TYPE=${PACKAGING_TYPE}") + + foreach(o out err) + if(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt) + set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt") + elseif(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${SUBTEST_SUFFIX}-std${o}.txt) + set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${SUBTEST_SUFFIX}-std${o}.txt") + elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-std${o}.txt) + set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-std${o}.txt") + elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-std${o}.txt) + set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-std${o}.txt") + else() + unset(RunCMake-std${o}-file) + endif() + endforeach() + run_cmake(${full_test_name_}) # execute optional build step if(build) + unset(RunCMake-stdout-file) + unset(RunCMake-stderr-file) run_cmake_command(${full_test_name_}-Build "${CMAKE_COMMAND}" --build "${RunCMake_TEST_BINARY_DIR}") endif() @@ -72,6 +89,8 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK set(RunCMake-std${o}-file "tests/${TEST_NAME}/${SUBTEST_SUFFIX}-std${o}.txt") elseif(EXISTS ${RunCMake_SOURCE_DIR}/${TEST_TYPE}/default_expected_std${o}.txt) set(RunCMake-std${o}-file "${TEST_TYPE}/default_expected_std${o}.txt") + else() + unset(RunCMake-std${o}-file) endif() endforeach() diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake b/Tests/RunCMake/CPack/DEB/Helpers.cmake index 6d8e84a..f7c5c84 100644 --- a/Tests/RunCMake/CPack/DEB/Helpers.cmake +++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake @@ -47,7 +47,20 @@ function(getPackageContentList FILE RESULT_VAR) endfunction() function(toExpectedContentList FILE_NO CONTENT_VAR) - # no need to do anything + # add install prefix to expected paths + if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX) + set(EXPECTED_FILE_PACKAGING_PREFIX + "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}") + elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX) + # default CPackDeb packaging install prefix + set(EXPECTED_FILE_PACKAGING_PREFIX "/usr") + endif() + set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}") + foreach(part_ IN LISTS ${CONTENT_VAR}) + list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}") + endforeach() + + set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE) endfunction() function(getMissingShlibsErrorExtra FILE RESULT_VAR) diff --git a/Tests/RunCMake/CPack/README.txt b/Tests/RunCMake/CPack/README.txt index 5877f97..2e2abdf 100644 --- a/Tests/RunCMake/CPack/README.txt +++ b/Tests/RunCMake/CPack/README.txt @@ -96,6 +96,14 @@ the test has to run some functions after CPack.cmake is included. In such cases a function run_after_include_cpack can be declared in test.cmake file and that function will run after the inclusion of CPack.cmake. +NOTE: During CMake configure stage developer warnings may be expected. In such +cases an expected output regular expression can be provided by creating +'<test_name>/configure-stdout.txt' and/or '<test_name>/configure-stderr.txt' +file. There are also more specialized versions of the file available: +- configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt +- configure-${SUBTEST_SUFFIX}-std${o}.txt +- configure-${PACKAGING_TYPE}-std${o}.txt + build phase (optional and not available for source package tests) ----------------------------------------------------------------- @@ -153,13 +161,19 @@ this step and must contain is later changed automatically depending on the generator so expected package content can be written only once per test for all generators. +- EXPECTED_FILE_PACKAGING_PREFIX and + EXPECTED_FILE_<file_number_starting_with_1>_PACKAGING_PREFIX variables can be + set to explicitly specified CPACK_PACKAGING_PREFIX value. By default this + variable does not need to be set as it is implicitly set to package generator + specific prefix. + Optional verification phase is generator specific and is optionaly executed. This phase is executed if '<test_name>/VerifyResult.cmake' script exists. VerifyResult.cmake script also automatically prints out standard output and standard error from CPack execution phase that is compared with '<test_name>/<generator_name>-stdout.txt' regular expression and -and '<test_name>/<generator_name>-stderr.txt' regular expresson respectively. +'<test_name>/<generator_name>-stderr.txt' regular expresson respectively. NOTE: For subtests generator name can also be suffixed with subtest name and/or packaging type (MONOLITHIC, COMPONENT, GROUP) and in such cases the preferences of which file will be used are as follows: diff --git a/Tests/RunCMake/CPack/RPM/Helpers.cmake b/Tests/RunCMake/CPack/RPM/Helpers.cmake index 88fc231..a29c020 100644 --- a/Tests/RunCMake/CPack/RPM/Helpers.cmake +++ b/Tests/RunCMake/CPack/RPM/Helpers.cmake @@ -47,14 +47,29 @@ function(getPackageContentList FILE RESULT_VAR) endfunction() function(toExpectedContentList FILE_NO CONTENT_VAR) - if(NOT DEFINED TEST_INSTALL_PREFIX_PATHS) - set(TEST_INSTALL_PREFIX_PATHS "/usr") + # add install prefix to expected paths + if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX) + set(EXPECTED_FILE_PACKAGING_PREFIX + "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}") + elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX) + # default CPackRPM packaging install prefix + set(EXPECTED_FILE_PACKAGING_PREFIX "/usr") endif() + set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}") + foreach(part_ IN LISTS ${CONTENT_VAR}) + list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}") + endforeach() + # remove paths that are excluded from auto packaging + if(NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) + set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST + /etc /etc/init.d /usr /usr/bin /usr/include /usr/lib + /usr/libx32 /usr/lib64 /usr/share /usr/share/aclocal /usr/share/doc) + endif() unset(filtered_) - foreach(part_ IN LISTS ${CONTENT_VAR}) + foreach(part_ IN LISTS prepared_) unset(dont_add_) - foreach(for_removal_ IN LISTS TEST_INSTALL_PREFIX_PATHS) + foreach(for_removal_ IN LISTS CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) if(part_ STREQUAL for_removal_) set(dont_add_ TRUE) break() diff --git a/Tests/RunCMake/CPack/STGZ/Helpers.cmake b/Tests/RunCMake/CPack/STGZ/Helpers.cmake index 68b1eab..1756645 100644 --- a/Tests/RunCMake/CPack/STGZ/Helpers.cmake +++ b/Tests/RunCMake/CPack/STGZ/Helpers.cmake @@ -47,18 +47,29 @@ function(toExpectedContentList FILE_NO CONTENT_VAR) string(SUBSTRING "${prefix_}" 0 ${pos_} prefix_) endif() - if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH) - set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr") + # add install prefix to expected paths + if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX) + set(EXPECTED_FILE_PACKAGING_PREFIX + "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}") + elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX) + # default CPack Archive packaging install prefix + set(EXPECTED_FILE_PACKAGING_PREFIX "/") endif() - set(filtered_ "${prefix_}") - foreach(part_ IN LISTS ${CONTENT_VAR}) - string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}") + # remove trailing slash otherwise path concatenation will cause double slashes + string(REGEX REPLACE "/$" "" EXPECTED_FILE_PACKAGING_PREFIX + "${EXPECTED_FILE_PACKAGING_PREFIX}") + + if(EXPECTED_FILE_PACKAGING_PREFIX) + set(prepared_ "${prefix_}") + else() + unset(prepared_) + endif() - if(part_) - list(APPEND filtered_ "${prefix_}/${part_}") - endif() + list(APPEND prepared_ "${prefix_}${EXPECTED_FILE_PACKAGING_PREFIX}") + foreach(part_ IN LISTS ${CONTENT_VAR}) + list(APPEND prepared_ "${prefix_}${EXPECTED_FILE_PACKAGING_PREFIX}${part_}") endforeach() - set(${CONTENT_VAR} "${filtered_}" PARENT_SCOPE) + set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE) endfunction() diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake index 5cb12c3..02a7821 100644 --- a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake @@ -1,3 +1,3 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/abc.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/abc.txt") diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake index 694dc00..6d895ec 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake @@ -1,9 +1,9 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") if(PACKAGING_TYPE STREQUAL "COMPONENT") set(EXPECTED_FILES_COUNT "2") set(EXPECTED_FILE_1_COMPONENT "test") set(EXPECTED_FILE_2_COMPONENT "test2") - set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") endif() diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake index 5cb280c..07226df 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake @@ -1,10 +1,10 @@ set(EXPECTED_FILES_COUNT "3") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) set(EXPECTED_FILE_1_COMPONENT "pkg_1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_NAME "second") -set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") -set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_2_LIST "/foo;/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_3_LIST "/foo;/foo/CMakeLists.txt") if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") string(TOLOWER "${GENERATOR_TYPE}" file_extension_) diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake index 3d8de74..b26c6c7 100644 --- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake @@ -5,11 +5,11 @@ set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) set(EXPECTED_FILE_1_NAME "Debuginfo") set(EXPECTED_FILE_1_COMPONENT "applications") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm") -set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm") -set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so") +set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") set(EXPECTED_FILE_4_NAME "Debuginfo") set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo") diff --git a/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake index 6142eb3..d1a3a5f 100644 --- a/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake index 9b8205b..b6fcc17 100644 --- a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake @@ -2,5 +2,5 @@ if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_.*_var") set(EXPECTED_FILES_COUNT "0") else() set(EXPECTED_FILES_COUNT "1") - set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") endif() diff --git a/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake index 3b280ba..be7ba07 100644 --- a/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake @@ -1,14 +1,14 @@ set(EXPECTED_FILES_COUNT "5") set(EXPECTED_FILE_1_COMPONENT "applications") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") set(EXPECTED_FILE_2_COMPONENT "applications_auto") -set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo_auto;/usr/foo_auto/test_prog") +set(EXPECTED_FILE_CONTENT_2_LIST "/foo_auto;/foo_auto/test_prog") set(EXPECTED_FILE_3_COMPONENT "headers") -set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_3_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_4_COMPONENT "libs") -set(EXPECTED_FILE_CONTENT_4_LIST "/usr/bas;/usr/bas/libtest_lib.so") +set(EXPECTED_FILE_CONTENT_4_LIST "/bas;/bas/libtest_lib.so") set(EXPECTED_FILE_5_COMPONENT "libs_auto") -set(EXPECTED_FILE_CONTENT_5_LIST "/usr;/usr/bas_auto;/usr/bas_auto/libtest_lib.so") +set(EXPECTED_FILE_CONTENT_5_LIST "/bas_auto;/bas_auto/libtest_lib.so") if(GENERATOR_TYPE STREQUAL "DEB") set(whitespaces_ "[\t\n\r ]*") diff --git a/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake index 6142eb3..d1a3a5f 100644 --- a/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake index 650687c..8df6831 100644 --- a/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake @@ -1,6 +1,6 @@ set(EXPECTED_FILES_COUNT "1") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/empty") +set(EXPECTED_FILE_CONTENT_1_LIST "/empty") if(PACKAGING_TYPE STREQUAL "COMPONENT") set(EXPECTED_FILE_1_COMPONENT "test") diff --git a/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake index ded2923..407cbe6 100644 --- a/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake @@ -1,8 +1,8 @@ set(EXPECTED_FILES_COUNT "3") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) set(EXPECTED_FILE_1_COMPONENT "foo") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_COMPONENT "bar") -set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_3_COMPONENT "bas") -set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake index a45b38d..974df22 100644 --- a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake @@ -2,6 +2,7 @@ set(whitespaces_ "[\t\n\r ]*") set(EXPECTED_FILES_COUNT "5") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) +set(EXPECTED_FILE_PACKAGING_PREFIX "") set(EXPECTED_FILE_1_COMPONENT "applications") set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake index 44346ab..de38df9 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake @@ -1,5 +1,5 @@ set(EXPECTED_FILES_COUNT "2") set(EXPECTED_FILE_1_COMPONENT "foo") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_COMPONENT "bar") -set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake index 631d957..4cb8dd0 100644 --- a/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake @@ -1,3 +1,3 @@ set(EXPECTED_FILES_COUNT "1") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt") diff --git a/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake index 6bfb0c1..629be9e 100644 --- a/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake @@ -3,9 +3,9 @@ set(EXPECTED_FILES_COUNT "0") if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "invalid") set(EXPECTED_FILES_COUNT "3") set(EXPECTED_FILE_1 "main_component-0.1.1-1.*.rpm") - set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_COMPONENT "headers") - set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_3_COMPONENT "libs") - set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/CMakeLists.txt") endif() diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake index 6142eb3..d1a3a5f 100644 --- a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake index 6142eb3..d1a3a5f 100644 --- a/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake index eed5b92..c375aca 100644 --- a/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake @@ -2,5 +2,5 @@ set(EXPECTED_FILES_COUNT "0") if(NOT ${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid") set(EXPECTED_FILES_COUNT "1") - set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") endif() diff --git a/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake index ae58c4b..137da47 100644 --- a/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake @@ -1,2 +1,4 @@ set(EXPECTED_FILES_COUNT "1") +# don't set the prefix here as we have absolute paths that should not be prefixed +set(EXPECTED_FILE_PACKAGING_PREFIX "") set(EXPECTED_FILE_CONTENT_1_LIST "/not_relocatable;/not_relocatable/CMakeLists.txt;/opt") diff --git a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake index 9bdb176..26fa1df 100644 --- a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake @@ -1,8 +1,8 @@ set(EXPECTED_FILES_COUNT "3") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) set(EXPECTED_FILE_1_COMPONENT "pkg_1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_2_NAME "second") -set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_2_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_3_COMPONENT "pkg_3") -set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_3_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake index ca866ea..8170d39 100644 --- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake @@ -5,25 +5,25 @@ set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo") set(EXPECTED_FILES_COUNT "4") set(EXPECTED_FILE_1 "single_debuginfo-0.1.1-1.*.rpm") - set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm") - set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") + set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm") - set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so") + set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") set(EXPECTED_FILE_4_COMPONENT "debuginfo") set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*") elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo") set(EXPECTED_FILES_COUNT "2") set(EXPECTED_FILE_1 "single_debuginfo-0*-applications.rpm") - set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") set(EXPECTED_FILE_2 "single_debuginfo-applications-debuginfo*.rpm") set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*") elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_components") set(EXPECTED_FILES_COUNT "2") set(EXPECTED_FILE_1 "single_debuginfo-0*.rpm") - set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog") + set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") set(EXPECTED_FILE_2 "single_debuginfo-debuginfo*.rpm") set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*") diff --git a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake index 0a3e426..d78f222 100644 --- a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake @@ -1,2 +1,3 @@ set(EXPECTED_FILES_COUNT "1") +set(EXPECTED_FILE_PACKAGING_PREFIX "") set(EXPECTED_FILE_CONTENT_1_LIST "source_package-0.1.1.tar.gz;source_package.spec") diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake index 6142eb3..d1a3a5f 100644 --- a/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake index 05be748..e8281a8 100644 --- a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake @@ -1,12 +1,11 @@ set(EXPECTED_FILES_COUNT "1") set(EXPECTED_FILE_CONTENT_1_LIST - "/usr" - "/usr/empty_dir" - "/usr/non_empty_dir" - "/usr/non_empty_dir/CMakeLists.txt" - "/usr/symlink_to_empty_dir" - "/usr/symlink_to_non_empty_dir") + "/empty_dir" + "/non_empty_dir" + "/non_empty_dir/CMakeLists.txt" + "/symlink_to_empty_dir" + "/symlink_to_non_empty_dir") if(PACKAGING_TYPE STREQUAL "COMPONENT") set(EXPECTED_FILE_1_COMPONENT "links") diff --git a/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake index aabe537..8420986 100644 --- a/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake @@ -1,2 +1,2 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr/one;/usr/one/foo.txt;/usr/one/two;/usr/one/two/bar.txt;/usr/three;/usr/three/baz.txt;/usr/three/qux.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/one;/one/foo.txt;/one/two;/one/two/bar.txt;/three;/three/baz.txt;/three/qux.txt") diff --git a/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake index 85c571c..372f71b 100644 --- a/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake @@ -1,3 +1,3 @@ set(EXPECTED_FILES_COUNT "1") -set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt") set(EXPECTED_FILE_1_REVISION "1") diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt new file mode 100644 index 0000000..f5ee220 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt @@ -0,0 +1,3 @@ +-- OpenGL_GL_PREFERENCE='GLVND' +-- OPENGL_gl_LIBRARY='' +-- OPENGL_LIBRARIES='OpenGL;GLX;GLU' diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake new file mode 100644 index 0000000..6cbbeec --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0072 NEW) +include(CMP0072-common.cmake) diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt new file mode 100644 index 0000000..22df1b1 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt @@ -0,0 +1,3 @@ +-- OpenGL_GL_PREFERENCE='LEGACY' +-- OPENGL_gl_LIBRARY='GL' +-- OPENGL_LIBRARIES='GL;GLU' diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake new file mode 100644 index 0000000..6d57004 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0072 OLD) +include(CMP0072-common.cmake) diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt new file mode 100644 index 0000000..f26f217 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt @@ -0,0 +1,21 @@ +^CMake Warning \(dev\) at .*/Modules/FindOpenGL.cmake:[0-9]+ \(message\): + Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when + available. Run "cmake --help-policy CMP0072" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. + + FindOpenGL found both a legacy GL library: + + OPENGL_gl_LIBRARY: GL + + and GLVND libraries for OpenGL and GLX: + + OPENGL_opengl_LIBRARY: OpenGL + OPENGL_glx_LIBRARY: GLX + + OpenGL_GL_PREFERENCE has not been set to "GLVND" or "LEGACY", so for + compatibility with CMake 3.10 and below the legacy GL library will be used. +Call Stack \(most recent call first\): + CMP0072-common.cmake:[0-9]+ \(find_package\) + CMP0072-WARN.cmake:[0-9]+ \(include\) + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt new file mode 100644 index 0000000..22df1b1 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt @@ -0,0 +1,3 @@ +-- OpenGL_GL_PREFERENCE='LEGACY' +-- OPENGL_gl_LIBRARY='GL' +-- OPENGL_LIBRARIES='GL;GLU' diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake new file mode 100644 index 0000000..459c458 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake @@ -0,0 +1 @@ +include(CMP0072-common.cmake) diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake new file mode 100644 index 0000000..3fe8030 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake @@ -0,0 +1,13 @@ +set(CYGWIN 0) +set(WIN32 0) +set(APPLE 0) +set(OPENGL_INCLUDE_DIR GL/include) +set(OPENGL_GLX_INCLUDE_DIR GLX/include) +set(OPENGL_gl_LIBRARY GL) +set(OPENGL_opengl_LIBRARY OpenGL) +set(OPENGL_glx_LIBRARY GLX) +set(OPENGL_glu_LIBRARY GLU) +find_package(OpenGL) +message(STATUS "OpenGL_GL_PREFERENCE='${OpenGL_GL_PREFERENCE}'") +message(STATUS "OPENGL_gl_LIBRARY='${OPENGL_gl_LIBRARY}'") +message(STATUS "OPENGL_LIBRARIES='${OPENGL_LIBRARIES}'") diff --git a/Tests/RunCMake/FindOpenGL/CMakeLists.txt b/Tests/RunCMake/FindOpenGL/CMakeLists.txt new file mode 100644 index 0000000..bf2ef15 --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.10) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake b/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake new file mode 100644 index 0000000..fcc130f --- /dev/null +++ b/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0072-WARN) +run_cmake(CMP0072-OLD) +run_cmake(CMP0072-NEW) |